/* ═══════════════════════════════════════════════════════════════════════════
   APEX FLOW — LAYOUT DE ESCRITORIO  ·  F1  ·  2026-08-28
   Archivo: css/apex-flow-desktop.css

   Plan:      05_WEB/2026-08-28_plan_web_escritorio_v02.md  (§0.5 manda)
   Auditoría: 05_WEB/desktop/2026-08-28_auditoria_semantica.md
   Inventario:05_WEB/desktop/2026-08-28_inventario_escritorio.md
   ═══════════════════════════════════════════════════════════════════════════

   ⚠️ TRES REGLAS QUE GOBIERNAN ESTE ARCHIVO ENTERO ⚠️

   1 · TODO vive dentro de @media (min-width: 1024px). Sin excepción.
       No es prolijidad: es la palanca de rollback. Si esto sale mal en
       producción se quita UNA línea de functions.php y la app vuelve a ser
       exactamente la de hoy — sin revertir 20 archivos ni tocar la base.
       Y es lo que garantiza que el teléfono y el .aab de Android compilado no
       cambien ni un píxel: nunca llegan a 1024px.

   2 · NI UN COLOR LITERAL. Solo var(--…) de apex-tokens.css.
       Esto es LAYOUT, no marca. El día que APEX Flow y Academia tengan cada
       una su paleta (el portal somosapex), la rama visual se resuelve
       redefiniendo tokens y este archivo se ve correcto en las dos sin que
       nadie lo abra. Un lima de marca escrito a mano hoy es una búsqueda-y-
       reemplazo el año que viene.
       ⚠️ Verificable con un comando, a propósito — y por eso este comentario NO
       escribe ningún color de ejemplo, ni siquiera para ilustrar:
           grep -c '#[0-9a-fA-F]\{3,6\}' css/apex-flow-desktop.css   →  debe dar 0
       Si algún día da distinto de 0, se rompió la regla.

   3 · UN ARCHIVO, UNA RESPONSABILIDAD.
       Prohibido esparcir @media (min-width:1024px) dentro de
       apex-shell-nav.css (106 KB) o apex-start-content.css (53 KB). Si mañana
       el escritorio molesta, se sabe exactamente qué archivo abrir.
       Y nada acá gana por !important: gana por estar DESPUÉS en la cascada
       (se encola al final, ver functions.php). Un !important en este archivo
       es un síntoma de orden mal puesto, no una solución.

   ── QUÉ HACE ────────────────────────────────────────────────────────────────
   Rompe la caja de 560px en la que vive toda la app y monta:

     ┌──────────────────────────────────────────────────────────┐
     │  AX  APEX FLOW    Mercado › Contexto      [PRO]  (SP)▾   │  topbar
     ├────────────┬─────────────────────────────────────────────┤
     │ MERCADO    │                                             │
     │  Precios   │        contenido, máx. 1440px               │
     │ ▸Contexto  │                                             │
     │ MI OPERAT. │                                             │
     │ ...        │                                             │
     └────────────┴─────────────────────────────────────────────┘
        240px                    resto

   El menú lateral (apex-nav-desktop.php) reemplaza a la vez la barra inferior
   y la tira de fichas: los DOS niveles de navegación se ven a la vez.

   ── QUÉ NO HACE (F1 es estructura; el contenido es F2) ──────────────────────
   No re-acomoda el contenido de ninguna pantalla. Después de esta fase las
   tarjetas siguen en una columna, ahora dentro de un contenedor ancho. Se ve
   incompleto y está bien: mezclar estructura con contenido es lo que estanca
   estos rediseños. La rejilla de 12 columnas es F2; los gráficos, F3.
   ═══════════════════════════════════════════════════════════════════════════ */


@media (min-width: 1024px) {

  /* ═══ 1 · EL CAPARAZÓN ════════════════════════════════════════════════════
     D2 (decisión de Sergio, 2026-08-28): el corte es 1024 y no 1200. Cubre
     iPad en horizontal y portátiles de 13", que es donde está la gente que
     pidió la versión web.
     D3: la app de Android NO se excluye. Un teléfono nunca llega a 1024, así
     que el .aab compilado ve lo de siempre; una tablet en horizontal recibe
     este layout, que es mejor experiencia, no peor. */

  body.apex-app {
    /* La variable que apex-shell-nav.css ya lee en sus cuatro lugares. Este es
       el único sitio del proyecto donde el ancho de la app cambia de valor. */
    --apex-shell-max: 100%;

    --apex-desknav-w: 240px;      /* D1: menú expandido, no plegable a iconos */
    --apex-desk-max: 1440px;      /* coherente con la portada (1200-1360) */
    --apex-desk-gutter: 32px;
    --apex-desk-topbar-h: 64px;
  }

  .apex-app-shell {
    /* Dos columnas: menú fijo + contenido. El shell deja de ser una columna
       centrada y pasa a ser la grilla de la aplicación. */
    display: grid;
    grid-template-columns: var(--apex-desknav-w) minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "nav topbar"
      "nav main";
    max-width: none;
    margin: 0;
  }

  /* ═══ 2 · SE APAGA LA NAVEGACIÓN DE TELÉFONO ══════════════════════════════
     La barra inferior y la tira de fichas no se esconden por gusto: sus dos
     niveles están ahora en el menú lateral, a la vista de forma permanente.
     Dejarlas encendidas sería mostrar la misma navegación dos veces.

     `display:none` y no `visibility`: son `position:fixed`, así que ocultarlas
     a medias dejaría su caja tapando el pie del contenido. */
  body.apex-app .apex-mob-nav,
  body.apex-app .apex-subnav,
  body.apex-app .apex-modeswitch {
    display: none;
  }

  /* Y con ellas fuera, el hueco que el contenido les reservaba abajo sobra.
     Esas alturas las inyecta apex-niveles.php en el <body> según si hay tira
     de fichas o switch de zona; acá se neutralizan de una sola vez en lugar de
     perseguir cada combinación de clases. */
  body.apex-app .apex-app-content,
  body.apex-app.apex-has-subnav .apex-app-content,
  body.apex-app.apex-has-modeswitch .apex-app-content {
    padding-bottom: 48px;
  }

  /* ═══ 3 · MENÚ LATERAL ════════════════════════════════════════════════════ */

  /* Enciende el menú. Su estado por defecto (`display:none`) vive en
     apex-shell-nav.css a propósito — ver el comentario grande allá: si ESTE
     archivo no llegara al servidor, el menú tiene que seguir oculto en el
     teléfono, no aparecer como una lista de viñetas suelta. */
  .apex-desknav {
    grid-area: nav;
    display: flex;
    flex-direction: column;
    gap: 4px;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0 12px 24px;
    background: var(--bg-deeper);
    border-right: 1px solid var(--border);
  }

  /* Marca */
  .apex-desknav-marca {
    display: flex;
    align-items: center;
    gap: 10px;
    height: var(--apex-desk-topbar-h);
    flex: 0 0 var(--apex-desk-topbar-h);
    padding: 0 4px;
    text-decoration: none;
    border-bottom: 1px solid var(--border);
    margin-bottom: 12px;
  }
  .apex-desknav-iso {
    width: 34px; height: 34px; flex: 0 0 34px;
    display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-md);
    background: var(--bg4);
    border: 1px solid var(--accent-bd);
    font-family: var(--font-display); font-size: 17px; font-weight: 900;
    color: var(--text); line-height: 1; letter-spacing: -.01em;
  }
  .apex-desknav-iso i { color: var(--accent); font-style: normal; }
  .apex-desknav-marca-txt {
    font-family: var(--font-display);
    font-size: 17px; font-weight: 800;
    text-transform: uppercase; letter-spacing: .02em;
    color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  .apex-desknav-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
  .apex-desknav-grupo { list-style: none; }

  /* Área (Mercado · Mi operativa · Aprende · Disciplina) */
  .apex-desknav-area {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 10px;
    border-radius: var(--radius-md);
    text-decoration: none;
    color: var(--gray);
    font-family: var(--font-mono);
    font-size: 11px; font-weight: 600;
    letter-spacing: .07em; text-transform: uppercase;
    transition: color .15s, background-color .15s;
  }
  .apex-desknav-area:hover { color: var(--text); background: var(--bg2); }
  .apex-desknav-grupo.is-activo > .apex-desknav-area { color: var(--accent); background: var(--accent-bg); }
  .apex-desknav-ico { display: flex; flex: 0 0 18px; }
  .apex-desknav-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .apex-desknav-soon {
    margin-left: auto;
    font-size: 8.5px; letter-spacing: .1em;
    color: var(--gray2);
  }

  /* Fichas del área activa. El filete a la izquierda hace de canaleta: dice
     "esto cuelga de lo de arriba" sin necesidad de indentar con espacios. */
  .apex-desknav-fichas {
    list-style: none;
    margin: 2px 0 8px;
    padding: 0 0 0 19px;
    border-left: 1px solid var(--border2);
    margin-left: 19px;
    display: flex; flex-direction: column; gap: 1px;
  }
  .apex-desknav-ficha {
    display: block;
    padding: 6px 10px;
    border-radius: var(--radius);
    text-decoration: none;
    color: var(--gray);
    font-size: 13.5px;
    transition: color .15s, background-color .15s;
  }
  .apex-desknav-ficha:hover { color: var(--text); background: var(--bg2); }
  .apex-desknav-ficha.is-activo { color: var(--text); background: var(--bg3); font-weight: 600; }

  /* Contador opcional colgado por JS (hoy: operaciones abiertas en "En vivo").
     Mismo contrato `data-key` + <span hidden> que la tira de fichas del
     teléfono, para que un solo script alimente las dos. */
  .apex-desknav-n {
    display: none;
    margin-left: 6px;
    font-family: var(--font-mono); font-size: 10px; font-weight: 700;
    color: var(--accent);
  }
  .apex-desknav-n:not([hidden]) { display: inline; }

  .apex-desknav a:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  /* ═══ 4 · TOPBAR Y CONTENIDO ══════════════════════════════════════════════ */

  .apex-app-topbar {
    grid-area: topbar;
    height: var(--apex-desk-topbar-h);
    /* En el teléfono el topbar reserva el notch con env(safe-area-inset-top).
       En escritorio no hay notch y ese padding deja el título descolgado. */
    padding: 0 var(--apex-desk-gutter);
  }
  /* El isotipo del topbar es redundante con el del menú lateral, que está
     justo a su izquierda y además es el enlace al inicio. Se retira acá y no
     del PHP: en el teléfono sigue siendo la única marca en pantalla. */
  .apex-app-topbar .apex-app-iso { display: none; }

  .apex-app-content {
    grid-area: main;
    width: 100%;
    max-width: var(--apex-desk-max);
    margin: 0 auto;
    padding-left: var(--apex-desk-gutter);
    padding-right: var(--apex-desk-gutter);
  }

  /* El botón flotante "En vivo" ya está anclado a la derecha (right:14px), así
     que su posición horizontal no hace falta tocarla. Lo que sí: su `bottom`
     suma --apex-nav-h + --apex-subnav-h para montarse SOBRE la barra inferior y
     la tira de fichas. Acá esas dos no existen, así que sin esto el botón
     flotaría a media pantalla sobre nada. */
  body.apex-app .apex-vivo-fab {
    bottom: 24px;
    right: var(--apex-desk-gutter);
  }

  /* La barra de guardado de Reglas es `position:fixed` y centrada respecto del
     viewport entero: sin esto quedaría corrida hacia la izquierda, montada
     sobre el menú. Se alinea con el área de contenido. */
  .apex-rg-savebar,
  .apex-rg-toast {
    left: calc(50% + (var(--apex-desknav-w) / 2));
    bottom: 0;
  }
  .apex-rg-savebar { max-width: var(--apex-desk-max); }
  .apex-rg-toast { bottom: 88px; }

  /* ═══ 5 · SELLO DE ALCANCE ════════════════════════════════════════════════
     El arreglo del hallazgo §1 de la auditoría: hoy "Score de disciplina" dice
     60 en Resumen (agosto) y 54 en Mente (histórico), y NADA en pantalla
     explica por qué. En el teléfono se ve una pantalla por vez y la
     contradicción queda escondida; en escritorio, con el menú siempre visible
     y dos secciones a un clic, se exhibe.

     El sello dice, en toda pantalla con datos, qué ventana se está mirando.
     El markup lo pone apex-lab.php (una vez por pantalla, no por tarjeta: lo
     de por-tarjeta es F2) y el estilo base vive en apex-shell-nav.css para que
     TAMBIÉN se vea en el teléfono — no es una mejora de escritorio, es una
     corrección del producto. Acá solo se lo acomoda al ancho nuevo. */
  .apex-lab-alcance {
    max-width: none;
  }


  /* ═══ 6 · LA REJILLA DE CONTENIDO  ·  F2  ·  2026-08-28 ═══════════════════
     Plan: 05_WEB/2026-08-28_plan_web_escritorio_v02.md (F2)
     Inventario: 05_WEB/desktop/2026-08-28_inventario_escritorio.md

     REGLA DE LA FASE: solo CSS sobre contenedores que ya agrupan elementos
     repetidos (una lista de tarjetas, una lista de filas). Cero markup nuevo.
     Donde una pantalla necesitaría un contenedor que no existe —Resumen,
     Riesgo, Conceptos, Glosario— NO se fuerza nada acá: queda para F3
     (maestro-detalle) o directamente fuera de este plan (la tabla de
     Instrumentos es F4). Forzar una grilla sin el wrapper correcto sería
     inventar markup a mitad de fase, que es justo lo que esta regla evita.

     Un sub-bloque por pestaña, en el mismo orden que el plan. */

  /* ── F2.a · MERCADO ────────────────────────────────────────────────────── */

  /* Precios — mi lista + catálogo por bróker. Cada .apex-act-card/-row ya es
     una fila autocontenida (símbolo | precio | acciones); pasa de columna
     única a grilla sin tocar una línea de PHP. */
  .apex-act-seleccionados,
  .apex-act-grupo-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  }

  /* Noticias — mismo criterio: .apex-news-card ya es una unidad completa. */
  .apex-news-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    align-items: start;
  }

  /* Calendario — SIN cambios acá, a propósito. Los grupos por día
     (.apex-cal-dia-grupo) son hermanos sueltos dentro de .apex-app-content,
     sin un contenedor que los agrupe — ponerlos en columnas de "semana"
     pediría agregar ese wrapper en apex-start.php, y eso es exactamente el
     markup nuevo que esta fase no toca. Candidato anotado para F3. */

  /* Contexto y Relaciones comparten el mismo componente de tarjetas
     (apex_contexto_registro() / apex_relaciones_render_par_correlacion()),
     así que UNA regla resuelve las dos pantallas — coherente con la Regla
     3.4 del plan (cero duplicación). auto-fit y no un número fijo de
     columnas: son tarjetas homogéneas, cuánto entra depende del texto real
     de cada frase, no de una cuenta redonda. */
  .apex-ctx-grid {
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  }
  /* Sin !important: misma especificidad que la regla de apex-shell-nav.css
     (0,1,0 los dos), así que gana por Regla 3.2 — por estar DESPUÉS en la
     cascada. Verificado en functions.php: apex-flow-desktop se encola con
     dependencia de apex-shell-nav y su llamada queda última en la función,
     así que su <link> imprime último sin importar en qué @media caiga cada
     regla. Dos umbrales de min-width no se ordenan entre sí por su número —
     los ordena la hoja en la que están, y la última hoja gana. */

  /* Volatilidad — hoy es una sola tarjeta ancha (D6: los 3 componentes de
     gráfico son F3, no F2). Se la limita para que no se estire a 1440px de
     puro texto — leer un párrafo de ese ancho es peor, no mejor. */
  .apex-start-volatilidad .apex-vol-card {
    max-width: 640px;
  }

  /* ── F2.b · MI OPERATIVA ───────────────────────────────────────────────── */

  /* Las tarjetas de KPI (P&L neto, operaciones, mejor/peor, exposición…) que
     usan Resumen, Rendimiento y Riesgo. 2 columnas alcanzaba en 560px; a
     1024 hay lugar de sobra para las 4 de una fila. La variante de 3
     columnas de "En vivo" (posición abierta: R, stop, equilibrio) queda
     como está — 3 ya es lo que le corresponde a esos datos. */
  .apex-lab-stats {
    grid-template-columns: repeat(4, 1fr);
  }

  /* Riesgo — la lista de "consistencia por activo" (.apex-an-corte) NO pasa
     a 2 columnas, a propósito: es una comparación entre instrumentos, tipo
     ranking, y leerla en dos columnas obligaría a comparar barras que no
     están una debajo de la otra. Una sola columna ancha es la lectura
     correcta, no una limitación de esta fase. */

  /* Operaciones e Instrumentos — sus tablas (.apex-an-tabla-*) no se tocan
     acá. Es trabajo de F4 (columnas que hoy se esconden en 560px vuelven),
     no de reacomodar en columnas. */

  /* ── F2.c · APRENDE ────────────────────────────────────────────────────── */

  /* Calculadora — el candidato más directo del inventario: formulario a la
     izquierda, resultado FIJO a la derecha. Los tres bloques (.apex-calc-form,
     .apex-calc-instr-nota, .apex-calc-out) ya son hijos directos de .apex-calc
     en ese orden en el DOM; se ubican por selector, no por orden — así el
     resultado puede ir a la columna 2 aunque en el HTML venga después de la
     nota. Sticky: en un formulario largo, el resultado no se pierde scrolleando. */
  /* ⚠️ .apex-calc tiene MÁS hijos de los que el nombre de la pantalla sugiere
     — verificado en el DOM, no adivinado: lead, form, nota, resultado,
     "¿cómo se usa esto?", la tarjeta de venta de Pro y el disclaimer legal.
     Confiar en el auto-placement de grid para los que no se asignan a mano
     es fragilidad — un reordenamiento de PHP el día de mañana movería la
     tarjeta de venta a mitad de columna sin que nadie lo pida. Cada hijo
     tiene su columna puesta explícitamente, ninguno queda "a la suerte". */
  .apex-calc {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: 8px 32px;
    align-items: start;
  }
  .apex-calc-form { grid-column: 1; }
  .apex-calc-instr-nota { grid-column: 1; }
  .apex-calc-out {
    grid-column: 2;
    grid-row: 2 / span 2;
    position: sticky;
    top: calc(var(--apex-desk-topbar-h) + 24px);
  }
  /* Todo lo demás —intro, "¿cómo se usa?", venta de Pro, disclaimer— a
     ancho completo, por debajo del par formulario/resultado. No compiten
     con el resultado fijo por espacio de columna. */
  .apex-calc > .apex-start-lead,
  .apex-calc > .apex-start-explica,
  .apex-calc > .apex-lab-card,
  .apex-calc > .apex-calc-disclaimer {
    grid-column: 1 / -1;
  }

  /* Checklist — 7 casilleros en columna única hoy; cada .apex-checklist-item
     es una fila autocontenida (checkbox + texto), grillable sin tocar PHP.
     ⚠️ El contenedor NO envuelve solo los 7 casilleros: también el párrafo
     de intro (.apex-start-lead) y el <details> "¿Por qué este checklist?"
     (verificado en el DOM, no supuesto). Sin esta salvedad, esos dos caen
     como si fueran casilleros más y ocupan la primera fila de la grilla —
     se detectó mirando la pantalla, no leyendo el PHP. */
  .apex-checklist {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px 24px;
  }
  .apex-checklist > .apex-start-lead,
  .apex-checklist > .apex-start-explica {
    grid-column: 1 / -1;
  }

  /* Videos — 2026-09-02: las tarjetas pasaron a VERTICAL 9:16 (toda la serie se
     graba así). Son angostas, así que en escritorio entran CUATRO; desde 620px
     ya son tres (apex-start-content.css). Con menos columnas cada tarjeta se
     estira a lo alto y una fila ocupa más que la pantalla. */
  .apex-videos-grid {
    grid-template-columns: repeat(4, 1fr);
  }
  /* Sin !important, mismo motivo que .apex-ctx-grid: gana por estar en la
     última hoja encolada (Regla 3.2), no por especificidad forzada. */

  /* Conceptos y Glosario — SIN cambios acá, a propósito (D6 / plan §F3): son
     los dos candidatos más claros a maestro-detalle (índice fijo a la
     izquierda + contenido a la derecha), y eso es un patrón de interacción
     nuevo, no una grilla. Forzarlos a 2 columnas ahora sería trabajo que hay
     que deshacer en F3. */

  /* ── F2.d · DISCIPLINA ─────────────────────────────────────────────────── */

  /* Declarar — el catálogo de reglas en accordions (uno por familia, "Lo
     esencial" incluido) pasa de lista vertical a 2 columnas. Y, dentro de un
     accordion ABIERTO, sus filas (.apex-rg-fila) también — cada fila ya es
     autocontenida (etiqueta + control), es la misma operación que en
     Checklist. Se sobreescribe display:block del JS de apertura por
     display:grid; nada del comportamiento de abrir/cerrar cambia. */
  .apex-rg-accordions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px 16px;
  }
  .apex-rg-accordion.is-open .apex-rg-acc-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 20px;
  }
  /* ⚠️ Mismo bug que en Checklist, mismo arreglo: cada .apex-rg-acc-body
     abre con un párrafo de ayuda (.apex-lab-muestra — "Con estas seis
     alcanza…" o el texto de la familia) ANTES de las filas de reglas.
     Verificado en apex-lab-reglas.php, no supuesto. Sin esto, la ayuda
     comparte fila con la primera regla en vez de ir arriba de las dos
     columnas. */
  .apex-rg-acc-body > .apex-lab-muestra {
    grid-column: 1 / -1;
  }

  /* Mi plan e Historial — SIN cambios: las píldoras de reglas
     (.apex-rg-chips) ya son flex-wrap y aprovechan el ancho solas; Historial
     es una lista corta que no gana nada forzándola a columnas. */


  /* ═══ 7 · MAESTRO–DETALLE  ·  F3  ·  2026-08-28 ══════════════════════════
     Plan §F3 · auditoría §2.1. Conceptos (32 lecciones / 6 módulos) y Glosario
     (72 términos) dejan de ser un scroll a ciegas: índice fijo a la izquierda,
     contenido a la derecha.

     El markup lo emite apex-indice-lateral.php en TODOS los anchos; su estado
     por defecto (oculto + display:contents) está en apex-shell-nav.css. Acá
     solo se lo enciende. */

  .apex-md {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    gap: 40px;
    align-items: start;
  }
  .apex-md-cuerpo { display: block; min-width: 0; }

  .apex-md-indice {
    display: block;
    position: sticky;
    /* Debajo del topbar, que es sticky y opaco: sin esto el índice se le mete
       por abajo al scrollear. */
    top: calc(var(--apex-desk-topbar-h) + 20px);
    max-height: calc(100vh - var(--apex-desk-topbar-h) - 40px);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 4px;
  }
  .apex-md-indice-t {
    margin: 0 0 10px;
    font-family: var(--font-mono);
    font-size: 10px; font-weight: 700;
    letter-spacing: .12em; text-transform: uppercase;
    color: var(--gray2);
  }
  .apex-md-indice-lista {
    list-style: none;
    margin: 0; padding: 0;
    display: flex; flex-direction: column; gap: 1px;
    /* Contador propio: los números del índice son la POSICIÓN del módulo (1-6),
       información real del orden en que hay que leerlos — el propio lead dice
       "en orden: primero cómo funciona el mercado…". No es decoración. */
    counter-reset: apexmd;
  }
  .apex-md-indice-a {
    counter-increment: apexmd;
    display: flex; align-items: baseline; gap: 8px;
    padding: 7px 10px;
    border-radius: var(--radius);
    border-left: 2px solid transparent;
    text-decoration: none;
    color: var(--gray);
    font-size: 13px; line-height: 1.35;
    transition: color .15s, background-color .15s, border-color .15s;
  }
  .apex-md-indice-a::before {
    content: counter(apexmd);
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-size: 10px; font-weight: 700;
    color: var(--gray2);
  }
  .apex-md-indice-a:hover { color: var(--text); background: var(--bg2); }
  /* `is-viendo` la pone el IntersectionObserver de apex-indice-lateral.php. */
  .apex-md-indice-a.is-viendo {
    color: var(--accent);
    border-left-color: var(--accent);
    background: var(--accent-bg);
  }
  .apex-md-indice-a.is-viendo::before { color: var(--accent); }
  .apex-md-indice-lbl { min-width: 0; }
  .apex-md-indice-n {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--gray2);
  }
  .apex-md-indice-a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

  /* Al saltar por un ancla, el destino no puede quedar tapado por el topbar
     sticky. Vale para los módulos, los grupos del glosario Y los términos
     sueltos — que son el destino de los enlaces "En el glosario: …" que
     Conceptos ya tenía desde antes de este proyecto. */
  .apex-con-mod,
  .apex-glo-grupo,
  .apex-glo-item {
    scroll-margin-top: calc(var(--apex-desk-topbar-h) + 24px);
  }

  /* El buscador del glosario queda arriba del par índice/contenido, a ancho
     completo: filtra TODOS los grupos, así que meterlo en una columna lo
     haría parecer que filtra solo esa. */
  .apex-glo-buscar { max-width: 520px; }


  /* ═══ 8 · GRÁFICOS (D6) ══════════════════════════════════════════════════
     El gráfico de banda se dibuja en los dos anchos y sus estilos viven en la
     hoja base (apex-shell-nav.css). Lo único que cambia acá es el alto: con el
     espacio de un monitor la figura respira y las tres bandas anidadas se
     distinguen sin forzar la vista. Una variable, no una regla duplicada. */
  /* 2026-09-01 · Ahora esta variable gobierna el alto de la PISTA sola (los
     divs de las bandas), no el del SVG entero — que además incluía las
     etiquetas. 150px de pista pelada quedaba desproporcionado; 110 mantiene
     la figura cómoda en escritorio sin volverla un cartel. */
  body.apex-app { --apex-vol-graf-h: 110px; }

  /* La ficha de Volatilidad deja de estar limitada a 640px cuando trae
     gráfico: el ancho ahora lo justifica una figura, no un párrafo estirado
     (que era el motivo del tope que puso F2). */
  .apex-start-volatilidad .apex-vol-card:has(.apex-vol-grafico) {
    max-width: 940px;
  }


  /* ═══ 9 · TABLAS ANCHAS  ·  F4  ·  2026-08-29 ═════════════════════════════
     Plan §F4 · inventario §Mi operativa item 12.

     ⚠️ HALLAZGO al verificar en producción con datos reales, no en el plan
     original: Instrumentos (.apex-an-tabla--activos) YA tiene sus 8 columnas
     propias en apex-shell-nav.css y se ve perfecta en escritorio — nada que
     hacer ahí, el "Cost drag" que el inventario de F0 marcó como cortado a
     560px hoy se lee entero solo por el ancho que dio F1.

     El problema real estaba en OPERACIONES: su cabecera ya declara 7 columnas
     (Fecha·Activo·Dir·Resultado·MAE·MFE·Salida — apex-lab-operaciones.php:91)
     pero `.apex-an-tabla--operaciones` nunca tuvo su propia grilla y hereda la
     base de 5 columnas (apex-shell-nav.css:1028). Con 7 ítems en 5 columnas,
     el navegador envuelve los 2 de más a una segunda fila — que es EXACTAMENTE
     el "MFE / Salida% apilados debajo de Fecha / Activo" que se veía en
     pantalla. No era diseño: era el ajuste de 560px filtrándose sin querer.
     A 1024px+ hay lugar de sobra para las 7 en una sola fila — la misma
     información, sin envolver nada. */
  .apex-an-tabla--operaciones .apex-an-tabla-h,
  .apex-an-tabla--operaciones .apex-an-tabla-r {
    grid-template-columns: .9fr .8fr .6fr 1fr 1fr 1fr .7fr;
  }
  /* Resultado, MAE, MFE y Salida son columnas numéricas — a la derecha se
     comparan de un vistazo entre filas, que es para lo que sirve una tabla. */
  .apex-an-tabla--operaciones .apex-an-tabla-h > :nth-child(4),
  .apex-an-tabla--operaciones .apex-an-tabla-r > :nth-child(4),
  .apex-an-tabla--operaciones .apex-an-tabla-h > :nth-child(5),
  .apex-an-tabla--operaciones .apex-an-tabla-r > :nth-child(5),
  .apex-an-tabla--operaciones .apex-an-tabla-h > :nth-child(6),
  .apex-an-tabla--operaciones .apex-an-tabla-r > :nth-child(6),
  .apex-an-tabla--operaciones .apex-an-tabla-h > :nth-child(7),
  .apex-an-tabla--operaciones .apex-an-tabla-r > :nth-child(7) {
    text-align: right;
  }

  /* Barrido de overflow-x sobrante (plan §F4): con el contenedor ancho, un
     min-width que fuerce scroll horizontal cuando sobra espacio es un bug,
     no un diseño. La de Instrumentos es la única con min-width propio y a
     1024px+ nunca hace falta — se neutraliza para que nunca se dispare por
     accidente en una ventana angosta-pero-ya-de-escritorio (1024-1200px). */
  .apex-an-tabla--activos { min-width: 0; }


  /* ═══ 10 · NOTICIAS EN MAESTRO–DETALLE  ·  F3  ·  2026-08-29 ══════════════
     Plan §F3 · auditoría §2.1: *"Hoy leer una noticia es ir a otra URL y
     volver; ahí es hacer clic en la lista y seguir leyendo."*

     Con nota abierta: lista angosta a la izquierda, nota a la derecha. Sin
     nota abierta, la lista ocupa todo el ancho y sigue siendo la grilla de
     tarjetas que dejó F2 — no se fuerza una columna vacía esperando un clic. */

  .apex-md-news--con-ficha {
    display: grid;
    grid-template-columns: 330px minmax(0, 1fr);
    gap: 32px;
    align-items: start;
  }
  /* La lista vuelve a mostrarse (en teléfono estaba oculta) y se ordena a la
     IZQUIERDA aunque en el DOM venga después de la ficha. Es la pieza que
     evita tener que reordenar 120 líneas de PHP — ver el comentario en
     apex-start.php. */
  .apex-md-news--con-ficha .apex-start-noticias { display: block; order: 1; }
  .apex-md-news--con-ficha .apex-noticia-ficha  { order: 2; }

  /* En la columna angosta la lista deja de ser grilla y vuelve a ser lista:
     es un índice, no una vitrina. Pegajosa, para no perderla al leer una nota
     larga. */
  .apex-md-news--con-ficha .apex-news-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  .apex-md-news--con-ficha .apex-start-noticias {
    position: sticky;
    top: calc(var(--apex-desk-topbar-h) + 20px);
    max-height: calc(100vh - var(--apex-desk-topbar-h) - 40px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  /* El resumen sobra en el índice: el titular alcanza para elegir, y sin él
     entran muchas más notas sin scrollear. El texto completo está a la derecha. */
  .apex-md-news--con-ficha .apex-news-resumen { display: none; }

  /* Cuál se está leyendo. Mismo lenguaje que la ficha activa del menú lateral
     y que el índice de Conceptos — una sola gramática visual para "estás acá". */
  .apex-news-card.is-abierta {
    border-color: var(--accent-bd);
    background: var(--accent-bg);
  }

  /* "← Volver a noticias" era la única forma de regresar cuando la ficha
     reemplazaba a la lista. Con la lista visible al lado, es un botón que no
     lleva a ningún lado nuevo. Se retira SOLO en escritorio: en teléfono sigue
     siendo imprescindible. */
  .apex-md-news--con-ficha .apex-noticia-volver { display: none; }


  /* ═══ 11 · OPERACIONES EN MAESTRO–DETALLE  ·  F3  ·  2026-08-29 ══════════
     Plan §F3 · auditoría §2.1: *"tabla arriba, ficha de la operación
     seleccionada abajo o al lado."*

     A diferencia de Noticias, acá NO hay estado en la URL — el panel se abre
     por JS al tocar una fila (ver apex-lab-operaciones.php). Por eso el
     layout de 2 columnas es FIJO desde que se entra a la pantalla, con el
     panel mostrando su estado vacío hasta el primer clic — no aparece recién
     cuando hay algo que mostrar, que dejaría a la tabla saltando de ancho. */
  .apex-md-ops {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 24px;
    align-items: start;
  }
  .apex-op-detalle,
  .apex-op-detalle-vacio {
    grid-column: 2;
    grid-row: 1;
    position: sticky;
    top: calc(var(--apex-desk-topbar-h) + 20px);
  }
  /* `hidden` del HTML ya oculta uno u otro — acá solo se asegura que el que
     esté visible ocupe la columna, nunca los dos compitiendo por ella. */
  .apex-op-detalle[hidden],
  .apex-op-detalle-vacio[hidden] { display: none; }

  /* ⚠️ ARREGLO 2026-08-29 (Tanda 2, docx "análisis escritorio" #5) — Sergio:
     "MI OPERATIVA/OPERACIÓN solo está desfasado un cuadrado, sale de su
     recuadro. El que dice +$5,05". Confirmado por qué: la sección 6 de este
     archivo pone `.apex-lab-stats` en `repeat(4, 1fr)` a partir de 1024px —
     correcto para Resumen/Rendimiento/Riesgo, donde esas tarjetas KPI viven a
     todo el ancho de la página. Pero `.apex-op-detalle` (arriba) es un panel
     de solo **320px**: forzar 4 columnas ahí deja ~65px por columna, y una
     etiqueta como "RIESGO PUESTO EN JUEGO" envuelve a 3-4 líneas mientras sus
     vecinas ("LOTES", "33 MIN") entran en una — la tarjeta larga se sale de
     la fila. Se vuelve a 2 columnas, como en mobile, que es lo que 320px de
     verdad sostiene. Único lugar donde pasa: `apex-lab-operaciones.php` es el
     único archivo que mete `.apex-lab-stats` dentro de un panel angosto (se
     verificó grep sobre los demás usos — todos viven a ancho completo). */
  .apex-op-detalle .apex-lab-stats {
    grid-template-columns: 1fr 1fr;
  }


  /* ═══ 12 · ALARMAS Y AVISOS POR NOTICIA  ·  2026-08-29 ═══════════════════
     Reporte de Sergio (docx "análisis escritorio"), verificado con capturas
     reales: cada alarma y cada opción de aviso ocupaba una fila a TODO el
     ancho del contenedor —hasta 860px— para mostrar 30-40 caracteres. Se
     leía "muy extendido, espacio perdido". Mismo defecto que el resto del
     plan v02 antes de esta pasada: ancho ganado, densidad no.

     Pedido de Sergio: "una al lado de otra y si supera cinco alarmas ya
     pasar abajo" — es el patrón auto-fill que ya usa el resto del plan (F2,
     sección 6), no uno nuevo. */
  #apexAlmLista {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 8px;
  }
  /* .apex-alm-row trae su propio margin-bottom (base, para mobile en columna
     única) — en la grilla ese margen duplica el gap. Se anula acá, no en la
     base, para no tocar el comportamiento mobile. */
  #apexAlmLista .apex-alm-row { margin-bottom: 0; }
  /* El estado vacío ("Sin alarmas todavía…") es un solo párrafo — si quedara
     dentro de la grilla, ocuparía una sola celda de 220px en vez de la fila
     completa y se leería descentrado. */
  #apexAlmLista .apex-act-vacio { grid-column: 1 / -1; }

  /* Los 4 niveles de "Avisos por noticia" tenían el mismo problema — título +
     una línea de texto en una tarjeta a todo el ancho. 2 columnas alcanzan:
     son 4 opciones fijas, nunca una lista larga que necesite auto-fill. */
  .apex-nnot-ops {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
  }


  /* ═══ 13 · PRECIOS COMO DASHBOARD  ·  2026-08-29 ═════════════════════════
     Pedido textual de Sergio: "aquí está la magia de escritorio… podría estar
     en un bloque tu lista seleccionada a la izq y a la derecha tus alarmas, y
     abajo tu lista completa de activos. Como un verdadero dashboard".

     Sale SIN markup nuevo: los bloques ya son hijos directos de .apex-activos
     en el orden correcto (lead · frescura · mi-lista · alarmas · catálogo ·
     nota-pro). Solo hace falta declarar la rejilla y decir qué ocupa el ancho
     completo. Los <script> intercalados no molestan: son display:none por la
     hoja del navegador, así que no generan celda.

     ⚠️ EL GUARDA :has() NO ES ADORNO. El bloque de alarmas solo se renderiza
     para Pro (y mi-lista puede no estar para el anónimo). Sin el guarda, un
     usuario gratis tendría mi-lista sola en la columna izquierda y media
     pantalla vacía a la derecha — cambiaríamos el espacio perdido de lugar en
     vez de arreglarlo. Con el guarda, si falta cualquiera de los dos la
     pantalla se queda como está hoy (apilada), que es lo correcto ahí. */
  .apex-activos:has(.apex-act-mi-lista):has(.apex-act-alarmas) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0 24px;
    align-items: start;
  }
  .apex-activos:has(.apex-act-mi-lista):has(.apex-act-alarmas) > .apex-start-lead,
  .apex-activos:has(.apex-act-mi-lista):has(.apex-act-alarmas) > .apex-act-frescura,
  .apex-activos:has(.apex-act-mi-lista):has(.apex-act-alarmas) > .apex-act-catalogo,
  .apex-activos:has(.apex-act-mi-lista):has(.apex-act-alarmas) > .apex-act-pro-nota,
  .apex-activos:has(.apex-act-mi-lista):has(.apex-act-alarmas) > .apex-act-migracion,
  .apex-activos:has(.apex-act-mi-lista):has(.apex-act-alarmas) > .apex-calc-aviso {
    grid-column: 1 / -1;
  }
  .apex-activos:has(.apex-act-mi-lista):has(.apex-act-alarmas) > .apex-act-mi-lista { grid-column: 1; }
  .apex-activos:has(.apex-act-mi-lista):has(.apex-act-alarmas) > .apex-act-alarmas  { grid-column: 2; }

  /* 🚨 ARREGLADO 2026-08-31 — EL TEXTO SE ENCIMABA CON LOS VALORES.
     Reportado por Sergio con una captura de "Mi lista": el símbolo, el precio
     y la variación aparecían escritos unos encima de otros, y "En vivo" partido
     en dos líneas ("En" / "vivo").

     Acá decía `minmax(200px, 1fr)`, y su comentario justificaba el número
     diciendo que "sigue alcanzando para EURUSD 1,0850 🔔 ×". **Ese ejemplo era
     el contenido más corto posible.** El real es `BTC/USD 77.839,68 −1,35%`.
     MEDIDO en pantalla: la tarjeta necesita **273 px** de ancho natural y la
     grilla le daba **220** — quedaban 104 px para tres textos que piden ~159.
     Las cajas no se solapaban entre sí: se aplastaban por debajo de su
     contenido y el TEXTO se desbordaba de cada una. Por eso "En vivo", que
     tiene un espacio donde cortar, se partía, y "BTC/USD", que no lo tiene, se
     montaba sobre el número.

     El mínimo pasa a 290 px (273 medidos + aire para un símbolo más largo o un
     precio de 6 cifras). En un portátil de 1440 siguen entrando 2 por lado. */
  .apex-act-mi-lista .apex-act-seleccionados {
    grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  }

  /* Y el cinturón, además del tirante: aunque una tarjeta quede corta por lo
     que sea, el texto NO se desborda ni se parte. El símbolo cede primero
     (con puntos suspensivos); el precio y la variación no se rompen nunca,
     porque un número partido a la mitad es peor que un nombre recortado. */
  .apex-act-card-sym {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .apex-act-card-precio,
  .apex-act-card-cambio {
    white-space: nowrap; flex: 0 0 auto;
  }
  .apex-act-card-precio { margin-left: auto; }


  /* ══ LEGIBILIDAD EN ESCRITORIO ═══════════════════════════════════════════
     Sergio, sobre el bloque de alertas del calendario: *"deberías subirle un
     número más a estas letras porque en la computadora casi ni se lee"*.

     LA CAUSA NO ES EL TAMAÑO EN SÍ, ES LA DISTANCIA. Estos cuerpos de 12 px se
     calibraron en el teléfono, que se sostiene a ~30 cm; un monitor está a ~60.
     Al doble de distancia, 12 px rinden como 6. Por eso el mismo texto que en
     el celular se lee cómodo, en la computadora "casi ni se lee" — y por eso el
     arreglo va acá, en el corte de escritorio, sin tocar el móvil, donde el
     tamaño actual es el correcto.

     Se sube un punto (12 → 13, y el título del bloque 13 → 14) y se aclara el
     gris: el problema era la suma de los dos, no solo el cuerpo. Va por CLASE y
     no por un `font-size` global, para no arrastrar cambios en tablas y datos
     mono, que están calibrados aparte. */
  .apex-act-pro-nota p { font-size: 13px; color: var(--gray2); }
  .apex-act-pro-nota b { font-size: 14px; }
  .apex-cal-nota      { font-size: 13px; }
  .apex-cal-fuente    { font-size: 12px; }
  .apex-nnot-d,
  .apex-nnot-op-d     { font-size: 13px; }
  .apex-nnot-nota     { font-size: 12.5px; }

}
