/* ============================================================
   Control Tower — TEMA ÚNICO (look ReloadedToken).
   Una sola fuente de verdad para colores/tipografía. Incluido en
   TODAS las páginas (<link href="/static/theme.css">). Los templates
   ya NO definen :root de color propio.
   Paleta calcada de reloadedtoken_site/styles.css.
   ============================================================ */
@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,600;9..144,700&family=Manrope:wght@400;500;600;700;800&display=swap');

:root{
  /* controles nativos (calendario de type=date, scrollbars) en modo oscuro */
  color-scheme: dark;
  /* tipografía */
  --font-display: 'Fraunces', Georgia, serif;
  --font-body:    'Manrope', 'Inter', system-ui, -apple-system, sans-serif;
  /* superficies */
  --bg:        #0b0d12;
  --bg-soft:   #12151d;
  --panel:     #161a24;
  --panel2:    #12151d;
  --card:      #161a24;
  --line:      #232838;
  --border:    #232838;
  /* texto */
  --text:  #e8ebf2;
  --txt:   #e8ebf2;
  --muted: #97a0b5;
  --dim:   #6b7280;
  /* acentos ReloadedToken: violeta -> azul */
  --accent:  #9b7bff;
  --accent2: #6c8cff;
  /* números (convención financiera) */
  --green: #34d399;
  --red:   #fb7185;
  --teal:  #5dcaa5;
  --amber: #fbbf24;
  --warn:  #fbbf24;
  --radius: 16px;
  /* Superficies veladas y sombras: existian SOLO como literales
     rgba(255,255,255,.0x) / rgba(0,0,0,.5x) repartidos por las paginas, y en
     tema claro un velo BLANCO sobre fondo blanco desaparece (y una sombra
     negra al 55% tapa la pantalla). Nombradas, el tema las voltea. */
  --veil-1: rgba(255,255,255,.04);   /* zebra de tabla, fondo sutil    */
  --veil-2: rgba(255,255,255,.06);   /* hover de fila, chip            */
  --veil-3: rgba(255,255,255,.12);   /* borde suave sobre superficie   */
  --scrim:  rgba(0,0,0,.55);         /* backdrop de modales            */
  --shadow: 0 16px 44px rgba(0,0,0,.5);
  /* Charts (Chart.js): rejilla y rotulos. Cada dashboard los tenia
     hardcodeados ('#6b7ba4', rgba(255,255,255,.04)) y sobre blanco quedaban
     invisibles — el mismo sintoma que ya mordio al exportar a PDF. */
  --grid:  rgba(255,255,255,.06);
  --tick:  #6b7ba4;
  /* texto encima del degradado de acento (pill activa, boton primario):
     blanco en los dos temas — el degradado no se aclara. */
  --on-accent: #ffffff;
  /* tinta sobre barras de color saturado (gantt): la barra no cambia con
     el tema, asi que su texto tampoco. Antes usaban var(--bg), que en
     claro se volvia BLANCO sobre teal — 54 fechas ilegibles. */
  --on-bar: #0b0d12;
  /* Chips/barras de ESTADO (gantt, semaforos): color fijo en los dos
     temas — llevan tinta oscura encima, asi que no pueden oscurecerse. */
  --st-green: #2dd4bf; --st-amber: #fbbf24; --st-red: #fb7185;
  /* Bandas del arbol del P&L (seccion / categoria / subcategoria / total).
     Vivian clavadas con !important en cada pantalla del estado, asi que el
     tema no las alcanzaba: en claro quedaban azul-oscuro con el texto ya
     oscuro encima (reporte de Gabriel 2026-08-03). */
  --row-section:  #222d52;
  --row-category: #181f3a;
  --row-sub:      #141a30;
  --row-total:    #2b3766;
  --row-even:     #151b30;
  --col-total:    #1b2240;
  --row-ink:      #ffffff;   /* texto sobre seccion/total */
  --row-sub-ink:  #c3cdea;
}

/* ── TEMA CLARO ────────────────────────────────────────────────────────────
   Se activa con data-theme="light" en <html> (lo pone _nav.html antes de
   pintar, para que no haya destello). La paleta es la MISMA que print.css
   viene usando desde julio para convertir cualquier pantalla en reporte: ya
   estaba probada en papel, solo no se podia ver en pantalla.
   Los colores semanticos (verde/rojo/ambar) se oscurecen: sobre blanco, el
   #34d399 de pantalla no tiene contraste suficiente para leerse. */
:root[data-theme="light"]{
  color-scheme: light;
  --bg:        #ffffff;
  --bg-soft:   #f3f4f6;
  --panel:     #ffffff;
  --panel2:    #f3f4f6;
  --card:      #ffffff;
  --line:      #d1d5db;
  --border:    #d1d5db;
  --text:  #111827;
  --txt:   #111827;
  --muted: #4b5563;
  --dim:   #6b7280;
  --accent:  #4338ca;
  --accent2: #1d4ed8;
  --green: #047857;
  --red:   #be123c;
  --teal:  #0f766e;
  --amber: #92400e;
  --warn:  #92400e;
  --veil-1: rgba(17,24,39,.035);
  --veil-2: rgba(17,24,39,.06);
  --veil-3: rgba(17,24,39,.14);
  --scrim:  rgba(17,24,39,.45);
  --shadow: 0 16px 44px rgba(17,24,39,.18);
  --grid:  rgba(17,24,39,.10);
  --tick:  #4b5563;
  --on-accent: #ffffff;
  --on-bar: #0b0d12;
  --st-green: #2dd4bf; --st-amber: #fbbf24; --st-red: #fb7185;
  /* En claro las bandas se vuelven azules PALIDAS con tinta oscura: la
     jerarquia se sigue leyendo (seccion mas fuerte que categoria) sin que la
     fila se convierta en un bloque negro. */
  --row-section:  #d7e0f4;
  --row-category: #e7ecf8;
  --row-sub:      #f1f4fb;
  --row-total:    #c3d0ee;
  --row-even:     #f7f9fd;
  --col-total:    #eef2fb;
  --row-ink:      #111827;
  --row-sub-ink:  #33406b;
}

/* El fondo de la pagina lo pinta cada template en su <body>; aca se fija una
   vez para que el toggle no dependa de que cada pantalla se acuerde. */
body{ background:var(--bg); color:var(--text); }

/* Superficies oscuras POR DISENO (decision de Gabriel 2026-08-03): el scope
   del radar y el mapa de Facilities conservan su fondo oscuro en los dos
   temas — un radar en blanco deja de leerse como un radar, y las teselas de
   CARTO son oscuras. Se comportan como una foto dentro de la pagina, que es
   lo que print.css ya hace con los charts al imprimir. */
[data-keep-dark]{
  color-scheme: dark;
  --bg:#0b0d12; --bg-soft:#12151d; --panel:#161a24; --panel2:#12151d;
  --card:#161a24; --line:#232838; --border:#232838;
  --text:#e8ebf2; --txt:#e8ebf2; --muted:#97a0b5; --dim:#6b7280;
  --green:#34d399; --red:#fb7185; --amber:#fbbf24; --warn:#fbbf24;
  --accent:#9b7bff; --accent2:#6c8cff; --teal:#5dcaa5;
  --veil-1:rgba(255,255,255,.04); --veil-2:rgba(255,255,255,.06);
  --veil-3:rgba(255,255,255,.12); --scrim:rgba(0,0,0,.55);
  --grid:rgba(255,255,255,.06); --tick:#6b7ba4; --on-accent:#ffffff;
  --row-section:#222d52; --row-category:#181f3a; --row-sub:#141a30;
  --row-total:#2b3766; --row-even:#151b30; --col-total:#1b2240;
  --row-ink:#ffffff; --row-sub-ink:#c3cdea;
  background:var(--bg); color:var(--text);
}

body{
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}

/* Tipografía display — títulos de sección y KPI */
h1, h2, h3,
.ct-title, .ttl, .page-title, .form-title {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -.02em;
}

/* Convención financiera de números (global) */
.neg  { color: var(--red); }
.pos  { color: var(--green); }
.zero { color: var(--muted); }
.tot  { font-weight: 700; }

/* Celdas numéricas — siempre alineadas a la derecha, fuente tabular */
td.num, th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
td.num { font-variant-numeric: tabular-nums; }

/* Navegaciones internas legadas (las reemplaza la barra unificada _nav.html). */
.navgroups{ display:none !important; }

/* ── Tira de controles de una pantalla (2026-08-05) ─────────────────────────
   Dos nombres, dos cosas, y hasta hoy el mismo nombre para las dos:

     .ctl-row  la FILA de controles de la pantalla
     .ctl      UN control: su etiqueta y su input, pegados

   `.ctl` estaba definido a mano en tres plantillas con DOS significados
   incompatibles: en el Income Statement es el par etiqueta+control (13 usos),
   y en Banking y Payroll era la fila entera (flex-wrap y margin-bottom). Eso
   es peor que duplicar — es una colisión: el dia que el tema definiera `.ctl`,
   dos de las tres pantallas se rompian, y compartir markup entre ellas ya era
   imposible. Gana el significado dominante y la fila estrena nombre propio.

   NO hay un partial de "barra de reportes" a proposito. Se evaluo y no se
   sostiene: lo unico repetido de verdad es esta cascara —tres reglas de flex—
   y el selector de Levels (4 pantallas). Los controles que muestra cada
   pantalla son preguntas distintas, asi que un componente generico habria
   necesitado una config por pagina mas larga que el markup que reemplaza. */
.ctl-row{ display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  margin-bottom:14px; }
.ctl{ display:flex; align-items:center; gap:7px; }

/* «Reset filters» — UN botón (regla de Gabriel, 2026-08-05) ─────────────────
   Nueve pantallas lo tenían escrito a mano con CINCO clases distintas (`btn`,
   `btn2`, `btn ghost`, `gf-clear`, y una con el estilo dentro del onclick) y
   TRES etiquetas. El comportamiento vive en filters.js; el dibujo, acá.

   Se define completo y NO hereda de `.btn`: `.btn` no existe en el tema — cada
   pantalla tiene el suyo, con su propio tamaño. Un botón que se agrega solo no
   puede depender de una clase que la página quizá no definió.

   El estado apagado no lo esconde: apagado significa «no hay nada filtrado»,
   que es información. Escondido, la barra saltaría de ancho cada vez que
   escribís la primera letra de una búsqueda. */
.ct-reset{
  display:inline-flex; align-items:center; gap:6px; white-space:nowrap;
  background:var(--panel); color:var(--text);
  border:1px solid var(--line); border-radius:9px;
  padding:6px 12px; font-family:inherit; font-size:12.5px; font-weight:600;
  cursor:pointer; transition:opacity .12s ease, border-color .12s ease; }
.ct-reset:hover{ border-color:var(--accent); }
.ct-reset.ct-reset--off{ opacity:.45; font-weight:500; }
.ct-reset.ct-reset--off:hover{ border-color:var(--line); }
@media (prefers-reduced-motion: reduce){ .ct-reset{ transition:none; } }
@media print{ .ct-reset{ display:none !important; } }

/* Panel «Customize» (Gabriel, 2026-08-05) ───────────────────────────────────
   La separación que faltaba: la tira de controles dice QUÉ estás mirando
   (período, columnas, comparación, base) y este panel dice CÓMO se ve
   (cuentas, ceros, profundidad, escala). Antes «Account #» y «Hide $0» eran
   dos checkboxes más entre once controles de la misma fila.

   El modal no se dibuja acá: usa `.pop-overlay` + `.pop--md`, el contrato de
   pop-up de la casa, así que hereda el centrado, el scrim del tema y el ancho.
   Lo de acá es el botón, los grupos y el pie. */
.cv-btn{ display:inline-flex; align-items:center; gap:6px; white-space:nowrap;
  background:var(--panel); color:var(--text); border:1px solid var(--line);
  border-radius:9px; padding:6px 12px; font-family:inherit; font-size:12.5px;
  font-weight:600; cursor:pointer; }
.cv-btn:hover{ border-color:var(--accent); }
/* El contador: un panel cerrado no puede esconder que la vista está tocada. */
.cv-btn .cv-n{ background:var(--accent2); color:var(--on-accent,#fff);
  border-radius:999px; min-width:16px; padding:0 5px; font-size:11px;
  line-height:16px; text-align:center; }

/* Vistas guardadas: arriba de todo, porque elegir una CAMBIA lo de abajo —
   un control que manda sobre los demás no puede estar debajo de ellos. */
.cv-views-row{ display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  margin-top:14px; padding-bottom:14px; border-bottom:1px solid var(--line); }
.cv-views-row label{ font-size:11px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--muted); }
.cv-views-row select{ flex:1; min-width:150px; }
.cv-save, .cv-del, .cv-load, .cv-ok, .cv-cancel{ background:none;
  border:1px solid var(--line); color:var(--muted); border-radius:9px;
  padding:6px 11px; font-family:inherit; font-size:12.5px;
  cursor:pointer; white-space:nowrap; }
.cv-save:hover, .cv-load:hover, .cv-ok:hover, .cv-cancel:hover,
.cv-del:not([disabled]):hover{ color:var(--text); border-color:var(--accent); }
.cv-del[disabled]{ opacity:.4; cursor:not-allowed; }
/* Encendido = la vista elegida NO es la que está dibujada. Es lo único que
   puede decirlo: la selección vuelve sola al navegar, cargarla no. */
.cv-load[data-hot]{ color:var(--on-accent,#fff); background:var(--accent2);
  border-color:var(--accent2); font-weight:600; }

/* «Save as…»: un renglón adentro del panel, no un `prompt()` del navegador —
   la vista lleva una decisión (¿se lleva el período?) y un prompt sólo sabe
   pedir un texto. */
.cv-saveas{ display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  margin-top:10px; padding:10px 11px; border:1px solid var(--line);
  border-radius:9px; background:var(--bg-soft); }
.cv-saveas .cv-name{ flex:1; min-width:150px; }
.cv-saveas .cv-inc{ display:inline-flex; align-items:center; gap:6px;
  font-size:12px; font-weight:400; letter-spacing:0; text-transform:none;
  color:var(--text); cursor:pointer; white-space:nowrap; }
.cv-msg{ margin-top:9px; font-size:12px; color:var(--muted); }

.cv-body{ display:flex; flex-direction:column; gap:16px; margin:14px 0 4px; }
.cv-grp{ display:flex; flex-direction:column; gap:9px; }
.cv-grp-t{ font-size:11px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--muted); }
/* Una opción por línea, etiqueta a la izquierda y control a la derecha: en una
   fila apretada se leían como una sopa, que es de donde venimos. */
.cv-grp > .ctl{ display:flex; align-items:center; justify-content:space-between;
  gap:14px; padding:8px 11px; border:1px solid var(--line); border-radius:9px;
  background:var(--bg-soft); font-size:13px; }
.cv-grp > .ctl > label{ color:var(--text); font-size:13px; cursor:pointer; }

.cv-foot{ display:flex; align-items:center; gap:10px; margin-top:16px;
  padding-top:14px; border-top:1px solid var(--line); }
.cv-restore{ background:none; border:1px solid var(--line); color:var(--muted);
  border-radius:9px; padding:6px 12px; font-family:inherit; font-size:12.5px;
  cursor:pointer; }
.cv-restore:hover{ color:var(--text); border-color:var(--accent); }
.cv-done{ margin-left:auto; background:var(--accent2); border:none;
  color:var(--on-accent,#fff); border-radius:9px; padding:7px 18px;
  font-family:inherit; font-size:12.5px; font-weight:600; cursor:pointer; }
@media print{ .cv-btn, #cv-pop{ display:none !important; } }

/* Barra de sub-pestañas — IDÉNTICA en todos los Controls (estandarización). */
.tabs{ display:flex; gap:7px; margin-bottom:14px; flex-wrap:wrap; }
.tab{ padding:8px 15px; border-radius:9px; cursor:pointer; font-weight:600; font-size:13.5px;
      color:var(--muted); background:var(--panel); border:1px solid var(--line); transition:.15s;
      text-decoration:none; display:inline-block; }
.tab:hover{ color:var(--text); }
.tab.active{ color:#fff; background:linear-gradient(135deg,var(--accent),var(--accent2));
             border-color:transparent; box-shadow:0 4px 18px rgba(108,140,255,.35); }
/* ── Variante RIEL (2026-08-04): las mismas pestañas, montadas sobre una línea
      que cruza todo el ancho, para cuando la fila queda PEGADA al contenido que
      conmuta (ficha del grant) en vez de encabezar la pantalla. Reporte de
      Gabriel: "se pierden como menús" — sueltas entre un bloque de datos y
      otro, y con botones de acción a un palmo, la fila no se leía como
      navegación. El riel es lo que la convierte en barra: dice dónde termina la
      navegación y dónde empieza el panel. La pestaña activa se apoya en él con
      su propio subrayado de acento, así que se ve a qué panel pertenece.
      Es una VARIANTE del componente compartido, no una copia privada: sigue
      siendo .tabs/.tab, con su degradado, y cualquier pantalla puede pedirla. ── */
.tabs--rail{ gap:4px; margin:18px 0 0; padding:6px 7px 0;
  /* El RECUADRO (2026-08-04): con las pestañas pintadas como cajas sobre el
     mismo fondo que los inputs, la fila se leía como "más campos" y no como
     navegación (reporte de Gabriel, sobre todo en tema claro, donde todo es
     claro). Ahora la BARRA es el objeto con marco y superficie propia, y las
     pestañas de adentro no tienen caja: se leen como rótulos hasta que una se
     enciende. Un campo tiene borde y fondo; una pestaña, no. */
  background:var(--veil-1); border:1px solid var(--line); border-bottom:none;
  border-radius:12px 12px 0 0; }
.tabs--rail .tab{ border-radius:8px 8px 0 0; padding:9px 16px; }
/* Sin caja SOLO las inactivas: la activa conserva el degradado del componente
   compartido. Si el `background:transparent` va en la regla general, gana por
   orden sobre `.tab.active` (misma especificidad) y la pestaña encendida se
   queda con tinta blanca sobre nada — invisible en tema claro. */
/* La inactiva SÍ lleva superficie, pero TINTADA de acento (2026-08-05, reporte
   de Gabriel: «estos tabs también deberían salir con fondo de algún color,
   quizás igual al de New grant, porque se pierden, especialmente en la vista
   dark»). Transparentes se leían como rótulos flotando sobre la barra.
   El tinte de acento es justo lo que las separa de un CAMPO —que es neutro,
   del color del panel— así que se resuelve el reporte de agosto 4 («se
   confunden con campos») y este a la vez: color = navegación, neutro = dato. */
.tabs--rail .tab:not(.active){ background:color-mix(in srgb, var(--accent2) 14%, transparent);
  border-color:color-mix(in srgb, var(--accent2) 32%, transparent); color:var(--accent2); }
.tabs--rail .tab:not(.active):hover{
  background:color-mix(in srgb, var(--accent2) 26%, transparent); color:var(--text); }
/* La activa conserva el degradado del componente compartido (regla de la casa:
   activo = accent→accent2). Su sombra sube, no baja: bajo el borde de la barra
   se vería como una mancha. */
.tabs--rail .tab.active{ box-shadow:0 -3px 14px -4px rgba(108,140,255,.45); }
/* ── Burbuja de ayuda "?" (2026-08-04) ──────────────────────────────────────
   Regla de Gabriel: "dentro de lo posible todo lo que es informativo debe ir en
   burbujas". Una descripción de pantalla ocupa dos renglones a lo ancho CADA VEZ
   que se entra, y se lee una sola vez en la vida; una burbuja la deja a un hover
   de distancia sin gastar el espacio donde está el trabajo.
   Vivía copiada en cada pantalla con tres tamaños distintos (assets 15px,
   cc_calibrate 13px, cc_projection con padding): esta es la canónica. Las copias
   viejas siguen ganando por orden de hoja hasta que se retiren. */
.qm{ display:inline-block; width:14px; height:14px; line-height:13px; text-align:center;
     border-radius:50%; border:1px solid var(--line); color:var(--dim);
     font-size:9.5px; font-weight:700; cursor:help; vertical-align:2px;
     margin-left:6px; user-select:none; flex:none; }
.qm:hover, .qm:focus-visible{ color:var(--accent2); border-color:var(--accent2); outline:none; }
/* A title inherits its own weight/size/colour; the mark must not. It is hung
   INSIDE headings (that is where a description belongs), so every property the
   heading would hand down is re-declared above. */
.qm{ font-family:var(--font-body); letter-spacing:0; }

/* The hoisted prose. It stays in the DOM inside the mark — hidden here,
   printed by print.css — because the pages ARE the reports: a description that
   only exists as a hover would vanish from the PDF. It is the ELEMENT that
   moves, not a copy of its text, so a screen that rewrites its own subtitle
   keeps working; the panel borrows this node while it is open. */
.qm .ct-bub-body{ display:none; }
.ct-bub .ct-bub-body{ display:block; }
/* Inside the bubble the description is the whole content: it brings none of
   the spacing, size or colour it had when it was a row of the page. */
.ct-bub .ct-bub-src{ margin:0 !important; padding:0 !important;
                     font-size:inherit !important; color:inherit !important;
                     line-height:inherit !important; display:block;
                     max-width:none !important; text-align:left !important; }
/* Several blocks can describe one title (a panel's opening line and the two
   footnotes under its table). They arrive as one note in parts, so the parts
   have to READ as parts — stacked flush they run into one wall of text. */
.ct-bub .ct-bub-src + .ct-bub-src{ margin-top:8px !important;
                     padding-top:8px !important; border-top:1px solid var(--line); }

/* ── The bubble itself (2026-08-17) ───────────────────────────────────────
   Gabriel: «las descripciones ponlas en bubbles, y eso hazlo por toda la
   aplicación». The native `title` tooltip could not carry the standard: it is
   unstyled (so it ignores the light theme), it truncates, and on a phone it
   does not exist — a description only reachable by hover is one a tablet
   cannot read. This is the panel CTBub paints instead.
   z-index 320: ABOVE the full-screen overlay layer (280) and the mobile drawer
   (290/300), because a `?` can be hung inside any of them. Safe at the top of
   the scale precisely because it is transient — it traps nothing: it closes on
   Escape, on a click outside, and when the pointer leaves. */
.ct-bub{ position:fixed; z-index:320; display:none; max-width:360px;
         background:var(--panel); border:1px solid var(--line); border-radius:11px;
         box-shadow:var(--shadow);
         padding:11px 13px; font-family:var(--font-body); font-size:12px;
         font-weight:400; line-height:1.5; color:var(--text); letter-spacing:0;
         text-align:left; max-height:min(60vh, 460px); overflow:auto;
         text-transform:none; }
.ct-bub.on{ display:block; }
.ct-bub a{ color:var(--accent2); }
.ct-bub b, .ct-bub strong{ color:var(--text); }
/* `title` strings carry real newlines and have to keep them; hoisted HTML must
   NOT get pre-line or its own source indentation would break every line. */
.ct-bub--text{ white-space:pre-line; }
/* Folded-in notes (a description that already ended in its own `?`, or a tip a
   screen composes at runtime) read as separate paragraphs, not one run-on
   sentence — and they are plain text, so they keep their newlines. */
.ct-bub .ct-bub-p{ display:block; margin-top:7px; padding-top:7px;
                   border-top:1px solid var(--line); color:var(--muted);
                   white-space:pre-line; }
.ct-bub .ct-bub-p:empty{ display:none; }

/* Contenedor de la sub-barra para las páginas que la incluyen como partial. */
.subnav-wrap{ padding:14px 24px 0; }

/* ── Barra de CONTEXTO: "Control › Página ▾" en UNA línea. Reemplaza la fila
      de sub-pestañas (_subnav.html) y, en móvil, también las pestañas internas
      de página (el colapso vive en _nav.html). Dice dónde estás sin gastar una
      fila entera de pantalla. ── */
.ctxbar{ display:flex; align-items:center; gap:7px; padding:12px 24px 2px;
         font-family:var(--font-body); flex-wrap:wrap; }
.ctx-crumb{ color:var(--muted); font-size:12.5px; font-weight:600; }
.ctx-sep{ color:var(--muted); font-size:13px; opacity:.55; }
.ctx-pick{ position:relative; }
.ctx-cur, .ctx-cur-static{ display:inline-flex; align-items:center; gap:6px;
         color:var(--text); font-size:14.5px; font-weight:700; letter-spacing:-.01em;
         background:none; border:none; padding:2px 0; font-family:inherit; }
.ctx-cur{ cursor:pointer; }
.ctx-cur .caret{ font-size:10px; opacity:.65; }
.ctx-cur:hover{ color:var(--accent2); }
.ctx-menu{ position:absolute; top:calc(100% + 6px); left:0; min-width:200px; display:none;
           background:var(--panel); border:1px solid var(--line);
           border-radius:12px; padding:6px; box-shadow:0 16px 44px rgba(0,0,0,.5); z-index:250; }
.ctx-pick.open .ctx-menu{ display:block; }
.ctx-menu a{ display:block; color:var(--muted); text-decoration:none; font-size:13px;
             font-weight:500; padding:9px 12px; border-radius:8px; white-space:nowrap; }
.ctx-menu a:hover{ color:var(--text); background:var(--panel2); }
.ctx-menu a.active{ color:#fff; background:linear-gradient(135deg,var(--accent),var(--accent2)); }
/* El selector generado para pestañas INTERNAS solo existe en móvil; en desktop
   las pestañas se quedan como están (1 clic para el cierre financiero). */
.ctxbar.ctx-mobile{ display:none; }
@media (max-width:768px){
  .ctxbar{ padding:10px 14px 2px; }
  .tabs.ct-collapsed, .gc-tabs.ct-collapsed{ display:none !important; }
}

/* Barras de filtros con data-mcol (colapsador genérico de _nav.html): en móvil
   viven detrás de un toggle "Filters (n)"; el botón solo existe en ≤768px. */
.mcol-toggle{ display:none; background:none; border:1px solid var(--border); border-radius:8px;
  color:var(--muted); font-family:inherit; font-size:12px; padding:5px 11px; cursor:pointer;
  align-items:center; gap:6px; margin:2px 0 8px; }
.mcol-toggle:hover{ color:var(--text); border-color:rgba(108,140,255,.4); }
.mcol-toggle .car{ color:var(--accent2); font-size:10px; }
.mcol-toggle .n{ background:linear-gradient(135deg,var(--accent),var(--accent2)); color:#fff;
  border-radius:999px; padding:0 7px; font-size:11px; }
.mcol-hidden{ display:none !important; }

/* Fechas editables — el icono de calendario SIEMPRE visible y clickeable
   (en dark theme el indicador nativo se veia negro sobre negro). El campo
   sigue tipeable; el icono abre el picker. */
input[type="date"]{ position:relative; }
input[type="date"]::-webkit-calendar-picker-indicator{
  filter: invert(.72) sepia(.12) saturate(2) hue-rotate(190deg);
  cursor: pointer; opacity:.85; padding:2px;
}
input[type="date"]::-webkit-calendar-picker-indicator:hover{ opacity:1; }

/* Relojes de período (estándar 2026-07-28): toda vista de grants declara en qué
   reloj está parada — FISCAL YEAR (ventana fija ESF 1-sep→31-ago, pregunta
   organizacional) o PERIOD OF PERFORMANCE (vigencia del award, pregunta de
   consumo del contrato). El pill va junto al selector/encabezado de período,
   con el MISMO texto de ayuda (title) en todas las páginas. */
.clock-pill{ display:inline-block; font-size:10.5px; font-weight:700;
  letter-spacing:.05em; text-transform:uppercase; padding:2px 9px 3px;
  border-radius:999px; white-space:nowrap; vertical-align:1px; cursor:help;
  color:var(--accent2); border:1px solid rgba(108,140,255,.45);
  background:rgba(108,140,255,.12); }
.clock-pill.is-pop{ color:var(--accent); border-color:rgba(155,123,255,.45);
  background:rgba(155,123,255,.12); }

/* Burbuja de ayuda — la nota que no cabe al lado del número ────────────────
   Las tarjetas del backtest llevaban la explicación en una tercera columna, y
   con tres tarjetas en fila se cortaba a media frase: "positive gap…", "of
   which $9,968,990 is A…" (reporte de Gabriel, 2026-08-02). Una nota cortada
   no es una nota — ocupa lugar y no se puede leer.

   El `title` nativo, que es el patrón viejo de la casa, tarda ~1s en aparecer
   y no se puede estilar. Esto es CSS puro: sale al instante, hereda el tema y
   no cuesta JS. Va con tabindex para que también se abra con teclado.

   Crece hacia la IZQUIERDA y hacia ABAJO a propósito: el ícono vive al final
   de una fila, cerca del borde derecho de su tarjeta, y arriba suele estar el
   tope del contenedor con scroll. */
.hint{ position:relative; display:inline-block; cursor:help; font-style:normal;
  color:var(--accent2); font-size:11px; line-height:1; vertical-align:1px;
  margin-left:5px; }
.hint::after{
  content:attr(data-hint);
  position:absolute; top:calc(100% + 7px); right:0; z-index:5;
  width:max-content; max-width:min(280px, 70vw);
  background:var(--panel2); color:var(--text);
  border:1px solid var(--line); border-radius:8px;
  padding:8px 10px; font-size:11.5px; line-height:1.5; font-weight:400;
  text-align:left; white-space:normal; letter-spacing:0;
  box-shadow:0 8px 22px rgba(0,0,0,.45);
  opacity:0; visibility:hidden; transform:translateY(-3px);
  transition:opacity .12s ease, transform .12s ease, visibility .12s; }
.hint:hover::after, .hint:focus-visible::after{
  opacity:1; visibility:visible; transform:none; }
.hint:focus-visible{ outline:2px solid var(--accent2); outline-offset:2px;
  border-radius:3px; }
@media (prefers-reduced-motion: reduce){ .hint::after{ transition:none; } }

/* Base de atribución — As posted / As serviced ─────────────────────────────
   Control segmentado compartido por Grant Control → Burn y Grant Analysis →
   Pace. Vivía suelto dentro de grant_control.html, así que Pace usaba las
   clases `basis`/`basis.on` SIN tenerlas: los dos spans salían como texto
   plano, sin borde ni cursor, y —lo grave— el activo no se distinguía del
   inactivo, porque `.basis.on` es la regla que lo pinta (bug 2026-08-02).
   Un control cuyo estado no se ve es peor que no tenerlo: los números cambian
   con la base y nadie sabe cuál está leyendo. Por eso vive acá y no en una
   página: lo usan dos, y la copia se queda vieja en una de las dos.
   Van como <button> porque son botones — teclado y aria-pressed gratis. */
.basis-seg{ display:inline-flex; border:1px solid var(--line); border-radius:8px;
  overflow:hidden; vertical-align:middle; }
.basis{ font:inherit; font-size:12px; line-height:1.55; color:var(--muted);
  background:none; border:0; padding:4px 10px; cursor:pointer; white-space:nowrap;
  user-select:none; }
.basis:hover{ color:#fff; }
.basis.on{ background:linear-gradient(135deg,var(--accent),var(--accent2)); color:#fff; }
.basis:focus-visible{ outline:2px solid var(--accent2); outline-offset:-2px; }

/* ── Región cargando (loading.js / CTLoad, 2026-08-04) ──────────────────────
   Regla de Gabriel: «cambio un selector y a veces no me dice nada y se demora
   en actualizar. esto es peligroso porque indica una cosa y muestra otra».

   La data vieja se ATENÚA y se desactiva en vez de desaparecer (decisión suya
   entre las dos opciones): así la pantalla no salta y seguís viendo QUÉ se
   está actualizando, pero es imposible leerlo como vigente — está gris,
   translúcido, sin color semántico y no se puede clickear ni seleccionar.
   Quitarle el color es parte del punto: un rojo o un verde a media opacidad
   sigue diciendo "esto va mal" o "esto va bien" sobre una cifra que ya no
   corresponde a lo que dice el selector.

   El rótulo va por `data-busy-label` y se pinta con ::after, no como nodo:
   inyectar un hijo lo dejaría huérfano en cuanto el render siguiente pisara
   el innerHTML de la región. */
/* min-height mientras está ocupada: en la CARGA INICIAL la región todavía está
   vacía, y un ::after con inset:0 sobre altura cero es invisible — la mitad del
   reporte de Gabriel (2026-08-12) era justo eso: la página abre y nada dice que
   está cargando. La clase se va al terminar, así que el alto no estorba. */
.ct-busy{ position:relative; min-height:64px; }
.ct-busy > *{ opacity:.28; filter:grayscale(1); pointer-events:none;
  user-select:none; transition:opacity .12s ease; }
/* The label is a PILL, not loose text (Gabriel 2026-08-19: «casi no se ve el
   updating»). Over a dimmed region, 12.5px of `--muted` with no ground
   competes with the data it is covering and loses — and the one thing that
   has to read at a glance is that THIS is not the current figure. With a
   surface, an accent border and a shadow it reads as a mark on top of the
   veil rather than as more body text. */
.ct-busy::after{
  content:attr(data-busy-label); position:absolute; z-index:1;
  left:50%; top:50%; transform:translate(-50%,-50%);
  padding:5px 13px; border-radius:20px; white-space:nowrap; pointer-events:none;
  background:var(--panel); border:1px solid var(--accent2); box-shadow:var(--shadow);
  font-family:var(--font-body); font-size:12.5px; font-weight:600;
  letter-spacing:.02em; color:var(--text); animation:ct-busy-pulse 1.1s ease-in-out infinite; }
@keyframes ct-busy-pulse{ 0%,100%{ opacity:1 } 50%{ opacity:.55 } }
/* A tall region (a long table, or a whole screen that repaints) leaves the
   label halfway down, far from where the user is looking. The kit measures at
   begin() and publishes `--ct-busy-top` = the top edge of the part of the
   region that is ON SCREEN. */
.ct-busy.ct-busy-top::after{ top:var(--ct-busy-top,16px); transform:translate(-50%,0); }
/* A control that has to stay LIVE inside the veil, marked in the markup:
   `<div class="section-hd" data-ct-live>`. The kit kills pointer events so a
   stale row cannot be clicked, but a region that repaints a whole block also
   contains the filter or the collapse header that TRIGGERED the load — and
   veiling the control you just used stops you from correcting it. Only works
   as a DIRECT child of the region: opacity composites, so a deeper node can
   never paint brighter than the parent it inherits from. */
.ct-busy > [data-ct-live]{ opacity:1; filter:none; pointer-events:auto;
  user-select:auto; }
/* NESTED regions (a detail card inside a block that repaints whole): the
   inner label inherits the outer dimming, reads washed out, and says the same
   thing twice. It goes quiet under a busy ancestor and comes back by itself
   the moment that veil lifts — which is exactly when it becomes the only
   signal that THAT card is still loading. */
.ct-busy .ct-busy::after{ content:none; }
/* A form control as the region (a <select> the response refills): min-height
   would stretch a 30px control to 64px and ::after does not paint on a
   replaced element anyway — the veil would be pure layout damage with no
   label to show for it. It dims, and nothing else. */
.ct-busy:is(select,input,textarea,button){ min-height:0; }
.ct-busy:is(select,input,textarea,button)::after{ content:none; }
@media (prefers-reduced-motion: reduce){
  .ct-busy > *{ transition:none; }
  .ct-busy::after{ animation:none; }
}

/* Modales / pop-ups — CAPA CANÓNICA (bug 2026-07-29, Gabriel abriendo un
   ticket de Asset Control: el pop-up salía DEBAJO del nav y el texto de los
   dos se veía superpuesto). La barra `.ctnav` es sticky con z-index:100 y sus
   menús llegan a 250, así que cualquier modal por debajo de eso queda tapado.
   Escala de capas de la casa:
       nav sticky 100 · menús del nav 200/250 · MODAL 280 · drawer móvil 290/300
   El modal va ARRIBA del nav (mientras está abierto el nav no se usa) pero
   DEBAJO del drawer móvil, que es navegación y debe poder abrirse encima.
   Una página que redefina `.pop-overlay` en su propio <style> gana por
   cascada: si lo hace, tiene que usar esta misma z-index (hay un test que lo
   verifica).

   ── Estandarización (regla de Gabriel 2026-08-04) ─────────────────────────
   «los pop ups deben sentirse como tal, no cubrir la mitad de la pantalla».
   Tres cosas se habían soltado y las tres se arreglan acá, en un solo lugar:

   1. **Centrado, siempre.** Había cajones anclados abajo (`#txn-panel`, de
      extremo a extremo y 44vh de alto — el drill-down de transacciones del
      Income Statement, en tres copias) y overlays que solo se separaban del
      borde con `padding:6vh 4vw`, o sea 92vw × 88vh: eso no es un pop-up, es
      otra pantalla. Un modal se centra y ocupa lo que su contenido pide.

   2. **El scrim sigue al TEMA.** Esta misma clase tenía `rgba(0,0,0,.55)`
      escrito a mano —y cinco dashboards lo pisaban con `rgba(5,7,12,.62)`—,
      así que en tema claro el fondo del modal seguía siendo negro. Ahora usa
      `var(--scrim)`, que el tema claro redefine. Único caso legítimo de fondo
      oscuro fijo: `[data-keep-dark]`, que es una decisión de diseño aparte.

   3. **Cuatro anchos, no “el que le quedó a cada página”.** Se elige un
      modificador, no se escribe un `width` nuevo:
        .pop         560px  — confirmar, un formulario corto, una ficha
        .pop--md     760px  — un gráfico, una lista breve  (= .pop-card)
        .pop--lg     980px  — una tabla de pocas columnas
        .pop--xl    1180px  — el drill-down de transacciones
      Todos con `100%` de tope, así que en teléfono son el ancho disponible
      menos el padding del overlay. */
.pop-overlay{ position:fixed; inset:0; background:var(--scrim); display:none;
  align-items:center; justify-content:center; z-index:280; padding:24px 14px;
  overflow:auto; }
/* Para abrir sin escribir `style.display='flex'` a mano y que nadie lo ponga
   en 'block' — con block se pierde el centrado y el modal se va arriba. */
.pop-overlay.open{ display:flex; }

/* `.pop-card` nació repetida en los cinco dashboards y es el mismo objeto que
   `.pop` con otro ancho: se conserva el nombre para no tocar su markup. */
.pop,.pop-card{ background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius, 14px); padding:18px 20px; width:min(560px,100%);
  max-height:calc(100vh - 48px); overflow:auto;
  box-shadow:0 18px 60px var(--scrim); }
.pop-card{ width:min(760px,100%); border-color:rgba(108,140,255,.35); }
.pop--md{ width:min(760px,100%); }
.pop--lg{ width:min(980px,100%); }
.pop--xl{ width:min(1180px,100%); }

/* Cabecera del modal: título a la izquierda, ✕ a la derecha. Estaba copiada
   en los cinco dashboards; el resto de las pantallas la escribía inline. */
.pop-hdr{ display:flex; align-items:center; justify-content:space-between;
  gap:12px; margin-bottom:2px; }
.pop-title{ font-size:14px; font-weight:700; color:var(--text); }
.pop-x{ background:none; border:none; color:var(--muted); font-size:15px;
  cursor:pointer; padding:4px 8px; font-family:inherit; line-height:1; }
.pop-x:hover{ color:var(--text); }
.pop-x:focus-visible{ outline:2px solid var(--accent2); outline-offset:2px; }

/* ── Pull-down con buscador (pulldown.js, 2026-08-01) ───────────────────────
   El selector ÚNICO para elegir de una lista larga: botón → panel con caja de
   búsqueda → eliges y se cierra. Reemplaza a los <datalist> nativos, que no
   reabren la lista completa si el campo tiene texto (y el truco que tapaba eso
   se comía lo tecleado al reenfocar). Vive acá, no en cada página, para que se
   vea igual en toda la app.
   Capas: el panel va a 260 — por encima del nav sticky (100) y sus menús
   (200/250), por debajo del modal (280), que es la escala de la casa. */
.ctpull{ position:relative; display:inline-flex; min-width:0; }
.ctpull-btn{ flex:1 1 auto; min-width:0; display:flex; align-items:center; gap:9px;
  background:var(--panel2); color:var(--text); border:1px solid var(--line);
  border-radius:9px; padding:8px 12px; font-family:inherit; font-size:13px;
  font-weight:600; cursor:pointer; text-align:left; }
.ctpull-btn:hover{ border-color:rgba(108,140,255,.45); }
.ctpull-btn:focus-visible{ outline:2px solid var(--accent2); outline-offset:2px; }
.ctpull.open .ctpull-btn{ border-color:rgba(108,140,255,.55); background:rgba(108,140,255,.08); }
.ctpull-car{ flex:none; color:var(--accent); font-size:10px; transition:transform .15s; }
.ctpull.open .ctpull-car{ transform:rotate(180deg); }
.ctpull-cur{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ctpull-cur.none{ color:var(--muted); font-weight:500; }
.ctpull-panel{ display:none; position:absolute; top:calc(100% + 5px); left:0; z-index:260;
  width:max(100%, 330px); max-width:min(560px, 92vw); background:var(--panel);
  border:1px solid rgba(108,140,255,.35); border-radius:11px; overflow:hidden;
  box-shadow:0 18px 40px rgba(0,0,0,.55); }
.ctpull.open .ctpull-panel{ display:block; }
.ctpull-q{ width:100%; box-sizing:border-box; background:var(--bg-soft); color:var(--text);
  border:none; border-bottom:1px solid var(--line); border-radius:0;
  padding:10px 13px; font-family:inherit; font-size:13px; }
.ctpull-q:focus{ outline:none; border-bottom-color:rgba(108,140,255,.55); }
.ctpull-list{ max-height:min(52vh, 340px); overflow:auto; }
.ctpull-opt{ padding:8px 13px; cursor:pointer; border-bottom:1px solid rgba(255,255,255,.04); }
.ctpull-opt:hover,.ctpull-opt.cur{ background:rgba(108,140,255,.14); }
.ctpull-opt.sel{ background:rgba(108,140,255,.09); }
.ctpull-opt.cur{ box-shadow:inset 2px 0 0 var(--accent2); }
.ctpull-nm{ display:block; font-size:13px; font-weight:600; color:var(--text); }
.ctpull-mt{ display:block; font-size:11px; color:var(--dim); margin-top:1px; }
.ctpull-clear{ color:var(--muted); font-size:12px; font-style:italic; }
.ctpull-empty{ padding:16px 13px; color:var(--dim); font-size:12.5px; text-align:center; }
/* Modo typeahead (CTPull.attach): el mismo panel, pero colgando de un <input>
   que sigue admitiendo texto libre. El input ES la caja de búsqueda. */
.ctpull-combo{ display:block; }
.ctpull-combo > input{ width:100%; }
/* fromSelect: el <select> original queda oculto dentro del wrapper y el
   pull-down ocupa su lugar, heredando el ancho que la página le había dado. */
.ctpull-wrap{ display:inline-flex; min-width:0; max-width:100%; }
.ctpull-wrap > .ctpull{ min-width:0; max-width:100%; }
