
  /* ══════════════════════════════════════════════════════
     DESIGN TOKENS — Flow Tracker
     Tema oscuro (default) + tema claro vía html[data-theme="light"].
     Los "wash" son lavados de superficie: en dark son blancos
     translúcidos, en light son negros translúcidos. Todo el CSS
     y el HTML generado por JS usan estos tokens — no agregar
     colores hardcodeados nuevos.
     ══════════════════════════════════════════════════════ */
  :root {
    color-scheme: dark;
    /* Dark mode refinado (sistema de diseño v3) */
    --bg:    #121214;
    --bg2:   #18181b;
    --card:  #1f1f23;
    --card2: #26262b;
    --border:  rgba(255,255,255,0.07);
    --border2: rgba(255,255,255,0.14);
    --text:  #f5f5f7;
    --text2: #a1a1a6;
    --text3: #868686;   /* A11y H3 (B5): antes #636366 (2.74:1 sobre card = FALLA AA); ahora 4.51:1 card / 5.14:1 bg, sigue por debajo de text2 */
    --accent: #0a84ff;
    --accent-hover: #409cff;
    --accent-soft:   rgba(var(--accent-rgb),0.16);
    --accent-border: rgba(var(--accent-rgb),0.32);
    /* Azul FIJO — no editable desde Editor UI. Úsalo para iconos/cifras de
       KPI que deben mantener su color sin importar el acento personalizado
       (p.ej. "Shows activos" y "Entregas esta semana" del Dashboard). */
    --kpi-blue:     #0a84ff;
    --kpi-blue-rgb: 10,132,255;
    --green:  #30d158;
    --yellow: #ffd60a;
    --orange: #ff9f0a;
    --red:    #ff453a;
    --purple: #bf5af2;
    /* Lavados de superficie (hover, inputs, barras, bordes suaves) */
    --wash-1: rgba(255,255,255,0.03);
    --wash-2: rgba(255,255,255,0.055);
    --wash-3: rgba(255,255,255,0.08);
    --wash-4: rgba(255,255,255,0.13);
    --wash-5: rgba(255,255,255,0.30);
    --logo-bg: rgba(255,255,255,0.93);
    --shadow-card:  0 1px 2px rgba(0,0,0,0.30);
    --shadow-modal: 0 24px 64px rgba(0,0,0,0.55);
    --shadow-pop:   0 12px 32px rgba(0,0,0,0.44);
    --thumb-bg: rgba(255,255,255,0.05);
    --sidebar-w: 216px;
    --radius:    12px;
    --radius-sm: 9px;
    --radius-xs: 6px;
    /* ── Fundación ampliada (unificación v4) ───────────────────
       Tokens aditivos. Familias de color soft/border que SÍ se
       adaptan al tema (antes se usaban rgba() crudos que se veían
       oscuros incluso en light). Cyan tokenizado. Radios lg/pill,
       escala tipográfica, spacing y motion. ──────────────────── */
    /* Componentes RGB por tema → permiten rgba(var(--green-rgb), α) que
       conserva la transparencia exacta y adapta el tono al tema. */
    --accent-rgb: 10,132,255;
    --green-rgb:  48,209,88;
    --yellow-rgb: 255,214,10;
    --orange-rgb: 255,159,10;
    --red-rgb:    255,69,58;
    --purple-rgb: 191,90,242;
    --cyan-rgb:   100,210,255;
    --cyan:         #64d2ff;
    --cyan-soft:    rgba(var(--cyan-rgb),0.16);
    --cyan-border:  rgba(var(--cyan-rgb),0.30);
    --green-soft:   rgba(var(--green-rgb),0.15);
    --green-border: rgba(var(--green-rgb),0.30);
    --yellow-soft:  rgba(var(--yellow-rgb),0.15);
    --yellow-border:rgba(var(--yellow-rgb),0.30);
    --orange-soft:  rgba(var(--orange-rgb),0.15);
    --orange-border:rgba(var(--orange-rgb),0.30);
    --red-soft:     rgba(var(--red-rgb),0.15);
    --red-border:   rgba(var(--red-rgb),0.30);
    --purple-soft:  rgba(var(--purple-rgb),0.15);
    --purple-border:rgba(var(--purple-rgb),0.30);
    /* ══ COLORES DE ESTATUS DE FPT (2026-08-26) ══════════════════
       Fuente de verdad ÚNICA de «Shots para revisión» y «KBKs Internos».
       Los `--rev-*` / `--kbk-*` son los MISMOS hex que el usuario ve en la
       instancia de Flow Production Tracking: el color de la app y el de FPT
       tienen que coincidir para reconocer el estatus de un vistazo. NO se
       tocan — cualquier ajuste de legibilidad vive en las variantes.

       Tres variantes por tono, y cada una tiene UN trabajo:
         ·  (sin sufijo) RELLENO — segmento de barra, punto de leyenda, chip
            activo. Hex EXACTO de FPT.
         ·  -ink        TEXTO y BORDE. Mismo matiz (hue idéntico), solo se
            mueve la luminosidad. Es el único token que cambia con el tema.
         ·  -on         texto que va ENCIMA del relleno (chip lleno). Negro o
            blanco según cuál de los dos gana contra el hex: se calculó la
            luminancia relativa, no se eligió a ojo.

       Por qué hacen falta las variantes: sobre el tema CLARO, los hex de FPT
       dan 1.52:1 (Artista), 1.44:1 (VFX Sup) y 1.09:1 (VFX Sup KBK) — texto
       ilegible y hasta un segmento de barra invisible sobre la pista. Las
       tintas de abajo cumplen >=4.55:1 sobre card/bg/card2 Y sobre su propio
       lavado al 14%, conservando el matiz:
         artista  #94e3a7 -> claro #207b36 (4.55:1) · oscuro el hex tal cual (7.03:1)
         lead     #818181 -> claro #656565 (4.55:1) · oscuro #9b9b9b (4.55:1)
         vfx sup  #00f900 -> claro #007b00 (4.55:1) · oscuro el hex tal cual (7.63:1)
         context  #835802 -> claro el hex tal cual (4.61:1) · oscuro #cb8700 (4.55:1)
         qc       #6e00f9 -> claro el hex tal cual (4.80:1) · oscuro #af6fff (4.55:1)
         kbk sup  #f9fe02 -> claro #707200 (4.55:1) · oscuro el hex tal cual (9.14:1)
         kbk lead #717171 -> claro #636363 (4.55:1) · oscuro #999999 (4.55:1)
       Aquí van los valores del tema OSCURO (el default de la app); el bloque
       html[data-theme="light"] sobrescribe SOLO las tintas. ═════════════ */
    --rev-artist:      #94e3a7;  --rev-artist-rgb:  148,227,167;
    --rev-lead:        #818181;  --rev-lead-rgb:    129,129,129;
    --rev-sup:         #00f900;  --rev-sup-rgb:     0,249,0;
    --rev-context:     #835802;  --rev-context-rgb: 131,88,2;
    --rev-qc:          #6e00f9;  --rev-qc-rgb:      110,0,249;
    --kbk-sup:         #f9fe02;  --kbk-sup-rgb:     249,254,2;
    --kbk-lead:        #717171;  --kbk-lead-rgb:    113,113,113;
    /* Tintas — tema oscuro */
    --rev-artist-ink:  #94e3a7;
    --rev-lead-ink:    #9b9b9b;
    --rev-sup-ink:     #00f900;
    --rev-context-ink: #cb8700;
    --rev-qc-ink:      #af6fff;
    --kbk-sup-ink:     #f9fe02;
    --kbk-lead-ink:    #999999;
    /* Texto sobre el relleno (no depende del tema: el relleno tampoco) */
    --rev-artist-on:   #000000;   /* 13.80:1 contra #94e3a7 (blanco daría 1.52:1) */
    --rev-lead-on:     #000000;   /*  5.39:1 contra #818181 (blanco daría 3.90:1) */
    --rev-sup-on:      #000000;   /* 14.55:1 contra #00f900 (blanco daría 1.44:1) */
    --rev-context-on:  #ffffff;   /*  6.25:1 contra #835802 (negro daría 3.36:1)  */
    --rev-qc-on:       #ffffff;   /*  6.93:1 contra #6e00f9 (negro daría 3.03:1)  */
    --kbk-sup-on:      #000000;   /* 19.21:1 contra #f9fe02 (blanco daría 1.09:1) */
    --kbk-lead-on:     #ffffff;   /*  4.88:1 contra #717171 (negro daría 4.30:1)  */
    /* Lavados: el 14% es el valor con el que se validaron las tintas de arriba. */
    --rev-artist-soft:  rgba(var(--rev-artist-rgb),0.14);
    --rev-lead-soft:    rgba(var(--rev-lead-rgb),0.14);
    --rev-sup-soft:     rgba(var(--rev-sup-rgb),0.14);
    --rev-context-soft: rgba(var(--rev-context-rgb),0.14);
    --rev-qc-soft:      rgba(var(--rev-qc-rgb),0.14);
    --kbk-sup-soft:     rgba(var(--kbk-sup-rgb),0.14);
    --kbk-lead-soft:    rgba(var(--kbk-lead-rgb),0.14);
    /* ── Los otros dos kickbacks (2026-08-26) ─────────────────────
       `--kbk-sup` / `--kbk-lead` nombran a QUIEN rebotó el shot. Estos dos son
       los estatus `kbk` y `edkbk` de Flow, que hasta hoy caían en un naranja
       genérico (o de plano en el azul de "sin mapear"):
         · --kbk-art = `kbk`   Kickback — el trabajo regresa AL ARTISTA.
         · --kbk-ed  = `edkbk` Editorial Kickback — lo rebota Editorial.
       Mismo contrato que arriba: sin sufijo = relleno con el hex EXACTO de
       FPT, `-ink` = texto/borde, `-on` = texto encima del relleno.
         kbk    #fcb800 -> claro #886300 (4.58:1) · oscuro el hex tal cual (6.39:1)
         edkbk  #ff0101 -> claro #c00000 (4.58:1) · oscuro #ff5858 (4.56:1)
       (Los mínimos son contra el peor de --card/--bg/--bg2/--card2 y contra el
       lavado al 14% del propio relleno, que es la misma vara que se usó para
       las tintas de revisión.) */
    --kbk-art:         #fcb800;  --kbk-art-rgb:     252,184,0;
    --kbk-ed:          #ff0101;  --kbk-ed-rgb:      255,1,1;
    --kbk-art-ink:     #fcb800;
    --kbk-ed-ink:      #ff5858;
    --kbk-art-on:      #000000;   /* 12.00:1 contra #fcb800 (blanco daría 1.75:1) */
    --kbk-ed-on:       #000000;   /*  5.26:1 contra #ff0101 (blanco daría 3.99:1) */
    --kbk-art-soft:    rgba(var(--kbk-art-rgb),0.14);
    --kbk-ed-soft:     rgba(var(--kbk-ed-rgb),0.14);
    /* ══ FIRMA DE EDITORIAL KICKBACK — NO LA COPIES A LOS OTROS ROJOS ══
       El #ff0101 de Editorial Kickback es indistinguible del rojo de ERROR que
       ya usan `stck` (Stuck), `tchf` (Tech Fail) y `cbb`: el contraste entre
       ellos es de 1.17:1 (vs --red oscuro) y 1.33:1 (vs --red claro), o sea
       ninguno. Sin diferenciarlos, "Editorial rebotó el shot" —que es una
       decisión de la edición, no una falla— se lee como "algo se rompió".
       En FPT ese estatus es ROJO Y NEGRO, y esa es justamente la diferencia:
       aquí `edkbk` es el ÚNICO estatus rojo que se pinta con relleno SÓLIDO,
       texto negro y ARO NEGRO. Stuck / Tech Fail / CBB se quedan con su tinte
       pálido y SIN aro a propósito.
       ⚠ Si alguien "empareja" el diseño poniéndole aro a los otros rojos, la
       señal desaparece y volvemos al problema. No lo hagas.
       El aro es negro en los DOS temas (no se sobrescribe en claro): es tinta
       de marca, no un color de superficie. */
    --kbk-ed-ring:     #000000;
    /* Radios extendidos */
    --radius-lg:   16px;   /* cards principales, modales */
    --radius-pill: 999px;  /* chips, badges totalmente redondeados */
    /* Escala tipográfica (referencia para unificar tamaños) */
    --fs-2xs: calc(9px * var(--fs-scale, 1)); --fs-xs: calc(10px * var(--fs-scale, 1)); --fs-sm: calc(11px * var(--fs-scale, 1)); --fs-base: calc(12px * var(--fs-scale, 1));
    --fs-md: calc(13px * var(--fs-scale, 1)); --fs-lg: calc(14px * var(--fs-scale, 1)); --fs-xl: calc(18px * var(--fs-scale, 1)); --fs-2xl: calc(22px * var(--fs-scale, 1));
    --fs-display: calc(30px * var(--fs-scale, 1));
    --fs-kpi: calc(22px * var(--fs-scale, 1));   /* cifra estándar de las barras de KPI (Calendario/Artistas/Proyectos/OT) */
    --filter-aside-w: 224px;   /* ancho único de los paneles laterales de filtros */
    --tracking-overline: 0.06em;
    /* Escala de spacing (4/8pt con pasos de apoyo) */
    --space-1: calc(4px * var(--sp-scale, 1));  --space-2: calc(8px * var(--sp-scale, 1));  --space-3: calc(12px * var(--sp-scale, 1)); --space-4: calc(16px * var(--sp-scale, 1));
    --space-5: calc(20px * var(--sp-scale, 1)); --space-6: calc(24px * var(--sp-scale, 1)); --space-7: calc(32px * var(--sp-scale, 1)); --space-8: calc(40px * var(--sp-scale, 1));
    /* Motion (easing estilo Apple) */
    --ease-out: cubic-bezier(.32,.72,0,1);
    --dur-micro: 120ms; --dur-fast: 150ms; --dur-base: 220ms; --dur-theme: 400ms;
    /* Escala de apilamiento (UI H7) — TODOS los z-index de overlay en un solo
       lugar. Los valores son los ACTUALES (tokens a valor exacto → cero cambio
       de apilamiento); esto centraliza la pila para razonar sobre ella, pero NO
       consolida capas: fusionar valores reordenaría overlays que quizá coexisten
       y exige validación en vivo overlay-por-overlay (se deja para eso). El
       ghost de arrastre queda sobre los toasts (arregla la colisión 9999==9999).
       Los z-index 1-8 intra-tabla (sticky de celdas) y los dev-* se quedan crudos. */
    --z-il2-catpop: 45; --z-il2-assignbar: 55; --z-menu: 60; --z-cal-filters: 80;
    --z-filter-pop: 80;   /* popovers de barras de filtro (mismo plano que --z-cal-filters) */
    --z-overlay-base: 100; --z-cal-panel: 200; --z-ftp-tip: 300; --z-apv-overlay: 320;
    --z-cal-datepicker: 400; --z-backdrop: 600; --z-panel: 601; --z-otdp: 900;
    --z-modal: 1000; --z-popover: 1100; --z-rd-pop: 1200; --z-tooltip-pop: 2100;
    --z-vp-datepicker: 3000; --z-impersonation: 5000; --z-cal-selbar: 9990;
    --z-toast: 9999; --z-drag: 10001; --z-banner: 99999;
    /* Stack monoespaciado único (B5/UI H9). Superset de las variantes que había
       sueltas (SF Mono / SFMono-Regular / Menlo / Consolas) → render idéntico. */
    --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;
  }
  /* ── Tema claro premium (default · sistema de diseño v3) ── */
  html[data-theme="light"] {
    color-scheme: light;
    --bg:    #faf9f7;   /* lienzo cálido, no blanco puro */
    --bg2:   #f4f2ef;   /* sidebar — beige sutil */
    --card:  #ffffff;
    --card2: #f5f4f2;
    --border:  rgba(0,0,0,0.08);
    --border2: rgba(0,0,0,0.14);
    --text:  #1d1d1f;
    --text2: #6e6e73;
    --text3: #737373;   /* A11y H3 (B5): antes #86868b (3.44:1 sobre bg = FALLA AA); ahora 4.51:1 bg / 4.74:1 card, sigue más claro que text2 */
    --accent: #0071e3;
    --accent-hover: #0077ed;
    --accent-soft:   rgba(0,113,227,0.10);
    --accent-border: rgba(0,113,227,0.22);
    /* Azul FIJO — no editable desde Editor UI (ver definición en :root). */
    --kpi-blue:     #0071e3;
    --kpi-blue-rgb: 0,113,227;
    /* A11y AA (auditoría 2026-07-19 P1): verde/rojo del tema claro subían
       3.13:1 / 4.46:1 sobre --card #fff. Estos valores dan 5.14:1 / 5.33:1
       (y ≥4.7:1 sobre #f5f5f7), mismo matiz, sin tocar el tema oscuro. */
    --green:  #1e7e34;
    --yellow: #b8860b;
    --orange: #e8820a;
    --red:    #c9302c;
    --purple: #9d4edd;
    --wash-1: rgba(0,0,0,0.035);
    --wash-2: rgba(0,0,0,0.055);
    --wash-3: rgba(0,0,0,0.08);
    --wash-4: rgba(0,0,0,0.13);
    --wash-5: rgba(0,0,0,0.28);
    --logo-bg: #ffffff;
    --shadow-card:  0 1px 3px rgba(0,0,0,0.06);
    --shadow-modal: 0 24px 64px rgba(0,0,0,0.16);
    --shadow-pop:   0 12px 32px rgba(0,0,0,0.12);
    --thumb-bg: rgba(0,0,0,0.05);
    /* ── Fundación ampliada (unificación v4) — tema claro ── */
    --accent-rgb: 0,113,227;
    --green-rgb:  30,126,52;
    --yellow-rgb: 184,134,11;
    --orange-rgb: 232,130,10;
    --red-rgb:    201,48,44;
    --purple-rgb: 157,78,221;
    --cyan-rgb:   10,159,212;
    --cyan:         #0a9fd4;
    --cyan-soft:    rgba(10,159,212,0.12);
    --cyan-border:  rgba(10,159,212,0.24);
    --green-soft:   rgba(41,167,69,0.11);
    --green-border: rgba(41,167,69,0.24);
    --yellow-soft:  rgba(184,134,11,0.12);
    --yellow-border:rgba(184,134,11,0.24);
    --orange-soft:  rgba(232,130,10,0.11);
    --orange-border:rgba(232,130,10,0.24);
    --red-soft:     rgba(224,53,43,0.10);
    --red-border:   rgba(224,53,43,0.22);
    --purple-soft:  rgba(157,78,221,0.10);
    --purple-border:rgba(157,78,221,0.22);
    /* ── Estatus de FPT: SOLO las tintas cambian con el tema ──────
       El relleno (--rev-*/--kbk-*) es el hex de FPT y se hereda de :root sin
       tocarlo. Estas tintas son el mismo matiz con la luminosidad bajada lo
       mínimo para llegar a >=4.55:1 sobre #ffffff / #faf9f7 / #f5f4f2 y sobre
       su propio lavado al 14%. Context Review y QC ya cumplían en claro con su
       hex real, así que se dejan idénticos al de FPT (ver tabla en :root). */
    --rev-artist-ink:  #207b36;
    --rev-lead-ink:    #656565;
    --rev-sup-ink:     #007b00;
    --rev-context-ink: #835802;
    --rev-qc-ink:      #6e00f9;
    --kbk-sup-ink:     #707200;
    --kbk-lead-ink:    #636363;
    /* `kbk` y `edkbk`: el relleno y el aro negro se heredan de :root; solo
       bajan las tintas. Los valores que se calcularon primero (#986f00 y
       #ee0000) pasaban 4.5:1 contra blanco puro pero se caían a 3.81:1 y
       3.20:1 sobre --card2 y sobre su propio lavado — el fondo real de las
       pastillas —, así que se bajaron un escalón más. */
    --kbk-art-ink:     #886300;
    --kbk-ed-ink:      #c00000;
    /* radios/escala/spacing/motion se heredan de :root (no cambian por tema) */
  }

  * { box-sizing: border-box; margin: 0; padding: 0; }

  /* ══ TOKENS DEL EDITOR UI (Fase A) ══
     Los define/sobrescribe modules/ui-theme.js según el tema activo.
     --fs-scale: escala tipográfica global (todos los font-size están
                 envueltos en calc() por tools/tokenize-css.mjs).
     --btn-scale: escala de botones (vía zoom, escala texto+padding+iconos).
     --font-main: familia tipográfica global. */
  :root {
    --fs-scale: 1;
    --btn-scale: 1;
    --font-main: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", sans-serif;
  }

  body {
    font-family: var(--font-main);
    background: var(--bg);
    color: var(--text);
    height: 100vh;
    overflow: hidden;
    font-size: var(--fs-md);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  /* ── Views ── */
  .view { display: none; width: 100%; height: 100vh; }
  .view.active { display: flex; }

  /* ── LOGIN ── */
  #view-login, #view-app-login {
    align-items: center; justify-content: center; flex-direction: column;
    background: var(--bg);
  }
  #view-login { gap: calc(28px * var(--sp-scale, 1)); }

  /* ── App login card (todo en un solo card) ── */
  .app-login-card {
    width: 420px; max-width: calc(100vw - 32px);
    background: var(--card); border: 1px solid var(--border2);
    border-radius: var(--radius-lg); padding: calc(36px * var(--sp-scale, 1)) var(--space-7);
    box-shadow: var(--shadow-modal);
  }
  .app-login-header {
    display: flex; flex-direction: column; align-items: center;
    gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 30px; text-align: center;
  }
  .app-login-header h1 { font-size: calc(22px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -0.5px; }
  .app-login-header p  { font-size: var(--fs-md); color: var(--text2); }
  .app-input-wrap {
    display: flex; align-items: center; gap: 0;
    background: var(--wash-2); border: 1px solid var(--border2);
    border-radius: var(--radius-sm); transition: border-color var(--dur-fast);
  }
  .app-input-wrap:focus-within { border-color: var(--accent); }
  .app-input-icon {
    padding: 0 calc(10px * var(--sp-scale, 1)) 0 var(--space-3); color: var(--text3); display: flex;
    align-items: center; flex-shrink: 0; pointer-events: none;
  }
  .app-input-wrap input {
    flex: 1; background: none; border: none; outline: none;
    color: var(--text); font-size: var(--fs-md); padding: calc(10px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)) 0;
    font-family: inherit;
  }
  .app-input-wrap input::placeholder { color: var(--text3); }
  .app-eye-btn {
    padding: 0 calc(11px * var(--sp-scale, 1)); background: none; border: none; cursor: pointer;
    color: var(--text3); display: flex; align-items: center;
    transition: color var(--dur-micro);
  }
  .app-eye-btn:hover { color: var(--text2); }
  .app-server-banner {
    display: flex; align-items: flex-start; gap: var(--space-2);
    background: rgba(var(--yellow-rgb),0.07); border: 1px solid rgba(var(--yellow-rgb),0.2);
    border-radius: var(--radius-sm); padding: calc(10px * var(--sp-scale, 1)) var(--space-3);
    font-size: var(--fs-base); color: var(--yellow); line-height: 1.55;
    margin-bottom: 18px;
  }
  .app-server-banner code {
    display: block; margin-top: 4px; background: rgba(0,0,0,0.3);
    border-radius: 5px; padding: calc(5px * var(--sp-scale, 1)) var(--space-2);
    font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--text);
  }
  .login-logo { display: flex; flex-direction: column; align-items: center; gap: var(--space-4); }
  /* Ícono de claqueta en pantalla de login */
  .login-app-icon {
    width: 68px; height: 68px; border-radius: 17px;
    background: linear-gradient(145deg, rgba(var(--accent-rgb),0.18) 0%, rgba(var(--accent-rgb),0.08) 100%);
    border: 1px solid rgba(var(--accent-rgb),0.22);
    display: flex; align-items: center; justify-content: center; color: var(--accent);
    box-shadow: 0 10px 36px rgba(var(--accent-rgb),0.20);
  }
  /* Fallback heredado — mantener por compatibilidad */
  .login-icon-fallback {
    width: 62px; height: 62px; border-radius: 15px;
    background: var(--accent);
    display: flex; align-items: center; justify-content: center; color: #fff;
    box-shadow: 0 10px 36px rgba(var(--accent-rgb),0.28);
  }
  .login-logo h1 { font-size: calc(22px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -0.6px; }
  .login-logo p  { color: var(--text2); font-size: var(--fs-md); }
  .login-card {
    width: 390px; max-width: calc(100vw - 32px);
    background: var(--card);
    border: 1px solid var(--border2);
    border-radius: 14px;
    padding: calc(26px * var(--sp-scale, 1));
    box-shadow: var(--shadow-modal);
  }

  /* ── Buttons ── */
  .btn {
    zoom: var(--btn-scale, 1);   /* escala de botones del Editor UI (texto+padding+iconos) */
    display: inline-flex; align-items: center; justify-content: center; gap: calc(6px * var(--sp-scale, 1));
    padding: var(--space-2) var(--space-4); border-radius: var(--btn-radius, var(--radius-sm));
    font-size: var(--fs-md); font-weight: 500; cursor: pointer; border: none;
    transition: background var(--dur-micro), opacity var(--dur-micro);
    text-decoration: none; letter-spacing: -0.1px;
    font-family: inherit;
  }
  /* .btn-primary es el CTA de acento. Su ancho es el NATURAL del botón.
     ────────────────────────────────────────────────────────────────
     Hasta 2026-07-24 esta clase traía `width: 100%` heredado del diseño
     del login (donde el botón sí ocupa toda la columna). Eso convertía en
     barra full-width a TODO botón primario que no viviera en una columna
     — el Save del modal FX, el Publicar de Aprobados, etc. — y obligó a
     tres parches dispersos con `width: auto` (Configuración, header ADM,
     Monitoreo). El full-width ahora es EXPLÍCITO con .btn-block: quien lo
     quiera, lo pide. Regla §6: si necesitas ancho completo, usa .btn-block;
     no redefinas .btn-primary dentro del scope de una página. */
  .btn-primary {
    background: var(--accent); color: #fff;
    padding: calc(11px * var(--sp-scale, 1)); font-size: var(--fs-lg); font-weight: 600;
  }
  /* Ancho completo explícito (login, setup de credenciales y cualquier CTA
     que ocupe su propia fila). Sirve para cualquier variante de .btn. */
  .btn-block { width: 100%; }
  .btn-primary:hover  { background: var(--accent-hover); }
  .btn-primary:disabled { opacity: 0.4; cursor: not-allowed; }
  .btn-secondary {
    background: var(--wash-3); color: var(--text);
    border: 1px solid var(--border);
  }
  .btn-secondary:hover { background: var(--wash-4); }
  .btn-ghost {
    background: transparent; color: var(--text2);
    border: 1px solid var(--border);
  }
  .btn-ghost:hover { background: var(--wash-2); color: var(--text); }
  .btn-danger {
    background: rgba(var(--red-rgb),0.1); color: var(--red);
    border: 1px solid rgba(var(--red-rgb),0.18);
  }
  .btn-danger:hover { background: rgba(var(--red-rgb),0.18); }
  /* var(--btn-radius, …): las variantes también obedecen a «Esquinas de
     botones» del Editor UI (antes pisaban el token y el control no hacía nada
     en los .btn-sm, que son la mayoría — bug reportado 2026-07-05). */
  .btn-sm   { padding: calc(5px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1)); font-size: var(--fs-base); border-radius: var(--btn-radius, var(--radius-xs)); }
  .btn-icon { width: 30px; height: 30px; padding: 0; border-radius: var(--btn-radius, var(--radius-xs)); }
  .split-menu-trigger .caret { transition: transform var(--dur-fast); }
  .split-menu.open .split-menu-trigger .caret { transform: rotate(180deg); }
  .split-menu.open .split-menu-panel { display: flex; }

  /* ── Dashboard: botón de refresco de las tarjetas por show ── */
  .dash-refresh-btn { display:inline-flex; align-items:center; justify-content:center; width:26px; height:26px; padding:0; border:none; border-radius:50%; background:var(--wash-2); color:var(--text); cursor:pointer; transition:background var(--dur-micro), color var(--dur-micro); }
  .dash-refresh-btn:hover { background:var(--wash-3); }
  /* ── Dashboard: fila con barra segmentada por SHOW (2026-08-24) ──
     Componente compartido por «Shots para revisión» y «KBKs Internos»
     (lib/dash-barra-ui.js). Paridad con la app iOS: nombre del show + caption
     + chevron arriba, y debajo la barra a todo el ancho con un segmento por
     nivel. La fila entera es un <button> (regla de accesibilidad). */
  .dashbar-row { display: block; width: 100%; text-align: left; font-family: inherit; color: inherit;
    background: none; border: none; cursor: pointer; border-radius: var(--radius-xs);
    padding: calc(6px * var(--sp-scale, 1)) var(--space-1); transition: background var(--dur-micro); }
  .dashbar-row:hover { background: var(--wash-1); }
  .dashbar-head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: 5px; }
  .dashbar-title { flex: 1; min-width: 0; font-size: var(--fs-md); font-weight: 600; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dashbar-caption { flex: none; font-size: var(--fs-sm); color: var(--text3); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .dashbar-chev { flex: none; display: flex; color: var(--text3); transition: transform var(--dur-fast), color var(--dur-micro); }
  .dashbar-row:hover .dashbar-chev { color: var(--text2); transform: translateX(2px); }
  .dashbar-track { display: block; height: 10px; border-radius: var(--radius-pill); background: var(--card2); overflow: hidden; }
  .dashbar-fill { display: flex; height: 100%; border-radius: var(--radius-pill); overflow: hidden;
    transition: width var(--dur-base) var(--ease-out); }
  /* El segmento conserva el relleno EXACTO de FPT y se le pone un aro interior
     del MISMO tono (la tinta --*-ink que pasa el componente en `--seg-ink`).
     Sin el aro, en tema claro un segmento de VFX Sup KBK (#f9fe02) contra la
     pista --card2 daba 1.01:1: la barra se veía vacía. El aro no altera el
     color que el usuario reconoce de FPT, solo dibuja su silueta. */
  .dashbar-seg { display: block; height: 100%; box-shadow: inset 0 0 0 1px var(--seg-ink, transparent); }
  /* (2026-08-27, fix del aro) El aro es un box-shadow INSET y sigue el
     border-radius DEL SEGMENTO, no el del contenedor: con segmentos
     rectangulares, el overflow:hidden de .dashbar-fill rebanaba el aro en
     diagonal en las puntas redondeadas y quedaba un borde dentado/pixeleado —
     la barra dejaba de verse como cápsula. Dándole al primer y último
     segmento sus propias puntas de píldora, el aro dibuja la silueta real y
     el recorte del contenedor ya no toca ningún trazo (queda de seguridad).
     Los segmentos de en medio siguen rectos: sus uniones son a hueso. */
  .dashbar-seg:first-child { border-top-left-radius: var(--radius-pill); border-bottom-left-radius: var(--radius-pill); }
  .dashbar-seg:last-child { border-top-right-radius: var(--radius-pill); border-bottom-right-radius: var(--radius-pill); }
  /* Leyenda de puntos: solo los niveles con datos en revisión, los dos fijos en KBKs */
  .dashbar-legend { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-4); margin-top: var(--space-2); }
  .dashbar-legend-item { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); font-size: var(--fs-xs); color: var(--text3); }
  /* Mismo criterio que .dashbar-seg: relleno exacto de FPT + aro del mismo
     tono, porque un punto de leyenda amarillo #f9fe02 sobre tarjeta blanca
     es literalmente invisible y la leyenda es lo que da el significado. */
  .dashbar-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; display: inline-block;
    box-shadow: inset 0 0 0 1px var(--seg-ink, transparent); }
  .dashbar-empty { font-size: var(--fs-base); color: var(--text3); padding: calc(6px * var(--sp-scale, 1)) 0; }
  .dashbar-note { font-size: var(--fs-xs); color: var(--yellow); margin-top: 6px; }
  /* Skeleton de una fila (equivalente del SkeletonChartRow de iOS) */
  .dashbar-skel { padding: calc(6px * var(--sp-scale, 1)) var(--space-1); }
  .dashbar-skel-head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: 6px; }
  .dashbar-skel-t { flex: none; width: 120px; height: 13px; display: block; }
  .dashbar-skel-c { flex: none; width: 28px; height: 11px; display: block; }
  .dashbar-skel-bar { height: 10px; border-radius: var(--radius-pill); display: block; }
  /* Variante SIN barra: «Playlist para revisión - AM/PM». Los grupos son por
     revisor y no tienen color de pipeline, así que la fila lleva el desglose
     en texto (igual que InternalReviewRow en iOS). Misma fila tocable. */
  .dashbar-row--texto .dashbar-head { margin-bottom: 2px; }
  .dashbar-sub { display: block; font-size: var(--fs-sm); color: var(--text2); }
  .dashbar-flag { display: block; font-size: var(--fs-xs); color: var(--text3); margin-top: 2px; }

  /* ── Detalle de un show de revisión interna (modal #pli-modal) ── */
  .pli-det-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3);
    padding: calc(6px * var(--sp-scale, 1)) var(--space-1); }
  .pli-det-row .pli-det-sub { flex: 1 1 100%; font-size: var(--fs-sm); color: var(--text3); }
  .pli-det-n { margin-left: auto; font-size: var(--fs-base); color: var(--text2); font-variant-numeric: tabular-nums; }
  .pli-det-foot { font-size: var(--fs-xs); color: var(--text3); padding: var(--space-2) var(--space-1); }

  /* ── Fields ── */
  .field { display: flex; flex-direction: column; gap: calc(5px * var(--sp-scale, 1)); margin-bottom: 14px; }
  .field label { font-size: var(--fs-base); font-weight: 500; color: var(--text2); }
  .field input, .field select, .field textarea {
    background: var(--wash-2);
    border: 1px solid var(--border2);
    border-radius: var(--radius-sm);
    padding: var(--space-2) calc(11px * var(--sp-scale, 1)); color: var(--text); font-size: var(--fs-md);
    outline: none; transition: border-color var(--dur-fast); width: 100%;
    font-family: inherit;
  }
  .field input:focus, .field select:focus, .field textarea:focus { border-color: var(--accent); }
  /* Revisión Sr. UX/UI 2026-07-29: .field es flex-column y sus hijos se
     ESTIRAN por default — los seg-control y botones sueltos salían de borde
     a borde («botones enormes» reportados por el productor: Idioma, Tema,
     Get Thumb). Los inputs no cambian: llevan width:100% explícito arriba.
     .btn-block queda fuera: su razón de ser es ocupar el ancho completo. */
  .field > .seg-control, .field > .btn:not(.btn-block) { align-self: flex-start; }
  .field textarea { resize: vertical; line-height: 1.5; }
  /* Todo el campo de fecha es clickeable, no solo el icono */
  .field input[type="date"] { cursor: pointer; }
  .field .help { font-size: var(--fs-sm); color: var(--text3); line-height: 1.4; }
  .field .input-row { display: flex; gap: calc(6px * var(--sp-scale, 1)); }
  .field .input-row input { flex: 1; }
  /* Los checkbox/radio NO deben heredar el estilo de input de texto (.field input) */
  .field input[type="checkbox"], .field input[type="radio"] {
    width: auto; min-width: 0; height: auto; padding: 0; margin: 0;
    border: 0; background: none; border-radius: 0; box-shadow: none;
    flex: 0 0 auto; accent-color: var(--accent);
    -webkit-appearance: auto; appearance: auto;
  }
  /* Fila de casilla + etiqueta (Configuración) */
  .settings-check { display: flex; gap: calc(9px * var(--sp-scale, 1)); align-items: flex-start; cursor: pointer;
    font-size: calc(12.5px * var(--fs-scale, 1)); font-weight: 400; color: var(--text2); line-height: 1.45;
    text-transform: none; letter-spacing: 0; }
  .settings-check input[type="checkbox"] { width: 16px; height: 16px; margin-top: 1px; }

  /* ── Site info row ── */
  .site-info {
    background: var(--wash-2); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: calc(10px * var(--sp-scale, 1)) var(--space-3);
    display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 18px;
  }
  .site-info .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green); flex-shrink: 0; }
  .site-info .info { flex: 1; min-width: 0; }
  .site-info .info small { color: var(--text2); font-size: var(--fs-sm); display: block; }
  .site-info .info span  { font-size: var(--fs-md); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
  .site-info .edit-btn {
    background: var(--wash-2); border: none; color: var(--text2); cursor: pointer;
    border-radius: 50%; width: 26px; height: 26px;
    display: flex; align-items: center; justify-content: center; transition: background var(--dur-micro);
  }
  .site-info .edit-btn:hover { background: var(--wash-4); color: var(--text); }

  /* ── Alerts ── */
  .alert {
    border-radius: var(--radius-sm); padding: calc(9px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1)); font-size: var(--fs-base);
    display: flex; align-items: flex-start; gap: calc(7px * var(--sp-scale, 1));
    margin-bottom: 14px; line-height: 1.5;
  }
  .alert-error   { background: rgba(var(--red-rgb),0.09);  color: var(--red); border: 1px solid rgba(var(--red-rgb),0.18); }
  .alert-success { background: rgba(var(--green-rgb),0.09);  color: var(--green); border: 1px solid rgba(var(--green-rgb),0.18); }
  .alert-info    { background: rgba(var(--accent-rgb),0.08); color: var(--accent); border: 1px solid rgba(var(--accent-rgb),0.18); }

  /* ── Modal ── */
  .modal-overlay {
    position: fixed; inset: 0; background: rgba(0,0,0,0.52);
    display: none; align-items: center; justify-content: center;
    z-index: var(--z-overlay-base); backdrop-filter: blur(10px);
  }
  .modal-overlay.open { display: flex; }
  .modal {
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--radius-lg);
    width: 460px; max-width: calc(100vw - 32px); max-height: 90vh; overflow: hidden;
    display: flex; flex-direction: column;
    box-shadow: var(--shadow-modal);
  }
  /* Tamaños estándar de modal (reemplazan anchos inline arbitrarios). */
  .modal.modal--sm { width: 420px; }
  .modal.modal--md { width: 560px; }
  .modal.modal--lg { width: 640px; }
  /* xl: tablas anchas de varias columnas (ej. Shots Activos del dashboard). */
  .modal.modal--xl { width: 780px; }
  .modal.modal--tall { max-height: 80vh; }
  /* ── Command palette (⌘K) — overlay centrado-arriba sobre .modal-overlay ── */
  .cmdk-overlay { align-items: flex-start; padding-top: calc(90px * var(--sp-scale, 1)); z-index: var(--z-modal); }
  .cmdk-modal { width: 560px; max-width: calc(100vw - 32px); overflow: hidden; }
  .cmdk-inputwrap { display: flex; align-items: center; gap: var(--space-2);
    padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); }
  .cmdk-input { flex: 1; min-width: 0; background: transparent; border: none; outline: none;
    color: var(--text); font-size: var(--fs-lg); font-family: inherit; }
  .cmdk-input::placeholder { color: var(--text3); }
  .cmdk-close { background: none; border: none; color: var(--text3); cursor: pointer;
    font-size: var(--fs-xl); line-height: 1; padding: 0 var(--space-1); }
  .cmdk-close:hover { color: var(--text); }
  .cmdk-list { max-height: calc(360px * var(--sp-scale, 1)); overflow-y: auto; padding: var(--space-2); }
  .cmdk-group { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: .04em;
    color: var(--text3); padding: var(--space-2) var(--space-2) var(--space-1); }
  .cmdk-item { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
    padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); cursor: pointer;
    color: var(--text); font-size: var(--fs-md); }
  .cmdk-item .cmdk-tag { font-size: var(--fs-2xs); color: var(--text3); flex-shrink: 0; }
  .cmdk-item.sel { background: var(--accent-soft); color: var(--accent); }
  .cmdk-item.sel .cmdk-tag { color: var(--accent); }
  .cmdk-empty { padding: var(--space-5); text-align: center; color: var(--text3); font-size: var(--fs-md); }
  .cmdk-foot { display: flex; justify-content: flex-end; padding: var(--space-2) var(--space-4);
    border-top: 1px solid var(--border); color: var(--text3); font-size: var(--fs-2xs); }
  /* ── Modal de Configuración: dos paneles (sidebar de categorías + detalle) ── */
  .modal.modal--settings { width: 860px; max-width: min(860px, calc(100vw - 24px)); height: min(80vh, 640px); }
  .settings-topbar { display: flex; align-items: center; justify-content: space-between; flex-shrink: 0;
    padding: calc(15px * var(--sp-scale, 1)) var(--space-5); border-bottom: 1px solid var(--border); }
  .settings-topbar-title { font-size: calc(19px * var(--fs-scale, 1)); font-weight: 700; margin: 0; letter-spacing: -.3px; color: var(--text); }
  .settings-shell { display: flex; min-height: 0; flex: 1; }
  .settings-side { width: 224px; flex-shrink: 0; background: var(--bg2); border-right: 1px solid var(--border);
    padding: var(--space-3) calc(10px * var(--sp-scale, 1)); overflow-y: auto; }
  .settings-cats { display: flex; flex-direction: column; gap: calc(2px * var(--sp-scale, 1)); }
  .settings-cat { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); width: 100%; text-align: left; border: 0;
    background: transparent; color: var(--text2); font-size: var(--fs-md); font-weight: 500; line-height: 1.3; padding: calc(9px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1));
    border-radius: var(--radius-sm); cursor: pointer; font-family: inherit; }
  .settings-cat:hover { background: var(--wash-2); color: var(--text); }
  .settings-cat.active { background: var(--accent-soft); color: var(--text); font-weight: 600; }
  .settings-cat.active svg { color: var(--accent); }
  .settings-cat svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--text3); }
  .settings-cat-badge { margin-left: auto; font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase;
    letter-spacing: .03em; color: var(--text3); background: var(--wash-2); padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: var(--radius-pill); }
  .settings-main { flex: 1; min-width: 0; overflow-y: auto; padding: var(--space-6) calc(30px * var(--sp-scale, 1)) calc(26px * var(--sp-scale, 1)); }
  .settings-pane { display: none; }
  .settings-pane.active { display: block; }
  .settings-pane h3 { font-size: calc(19px * var(--fs-scale, 1)); font-weight: 700; margin: 0 0 4px; letter-spacing: -.25px; }
  .settings-pane-sub { font-size: calc(12.5px * var(--fs-scale, 1)); color: var(--text3); margin: 0 0 22px; line-height: 1.5; }
  /* Tipografía tipo "Preferencias": subtítulo de ajuste en negrita + descripción gris */
  .settings-pane .field { margin-bottom: 22px; }
  .settings-pane .field > label { font-size: var(--fs-md); font-weight: 600; color: var(--text); }
  .settings-pane .field .help { font-size: var(--fs-base); color: var(--text3); }
  /* Tamaño de los botones de acción de Configuración. El `width: auto` que
     esta regla traía se RETIRÓ el 2026-07-24: ya no hace falta porque
     .btn-primary dejó de ser full-width (ver la nota junto a .btn-primary).
     Se conserva solo el ajuste de padding/tipografía. */
  /* (Los dos parches de tamaño de .settings-main .btn-primary se retiraron en
     la limpieza 07-29: todos los primarios del modal ya llevan .btn-sm.) */
  /* ── Configuración · filas "etiqueta lateral + campo" (correo Comfy) ──
     Sustituye los estilos inline del pane; los campos heredan el look
     estándar de .field input/textarea (wash-2 + border2 + radius-sm). */
  .settings-mailfields { display: flex; flex-direction: column; gap: var(--space-2); }
  .settings-mailfields .mailrow { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
  .settings-mailfields .mailrow-top { align-items: flex-start; }
  .settings-mailfields .mail-lbl {
    width: 52px; flex-shrink: 0;
    font-size: var(--fs-sm); color: var(--text3);
  }
  .settings-mailfields .mailrow-top .mail-lbl { padding-top: var(--space-2); }
  /* Skin en la PROPIA clase (revisión Sr. UX/UI 07-29): en el modal lo daba el
     ancestro .field, pero en Herramientas › Avisos no hay .field y el
     formulario salía con inputs nativos del navegador. */
  .settings-mailfields .mailrow input:not([type="checkbox"]):not([type="file"]),
  .settings-mailfields .mailrow textarea {
    flex: 1; min-width: 0; width: auto;
    background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-sm);
    padding: var(--space-2) calc(11px * var(--sp-scale, 1)); color: var(--text); font-size: var(--fs-md);
    outline: none; transition: border-color var(--dur-fast); font-family: inherit;
  }
  .settings-mailfields .mailrow input:focus, .settings-mailfields .mailrow textarea:focus { border-color: var(--accent); }
  .settings-mailfields .mailrow textarea { resize: vertical; line-height: 1.5; }
  .settings-mailfields .mailrow input[type="number"] { flex: 0 0 auto; width: 110px; }
  .settings-mailfields .mail-note {
    font-size: var(--fs-sm); color: var(--text3);
    line-height: 1.45; margin: -2px 0 0 60px; /* 60 = ancho label + gap */
  }
  .settings-mailfields .mail-note b { color: var(--text2); }
  /* ── Limpieza 2026-07-29 (auditoría Settings): fila de control canónica del
     modal — reemplaza los display:flex inline repetidos en cada pane. ── */
  .cfg-row { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
  .cfg-row .help { margin: 0; }
  .cfg-row .btn { flex-shrink: 0; }
  .cfg-row input[type="number"] { width: 90px; }
  .cfg-row--nowrap { flex-wrap: nowrap; }
  .cfg-row--nowrap input[type="text"] { flex: 1; min-width: 0; }
  .cfg-unit { font-size: var(--fs-base); color: var(--text2); }
  .cfg-info { font-size: var(--fs-sm); color: var(--text3); }
  .cfg-sub {
    font-size: var(--fs-xs); font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
    color: var(--text3); margin-bottom: calc(6px * var(--sp-scale, 1));
  }
  .settings-pane code { font-size: var(--fs-base); color: var(--text2); }
  /* Avisos (Configuración › Integraciones, 2026-07-24): resultado por medio
     del último envío. Va aquí y no inline para respetar el trinquete de
     ds-lint — el font-size crudo en JS solo puede bajar. */
  .noti-res-item { font-size: var(--fs-base); margin-top: calc(6px * var(--sp-scale, 1)); }
  .noti-res-ok  { color: var(--green); }
  .noti-res-err { color: var(--red); }
  /* ── Integraciones en cards (rediseño 2026-07-29): una card por servicio
     con semáforo de estado. Derivada de .report-card pero SIN affordance de
     click (la card no navega; sus controles sí). ── */
  .integ-grid { display: flex; flex-direction: column; gap: var(--space-3); }
  .integ-card {
    background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm);
    padding: calc(14px * var(--sp-scale, 1)) var(--space-4);
    display: flex; flex-direction: column; gap: calc(10px * var(--sp-scale, 1));
  }
  .integ-head { display: flex; align-items: center; gap: calc(9px * var(--sp-scale, 1)); }
  .integ-ico {
    width: 30px; height: 30px; border-radius: 7px; flex-shrink: 0; color: var(--text2);
    background: var(--wash-2); display: flex; align-items: center; justify-content: center;
  }
  .integ-title { font-size: calc(13.5px * var(--fs-scale, 1)); font-weight: 650; letter-spacing: -0.2px; flex: 1; }
  .integ-badge {
    display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1));
    font-size: var(--fs-sm); font-weight: 600; color: var(--text2);
    padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1));
    border: 1px solid var(--border); border-radius: 20px; background: var(--wash-2);
  }
  .integ-badge .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text3); flex-shrink: 0; }
  .integ-badge--ok .dot  { background: var(--green); }
  .integ-badge--err .dot { background: var(--red); }
  .integ-badge--off .dot { background: var(--text3); }
  .integ-lines { font-size: var(--fs-base); color: var(--text2); line-height: 1.55; }
  .integ-foot { display: flex; align-items: center; gap: var(--space-2); }
  /* Skin propio: las cards viven fuera de .field, así que sus inputs salían
     con el look nativo del navegador (revisión Sr. UX/UI 07-29). */
  .integ-foot input {
    flex: 1; min-width: 0;
    background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-sm);
    padding: var(--space-2) calc(11px * var(--sp-scale, 1)); color: var(--text); font-size: var(--fs-md);
    outline: none; transition: border-color var(--dur-fast); font-family: inherit;
  }
  .integ-foot input:focus { border-color: var(--accent); }
  .integ-foot .btn { flex-shrink: 0; }
  .integ-note, .integ-hint { font-size: var(--fs-sm); color: var(--text3); line-height: 1.4; }
  .integ-hint { margin: calc(10px * var(--sp-scale, 1)) 0 0; }
  #integ-slack-cfg:not(:empty) { border-top: 1px solid var(--border); padding-top: calc(10px * var(--sp-scale, 1)); }
  /* Avisos del Tablero (2026-07-29): filas de checkbox con ayuda, subtítulos
     de sección y etiquetas más anchas (nombres de tablero/usuario no caben en
     los 52px del correo). */
  #tav-root .mail-lbl { width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #tav-root .mail-note { margin-left: 0; }
  .tav-row { display: flex; gap: var(--space-2); align-items: flex-start; }
  .tav-row input[type="checkbox"] { margin-top: calc(3px * var(--sp-scale, 1)); }
  .tav-row label { font-size: var(--fs-base); color: var(--text); }
  .tav-help { display: block; font-size: var(--fs-sm); color: var(--text3); line-height: 1.4; }
  .tav-sub {
    font-size: var(--fs-xs); font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
    color: var(--text3); margin-top: var(--space-2);
  }
  /* iPad retrato / ventana comprimida: los dos paneles se apilan; categorías como chips que envuelven */
  @media (max-width: 720px) {
    .modal.modal--settings { width: 100%; max-width: calc(100vw - 20px); height: min(88vh, 720px); }
    .settings-topbar { padding: calc(13px * var(--sp-scale, 1)) var(--space-4); }
    .settings-topbar-title { font-size: calc(17px * var(--fs-scale, 1)); }
    .settings-shell { flex-direction: column; }
    .settings-side { width: auto; border-right: 0; border-bottom: 1px solid var(--border); padding: calc(9px * var(--sp-scale, 1)); overflow-y: visible; flex-shrink: 0; }
    .settings-side-title { display: none; }
    .settings-cats { flex-direction: row; flex-wrap: wrap; gap: calc(6px * var(--sp-scale, 1)); }
    .settings-cat { width: auto; flex: 0 0 auto; font-size: calc(12.5px * var(--fs-scale, 1)); padding: calc(7px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1));
      background: var(--wash-1); border: 1px solid var(--border); }
    .settings-cat svg { display: none; }
    .settings-cat.active { border-color: var(--accent-border); }
    .settings-cat-badge { margin-left: 6px; }
    .settings-main { padding: var(--space-5) calc(18px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1)); }
    .settings-pane h3 { font-size: calc(17px * var(--fs-scale, 1)); }
  }
  /* iPhone: aún más compacto */
  @media (max-width: 430px) {
    .settings-main { padding: calc(18px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)) var(--space-4); }
    .settings-cat { font-size: var(--fs-base); padding: calc(6px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); }
    .settings-pane-sub { margin-bottom: 16px; }
  }
  /* Alias (2026-07-27): 8 modales del HTML usan .modal-head y 14 usan
     .modal-foot — nombres que NUNCA tuvieron regla. Sin esto el header no es
     flex (la ✕ cae debajo del título) y el pie no tiene padding ni borde (los
     botones se salen de la tarjeta). Se unifican aquí en vez de renombrar 22
     nodos del HTML. */
  .modal-header,
  .modal-head {
    padding: calc(17px * var(--sp-scale, 1)) calc(21px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border);
    display: flex; align-items: center; justify-content: space-between;
  }
  .modal-header h3, .modal-head h3 { font-size: var(--fs-lg); font-weight: 600; }
  /* Botón de cerrar GLOBAL — un solo look en TODA la app (modales, paneles,
     Configuración, publicar shots, etc.), sin importar el header contenedor. */
  .close-btn {
    background: var(--wash-3); border: none; color: var(--text2); cursor: pointer;
    width: 24px; height: 24px; border-radius: 50%; padding: 0;
    position: relative; font-size: 0;   /* la X se dibuja con pseudo-elementos (centrado exacto) */
    display: inline-flex; align-items: center; justify-content: center;
    transition: background var(--dur-micro);
    flex-shrink: 0;   /* headers con varios elementos (p.ej. Shots aprobados) no lo deforman */
  }
  /* X perfectamente centrada (dos líneas cruzadas) */
  .close-btn::before, .close-btn::after {
    content: ""; position: absolute; top: 50%; left: 50%;
    width: 11px; height: 1.6px; background: currentColor; border-radius: 2px;
  }
  .close-btn::before { transform: translate(-50%, -50%) rotate(45deg); }
  .close-btn::after  { transform: translate(-50%, -50%) rotate(-45deg); }
  /* Si el botón ya tiene icono Lucide (inyectado por icons.js), la X de
     pseudo-elementos se oculta: el icono es editable desde Personalización. */
  .close-btn:has(svg.lucide)::before, .close-btn:has(svg.lucide)::after { display: none; }
  .close-btn svg.lucide { display: block; }
  .close-btn:hover { background: var(--wash-4); color: var(--text); }
  .modal-body { padding: calc(21px * var(--sp-scale, 1)); overflow-y: auto; flex: 1; }
  .modal-footer,
  .modal-foot {
    padding: calc(13px * var(--sp-scale, 1)) calc(21px * var(--sp-scale, 1)); border-top: 1px solid var(--border);
    display: flex; justify-content: flex-end; gap: var(--space-2);
  }

  /* ── Sidebar ── */
  .sidebar {
    width: var(--sidebar-w); height: 100vh; background: var(--bg2);
    border-right: 1px solid var(--border);
    display: flex; flex-direction: column; flex-shrink: 0;
    transition: width var(--dur-base) cubic-bezier(.32,.72,0,1);
  }
  .sidebar-header {
    padding: calc(15px * var(--sp-scale, 1)) var(--space-3) var(--space-3);
    display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 4px;
  }
  .sidebar-brand { flex: 1; min-width: 0; }
  .sidebar-logo {
    flex-shrink: 0;
    display: flex; align-items: center; justify-content: flex-start;
  }
  /* Ícono de claqueta en sidebar */
  .sidebar-logo svg {
    display: block; color: var(--accent);
    background: var(--logo-bg);
    border-radius: 7px;
    padding: var(--space-1) var(--space-2);
  }
  /* Fallback si logo.png no carga */
  .sidebar-logo-fallback {
    width: 27px; height: 27px; border-radius: 7px; background: var(--accent);
    display: flex; align-items: center; justify-content: center;
    color: #fff; flex-shrink: 0;
  }
  .sidebar-header h2    { font-size: var(--fs-lg); font-weight: 650; letter-spacing: -0.2px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sidebar-header small { font-size: calc(10.5px * var(--fs-scale, 1)); color: var(--text2); display: block; margin-top: 1px; letter-spacing: .02em; }
  .sidebar-nav { padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); flex: 1; overflow-y: auto; }
  .nav-section { margin-bottom: 20px; }
  .nav-label {
    font-size: var(--fs-xs); font-weight: 600; color: var(--text3);
    text-transform: uppercase; letter-spacing: 0.07em;
    padding: 0 var(--space-2); margin-bottom: 3px;
  }
  .nav-item {
    position: relative;
    display: flex; align-items: center; gap: var(--space-2);
    padding: calc(7px * var(--sp-scale, 1)) var(--space-2); border-radius: var(--radius-sm);
    cursor: pointer; color: var(--text2); font-size: var(--fs-md); font-weight: 500;
    transition: background var(--dur-fast), color var(--dur-fast);
    margin-bottom: 1px; user-select: none;
  }
  .nav-item:hover  { background: var(--wash-2); color: var(--text); }
  .nav-item.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
  /* Indicador de barra lateral en la pestaña activa (estética v3) */
  .nav-item.active::before {
    content: ''; position: absolute; left: -2px; top: 50%;
    transform: translateY(-50%); width: 3px; height: 16px;
    background: var(--accent); border-radius: 0 3px 3px 0;
  }
  .nav-item svg    { flex-shrink: 0; opacity: 0.65; }
  .nav-item.active svg { opacity: 1; }
  .nav-item .nbadge { display: none; }   /* ocultos: no se muestran los contadores en el menú lateral */
  .nav-item.active .nbadge { background: var(--accent-soft); color: var(--accent); }
  /* Sub-navegación (Operación → Monitoreo) — diseño v3 */
  .subnav {
    display: flex; flex-direction: column; gap: calc(1px * var(--sp-scale, 1));
    margin: 2px 0 2px 15px; padding-left: calc(10px * var(--sp-scale, 1));
    border-left: 1.5px solid var(--border);
  }
  .subnav .nav-item { font-size: calc(12.5px * var(--fs-scale, 1)); padding: calc(6px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); }
  .subnav .nav-item.active { background: var(--accent-soft); }
  .nav-item.parent-active { color: var(--text); }
  .nav-item.parent-active svg { opacity: 1; }
  /* ── Gating por ROL (solo UX; la seguridad real la aplica el backend) ──
     Para cualquier rol que NO sea admin: ocultar el botón de Configuración,
     el de Usuarios y los botones de ocultar/mostrar artistas.

     2026-07-24 — la sección Operación YA NO se oculta por rol. Contenía
     Monitoreo + Presupuesto; Presupuesto se retiró el 2026-07-16 y Monitoreo
     pasó a llamarse Herramientas, que desde hoy aloja el Tablero de Tareas:
     la única herramienta abierta a TODO el equipo. Con el `:not(.role-*)`
     viejo, el rol `estandar` tenía permiso de backend (`view:tasks`) y de
     front (`NONADMIN_PAGES`) pero NI UN SOLO elemento clicable que llevara
     ahí — solo ⌘K, que es solo-teclado por decisión del productor.
     Lo que este rol NO debe abrir se oculta tarjeta por tarjeta dentro del
     hub (ver el bloque `role-estandar` más abajo) y lo niega el backend. */
  /* Fase A (2026-08-20): la condición real es el PERMISO admin.settings
     (clase perm--admin-settings de /proxy/me); :not(.role-admin) queda como
     respaldo del arranque en frío (antes de que /me responda). */
  #view-app:not(.role-admin):not(.perm--admin-settings) .settings-btn,
  #view-app:not(.role-admin):not(.perm--admin-settings) .dept-eye { display: none !important; }
  /* 'Usuarios' vive en el footer (cluster admin junto a Configuración); hereda el gating de .settings-btn. */
  /* (Las listas negras por rol de las tarjetas del hub se retiraron en la
     Fase A: ver el bloque "Herramientas por permiso" junto al hub.) */

  /* ── Panel de Gestión de Usuarios (UX/UI) ── */
  #users-modal .modal-body { padding-top: var(--space-1); }
  .um-section-label { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--text3); margin: 0 0 10px; }
  .um-create { background: var(--wash-1); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: calc(14px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)) var(--space-3); margin-bottom: 22px; }
  .um-create-grid { display: grid; grid-template-columns: 1fr 1fr 150px; gap: calc(10px * var(--sp-scale, 1)); }
  .um-field { display: flex; flex-direction: column; gap: calc(5px * var(--sp-scale, 1)); min-width: 0; }
  .um-field > span { font-size: var(--fs-base); font-weight: 500; color: var(--text2); }
  /* Campos del modal con el MISMO estilo que el resto de la app (.field input) */
  .um-field input, .um-field select {
    background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-sm);
    padding: var(--space-2) calc(11px * var(--sp-scale, 1)); color: var(--text); font-size: var(--fs-md); outline: none;
    transition: border-color var(--dur-fast); width: 100%; font-family: inherit;
  }
  .um-field input:focus, .um-field select:focus { border-color: var(--accent); }
  .um-field input::placeholder { color: var(--text3); }
  .um-create-foot { display: flex; align-items: center; justify-content: space-between; gap: calc(14px * var(--sp-scale, 1)); margin-top: 13px; flex-wrap: wrap; }
  .um-check { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); font-size: var(--fs-base); color: var(--text2); cursor: pointer; font-weight: 500; }
  .um-check input { width: auto; margin: 0; }
  .um-list { display: flex; flex-direction: column; gap: var(--space-2); }
  .um-user { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: calc(10px * var(--sp-scale, 1)) var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--card); transition: border-color var(--dur-fast); flex-wrap: wrap; }
  .um-user:hover { border-color: var(--border2); }
  .um-user-info { display: flex; flex-direction: column; gap: calc(3px * var(--sp-scale, 1)); min-width: 130px; }
  .um-user-top { display: flex; align-items: center; gap: var(--space-2); }
  .um-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
  .um-dot.on { background: var(--green); } .um-dot.off { background: var(--text3); }
  .um-name { font-weight: 600; font-size: var(--fs-lg); color: var(--text); }
  .um-role-badge { font-size: var(--fs-xs); font-weight: 600; padding: calc(1.5px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius: 20px; background: var(--wash-2); color: var(--text2); white-space: nowrap; }
  .um-role-badge.admin { background: rgba(var(--accent-rgb),0.12); color: var(--accent); }
  .um-sub { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); font-size: var(--fs-sm); font-weight: 500; color: var(--text3); flex-wrap: wrap; }
  .um-presence.on { color: var(--green); } .um-presence.off { color: var(--text3); }
  .um-flag { color: var(--accent); }
  .um-actions { display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); flex-wrap: wrap; justify-content: flex-end; }
  /* width:auto: #um-embed vive dentro de un .field y su `select {width:100%}`
     volvía dropdown de borde a borde el selector de rol (revisión 07-29). */
  .um-actions select { width: auto; font-size: var(--fs-base); padding: calc(6px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-sm); color: var(--text); outline: none; font-family: inherit; transition: border-color var(--dur-fast); }
  .um-actions select:focus { border-color: var(--accent); }
  /* Cabecera centrada con cierre a la izquierda (estilo referencia) */
  #users-modal .modal-header { position: relative; justify-content: center; }
  #users-modal .modal-header h3 { text-align: center; }
  #users-modal .modal-header .close-btn { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); }
  .um-list-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin: 0 0 10px; }
  .um-filter { max-width: 200px; padding: calc(7px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); font-size: var(--fs-md); background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-sm); color: var(--text); outline: none; font-family: inherit; transition: border-color var(--dur-fast); }
  .um-filter:focus { border-color: var(--accent); }
  .um-filter::placeholder { color: var(--text3); }
  /* Toggle estilo iOS para "pedir cambio de contraseña" */
  .um-switch { position: relative; display: inline-block; width: 34px; height: 20px; flex-shrink: 0; }
  .um-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
  .um-switch .tr { position: absolute; inset: 0; background: var(--wash-3); border-radius: 20px; transition: background var(--dur-fast); cursor: pointer; }
  .um-switch .tr::before { content: ''; position: absolute; left: 2px; top: 2px; width: 16px; height: 16px; background: #fff; border-radius: 50%; transition: transform var(--dur-fast); box-shadow: 0 1px 2px rgba(0,0,0,.3); }
  .um-switch input:checked + .tr { background: var(--green); }
  .um-switch input:checked + .tr::before { transform: translateX(14px); }
  .um-actions .btn svg { vertical-align: -2px; margin-right: 3px; }
  .nav-section + .nav-section { margin-top: 12px; }
  .project-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
  /* ===== Sidebar footer — grupo unificado (EXPANDIDO) ===== */
  .sidebar-footer {
    padding: var(--space-2) var(--space-2); border-top: 1px solid var(--border);
    display: flex; align-items: center; gap: var(--space-1);
    /* Revisión UX 2026-08-03: los 3 controles se reparten con separación
       SIMÉTRICA. Antes logout se anclaba con margin-left:auto y quedaba un
       hueco muerto de ~28px entre Configuración y salir (4px vs 28px se leía
       como error de layout, no como agrupación intencional). */
    justify-content: space-between;
  }
  .sidebar-footer .theme-toggle-btn,
  .sidebar-footer .settings-btn,
  .sidebar-footer .logout-btn {
    height: 32px; min-width: 32px; padding: 0 var(--space-2);
    display: flex; align-items: center; justify-content: center; gap: calc(7px * var(--sp-scale, 1));
    border: none; background: none; border-radius: var(--radius-sm);
    color: var(--text2); font-size: var(--fs-base); font-weight: 500; font-family: inherit; cursor: pointer;
    transition: background var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out);
  }
  .sidebar-footer .theme-toggle-btn,
  .sidebar-footer .logout-btn { width: 32px; padding: 0; flex: 0 0 auto; }
  /* Hug content (revisión UX 2026-07-18): antes flex:1 estiraba el botón a
     todo el ancho — con textos cortos ("Settings" en EN) el hover/focus
     pintaba un rectángulo gigante y el área de click mentía. El botón sigue
     midiendo su contenido; el reparto simétrico lo da el space-between del
     contenedor (revisión UX 2026-08-03 — se retiró el margin-left:auto del
     logout que dejaba un hueco desigual). */
  .sidebar-footer .settings-btn { flex: 0 1 auto; }
  .sidebar-footer .theme-toggle-btn svg,
  .sidebar-footer .settings-btn svg,
  .sidebar-footer .logout-btn svg { opacity: .7; flex-shrink: 0; transition: opacity var(--dur-micro) var(--ease-out); }
  .sidebar-footer .theme-toggle-btn:hover,
  .sidebar-footer .settings-btn:hover { background: var(--wash-2); color: var(--text); }
  .sidebar-footer .theme-toggle-btn:hover svg,
  .sidebar-footer .settings-btn:hover svg { opacity: 1; }
  .sidebar-footer .logout-btn { color: var(--text3); }
  .sidebar-footer .logout-btn:hover { background: rgba(var(--red-rgb),0.12); color: var(--red); }
  .sidebar-footer .logout-btn:hover svg { opacity: 1; }
  .sidebar-footer .theme-toggle-btn:active,
  .sidebar-footer .settings-btn:active,
  .sidebar-footer .logout-btn:active { background: var(--wash-1); }
  .sidebar-footer .theme-toggle-btn:focus-visible,
  .sidebar-footer .settings-btn:focus-visible,
  .sidebar-footer .logout-btn:focus-visible { outline: 2px solid var(--text2); outline-offset: 2px; }

  /* ── Main ── */
  /* min-width:0 evita que contenido ancho (tablas) deforme el layout flex */
  .main-content { flex: 1; min-width: 0; height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
  .page { display: none; flex: 1; min-width: 0; overflow-y: auto; }
  .page.active { display: flex; flex-direction: column; }
  /* Entrada de página (2026-08-24): antes era un corte seco display:none→flex.
     6px y un fade bastan para que se entienda que una vista reemplazó a otra;
     más que eso estorbaría a quien navega rápido. La animación NO bloquea:
     el contenido ya es interactivo desde el primer frame. */
  .page.active { animation: pg-in var(--dur-base) var(--ease-out); }
  @keyframes pg-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
  .page > .page-header h1:focus { outline: none; }
/* ══════════════════════════════════════════════════════════
   Accesibilidad — Reducir movimiento (A11y H6, B5)
   Respeta la preferencia del sistema "Reducir movimiento": neutraliza
   animaciones, transiciones y scroll suave para usuarios sensibles al
   movimiento (mareo/vestibular). Aditivo: SOLO aplica cuando el usuario
   activó la preferencia — sin efecto en el resto.

   (Auditoría UX 2026-09-01 · D1) Este bloque vivía DESPUÉS de los bloques
   finos de reduced-motion y, al llevar `!important`, los anulaba: el
   cross-fade que sustituye al deslizamiento de página y la transición de
   color de las tarjetas nunca llegaban a pantalla, y el usuario recibía
   "cero movimiento" en vez del "equivalente suave" que pide el spec.
   Ahora va PRIMERO y los bloques que quieren un equivalente suave lo
   sobreescriben marcando su regla (mismo peso, ganan por orden).
   ══════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ══════════════════════════════════════════════════════════
   Accesibilidad — las otras DOS preferencias del sistema
   (auditoría UX 2026-09-01 · D6). Se respetaba "reducir movimiento" pero no
   "reducir transparencia" ni "más contraste", con 3 superficies translúcidas
   activas. Aditivo: solo aplica si el usuario activó la preferencia.
   ══════════════════════════════════════════════════════════ */
@media (prefers-reduced-transparency: reduce) {
  /* El velo deja de difuminar y se hace más opaco: la legibilidad manda
     sobre el efecto de material. */
  .modal-overlay, .cmdk-overlay { backdrop-filter: none; background: rgba(0, 0, 0, 0.72); }
}
@media (prefers-contrast: more) {
  /* Bordes definidos donde hoy hay solo un lavado de color. */
  .modal, .aso-panel, .chip, .loc-chip, .card, .stat-card { border-color: var(--text2); }
  :focus-visible { outline-width: 3px; }
}

/* Respuesta al PULSAR (auditoría UX 2026-09-01 · D5) — la app tenía 272
   estados de "mouse encima" y solo 13 de "pulsado", y el único real cubría
   los botones. En una app que consulta a Flow, el hueco entre el clic y la
   respuesta es donde se pierde la sensación de control: el hundido mínimo
   confirma que el clic SÍ se registró. El bloque de arriba lo neutraliza
   cuando el usuario pidió menos movimiento. */
.chip:active, .loc-chip:active, .nav-item:active, .report-card:active,
.cal-task:active, .cal-mc-card:active, .cal-list-row:active, .project-item:active {
  transform: scale(0.985);
  transition: transform 100ms ease-out;
}

  @media (prefers-reduced-motion: reduce) {
    /* Equivalente suave (no "nada"): fundido corto en vez del deslizamiento. */
    .page.active { animation: pg-fade var(--dur-fast) linear !important; }
    @keyframes pg-fade { from { opacity: 0; } to { opacity: 1; } }
  }
  .page-header {
    padding: var(--space-6) calc(28px * var(--sp-scale, 1)) calc(17px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border);
    display: flex; align-items: flex-start; justify-content: space-between;
    flex-shrink: 0; flex-wrap: wrap; gap: var(--space-3);
  }
  .page-header h1 { font-size: calc(22px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -0.6px; }
  .page-header p  { color: var(--text2); font-size: var(--fs-base); margin-top: 3px; }
  .page-header-actions { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
  .page-body { padding: var(--space-5) calc(28px * var(--sp-scale, 1)); flex: 1; min-width: 0; overflow-x: auto; }

  /* ── Cards & Stats ── */
  /* Grid responsive: 7 col en escritorio (≥1280 · compacto hasta 1500) · auto-fit <1280 · 2 col en iPhone (ver media queries). */
  .stats-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--space-3); margin-bottom: 18px; }
  /* KPI "Entregas esta semana" (WIP/PPF planeados · click → Calendario)
     Color FIJO (--kpi-blue): no debe seguir el acento personalizable de
     Editor UI — ver bug reportado donde cambiar el acento tintaba estos
     iconos/cifras junto con el resto de la UI. */
  .stat-card.is-week { border-color: rgba(var(--kpi-blue-rgb), .30); }
  .stat-card.is-week .value { color: var(--kpi-blue); }
  .stat-breakdown .wk-wip { color: var(--yellow); font-weight: 700; }
  .stat-breakdown .wk-ppf { color: var(--green); font-weight: 700; }
  /* ── Tarjeta KPI unificada (2026-07-05): un solo patrón — franja de acento
     (--c) + tile de color + número neutro (salvo estado). El acento por tarjeta
     lo define data-accent (default abajo) y lo puede pisar el tema (cardAccents
     de la galería), que además cascada al glifo del icono. ── */
  .stat-card {
    position: relative; overflow: hidden;
    background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
    padding: calc(15px * var(--sp-scale, 1)); display: flex; align-items: center; gap: var(--space-3); min-width: 0;
    transition: transform var(--dur-fast) cubic-bezier(.32,.72,0,1), border-color var(--dur-fast), box-shadow var(--dur-fast);
  }
  .stat-card::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
    background: var(--c, var(--accent)); opacity: .9;
  }
  /* Acento por defecto de cada tarjeta (el tema puede pisarlo) */
  .stat-card[data-accent="stat-shows-activos"]   { --c: var(--accent); --c-rgb: var(--accent-rgb); }
  .stat-card[data-accent="stat-shots-activos"]   { --c: var(--cyan);   --c-rgb: var(--cyan-rgb); }
  .stat-card[data-accent="stat-artistas"]        { --c: var(--purple); --c-rgb: var(--purple-rgb); }
  .stat-card[data-accent="stat-entregas-semana"] { --c: var(--accent); --c-rgb: var(--accent-rgb); }
  .stat-card[data-accent="stat-shots-aprobados"] { --c: var(--green);  --c-rgb: var(--green-rgb); }
  .stat-card[data-accent="stat-comfy"]           { --c: var(--orange); --c-rgb: var(--orange-rgb); }
  .stat-card > div { min-width: 0; }
  /* Bloque de texto con altura reservada uniforme (3 líneas): los 5 números KPI
     quedan a la misma altura aunque solo Artistas use la línea de desglose. */
  .stat-card > div:last-child { display: flex; flex-direction: column; justify-content: flex-start; min-height: 60px; }
  .stat-card:hover { transform: translateY(-2px); border-color: var(--border2); box-shadow: 0 6px 18px rgba(0,0,0,0.12); }
  .stat-icon {
    width: 38px; height: 38px; border-radius: var(--radius-sm);
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    background: rgba(var(--c-rgb, var(--accent-rgb)), 0.14); color: var(--c, var(--accent));
  }
  .stat-card .value { font-size: var(--fs-kpi); font-weight: 700; line-height: 1; letter-spacing: -0.6px; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; max-width: 100%; }
  /* Número neutro por defecto; solo las tarjetas de ESTADO tiñen el número */
  .stat-card .value.semantic { color: var(--c, var(--accent)); }
  /* Label y desglose: con 7 tarjetas el espacio de texto baja a ~55-75px en
     1280-1500px, así que en vez de nowrap+ellipsis (truncaba "Entregas es…")
     se permite envolver a máx. 2 líneas cortando SOLO en espacios. */
  .stat-card .label { font-size: var(--fs-sm); color: var(--text2); margin-top: 3px; line-height: 1.3; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
  .stat-breakdown { font-size: var(--fs-xs); color: var(--text3); margin-top: 3px; line-height: 1.35; font-variant-numeric: tabular-nums; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
  .stat-breakdown span { color: var(--text2); font-weight: 600; }
  /* ── Tarjeta Créditos Comfy (punto de estado · click → detalle) ──
     Unificada 2026-07-01: misma anatomía que las demás KPI (ícono 38px a la
     izquierda, número + etiqueta a la izquierda). El número se autoajusta (JS)
     para caber sin cortar; el punto de color conserva el estado del saldo. */
  .comfy-card .label { display: flex; align-items: center; justify-content: flex-start; gap: calc(5px * var(--sp-scale, 1)); }
  .comfy-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text3); flex-shrink: 0; }
  /* Botón "Enviar correo" del modal de detalle: compacto y con la estética de la app */
  .comfy-modal-foot { align-items: center; justify-content: flex-end; flex-wrap: wrap; }
  .comfy-send-btn { width: auto; background: var(--accent); color: #fff; }
  .comfy-send-btn:hover { background: var(--accent-hover); }
  /* Lista de usuarios embebida en Configuración › Seguridad. Sin scroll propio:
     scrollea todo el panel una sola vez (evita el doble scroll). */
  .um-list--embed { margin-top: 4px; }
  /* MFA compacto en una línea + divisor de sección */
  .um-row-inline { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; margin-bottom: 16px; }
  .um-inline-title { font-size: var(--fs-md); font-weight: 600; color: var(--text); }
  .um-inline-sub { font-size: var(--fs-base); color: var(--text3); margin-top: 3px; }
  .um-divider { height: 1px; background: var(--border); margin: 4px 0 20px; }
  /* ── Modal de detalle Comfy ── */
  .comfy-detail-head { align-items: flex-start; }
  .comfy-detail-title { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-md); font-weight: 600; color: var(--text2); }
  .comfy-detail-ic { width: 16px; height: 16px; color: var(--text3); flex-shrink: 0; }
  .comfy-detail-sub { font-size: var(--fs-sm); color: var(--text3); margin: 6px 0 0; }
  /* Solo indicador: punto de color de estado, sin pill ni texto. */
  .comfy-chip { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: currentColor; vertical-align: middle; margin-left: 4px; }
  .comfy-chip.green  { color: var(--green);  }
  .comfy-chip.yellow { color: var(--orange); }
  .comfy-chip.red    { color: var(--red);    }
  .comfy-chip.off    { color: var(--text3);  }
  .comfy-modal-big { font-size: calc(34px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -1px; line-height: 1; font-variant-numeric: tabular-nums; margin: 12px 0 0; }
  .comfy-modal-big span { font-size: var(--fs-lg); color: var(--text3); font-weight: 600; letter-spacing: 0; margin-left: 3px; }
  .comfy-modal-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: calc(10px * var(--sp-scale, 1)); }
  .comfy-mini { background: var(--card2); border: 1px solid var(--border); border-radius: 10px; padding: calc(11px * var(--sp-scale, 1)); }
  .comfy-mini .k { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: .04em; color: var(--text3); }
  .comfy-mini .v { font-size: calc(16px * var(--fs-scale, 1)); font-weight: 700; margin-top: 4px; font-variant-numeric: tabular-nums; }
  /* Fuente del dato (de dónde salió el promedio diario): un número de dinero
     sin fuente declarada no se pinta — ver comfy-creditos.js. */
  .comfy-mini .s { font-size: var(--fs-2xs); color: var(--text3); margin-top: 3px; line-height: 1.3; }
  @media (max-width: 560px) { .comfy-modal-grid { grid-template-columns: 1fr 1fr; } }
  /* ── Consumo real por periodo (24 h / 7 d / 30 d) — paridad con iOS ── */
  .comfy-usage { margin-top: var(--space-3); border-top: 1px solid var(--border); padding-top: var(--space-3); }
  .comfy-usage-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-2); }
  .comfy-usage-title { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: .04em; color: var(--text3); font-weight: 700; }
  .comfy-usage-tabs { display: flex; gap: 0; border: 1px solid var(--border); border-radius: var(--radius-pill); overflow: hidden; }
  .comfy-usage-tab { background: transparent; border: 0; color: var(--text2); font-family: inherit;
    font-size: var(--fs-sm); font-weight: 600; padding: calc(5px * var(--sp-scale, 1)) var(--space-3);
    cursor: pointer; transition: background var(--dur-fast), color var(--dur-fast); }
  .comfy-usage-tab:hover { background: var(--card2); }
  .comfy-usage-tab.active { background: var(--accent); color: #fff; }
  .comfy-usage-total { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
  .comfy-usage-total-lbl { font-size: var(--fs-sm); color: var(--text3); }
  .comfy-usage-total-num { font-size: calc(20px * var(--fs-scale, 1)); font-weight: 700; font-variant-numeric: tabular-nums; }
  .comfy-usage-cap { font-size: var(--fs-2xs); color: var(--text3); margin: var(--space-2) 0 var(--space-1); }
  .comfy-usage-list { list-style: none; margin: 0; padding: 0; max-height: 210px; overflow-y: auto; }
  .comfy-usage-row { display: flex; align-items: baseline; gap: var(--space-2); padding: calc(3px * var(--sp-scale, 1)) 0; }
  .comfy-usage-prod { flex: 1; min-width: 0; font-size: var(--fs-sm); color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .comfy-usage-num { font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; }
  .comfy-usage-pct { width: 38px; text-align: right; font-size: var(--fs-sm); color: var(--text3); font-variant-numeric: tabular-nums; }
  .comfy-usage-msg { margin: var(--space-1) 0 0; }
  .comfy-usage-err { margin: var(--space-1) 0 0; font-size: var(--fs-sm); color: var(--red); line-height: 1.5; }
  /* Gate de `comfy.credits.request` SOLO para el consumo por periodo (2026-08-24
     tarde). El saldo se ve sin permiso —como en iOS y como en el server, que no
     le pone `requirePerm` a `/proxy/comfy/credits`—; lo que el server sí corta
     con 403 es `/proxy/comfy/usage-series`, y eso es lo que se esconde aquí.
     ¿Por qué por CLASE y no con el patrón `#view-app.perms-loaded:not(.perm--x)`
     del hub de Herramientas? Porque #comfy-modal vive FUERA de #view-app (son
     hermanos en el body, y el modal va ANTES), así que ningún combinador de
     descendencia ni de hermano posterior lo alcanza. La pone comfy-creditos.js
     (`_renderComfyUsage`) y solo cuando /me YA respondió: sin respuesta se deja
     visible y manda el 403 del server, que se pinta como mensaje.
     §6: la sección tiene `display` de autor, por eso el ocultamiento va por
     clase y no por [hidden]. */
  .comfy-usage.comfy-usage--sin-permiso { display: none; }
  /* ── Panel de solicitud de compra de créditos (dentro del modal Comfy) ── */
  .comfy-req { padding-top: var(--space-1); }
  .comfy-req-row { display: flex; gap: calc(10px * var(--sp-scale, 1)); align-items: baseline; margin-bottom: 8px; }
  .comfy-req-lbl { width: 42px; flex-shrink: 0; font-size: calc(10.5px * var(--fs-scale, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--text3); }
  .comfy-req-chips { display: flex; flex-wrap: wrap; gap: calc(6px * var(--sp-scale, 1)); }
  .comfy-req-chip { font-size: calc(11.5px * var(--fs-scale, 1)); background: var(--card2); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); color: var(--text2); }
  .comfy-req-field { display: flex; flex-direction: column; gap: var(--space-1); margin-bottom: 10px; }
  .comfy-req-lbl2 { font-size: calc(10.5px * var(--fs-scale, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--text3); }
  .comfy-req-field input, .comfy-req-field textarea { width: 100%; background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius-sm); color: var(--text); font-size: calc(12.5px * var(--fs-scale, 1)); padding: var(--space-2) calc(10px * var(--sp-scale, 1)); outline: none; font-family: inherit; line-height: 1.55; }
  .comfy-req-field textarea { resize: vertical; min-height: 116px; }
  /* Aviso rojo dentro del panel (lo que antes decía la alerta del dashboard) */
  .comfy-req-alerta { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); margin: 0 0 var(--space-2);
    font-size: var(--fs-base); font-weight: 600; color: var(--red); }
  .comfy-req-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--red); display: inline-block; }
  .comfy-req-help { margin: var(--space-2) 0; }
  .stat-card.clickable { cursor: pointer; }
  .stat-card.is-risk { border-color: rgba(var(--red-rgb), .28); }
  .stat-card .value.is-danger { color: var(--red); }
  /* Fijo (--kpi-blue): no debe seguir el acento personalizable de Editor UI. */
  .stat-icon.tint-blue-fixed { background: rgba(var(--kpi-blue-rgb), .12); color: var(--kpi-blue); }
  .stat-icon.tint-neutral { background: var(--wash-2); color: var(--text2); }
  .stat-icon.tint-risk    { background: rgba(var(--red-rgb), .12); color: var(--red); }
  .stat-flag { font-size: var(--fs-2xs); font-weight: 600; color: var(--text3); background: var(--wash-2); border-radius: var(--radius-pill); padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); margin-left: 7px; vertical-align: middle; }
  .card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: calc(17px * var(--sp-scale, 1)); box-shadow: var(--shadow-card); }

  /* ── Dashboard · lista compacta de proyectos activos (diseño v3) ── */
  #dash-table-wrap { overflow-x: auto; }
  .dash-plist { display: flex; flex-direction: column; min-width: 560px; }
  .dash-phead, .dash-prow {
    display: grid;
    /* Columnas más separadas: Shots act. y Entrega con aire propio para que
       los encabezados alineen con su contenido (feedback 2026-07-03). */
    grid-template-columns: minmax(170px,1fr) 150px 90px 120px 40px;
    align-items: center; gap: calc(18px * var(--sp-scale, 1)); padding: calc(7px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1));
  }
  /* Roles no-admin: sin columna "Visible" (herramienta solo de administración) */
  .dash-plist.no-vis .dash-phead, .dash-plist.no-vis .dash-prow {
    grid-template-columns: minmax(170px,1fr) 150px 90px 120px;
  }
  .dash-phead {
    font-size: calc(10.5px * var(--fs-scale, 1)); font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; color: var(--text3); border-bottom: 1px solid var(--border);
  }
  .dash-prow {
    border-bottom: 1px solid var(--border); font-size: var(--fs-md); min-height: 52px;
    transition: background var(--dur-micro), opacity var(--dur-base);
  }
  .dash-prow:last-child { border-bottom: none; }
  .dash-prow:hover { background: var(--wash-1); }
  .dash-prow.off { opacity: .42; }
  .dash-health { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
  /* Nombre + tipo apilados (el tipo va debajo, en gris pequeño) */
  .dash-pname { cursor: pointer; display: flex; flex-direction: row; align-items: center; gap: var(--space-2); min-width: 0; }
  .dash-pname-txt { display: flex; flex-direction: column; justify-content: center; min-width: 0; }
  .dash-pname-top { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .dash-pname b { font-weight: 650; color: var(--text); }
  .dash-pname .pn { color: var(--text); font-weight: 600; margin-left: 0; }
  .dash-pname:hover .pn { color: var(--text); }
  .dash-pname-type { font-size: var(--fs-sm); color: var(--text3); margin-top: 2px; }
  .dash-psup { color: var(--text2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .dash-pshots { text-align: right; padding-right: var(--space-4); font-variant-numeric: tabular-nums; color: var(--text); font-weight: 600; }
  .dash-pprog { display: flex; align-items: center; gap: var(--space-2); min-width: 0; padding-right: calc(14px * var(--sp-scale, 1)); }
  .dash-prog-bar { flex: 0 0 72px; width: 72px; height: 6px; background: var(--wash-2); border-radius: var(--radius-pill); overflow: hidden; }
  .dash-prog-fill { display: block; height: 100%; background: var(--accent); border-radius: inherit; transition: width .35s var(--ease-out); }
  .dash-prog-pct { font-size: var(--fs-sm); color: var(--text2); font-variant-numeric: tabular-nums; min-width: 32px; text-align: right; }
  .dash-pdate { color: var(--text2); font-variant-numeric: tabular-nums; white-space: nowrap; }
  /* "Sin fecha" como píldora (estado definido del sistema, no error) */
  .dash-pdate.none { color: var(--text2); font-style: normal; background: var(--wash-2); border-radius: var(--radius-pill); padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); font-size: var(--fs-sm); justify-self: start; }
  /* Toggle estilo Apple */
  .dash-switch {
    width: 38px; height: 22px; border-radius: 11px; background: var(--wash-3);
    position: relative; cursor: pointer; flex-shrink: 0; justify-self: end;
    border: 1px solid var(--border); transition: background var(--dur-base) cubic-bezier(.32,.72,0,1);
  }
  .dash-switch.on { background: var(--green); border-color: transparent; }
  .dash-knob {
    position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
    border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3);
    transition: transform var(--dur-base) cubic-bezier(.32,.72,0,1);
  }
  .dash-switch.on .dash-knob { transform: translateX(16px); }
  .card-title {
    font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--text2); margin-bottom: 14px;
    display: flex; align-items: center; justify-content: space-between;
  }
  .card-title span { text-transform: none; letter-spacing: 0; font-weight: 400; font-size: var(--fs-sm); color: var(--text3); }
  .charts-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px,1fr)); gap: var(--space-3); margin-bottom: 18px; }

  /* ── Responsive: tablas con scroll interno y contenedores que no se rompen ── */
  #dash-table-wrap { overflow-x: auto; }
  .table-scroll { overflow-x: auto; }
  .tab-panel { overflow-x: auto; }

  /* Navegador reducido: menos padding y barra lateral un poco más angosta */
  @media (max-width: 1024px) {
    .page-header { padding: calc(18px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); }
    .page-body   { padding: var(--space-4) calc(18px * var(--sp-scale, 1)); }
    :root { --sidebar-w: 200px; --filter-aside-w: 200px; }
    .projects-sidebar { width: 224px; }
  }
  /* Proyectos: 3 columnas (lista · detalle · filtros) colapsan en pantallas angostas */
  @media (max-width: 900px) {
    .projects-layout { flex-wrap: wrap; overflow-y: auto; }
    .projects-sidebar {
      width: 100%; height: auto; max-height: 260px;
      border-right: none; border-bottom: 1px solid var(--border);
    }
    .projects-layout > aside { width: 100% !important; order: -1; }
    .project-detail { width: 100%; min-width: 0; }
  }
  /* 7 KPIs en una fila: en 1280-1500px cada tarjeta queda en ~134-165px, así
     que se compacta padding/gap/ícono para dejar ~70px reales al texto
     (suficiente para "esta semana" a 10.5px sin truncar). El SVG interno se
     reescala vía CSS; #comfy-card no se toca: su JS (_fitComfyBalance) lee
     clientWidth en runtime y se re-ajusta solo. */
  @media (min-width: 1280px) and (max-width: 1500px) {
    .stats-grid { gap: calc(10px * var(--sp-scale, 1)); }
    .stats-grid .stat-card { padding: var(--space-3) calc(11px * var(--sp-scale, 1)); gap: calc(9px * var(--sp-scale, 1)); }
    .stats-grid .stat-icon { width: 30px; height: 30px; border-radius: 8px; }
    .stats-grid .stat-icon svg { width: 16px; height: 16px; }
    .stats-grid .stat-card .label { font-size: calc(10.5px * var(--fs-scale, 1)); }
    .stats-grid .stat-breakdown { font-size: calc(9.5px * var(--fs-scale, 1)); }
  }
  /* Debajo de 1280px de viewport ya no caben 7 columnas legibles (tarjetas de
     <134px): la fila envuelve con auto-fit (antes el corte estaba en 1100px y
     entre 1100-1280px las tarjetas quedaban en 115-133px, ilegibles). */
  @media (max-width: 1279.98px) {
    .stats-grid  { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
  }
  @media (max-width: 820px) {
    .page-body   { padding: calc(14px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); }
  }
  @media (max-width: 600px) {
    .stats-grid       { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: calc(10px * var(--sp-scale, 1)); }
    .comfy-card       { grid-column: 1 / -1; }
    .stats-grid .stat-icon { display: none; }
    .stat-card        { padding: calc(13px * var(--sp-scale, 1)); gap: calc(10px * var(--sp-scale, 1)); }
    .stat-card .label { font-size: var(--fs-base); }
  }

  /* ── Projects layout ── */
  .projects-layout { display: flex; flex: 1; overflow: hidden; height: 100%; }
  .projects-sidebar {
    width: 264px; flex-shrink: 0; border-right: 1px solid var(--border);
    display: flex; flex-direction: column; height: 100%;
  }
  .search-box {
    display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1));
    background: var(--wash-2); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: calc(6px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); margin-bottom: 7px;
  }
  .search-box input {
    background: none; border: none; color: var(--text); font-size: var(--fs-md);
    outline: none; flex: 1; font-family: inherit;
  }
  .search-box input::placeholder { color: var(--text3); }
  .filter-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
  .chip {
    padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius: var(--radius-pill); font-size: var(--fs-sm); font-weight: 500;
    cursor: pointer; border: 1px solid var(--border); background: transparent;
    color: var(--text2); transition: all var(--dur-micro);
  }
  .chip:hover { border-color: var(--border2); color: var(--text); }
  .chip.active { background: rgba(var(--accent-rgb),0.14); border-color: rgba(var(--accent-rgb),0.28); color: var(--accent); }

  /* ── Filtro de Locación ────────────────────────────────── */
  .loc-filter-section {
    margin-top: 8px; padding-top: var(--space-2);
    border-top: 1px solid var(--border);
  }
  .loc-filter-header {
    display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); margin-bottom: 6px;
  }
  .loc-filter-label {
    font-size: var(--fs-xs); font-weight: 700; color: var(--text3);
    text-transform: uppercase; letter-spacing: .05em; flex: 1;
  }
  .loc-filter-count {
    font-size: var(--fs-2xs); background: rgba(var(--accent-rgb),0.18); color: var(--accent);
    border-radius: var(--radius-xs); padding: 0 calc(5px * var(--sp-scale, 1)); font-weight: 700; line-height: calc(16px * var(--fs-scale, 1));
  }
  .loc-filter-clear {
    font-size: var(--fs-xs); color: var(--text3); background: none; border: none;
    cursor: pointer; padding: 0; transition: color var(--dur-micro);
  }
  .loc-filter-clear:hover { color: var(--accent); }
  .loc-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
  /* (Auditoría UX 2026-09-01 · D9) `.loc-chip` repetía las 8 declaraciones de
     `.chip` y solo añadía 3 propias — dos definiciones de lo mismo derivan con
     el tiempo. Ahora hereda y declara SOLO su diferencia (cero cambio visual). */
  .loc-chip {
    padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius: var(--radius-pill); font-size: var(--fs-sm); font-weight: 500;
    cursor: pointer; border: 1px solid var(--border); background: transparent;
    color: var(--text2); transition: all var(--dur-micro);
    white-space: nowrap; display: flex; align-items: center; gap: var(--space-1);
  }
  .loc-chip:hover { border-color: var(--border2); color: var(--text); }
  .loc-chip.active {
    background: rgba(var(--accent-rgb),0.14); border-color: rgba(var(--accent-rgb),0.28); color: var(--accent);
  }
  .projects-list { overflow-y: auto; flex: 1; padding: calc(5px * var(--sp-scale, 1)); }
  .project-item {
    padding: calc(9px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1)); border-radius: var(--radius-sm); cursor: pointer;
    margin-bottom: 1px; transition: background var(--dur-micro); border: 1px solid transparent;
  }
  .project-item:hover  { background: var(--wash-2); }
  .project-item.active { background: rgba(var(--accent-rgb),0.1); border-color: rgba(var(--accent-rgb),0.18); }
  .project-item .project-name { font-size: var(--fs-md); font-weight: 500; display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); margin-bottom: 4px; }
  .project-item .project-meta { display: flex; gap: calc(5px * var(--sp-scale, 1)); align-items: center; flex-wrap: wrap; }
  .project-detail { flex: 1; min-width: 0; overflow: hidden; display: flex; flex-direction: column; }

  /* ── Detail header ── */
  .detail-header { padding: calc(21px * var(--sp-scale, 1)) var(--space-6) 0; border-bottom: 1px solid var(--border); flex-shrink: 0; }
  .detail-header h2 {
    font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.4px;
    display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 8px; flex-wrap: wrap;
  }
  .detail-meta { display: flex; gap: calc(14px * var(--sp-scale, 1)); align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
  .detail-meta .meta-item { display: flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); font-size: var(--fs-base); color: var(--text2); }
  .detail-mini-stats { display: flex; gap: var(--space-5); margin-bottom: 16px; }
  .detail-mini-stat .val { font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.3px; }
  .detail-mini-stat .lbl { font-size: var(--fs-sm); color: var(--text2); }
  .tabs { display: flex; gap: 0; }
  .tab-btn, .budget-subnav-btn {
    padding: calc(9px * var(--sp-scale, 1)) calc(15px * var(--sp-scale, 1)); font-size: var(--fs-md); font-weight: 500;
    background: none; border: none; color: var(--text2);
    cursor: pointer; border-bottom: 2px solid transparent; transition: all var(--dur-micro);
    font-family: inherit;
  }
  .tab-btn:hover, .budget-subnav-btn:hover { color: var(--text); }
  .tab-btn.active, .budget-subnav-btn.active { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }
  .tab-panels { flex: 1; overflow-y: auto; }
  /* Etiqueta de filtro única (reemplaza los estilos inline repetidos) */
  .filter-label { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text3); margin-bottom: 9px; }
  .tab-panel { display: none; padding: var(--space-5) var(--space-6); }
  .tab-panel.active { display: block; }

  /* ── Tables ── */
  .data-table { width: 100%; border-collapse: collapse; }
  .data-table th {
    text-align: left; font-size: var(--fs-xs); font-weight: 600; color: var(--text3);
    text-transform: uppercase; letter-spacing: 0.06em;
    padding: 0 calc(10px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border);
  }
  .data-table td {
    padding: calc(9px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); font-size: var(--fs-md);
    border-bottom: 1px solid var(--wash-1); vertical-align: middle;
  }
  .data-table tr:last-child td { border-bottom: none; }
  .data-table tr:hover td { background: var(--wash-1); }

  /* ── Badges ── */
  .badge {
    display: inline-flex; align-items: center; gap: calc(3px * var(--sp-scale, 1)); padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1));
    border-radius: var(--radius-pill); font-size: var(--fs-sm); font-weight: 500; white-space: nowrap; letter-spacing: 0.1px;
  }
  .badge-green  { background: rgba(var(--green-rgb),0.12);  color: var(--green); }
  .badge-yellow { background: rgba(var(--yellow-rgb),0.12); color: var(--yellow); }
  .badge-orange { background: rgba(var(--orange-rgb),0.12); color: var(--orange); }
  .badge-blue   { background: rgba(var(--accent-rgb),0.12); color: var(--accent); }
  .badge-purple { background: rgba(var(--purple-rgb),0.12); color: var(--purple); }
  .badge-gray   { background: var(--wash-3); color: var(--text2); }
  .badge-red    { background: rgba(var(--red-rgb),0.12);  color: var(--red); }

  /* ── Progress ── */
  .progress-bar  { height: 5px; background: var(--wash-3); border-radius: 3px; overflow: hidden; }
  .progress-fill { height: 100%; border-radius: 3px; transition: width .5s ease; }

  /* ── Artists ── */
  .dept-chips { display: flex; gap: calc(5px * var(--sp-scale, 1)); flex-wrap: wrap; margin-bottom: 14px; }
  .dept-chip {
    display: flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius: var(--radius-pill);
    font-size: var(--fs-sm); font-weight: 500; cursor: pointer;
    border: 1px solid var(--border); background: transparent; color: var(--text2); transition: all var(--dur-micro);
  }
  .dept-chip:hover  { border-color: var(--border2); color: var(--text); }
  .dept-chip.active { background: rgba(var(--accent-rgb),0.14); border-color: rgba(var(--accent-rgb),0.28); color: var(--accent); }
  .dept-chip .count { background: var(--wash-3); padding: 0 calc(5px * var(--sp-scale, 1)); border-radius: var(--radius-pill); font-size: var(--fs-xs); }
  .dept-chip.active .count { background: rgba(var(--accent-rgb),0.18); }
  .artists-grid { display: grid; grid-template-columns: repeat(auto-fill,minmax(288px,1fr)); gap: var(--space-2); }
  .artist-card {
    background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
    padding: calc(13px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); display: flex; flex-direction: column; gap: calc(9px * var(--sp-scale, 1)); transition: border-color var(--dur-micro), border-left-color var(--dur-micro);
    border-left-width: 3px; border-left-style: solid; border-left-color: var(--border);
  }
  .artist-card:hover { border-color: var(--border2); background: var(--card2); }
  .artist-card.status-green  { border-left-color: var(--green); }
  .artist-card.status-orange { border-left-color: var(--orange); }
  .artist-card.status-red    { border-left-color: var(--red); }
  .artist-card-top { display: flex; align-items: center; gap: calc(11px * var(--sp-scale, 1)); }
  .avatar {
    width: 35px; height: 35px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: var(--fs-base); font-weight: 600; flex-shrink: 0; letter-spacing: -0.3px;
  }
  .artist-info { flex: 1; min-width: 0; }
  .artist-name  { font-size: var(--fs-md); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .artist-email { font-size: var(--fs-sm); color: var(--text2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
  .artist-status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green); flex-shrink: 0; }
  .artist-card-footer {
    display: flex; align-items: center; justify-content: space-between;
    padding-top: var(--space-2); border-top: 1px solid var(--border); gap: var(--space-2);
  }
  .task-count-pill {
    display: flex; align-items: center; gap: var(--space-1); font-size: var(--fs-sm); font-weight: 500;
    background: rgba(var(--accent-rgb),0.1); color: var(--accent);
    padding: calc(3px * var(--sp-scale, 1)) var(--space-2); border-radius: 20px; white-space: nowrap; flex-shrink: 0;
  }
  .project-pills { display: flex; flex-wrap: wrap; gap: calc(3px * var(--sp-scale, 1)); }
  .project-pill {
    font-size: var(--fs-xs); padding: calc(2px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); border-radius: 5px;
    background: var(--wash-2); color: var(--text2); white-space: nowrap;
    max-width: 120px; overflow: hidden; text-overflow: ellipsis; border: 1px solid var(--border);
  }
  .proj-code-pill {
    display: inline-flex; align-items: center; gap: var(--space-1);
    background: rgba(var(--accent-rgb),0.1); border: 1px solid rgba(var(--accent-rgb),0.2);
    color: var(--accent); border-radius: 5px; padding: calc(2px * var(--sp-scale, 1)) var(--space-2);
    font-size: var(--fs-xs); font-weight: 700; white-space: nowrap;
    font-family: var(--font-mono); letter-spacing: 0.03em;
  }
  .proj-task-count {
    background: rgba(var(--accent-rgb),0.22); border-radius: 10px;
    padding: 0 var(--space-1); font-size: var(--fs-2xs); font-weight: 600;
  }
  .artist-dept-badge {
    font-size: var(--fs-xs); font-weight: 600; color: var(--text3);
    text-transform: uppercase; letter-spacing: 0.05em; margin-top: 2px;
  }
  .dept-section { margin-bottom: 24px; }
  .dept-section-header { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); margin-bottom: 10px; }
  .dept-section-header h3 {
    font-size: var(--fs-sm); font-weight: 600; color: var(--text2);
    text-transform: uppercase; letter-spacing: 0.06em;
  }
  .dept-section-header .dept-count {
    font-size: var(--fs-xs); font-weight: 600; color: var(--purple);
    background: rgba(var(--purple-rgb),0.1); padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: 10px;
  }

  /* ── Loading skeleton ── */
  .skeleton {
    background: linear-gradient(90deg,
      var(--wash-2) 25%,
      var(--wash-3) 50%,
      var(--wash-2) 75%);
    background-size: 200% 100%; animation: shimmer 1.8s infinite; border-radius: var(--radius-xs);
  }
  @keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
  .skeleton-row { height: 40px; margin-bottom: 4px; }
  /* Skeleton de barra (Tablero de Tareas) */
  .skeleton-bar { height: 18px; margin-bottom: 8px; }
  .skeleton-bar.w48 { width: 48%; margin-bottom: 0; }

  /* ── Carga progresiva del Dashboard (dash-load.js · 2026-07-28) ──
     Un solo vocabulario de carga: mientras la tarjeta KPI tiene .skel, su
     número y desglose se ocultan y un chip shimmer del MISMO tamaño
     tipográfico ocupa el lugar (cero layout shift; el label queda visible y
     dice qué está cargando). dash-load.js revela por tandas → .reveal. */
  /* !important: reglas posteriores (p.ej. .stat-card.is-approved .value) no
     deben filtrarse a través del skeleton */
  .stat-card.skel .value,
  .stat-card.skel .value.semantic,
  .stat-card.skel .value.is-danger { color: transparent !important; }
  .stat-card.skel .value { position: relative; }
  .stat-card.skel .value::after {
    content: ""; position: absolute; left: 0; top: 0; height: 100%; width: 2.5ch;
    border-radius: var(--radius-xs);
    background: linear-gradient(90deg, var(--wash-2) 25%, var(--wash-3) 50%, var(--wash-2) 75%);
    background-size: 200% 100%; animation: shimmer 1.8s infinite;
  }
  .stat-card.skel .stat-breakdown { opacity: 0; }
  /* Revelado skel → dato: fade + lift sutil, una sola vez por tarjeta */
  .stat-card.reveal .value, .stat-card.reveal .stat-breakdown { animation: dash-kpi-in var(--dur-fast) var(--ease-out); }
  @keyframes dash-kpi-in { from { opacity: 0; transform: translateY(2px); } }
  /* Pulso "dato nuevo" en sync silenciosa: acento de la tarjeta, decae solo.
     Solo se aplica (JS) si el valor CAMBIÓ — sin cambio, cero movimiento. */
  .stat-card.stat-flash { animation: dash-flash var(--dur-theme) ease-out 1; }
  @keyframes dash-flash { 0% { background-color: rgba(var(--c-rgb, var(--accent-rgb)), .10); } 100% { background-color: var(--card); } }

  /* Barra fina de progreso determinada. La pista SIEMPRE ocupa su alto (sin
     layout shift); el fill aparece/desaparece por opacidad. El "cuándo se
     actualizó" vive en la tarjeta FTP del sidebar (last sync). */
  .dash-loadhead { display: flex; align-items: center; gap: var(--space-3); min-height: 12px; margin-bottom: 6px; }
  .dash-loadbar { flex: 1; height: 2px; border-radius: var(--radius-pill); background: transparent; overflow: hidden; transition: background var(--dur-base); }
  .dash-loadbar.on { background: var(--wash-2); }
  .dash-loadbar-fill { display: block; height: 100%; width: 0; border-radius: inherit; background: var(--accent); opacity: 0; transition: width var(--dur-base) var(--ease-out), opacity var(--dur-base); }
  .dash-loadbar.on .dash-loadbar-fill { opacity: 1; }

  @media (prefers-reduced-motion: reduce) {
    .skeleton, .stat-card.skel .value::after { animation: none; }
    .stat-card.reveal .value, .stat-card.reveal .stat-breakdown { animation: none; }
    .stat-card.stat-flash { animation: none; }
  }

  /* ── Misc ── */
  .empty-state {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    padding: calc(60px * var(--sp-scale, 1)) var(--space-5); gap: calc(10px * var(--sp-scale, 1)); color: var(--text2); text-align: center;
  }
  .empty-state .empty-icon { opacity: 0.28; margin-bottom: 2px; }
  .empty-state strong { font-size: var(--fs-md); font-weight: 600; color: var(--text); }
  .empty-state p { font-size: var(--fs-base); line-height: 1.5; }
  .confirm-dialog {
    background: var(--card); border: 1px solid var(--border2); border-radius: 14px;
    padding: var(--space-6); width: 330px; text-align: center;
    box-shadow: var(--shadow-modal);
  }
  .confirm-dialog h3  { font-size: calc(15px * var(--fs-scale, 1)); font-weight: 600; margin-bottom: 7px; letter-spacing: -0.2px; }
  .confirm-dialog p   { color: var(--text2); font-size: var(--fs-md); line-height: 1.5; margin-bottom: 20px; }
  .confirm-dialog .actions { display: flex; gap: var(--space-2); justify-content: center; }
  .chart-legend { display: flex; flex-direction: column; gap: calc(5px * var(--sp-scale, 1)); margin-top: 8px; }
  .legend-item  { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-sm); }
  details summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); }
  details summary::-webkit-details-marker { display: none; }
  details[open] summary .arrow { transform: rotate(90deg); }
  .arrow { transition: transform var(--dur-fast); font-size: var(--fs-2xs); color: var(--text3); }
  details .disclosure-body { padding: calc(10px * var(--sp-scale, 1)) 0 var(--space-1); font-size: var(--fs-base); color: var(--text2); line-height: 1.7; }

  /* ── Dashboard rediseñado ── */
  .dash-section-label {
    font-size: var(--fs-xs); font-weight: 600; color: var(--text3);
    text-transform: uppercase; letter-spacing: 0.07em; margin-bottom: 12px;
    display: flex; align-items: center; gap: var(--space-2);
  }
  .dash-section-label strong {
    font-size: calc(20px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -0.5px;
    color: var(--text); text-transform: none; letter-spacing: -0.5px;
  }
  .dash-locations-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 20px;
  }
  .dash-location-card {
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius); padding: calc(14px * var(--sp-scale, 1)) var(--space-4);
  }
  .dash-location-header {
    display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;
  }
  .dash-location-name  { font-size: var(--fs-md); font-weight: 600; }
  .dash-location-count {
    font-size: calc(26px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -1px; color: var(--accent); line-height: 1;
  }
  .dash-show-item {
    display: flex; align-items: center; justify-content: space-between;
    padding: calc(5px * var(--sp-scale, 1)) 0; cursor: pointer; border-top: 1px solid var(--border);
    transition: opacity var(--dur-micro);
  }
  .dash-show-item:hover { opacity: 0.75; }
  .dash-show-code {
    font-size: var(--fs-base); font-weight: 600;
    font-family: var(--font-mono); color: var(--text);
  }
  .dash-kpi-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
  .dash-kpi-card {
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius); padding: calc(18px * var(--sp-scale, 1)) var(--space-5);
    display: flex; align-items: center; gap: var(--space-4);
  }
  .dash-kpi-icon {
    width: 44px; height: 44px; border-radius: 10px;
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  }
  .dash-kpi-value { font-size: calc(34px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -1.2px; line-height: 1; margin-bottom: 4px; }
  .dash-kpi-label { font-size: var(--fs-base); color: var(--text2); }

  /* ── Project overview dashboard (sin pestañas) ── */
  .project-overview-body { padding: calc(22px * var(--sp-scale, 1)) var(--space-6); overflow-y: auto; flex: 1; }
  .overview-section { margin-bottom: 26px; }
  .overview-section-title {
    font-size: var(--fs-xs); font-weight: 600; color: var(--text3);
    text-transform: uppercase; letter-spacing: 0.07em;
    display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); margin-bottom: 10px;
  }
  .shots-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: calc(10px * var(--sp-scale, 1)); }
  /* v-projects: % + barra de progreso + tarjeta "agregar" */
  .shots-row .shot-stat-card { padding: calc(15px * var(--sp-scale, 1)) calc(15px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1)); }
  .shots-row .shot-stat-value { font-size: calc(31px * var(--fs-scale, 1)); }
  .shot-stat-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
  .shot-stat-pct { font-size: var(--fs-base); font-weight: 700; }
  .shot-stat-bar { height: 4px; border-radius: var(--radius-pill); background: var(--wash-2); margin-top: 10px; overflow: hidden; }
  .shot-stat-bar > span { display: block; height: 100%; border-radius: var(--radius-pill); }
  .shot-stat-card.final-card { border-left-color: var(--accent); }
  .shot-stat-card.add-card { border: 1px dashed var(--border2); background: transparent; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: calc(6px * var(--sp-scale, 1)); color: var(--text3); cursor: pointer; text-align: center; transition: border-color var(--dur-micro), color var(--dur-micro); }
  .shot-stat-card.add-card:hover { border-color: var(--accent); color: var(--accent); }
  @media (max-width: 1000px) { .shots-row { grid-template-columns: repeat(2, 1fr); } }

  /* v-projects: botón de filtro + dropdown en la lista de proyectos */
  .proj-sidebar-head { display: flex; align-items: center; gap: var(--space-2); padding: calc(11px * var(--sp-scale, 1)) var(--space-3); border-bottom: 1px solid var(--border); flex-shrink: 0; }
  .proj-sidebar-ttl { font-size: var(--fs-md); font-weight: 600; color: var(--text2); flex: 1; }
  .proj-filter-btn { position: relative; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-xs); border: 1px solid var(--border); background: var(--card2); color: var(--text2); cursor: pointer; transition: background var(--dur-micro), color var(--dur-micro); }
  .proj-filter-btn:hover, .proj-filter-btn.active { background: rgba(var(--accent-rgb),0.16); color: var(--accent); border-color: rgba(var(--accent-rgb),0.35); }
  .proj-filter-badge { position: absolute; top: -5px; right: -5px; min-width: 15px; height: 15px; padding: 0 var(--space-1); border-radius: var(--radius-pill); background: var(--accent); color: #fff; font-size: calc(8px * var(--fs-scale, 1)); font-weight: 800; display: flex; align-items: center; justify-content: center; box-shadow: 0 0 0 2px var(--bg); }
  .proj-filter-pop { display: none; padding: var(--space-3); border-bottom: 1px solid var(--border); background: var(--bg2); flex-shrink: 0; }
  .proj-filter-pop.open { display: block; }
  .proj-filter-flabel { font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--text3); margin-bottom: 8px; }

  /* v-projects: modal ligero de shots del artista */
  .asm-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: none; align-items: center; justify-content: center; z-index: var(--z-modal); }
  .asm-backdrop.open { display: flex; }
  .asm-modal { width: min(520px, 92vw); max-height: 76vh; background: var(--card); border: 1px solid var(--border2); border-radius: var(--radius); box-shadow: var(--shadow-modal); display: flex; flex-direction: column; overflow: hidden; }
  .asm-head { display: flex; align-items: center; gap: calc(11px * var(--sp-scale, 1)); padding: calc(14px * var(--sp-scale, 1)) var(--space-4); border-bottom: 1px solid var(--border); }
  .asm-av { width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: var(--fs-sm); font-weight: 700; flex-shrink: 0; }
  .asm-nm { font-size: var(--fs-lg); font-weight: 600; flex: 1; }
  .asm-nm small { display: block; font-size: var(--fs-sm); color: var(--text3); font-weight: 400; margin-top: 1px; }
  .asm-body { overflow-y: auto; padding: calc(6px * var(--sp-scale, 1)) var(--space-4) calc(14px * var(--sp-scale, 1)); }
  .shot-stat-card {
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius); padding: calc(18px * var(--sp-scale, 1)) var(--space-5);
    border-left: 3px solid transparent;
  }
  .shot-stat-card.active-card { border-left-color: var(--green); }
  .shot-stat-card.pbda-card   { border-left-color: var(--orange); }
  .shot-stat-value { font-size: calc(38px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -1.5px; line-height: 1; }
  .shot-stat-label { font-size: var(--fs-base); color: var(--text2); margin-top: 7px; font-weight: 500; }
  .shot-stat-sub   { font-size: var(--fs-sm); color: var(--text3); margin-top: 3px; }
  .dept-artist-card {
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius); padding: calc(14px * var(--sp-scale, 1)) var(--space-4); margin-bottom: 8px;
  }
  .dept-artist-card-header {
    display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 11px;
  }
  .dept-name-badge {
    font-size: var(--fs-sm); font-weight: 700; padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1));
    border-radius: var(--radius-xs); letter-spacing: 0.04em;
  }
  .dept-count-big { font-size: calc(22px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -0.5px; margin-left: auto; }
  .artist-chips { display: flex; flex-wrap: wrap; gap: calc(5px * var(--sp-scale, 1)); }
  .artist-chip {
    display: flex; align-items: center; gap: calc(5px * var(--sp-scale, 1));
    background: var(--wash-2); border: 1px solid var(--border);
    border-radius: 20px; padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)) calc(3px * var(--sp-scale, 1)) var(--space-1);
    font-size: var(--fs-sm); color: var(--text2); white-space: nowrap;
    transition: border-color var(--dur-micro), background var(--dur-micro);
  }
  .artist-chip-clickable:hover {
    border-color: var(--border2); background: var(--wash-3);
    color: var(--text);
  }

  /* ── Modal de detalle de tareas por artista ── */
  .task-detail-table { width: 100%; border-collapse: collapse; margin-top: 6px; }
  .task-detail-table th {
    text-align: left; font-size: var(--fs-xs); font-weight: 600; color: var(--text3);
    text-transform: uppercase; letter-spacing: 0.06em;
    padding: 0 calc(10px * var(--sp-scale, 1)) var(--space-2); border-bottom: 1px solid var(--border);
  }
  .task-detail-table td {
    padding: var(--space-2) calc(10px * var(--sp-scale, 1)); font-size: var(--fs-base);
    border-bottom: 1px solid var(--wash-1); vertical-align: middle;
  }
  .task-detail-table tr:last-child td { border-bottom: none; }
  .task-detail-table tr:hover td { background: var(--wash-1); }
  .task-vfx-id {
    font-family: var(--font-mono); font-size: var(--fs-sm); font-weight: 600;
    color: var(--text);
  }
  .task-status-badge {
    font-size: var(--fs-xs); font-weight: 600; padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: 5px;
    text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap;
  }
  .task-status-wip   { background: rgba(var(--accent-rgb),0.12);  color: var(--accent); }
  .task-status-rev   { background: rgba(var(--orange-rgb),0.12);  color: var(--orange); }
  .task-status-hld   { background: rgba(var(--yellow-rgb),0.12);  color: var(--yellow); }
  .task-status-rdy   { background: rgba(var(--purple-rgb),0.12);  color: var(--purple); }
  .task-status-wtg   { background: var(--wash-2); color: var(--text3);  }
  .task-status-pbda  { background: rgba(var(--orange-rgb),0.12);  color: var(--orange); }
  /* Kickbacks (2026-08-26): los cuatro tienen color propio en FPT y hasta hoy
     compartían el cyan (kbk+mkbk) o caían en el gris de "otro" (edkbk). */
  .task-status-kbk   { background: var(--kbk-art-soft);  color: var(--kbk-art-ink); }
  .task-status-mkbk  { background: var(--kbk-sup-soft);  color: var(--kbk-sup-ink); }
  .task-status-apr   { background: rgba(var(--green-rgb),0.10);  color: var(--green); }
  .task-status-apv   { background: rgba(var(--green-rgb),0.15);  color: var(--green); }
  .task-status-ctxr  { background: rgba(var(--cyan-rgb),0.10); color: var(--cyan); }
  .task-status-cbb   { background: rgba(var(--purple-rgb),0.12); color: var(--purple); }
  .task-status-tchf  { background: rgba(var(--green-rgb),0.12);  color: var(--green);  }
  .task-status-other { background: var(--wash-2); color: var(--text2);  }
  /* ── Editorial Kickback: la única pastilla de relleno SÓLIDO ──────────────
     Ver la nota larga en :root (--kbk-ed-ring). Resumen: `edkbk` comparte el
     rojo con el estatus de error, así que no puede distinguirse por el tono —
     se distingue por el TRATAMIENTO. Relleno sólido + texto negro + aro negro,
     que es como se ve en FPT. `stck`/`tchf`/`cbb` NO llevan esto.
     PROBLEMA DEL TEMA OSCURO Y CÓMO SE RESOLVIÓ: un aro negro al ras del borde
     se ve perfecto sobre tarjeta blanca, pero sobre el fondo oscuro de la app
     desaparece — negro contra --card #1f1f23 da 1.28:1, contra --bg #121214 da
     1.12:1 — y `edkbk` volvía a ser indistinguible del rojo de error justo en
     el tema que el usuario tiene por default.
     La solución NO es aclarar el aro (dejaría de ser negro y se pierde el
     "rojo y negro" de FPT) sino ENMARCARLO con el propio rojo: 1px de #ff0101
     por FUERA del borde + el aro negro por DENTRO. Así el negro siempre queda
     entre rojo y rojo (5.26:1 de los dos lados) y su visibilidad ya no depende
     de la superficie donde caiga la pastilla — se ve idéntico en claro y en
     oscuro, y de paso el halo rojo engorda la mancha de color.
     El realce va POR FUERA (y no como un segundo `inset`) para no comerse el
     respiro interior de la pastilla, que son dos o tres puntos verticales: dos
     aros hacia adentro dejaban el texto pegado al aro. */
  .kbk-ed-aro { box-shadow: inset 0 0 0 1px var(--kbk-ed-ring), 0 0 0 1px var(--kbk-ed); }
  .task-status-edkbk { background: var(--kbk-ed); color: var(--kbk-ed-on); }
  /* ── Detalle de artista: layout con filtros laterales ── */
  .ad-layout    { flex:1; display:flex; overflow:hidden; min-height:0; }
  .ad-content   { flex:1; overflow-y:auto; padding: var(--space-5) var(--space-6); }
  .ad-filters   { width:var(--filter-aside-w); flex-shrink:0; border-left:1px solid var(--border); overflow-y:auto; padding: var(--space-4) calc(14px * var(--sp-scale, 1)); }
  .ad-filters h4 { font-size: var(--fs-xs); text-transform:uppercase; letter-spacing:0.06em; color:var(--text3); margin:0 0 8px; font-weight:700; }
  .ad-filter-group { margin-bottom:18px; }
  .ad-chips     { display:flex; flex-wrap:wrap; gap: calc(6px * var(--sp-scale, 1)); }
  .ad-chip-n    { opacity:.6; font-size: var(--fs-xs); margin-left:2px; }
  .ad-group     { margin-bottom:14px; }
  .ad-group-head { display:flex; align-items:center; gap: var(--space-2); margin:0 0 6px; padding-top: calc(2px * var(--sp-scale, 1)); }
  .ad-group-name { font-size: var(--fs-base); font-weight:600; color:var(--text2); }
  .ad-group-count { font-size: var(--fs-xs); color:var(--text3); background:var(--wash-2); border-radius:8px; padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); }
  /* ── DEV DEBUG (solo modo desarrollo) ── */
  .dev-debug-btn { position:fixed; right:16px; bottom:16px; z-index:9999; background:var(--card); color:var(--text); /* #fff era invisible en tema claro (revisión 07-29) */ border:1px solid rgba(255,255,255,0.18); border-radius:20px; padding: var(--space-2) calc(14px * var(--sp-scale, 1)); font-size: var(--fs-base); font-weight:600; cursor:pointer; box-shadow:0 4px 14px rgba(0,0,0,0.3); display:flex; align-items:center; gap: calc(6px * var(--sp-scale, 1)); }
  .dev-debug-btn.has-errors { background:rgba(var(--red-rgb),0.20); border-color:var(--red); }
  .dev-debug-badge { background:var(--red); color:#fff; border-radius:10px; padding: 0 calc(6px * var(--sp-scale, 1)); font-size: var(--fs-xs); min-width:16px; text-align:center; }
  .dev-debug-panel { position:fixed; right:16px; bottom:60px; z-index:9999; width:min(560px,92vw); max-height:70vh; background:var(--card,var(--card)); color:var(--text,#fff); border:1px solid var(--border,rgba(255,255,255,0.15)); border-radius: var(--radius); box-shadow:var(--shadow-pop); display:flex; flex-direction:column; overflow:hidden; }
  .dev-debug-head { display:flex; align-items:center; justify-content:space-between; gap: var(--space-2); padding: calc(10px * var(--sp-scale, 1)) var(--space-3); border-bottom:1px solid var(--border,rgba(255,255,255,0.12)); flex-shrink:0; }
  .dev-debug-pre { margin:0; padding: var(--space-3); overflow:auto; font-family:var(--font-mono); font-size: var(--fs-sm); line-height:1.5; white-space:pre-wrap; word-break:break-word; }
  .dev-toast { position:fixed; right:16px; bottom:110px; z-index:10000; background:var(--accent); color:#fff; padding: var(--space-2) calc(14px * var(--sp-scale, 1)); border-radius:var(--radius-sm); font-size: var(--fs-base); box-shadow:var(--shadow-pop); }
  /* Elementos visibles SOLO en modo desarrollo (VFX_Tracker_Dev.command).
     Ocultos en producción y también antes de que cargue la config (body sin clase). */
  body:not(.dev-mode) .dev-only { display: none !important; }
  /* BLINDAJE de modos: el botón/panel de Debug solo existen en desarrollo. */
  body:not(.dev-mode) .dev-debug-btn,
  body:not(.dev-mode) #dev-debug-btn,
  body:not(.dev-mode) .dev-debug-panel,
  body:not(.dev-mode) #dev-debug-panel { display: none !important; }
  /* ── Íconos de status FTP (Shots Activos) ── */
  .as-status  { display:inline-flex; align-items:center; }
  .status-icon { width:15px; height:15px; border-radius:50%; object-fit:cover; display:inline-block; vertical-align:middle; box-shadow:0 1px 3px rgba(0,0,0,0.35); }
  .artist-chip-avatar {
    width: 18px; height: 18px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: calc(8px * var(--fs-scale, 1)); font-weight: 700; flex-shrink: 0;
  }

  /* ── Project type groups in sidebar ── */
  .type-group-label {
    font-size: var(--fs-xs); font-weight: 600; color: var(--text3);
    text-transform: uppercase; letter-spacing: 0.07em;
    padding: var(--space-3) var(--space-2) var(--space-1); display: flex; align-items: center;
    justify-content: space-between;
  }
  .type-group-label:first-child { padding-top: calc(6px * var(--sp-scale, 1)); }
  .type-group-label .tg-count {
    background: var(--wash-2); color: var(--text3);
    font-size: var(--fs-xs); padding: calc(1px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); border-radius: 10px; font-weight: 600;
  }
  .project-location {
    font-size: var(--fs-sm); color: var(--text3);
    display: flex; align-items: center; gap: var(--space-1);
    margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .project-crew-mini {
    display: flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); margin-top: 6px;
  }
  .crew-dot-sm {
    width: 19px; height: 19px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: calc(8px * var(--fs-scale, 1)); font-weight: 700; flex-shrink: 0; letter-spacing: -0.2px;
  }
  .crew-role-mini { font-size: var(--fs-xs); color: var(--text3); }

  /* ── Crew section in project detail ── */
  .crew-section {
    display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: 14px;
  }
  .crew-member {
    display: flex; align-items: center; gap: calc(9px * var(--sp-scale, 1));
    background: var(--wash-2); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); flex: 1; min-width: 160px;
  }
  .crew-avatar-md {
    width: 32px; height: 32px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: var(--fs-sm); font-weight: 700; flex-shrink: 0; letter-spacing: -0.3px;
  }
  .crew-info .crew-name { font-size: var(--fs-md); font-weight: 500; }
  .crew-info .crew-role { font-size: var(--fs-sm); color: var(--text2); margin-top: 1px; }

  ::-webkit-scrollbar { width: 3px; height: 3px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb { background: var(--wash-3); border-radius: 2px; }
  ::-webkit-scrollbar-thumb:hover { background: var(--wash-4); }

  /* ══════════════════════════════════════════════
     PRESUPUESTO GENERAL — sistema de diseño completo
     ══════════════════════════════════════════════ */

  /* ── Candado ── */
  .budget-lock { display: flex; justify-content: center; padding-top: calc(48px * var(--sp-scale, 1)); }
  .budget-lock-card {
    width: 100%; max-width: 380px; text-align: center;
    background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: calc(34px * var(--sp-scale, 1)) calc(30px * var(--sp-scale, 1));
  }
  .budget-lock-icon {
    width: 56px; height: 56px; border-radius: 14px; margin: 0 auto 16px;
    background: rgba(var(--accent-rgb),0.1); color: var(--accent);
    display: flex; align-items: center; justify-content: center;
  }
  .budget-lock-card h2 { font-size: calc(17px * var(--fs-scale, 1)); font-weight: 600; }
  .budget-lock-card p  { font-size: calc(12.5px * var(--fs-scale, 1)); color: var(--text2); margin: 6px 0 18px; line-height: 1.6; }
  .budget-pass-input {
    width: 100%; background: var(--bg2); border: 1px solid var(--border2); border-radius: var(--radius-sm);
    padding: calc(11px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1)); color: var(--text); font-size: var(--fs-md); outline: none; margin-bottom: 10px;
    font-family: inherit;
  }
  .budget-pass-input:focus { border-color: var(--accent); }
  .budget-pass-error { display: none; font-size: var(--fs-base); margin-bottom: 10px; line-height: 1.5; }
  .budget-keychain-setup {
    background: rgba(var(--yellow-rgb),0.07); border: 1px solid rgba(var(--yellow-rgb),0.18);
    border-radius: var(--radius-sm); padding: var(--space-3) calc(14px * var(--sp-scale, 1)); text-align: left; margin-bottom: 14px;
    font-size: calc(11.5px * var(--fs-scale, 1)); color: var(--yellow); line-height: 1.7; display: none;
  }
  .budget-keychain-setup code {
    display: block; margin-top: 6px; background: rgba(0,0,0,0.3);
    border-radius: var(--radius-xs); padding: calc(7px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); font-family: var(--font-mono);
    font-size: var(--fs-sm); color: var(--text); word-break: break-all;
  }

  /* ── Sub-navegación dentro de Presupuesto ── */
  .budget-subnav {
    display: flex; gap: 0; border-bottom: 1px solid var(--border);
    margin: 0 -28px; padding: 0 calc(28px * var(--sp-scale, 1)); flex-shrink: 0;
  }
  /* .budget-subnav-btn comparte el componente de pestaña (.tab-btn); solo
     conserva la alineación con el borde inferior de su contenedor. */
  .budget-subnav-btn { margin-bottom: -1px; }

  /* ── Artistas: subnav de tabs (Global / 2D / 3D) — segmented control ── */
  .artists-subnav { display: inline-flex; align-self: flex-start; gap: calc(2px * var(--sp-scale, 1)); background: var(--wash-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: calc(3px * var(--sp-scale, 1)); flex-shrink: 0; margin: 14px 24px 0; }
  /* Fila del subnav + toggle de densidad (Artistas) */
  .artists-subnav-row { display: flex; align-items: center; gap: var(--space-3); margin: 14px 24px 0; }
  .artists-subnav-row .artists-subnav { margin: 0; }
  .artists-subnav-row .as-density-seg { margin-left: auto; }
  /* Títulos de sección por depto: pegajosos para no perder el agrupado al hacer scroll */
  #page-artists .dept-ov-sec-title { position: sticky; top: 0; z-index: 5; background: var(--bg); padding: var(--space-2) 0; margin: 0 0 11px; border-bottom: 1px solid var(--border); }
  /* ── Densidad COMPACTA (solo presentación; agrupado y filtros intactos) ── */
  #page-artists.density-compact .dept-art-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 196px), 1fr)); gap: calc(6px * var(--sp-scale, 1)); }
  #page-artists.density-compact .dept-art-head { padding: calc(7px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); gap: calc(6px * var(--sp-scale, 1)); }
  #page-artists.density-compact .dept-art-name { font-size: var(--fs-base); }
  #page-artists.density-compact .dept-art-pills { display: none; }
  #page-artists.density-compact .dept-art-loadbar { display: none; }
  #page-artists.density-compact .dept-art-card { border-top: 2px solid var(--bdc, var(--border)); }
  #page-artists.density-compact .dept-art-metrics { gap: var(--space-2); }
  #page-artists.density-compact .dept-art-metric { min-width: 0; }
  #page-artists.density-compact .dept-art-metric .m-val { font-size: calc(12.5px * var(--fs-scale, 1)); }
  #page-artists.density-compact .dept-art-metric .m-lbl { display: none; }
  #page-artists.density-compact .dept-art-chev { width: 10px; height: 10px; }
  #page-artists.density-compact .dept-art-eye-inline { opacity: 0; transition: opacity var(--dur-micro) var(--ease-out); }
  #page-artists.density-compact .dept-art-card:hover .dept-art-eye-inline { opacity: 1; }
  .artists-subnav-btn {
    padding: calc(6px * var(--sp-scale, 1)) var(--space-4); font-size: calc(12.5px * var(--fs-scale, 1)); font-weight: 600;
    background: transparent; border: none; color: var(--text2);
    cursor: pointer; border-radius: 7px; transition: background var(--dur-fast), color var(--dur-fast); font-family: inherit;
  }
  .artists-subnav-btn:hover  { color: var(--text); }
  .artists-subnav-btn.active { color: var(--text); background: var(--card); box-shadow: 0 1px 2px rgba(0,0,0,.3); }
  .artists-tab { min-height: 0; }

  /* ── Artistas v2: píldoras de proyecto + vendor + slide-over ── */
  .dept-art-pills { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-left: auto; justify-content: flex-end; min-width: 0; overflow: hidden; }
  .dept-art-pill { font-size: var(--fs-xs); font-weight: 600; color: var(--text2); background: var(--wash-2); border: 1px solid var(--border); padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: var(--radius-pill); white-space: nowrap; }
  .dept-art-card.is-vendor { border-left: 2px solid var(--cyan); }
  .dept-art-vendortag { display: inline-flex; align-items: center; gap: calc(3px * var(--sp-scale, 1)); font-size: var(--fs-2xs); font-weight: 700; color: var(--cyan); background: rgba(var(--cyan-rgb),0.12); border-radius: 8px; padding: calc(1px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); letter-spacing: .03em; flex-shrink: 0; }
  /* Ojo de ocultar (solo Global): centrado a la derecha, ghost (recuadro solo en hover) */
  .dept-art-eye { position: absolute; top: 50%; right: 8px; transform: translateY(-50%); z-index: 2; border: 1px solid transparent !important; }
  .dept-art-eye:hover { border-color: var(--border2) !important; }
  /* Ojo en la fila de métricas, alineado a la flecha (chevron). 20% menor con +10% en el icono. */
  .dept-art-eye-inline { width: 21px; height: 21px; flex-shrink: 0; }
  .dept-art-eye-inline svg { width: 11px; height: 11px; }
  /* el chevron ya no rota (abre slide-over en vez de expandir) */
  .dept-shot-chip { cursor: pointer; transition: border-color var(--dur-micro), background var(--dur-micro), transform var(--dur-micro); }
  .dept-shot-chip:hover { border-color: var(--accent); background: var(--wash-3); transform: translateY(-1px); }

  /* Slide-over de detalle del artista */
  .aso-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.45); opacity: 0; pointer-events: none; transition: opacity var(--dur-base); z-index: var(--z-backdrop); }
  .aso-backdrop.open { opacity: 1; pointer-events: auto; }
  .aso-panel { position: fixed; top: 0; right: 0; height: 100%; width: min(430px, 94vw); background: var(--bg2); border-left: 1px solid var(--border2); box-shadow: -24px 0 64px rgba(0,0,0,0.5); transform: translateX(100%); transition: transform var(--dur-base) var(--ease-out); z-index: var(--z-panel); display: flex; flex-direction: column; }
  .aso-panel.open { transform: translateX(0); }
  .aso-head { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4) calc(18px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); }
  .aso-av { width: 40px; height: 40px; border-radius: var(--radius); display: flex; align-items: center; justify-content: center; font-size: var(--fs-lg); font-weight: 700; flex-shrink: 0; }
  .aso-name { font-size: calc(15px * var(--fs-scale, 1)); font-weight: 700; }
  .aso-role { font-size: var(--fs-sm); color: var(--text3); margin-top: 1px; }
  /* Unificación de cierres 2026-07-29: el botón es ya el .close-btn global —
     solo se conserva el posicionamiento (empujado a la derecha del header). */
  .aso-head .close-btn { margin-left: auto; }
  .aso-body { flex: 1; overflow-y: auto; padding: var(--space-4) calc(18px * var(--sp-scale, 1)); }
  .aso-kpis { display: flex; gap: var(--space-2); margin-bottom: 18px; }
  .aso-kpi { flex: 1; background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-xs); padding: calc(10px * var(--sp-scale, 1)) var(--space-3); text-align: center; }
  .aso-kpi .v { font-size: var(--fs-kpi); font-weight: 700; line-height: 1; }
  .aso-kpi .l { font-size: var(--fs-2xs); color: var(--text3); text-transform: uppercase; letter-spacing: .04em; margin-top: 3px; }
  .aso-sec { margin-bottom: 16px; }
  .aso-sec-h { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text3); margin-bottom: 9px; }
  .aso-sec.warn { background: rgba(var(--orange-rgb),0.07); border: 1px solid rgba(var(--orange-rgb),0.22); border-radius: var(--radius-sm); padding: var(--space-3); }
  .aso-sec.warn .aso-sec-h { color: var(--orange); }

  /* ── Vista por departamento (2D / 3D) ── */
  /* Sección de KPIs ~10% más compacta (a pedido) */
  .dept-ov-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(116px, 1fr)); gap: calc(11px * var(--sp-scale, 1)); margin-bottom: 16px; }
  .dept-ov-kpi { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: var(--space-3) calc(14px * var(--sp-scale, 1)); min-width: 0; }
  .dept-ov-kpi .lbl { font-size: var(--fs-xs); color: var(--text2); font-weight: 600; letter-spacing: .3px; line-height: 1.3; min-width: 0; }
  .dept-ov-kpi .val { font-size: var(--fs-kpi); font-weight: 700; letter-spacing: -1px; line-height: 1; white-space: nowrap; flex-shrink: 0; }
  .dept-ov-sec-title { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-md); font-weight: 600; color: var(--text); margin: 4px 0 11px; }
  .dept-ov-sec-title .n { font-size: var(--fs-sm); color: var(--text3); font-weight: 500; }

  .dept-art-card { position: relative; border: 1px solid var(--border); border-radius: var(--radius-sm); margin-bottom: 9px; overflow: hidden; background: var(--card); }
  /* Tarjeta de artista en DOS filas: fila 1 = nombre (1fr) + acciones; fila 2 = métricas + proyectos.
     Da al nombre el ancho completo de la tarjeta para que se lea aunque sea largo. */
  .dept-art-head { display: grid; grid-template-rows: auto auto; gap: calc(9px * var(--sp-scale, 1)); padding: calc(11px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1)); cursor: pointer; transition: background var(--dur-micro); }
  .dept-art-head:hover { background: var(--card2); }
  .dept-art-id { min-width: 0; }
  .dept-art-toprow { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: var(--space-2); min-width: 0; }
  .dept-art-actions { display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); flex-shrink: 0; color: var(--text3); }
  .dept-art-meta { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
  .dept-art-name { font-size: var(--fs-md); font-weight: 600; color: var(--text); display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
  .dept-art-nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
  .dept-art-deptbadge { font-size: var(--fs-xs); font-weight: 600; color: var(--text3); background: var(--wash-3); padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: 10px; flex-shrink: 0; }
  .dept-art-codes { font-size: var(--fs-sm); color: var(--text3); margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dept-art-metrics { display: flex; align-items: center; gap: calc(14px * var(--sp-scale, 1)); flex-shrink: 0; }
  .dept-art-metric { display: flex; align-items: baseline; gap: var(--space-1); }
  .dept-art-metric .m-val { font-size: calc(14.4px * var(--fs-scale, 1)); font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
  .dept-art-metric .m-lbl { font-size: var(--fs-2xs); color: var(--text3); text-transform: uppercase; letter-spacing: .04em; }
  .dept-art-bar { width: 84px; height: 6px; background: var(--wash-3); border-radius: 4px; overflow: hidden; flex-shrink: 0; }
  .dept-art-bar > span { display: block; height: 100%; border-radius: 4px; }
  .dept-art-chev { color: var(--text3); transition: transform var(--dur-fast); flex-shrink: 0; }
  .dept-art-card.open .dept-art-chev { transform: rotate(90deg); }
  .dept-art-shots { display: none; padding: 0 calc(13px * var(--sp-scale, 1)) var(--space-3); border-top: 1px solid var(--border); }
  .dept-art-card.open .dept-art-shots { display: block; }
  .dept-art-shots-group { margin-top: 10px; }
  .dept-art-shots-group .g-lbl { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text3); margin-bottom: 6px; }
  .dept-shot-chips { display: flex; flex-wrap: wrap; gap: calc(5px * var(--sp-scale, 1)); }
  .dept-shot-chip { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); font-size: var(--fs-sm); color: var(--text); background: var(--wash-2); border: 1px solid var(--border); padding: calc(2px * var(--sp-scale, 1)) var(--space-2); border-radius: 11px; }
  .dept-art-open-link { font-size: var(--fs-sm); color: var(--accent); text-decoration: none; margin-top: 10px; display: inline-block; }
  .dept-art-open-link:hover { text-decoration: underline; }

  .dept-sup-row { display: grid; grid-template-columns: 1fr 1fr auto; gap: calc(10px * var(--sp-scale, 1)); align-items: center; padding: var(--space-2) var(--space-3); border-top: 1px solid var(--border); font-size: var(--fs-base); }
  .dept-sup-row:first-child { border-top: none; }
  .dept-sup-shot { font-weight: 600; color: var(--text); }
  .dept-sup-meta { color: var(--text3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Densidad: tarjetas de artista a ~50% (2 columnas) */
  .dept-art-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: calc(9px * var(--sp-scale, 1)); }
  .dept-art-grid .dept-art-card { margin-bottom: 0; }
  .dept-art-loadbar { height: 4px; background: var(--wash-2); }
  .dept-art-loadbar > span { display: block; height: 100%; }
  .dept-art-card.is-hidden { opacity: .55; }
  .dept-eye { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; border: none; border-radius: var(--radius-xs); background: transparent; color: var(--text2); cursor: pointer; flex-shrink: 0; transition: background var(--dur-micro), color var(--dur-micro); }
  .dept-eye:hover { background: var(--wash-3); color: var(--text); }
  .dept-hidden-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: calc(5px * var(--sp-scale, 1)) 0; font-size: var(--fs-base); color: var(--text2); }
  .dept-flt-label { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text3); margin: 14px 0 9px; }
  .dept-flt-label:first-child { margin-top: 0; }

  /* ── Dashboard grid de proyectos ── */
  .budget-projects-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
    gap: var(--space-3); padding: var(--space-5) 0;
  }
  .budget-project-card {
    background: var(--card); border: 1px solid var(--border); border-radius: 14px;
    cursor: pointer; transition: border-color var(--dur-fast), transform var(--dur-micro);
    display: flex; flex-direction: column; overflow: hidden;
  }
  .budget-project-card:hover {
    border-color: var(--border2);
    transform: translateY(-1px);
  }
  .bpc-ia-btn.on {
    background: rgba(var(--purple-rgb),0.14); border-color: rgba(var(--purple-rgb),0.45); color: var(--purple);
  }
  .budget-project-card.is-hidden { opacity: 0.5; }
  .budget-project-card.is-hidden:hover { opacity: 0.75; }
  .budget-projects-toolbar { display: flex; justify-content: space-between; align-items: center; gap: var(--space-2); padding: var(--space-1) 0 0; flex-wrap: wrap; }
  .budget-projects-note { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale,1)); font-size: var(--fs-xs); color: var(--text3); }
  .budget-projects-note svg { flex: none; }
  .budget-projects-ctrls { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }
  .bpc-stat .bpc-stat-value.ok  { color: var(--green); }
  .bpc-stat .bpc-stat-value.neg { color: var(--red); }
  .bpc-risk .dot { width: calc(7px * var(--sp-scale,1)); height: calc(7px * var(--sp-scale,1)); border-radius: 50%; flex: none; }
  .bpc-risk.ok       { background: var(--green-soft);  color: var(--green); }
  .bpc-risk.ok .dot  { background: var(--green); }
  .bpc-risk.alerta      { background: var(--orange-soft); color: var(--orange); }
  .bpc-risk.alerta .dot { background: var(--orange); }
  .bpc-risk.critico .dot { background: var(--red); }
  .bpc-risk.fx, .bpc-risk.nodata           { background: var(--wash-2); color: var(--text3); }
  .bpc-risk.fx .dot, .bpc-risk.nodata .dot { background: var(--text3); }
  .bpc-margin.ok { color: var(--green); }
  .bpc-burn-track .s-vendor  { background: rgba(var(--purple-rgb), 0.62); }
  .bpc-burn-track .s-ot      { background: rgba(var(--cyan-rgb),   0.62); }

  /* ── Detalle de proyecto ── */
  #budget-project-detail { display: none; }
  .bdetail-back {
    display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1));
    background: var(--wash-2); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: calc(6px * var(--sp-scale, 1)) var(--space-3); font-size: var(--fs-base); font-weight: 500;
    color: var(--text2); cursor: pointer; font-family: inherit; transition: all var(--dur-micro);
    white-space: nowrap; flex-shrink: 0;
  }
  .bdetail-back:hover { background: var(--wash-4); color: var(--text); }
  .bhero-fx.warn { color: var(--orange); background: var(--orange-soft); }
  .aso-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--border); font-size: var(--fs-base); }
  .aso-row-k { color: var(--text2); }
  .aso-row-v { font-variant-numeric: tabular-nums; font-weight: 600; }
  .aso-note { font-size: var(--fs-base); color: var(--text3); margin: 0 0 10px; }
  .bkpi-income .revenue-input { width: 84px; max-width: 84px; background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-xs); color: var(--text); padding: var(--space-1) calc(7px * var(--sp-scale, 1)); font-size: var(--fs-sm); font-family: inherit; }
  .bkpi-income .revenue-currency-select { background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-xs); color: var(--text); padding: var(--space-1) calc(5px * var(--sp-scale, 1)); font-size: var(--fs-sm); font-family: inherit; }
  .bdtab.active { color: var(--accent); border-bottom-color: var(--accent); }
  .bdpanel.active { display: block; }
  /* Vendors por episodio (estilo mockup) */
  .vepg { border: 1px solid var(--border); border-radius: var(--radius-sm); margin-bottom: var(--space-2); overflow: hidden; }
  .vepg-h { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); width: 100%; padding: calc(11px * var(--sp-scale,1)) var(--space-4); background: var(--wash-1); border: none; color: inherit; font-family: inherit; font-size: var(--fs-base); cursor: pointer; text-align: left; }
  .vepg-h:hover { background: var(--wash-2); }
  .vepg-t { font-weight: 650; display: flex; align-items: center; gap: calc(9px * var(--sp-scale,1)); }
  .vepg-chev { color: var(--text3); transition: transform var(--dur-fast); display: inline-block; }
  .vepg.open .vepg-chev { transform: rotate(90deg); }
  .vepg-sub { font-weight: 700; font-variant-numeric: tabular-nums; }
  .vepg-body { display: none; }
  .vepg.open .vepg-body { display: block; }
  .vep-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: calc(9px * var(--sp-scale,1)) var(--space-4); border-top: 1px solid var(--border); font-size: var(--fs-base); }
  .vep-nm { font-weight: 550; }
  .vep-code { color: var(--text3); font-size: var(--fs-sm); }
  .vep-dec { color: var(--text3); font-size: var(--fs-sm); font-family: ui-monospace, monospace; margin-top: 2px; }
  .vep-amt { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
  .vep-none { background: var(--accent-soft); color: var(--accent); font-size: var(--fs-2xs); font-weight: 700; padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: var(--radius-xs); }
  /* KPI Hold / Reserva: acento morado (reserva) — fiel al mockup */
  #split-hold-value { color: var(--purple); }
  /* Botón de configuración (engrane) en la cabecera del Presupuesto */
  .budget-cfg-btn { padding-left: var(--space-2); padding-right: var(--space-2); }
  @media (max-width: 820px) { }

  /* ── Editores del hero (ingreso / reserva) ── */
  .revenue-currency-select {
    background: var(--wash-2); border: 1px solid var(--border);
    border-radius: var(--radius-xs); color: var(--text2); font-size: var(--fs-base); font-weight: 600;
    padding: var(--space-1) var(--space-2); outline: none; cursor: pointer; font-family: inherit;
  }
  .util-pct-input {
    width: 56px; background: var(--card); border: 1px solid var(--border2); border-radius: var(--radius-xs);
    color: var(--text); font-size: var(--fs-base); font-weight: 600; padding: calc(3px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); outline: none; text-align: right;
  }
  .util-pct-input:focus { border-color: var(--green); }

  /* ── Importador de Bids (dropzone + lista) ── */
  .bid-dropzone {
    border: 1.5px dashed var(--border2); border-radius: 10px;
    padding: var(--space-6) var(--space-5); text-align: center;
    cursor: pointer; transition: border-color var(--dur-fast), background var(--dur-fast);
    background: var(--wash-1);
  }
  .bid-dropzone:hover, .bid-dropzone.dragging {
    border-color: var(--accent); background: rgba(var(--accent-rgb),0.05);
  }
  .bid-dropzone-icon { color: var(--text3); margin-bottom: 8px; }
  .bid-dropzone p { font-size: var(--fs-md); color: var(--text2); }
  .bid-dropzone small { font-size: var(--fs-sm); color: var(--text3); margin-top: 3px; display: block; }
  .bid-dropzone input[type=file] { display: none; }

  .bid-list { margin-top: 14px; display: flex; flex-direction: column; gap: calc(6px * var(--sp-scale, 1)); }
  .bid-row {
    display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1));
    background: var(--card2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: calc(10px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1));
    transition: border-color var(--dur-micro);
  }
  .bid-row:hover { border-color: var(--border2); }
  .bid-row.inactive { opacity: 0.45; }
  .bid-row-icon {
    width: 30px; height: 30px; border-radius: 7px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
  }
  .bid-row-icon.xlsx { background: rgba(var(--green-rgb),0.12); color: var(--green); }
  .bid-row-icon.csv  { background: rgba(var(--accent-rgb),0.12); color: var(--accent); }
  .bid-row-info { flex: 1; min-width: 0; }
  .bid-row-name {
    font-size: var(--fs-md); font-weight: 500;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .bid-row-meta { font-size: var(--fs-sm); color: var(--text2); margin-top: 2px; }
  .bid-version-badge {
    font-size: var(--fs-xs); font-weight: 700; padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: 5px;
    font-family: var(--font-mono); flex-shrink: 0;
    text-transform: uppercase; letter-spacing: 0.04em;
  }
  .bid-version-badge.active   { background: rgba(var(--green-rgb),0.14); color: var(--green); }
  .bid-version-badge.inactive { background: var(--wash-2); color: var(--text3); }
  .bid-amount-tag {
    font-size: var(--fs-base); font-weight: 600; color: var(--text); flex-shrink: 0;
    padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); background: var(--wash-2); border-radius: var(--radius-xs);
    border: 1px solid var(--border);
  }
  .bid-amount-tag.loading { color: var(--text3); font-weight: 400; font-size: var(--fs-sm); }
  .bid-delete-btn {
    width: 26px; height: 26px; border-radius: var(--radius-xs); flex-shrink: 0;
    background: none; border: none; color: var(--text3); cursor: pointer;
    display: flex; align-items: center; justify-content: center; transition: all var(--dur-micro);
  }
  .bid-delete-btn:hover { background: rgba(var(--red-rgb),0.12); color: var(--red); }

  /* ── Sección 3: Nómina ── */
  .payroll-header-row {
    display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px;
  }
  .payroll-total-chip {
    font-size: var(--fs-base); font-weight: 600; color: var(--purple);
    background: rgba(var(--purple-rgb),0.1); border: 1px solid rgba(var(--purple-rgb),0.2);
    border-radius: 7px; padding: calc(5px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1));
  }
  .payroll-table-wrap { overflow-x: auto; }
  .payroll-table { width: 100%; border-collapse: collapse; }
  .payroll-table th {
    font-size: var(--fs-xs); font-weight: 600; color: var(--text3); text-transform: uppercase;
    letter-spacing: 0.06em; padding: 0 calc(10px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border);
    text-align: left; white-space: nowrap;
  }
  .payroll-table td {
    padding: calc(9px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); font-size: var(--fs-md);
    border-bottom: 1px solid var(--wash-1); vertical-align: middle;
  }
  .payroll-table tr:last-child td { border-bottom: none; }
  .payroll-table tr:hover td { background: var(--wash-1); }
  .payroll-alloc-badge {
    font-size: var(--fs-sm); font-weight: 600; padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: 5px;
    background: rgba(var(--purple-rgb),0.12); color: var(--purple);
  }
  .payroll-cost { font-weight: 600; color: var(--text); }
  .payroll-empty {
    text-align: center; padding: var(--space-7) var(--space-5);
    font-size: var(--fs-base); color: var(--text3);
  }

  /* ── Modal para agregar artista a nómina ── */
  #payroll-modal .modal { width: 500px; }

  /* ── Sección 4: Historial de versiones ── */
  .bid-version-history { display: flex; flex-direction: column; gap: 0; }
  .bvh-vendor-label .vendor-code-pill {
    font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700;
    background: rgba(var(--accent-rgb),0.1); color: var(--accent);
    border: 1px solid rgba(var(--accent-rgb),0.2); border-radius: 5px; padding: calc(1px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1));
  }
  .bvh-vendor-group.collapsed .bvh-chevron { transform: rotate(-90deg); }
  .bvh-vendor-group.collapsed .bvh-rows { display: none; }

  /* ── Base de datos de Vendors ── */
  .vendors-toolbar {
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--space-4) 0 calc(14px * var(--sp-scale, 1)); flex-shrink: 0;
  }
  .vendors-toolbar h2 { font-size: calc(16px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -0.3px; }
  .vendors-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(260px,1fr)); gap: calc(10px * var(--sp-scale, 1));
  }
  .vendor-card {
    background: var(--card); border: 1px solid var(--border); border-radius: var(--radius);
    padding: calc(14px * var(--sp-scale, 1)) var(--space-4); display: flex; flex-direction: column; gap: var(--space-2);
    transition: border-color var(--dur-micro);
  }
  .vendor-card:hover { border-color: var(--border2); }
  .vendor-card-top { display: flex; align-items: center; gap: calc(11px * var(--sp-scale, 1)); }
  .vendor-icon {
    width: 36px; height: 36px; border-radius: var(--radius-sm); flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: var(--fs-base); font-weight: 700; letter-spacing: -0.3px;
  }
  .vendor-icon.studio   { background: rgba(var(--accent-rgb),0.12); color: var(--accent); }
  .vendor-icon.artista  { background: rgba(var(--purple-rgb),0.12); color: var(--purple); }
  .vendor-card-name { font-size: var(--fs-md); font-weight: 600; line-height: 1.3; }
  .vendor-card-code {
    font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700;
    background: var(--wash-2); color: var(--text2); border-radius: 4px;
    padding: calc(1px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); display: inline-block; margin-top: 2px;
  }
  .vendor-card-meta { font-size: var(--fs-sm); color: var(--text2); }
  .vendor-card-footer {
    display: flex; align-items: center; justify-content: space-between;
    border-top: 1px solid var(--border); padding-top: var(--space-2); margin-top: 2px;
  }
  .vendor-bid-count { font-size: var(--fs-sm); color: var(--text3); }
  .vendor-actions { display: flex; gap: var(--space-1); }
  .vendor-btn {
    width: 26px; height: 26px; border-radius: var(--radius-xs);
    background: none; border: none; color: var(--text3); cursor: pointer;
    display: flex; align-items: center; justify-content: center; transition: all var(--dur-micro);
  }
  .vendor-btn:hover { background: var(--wash-3); color: var(--text); }
  .vendor-btn.del:hover { background: rgba(var(--red-rgb),0.12); color: var(--red); }
  .vendors-empty {
    grid-column: 1/-1; padding: calc(60px * var(--sp-scale, 1)) var(--space-5); text-align: center;
    color: var(--text3); font-size: var(--fs-md);
  }
  /* Presupuesto: controles del header del detalle a un tamaño uniforme (misma altura + tipografía) */
  /* Controles NO-botón del header alineados a las MÉTRICAS del botón global .btn-sm
     (mismo padding/font/radio). REGLA: no hardcodear altura ni pisar .btn — el
     botón (Reset) conserva su tamaño global .btn-sm intacto. */
  .bdetail-header .bdetail-back,
  .bdetail-header .budget-cur-select,
  .bdetail-header .bfx-chip {
    display: inline-flex; align-items: center;
    padding: calc(5px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1));
    font-size: var(--fs-base); border-radius: var(--btn-radius, var(--radius-xs));
  }
  .budget-cur-select {
    background: var(--wash-2); border: 1px solid var(--border2); color: var(--text);
    outline: none; font-family: inherit; cursor: pointer;
  }
  /* Presupuesto: header del detalle alineado — código + tag juntos, grupo moneda/FX agrupado (notas del mockup) */
  .bdetail-header-spacer { flex: 1; }
  /* Presupuesto: la tabla de transparencia vive en una tarjeta (lectura, fiel al mockup) */
  #bdetail-transparency { border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--card2); padding: var(--space-4); }
  .bhold-edit .util-pct-input { width: 42px; background: transparent; border: none; color: var(--text); font-size: var(--fs-sm); font-weight: 700; text-align: center; font-variant-numeric: tabular-nums; outline: none; padding: 0 calc(3px * var(--sp-scale, 1)); font-family: inherit; -moz-appearance: textfield; appearance: textfield; }
  .bhold-edit .util-pct-input::-webkit-outer-spin-button,
  .bhold-edit .util-pct-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

  /* ── Presupuesto: slide-over (reusa .aso-panel) — notas, acciones ── */
  .bso-note { font-size: var(--fs-sm); color: var(--text3); line-height: 1.5; margin: 0 0 var(--space-3); }
  .bso-note b { color: var(--text2); }
  .bso-actions { display: flex; gap: var(--space-2); margin-top: var(--space-4); }

  /* ── Editor FX (filas "1 USD = X") en el slide-over ── */
  .bfx-erow {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
    padding: calc(10px * var(--sp-scale, 1)) 0; border-bottom: 1px solid var(--border);
  }
  .bfx-erow label { color: var(--text2); font-weight: 600; font-size: var(--fs-base); }
  .bfx-erow > div { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); }
  .bfx-erow b { color: var(--text); font-weight: 600; font-size: var(--fs-base); }
  .bfx-eq { color: var(--text3); font-size: var(--fs-sm); }
  .bfx-erow input {
    width: 96px; background: var(--card); border: 1px solid var(--border2); color: var(--text);
    border-radius: var(--radius-xs); padding: calc(6px * var(--sp-scale, 1)) var(--space-2);
    font-size: var(--fs-base); text-align: right; outline: none; font-family: inherit;
  }
  .bfx-erow input:focus { border-color: var(--accent); }
  .bfx-daily {
    margin-top: calc(14px * var(--sp-scale, 1)); width: 100%;
    background: var(--accent-soft); border: 1px solid var(--accent-border); color: var(--accent);
    border-radius: var(--radius-sm); padding: calc(9px * var(--sp-scale, 1)); font-weight: 650; font-size: var(--fs-base);
    cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  }
  .bfx-daily:hover { filter: brightness(1.04); }
  .bfx-save {
    flex: 1; background: var(--accent); border: none; color: #fff;
    border-radius: var(--radius-sm); padding: calc(9px * var(--sp-scale, 1)); font-weight: 650; font-size: var(--fs-base);
    cursor: pointer; font-family: inherit;
  }
  .bfx-save:hover { background: var(--accent-hover); }
  .bfx-cancel {
    flex: 1; background: var(--wash-2); border: 1px solid var(--border); color: var(--text2);
    border-radius: var(--radius-sm); padding: calc(9px * var(--sp-scale, 1)); font-weight: 600; font-size: var(--fs-base);
    cursor: pointer; font-family: inherit;
  }
  .bfx-cancel:hover { color: var(--text); border-color: var(--border2); }

  /* ── Configuración: barra de pestañas del slide-over ── */
  .bcfg-tabs { display: flex; gap: var(--space-1); border-bottom: 1px solid var(--border); margin-bottom: calc(14px * var(--sp-scale, 1)); }
  .bcfg-tab {
    background: none; border: none; padding: var(--space-2) var(--space-3); color: var(--text2);
    font-weight: 600; font-size: var(--fs-base); border-bottom: 2px solid transparent; cursor: pointer; font-family: inherit;
  }
  .bcfg-tab:hover { color: var(--text); }
  .bcfg-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
  .vdb-group.collapsed .vdb-group-chevron { transform: rotate(-90deg); }
  .vdb-group.collapsed .vdb-table { display: none; }
  .vdb-table .vendor-btn { width: 24px; height: 24px; }
  /* ── Importar reporte de proyectos: drag & drop ── */
  .pimport-dropzone {
    border: 1.5px dashed var(--border2); border-radius: var(--radius);
    padding: calc(30px * var(--sp-scale, 1)) var(--space-5); text-align: center; cursor: pointer;
    display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
    transition: border-color var(--dur-fast), background var(--dur-fast);
  }
  .pimport-dropzone:hover { border-color: var(--accent); background: rgba(var(--accent-rgb),0.04); }
  .pimport-dropzone.dragover { border-color: var(--accent); background: rgba(var(--accent-rgb),0.08); }
  .pimport-dz-title { font-size: var(--fs-md); font-weight: 600; color: var(--text); }
  .pimport-dz-sub { font-size: var(--fs-sm); color: var(--text3); }
  .pimport-result { border: 1px solid var(--border); border-radius: 10px; padding: var(--space-3) calc(14px * var(--sp-scale, 1)); font-size: calc(12.5px * var(--fs-scale, 1)); }
  .pimport-result h4 { font-size: var(--fs-base); font-weight: 700; margin: 0 0 8px; }
  .pimport-row { display: flex; justify-content: space-between; gap: calc(10px * var(--sp-scale, 1)); padding: calc(3px * var(--sp-scale, 1)) 0; color: var(--text2); }
  .pimport-row b { color: var(--text); font-weight: 600; }
  .pimport-warn { color: var(--orange); font-size: var(--fs-base); margin-top: 8px; padding: var(--space-2) calc(10px * var(--sp-scale, 1)); background: rgba(var(--orange-rgb),0.08); border-radius: 8px; }
  .pimport-err  { color: var(--red); font-size: var(--fs-base); padding: calc(10px * var(--sp-scale, 1)) var(--space-3); background: rgba(var(--red-rgb),0.08); border: 1px solid rgba(var(--red-rgb),0.25); border-radius: 8px; }
  /* ── Resumen de Vendors / Freelance ── */
  .vsum-head { font-size: var(--fs-base); font-weight: 700; color: var(--text); margin-bottom: 8px; }
  .vsum-row.mixed { border-color: rgba(var(--orange-rgb),0.5); background: rgba(var(--orange-rgb),0.06); }
  .vbk-project:not(.collapsed) > .vbk-project-head > .vbk-chevron,
  .vbk-vendor:not(.collapsed)  > .vbk-vendor-head  > .vbk-chevron { transform: rotate(90deg); }
  .vbk-project.collapsed .vbk-project-body, .vbk-vendor.collapsed .vbk-vendor-body { display: none; }
  .vbk-table th.num, .vbk-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
  .vbk-subtotal-row td.num { color: var(--text); font-weight: 700; }
  .vbk-cur.mxn { color: var(--green); background: rgba(var(--green-rgb),0.12); border: 1px solid rgba(var(--green-rgb),0.22); }
  .vbk-cur.usd { color: var(--accent); background: rgba(var(--accent-rgb),0.12); border: 1px solid rgba(var(--accent-rgb),0.22); }
  .vbk-cur.eur { color: var(--purple); background: rgba(var(--purple-rgb),0.12); border: 1px solid rgba(var(--purple-rgb),0.22); }
  .vbk-cur.other { color: var(--text2); background: var(--wash-2); border: 1px solid var(--border); }
  .vbk-table4 th.num, .vbk-table4 td.num { text-align: right; font-variant-numeric: tabular-nums; }

  /* ── Modal de vendor ── */
  #vendor-modal .modal { width: 420px; }

  /* ══════════════════════════════════════════════════════════
     CALENDARIO
  ══════════════════════════════════════════════════════════ */

  /* Layout principal: dos columnas */
  #page-calendar .page-body {
    padding: 0; overflow: hidden;
    display: flex; flex-direction: row;
  }
  .cal-main {
    flex: 1; min-width: 0; overflow: hidden;
    display: flex; flex-direction: column;
  }

  /* KPIs */
  .cal-kpis { display: flex; gap: var(--space-2); padding: calc(14px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1)) 0; flex-shrink: 0; flex-wrap: wrap; }
  .cal-kpi {
    flex: 1; min-width: 90px; background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: calc(10px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1));
  }
  .cal-kpi-value { font-size: var(--fs-kpi); font-weight: 700; letter-spacing: -0.5px; }
  .cal-kpi-label { font-size: var(--fs-xs); color: var(--text2); margin-top: 2px; }

  /* Barra de navegación principal.
     flex-wrap: en ventanas angostas los grupos (Agrupar/densidad/vista) bajan a
     una segunda fila en vez de recortarse contra el panel de filtros (fix 2026-07-02). */
  .cal-nav-bar {
    display: flex; align-items: center; gap: var(--space-2); row-gap: var(--space-2); padding: calc(10px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1));
    border-bottom: 1px solid var(--border); flex-shrink: 0; flex-wrap: wrap;
  }
  .cal-nav-bar > * { flex-shrink: 0; }   /* ningún grupo se comprime: envuelven completos */
  .cal-week-nav {
    display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1));
    font-size: var(--fs-md); font-weight: 600; color: var(--text);
  }
  .cal-week-nav button {
    width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-xs); border: 1px solid var(--border);
    background: var(--card2); color: var(--text2); cursor: pointer; transition: background var(--dur-micro);
  }
  .cal-week-nav button:hover { background: var(--wash-3); color: var(--text); }
  .cal-btn {
    display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
    height: 26px; padding: 0 calc(10px * var(--sp-scale, 1)); border-radius: var(--radius-xs);
    border: 1px solid var(--border); background: var(--card2);
    color: var(--text2); font-size: var(--fs-sm); cursor: pointer; white-space: nowrap; line-height: 1;
    transition: background var(--dur-micro), color var(--dur-micro), border-color var(--dur-micro);
  }
  .cal-btn svg, .cal-btn i { flex-shrink: 0; }
  .cal-btn:hover { background: var(--wash-3); color: var(--text); }
  .cal-btn.active { background: rgba(var(--accent-rgb),0.14); border-color: rgba(var(--accent-rgb),0.35); color: var(--accent); }
  /* Control segmentado canónico (pill) — unificado en toda la app */
  .cal-view-toggle { display: inline-flex; align-items: center; gap: calc(2px * var(--sp-scale, 1)); height: 26px; box-sizing: border-box; background: var(--wash-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: calc(2px * var(--sp-scale, 1)); }
  .cal-view-toggle button {
    height: 20px; padding: 0 calc(11px * var(--sp-scale, 1)); background: transparent; border: none; border-radius: var(--radius-xs);
    color: var(--text2); font-size: var(--fs-sm); font-weight: 600; cursor: pointer; transition: background var(--dur-micro), color var(--dur-micro);
    display: inline-flex; align-items: center;
  }
  .cal-view-toggle button.active { background: var(--card); color: var(--text); box-shadow: 0 1px 2px rgba(0,0,0,.18); }

  /* Área de contenido — scrollable para que la sección overflow sea alcanzable */
  .cal-content {
    flex: 1; min-height: 0; overflow-y: auto;
    display: flex; flex-direction: column;
  }

  /* Vista semanal — el wrap ya no trata de ocupar toda la altura; el scroll es en cal-content */
  .cal-week-wrap {
    display: flex; flex-direction: column; flex-shrink: 0; width: 100%;
  }
  /* Header y body comparten exactamente el mismo grid: minmax(0,1fr) impide blowout */
  .cal-week-header {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: calc(1px * var(--sp-scale, 1)); background: var(--border); flex-shrink: 0;
  }
  .cal-week-body {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: calc(1px * var(--sp-scale, 1)); background: var(--border);
  }
  /* min-width:0 evita que el contenido empuje la columna más allá de su 1fr */
  .cal-day-head {
    background: var(--bg2); padding: calc(9px * var(--sp-scale, 1)) var(--space-2) calc(7px * var(--sp-scale, 1)); text-align: center;
    border-bottom: 2px solid transparent;
    min-width: 0; overflow: hidden;
  }
  .cal-day-head.today { border-bottom-color: var(--accent); }
  .cal-day-head .day-name { font-size: var(--fs-xs); color: var(--text2); text-transform: uppercase; letter-spacing: 0.06em; }
  .cal-day-head .day-num  { font-size: calc(17px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -0.5px; margin-top: 1px; }
  .cal-day-head .day-count { font-size: var(--fs-2xs); color: var(--text3); margin-top: 2px; }
  .cal-day-head.today .day-num { color: var(--accent); }
  .cal-day-col {
    background: var(--bg); padding: calc(5px * var(--sp-scale, 1)); min-height: 140px;
    min-width: 0; overflow: hidden;
  }
  .cal-day-col.today { background: rgba(var(--accent-rgb),0.025); }

  /* ── Tarjeta de tarea: thumbnail + VFX ID + artista ─── */
  .cal-task {
    position: relative;
    background: var(--card); border: 1px solid var(--border); border-top: 2px solid;
    border-radius: var(--radius-xs); overflow: hidden; cursor: pointer;
    width: 100%; box-sizing: border-box; min-width: 0; margin-bottom: 5px;
    transition: background var(--dur-micro), border-color var(--dur-micro);
  }
  .cal-task:hover { background: var(--card2); border-color: var(--border2); }
  /* v3: borde NEUTRAL — el estado lo comunican la etiqueta WIP/PPF y el punto de vencimiento */
  .cal-task { border-top-color: var(--border2); }
  .cal-task.step-wip { border-top-color: var(--yellow); }
  .cal-task.step-ppf { border-top-color: var(--green); }
  /* Checkbox de selección múltiple (aparece al hover o cuando está marcada) */
  .cal-sel-box { position: absolute; top: 6px; left: 6px; z-index: 8; width: 17px; height: 17px; border-radius: 5px;
    border: 1.5px solid var(--border2); background: rgba(0,0,0,0.45); cursor: pointer; opacity: 0; transition: opacity var(--dur-micro);
    display: flex; align-items: center; justify-content: center; }
  .cal-task:hover .cal-sel-box, .cal-task.cal-selected .cal-sel-box { opacity: 1; }
  .cal-task.cal-selected .cal-sel-box { background: var(--accent); border-color: var(--accent); }
  .cal-task.cal-selected .cal-sel-box::after { content: ''; width: 4px; height: 8px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg) translate(0,-1px); }
  .cal-task.cal-selected { outline: 2px solid var(--accent); outline-offset: -1px; }
  .cal-ghost-count { position: absolute; top: -8px; right: -8px; background: var(--accent); color: #fff; font-size: var(--fs-xs); font-weight: 800; border-radius: var(--radius-pill); padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); box-shadow: 0 0 0 2px var(--bg2); }
  /* Barra flotante de selección */
  .cal-selbar { position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: var(--z-cal-selbar);
    display: flex; align-items: center; gap: var(--space-3); background: var(--card); border: 1px solid var(--border2);
    border-radius: var(--radius-pill); box-shadow: var(--shadow-modal); padding: var(--space-2) calc(15px * var(--sp-scale, 1)); font-size: calc(12.5px * var(--fs-scale, 1)); color: var(--text); }
  .cal-selbar button { background: var(--wash-2); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: calc(3px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1)); font-size: calc(11.5px * var(--fs-scale, 1)); font-weight: 600; color: var(--text2); cursor: pointer; font-family: inherit; }
  .cal-selbar button:hover { color: var(--text); border-color: var(--border2); }
  .cal-task-toprow { display: flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); }
  .cal-task-toprow .cal-task-vfx { flex: 1; min-width: 0; }
  .cal-task-due-pip { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
  .cal-task-due-pip.due-overdue { background: var(--red); }
  .cal-task-due-pip.due-urgent  { background: var(--orange); }
  .cal-task-due-pip.due-soon    { background: var(--green); }
  .cal-task-due-pip.due-none    { background: var(--text3); }
  .cal-task-badge { font-size: calc(8px * var(--fs-scale, 1)); font-weight: 800; border-radius: 4px; padding: calc(1px * var(--sp-scale, 1)) var(--space-1); letter-spacing: .04em; white-space: nowrap; flex-shrink: 0; }
  .cal-task-badge.wip { background: rgba(var(--yellow-rgb),0.20); color: var(--yellow); }
  .cal-task-badge.ppf { background: rgba(var(--green-rgb),0.20); color: var(--green); }

  /* v3: modo compacto (lista densa, mini-miniatura a la izquierda) */
  #cal-content.density-compact .cal-task { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); padding: var(--space-1) calc(7px * var(--sp-scale, 1)) var(--space-1) calc(5px * var(--sp-scale, 1)); border-top: 1px solid var(--border); border-left: 2px solid var(--border2); }
  #cal-content.density-compact .cal-task-thumb { width: 26px !important; height: 26px !important; min-width: 26px; margin-bottom: 0 !important; border-radius: 4px; }
  #cal-content.density-compact .cal-task-info { padding: 0; flex: 1; min-width: 0; }
  #cal-content.density-compact .cal-task-artist { margin-top: 0; }

  /* v3: contador por día como píldora junto al número */
  .cal-day-head .day-row { display: flex; align-items: baseline; justify-content: center; gap: calc(6px * var(--sp-scale, 1)); margin-top: 1px; }
  .cal-day-head .day-count { font-size: var(--fs-xs); font-weight: 700; color: var(--text2); background: var(--wash-2); border-radius: var(--radius-pill); padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); line-height: calc(16px * var(--fs-scale, 1)); margin-top: 0; }
  .cal-day-head.today .day-count { background: rgba(var(--accent-rgb),0.18); color: var(--accent); }
  .cal-day-head .day-count.hot { background: rgba(var(--orange-rgb),0.18); color: var(--orange); }

  /* v3: KPIs con borde superior de color sutil */
  .cal-kpi { border-top: 2px solid var(--border2); }
  .cal-kpi.k-wip { border-top-color: var(--yellow); }
  .cal-kpi.k-ppf { border-top-color: var(--green); }

  /* v3: leyenda de estado */
  .cal-legend { display: flex; align-items: center; gap: calc(14px * var(--sp-scale, 1)); padding: var(--space-2) calc(18px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); flex-wrap: wrap; flex-shrink: 0; }
  .cal-legend-item { display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); font-size: var(--fs-sm); color: var(--text2); }
  .cal-legend-chip { font-size: calc(8px * var(--fs-scale, 1)); font-weight: 800; border-radius: 4px; padding: calc(1px * var(--sp-scale, 1)) calc(5px * var(--sp-scale, 1)); letter-spacing: .04em; }
  .cal-legend-chip.wip { background: rgba(var(--accent-rgb),0.18); color: var(--accent); }
  .cal-legend-chip.ppf { background: rgba(var(--purple-rgb),0.18); color: var(--purple); }
  .cal-legend-sep { width: 1px; height: 14px; background: var(--border); }
  .cal-legend-pip { width: 8px; height: 8px; border-radius: 50%; }
  .cal-legend-pip.due-overdue { background: var(--red); }
  .cal-legend-pip.due-urgent  { background: var(--orange); }
  .cal-legend-pip.due-soon    { background: var(--green); }

  /* v3: agrupación por artista/proyecto (acordeón dentro de la columna) */
  .cal-group { border: 1px solid var(--border); border-radius: var(--radius-xs); margin-bottom: 6px; overflow: hidden; background: var(--wash-1); }
  .cal-group-head { display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); padding: calc(5px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); cursor: pointer; user-select: none; background: var(--card); border-left: 2px solid var(--border2); transition: background var(--dur-micro); }
  .cal-group-head:hover { background: var(--card2); }
  .cal-group-chev { transition: transform var(--dur-fast) var(--ease-out); color: var(--text3); flex-shrink: 0; }
  .cal-group.open .cal-group-chev { transform: rotate(90deg); }
  .cal-group-title { font-size: var(--fs-sm); font-weight: 700; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .cal-group-pill { font-size: var(--fs-2xs); font-weight: 700; color: var(--text2); background: var(--wash-3); border-radius: var(--radius-pill); padding: calc(1px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); flex-shrink: 0; }
  .cal-group-body { padding: calc(5px * var(--sp-scale, 1)) calc(5px * var(--sp-scale, 1)) calc(2px * var(--sp-scale, 1)); display: none; }
  .cal-group.open .cal-group-body { display: block; }

  /* v3: menú desplegable (agrupar / filtros rápidos de fecha) */
  .cal-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: var(--z-menu); background: var(--card); border: 1px solid var(--border2); border-radius: var(--radius-sm); box-shadow: var(--shadow-pop); padding: calc(5px * var(--sp-scale, 1)); display: none; min-width: 170px; }
  .cal-menu.open { display: block; }
  .cal-menu-label { font-size: var(--fs-2xs); font-weight: 700; color: var(--text3); text-transform: uppercase; letter-spacing: .07em; padding: calc(6px * var(--sp-scale, 1)) var(--space-2) var(--space-1); }
  .cal-menu-item { display: flex; align-items: center; justify-content: space-between; gap: calc(10px * var(--sp-scale, 1)); padding: calc(7px * var(--sp-scale, 1)) var(--space-2); border-radius: var(--radius-xs); font-size: var(--fs-base); color: var(--text2); cursor: pointer; }
  .cal-menu-item:hover { background: var(--wash-3); color: var(--text); }
  .cal-menu-item.on { color: var(--accent); }
  .cal-menu-item.on::after { content: '✓'; font-size: var(--fs-sm); }
  .cal-btn b { color: var(--text); font-weight: 600; margin-left: 4px; }

  /* v3: filtros rápidos de fecha dentro del date picker */
  .cal-dp-quick { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-bottom: 8px; }

  /* v3: secciones colapsables del panel de filtros */
  .cal-fsec { border-bottom: 1px solid var(--border); }
  .cal-fsec:last-child { border-bottom: none; }
  .cal-fsec-head { display: flex; align-items: center; gap: var(--space-2); padding: calc(11px * var(--sp-scale, 1)) calc(2px * var(--sp-scale, 1)); cursor: pointer; user-select: none; }
  .cal-fsec-chev { transition: transform var(--dur-fast) var(--ease-out); color: var(--text3); flex-shrink: 0; transform: rotate(90deg); /* expandido → abajo */ }
  .cal-fsec.collapsed .cal-fsec-chev { transform: rotate(0deg); /* colapsado → derecha */ }
  .cal-fsec-title { font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 600; color: var(--text3); text-transform: uppercase; letter-spacing: .08em; flex: 1; margin: 0; }
  .cal-fsec-body { padding: 0 0 var(--space-3); }
  .cal-fsec.collapsed .cal-fsec-body { display: none; }
  .cal-sort-btn { display: flex; align-items: center; gap: calc(3px * var(--sp-scale, 1)); font-size: calc(9.5px * var(--fs-scale, 1)); color: var(--text3); background: var(--wash-1); border: 1px solid var(--border); border-radius: var(--radius-xs); padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); cursor: pointer; transition: color var(--dur-micro), background var(--dur-micro); flex-shrink: 0; }
  .cal-sort-btn:hover { color: var(--text); background: var(--wash-3); }
  .cal-sort-btn.active { color: var(--accent); border-color: rgba(var(--accent-rgb),0.4); }
  /* Thumbnail */
  .cal-task-thumb {
    width: 100%; height: 65px; overflow: hidden; flex-shrink: 0;
    background: var(--wash-2);
    display: flex; align-items: center; justify-content: center;
  }
  .cal-task-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .cal-task-thumb-ph { color: var(--border2); }
  /* Texto debajo del thumb */
  .cal-task-info { padding: calc(5px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); }
  .cal-task-vfx {
    font-size: var(--fs-sm); font-weight: 700; letter-spacing: -0.2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .cal-task-artist {
    font-size: var(--fs-xs); color: var(--text2); margin-top: 2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .cal-task-extra-art { color: var(--text3); font-size: var(--fs-2xs); }

  /* Badges */
  .cal-badge {
    font-size: var(--fs-2xs); font-weight: 700; border-radius: 4px; padding: calc(1px * var(--sp-scale, 1)) calc(5px * var(--sp-scale, 1));
    letter-spacing: 0.04em; white-space: nowrap;
  }
  .cal-badge.wip        { background: rgba(var(--accent-rgb),0.14);  color: var(--accent); }
  .cal-badge.ppf        { background: rgba(var(--purple-rgb),0.14);  color: var(--purple); }
  .cal-badge.due-overdue{ background: rgba(var(--red-rgb),0.14);   color: var(--red);    }
  .cal-badge.due-urgent { background: rgba(var(--orange-rgb),0.14);  color: var(--orange); }
  .cal-badge.due-soon   { background: rgba(var(--green-rgb),0.12);   color: var(--green);  }
  .cal-badge.due-none   { background: var(--wash-2); color: var(--text3);  }
  .cal-date-chip {
    display: inline-block; font-size: var(--fs-xs); font-weight: 700; border-radius: 5px; padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); white-space: nowrap;
  }

  /* Overflow sections */
  .cal-overflow-section { padding: calc(10px * var(--sp-scale, 1)) var(--space-4); flex-shrink: 0; border-top: 1px solid var(--border); }
  .cal-overflow-label { font-size: var(--fs-xs); color: var(--text3); margin-bottom: 7px; text-transform: uppercase; letter-spacing: 0.06em; }
  .cal-overflow-grid  { display: flex; flex-wrap: wrap; gap: calc(5px * var(--sp-scale, 1)); }

  /* Vista lista */
  .cal-list-wrap { flex: 1; overflow-y: auto; padding: calc(14px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1)); }
  .cal-list-table { width: 100%; border-collapse: collapse; }
  .cal-list-table th {
    font-size: var(--fs-xs); font-weight: 600; color: var(--text2); text-align: left;
    padding: calc(6px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); text-transform: uppercase; letter-spacing: 0.05em;
  }
  .cal-list-table td { padding: calc(9px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); font-size: var(--fs-base); }
  .cal-list-table tr:hover td { background: var(--wash-1); cursor: pointer; }
  .cal-list-table .vfx-id { font-weight: 600; }

  /* ── Panel de Filtros (columna derecha fija) ── */
  /* v4: panel de filtros FLOTANTE (dropdown del botón "Filtros") */
  .cal-filter-wrap { position: relative; }
  #cal-filter-btn.active { color: var(--accent); border-color: rgba(var(--accent-rgb),0.4); background: rgba(var(--accent-rgb),0.10); }
  .cal-filter-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 15px; height: 15px;
    padding: 0 var(--space-1); margin-left: 4px; border-radius: var(--radius-pill); background: var(--accent); color: #fff; font-size: var(--fs-2xs); font-weight: 800; }
  .cal-filters-panel {
    position: absolute; top: calc(100% + 7px); right: 0; z-index: var(--z-cal-filters);
    width: 290px; max-height: 70vh; overflow-y: auto;
    border: 1px solid var(--border2); background: var(--card); border-radius: var(--radius); box-shadow: var(--shadow-pop);
    display: none; flex-direction: column;
    padding: var(--space-3) calc(14px * var(--sp-scale, 1)); gap: 0;
  }
  .cal-filters-panel.open { display: flex; }
  .cal-fs-title {
    font-size: var(--fs-xs); font-weight: 700; color: var(--text3);
    text-transform: uppercase; letter-spacing: 0.07em;
    margin-bottom: 8px; margin-top: 16px;
  }
  .cal-fs-title:first-child { margin-top: 0; }
  .cal-fs-sep { height: 1px; background: var(--border); margin: 14px 0 0; }

  /* Filtro de chips (Step, Date) */
  .cal-fs-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
  .cal-fs-chip {
    height: 24px; padding: 0 calc(10px * var(--sp-scale, 1)); border-radius: var(--radius);
    border: 1px solid var(--border); background: var(--card);
    color: var(--text2); font-size: var(--fs-sm); font-weight: 500; cursor: pointer;
    transition: background var(--dur-micro), color var(--dur-micro), border-color var(--dur-micro); white-space: nowrap;
  }
  .cal-fs-chip:hover { background: var(--wash-3); color: var(--text); }
  .cal-fs-chip.active { background: rgba(var(--accent-rgb),0.14); border-color: rgba(var(--accent-rgb),0.35); color: var(--accent); }
  .cal-fs-chip.wip.active { background: rgba(var(--yellow-rgb),0.18); border-color: rgba(var(--yellow-rgb),0.35); color: var(--yellow); }
  .cal-fs-chip.ppf.active { background: rgba(var(--green-rgb),0.18); border-color: rgba(var(--green-rgb),0.35); color: var(--green); }

  /* Filtro de lista con búsqueda (Proyecto, Artista) */
  .cal-fs-search {
    width: 100%; background: var(--wash-2); border: 1px solid var(--border);
    border-radius: var(--radius-xs); color: var(--text); font-size: var(--fs-sm);
    padding: calc(6px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); outline: none; margin-bottom: 6px; transition: border-color var(--dur-fast);
    box-sizing: border-box;
  }
  .cal-fs-search:focus { border-color: var(--accent); }
  .cal-fs-search::placeholder { color: var(--text3); }
  /* Las listas crecen completas dentro del panel (que ya tiene scroll propio):
     sin max-height interno no se cortan filas/nombres a la mitad. */
  .cal-fs-list { display: flex; flex-direction: column; gap: calc(1px * var(--sp-scale, 1)); }
  /* (2026-07-29) .cal-range-input eliminado: los inputs nativos del popup de
     rango ya no existen — el rango se elige en el grid del datepicker. */
  /* Resalte de los días dentro del rango personalizado (vista mensual) */
  .cal-month-cell.mc-inrange { background: rgba(var(--accent-rgb),0.07); box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb),0.16); }
  /* VFX ID como enlace a Flow Production Tracking — clickeable pero discreto */
  .vfx-link { color: inherit; text-decoration: none; cursor: pointer; border-bottom: 1px dotted var(--wash-5); transition: color var(--dur-micro), border-color var(--dur-micro); }
  .vfx-link:hover, .vfx-link:focus { color: var(--accent); border-bottom-color: var(--accent); outline: none; }
  .cal-fs-item {
    display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); padding: calc(5px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1));
    border-radius: var(--radius-xs); cursor: pointer; font-size: var(--fs-sm);
    transition: background var(--dur-micro);
  }
  .cal-fs-item:hover { background: var(--wash-2); }
  /* Checkbox dark-themed */
  .fs-item input[type="checkbox"], .cal-fs-item input[type="checkbox"] {
    width: 13px; height: 13px; flex-shrink: 0;
    appearance: none; -webkit-appearance: none;
    background: var(--wash-3);
    border: 1.5px solid var(--wash-5);
    border-radius: 3px; cursor: pointer;
    transition: background var(--dur-micro), border-color var(--dur-micro);
    position: relative; vertical-align: middle;
  }
  /* OJO: los pseudo-selectores van en CADA alternativa. Un
     ".fs-item input, .cal-fs-item input:checked" aplica el estado marcado a
     TODAS las casillas .fs-item (bug visto en vivo 2026-07-30: se pintaban
     todas azules como si estuvieran seleccionadas). */
  .fs-item input[type="checkbox"]:hover,
  .cal-fs-item input[type="checkbox"]:hover {
    border-color: var(--wash-5);
    background: var(--wash-4);
  }
  .fs-item input[type="checkbox"]:checked,
  .cal-fs-item input[type="checkbox"]:checked {
    background: var(--accent);
    border-color: var(--accent);
  }
  .fs-item input[type="checkbox"]:checked::after,
  .cal-fs-item input[type="checkbox"]:checked::after {
    content: '';
    position: absolute; top: 1px; left: 3px;
    width: 4px; height: 7px;
    border: 2px solid #fff; border-top: none; border-left: none;
    transform: rotate(42deg);
  }
  .fs-item input[type="checkbox"]:focus-visible,
  .cal-fs-item input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 2px;
  }
  .cal-fs-item-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .cal-fs-clear {
    font-size: var(--fs-xs); color: var(--text3); background: none; border: none; cursor: pointer;
    padding: 0; margin-left: 4px; transition: color var(--dur-micro); flex-shrink: 0;
  }
  .cal-fs-clear:hover { color: var(--accent); }
  .cal-fs-header { display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); margin-bottom: 6px; }
  .cal-fs-count {
    font-size: var(--fs-2xs); background: rgba(var(--accent-rgb),0.18); color: var(--accent);
    border-radius: var(--radius-xs); padding: calc(0px * var(--sp-scale, 1)) calc(5px * var(--sp-scale, 1)); font-weight: 700; line-height: calc(16px * var(--fs-scale, 1));
  }

  /* ── Date Picker ─────────────────────────────────────── */
  .cal-datepicker-wrap { position: relative; display: flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); }
  .cal-date-label-btn {
    display: flex; align-items: center; gap: calc(5px * var(--sp-scale, 1));
    height: 26px; padding: 0 calc(10px * var(--sp-scale, 1)); border-radius: var(--radius-xs);
    border: 1px solid var(--border); background: var(--card2);
    color: var(--text2); font-size: var(--fs-base); font-weight: 500; cursor: pointer;
    transition: background var(--dur-micro), color var(--dur-micro);
    white-space: nowrap;   /* la fecha nunca se parte en varias líneas */
  }
  .cal-date-label-btn:hover { background: var(--wash-3); color: var(--text); }
  .cal-period-nav {
    width: 24px; height: 26px; display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-xs); border: 1px solid var(--border); background: var(--card2);
    color: var(--text2); cursor: pointer; font-size: var(--fs-lg); line-height: 1;
    transition: background var(--dur-micro), color var(--dur-micro); flex-shrink: 0;
  }
  .cal-period-nav:hover { background: var(--wash-3); color: var(--text); }
  .cal-today-btn {
    height: 26px; padding: 0 var(--space-2); border-radius: var(--radius-xs);
    border: 1px solid var(--border); background: var(--card2);
    color: var(--text2); font-size: var(--fs-xs); cursor: pointer; white-space: nowrap;
    transition: background var(--dur-micro), color var(--dur-micro);
  }
  .cal-today-btn:hover { background: var(--wash-3); color: var(--text); }
  /* (2026-07-29) Unificado con el picker canónico OTDP: misma tipografía,
     mismas celdas circulares, mismos botones de footer. */
  #cal-datepicker-popup {
    position: absolute; top: calc(100% + 6px); left: 0; z-index: var(--z-cal-datepicker);
    background: var(--card); border: 1px solid var(--border2);
    border-radius: 14px; padding: var(--space-3) calc(14px * var(--sp-scale, 1)) var(--space-3);
    box-shadow: var(--shadow-pop); width: 248px;
    display: none;
  }
  #cal-datepicker-popup.dp-open { display: block; }
  .cal-dp-hdr {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 10px; padding: 0 calc(2px * var(--sp-scale, 1));
  }
  .cal-dp-title {
    font-size: var(--fs-lg); font-weight: 600; color: var(--text);
    letter-spacing: -.4px; text-transform: capitalize;
    flex: 1; text-align: center;
  }
  .cal-dp-nav {
    width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
    background: var(--wash-2); border: 1px solid var(--wash-3);
    color: var(--text2); border-radius: 8px; cursor: pointer; font-size: var(--fs-md); line-height: 1; flex-shrink: 0;
    transition: background var(--dur-micro), color var(--dur-micro), border-color var(--dur-micro), transform var(--dur-micro);
  }
  .cal-dp-nav:hover { background: var(--wash-4); border-color: var(--wash-4); color: var(--text); transform: scale(1.08); }
  .cal-dp-nav:active { background: var(--wash-4); transform: scale(.94); }
  .cal-dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: calc(1px * var(--sp-scale, 1)); }
  .cal-dp-dow {
    font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 700; color: var(--text3);
    text-align: center; padding: 0 0 calc(7px * var(--sp-scale, 1));
    text-transform: uppercase; letter-spacing: .07em;
  }
  .cal-dp-day {
    display: flex; align-items: center; justify-content: center;
    aspect-ratio: 1; border-radius: 50%; position: relative;
    font-size: calc(12.5px * var(--fs-scale, 1)); color: var(--text2);
    cursor: pointer; user-select: none;
    transition: background var(--dur-micro), color var(--dur-micro), transform var(--dur-micro);
  }
  .cal-dp-day:hover { background: var(--wash-3); color: var(--text); transform: scale(1.08); }
  .cal-dp-day.dp-other  { color: var(--text3); opacity: .35; }
  .cal-dp-day.dp-today  { color: var(--accent); font-weight: 700; }
  .cal-dp-day.dp-today::after {
    content: ''; position: absolute; bottom: 3px; left: 50%;
    transform: translateX(-50%);
    width: 3.5px; height: 3.5px; border-radius: 50%;
    background: var(--accent);
  }
  .cal-dp-day.dp-inweek { background: rgba(var(--accent-rgb),0.08); }
  .cal-dp-day.dp-sel    {
    background: var(--accent) !important; color: #fff !important; font-weight: 600;
    box-shadow: 0 2px 8px rgba(var(--accent-rgb),.5), 0 0 0 1px rgba(var(--accent-rgb),.3);
  }
  .cal-dp-sep { height: 1px; background: var(--wash-2); margin: 8px calc(-14px * var(--sp-scale, 1)); margin-top: 8px; margin-bottom: 8px; }
  /* Aviso del modo rango (elegir inicio/fin en el grid) */
  .cal-dp-range-hint {
    font-size: var(--fs-xs); font-weight: 600; color: var(--accent);
    background: rgba(var(--accent-rgb),0.10); border: 1px solid rgba(var(--accent-rgb),0.25);
    border-radius: 8px; padding: calc(5px * var(--sp-scale, 1)) var(--space-2);
    margin-bottom: 8px; text-align: center;
  }
  .cal-fs-chip.picking { background: rgba(var(--accent-rgb),0.14); border-color: var(--accent); color: var(--accent); }
  .cal-dp-footer-btn {
    width: 100%; height: 30px; border-radius: 8px;
    background: var(--accent); color: #fff; border: none;
    font-size: var(--fs-base); font-weight: 600; cursor: pointer;
    font-family: inherit; letter-spacing: -.2px;
    box-shadow: 0 1px 6px rgba(var(--accent-rgb),.35);
    transition: background var(--dur-fast), box-shadow var(--dur-fast), transform var(--dur-micro);
  }
  .cal-dp-footer-btn:hover { background: var(--accent-hover); box-shadow: 0 3px 12px rgba(var(--accent-rgb),.5); transform: translateY(-1px); }
  .cal-dp-footer-btn:active { transform: scale(.96); box-shadow: none; }

  /* ── Vista Mensual ───────────────────────────────────── */
  #cal-btn-monthly.active { background: rgba(var(--green-rgb),0.14); color: var(--green); }
  .cal-month-wrap { flex: 1; overflow: auto; padding: calc(10px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); display: flex; flex-direction: column; }
  .cal-month-dow-row {
    display: grid; grid-template-columns: repeat(7, 1fr);
    border-bottom: 1px solid var(--border); flex-shrink: 0;
  }
  .cal-month-dow {
    font-size: var(--fs-2xs); font-weight: 700; color: var(--text3);
    text-transform: uppercase; letter-spacing: .06em; text-align: center; padding: calc(5px * var(--sp-scale, 1)) 0;
  }
  .cal-month-grid {
    flex: 1; display: grid; grid-template-columns: repeat(7, 1fr);
    gap: calc(1px * var(--sp-scale, 1)); background: var(--border);
    grid-auto-rows: minmax(88px, 1fr);
  }
  .cal-month-cell {
    background: var(--bg); padding: calc(5px * var(--sp-scale, 1)); display: flex;
    flex-direction: column; overflow: hidden; min-height: 88px;
  }
  .cal-month-cell.mc-other  { background: var(--bg2); }
  .cal-month-cell.mc-today  { background: rgba(var(--accent-rgb),0.04); }
  .cal-month-cell.mc-today .cal-mc-daynum { color: var(--accent); font-weight: 700; }
  .cal-mc-daynum { font-size: var(--fs-sm); color: var(--text3); margin-bottom: 4px; flex-shrink: 0; }
  .cal-mc-card {
    font-size: var(--fs-xs); border-radius: 3px; padding: calc(2px * var(--sp-scale, 1)) calc(5px * var(--sp-scale, 1)); margin-bottom: 2px; cursor: pointer;
    border-left: 2px solid; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
    flex-shrink: 0; transition: opacity var(--dur-micro);
  }
  .cal-mc-card:hover { opacity: .75; }
  .cal-mc-card.step-wip { background: rgba(var(--yellow-rgb),0.12); border-left-color: var(--yellow); }
  .cal-mc-card.step-ppf { background: rgba(var(--green-rgb),0.12); border-left-color: var(--green); }
  /* Selección múltiple en la vista mensual (2026-08-03): mismo checkbox que la
     semanal pero más chico (la tarjeta compacta mide ~20px de alto) y en la
     esquina superior DERECHA para no tapar el borde de color del step. */
  .cal-mc-card { position: relative; }
  .cal-mc-card .cal-sel-box { top: 2px; right: 2px; left: auto; width: 14px; height: 14px; border-radius: 4px; }
  .cal-mc-card:hover .cal-sel-box, .cal-mc-card.cal-selected .cal-sel-box { opacity: 1; }
  .cal-mc-card.cal-selected .cal-sel-box { background: var(--accent); border-color: var(--accent); }
  .cal-mc-card.cal-selected .cal-sel-box::after { content: ''; width: 3px; height: 7px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg) translate(0,-1px); }
  .cal-mc-card.cal-selected { outline: 2px solid var(--accent); outline-offset: -1px; }
  .cal-mc-more { font-size: var(--fs-2xs); color: var(--text3); margin-top: 1px; }

  /* ── Thumbnail en tarjeta ────────────────────────────── */
  .cal-task-thumb {
    width: 100%; height: 50px; border-radius: 3px; overflow: hidden;
    background: var(--bg2); margin-bottom: 5px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
  }
  .cal-task-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .cal-task-thumb-ph { color: var(--border2); }

  /* ── Vista Prueba WIP/PPF ────────────────────────────── */
  #cal-btn-test { border-left: 1px solid var(--border); }
  #cal-btn-test.active { background: rgba(var(--purple-rgb),0.15); color: var(--purple); }
  .cal-test-wrap { flex: 1; overflow-y: auto; padding: calc(14px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1)); }
  .cal-test-banner {
    background: rgba(var(--purple-rgb),0.07); border: 1px solid rgba(var(--purple-rgb),0.25);
    border-radius: var(--radius-sm); padding: var(--space-2) calc(14px * var(--sp-scale, 1)); margin-bottom: 12px;
    font-size: var(--fs-sm); color: var(--text2); display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); flex-wrap: wrap;
  }
  .cal-test-banner strong { color: var(--purple); }
  .cal-test-kpis { display: flex; gap: calc(6px * var(--sp-scale, 1)); margin-bottom: 12px; flex-wrap: wrap; }
  .cal-test-kpi {
    background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-xs);
    padding: calc(6px * var(--sp-scale, 1)) var(--space-3); text-align: center; min-width: 80px;
  }
  .cal-test-kpi-val { font-size: var(--fs-kpi); font-weight: 700; }
  .cal-test-kpi-lbl { font-size: var(--fs-2xs); color: var(--text2); margin-top: 1px; }
  .cal-test-kpi.k-wip  .cal-test-kpi-val { color: var(--yellow); }
  .cal-test-kpi.k-ppf  .cal-test-kpi-val { color: var(--green); }
  .cal-test-kpi.k-zero .cal-test-kpi-val { color: var(--red); }
  .cal-test-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
  .cal-test-table th {
    font-size: var(--fs-2xs); font-weight: 700; color: var(--text3); text-transform: uppercase;
    letter-spacing: .05em; padding: calc(5px * var(--sp-scale, 1)) var(--space-2); border-bottom: 1px solid var(--border);
    text-align: left; white-space: nowrap; position: sticky; top: 0; background: var(--bg); z-index: 1;
  }
  .cal-test-table td { padding: calc(6px * var(--sp-scale, 1)) var(--space-2); border-bottom: 1px solid var(--border); vertical-align: top; }
  .cal-test-table tr:hover td { background: var(--wash-1); }
  .cal-test-step-src { font-size: var(--fs-2xs); color: var(--text3); font-family: monospace; display: block; margin-top: 1px; }
  .cal-test-rawdump { margin-top: 14px; }
  .cal-test-rawdump-hdr { font-size: var(--fs-xs); color: var(--orange); font-weight: 700; margin-bottom: 6px; }
  .cal-test-rawdump table { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); font-family: monospace; }
  .cal-test-rawdump th {
    background: var(--bg2); padding: var(--space-1) var(--space-2); text-align: left; color: var(--text2);
    border-bottom: 1px solid var(--border); white-space: nowrap; position: sticky; top: 0;
  }
  .cal-test-rawdump td { padding: calc(3px * var(--sp-scale, 1)) var(--space-2); border-bottom: 1px solid var(--border); white-space: nowrap; max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
  .cal-test-rawdump tr:hover td { background: var(--wash-1); }

  /* ── Debug Panel ─────────────────────────────────────── */
  .cal-debug-panel {
    flex-shrink: 0; margin: 8px 18px 0;
    background: rgba(var(--orange-rgb),0.05); border: 1px solid rgba(var(--orange-rgb),0.28);
    border-radius: var(--radius-sm); font-size: var(--fs-sm); overflow: hidden;
  }
  .cal-debug-hdr {
    display: flex; align-items: center; gap: var(--space-2);
    padding: calc(7px * var(--sp-scale, 1)) var(--space-3); background: rgba(var(--orange-rgb),0.09);
    border-bottom: 1px solid rgba(var(--orange-rgb),0.2); cursor: pointer; user-select: none;
  }
  .cal-debug-hdr-title { font-weight: 700; color: var(--orange); flex: 1; font-size: var(--fs-sm); }
  .cal-debug-hdr-close {
    background: none; border: none; color: var(--text3); cursor: pointer;
    font-size: var(--fs-lg); line-height: 1; padding: 0 calc(2px * var(--sp-scale, 1)); transition: color var(--dur-micro);
  }
  .cal-debug-hdr-close:hover { color: var(--text); }
  .cal-debug-body { padding: calc(10px * var(--sp-scale, 1)) var(--space-3); }
  .cal-debug-cnt-grid { display: flex; flex-wrap: wrap; gap: calc(5px * var(--sp-scale, 1)); margin-bottom: 10px; }
  .cal-debug-cnt {
    background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius-xs);
    padding: calc(5px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); min-width: 72px; text-align: center;
  }
  .cal-debug-cnt-val { font-size: calc(16px * var(--fs-scale, 1)); font-weight: 700; }
  .cal-debug-cnt-lbl { font-size: var(--fs-2xs); color: var(--text2); margin-top: 1px; white-space: nowrap; }
  .cal-debug-cnt.cnt-zero .cal-debug-cnt-val { color: var(--red); }
  .cal-debug-cnt.cnt-ok   .cal-debug-cnt-val { color: var(--green); }
  .cal-debug-cnt.cnt-warn .cal-debug-cnt-val { color: var(--orange); }
  .cal-debug-actions { display: flex; gap: calc(6px * var(--sp-scale, 1)); flex-wrap: wrap; margin-bottom: 8px; }
  .cal-debug-rawwrap {
    background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-xs);
    overflow: auto; max-height: 320px; margin-top: 8px;
  }
  .cal-debug-rawwrap table { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); font-family: monospace; }
  .cal-debug-rawwrap th {
    background: var(--bg2); padding: var(--space-1) var(--space-2); text-align: left; color: var(--text2);
    border-bottom: 1px solid var(--border); white-space: nowrap; position: sticky; top: 0; z-index: 1;
  }
  .cal-debug-rawwrap td {
    padding: calc(3px * var(--sp-scale, 1)) var(--space-2); border-bottom: 1px solid var(--border);
    white-space: nowrap; max-width: 200px; overflow: hidden; text-overflow: ellipsis;
  }
  .cal-debug-rawwrap tr:hover td { background: var(--wash-1); }
  .td-bad  { color: var(--red)    !important; }

  /* Panel lateral de detalle de tarea */
  #cal-panel {
    position: fixed; top: 0; right: -380px; width: 340px; height: 100vh;
    background: var(--card); border-left: 1px solid var(--border2);
    z-index: var(--z-cal-panel); transition: right var(--dur-base) cubic-bezier(.4,0,.2,1);
    display: flex; flex-direction: column; overflow: hidden;
    box-shadow: -4px 0 20px rgba(0,0,0,0.35);
  }
  #cal-panel.open { right: 0; }
  .cal-panel-header {
    display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1));
    padding: calc(14px * var(--sp-scale, 1)) var(--space-4) var(--space-3); border-bottom: 1px solid var(--border); flex-shrink: 0;
  }
  .cal-panel-header h3 { flex: 1; font-size: var(--fs-lg); font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cal-panel-body { flex: 1; overflow-y: auto; padding: calc(14px * var(--sp-scale, 1)) var(--space-4); }
  .cal-detail-row { display: flex; gap: var(--space-2); margin-bottom: 12px; font-size: var(--fs-base); }
  .cal-detail-label { color: var(--text2); width: 80px; flex-shrink: 0; font-size: var(--fs-sm); padding-top: calc(1px * var(--sp-scale, 1)); }
  .cal-detail-value { color: var(--text); flex: 1; }
  .cal-detail-sep { height: 1px; background: var(--border); margin: 10px 0; }

  /* ── Reportes ────────────────────────────────────────── */
  #page-reports .page-body {
    padding: var(--space-6) calc(28px * var(--sp-scale, 1)); overflow-y: auto;
    display: flex; flex-direction: column; gap: var(--space-6);
  }
  .reports-intro {
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: var(--space-4) var(--space-5);
    display: flex; align-items: center; gap: calc(14px * var(--sp-scale, 1));
  }
  .reports-intro-icon {
    width: 40px; height: 40px; border-radius: 10px;
    background: rgba(var(--accent-rgb),0.12); color: var(--accent);
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  }
  .reports-intro-text { font-size: var(--fs-base); color: var(--text2); line-height: 1.55; }
  .reports-intro-text strong { color: var(--text); font-size: var(--fs-md); display: block; margin-bottom: 2px; }
  .reports-section-title {
    font-size: var(--fs-sm); font-weight: 700; color: var(--text3);
    text-transform: uppercase; letter-spacing: .07em; margin-bottom: 10px;
  }
  .reports-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: calc(10px * var(--sp-scale, 1));
  }
  /* Tarjeta de módulo (Monitoreo): compacta, con franja de acento por sección
     (--rc, inline por tarjeta) y mini-copy. El color del icono lo controla la
     galería de iconos (defColor por slot / color individual / global). */
  /* .report-card es un <button> desde 2026-08-24 (era un <div data-action>, y
     `lib/actions.js` solo engancha data-action a `click` → el hub entero era
     inoperable por teclado). Estas cuatro líneas de reset son lo único que
     hace falta para que un <button> se vea igual que el <div> de antes. */
  .report-card {
    position: relative; overflow: hidden;
    background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm);
    padding: calc(13px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1));
    cursor: pointer; min-height: 104px;
    transition: transform var(--dur-fast) cubic-bezier(.32,.72,0,1), border-color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast);
    display: flex; flex-direction: column; gap: var(--space-2);
    font: inherit; color: inherit; text-align: left; width: 100%; margin: 0;
    /* `align-items: stretch` es OBLIGATORIO: la hoja de estilos del navegador
       le pone `align-items: flex-start` a todo <button>, y como la tarjeta es
       flex-column eso encoge a los hijos a su ancho de contenido — el
       `justify-content: flex-end` del footer deja de tener a dónde empujar y
       el chevron se pega al texto en vez de irse a la derecha. */
    align-items: stretch;
  }
  .report-card::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
    background: var(--rc, var(--accent)); opacity: .85;
  }
  .report-card:hover { transform: translateY(-2px); background: var(--card2); border-color: var(--border2); box-shadow: 0 6px 18px rgba(0,0,0,0.14); }
  /* Respuesta en pointer-DOWN, no en release: sin esto la primera señal de que
     algo pasó es que la página ya cambió. En trackpad y táctil el :hover no
     llega o llega tarde, así que este era el único estado que faltaba. */
  .report-card:active { transform: translateY(0) scale(.985); transition: transform 100ms ease-out; box-shadow: none; }
  .report-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  @media (prefers-reduced-motion: reduce) {
    .report-card, .report-card:hover, .report-card:active { transition: background var(--dur-fast), border-color var(--dur-fast) !important; transform: none; }
  }
  .report-card-header { display: flex; align-items: center; gap: calc(9px * var(--sp-scale, 1)); }
  .report-card-icon {
    width: 30px; height: 30px; border-radius: 7px; flex-shrink: 0; color: var(--text2);
    display: flex; align-items: center; justify-content: center;
  }
  .report-card-title { font-size: calc(13.5px * var(--fs-scale, 1)); font-weight: 650; letter-spacing: -0.2px; }
  /* Mini-copy: un tono más tenue que el título para dar jerarquía */
  .report-card-desc  { font-size: var(--fs-sm); color: var(--text2); line-height: 1.45; flex: 1; }
  .report-card-footer { display: flex; align-items: center; justify-content: flex-end; margin-top: calc(1px * var(--sp-scale, 1)); }
  .report-badge-soon {
    font-size: var(--fs-xs); font-weight: 600; padding: calc(2px * var(--sp-scale, 1)) var(--space-2); border-radius: 20px;
    background: var(--wash-2); color: var(--text3); border: 1px solid var(--border);
  }
  /* Tag de formato de salida (Excel / Gráficas / Log de Flow) — neutral */
  .report-format {
    display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1));
    font-size: var(--fs-xs); font-weight: 700; letter-spacing: .02em;
    padding: calc(2px * var(--sp-scale, 1)) var(--space-2); border-radius: 20px;
    background: var(--wash-2); color: var(--text2); border: 1px solid var(--border);
  }
  .report-format svg { opacity: .8; }

  /* ══════════════════════════════════════════════════════
     OTDP — Custom Date Picker · Premium Redesign
     Sistema de diseño: Ollin VFX Flow Tracker (dark)
     Inspirado en Linear, Vercel, Raycast, Notion.
     ══════════════════════════════════════════════════════ */

  @keyframes otdp-in {
    from { opacity: 0; transform: scale(.94) translateY(-10px); }
    to   { opacity: 1; transform: scale(1)   translateY(0);     }
  }
  @keyframes otdp-out {
    from { opacity: 1; transform: scale(1)   translateY(0);     }
    to   { opacity: 0; transform: scale(.94) translateY(-6px);  }
  }
  @keyframes otdp-day-mount {
    from { opacity: 0; transform: scale(.7); }
    to   { opacity: 1; transform: scale(1);  }
  }

  /* ── Trigger ────────────────────────────────────────── */
  .otdp { position: relative; }
  .otdp-trigger {
    width: 100%; display: flex; align-items: center; gap: calc(9px * var(--sp-scale, 1));
    background: var(--wash-2);
    border: 1px solid var(--border2);
    border-radius: var(--radius-sm); padding: calc(9px * var(--sp-scale, 1)) var(--space-3);
    color: var(--text); font-size: var(--fs-md); font-family: inherit;
    cursor: pointer; text-align: left; outline: none;
    transition: border-color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast);
  }
  .otdp-trigger:hover {
    background: var(--wash-3);
    border-color: var(--wash-4);
  }
  .otdp-trigger.otdp-open {
    border-color: var(--accent);
    background: rgba(var(--accent-rgb),0.06);
    box-shadow: 0 0 0 3px rgba(var(--accent-rgb),0.15);
  }
  .otdp-icon    { color: var(--text3); flex-shrink: 0; transition: color var(--dur-fast); }
  .otdp-trigger.otdp-open .otdp-icon { color: var(--accent); }
  .otdp-display { flex: 1; color: var(--text); font-variant-numeric: tabular-nums; }
  .otdp-display.ph { color: var(--text3); font-weight: 400; }
  .otdp-chevron {
    color: var(--text3); flex-shrink: 0;
    transition: transform var(--dur-base) cubic-bezier(.4,0,.2,1), color var(--dur-fast);
  }
  .otdp-trigger.otdp-open .otdp-chevron {
    transform: rotate(180deg); color: var(--accent);
  }

  /* ── Popup shell ────────────────────────────────────── */
  .otdp-popup {
    position: absolute; top: calc(100% + 8px); left: 0; z-index: var(--z-otdp);
    width: 284px; max-width: calc(100vw - 32px); padding: var(--space-4) calc(14px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1));
    background: var(--card2);
    border: 1px solid var(--wash-4);
    border-radius: 14px; box-sizing: border-box;
    box-shadow:
      0 0 0 1px rgba(0,0,0,.6),
      0 2px 4px rgba(0,0,0,.3),
      0 8px 20px rgba(0,0,0,.45),
      0 24px 48px rgba(0,0,0,.35),
      inset 0 1px 0 var(--wash-2);
    opacity: 0; transform: scale(.94) translateY(-10px);
    transform-origin: top left; pointer-events: none;
    transition:
      opacity var(--dur-fast) cubic-bezier(.4,0,.2,1),
      transform var(--dur-base) cubic-bezier(.175,.885,.32,1.1);
  }
  .otdp-popup.otdp-open {
    opacity: 1; transform: scale(1) translateY(0); pointer-events: all;
    animation: otdp-in var(--dur-base) cubic-bezier(.175,.885,.32,1.1) both;
  }

  /* ── Header: mes + año + flechas ───────────────────── */
  .otdp-hdr {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 12px; padding: 0 calc(2px * var(--sp-scale, 1));
  }
  .otdp-month-lbl {
    font-size: var(--fs-lg); font-weight: 600; color: var(--text);
    letter-spacing: -.4px; text-transform: capitalize;
    flex: 1; text-align: center;
    background: transparent; border: none; cursor: default;
    font-family: inherit; padding: 0;
  }
  .otdp-nav {
    width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
    background: var(--wash-2);
    border: 1px solid var(--wash-3);
    color: var(--text2); border-radius: 8px; cursor: pointer; flex-shrink: 0;
    transition: background var(--dur-micro), color var(--dur-micro), border-color var(--dur-micro), transform var(--dur-micro);
  }
  .otdp-nav:hover {
    background: var(--wash-4);
    border-color: var(--wash-4);
    color: var(--text);
    transform: scale(1.08);
  }
  .otdp-nav:active { background: var(--wash-4); transform: scale(.94); }

  /* ── Separador bajo header ──────────────────────────── */
  .otdp-divider {
    height: 1px; background: var(--wash-2);
    margin: 0 -14px 12px; /* sangra hasta el borde del popup */
  }

  /* ── Grid días ──────────────────────────────────────── */
  .otdp-grid {
    display: grid; grid-template-columns: repeat(7,1fr);
    gap: calc(1px * var(--sp-scale, 1));
  }
  .otdp-dow {
    font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 700; color: var(--text3);
    text-align: center; padding: 0 0 calc(9px * var(--sp-scale, 1));
    text-transform: uppercase; letter-spacing: .07em;
  }

  /* Celda día: contenedor + círculo interno */
  .otdp-day {
    display: flex; align-items: center; justify-content: center;
    aspect-ratio: 1; border-radius: 8px;
    cursor: pointer; user-select: none;
    transition: background var(--dur-micro);
    position: relative;
  }
  .otdp-day span {
    display: flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 50%;
    font-size: calc(12.5px * var(--fs-scale, 1)); color: var(--text2); font-weight: 400;
    transition: background var(--dur-micro), color var(--dur-micro), box-shadow var(--dur-micro), transform var(--dur-micro);
  }

  /* Hover */
  .otdp-day:hover:not(.od-other):not(.od-sel) span {
    background: var(--wash-3); color: var(--text);
    transform: scale(1.08);
  }

  /* Foco de teclado (auditoría #4, M1): el día enfocado con flechas tiene que
     VERSE. El contenedor no pinta el outline (se comería el círculo): va sobre
     el span, que es la píldora visible. `:focus` sin -visible además, porque el
     foco lo movemos por código y Safari no siempre lo marca como visible. */
  .otdp-day:focus { outline: none; }
  .otdp-day:focus-visible span,
  .otdp-day:focus span {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    background: var(--wash-3); color: var(--text);
  }

  /* Días fuera del mes */
  .otdp-day.od-other { pointer-events: none; }
  .otdp-day.od-other span { color: var(--text3); opacity: .3; }

  /* Hoy — punto + texto en azul */
  .otdp-day.od-today span {
    color: var(--accent); font-weight: 700;
  }
  .otdp-day.od-today::after {
    content: ''; position: absolute; bottom: 3px; left: 50%;
    transform: translateX(-50%);
    width: 3.5px; height: 3.5px; border-radius: 50%;
    background: var(--accent);
  }
  .otdp-day.od-today.od-sel::after { background: var(--wash-5); }

  /* Seleccionado */
  .otdp-day.od-sel span {
    background: var(--accent) !important;
    color: #fff !important; font-weight: 600;
    box-shadow: 0 2px 8px rgba(var(--accent-rgb),.5), 0 0 0 1px rgba(var(--accent-rgb),.3);
    transform: scale(1.08);
  }
  .otdp-day.od-sel:hover span {
    background: var(--accent-hover) !important;
    box-shadow: 0 4px 14px rgba(var(--accent-rgb),.6), 0 0 0 1px rgba(var(--accent-rgb),.4);
  }

  /* ── Footer ─────────────────────────────────────────── */
  .otdp-footer {
    display: flex; gap: calc(7px * var(--sp-scale, 1)); margin-top: 12px;
    padding-top: var(--space-3); border-top: 1px solid var(--wash-2);
  }
  .otdp-btn {
    flex: 1; height: 30px; border-radius: 8px;
    font-size: var(--fs-base); font-weight: 600; cursor: pointer;
    font-family: inherit; outline: none;
    transition: background var(--dur-fast), color var(--dur-fast), box-shadow var(--dur-fast), transform var(--dur-micro);
    letter-spacing: -.2px;
  }
  .otdp-btn:active { transform: scale(.96); }

  /* "Hoy" — acción primaria */
  .otdp-btn-today {
    background: var(--accent); color: #fff; border: none;
    box-shadow: 0 1px 6px rgba(var(--accent-rgb),.35);
  }
  .otdp-btn-today:hover {
    background: var(--accent-hover);
    box-shadow: 0 3px 12px rgba(var(--accent-rgb),.5);
    transform: translateY(-1px);
  }
  .otdp-btn-today:active { transform: scale(.96); box-shadow: none; }

  /* "Borrar" — acción secundaria ghost */
  .otdp-btn-clear {
    background: transparent; color: var(--text2);
    border: 1px solid var(--wash-4);
  }
  .otdp-btn-clear:hover {
    background: var(--wash-3); color: var(--text);
    border-color: var(--wash-4);
  }

  /* ── Reporte OT ──────────────────────────────────────── */
  #page-report-ot .page-body { padding: var(--space-6) calc(28px * var(--sp-scale, 1)); overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-4); }
  .ot-section { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: calc(18px * var(--sp-scale, 1)) var(--space-5); }
  .ot-section-title { font-size: var(--fs-xs); font-weight: 700; color: var(--text3); text-transform: uppercase; letter-spacing: .07em; margin-bottom: 14px; display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); }
  .ot-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: calc(14px * var(--sp-scale, 1)); }
  /* ── Project Cost: tarjetas compactas + historial de códigos ── */
  #page-report-artist .ot-section { padding: calc(10px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); }
  #page-report-artist .ot-section-title { margin-bottom: 8px; }
  #page-report-artist .page-body { gap: calc(10px * var(--sp-scale, 1)); }
  .ot-upload-zone {
    border: 1.5px dashed var(--border2); border-radius: var(--radius-sm); padding: calc(22px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1));
    text-align: center; cursor: pointer; transition: border-color var(--dur-fast), background var(--dur-fast);
  }
  .ot-upload-zone:hover,
  .ot-upload-zone.dragging { border-color: var(--accent); background: rgba(var(--accent-rgb),0.04); }
  .ot-upload-zone.has-file { border-color: var(--green); border-style: solid; background: rgba(var(--green-rgb),0.04); }
  .ot-upload-label { font-size: var(--fs-base); color: var(--text2); font-weight: 500; margin-top: 8px; }
  .ot-upload-hint  { font-size: var(--fs-sm); color: var(--text3); margin-top: 3px; }
  .ot-file-info { margin-top: 9px; font-size: var(--fs-base); display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); }
  .ot-status-bar { border-radius: var(--radius-sm); padding: calc(9px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1)); font-size: var(--fs-base); display: flex; align-items: center; gap: var(--space-2); }
  /* `display:flex` le gana al [hidden] del navegador — la misma trampa que ya
     está documentada para .tb-card, .cal-avisos y .seg-fbar. Sin esto,
     `setToolStatus(el, null)` deja una barra vacía con padding a la vista. */
  .ot-status-bar[hidden], .tool-skel[hidden], .tool-empty[hidden], .tool-actions[hidden] { display: none; }
  .ot-status-bar.s-loading { background:rgba(var(--accent-rgb),0.08); color:var(--accent);  border:1px solid rgba(var(--accent-rgb),0.2); }
  .ot-status-bar.s-success { background:rgba(var(--green-rgb),0.08); color:var(--green);   border:1px solid rgba(var(--green-rgb),0.2); }
  .ot-status-bar.s-error   { background:rgba(var(--red-rgb),0.08); color:var(--red);     border:1px solid rgba(var(--red-rgb),0.2); }
  .ot-status-bar.s-empty   { background:var(--wash-2); color:var(--text2); border:1px solid var(--border); }
  /* s-warn FALTABA (auditoría 2026-08-24): `_monSetStatus('warn')` y
     `_prmRenderWarnings` ya emitían esta clase, pero sin regla salían como
     texto neutro — una advertencia que no se ve no es una advertencia. */
  .ot-status-bar.s-warn    { background:rgba(var(--orange-rgb),0.08); color:var(--orange); border:1px solid rgba(var(--orange-rgb),0.22); }
  .ot-kpi-row { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: 14px; }
  .ot-kpi { background: var(--card2); border: 1px solid var(--border); border-radius: var(--radius-xs); padding: calc(7px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1)); text-align: center; min-width: 80px; }
  .ot-kpi-val { font-size: var(--fs-kpi); font-weight: 700; }
  .ot-kpi-lbl { font-size: var(--fs-2xs); color: var(--text2); margin-top: 1px; text-transform: uppercase; letter-spacing: .04em; }
  .ot-kpi-val.c-blue   { color: var(--accent); }
  .ot-kpi-val.c-green  { color: var(--green); }
  .ot-kpi-val.c-orange { color: var(--orange); }
  .ot-table-wrap { overflow-x: auto; }
  .ot-table { width: 100%; border-collapse: collapse; font-size: var(--fs-base); }
  .ot-table th { font-size: var(--fs-xs); font-weight: 700; color: var(--text3); text-transform: uppercase; letter-spacing: .05em; padding: calc(6px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); text-align: left; white-space: nowrap; }
  .ot-table td { padding: calc(7px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); vertical-align: middle; }
  /* La fila TOTAL ya se marca explícitamente con `.is-total` (05-import-archivos.js).
     Este selector por posición era el acoplamiento frágil que la auditoría
     2026-08-24 señaló: cualquier fila añadida al final heredaba el look de
     total. Se retira ahora que el JS emite la clase. */
  .ot-table tr:hover td { background: var(--wash-1); }
  .ot-table .td-r { text-align: right; }
  .ot-warn { color: var(--orange); font-size: var(--fs-2xs); margin-left: 4px; }
  .ot-dl-btn { width: 100%; margin-top: 14px; display: flex; align-items: center; justify-content: center; gap: calc(7px * var(--sp-scale, 1)); }

  /* ── Reporte Monitoreo Artistas ──────────────────────── */
  #page-report-monitoring .page-body,
  #page-report-artist .page-body { padding: var(--space-6) calc(28px * var(--sp-scale, 1)); overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-4); }
  .mon-table-wrap  { overflow-x: auto; margin-top: 14px; }
  .mon-table { width: 100%; border-collapse: collapse; font-size: var(--fs-base); }
  .mon-table th { font-size: var(--fs-xs); font-weight: 700; color: var(--text3); text-transform: uppercase; letter-spacing:.05em; padding: calc(6px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); text-align: left; white-space: nowrap; }
  .mon-table td { padding: calc(7px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); vertical-align: middle; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mon-table td.mon-td-wrap { white-space: normal; word-break: break-all; max-width: 320px; }
  .mon-table tr:hover td { background: var(--wash-1); }
  .mon-table .td-r { text-align: right; }
  /* ── Progress list ── */
  .mon-progress-list { display: flex; flex-direction: column; gap: calc(6px * var(--sp-scale, 1)); margin-top: 4px; }
  .mon-progress-item { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); padding: var(--space-2) var(--space-3);
    background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-xs); font-size: var(--fs-base); }
  .mon-progress-item.pi-ok     { border-left: 3px solid var(--green); }
  .mon-progress-item.pi-error  { border-left: 3px solid var(--red); }
  .mon-progress-item.pi-warn   { border-left: 3px solid var(--orange); }
  .mon-progress-item.pi-loading{ border-left: 3px solid var(--accent); }
  .mon-pi-name  { flex: 0 0 200px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mon-pi-status{ flex: 1; color: var(--text2); font-size: var(--fs-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mon-pi-icon  { flex-shrink: 0; display: flex; align-items: center; }
  /* ── Acción XLSX ── */
  .mon-xlsx-bar { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); flex-wrap: wrap; padding: var(--space-3) var(--space-4);
    background: rgba(var(--green-rgb),0.07); border: 1px solid rgba(var(--green-rgb),0.25); border-radius: 8px; }

  /* ══════════════════════════════════════════════════════════
     HERRAMIENTAS — capa compartida (rediseño 2026-08-24)
     ─────────────────────────────────────────────────────────
     Las 5 tools portadas de iOS nacieron con `.settings-mailfields`, que es
     el patrón del MODAL de Configuración: columna de etiqueta de 52px y filas
     sueltas. En una página completa eso se lee como un muro de campos.
     Aquí NO se inventa un look nuevo: se reutiliza el que la sección ya tenía
     (`.ot-section` + `.ot-section-title` + `.ot-status-bar`) y solo se agrega
     lo que faltaba — campos con etiqueta real, barra de acción y estado vacío.
     Regla de la casa: el tamaño de los botones es GLOBAL (.btn/.btn-sm); aquí
     no se declara ni un height ni un padding de botón.
  ══════════════════════════════════════════════════════════ */

  /* Lienzo de página: mismo ritmo que OT y Monitoreo. Ancho máximo porque un
     formulario a 1900px obliga a barrer la pantalla con los ojos. */
  #page-report-client .page-body, #page-credits .page-body,
  #page-contact-list .page-body, #page-gmail-groups .page-body,
  #page-meet .page-body {
    padding: var(--space-6) calc(28px * var(--sp-scale, 1));
    overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-4);
  }
  .tool-shell { display: flex; flex-direction: column; gap: var(--space-4); width: 100%; max-width: 980px; }
  .tool-shell--wide { max-width: 1280px; }

  /* ── Campo: etiqueta REAL a un lado, control a la derecha ──
     Grid en vez de flex: todas las etiquetas de una sección se alinean sin
     fijarle un ancho a cada una. Bajo 720px se apila (la etiqueta encima),
     que es lo que funciona en iPad vertical y en el iPhone. */
  .tool-fields { display: flex; flex-direction: column; gap: var(--space-3); }
  .tool-field  { display: grid; grid-template-columns: var(--tool-lbl-w, 148px) minmax(0, 1fr); gap: var(--space-3); align-items: center; }
  .tool-field--top { align-items: start; }
  .tool-field--top > .tool-lbl { padding-top: calc(7px * var(--sp-scale, 1)); }
  .tool-lbl {
    font-size: var(--fs-sm); color: var(--text2); font-weight: 500;
    line-height: 1.35; min-width: 0; overflow-wrap: anywhere;
  }
  .tool-lbl .req { color: var(--orange); margin-left: 2px; }
  .tool-ctl { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; min-width: 0; }
  .tool-ctl > select, .tool-ctl > input[type="text"], .tool-ctl > input[type="email"], .tool-ctl > textarea { flex: 1 1 240px; min-width: 0; }
  /* Skin de campo — el mismo de .settings-mailfields, pero sin depender del
     modal. Copiado a propósito: si un día cambia el look de los inputs, este
     bloque y el del modal deben moverse juntos. */
  .tool-ctl input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
  .tool-ctl select, .tool-ctl textarea {
    background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-sm);
    padding: var(--space-2) calc(11px * var(--sp-scale, 1)); color: var(--text); font-size: var(--fs-md);
    outline: none; transition: border-color var(--dur-fast), box-shadow var(--dur-fast); font-family: inherit;
  }
  .tool-ctl input:focus, .tool-ctl select:focus, .tool-ctl textarea:focus { border-color: var(--accent); }
  .tool-ctl textarea { resize: vertical; line-height: 1.5; width: 100%; }
  /* Error de validación EN EL CAMPO, no en un resumen al final. */
  .tool-ctl input[aria-invalid="true"], .tool-ctl select[aria-invalid="true"] { border-color: var(--red); }
  .tool-err  { font-size: var(--fs-sm); color: var(--red); line-height: 1.4; }
  .tool-hint { font-size: var(--fs-sm); color: var(--text3); line-height: 1.45; }
  .tool-hint b { color: var(--text2); font-weight: 600; }
  .tool-field > .tool-err, .tool-field > .tool-hint { grid-column: 2; margin-top: calc(-1 * var(--space-1)); }
  @media (max-width: 720px) {
    .tool-field { grid-template-columns: 1fr; gap: var(--space-1); align-items: start; }
    .tool-field--top > .tool-lbl { padding-top: 0; }
    .tool-field > .tool-err, .tool-field > .tool-hint { grid-column: 1; }
  }

  /* ── Barra de acción: el CTA vive JUNTO a sus insumos, no en el header ──
     Proximidad implica relación (auditoría T11). El estado se lee en la misma
     línea del botón, que es donde el ojo ya está después de pulsar. */
  .tool-actions {
    display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
    padding-top: var(--space-4); margin-top: var(--space-1);
    border-top: 1px solid var(--border);
  }
  .tool-actions .tool-actions-msg { font-size: var(--fs-sm); color: var(--text2); flex: 1 1 200px; min-width: 0; line-height: 1.4; }
  .tool-actions .tool-actions-msg.is-error { color: var(--red); }
  .tool-actions-spacer { flex: 1 1 auto; }

  /* ── Estado vacío: dice qué va a pasar antes de que pase ── */
  .tool-empty {
    display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
    padding: calc(34px * var(--sp-scale, 1)) var(--space-5);
    border: 1px dashed var(--border2); border-radius: var(--radius-sm);
    background: var(--wash-1); text-align: center;
  }
  .tool-empty-icon { color: var(--text3); opacity: .7; }
  .tool-empty-title { font-size: var(--fs-md); font-weight: 600; color: var(--text2); }
  .tool-empty-desc  { font-size: var(--fs-sm); color: var(--text3); line-height: 1.5; max-width: 46ch; }

  /* ── Skeleton de carga: la silueta del contenido, no un spinner genérico ── */
  .tool-skel { display: flex; flex-direction: column; gap: var(--space-2); }
  .tool-skel-row { height: calc(34px * var(--sp-scale, 1)); border-radius: var(--radius-xs); background: var(--wash-2); position: relative; overflow: hidden; }
  .tool-skel-row::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, var(--wash-3), transparent);
    animation: tool-skel-sweep 1.15s ease-in-out infinite;
  }
  @keyframes tool-skel-sweep { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

  /* ── Área de golpe de 44px sin agrandar el control ──
     El usuario pidió explícitamente que no haya botones enormes: el pixel
     visible se queda igual y solo se extiende la zona sensible. */
  .hit-44 { position: relative; }
  .hit-44::after {
    content: ""; position: absolute; left: 0; right: 0; top: 50%;
    height: max(100%, 44px); transform: translateY(-50%);
  }
  /* Solo se extiende a lo ALTO, y solo hasta el ancho real del control: un
     overlay de 44px centrado en los dos ejes se desborda por los lados en
     controles angostos y le roba el clic al vecino. El alto sí puede crecer
     porque las filas de estas tools ya van separadas por --space-2 o más. */

  /* ── Botón «volver a Herramientas» ──
     Antes cada una de las 8 páginas traía su propio padding inline, y encima
     no coincidía con el del .btn-sm: el botón de volver era un pelo más
     angosto que cualquier otro botón de la app. El tamaño es GLOBAL. */
  .btn-back { display: inline-flex; align-items: center; gap: var(--space-1); flex-shrink: 0; }

  /* ── Encabezados de tabla pegajosos ──
     Quien scrollea 200 filas de OT o Monitoreo pierde los encabezados porque
     el que scrollea es .page-body. El wrap toma el scroll y el th se ancla. */
  .ot-table-wrap, .mon-table-wrap { overflow: auto; max-height: min(62vh, 620px); }
  /* `background: var(--card)` OPACO, no un wash translúcido: al pegarse, las
     filas pasarían por debajo y se leerían a través del encabezado.
     El `box-shadow: inset` reemplaza al `border-bottom`, que `border-collapse:
     collapse` descarta en cuanto la celda se vuelve sticky. */
  .ot-table th, .mon-table th {
    position: sticky; top: 0; z-index: 2;
    background: var(--card); box-shadow: inset 0 -1px 0 var(--border);
  }
  /* La fila TOTAL de OT dependía de `tr:last-child` — frágil ante cualquier
     fila que se agregue después. Ahora es explícita (`<tr class="is-total">`);
     se conserva el selector viejo por compatibilidad mientras el JS migra. */
  .ot-table tr.is-total td {
    font-weight: 700; position: sticky; bottom: 0;
    background: var(--card); box-shadow: inset 0 1px 0 var(--border);
  }
  /* Columnas ordenables: el th es un botón real, no un th con onclick. */
  .th-sort { background: none; border: 0; padding: 0; font: inherit; color: inherit; letter-spacing: inherit;
    text-transform: inherit; cursor: pointer; display: inline-flex; align-items: center; gap: var(--space-1); }
  .th-sort .th-arrow { opacity: 0; transition: opacity var(--dur-fast); }
  /* `data-sort` y no `aria-sort`: el atributo ARIA solo es válido en el <th>
     (columnheader). Aquí se necesita el estado en el <button> para la flecha,
     y para eso un data-attr es lo correcto. */
  .th-sort[data-sort="ascending"] .th-arrow, .th-sort[data-sort="descending"] .th-arrow { opacity: 1; }
  .th-sort[data-sort="descending"] .th-arrow { transform: rotate(180deg); }
  .th-sort:hover { color: var(--text); }

  /* OVFX — sidebar colapsable (Fase 1) — botón flecha minimalista */
  .sidebar{transition:width var(--dur-base) cubic-bezier(.32,.72,0,1)}
  .sb-toggle{background:none;border:none;color:var(--text3);cursor:pointer;padding: calc(5px * var(--sp-scale, 1));border-radius:7px;display:flex;align-items:center;flex-shrink:0;transition:background var(--dur-fast),color var(--dur-fast)}
  .sb-toggle:hover{background:var(--wash-2);color:var(--text)}
  .sb-toggle svg{transition:transform var(--dur-base) cubic-bezier(.32,.72,0,1);display:block}
  #view-app.sb-collapsed .sidebar{width:66px}
  #view-app.sb-collapsed .sb-toggle svg{transform:rotate(180deg)}
  #view-app.sb-collapsed .sidebar-header{flex-direction:column;justify-content:center;align-items:center;gap: calc(10px * var(--sp-scale, 1));padding: calc(14px * var(--sp-scale, 1)) 0 calc(10px * var(--sp-scale, 1))}
  #view-app.sb-collapsed .sidebar-brand{display:none}
  #view-app.sb-collapsed .sidebar .nav-item{font-size:0;justify-content:center;gap:0;padding-left:0;padding-right:0}
  #view-app.sb-collapsed .sidebar .nav-item svg{font-size:initial}
  #view-app.sb-collapsed .sidebar .nav-label{display:none}
  #view-app.sb-collapsed .sidebar .subnav{display:none}
  #view-app.sb-collapsed .sidebar .nav-section + .nav-section{margin-top:6px}
  #view-app.sb-collapsed .sidebar .nbadge{display:none}
  #view-app.sb-collapsed #quick-access-section{display:none}
  /* ===== Sidebar footer — columna centrada (COLAPSADO 66px) ===== */
  #view-app.sb-collapsed .sidebar-footer { flex-direction: column; align-items: center; gap: var(--space-1); padding: var(--space-2) 0; }
  #view-app.sb-collapsed .sidebar-footer .theme-toggle-btn,
  #view-app.sb-collapsed .sidebar-footer .settings-btn,
  #view-app.sb-collapsed .sidebar-footer .logout-btn {
    flex: 0 0 auto; width: 38px; height: 38px; min-width: 0; padding: 0; gap: 0; justify-content: center;
  }
  #view-app.sb-collapsed .sidebar-footer .settings-btn { font-size: 0; }
  #view-app.sb-collapsed .sidebar-footer .settings-btn svg { font-size: initial; opacity: .7; }
  /* margin-left:0 — en columna, el margin-left:auto del estado expandido
     empujaría el botón al borde derecho en vez de centrarlo. */
  #view-app.sb-collapsed .sidebar-footer .logout-btn { display: flex; margin-left: 0; }

  /* ══ Transición suave al cambiar de tema ══ */
  body, .card, .sidebar, .page-header, .modal, input, select, button {
    transition: background-color var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease;
  }

  /* ══ Estados de foco accesibles (teclado) ══ */
  .btn:focus-visible, .chip:focus-visible, .nav-item:focus-visible,
  .vfx-link:focus-visible, .shot-thumb:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-xs);
  }
  /* Foco de los nav-item INSET: la barra colapsada (66px) + overflow de
     .sidebar-nav recortaban el anillo exterior. Dibujado hacia adentro no se
     corta ni expandida ni colapsada (A11y/B5). */
  .nav-item:focus-visible { outline-offset: -2px; }

  /* ══ SHOT THUMBNAIL — componente central ══
     Uso: shotThumbHtml({thumbUrl, vfxId, entityId, size}) en JS. */
  .shot-thumb {
    position: relative; flex-shrink: 0; overflow: hidden;
    border-radius: 5px; border: 1px solid var(--border);
    background: var(--thumb-bg);
    display: flex; align-items: center; justify-content: center;
  }
  .shot-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .shot-thumb .st-ph { color: var(--text3); display: flex; }
  .shot-thumb.st-sm { width: 42px; height: 30px; }
  .shot-thumb.st-md { width: 64px; height: 42px; }
  .shot-thumb.st-lg { width: 120px; height: 76px; border-radius: var(--radius-xs); }
  .shot-thumb.st-xl { width: 128px; height: 84px; border-radius: var(--radius-xs); }
  /* st-poster: ocupa el ancho de su contenedor con relación 16:9 (tarjetas de
     Seguimiento). Único tamaño fluido — de ahí width:100% en vez de px fijos. */
  .shot-thumb.st-poster {
    width: 100%; aspect-ratio: 16 / 9; border-radius: var(--radius-xs);
  }
  .shot-thumb.st-poster .st-ph svg { width: 26px; height: 26px; }
  /* Modales "Shots para revisión" y "KBKs Internos" (pedido 2026-08-03):
     thumbnail 20% más grande que st-md (64×42 → 77×50) SOLO en estos dos
     modales — el de Aprobados comparte st-md y conserva su tamaño. */
  #review-modal .shot-thumb.st-md,
  #kbk-modal .shot-thumb.st-md { width: 77px; height: 50px; }

  /* ══ SHOTS ACTIVOS — agrupación por proyecto (tarjeta por grupo · Opción B) ══ */
  .as-groups { display: flex; flex-direction: column; gap: var(--space-4); }
  .as-group-card {
    background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow-card); overflow: hidden;
  }
  .as-group-head {
    display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1));
    padding: calc(11px * var(--sp-scale, 1)) var(--space-4); background: var(--wash-1);
    border-bottom: 1px solid var(--border);
  }
  .as-group-head .gdot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
  .as-group-name  { font-size: var(--fs-lg); font-weight: 650; letter-spacing: -0.01em; }
  .as-group-count { font-size: calc(11.5px * var(--fs-scale, 1)); color: var(--text2); }
  /* v-shots: filas en columnas de metadata (thumb · shot · artista · estado · frames · entrega · link) */
  .as-colhead, .as-shot-row {
    display: grid; align-items: center; gap: calc(14px * var(--sp-scale, 1)); padding: calc(9px * var(--sp-scale, 1)) var(--space-4);
    grid-template-columns: 64px minmax(110px,1.3fr) minmax(130px,1fr) 124px 78px 112px 32px;
  }
  .as-colhead {
    background: var(--bg2); border-bottom: 1px solid var(--border);
    font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text3);
  }
  .as-shot-row { border-bottom: 1px solid var(--border); transition: background var(--dur-micro); }
  .as-shot-row:last-child { border-bottom: none; }
  .as-shot-row:hover { background: var(--wash-1); }
  .as-shot-main { min-width: 0; display: flex; flex-direction: column; gap: calc(2px * var(--sp-scale, 1)); }
  .as-shot-id {
    font-family: inherit; font-size: var(--fs-lg); font-weight: 600;
    color: var(--accent); text-decoration: none; letter-spacing: .2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block;
  }
  .as-shot-id:hover { text-decoration: underline; }
  .as-shot-proj { font-size: var(--fs-xs); color: var(--text3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .as-col-artist { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
  .as-av { width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: var(--fs-2xs); font-weight: 700; flex-shrink: 0; }
  .as-col-artist .nm { font-size: var(--fs-base); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .as-col-artist.empty .nm { color: var(--text3); }
  .as-st-badge { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); font-size: var(--fs-sm); font-weight: 600; padding: calc(2px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius: var(--radius-pill); white-space: nowrap; max-width: 100%; }
  .as-st-badge .st-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
  .as-col-frames { font-size: var(--fs-base); color: var(--text2); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .as-col-due { font-size: var(--fs-base); white-space: nowrap; }
  .as-col-due.due-soon { color: var(--green); }
  .as-col-due.due-urgent { color: var(--orange); }
  .as-col-due.due-overdue { color: var(--red); }
  .as-col-due.due-none { color: var(--text3); }
  .as-col-muted { color: var(--text3); }

  /* v-shots: toolbar de densidad */
  .as-toolbar { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 14px; flex-wrap: wrap; }
  .as-toolbar-label { font-size: var(--fs-xs); color: var(--text3); text-transform: uppercase; letter-spacing: .06em; }
  .as-density-seg { display: inline-flex; align-items: center; gap: calc(2px * var(--sp-scale, 1)); height: 26px; box-sizing: border-box; background: var(--wash-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: calc(2px * var(--sp-scale, 1)); }
  .as-density-seg button { height: 20px; padding: 0 var(--space-3); background: transparent; border: none; border-radius: var(--radius-xs); color: var(--text2); font-size: var(--fs-sm); font-weight: 600; cursor: pointer; transition: background var(--dur-micro), color var(--dur-micro); display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); }
  .as-density-seg button.active { background: var(--card); color: var(--text); box-shadow: 0 1px 2px rgba(0,0,0,.18); }

  /* v-shots: modo compacto (fila ~1/3 del alto, thumb pequeño) */
  .as-density-compact .as-colhead, .as-density-compact .as-shot-row {
    grid-template-columns: 34px minmax(100px,1.2fr) minmax(120px,1fr) 112px 70px 100px 28px;
    gap: var(--space-3); padding-top: var(--space-1); padding-bottom: var(--space-1);
  }
  .as-density-compact .shot-thumb { width: 30px !important; height: 30px !important; }
  .as-density-compact .as-shot-proj { display: none; }
  .as-density-compact .as-shot-id { font-size: calc(12.5px * var(--fs-scale, 1)); }
  .as-density-compact .as-av { width: 20px; height: 20px; font-size: calc(8px * var(--fs-scale, 1)); }
  .as-density-compact .as-st-badge { font-size: var(--fs-xs); padding: calc(1px * var(--sp-scale, 1)) var(--space-2); }

  /* v-shots: sentinela de scroll infinito */
  .as-infinite { display: flex; align-items: center; justify-content: center; gap: calc(9px * var(--sp-scale, 1)); padding: var(--space-4); color: var(--text3); font-size: var(--fs-base); }
  .as-infinite .as-spin { width: 14px; height: 14px; border: 2px solid var(--wash-3); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; }
  /* (keyframe as-spin colapsado a `spin` — H8: 4 rotaciones idénticas → 1) */
  /* Spinner genérico. Faltaba el keyframe `spin` y la clase `.spin`, por lo que
     todos los íconos de carga que los referencian se veían CONGELADos (parecían
     error). Definirlos aquí los anima a todos a la vez. */
  @keyframes spin { to { transform: rotate(360deg); } }
  .spin { animation: spin 1s linear infinite; transform-origin: center; }
  .loading-icon { animation: spin 1s linear infinite; transform-origin: center; }
  a.shot-thumb { cursor: pointer; transition: border-color var(--dur-fast), transform var(--dur-fast); }
  a.shot-thumb:hover { border-color: var(--accent); }
  .shot-thumb.st-loading { background: linear-gradient(100deg, var(--wash-1) 40%, var(--wash-2) 50%, var(--wash-1) 60%); background-size: 200% 100%; animation: st-shimmer 1.4s infinite; }
  @keyframes st-shimmer { to { background-position: -200% 0; } }

  /* ══ FTP STATUS — indicador global (sidebar, todas las páginas) ══ */
  .ftp-status {
    margin: 0 10px 8px; padding: var(--space-2) calc(10px * var(--sp-scale, 1));
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--wash-1);
    display: flex; align-items: center; gap: var(--space-2);
    font-size: var(--fs-sm); color: var(--text2); cursor: default;
    position: relative;
  }
  .ftp-status .ftp-dot {
    width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
    background: var(--text3); transition: background var(--dur-base);
  }
  .ftp-status.ftp-connected .ftp-dot { background: var(--green); box-shadow: 0 0 0 3px rgba(var(--green-rgb),0.15); }
  .ftp-status.ftp-syncing   .ftp-dot { background: var(--yellow); animation: ftp-pulse 1.1s infinite; }
  .ftp-status.ftp-error     .ftp-dot { background: var(--red); box-shadow: 0 0 0 3px rgba(var(--red-rgb),0.15); }
  .ftp-status.ftp-offline   .ftp-dot { background: var(--red); }
  @keyframes ftp-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
  .ftp-status .ftp-info { flex: 1; min-width: 0; line-height: 1.35; }
  .ftp-status .ftp-state { font-weight: 600; color: var(--text); font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .ftp-status .ftp-sub   { font-size: var(--fs-xs); color: var(--text3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .ftp-status .ftp-sync-btn {
    background: none; border: none; color: var(--text2); cursor: pointer;
    padding: var(--space-1); border-radius: 5px; display: flex; flex-shrink: 0;
    transition: background var(--dur-fast), color var(--dur-fast);
  }
  .ftp-status .ftp-sync-btn:hover:not(:disabled) { background: var(--wash-3); color: var(--text); }
  .ftp-status .ftp-sync-btn:disabled { opacity: .45; cursor: not-allowed; }
  .ftp-status .ftp-sync-btn.spinning svg { animation: spin 0.9s linear infinite; }
  /* (keyframe ftp-spin colapsado a `spin` — H8) */
  /* Tooltip con detalle al hacer hover */
  .ftp-status .ftp-tip {
    display: none; position: absolute; left: 8px; bottom: calc(100% + 8px);
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--radius-sm);
    box-shadow: var(--shadow-modal); padding: calc(10px * var(--sp-scale, 1)) var(--space-3); z-index: var(--z-ftp-tip);
    width: 220px; font-size: var(--fs-sm); color: var(--text2); line-height: 1.6;
  }
  .ftp-status:hover .ftp-tip { display: block; }
  .ftp-status .ftp-tip strong { color: var(--text); }
  #view-app.sb-collapsed .ftp-status .ftp-info,
  #view-app.sb-collapsed .ftp-status .ftp-sync-btn { display: none; }
  #view-app.sb-collapsed .ftp-status { justify-content: center; padding: var(--space-2) 0; margin: 0 8px 8px; }

  /* ══ Toggle de tema (sidebar footer) ══ */
  /* (.theme-toggle-btn se estiliza dentro de .sidebar-footer — grupo unificado) */

  /* ══ Selector segmentado (Apariencia / Auto-sync en Configuración) ══ */
  .seg-control { display: inline-flex; border: 1px solid var(--border2); border-radius: var(--radius-sm); overflow: hidden; background: var(--wash-1); }
  .seg-control button {
    background: none; border: none; padding: calc(6px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); font-size: var(--fs-base); font-family: inherit;
    color: var(--text2); cursor: pointer; transition: background var(--dur-fast), color var(--dur-fast);
    border-right: 1px solid var(--border);
  }
  .seg-control button:last-child { border-right: none; }
  .seg-control button.active { background: var(--accent); color: #fff; font-weight: 600; }
  .seg-control button:not(.active):hover { background: var(--wash-2); color: var(--text); }

  /* ══════════════════════════════════════════════════════
     UNIFICACIÓN v4 — CAPA ADITIVA
     Estados de componente + utilidades para los patrones inline
     más repetidos. Todo aquí es aditivo: las clases nuevas no
     están referenciadas aún, así que NO cambian el render actual.
     Se adoptan progresivamente al migrar cada sección.
     ══════════════════════════════════════════════════════ */

  /* — Estados de botón faltantes (pulido + accesibilidad) — */
  .btn:active, .btn-sm:active, .btn-icon:active { transform: translateY(0.5px); }
  .btn:focus-visible, .btn-sm:focus-visible, .btn-icon:focus-visible,
  .btn-primary:focus-visible, .btn-secondary:focus-visible,
  .btn-ghost:focus-visible, .btn-danger:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 2px;
  }
  .btn:disabled, .btn-sm:disabled, .btn-icon:disabled,
  .btn-secondary:disabled, .btn-ghost:disabled, .btn-danger:disabled {
    opacity: 0.45; cursor: not-allowed; pointer-events: none;
  }
  /* Anillo de foco consistente para inputs/selects nativos */
  .field input:focus-visible, .field select:focus-visible,
  .field textarea:focus-visible,
  .search-box:focus-within { outline: none; }

/* ── Núcleo: lista agrupada de shots dentro de un modal (prefijo .risk-*) ──
   Nació con el modal «Shots en riesgo», RETIRADO el 2026-08-24 con su KPI.
   Las clases NO se van con él: son el patrón de lista agrupada que reusan los
   modales de Aprobados, KBKs Internos, Shots para revisión, Entregas de la
   semana y Playlist para revisión. El prefijo se conserva por compatibilidad
   (renombrarlo tocaría 6 módulos y sus goldens). ── */
.risk-empty { color: var(--text3); font-size: var(--fs-md); padding: calc(18px * var(--sp-scale, 1)) var(--space-1); text-align: center; }
.risk-group { margin-bottom: 14px; }
.risk-group-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); font-size: var(--fs-base); font-weight: 700; color: var(--text); padding: calc(6px * var(--sp-scale, 1)) calc(2px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); margin-bottom: 4px; }
.risk-group-n { font-size: var(--fs-sm); font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text); background: var(--wash-3); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); min-width: var(--space-6); text-align: center; display: inline-block; box-sizing: border-box; }
.risk-rows { display: flex; flex-direction: column; }
.risk-code { font-size: calc(12.5px * var(--fs-scale, 1)); color: var(--text); text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
a.risk-code:hover { color: var(--accent); text-decoration: underline; }
.risk-due { font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.risk-due.due-overdue { color: var(--red); } .risk-due.due-urgent { color: var(--orange); } .risk-due.due-soon { color: var(--text2); } .risk-due.due-none { color: var(--text3); }

/* ── KPI + Modal: Shots aprobados (supapv) ────────────────── */
.stat-icon.tint-green { background: var(--green-soft); color: var(--green); }
.stat-card.is-approved { border-color: rgba(var(--green-rgb), .28); }
.stat-card.is-approved .value { color: var(--green); }
/* Código del show (4 letras) en el encabezado de cada grupo del modal */
/* ── Modal Shots Activos (2026-07-17, prefijo actm- — "asm-" ya lo usa el
   modal de shots del artista). Tabla: Proyecto / Avance / Shots activos /
   Entrega / Cuenta regresiva / Visible (solo admin — .no-vis la quita).
   Vive en .modal--xl (780px): las mínimas de la tabla (~670px con gaps y
   padding del body) caben completas; Proyecto y Avance absorben el sobrante
   (fr) y las columnas de datos crecen solo a su contenido (max-content).
   En ventanas angostas min-width:fit-content degrada a scroll horizontal
   limpio del .modal-body (último recurso) en vez de cortar columnas. */
#active-shots-modal .modal-body { padding-top: 0; }  /* el header sticky pega al borde: sin franja de filas asomando arriba */
.actm-list { display: flex; flex-direction: column; min-width: fit-content; }
.actm-head, .actm-row { display: grid;
  grid-template-columns:
    minmax(calc(150px * var(--sp-scale, 1)), 1.6fr)         /* Proyecto (dot + nombre con ellipsis) */
    minmax(calc(112px * var(--sp-scale, 1)), 1fr)           /* Avance (barra flexible + %) */
    minmax(calc(84px * var(--sp-scale, 1)), max-content)    /* Shots activos */
    minmax(calc(88px * var(--sp-scale, 1)), max-content)    /* Entrega final */
    minmax(calc(76px * var(--sp-scale, 1)), max-content)    /* Semanas restantes */
    minmax(calc(96px * var(--sp-scale, 1)), max-content)    /* Días hábiles */
    minmax(calc(48px * var(--sp-scale, 1)), max-content);   /* Visible (admin) */
  column-gap: var(--space-3); align-items: center;
  padding: var(--space-2) calc(10px * var(--sp-scale, 1)); }
.actm-list.no-vis .actm-head, .actm-list.no-vis .actm-row { grid-template-columns:
    minmax(calc(150px * var(--sp-scale, 1)), 1.6fr)
    minmax(calc(112px * var(--sp-scale, 1)), 1fr)
    minmax(calc(84px * var(--sp-scale, 1)), max-content)
    minmax(calc(88px * var(--sp-scale, 1)), max-content)
    minmax(calc(76px * var(--sp-scale, 1)), max-content)
    minmax(calc(96px * var(--sp-scale, 1)), max-content); }
.actm-head { position: sticky; top: 0; background: var(--card);
  padding-top: var(--space-3);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text3); border-bottom: 1px solid var(--border); }
.actm-head span { white-space: nowrap; }
.actm-row { border-bottom: 1px solid var(--wash-2); font-size: var(--fs-sm); color: var(--text);
  padding-top: calc(10px * var(--sp-scale, 1)); padding-bottom: calc(10px * var(--sp-scale, 1)); }
.actm-row.off { opacity: .45; }
.actm-head .r, .actm-row .r { text-align: right; }
.actm-pname { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; overflow: hidden; }
.actm-pname:hover .actm-pname-txt { color: var(--accent); }
.actm-pname-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.actm-prog { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
/* La barra de avance se estira con la columna (en el dashboard es fija de 72px)
   pero nunca se colapsa por debajo de 56px ni domina la fila. */
.actm-prog .dash-prog-bar { flex: 1 1 auto; width: auto;
  min-width: calc(56px * var(--sp-scale, 1)); max-width: calc(120px * var(--sp-scale, 1)); }
.actm-shots { font-weight: 600; font-variant-numeric: tabular-nums; }
.actm-date { font-variant-numeric: tabular-nums; white-space: nowrap; }
.actm-date.none, .actm-cd.none { color: var(--text3); }
.actm-cd { font-variant-numeric: tabular-nums; white-space: nowrap; }
.actm-cd.soon { color: var(--yellow); font-weight: 600; }
.actm-cd.late { color: var(--red); font-weight: 600; }

/* ══ Modal ENTREGAS DE LA SEMANA (2026-08-19, prefijo entw-) ══
   Detalle del KPI "Entregas esta semana", agrupado por show. Reutiliza el
   núcleo: .risk-group/.risk-rows para los grupos, .risk-code para el shot,
   .badge para el tipo (WIP/PPF), .risk-due para los días restantes y .chip
   para los filtros. Lo único propio es la barra de filtros y la fila. */
#deliveries-modal .modal-body { padding-top: 0; }   /* la barra sticky pega al borde */
.entw-count { color: var(--accent); font-variant-numeric: tabular-nums; }
.entw-sub { color: var(--text3); font-size: var(--fs-md); margin-top: calc(2px * var(--sp-scale, 1)); }
.entw-sub .v { color: var(--text2); font-weight: 600; font-variant-numeric: tabular-nums; }
.entw-sub .v.alerta { color: var(--red); }
.entw-sub .v.ok { color: var(--green); }
/* Barra de filtros: pegada arriba porque las listas largas se recorren y el
   filtro tiene que seguir a la mano. */
.entw-bar { position: sticky; top: 0; z-index: 2; background: var(--card);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4);
  padding: var(--space-3) var(--space-1); margin-bottom: var(--space-3);
  border-bottom: 1px solid var(--border); }
.entw-grp { display: flex; flex-wrap: wrap; align-items: center; gap: calc(5px * var(--sp-scale, 1)); }
.entw-grp-lbl { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text3); margin-right: calc(2px * var(--sp-scale, 1)); }
.entw-bar .chip { font-family: inherit; display: inline-flex; align-items: baseline; gap: calc(5px * var(--sp-scale, 1)); max-width: calc(220px * var(--sp-scale, 1)); }
.entw-bar .chip > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.entw-bar .chip .dnum { font-size: var(--fs-2xs); color: var(--text3); font-variant-numeric: tabular-nums; }
.entw-bar .chip .n { font-size: var(--fs-2xs); font-weight: 700; font-variant-numeric: tabular-nums;
  background: var(--wash-3); border-radius: var(--radius-pill); padding: 0 calc(5px * var(--sp-scale, 1)); }
.entw-bar .chip.active .n { background: rgba(var(--accent-rgb), .18); }
.entw-limpiar { color: var(--orange); border-color: rgba(var(--orange-rgb), .35); }
/* Meta del encabezado de cada show (WIP · PPF · total) */
.entw-grp-meta { display: inline-flex; align-items: center; gap: var(--space-2); }
.entw-grp-meta .badge .n { font-variant-numeric: tabular-nums; font-weight: 700; }
/* Fila = una entrega. thumb · shot+artista · tipo · día · estatus · restante */
.entw-row { display: grid; align-items: center; gap: calc(10px * var(--sp-scale, 1));
  grid-template-columns: auto minmax(110px, 1.6fr) calc(58px * var(--sp-scale, 1)) calc(64px * var(--sp-scale, 1)) minmax(80px, .9fr) calc(88px * var(--sp-scale, 1));
  padding: calc(5px * var(--sp-scale, 1)) var(--space-1); border-radius: var(--radius-xs);
  border-left: 2px solid transparent; }
.entw-row:hover { background: var(--wash-1); }
.entw-id { min-width: 0; display: flex; flex-direction: column; }
.entw-id .risk-code { font-weight: 600; }
.entw-art { font-size: var(--fs-xs); color: var(--text3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.entw-tipo { justify-content: center; font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .04em; }
.entw-dia { display: flex; align-items: baseline; gap: var(--space-1);
  font-size: var(--fs-sm); color: var(--text2); white-space: nowrap; }
.entw-dia .dnum { font-variant-numeric: tabular-nums; color: var(--text3); }
.entw-est { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .03em; color: var(--text3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Semáforo "¿va a llegar?": franja izquierda + color del estatus. Nunca un hex
   inline — así respeta tema claro/oscuro y las escalas del Editor UI. */
.entw-row.r-vencida { border-left-color: var(--red); }
.entw-row.r-vencida .entw-est { color: var(--red); }
.entw-row.r-atorado { border-left-color: var(--orange); }
.entw-row.r-atorado .entw-est { color: var(--orange); }
.entw-row.r-hoy { border-left-color: var(--yellow); }
.entw-row.r-listo { border-left-color: var(--green); }
.entw-row.r-listo .entw-est { color: var(--green); }
.entw-row.r-listo .entw-id .risk-code { text-decoration: line-through; text-decoration-color: var(--border2); }
.entw-nota { font-size: var(--fs-sm); color: var(--text3); padding: var(--space-3) var(--space-1) 0;
  border-top: 1px solid var(--border); margin-top: var(--space-2); }
.entw-nota .n { font-weight: 700; color: var(--text2); font-variant-numeric: tabular-nums; }
.entw-vacio-btn { margin-left: var(--space-2); }
/* Pantallas chicas: el thumbnail y el estatus ceden primero (la pregunta
   "qué shot y qué día" se contesta con el código, el tipo y el día). */
@media (max-width: 820px) {
  .entw-row { grid-template-columns: auto minmax(90px, 1.4fr) calc(52px * var(--sp-scale, 1)) calc(58px * var(--sp-scale, 1)) calc(78px * var(--sp-scale, 1)); }
  .entw-row .entw-est { display: none; }
}

.apv-gcode { font-size: calc(10.5px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: .05em; color: var(--text2);
  background: var(--wash-2); border: 1px solid var(--border); border-radius: var(--radius-pill);
  padding: calc(1px * var(--sp-scale, 1)) var(--space-2); margin-right: 4px; }
/* Chip clickeable → abre el proyecto en Flow (pestaña Playlist, 2026-07-17) */
a.apv-gcode.link { text-decoration: none; cursor: pointer; display: inline-block; }
a.apv-gcode.link:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-soft, var(--wash-2)); }
/* Fila: thumbnail · VFX ID · pill SUPAPV · hora de aprobación */
.apv-row { display: grid; grid-template-columns: auto 1fr auto 96px; gap: var(--space-3); align-items: center;
  padding: calc(6px * var(--sp-scale, 1)) var(--space-1); border-radius: var(--radius-xs); }
.apv-row:hover { background: var(--wash-1); }
.apv-id { min-width: 0; }
.apv-id .risk-code { display: block; }
/* Step · nombre de la versión: renglón propio a TODO el ancho de la fila,
   sin truncar (se lee completo; envuelve si hace falta). */
.apv-sub { grid-column: 1 / -1; font-size: calc(10.5px * var(--fs-scale, 1)); color: var(--text3);
  padding: 0 calc(2px * var(--sp-scale, 1)) calc(2px * var(--sp-scale, 1)); margin-top: -2px; white-space: normal; word-break: break-word; }
.apv-pill { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .05em; color: var(--green);
  background: var(--green-soft); border: 1px solid var(--green-border);
  border-radius: var(--radius-pill); padding: calc(2.5px * var(--sp-scale, 1)) var(--space-2); white-space: nowrap; }
.apv-when { text-align: right; font-variant-numeric: tabular-nums; }
.apv-when b { display: block; font-size: var(--fs-base); font-weight: 600; color: var(--text); }
.apv-when small { font-size: var(--fs-xs); color: var(--text3); }

/* ── Shots aprobados: publicar a Deadline + archivado ─────── */
/* Header del modal: botón Archivados + chip de la VPN del pipe.
   El título/subtítulo ceden espacio (truncan) y las herramientas + la X nunca se comprimen. */
#approved-modal .modal-header { gap: calc(10px * var(--sp-scale, 1)); }
#approved-modal .modal-header > div:first-child { flex: 1; min-width: 0; }
#approved-modal .modal-header > div:first-child p { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* margin-right (2026-07-17): aire entre las herramientas del header y el
   botón de cerrar (×) — antes quedaban pegados (reporte del usuario en el
   modal Shots Activos; aplica igual al de Shots aprobados). */
.apv-head-tools { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; margin-left: auto; margin-right: calc(14px * var(--sp-scale, 1)); }
/* Shots aprobados (2026-07-21): el chip VPN creció a "VPN del server · …"
   (claridad 2026-07-20) y ya no cabe en una sola fila del header md (560px) —
   el título y las pills quedaban APRETADOS. El header envuelve: fila 1 =
   título + ×, fila 2 = herramientas alineadas a la derecha. flex-wrap solo
   actúa cuando no cabe, así que si el contenido algún día se acorta vuelve
   solo a una fila. */
#approved-modal .modal-header { flex-wrap: wrap; row-gap: var(--space-2); }
#approved-modal .apv-head-tools { margin-right: 0; flex-wrap: wrap; justify-content: flex-end; row-gap: calc(6px * var(--sp-scale, 1)); }
.vpn-chip { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); font-size: calc(10.5px * var(--fs-scale, 1)); font-weight: 700;
  letter-spacing: .04em; padding: var(--space-1) calc(10px * var(--sp-scale, 1)); border-radius: var(--radius-pill);
  color: var(--text3); background: var(--wash-2); border: 1px solid var(--border); white-space: nowrap; }
/* Sync FTP: pill hermana del chip VPN (mismas métricas) pero en acento — se lee como acción, no como estado */
.apv-sync-chip { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); font-family: inherit; font-size: calc(10.5px * var(--fs-scale, 1)); font-weight: 700;
  letter-spacing: .04em; padding: var(--space-1) calc(10px * var(--sp-scale, 1)); border-radius: var(--radius-pill); cursor: pointer;
  color: var(--accent); background: rgba(var(--accent-rgb), 0.12); border: 1px solid rgba(var(--accent-rgb), 0.35); white-space: nowrap;
  transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease; }
.apv-sync-chip:hover { background: rgba(var(--accent-rgb), 0.2); border-color: rgba(var(--accent-rgb), 0.5); }
.apv-sync-chip:active { background: rgba(var(--accent-rgb), 0.28); }
.vpn-chip .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text3); flex-shrink: 0; }
.vpn-chip.on  { color: var(--green); background: var(--green-soft); border-color: var(--green-border); }
.vpn-chip.on .dot  { background: var(--green); }
.vpn-chip.off { color: var(--red); background: var(--red-soft); border-color: var(--red-border); }
.vpn-chip.off .dot { background: var(--red); }
.apv-arch-toggle { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); font-size: calc(10.5px * var(--fs-scale, 1)); font-weight: 700;
  letter-spacing: .03em; padding: var(--space-1) calc(10px * var(--sp-scale, 1)); border-radius: var(--radius-pill); cursor: pointer;
  background: var(--wash-2); border: 1px solid var(--border); color: var(--text2); white-space: nowrap; }
.apv-arch-toggle:hover { background: var(--wash-3); color: var(--text); }
.apv-arch-toggle.active { color: var(--orange); background: var(--orange-soft); border-color: var(--orange-border); }
.apv-arch-toggle .n { font-variant-numeric: tabular-nums; background: var(--wash-3); border-radius: var(--radius-pill); padding: 0 calc(6px * var(--sp-scale, 1)); }
/* ── Chips de nivel de «Shots para revisión» y «KBKs Internos» (2026-08-26) ──
   Estos chips SÍ llevan el color de estatus: activo = relleno con el hex EXACTO
   de FPT (igual que la pastilla de estatus dentro de Flow) y el texto encima en
   negro o blanco, el que gana contraste contra ese hex — está calculado y
   documentado en los tokens --*-on de :root. El contador `.n` usa un lavado
   neutro del MISMO color del texto para no romper el par relleno/texto.
   OJO regla CSS del proyecto: el pseudo-selector/clase va en CADA alternativa
   de la lista separada por comas, no solo en la última. */
#rev-flt-rev.active   { background: var(--rev-artist);  border-color: var(--rev-artist);  color: var(--rev-artist-on);  --chip-n-wash: rgba(0,0,0,0.13); }
#rev-flt-ldapv.active { background: var(--rev-lead);    border-color: var(--rev-lead);    color: var(--rev-lead-on);    --chip-n-wash: rgba(0,0,0,0.13); }
#rev-flt-apr.active   { background: var(--rev-sup);     border-color: var(--rev-sup);     color: var(--rev-sup-on);     --chip-n-wash: rgba(0,0,0,0.13); }
#rev-flt-ctxr.active  { background: var(--rev-context); border-color: var(--rev-context); color: var(--rev-context-on); --chip-n-wash: rgba(255,255,255,0.22); }
#rev-flt-teqc.active  { background: var(--rev-qc);      border-color: var(--rev-qc);      color: var(--rev-qc-on);      --chip-n-wash: rgba(255,255,255,0.22); }
#kbk-flt-mkbk.active  { background: var(--kbk-sup);     border-color: var(--kbk-sup);     color: var(--kbk-sup-on);     --chip-n-wash: rgba(0,0,0,0.13); }
#kbk-flt-vwd.active   { background: var(--kbk-lead);    border-color: var(--kbk-lead);    color: var(--kbk-lead-on);    --chip-n-wash: rgba(255,255,255,0.22); }
#rev-flt-rev.active .n, #rev-flt-ldapv.active .n, #rev-flt-apr.active .n,
#rev-flt-ctxr.active .n, #rev-flt-teqc.active .n,
#kbk-flt-mkbk.active .n, #kbk-flt-vwd.active .n { background: var(--chip-n-wash); }
.apv-arch-banner { font-size: var(--fs-sm); color: var(--orange); background: rgba(var(--orange-rgb), .09);
  border: 1px solid rgba(var(--orange-rgb), .22); border-radius: var(--radius-sm); padding: calc(7px * var(--sp-scale, 1)) var(--space-3); margin-bottom: 12px; }
/* ── Carga degradada (UX-01, auditoría 2026-07-06): chip de fallos parciales en subtítulos ── */
.pload-badge { display: inline-flex; align-items: center; gap: var(--space-1); margin-left: calc(6px * var(--sp-scale, 1));
  padding: 1px var(--space-2); font-size: var(--fs-sm); font-weight: 600; color: var(--orange);
  background: rgba(var(--orange-rgb), .10); border: 1px solid rgba(var(--orange-rgb), .35); border-radius: var(--radius-pill);
  cursor: pointer; user-select: none; vertical-align: middle; }
.pload-badge:hover { background: rgba(var(--orange-rgb), .18); }
.pload-badge:focus-visible { outline: 2px solid var(--orange); outline-offset: 1px; }
/* ── Pestañas del modal Shots aprobados (2026-07-06) ── */
.apv-tabs { display:flex; gap: calc(2px * var(--sp-scale, 1)); padding: 0 calc(14px * var(--sp-scale, 1)); border-bottom:1px solid var(--border); flex-shrink:0; }
.apv-tab { font-size: calc(11.5px * var(--fs-scale, 1)); font-weight:600; padding: var(--space-2) var(--space-3); border:none; background:none; color:var(--text3); cursor:pointer; border-bottom:2px solid transparent; margin-bottom:-1px; }
.apv-tab:hover { color:var(--text); }
.apv-tab.active { color:var(--text); border-bottom-color:var(--accent); }
.apv-pl-name.link { color:var(--text); text-decoration:none; cursor:pointer; border-bottom:1px dotted var(--border); padding-bottom: calc(1px * var(--sp-scale, 1)); }
.apv-pl-name.link::after { content:'↗'; font-size: var(--fs-2xs); color:var(--text3); margin-left:4px; }
.apv-pl-name.link:hover { color:var(--accent); border-bottom-color:var(--accent); }
.apv-pl-name.link:hover::after { color:var(--accent); }
/* Tabla de versiones: 5 columnas que CABEN en el modal (~540-580px útiles).
   Template FIJO e idéntico en head y filas — la última columna era `auto` y,
   como cada .apv-plv-* es un grid independiente, se dimensionaba por contenido
   en cada contenedor ("Estado" angosto en el head vs "Versión agregada" ancho
   en las filas) → Type y Client Version no caían sobre sus datos.
   Thumb fijo · Link fluido con ellipsis real (minmax(0,1fr) + min-width:0) ·
   Type centrado · Client Ver fijo · Estado fijo a la derecha (110px: cabe
   "Versión agregada" a 10px). */
.apv-plv-head, .apv-plv-row { display:grid; grid-template-columns:58px minmax(0,1fr) 40px 90px 110px; gap: var(--space-2); align-items:center; padding: calc(6px * var(--sp-scale, 1)) var(--space-3); }
.apv-plv-head > span, .apv-plv-row > * { min-width:0; }
.apv-plv-head > :nth-child(3), .apv-plv-row > :nth-child(3) { text-align:center; }
.apv-plv-head > :nth-child(4), .apv-plv-row > :nth-child(4) { justify-self:center; text-align:center; }
.apv-plv-head > :last-child, .apv-plv-row > :last-child { justify-self:end; text-align:right; }
.apv-plv-head { font-size: var(--fs-2xs); font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--text3); border-bottom:1px solid var(--wash-2); }
.apv-plv-head > span { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.apv-plv-row { border-top:1px solid var(--wash-2); font-size: var(--fs-sm); min-height:34px; }
.apv-plv-row:first-of-type { border-top:none; }
.apv-plv-row:hover { background:var(--wash-1); }
.apv-plv-row .risk-code { display:block; font-family:var(--font-mono); font-size: calc(10.5px * var(--fs-scale, 1)); }
.apv-plv-type { font-weight:700; font-size: var(--fs-xs); letter-spacing:.03em; color:var(--text2); }
.apv-plv-cv { font-family:var(--font-mono); font-size: calc(10.5px * var(--fs-scale, 1)); color:var(--text2); font-variant-numeric:tabular-nums; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.apv-plv-send { font-size: var(--fs-xs); font-weight:600; padding: calc(3px * var(--sp-scale, 1)) var(--space-2); border-radius: var(--radius-xs); white-space:nowrap; }
.apv-plv-sent { color:var(--green); font-size: var(--fs-xs); font-weight:600; white-space:nowrap; }
.apv-plv-pend { color:var(--text3); font-size: var(--fs-xs); }
/* ── MOCKUP Playlists del día (Shots aprobados, 2026-07-06) ── */
.apv-pl-panel { margin:6px 10px 10px; padding: calc(9px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1)); border:1px dashed var(--border); border-radius:10px; background:var(--wash-1); font-size: var(--fs-sm); }
.apv-pl-head { display:flex; align-items:center; gap: var(--space-2); font-size: var(--fs-xs); font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--text3); margin-bottom:7px; }
.apv-pl-badge { font-size: calc(8.5px * var(--fs-scale, 1)); font-weight:800; letter-spacing:.08em; padding: calc(2px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); border-radius:5px; background:var(--yellow-soft); color:var(--yellow); }
.apv-pl-row { display:flex; align-items:center; gap: var(--space-2); padding: calc(3px * var(--sp-scale, 1)) 0; min-height:28px; }
.apv-pl-row .apv-pl-name { flex:0 1 auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.apv-pl-row .apv-pl-chip { margin-left:auto; white-space:nowrap; flex-shrink:0; }
.apv-pl-row .apv-pl-btn { white-space:nowrap; flex-shrink:0; }
.apv-pl-btn.apv-pl-create { min-width:52px; text-align:center; font-weight:700; }
.apv-pl-kind { font-weight:700; font-size: var(--fs-2xs); letter-spacing:.04em; width:30px; color:var(--text3); flex-shrink:0; }
.apv-pl-name { font-family:var(--font-mono); font-size: var(--fs-sm); color:var(--text); }
.apv-pl-chip { font-size: var(--fs-2xs); font-weight:700; text-transform:uppercase; letter-spacing:.05em; line-height:1.3; padding: calc(3px * var(--sp-scale, 1)) var(--space-2); border-radius:20px; background:var(--wash-2); color:var(--text3); white-space:nowrap; }
.apv-pl-chip.ok { background:var(--green-soft); color:var(--green); }
.apv-pl-dot { width:10px; height:10px; border-radius:50%; background:var(--yellow); flex-shrink:0; margin-left:auto; box-shadow:0 0 0 3px var(--yellow-soft); }
.apv-pl-dot.ok { background:var(--green); box-shadow:0 0 0 3px var(--green-soft); }
.apv-pl-added { font-size: calc(9.5px * var(--fs-scale, 1)); color:var(--green); white-space:nowrap; flex-shrink:0; }
.apv-pl-actions { display:flex; gap: calc(6px * var(--sp-scale, 1)); margin-top:8px; padding-top: var(--space-2); border-top:1px solid var(--wash-2); flex-wrap:wrap; }
.apv-pl-btn { font-size: calc(10.5px * var(--fs-scale, 1)); padding: var(--space-1) calc(10px * var(--sp-scale, 1)); border-radius:7px; border:1px solid var(--border); background:var(--wash-2); color:var(--text); cursor:pointer; }
.apv-pl-btn:hover { background:var(--wash-3); }
.apv-pl-btn.main { font-weight:700; border-color:rgba(var(--accent-rgb),0.45); background:rgba(var(--accent-rgb),0.14); }
.apv-pl-btn.main:hover { background:rgba(var(--accent-rgb),0.22); }

/* Acciones por fila (5ª columna del grid) */
.apv-row { grid-template-columns: auto 1fr auto 88px auto; }
.apv-actions { display: flex; gap: calc(5px * var(--sp-scale, 1)); align-items: center; }
/* .rev-act-btn (2026-07-31) comparte la pill de .apv-pub-btn: los botones de
   "Shots para revisión" y los de "Shots aprobados" son la misma familia
   visual. OJO regla CSS del proyecto: el pseudo-selector va en CADA
   alternativa de la lista separada por comas, no solo en la última. */
.apv-pub-btn, .rev-act-btn { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .03em; padding: calc(4.5px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1));
  border-radius: var(--radius-pill); cursor: pointer; border: 1px solid var(--border2);
  background: var(--wash-2); color: var(--text2); display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1));
  transition: all var(--dur-micro) var(--ease-out); white-space: nowrap; }
.apv-pub-btn:hover, .rev-act-btn:hover { color: var(--text); background: var(--wash-3); }
/* Color del destino = color de su barra en la gráfica: al pasar el mouse ya
   se lee a qué grupo va a saltar la tarjeta. Aquí el color va en TEXTO y en
   BORDE, así que se usa la TINTA (--*-ink) y no el relleno de FPT: el hex
   crudo de VFX Sup (#00f900) sobre tarjeta clara daba 1.44:1. El fondo sigue
   siendo el lavado del hex real, con lo que el tono se reconoce igual.
   `supapv` (Approval) NO es un nivel de esta gráfica: sale del flujo hacia
   "Shots aprobados", así que conserva el verde semántico del DS. */
.rev-act-btn.to-ldapv:hover  { color: var(--rev-lead-ink);    border-color: var(--rev-lead-ink);    background: var(--rev-lead-soft); }
.rev-act-btn.to-apr:hover    { color: var(--rev-sup-ink);     border-color: var(--rev-sup-ink);     background: var(--rev-sup-soft); }
.rev-act-btn.to-teqc:hover   { color: var(--rev-qc-ink);      border-color: var(--rev-qc-ink);      background: var(--rev-qc-soft); }
.rev-act-btn.to-supapv:hover { color: var(--green);  border-color: var(--green-border);  background: var(--green-soft); }
.rev-act-btn:disabled { opacity: .4; cursor: not-allowed; }
.rev-act-btn.busy { pointer-events: none; color: var(--text3); }
.apv-pub-btn.mov:hover { color: var(--cyan); border-color: var(--cyan-border); background: var(--cyan-soft); }
.apv-pub-btn.exr:hover { color: var(--purple); border-color: var(--purple-border); background: var(--purple-soft); }
.apv-pub-btn:disabled { opacity: .4; cursor: not-allowed; }
.apv-pub-btn.busy { pointer-events: none; }
/* 2026-09-01: la web ya no publica a Deadline. En lugar de los botones MOV/EXR
   va este aviso pasivo (misma pill, sin hover ni cursor: no es un botón). */
.apv-pub-hint { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .02em; padding: calc(4.5px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1));
  border-radius: var(--radius-pill); border: 1px dashed var(--border2); color: var(--text3); white-space: nowrap; cursor: help; }
.apv-spin { width: 10px; height: 10px; border: 1.5px solid currentColor; border-top-color: transparent;
  border-radius: 50%; animation: spin .7s linear infinite; }
/* (keyframe apv-rot colapsado a `spin` — H8) */
.apv-mark { font-size: var(--fs-xs); font-weight: 700; padding: 0 calc(2px * var(--sp-scale, 1)); }
.apv-mark.ok  { color: var(--green); }
.apv-mark.err { color: var(--red); cursor: help; }
.apv-icon-btn { width: 26px; height: 26px; border-radius: var(--radius-xs); border: 1px solid transparent;
  background: transparent; color: var(--text3); cursor: pointer; display: inline-flex;
  align-items: center; justify-content: center; flex-shrink: 0; }
.apv-icon-btn:hover { color: var(--orange); background: var(--orange-soft); border-color: var(--orange-border); }
.apv-icon-btn.restore:hover { color: var(--green); background: var(--green-soft); border-color: var(--green-border); }
/* Formulario de publicación */
.apv-pub-overlay { z-index: var(--z-apv-overlay); }
.apv-pub-meta { margin-bottom: 14px; padding: calc(9px * var(--sp-scale, 1)) var(--space-3); background: var(--wash-1); border: 1px solid var(--border);
  border-radius: var(--radius-sm); font-size: calc(11.5px * var(--fs-scale, 1)); color: var(--text2); display: grid; gap: calc(3px * var(--sp-scale, 1)); }
.apv-pub-meta b { color: var(--text); font-weight: 600; }
.apv-f { margin-bottom: 12px; }
.apv-f label { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--text2); margin-bottom: 5px; }
.apv-f label .req { color: var(--red); }
.apv-f input, .apv-f select, .apv-f textarea { width: 100%; background: var(--wash-1); border: 1px solid var(--border2);
  border-radius: var(--radius-sm); color: var(--text); font-size: calc(12.5px * var(--fs-scale, 1)); padding: var(--space-2) calc(10px * var(--sp-scale, 1)); font-family: inherit; outline: none; }
.apv-f input:focus, .apv-f select:focus, .apv-f textarea:focus { border-color: var(--accent); }
.apv-f textarea { resize: vertical; min-height: 58px; }

  /* ── Calendario: drag & drop de milestones WIP/PPF (2026-07-02) ── */
  .cal-draggable { cursor: grab; touch-action: pan-y; }
  .cal-draggable:active { cursor: grabbing; }
  /* BUG 2026-08-03: el <img> del thumbnail y el <a> del VFX ID disparaban el
     DRAG NATIVO del navegador (fantasma del browser) y secuestraban el gesto —
     el DnD propio nunca arrancaba. Se notó cuando los thumbs empezaron a bajar
     para TODOS los shots (07-30): tarjetas con imagen real = área de agarre
     nativamente arrastrable. Cinturón doble: aquí + preventDefault en dragstart. */
  .cal-draggable img, .cal-draggable a { -webkit-user-drag: none; user-drag: none; }
  .cal-drag-src { opacity: .35; }
  body.cal-dragging { user-select: none; -webkit-user-select: none; cursor: grabbing; }
  .cal-day-col.cal-drop-hover,
  .cal-month-cell.cal-drop-hover {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
    background: var(--accent-soft);
    border-radius: 8px;
    transition: background var(--dur-micro);
  }

  /* ── Drag-to-edge: franjas ‹ › visibles solo durante el arrastre ── */
  .cal-edge-zone {
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(to right, rgba(var(--accent-rgb), .10), transparent);
    opacity: .75; transition: opacity var(--dur-fast), background var(--dur-fast);
  }
  .cal-edge-zone.right { background: linear-gradient(to left, rgba(var(--accent-rgb), .10), transparent); }
  .cal-edge-zone .cal-edge-arrow {
    font-size: calc(22px * var(--fs-scale, 1)); font-weight: 700; color: var(--accent);
    background: var(--card); border: 1px solid var(--accent-border);
    width: 30px; height: 30px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    box-shadow: var(--shadow-card);
  }
  .cal-edge-zone.armed { opacity: 1; background: linear-gradient(to right, rgba(var(--accent-rgb), .22), transparent); }
  .cal-edge-zone.right.armed { background: linear-gradient(to left, rgba(var(--accent-rgb), .22), transparent); }
  .cal-edge-zone.armed .cal-edge-arrow { animation: cal-edge-pulse .6s ease-in-out infinite; }
  @keyframes cal-edge-pulse { 50% { transform: scale(1.18); } }

  /* ── Panel de tarjeta: bloque Reprogramar ── */
  .cal-resched { margin-top: 14px; padding: var(--space-3); background: var(--wash-1); border: 1px solid var(--border); border-radius: 10px; }
  .cal-resched-label { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text3); margin-bottom: 8px; }
  .cal-resched-row { display: flex; gap: var(--space-2); align-items: center; }
  /* (2026-07-29) .cal-resched-input eliminado: el input nativo se reemplazó
     por el picker unificado OTDP. El .otdp ocupa el espacio flexible. */
  .cal-resched-row .otdp { flex: 1; min-width: 0; }
  .cal-resched-btn { width: auto; background: var(--accent); color: #fff; border: none; }
  .cal-resched-btn:hover { background: var(--accent-hover); }
  .cal-resched-btn:disabled { opacity: .5; }
  .cal-resched-hint { font-size: var(--fs-xs); color: var(--text3); margin-top: 7px; line-height: 1.4; }

  /* ── Artistas › Global: toggle In-house (2026-07-02) ── */
  .inhouse-toggle {
    display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1));
    height: 26px; padding: 0 calc(11px * var(--sp-scale, 1));
    border-radius: var(--radius-pill, 999px); border: 1px solid var(--border);
    background: var(--card2); color: var(--text2);
    font-size: var(--fs-sm); font-weight: 600; font-family: inherit;
    cursor: pointer; white-space: nowrap; flex-shrink: 0;
    transition: background var(--dur-micro), color var(--dur-micro), border-color var(--dur-micro);
  }
  .inhouse-toggle:hover { background: var(--wash-3); color: var(--text); }
  .inhouse-toggle .inhouse-toggle-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--text3); transition: background var(--dur-micro);
  }
  .inhouse-toggle.active {
    background: rgba(var(--accent-rgb), .14);
    border-color: rgba(var(--accent-rgb), .35);
    color: var(--accent);
  }
  .inhouse-toggle.active .inhouse-toggle-dot { background: var(--green); }

  /* ══ VFX PLANNER / CALENDAR CREW — estilos scoped a #page-calendar-crew (portados del mockup) ══ */
#page-calendar-crew * { box-sizing:border-box; margin:0; padding:0; }#page-calendar-crew .screen { display:none; }#page-calendar-crew .screen.active { display:block; }#page-calendar-crew .wrap { max-width:1440px; margin:0 auto; padding: calc(22px * var(--sp-scale, 1)) var(--space-6) calc(60px * var(--sp-scale, 1)); }#page-calendar-crew /* ── Header genérico ── */
  .topbar { display:flex; align-items:center; gap: var(--space-3); margin-bottom:20px; flex-wrap:wrap; }#page-calendar-crew .topbar h1 { font-size: calc(22px * var(--fs-scale, 1)); font-weight:700; letter-spacing:-0.5px; }#page-calendar-crew .topbar .sub { font-size: var(--fs-base); color:var(--text2); }#page-calendar-crew .spacer { flex:1; }#page-calendar-crew .badge-admin {
    font-size: var(--fs-xs); font-weight:700; text-transform:uppercase; letter-spacing:.06em;
    color:var(--orange); background:var(--orange-soft); border:1px solid rgba(var(--orange-rgb),0.3);
    padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius:var(--radius-pill);
  }#page-calendar-crew .badge-mock {
    font-size: var(--fs-xs); font-weight:700; text-transform:uppercase; letter-spacing:.06em;
    color:var(--purple); background:var(--purple-soft); border:1px solid var(--purple-border);
    padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius:var(--radius-pill);
  }#page-calendar-crew .btn {
    display:inline-flex; align-items:center; gap: calc(6px * var(--sp-scale, 1)); padding: var(--space-2) calc(14px * var(--sp-scale, 1));
    border-radius:var(--radius-sm); border:1px solid var(--border2); background:var(--card);
    color:var(--text); font-size: var(--fs-base); font-weight:600; cursor:pointer;
    transition:background var(--dur-micro), border-color var(--dur-micro);
  }#page-calendar-crew .btn:hover { background:var(--wash-2); }#page-calendar-crew .btn.primary { background:var(--accent); border-color:var(--accent); color:#fff; }#page-calendar-crew .btn.primary:hover { background:var(--accent-hover); }#page-calendar-crew .btn.ghost { background:transparent; }#page-calendar-crew .btn.sm { padding: calc(5px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); font-size: var(--fs-sm); }#page-calendar-crew .icon-btn {
    width:32px; height:32px; display:inline-flex; align-items:center; justify-content:center;
    border-radius:var(--radius-xs); border:1px solid var(--border); background:var(--card2);
    color:var(--text2); cursor:pointer; font-size: var(--fs-lg);
  }#page-calendar-crew .icon-btn:hover { background:var(--accent-soft); color:var(--accent); }#page-calendar-crew .icon-btn.lang { width:auto; padding: 0 calc(10px * var(--sp-scale, 1)); font-size: var(--fs-sm); font-weight:700; }#page-calendar-crew .proj-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(270px,1fr)); gap: calc(14px * var(--sp-scale, 1)); }#page-calendar-crew .proj-card {
    background:var(--card); border:1px solid var(--border); border-radius:var(--radius);
    padding: var(--space-5); box-shadow:var(--shadow-card); display:flex; flex-direction:column; gap: var(--space-3);
  }#page-calendar-crew .proj-card.archived-card { opacity:.6; }#page-calendar-crew .proj-head { display:flex; align-items:center; gap: calc(10px * var(--sp-scale, 1)); }#page-calendar-crew .proj-code { font-size: calc(20px * var(--fs-scale, 1)); font-weight:700; letter-spacing:-0.5px; font-family:var(--font-mono); }#page-calendar-crew .proj-actions { margin-left:auto; display:flex; gap: var(--space-1); opacity:0; transition:opacity var(--dur-fast); }#page-calendar-crew .proj-card:hover .proj-actions { opacity:1; }#page-calendar-crew .proj-act {
    width:26px; height:26px; border:1px solid var(--border); background:var(--card2);
    color:var(--text2); cursor:pointer; border-radius:var(--radius-xs); font-size: var(--fs-base);
    display:inline-flex; align-items:center; justify-content:center;
  }#page-calendar-crew .proj-act:hover { background:var(--accent-soft); color:var(--accent); }#page-calendar-crew .proj-act.danger:hover { background:var(--red-soft); color:var(--red); border-color:var(--red-border); }#page-calendar-crew .proj-meta { display:grid; grid-template-columns:1fr 1fr; gap: var(--space-2) calc(14px * var(--sp-scale, 1)); }#page-calendar-crew .proj-meta .m label { display:block; font-size: var(--fs-2xs); font-weight:600; text-transform:uppercase; letter-spacing:.06em; color:var(--text3); margin-bottom:2px; }#page-calendar-crew .proj-meta .m span { font-size: var(--fs-md); font-weight:600; font-variant-numeric:tabular-nums; }#page-calendar-crew .proj-foot { font-size: calc(10.5px * var(--fs-scale, 1)); color:var(--text3); border-top:1px solid var(--border); padding-top: calc(10px * var(--sp-scale, 1)); display:flex; align-items:center; gap: var(--space-2); }#page-calendar-crew .proj-card.add {
    border:1px dashed var(--border2); background:transparent; box-shadow:none;
    align-items:center; justify-content:center; text-align:center; gap: var(--space-2); min-height:170px;
    color:var(--text3); font-weight:600;
  }#page-calendar-crew .proj-card.add:hover { border-color:var(--accent); color:var(--accent); box-shadow:none; }#page-calendar-crew .proj-card.add .plus { font-size: calc(28px * var(--fs-scale, 1)); line-height:1; }#page-calendar-crew .arch-title { font-size: var(--fs-xs); font-weight:700; text-transform:uppercase; letter-spacing:.07em; color:var(--text3); margin:26px 0 10px; }#page-calendar-crew /* ── Secciones del planner ── */
  .section { margin-bottom:26px; }#page-calendar-crew .section-title {
    font-size: var(--fs-xs); font-weight:600; color:var(--text3); text-transform:uppercase;
    letter-spacing:.07em; display:flex; align-items:center; gap: var(--space-2); margin-bottom:10px;
  }#page-calendar-crew .section-title .hint { text-transform:none; letter-spacing:0; font-weight:400; color:var(--text3); }#page-calendar-crew .card {
    background:var(--card); border:1px solid var(--border); border-radius:var(--radius);
    box-shadow:var(--shadow-card); overflow:hidden;
  }#page-calendar-crew .card-pad { padding: var(--space-4) calc(18px * var(--sp-scale, 1)); }#page-calendar-crew /* ── Tablas editables ── */
  .tbl-scroll { overflow-x:auto; }#page-calendar-crew table.ft { width:100%; border-collapse:collapse; font-size: var(--fs-base); }#page-calendar-crew table.ft th {
    font-size: calc(9.5px * var(--fs-scale, 1)); font-weight:600; text-transform:uppercase; letter-spacing:.06em;
    color:var(--text3); text-align:left; padding: calc(9px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-bottom:1px solid var(--border);
    white-space:nowrap; background:var(--card2);
  }#page-calendar-crew table.ft td { padding: calc(5px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-bottom:1px solid var(--border); white-space:nowrap; }#page-calendar-crew table.ft tr:last-child td { border-bottom:none; }#page-calendar-crew table.ft tr.total-row td { font-weight:700; background:var(--wash-1); }#page-calendar-crew table.ft td.num, #page-calendar-crew table.ft th.num { text-align:right; }#page-calendar-crew td.calc { color:var(--text2); font-variant-numeric:tabular-nums; text-align:right; }#page-calendar-crew td.calc b { color:var(--text); }#page-calendar-crew input.cell, #page-calendar-crew select.cell {
    background:transparent; border:1px solid transparent; border-radius:var(--radius-xs);
    color:var(--text); font:inherit; padding: var(--space-1) calc(6px * var(--sp-scale, 1)); width:100%; min-width:70px;
    transition:border-color var(--dur-micro), background var(--dur-micro);
  }#page-calendar-crew input.cell:hover, #page-calendar-crew select.cell:hover { background:var(--wash-1); }#page-calendar-crew input.cell:focus, #page-calendar-crew select.cell:focus { outline:none; border-color:var(--accent-border); background:var(--wash-1); }#page-calendar-crew input.cell.n { text-align:right; min-width:54px; max-width:90px; font-variant-numeric:tabular-nums; }
  /* Inputs de dinero formateado ($72,000 / $3,310.34) del booking (2026-07-15):
     ancho mínimo para que el número NUNCA se corte al comprimir la ventana —
     la tabla vive en .tbl-scroll y scrollea horizontal en vez de recortar. */
  #page-calendar-crew input.cell.n[data-k] { min-width:88px; max-width:112px; }
  /* Checkboxes de selección invisibles hasta pasar el cursor por la fila
     (feedback 2026-07-15, aplica a TODAS las tablas del planner por igual).
     Siguen visibles si están marcados o con foco de teclado (a11y). */
  #page-calendar-crew table.ft tbody td:first-child > input[type=checkbox],
  #page-calendar-crew table.ft thead input[type=checkbox] { opacity:0; transition:opacity var(--dur-micro); }
  #page-calendar-crew table.ft tbody tr:hover td:first-child > input[type=checkbox],
  #page-calendar-crew table.ft thead tr:hover input[type=checkbox],
  #page-calendar-crew table.ft input[type=checkbox]:checked,
  #page-calendar-crew table.ft input[type=checkbox]:focus-visible { opacity:1; }#page-calendar-crew input.cell.d { min-width:96px; max-width:110px; font-variant-numeric:tabular-nums; cursor:pointer; caret-color:transparent; }#page-calendar-crew input.cell.t { min-width:110px; }#page-calendar-crew .money { display:inline-flex; align-items:center; gap: calc(1px * var(--sp-scale, 1)); color:var(--text2); font-weight:600; }#page-calendar-crew .money input { min-width:76px; }#page-calendar-crew .row-del {
    width:24px; height:24px; border:none; background:transparent; color:var(--text3);
    cursor:pointer; border-radius:var(--radius-xs); font-size: var(--fs-md);
  }#page-calendar-crew .row-del:hover { background:var(--red-soft); color:var(--red); }#page-calendar-crew .add-row {
    display:flex; align-items:center; gap: calc(6px * var(--sp-scale, 1)); padding: calc(9px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); width:100%;
    background:transparent; border:none; border-top:1px dashed var(--border2);
    color:var(--text3); font-size: calc(11.5px * var(--fs-scale, 1)); font-weight:600; cursor:pointer;
  }#page-calendar-crew .add-row:hover { color:var(--accent); }#page-calendar-crew /* ── KPIs ── */
  .kpi-row { display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap: var(--space-3); }#page-calendar-crew .kpi-card {
    background:var(--card); border:1px solid var(--border); border-radius:var(--radius);
    padding: var(--space-4) calc(18px * var(--sp-scale, 1)); border-left:3px solid var(--accent); box-shadow:var(--shadow-card);
  }#page-calendar-crew .kpi-card.g { border-left-color:var(--green); }#page-calendar-crew .kpi-card.o { border-left-color:var(--orange); }#page-calendar-crew .kpi-card.p { border-left-color:var(--purple); }#page-calendar-crew .kpi-v { font-size: calc(28px * var(--fs-scale, 1)); font-weight:700; letter-spacing:-1px; line-height:1; font-variant-numeric:tabular-nums; }#page-calendar-crew .kpi-l { font-size: var(--fs-sm); color:var(--text2); margin-top:6px; font-weight:500; }#page-calendar-crew .split { display:grid; grid-template-columns:5fr 7fr; gap: var(--space-4); align-items:start; }
  @media (max-width:1100px){#page-calendar-crew .split { grid-template-columns:1fr; } }#page-calendar-crew /* Budget listas */
  .bline { display:flex; align-items:center; justify-content:space-between; gap: calc(10px * var(--sp-scale, 1)); padding: calc(7px * var(--sp-scale, 1)) 0; border-bottom:1px solid var(--border); font-size: var(--fs-base); }#page-calendar-crew .bline:last-child { border-bottom:none; }#page-calendar-crew .bline .lbl { color:var(--text2); }#page-calendar-crew .bline .val { font-weight:600; font-variant-numeric:tabular-nums; }#page-calendar-crew .bline .val.over { color:var(--red); }#page-calendar-crew .bline.total { font-weight:700; }#page-calendar-crew .bline.total .lbl { color:var(--text); }#page-calendar-crew .bline .pct { font-size: var(--fs-xs); color:var(--text3); margin-left:6px; }#page-calendar-crew .bline .money input { max-width:100px; text-align:right; font-weight:600; }#page-calendar-crew .bgroup-title { font-size: var(--fs-xs); font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--text3); margin:14px 0 4px; }#page-calendar-crew .bgroup-title:first-child { margin-top:0; }#page-calendar-crew /* ── Calendarios ── */
  .cal-scroll { overflow-x:auto; padding-bottom: var(--space-1); }#page-calendar-crew .cal { display:grid; font-size: var(--fs-xs); min-width:max-content; }#page-calendar-crew .cal-rowlabel {
    position:sticky; left:0; background:var(--card); z-index:2; padding: 0 var(--space-3) 0 calc(14px * var(--sp-scale, 1));
    display:flex; align-items:center; font-weight:600; font-size: var(--fs-sm); white-space:nowrap;
    border-right:1px solid var(--border); min-width:150px; gap: calc(6px * var(--sp-scale, 1));
  }#page-calendar-crew .cal-rowlabel small { color:var(--text3); font-weight:400; }/* Filas de título del Bookings Calendar (fix encimado 2026-07-20): ocupan todo el ancho del grid (sin celdas detrás) y el texto es sticky para sobrevivir el scroll horizontal */#page-calendar-crew .cal-secrow { display:flex; align-items:center; height:30px; background:var(--wash-1); border-top:1px solid var(--wash-2); }#page-calendar-crew .cal-secrow.sub { background:transparent; height:26px; }#page-calendar-crew .cal-secrow .cal-sectitle { position:sticky; left:0; padding:0 var(--space-3) 0 calc(14px * var(--sp-scale, 1)); font-weight:700; font-size: calc(9.5px * var(--fs-scale, 1)); text-transform:uppercase; letter-spacing:.06em; color:var(--text3); white-space:nowrap; }#page-calendar-crew .cal-secrow.sub .cal-sectitle { padding-left: calc(26px * var(--sp-scale, 1)); font-size: var(--fs-2xs); }#page-calendar-crew .cal-cell { width:34px; height:30px; border-right:1px solid var(--wash-2); border-top:1px solid var(--wash-2); position:relative; display:flex; align-items:center; justify-content:center; }#page-calendar-crew .cal-head { height:26px; font-size: var(--fs-2xs); color:var(--text3); font-variant-numeric:tabular-nums; border-top:none; }#page-calendar-crew .cal-month { height:20px; border-top:none; border-right:none; font-size: var(--fs-2xs); font-weight:700; color:var(--text2); text-transform:uppercase; letter-spacing:.05em; justify-content:flex-start; padding-left: var(--space-1); overflow:visible; white-space:nowrap; }#page-calendar-crew .cal-cell.holiday::after { content:''; position:absolute; top:2px; right:2px; width:5px; height:5px; border-radius:50%; background:var(--red); }#page-calendar-crew .cal-head.now { color:var(--accent); font-weight:700; background:rgba(var(--accent-rgb),0.16); }#page-calendar-crew .cal-cell.now-col { background:rgba(var(--accent-rgb),0.06); box-shadow:inset 1px 0 0 rgba(var(--accent-rgb),0.45), inset -1px 0 0 rgba(var(--accent-rgb),0.45); }#page-calendar-crew .seg { position:absolute; inset:6px 1px; border-radius:4px; background:var(--accent-soft); }#page-calendar-crew .seg.full { background:rgba(var(--accent-rgb),0.35); }#page-calendar-crew .seg.shield { background:repeating-linear-gradient(135deg, var(--orange-soft), var(--orange-soft) 4px, rgba(var(--orange-rgb),0.32) 4px, rgba(var(--orange-rgb),0.32) 8px); }#page-calendar-crew .seg.book { background:rgba(var(--accent-rgb),0.28); inset:5px 1px; }#page-calendar-crew .seg.book.mx { background:rgba(var(--green-rgb),0.30); }#page-calendar-crew .seg.book.sup { background:rgba(var(--purple-rgb),0.32); }#page-calendar-crew .mark-temps { position:absolute; bottom:3px; left:50%; transform:translateX(-50%); width:6px; height:6px; border-radius:50%; background:var(--yellow); z-index:1; }#page-calendar-crew .mark-del { position:absolute; top:1px; left:50%; transform:translateX(-50%); font-size: var(--fs-2xs); z-index:1; }#page-calendar-crew .spw-cell { font-size: calc(9.5px * var(--fs-scale, 1)); font-weight:600; font-variant-numeric:tabular-nums; color:var(--text2); }#page-calendar-crew .spw-cell.hot { background:var(--red-soft); color:var(--red); }#page-calendar-crew .spw-cell.warm { background:var(--yellow-soft); color:var(--yellow); }#page-calendar-crew .cal-legend { display:flex; gap: var(--space-4); flex-wrap:wrap; padding: calc(10px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); border-top:1px solid var(--border); font-size: calc(10.5px * var(--fs-scale, 1)); color:var(--text2); }#page-calendar-crew .lg { display:flex; align-items:center; gap: calc(6px * var(--sp-scale, 1)); }#page-calendar-crew .lg i { width:14px; height:10px; border-radius:3px; display:inline-block; }#page-calendar-crew /* ── Modales ── */
  .backdrop {
    position:fixed; inset:0; background:rgba(0,0,0,0.5); display:none;
    align-items:center; justify-content:center; z-index:var(--z-modal); padding: var(--space-5);
  }#page-calendar-crew .backdrop.open { display:flex; }#page-calendar-crew .modal {
    width:min(680px, 96vw); max-height:86vh; background:var(--card);
    border:1px solid var(--border2); border-radius:var(--radius-lg);
    box-shadow:var(--shadow-modal); display:flex; flex-direction:column; overflow:hidden;
  }#page-calendar-crew .modal.wide { width:min(860px,96vw); }#page-calendar-crew .modal-head { display:flex; align-items:center; gap: calc(10px * var(--sp-scale, 1)); padding: var(--space-4) var(--space-5); border-bottom:1px solid var(--border); }#page-calendar-crew .modal-head h3 { font-size: calc(15px * var(--fs-scale, 1)); font-weight:700; flex:1; }#page-calendar-crew .modal-body { overflow-y:auto; padding: calc(18px * var(--sp-scale, 1)) var(--space-5); }#page-calendar-crew .modal-foot { display:flex; justify-content:flex-end; gap: calc(10px * var(--sp-scale, 1)); padding: calc(14px * var(--sp-scale, 1)) var(--space-5); border-top:1px solid var(--border); }#page-calendar-crew .cfg-grid { display:grid; grid-template-columns:1fr 1fr; gap: calc(14px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1)); }
  @media (max-width:640px){#page-calendar-crew .cfg-grid { grid-template-columns:1fr; } }#page-calendar-crew .field label { display:block; font-size: var(--fs-xs); font-weight:600; text-transform:uppercase; letter-spacing:.06em; color:var(--text3); margin-bottom:5px; }#page-calendar-crew .field input, #page-calendar-crew .field select {
    width:100%; padding: var(--space-2) calc(10px * var(--sp-scale, 1)); border-radius:var(--radius-sm); border:1px solid var(--border2);
    background:var(--card2); color:var(--text); font:inherit;
  }#page-calendar-crew .field input:focus, #page-calendar-crew .field select:focus { outline:none; border-color:var(--accent); }#page-calendar-crew .field input.dp-input { cursor:pointer; caret-color:transparent; }#page-calendar-crew .chip { display:inline-flex; align-items:center; gap: calc(6px * var(--sp-scale, 1)); padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-radius:var(--radius-pill); font-size: var(--fs-sm); font-weight:600; background:var(--wash-2); }#page-calendar-crew .chip .zone { font-size: var(--fs-2xs); font-weight:700; color:var(--accent); text-transform:uppercase; }/* Chip IA (Centro de Imports 2026-07-20): mismo look morado que la marca IA de Project Cost (.bpc-ia-btn.on) */#page-calendar-crew .chip.vp-chip-ia { background:rgba(var(--purple-rgb),0.14); color:var(--purple); }#page-calendar-crew .chip button { border:none; background:none; color:var(--text3); cursor:pointer; font-size: var(--fs-base); }#page-calendar-crew .chip button:hover { color:var(--red); }#page-calendar-crew .chips { display:flex; flex-wrap:wrap; gap: calc(6px * var(--sp-scale, 1)); margin-top:8px; }#page-calendar-crew .status-chip { font-size: var(--fs-xs); font-weight:700; padding: calc(2px * var(--sp-scale, 1)) var(--space-2); border-radius:var(--radius-pill); }#page-calendar-crew .status-chip.apv { background:var(--green-soft); color:var(--green); }#page-calendar-crew .status-chip.sent { background:var(--yellow-soft); color:var(--yellow); }#page-calendar-crew .status-chip.bid { background:var(--wash-2); color:var(--text3); }/* ── Datepicker propio (estética FlowTracker) ── */
  /* (2026-07-29) Unificado con el picker canónico OTDP: misma tipografía,
     celdas circulares y botones de footer tipo píldora. */
  #page-calendar-crew #vp-dp {
    position:fixed; z-index: var(--z-vp-datepicker); width:248px; background:var(--card);
    border:1px solid var(--border2); border-radius:14px;
    box-shadow:var(--shadow-pop); padding: var(--space-3) calc(14px * var(--sp-scale, 1)) var(--space-3); display:none;
  }#page-calendar-crew #vp-dp.open { display:block; }#page-calendar-crew .dp-head { display:flex; align-items:center; gap: calc(6px * var(--sp-scale, 1)); margin-bottom:10px; }#page-calendar-crew .dp-title { flex:1; font-size: var(--fs-lg); font-weight:600; letter-spacing:-.4px; text-transform:capitalize; text-align:center; order:1; }#page-calendar-crew .dp-nav {
    width:26px; height:26px; border-radius:8px; border:1px solid var(--wash-3);
    background:var(--wash-2); color:var(--text2); cursor:pointer; font-size: var(--fs-base);
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
    transition: background var(--dur-micro), color var(--dur-micro), border-color var(--dur-micro), transform var(--dur-micro);
  }#page-calendar-crew .dp-nav:hover { background:var(--wash-4); border-color:var(--wash-4); color:var(--text); transform:scale(1.08); }#page-calendar-crew .dp-nav:first-of-type { order:0; }#page-calendar-crew .dp-nav:last-of-type { order:2; }#page-calendar-crew .dp-grid { display:grid; grid-template-columns:repeat(7,1fr); gap: calc(1px * var(--sp-scale, 1)); }#page-calendar-crew .dp-wd { text-align:center; font-size: calc(9.5px * var(--fs-scale, 1)); font-weight:700; color:var(--text3); letter-spacing:.07em; text-transform:uppercase; padding: 0 0 calc(7px * var(--sp-scale, 1)); }#page-calendar-crew .dp-day {
    aspect-ratio:1; display:flex; align-items:center; justify-content:center; position:relative;
    font-size: calc(12.5px * var(--fs-scale, 1)); font-variant-numeric:tabular-nums; border-radius:50%;
    cursor:pointer; color:var(--text2);
    transition: background var(--dur-micro), color var(--dur-micro), transform var(--dur-micro);
  }#page-calendar-crew .dp-day:hover { background:var(--wash-3); color:var(--text); transform:scale(1.08); }#page-calendar-crew .dp-day.out { color:var(--text3); opacity:.35; }#page-calendar-crew .dp-day.today { color:var(--accent); font-weight:700; }#page-calendar-crew .dp-day.today::after { content:''; position:absolute; bottom:3px; left:50%; transform:translateX(-50%); width:3.5px; height:3.5px; border-radius:50%; background:var(--accent); }#page-calendar-crew .dp-day.sel { background:var(--accent); color:#fff; font-weight:600; box-shadow: 0 2px 8px rgba(var(--accent-rgb),.5), 0 0 0 1px rgba(var(--accent-rgb),.3); }#page-calendar-crew .dp-foot { display:flex; gap: calc(7px * var(--sp-scale, 1)); margin-top:12px; padding-top: var(--space-3); border-top:1px solid var(--wash-2); }#page-calendar-crew .dp-link { flex:1; height:30px; border-radius:8px; font-size: var(--fs-base); font-weight:600; cursor:pointer; font-family:inherit; letter-spacing:-.2px; background:transparent; color:var(--text2); border:1px solid var(--wash-4); transition: background var(--dur-fast), color var(--dur-fast), box-shadow var(--dur-fast), transform var(--dur-micro); }#page-calendar-crew .dp-link:hover { background:var(--wash-3); color:var(--text); }#page-calendar-crew .dp-link:last-child { background:var(--accent); color:#fff; border:none; box-shadow: 0 1px 6px rgba(var(--accent-rgb),.35); }#page-calendar-crew .dp-link:last-child:hover { background:var(--accent-hover); box-shadow: 0 3px 12px rgba(var(--accent-rgb),.5); }#page-calendar-crew /* ── Dropzone de ingesta xlsx ── */
  .dropzone {
    border:1.5px dashed var(--border2); border-radius:var(--radius-sm);
    padding: var(--space-4) calc(14px * var(--sp-scale, 1)); text-align:center; cursor:pointer; margin-bottom:12px;
    color:var(--text3); font-size: var(--fs-base); transition:border-color var(--dur-fast), background var(--dur-fast);
  }#page-calendar-crew .dropzone:hover, #page-calendar-crew .dropzone.drag { border-color:var(--accent); background:var(--accent-soft); color:var(--accent); }#page-calendar-crew .dropzone b { color:var(--text2); font-weight:600; }#page-calendar-crew .dropzone.drag b { color:var(--accent); }#page-calendar-crew .dz-cols { font-size: calc(10.5px * var(--fs-scale, 1)); color:var(--text3); margin:-4px 0 12px; line-height:1.5; }#page-calendar-crew .dz-cols b { color:var(--text2); }

  @media (max-width:820px){#page-calendar-crew .wrap { padding: var(--space-4) calc(14px * var(--sp-scale, 1)) calc(50px * var(--sp-scale, 1)); }#page-calendar-crew .topbar h1 { font-size: calc(19px * var(--fs-scale, 1)); }#page-calendar-crew .kpi-v { font-size: calc(23px * var(--fs-scale, 1)); }
  }

  /* ── Proyectos: panel de filtros flotante (mismo look/UX que Artistas) ──
     Separado del borde de la página y del detalle, con scroll propio para
     que no se rompa al hacer scroll en el contenido. ── */
  .projects-layout > aside { margin: 16px 24px 16px 18px; overflow-y: auto; }

  /* ── Utilidad: contenedor desplazable SIN barra visible (Artistas · Global).
     El scroll funciona igual (rueda/trackpad); solo se oculta la línea. ── */
  .vscroll-quiet { scrollbar-width: none; -ms-overflow-style: none; }
  .vscroll-quiet::-webkit-scrollbar { display: none; width: 0; height: 0; }

  /* ── Calendar Crew: modal de configuración compacto (la info es poca) ── */
  #page-calendar-crew #vp-modal-cfg .modal { width: min(480px, 96vw); }
  #page-calendar-crew #vp-modal-cfg .modal-body { padding: calc(14px * var(--sp-scale, 1)) var(--space-4); }
  #page-calendar-crew #vp-modal-cfg .cfg-grid { gap: calc(10px * var(--sp-scale, 1)) var(--space-3); }
  #page-calendar-crew #vp-modal-cfg .field input, 
  #page-calendar-crew #vp-modal-cfg .field select { padding: calc(6px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); font-size: var(--fs-base); }

  /* ── Calendar Crew · modal cfg: inputs alineados aunque el label haga 2 líneas ── */
  #page-calendar-crew #vp-modal-cfg .cfg-grid .field { display: flex; flex-direction: column; }
  #page-calendar-crew #vp-modal-cfg .cfg-grid .field label { flex: 1; }
  #page-calendar-crew #vp-modal-cfg .cfg-grid .field input,
  #page-calendar-crew #vp-modal-cfg .cfg-grid .field select { margin-top: auto; }

  /* ── Calendar Crew: columnas de dinero estilo contable — $ anclado a la
     izquierda (misma posición en todas las filas) y cifra a la derecha. ── */
  #page-calendar-crew .money { width: 108px; justify-content: flex-start; }

  /* ── Calendar Crew: TOs archivados (entregados) — atenuados, con chip ── */
  #page-calendar-crew .vp-row-archived td { opacity: .5; }
  #page-calendar-crew .vp-row-archived td:last-child { opacity: 1; }
  #page-calendar-crew .vp-arch-chip {
    font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
    color: var(--text3); background: var(--wash-2); border-radius: var(--radius-pill);
    padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); margin-left: 6px; vertical-align: 1px;
  }
  #page-calendar-crew .vp-arch-btn:hover { background: var(--accent-soft); color: var(--accent); }

  /* ── Herramientas por PERMISO (Fase A, 2026-08-20) ──
     Cada tarjeta del hub se muestra solo si /proxy/me trajo su permiso
     (clases perm--* que pinta perms.js). El marcador .perms-loaded evita
     esconderlo todo durante el arranque en frío. Reemplaza las 4 listas
     negras por rol que había (estandar/coordinador/PM/avisos).
     OJO: presentación, no seguridad — la ley es requirePerm() en el server. ── */
  #view-app.perms-loaded:not(.perm--tasks-use) #page-reports .report-card[data-action*="'tasks'"],
  #view-app.perms-loaded:not(.perm--rondin-use) #page-reports .report-card[data-action*="'rondin'"],
  #view-app.perms-loaded:not(.perm--monitor-read) #page-reports .report-card[data-action*="'report-monitoring'"],
  #view-app.perms-loaded:not(.perm--reports-ot-run) #page-reports .report-card[data-action*="'report-ot'"],
  #view-app.perms-loaded:not(.perm--reports-production-run) #page-reports .report-card[data-action*="'report-prod'"],
  /* Tools portadas de Shotly iOS (2026-08-24) — Avisos se retiró del hub. */
  #view-app.perms-loaded:not(.perm--reports-run) #page-reports .report-card[data-action*="'report-client'"],
  #view-app.perms-loaded:not(.perm--comfy-credits-request) #page-reports .report-card[data-action*="'credits'"],
  #view-app.perms-loaded:not(.perm--tools-contacts-use) #page-reports .report-card[data-action*="'contact-list'"],
  #view-app.perms-loaded:not(.perm--tools-groups-use) #page-reports .report-card[data-action*="'gmail-groups'"],
  #view-app.perms-loaded:not(.perm--tools-meet-use) #page-reports .report-card[data-action*="'meet'"],
  /* «Playlist para revisión - AM/PM» del Dashboard: quien no puede escribir
     playlists no tiene nada que hacer ahí (el botón es toda la sección). */
  #view-app.perms-loaded:not(.perm--playlist-write) #dash-pli-card,
  /* ⚠ Créditos Comfy: la tarjeta #comfy-card NO se gatea (revertido el
     2026-08-24 tarde). El SALDO se ve sin permiso —igual que en iOS, donde el
     KPI y `ComfyCreditsSheet` no consultan ningún permiso, e igual que en el
     server, donde `GET /proxy/comfy/credits` no lleva `requirePerm`—. Lo único
     que cuelga de `comfy.credits.request` es el CONSUMO por periodo, que el
     server sí corta con 403; ese bloque vive dentro de #comfy-modal, que está
     FUERA de #view-app (es hermano suyo en el body), así que su gate no se
     puede escribir con este patrón: lo aplica comfy-creditos.js poniendo la
     clase .comfy-usage--sin-permiso (ver más arriba, junto a .comfy-usage). */
  #view-app.perms-loaded:not(.perm--audit-read) #nav-adm-bitacora { display: none !important; }
  /* Respaldo del arranque en frío (sin /me aún): las tools portadas y Equipo
     nacen negadas para no-admin; que no parpadeen antes de que llegue /me. */
  #view-app:not(.perms-loaded):not(.role-admin) #page-reports .report-card[data-action*="'report-client'"],
  #view-app:not(.perms-loaded):not(.role-admin) #page-reports .report-card[data-action*="'credits'"],
  #view-app:not(.perms-loaded):not(.role-admin) #page-reports .report-card[data-action*="'contact-list'"],
  #view-app:not(.perms-loaded):not(.role-admin) #page-reports .report-card[data-action*="'gmail-groups'"],
  #view-app:not(.perms-loaded):not(.role-admin) #page-reports .report-card[data-action*="'meet'"],
  /* La tarjeta de playlists del Dashboard entra al MISMO respaldo (revisión
     de integración): sin esto, un no-admin veía —y podía apretar— «Crear
     playlists» en el parpadeo previo a /me.
     #comfy-card SALIÓ de esta lista el 2026-08-24 (tarde): su saldo se ve sin
     permiso, así que no hay nada que ocultar en el arranque en frío. */
  #view-app:not(.perms-loaded):not(.role-admin) #dash-pli-card,
  #view-app:not(.perms-loaded):not(.role-admin) #nav-adm-bitacora { display: none !important; }

  /* (Fase A 2026-08-20: las listas negras por rol de las tarjetas del hub
     —estandar/coordinador/PM— se retiraron; manda el bloque "Herramientas
     por PERMISO" de arriba. #nav-budget ya no existía en el HTML.) */

  /* ══ RONDÍN — estilos (scoped, tokens del sistema) ══ */
  #page-rondin .rd-wrap { max-width: 1180px; margin: 0 auto; padding: calc(22px * var(--sp-scale, 1)) var(--space-6) calc(70px * var(--sp-scale, 1)); overflow-y: auto; height: 100%; }
  #page-rondin { overflow-y: auto; }
  .rd-band { display: flex; align-items: center; gap: calc(14px * var(--sp-scale, 1)); margin-bottom: 14px; flex-wrap: wrap; }
  .rd-date { font-size: calc(15px * var(--fs-scale, 1)); font-weight: 700; text-transform: capitalize; }
  .rd-note { font-size: calc(10.5px * var(--fs-scale, 1)); color: var(--text3); }
  .rd-spacer { flex: 1; }
  .rd-iconbtn { width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--radius-xs); border: 1px solid var(--border); background: var(--card2); color: var(--text2); cursor: pointer; }
  .rd-iconbtn:hover { background: var(--accent-soft); color: var(--accent); }
  .rd-btn { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); padding: calc(7px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1)); border-radius: var(--radius-sm);
    border: 1px solid var(--border2); background: var(--card); color: var(--text); font-size: var(--fs-base); font-weight: 600; cursor: pointer; }
  .rd-pill { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius-pill); padding: calc(7px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); }
  .rd-pill b { font-size: var(--fs-lg); }
  .rd-pbar { width: 120px; height: 5px; border-radius: var(--radius-pill); background: var(--wash-2); overflow: hidden; }
  .rd-pbar > span { display: block; height: 100%; border-radius: var(--radius-pill); background: var(--green); transition: width .3s var(--ease-out); }
  .rd-alarm { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); flex-wrap: wrap; background: var(--red-soft);
    border: 1px solid rgba(var(--red-rgb),0.35); border-radius: var(--radius); padding: calc(10px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); margin-bottom: 14px;
    animation: rdpulse 1.6s ease infinite; }
  @keyframes rdpulse { 0%,100% { box-shadow: 0 0 0 0 rgba(var(--red-rgb),0.28); } 50% { box-shadow: 0 0 0 7px rgba(var(--red-rgb),0); } }
  .rd-alarm-ttl { font-weight: 800; color: var(--red); font-size: calc(12.5px * var(--fs-scale, 1)); }
  .rd-alarm-item { display: inline-flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); background: var(--card);
    border: 1px solid rgba(var(--red-rgb),0.3); border-radius: var(--radius-pill); padding: calc(5px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)) calc(5px * var(--sp-scale, 1)) var(--space-3); font-size: calc(11.5px * var(--fs-scale, 1)); font-weight: 600; }
  .rd-alarm-item button { border: none; border-radius: var(--radius-pill); background: var(--red); color: #fff;
    font-size: var(--fs-xs); font-weight: 700; padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); cursor: pointer; }
  .rd-flabel { font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text3); }
  .rd-chip { padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill); font-size: var(--fs-sm); font-weight: 600;
    background: var(--card2); border: 1px solid var(--border); color: var(--text2); cursor: pointer; }
  .rd-chip.on { background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent); }
  .rd-list { display: flex; flex-direction: column; gap: var(--space-2); }
  .rd-empty { padding: calc(30px * var(--sp-scale, 1)); text-align: center; color: var(--text3); font-size: var(--fs-base); }
  .rd-row { display: flex; align-items: flex-start; gap: calc(14px * var(--sp-scale, 1)); background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius); padding: var(--space-3) var(--space-4); box-shadow: var(--shadow-card); flex-wrap: wrap; }
  .rd-row.status-green { border-left: 3px solid var(--green); }
  .rd-row.status-orange { border-left: 3px solid var(--orange); }
  .rd-row.status-red { border-left: 3px solid var(--red); }
  .rd-row.alarming { border-color: rgba(var(--red-rgb),0.4); animation: rdpulse 1.6s ease infinite; }
  .rd-avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--accent-soft); color: var(--accent);
    display: flex; align-items: center; justify-content: center; font-size: var(--fs-sm); font-weight: 800; flex-shrink: 0; }
  .rd-main { min-width: 150px; flex: 0 0 170px; }
  .rd-name { font-size: calc(13.5px * var(--fs-scale, 1)); font-weight: 700; }
  .rd-meta { display: flex; gap: calc(5px * var(--sp-scale, 1)); margin-top: 3px; flex-wrap: wrap; }
  .rd-tag { font-size: var(--fs-2xs); font-weight: 700; padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: var(--radius-pill); text-transform: uppercase; letter-spacing: .04em; }
  .rd-tag.d2 { background: var(--accent-soft); color: var(--accent); }
  .rd-tag.d3 { background: var(--purple-soft); color: var(--purple); }
  .rd-tag.sup { background: var(--green-soft); color: var(--green); }
  .rd-tag.vendor { background: var(--cyan-soft); color: var(--cyan); }
  .rd-tag.free { background: var(--orange-soft); color: var(--orange); }
  .rd-shots { flex: 1 1 260px; min-width: 240px; display: flex; flex-direction: column; gap: calc(5px * var(--sp-scale, 1)); }
  .rd-shot { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); flex-wrap: wrap; font-size: calc(11.5px * var(--fs-scale, 1));
    background: var(--wash-1); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: calc(5px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); }
  .rd-code { font-family: var(--font-mono); font-weight: 600; color: var(--text); }
  .rd-st { font-size: var(--fs-2xs); font-weight: 800; padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); border-radius: var(--radius-pill); text-transform: uppercase; }
  .rd-st.wip { background: var(--accent-soft); color: var(--accent); }
  .rd-st.rev { background: var(--yellow-soft); color: var(--yellow); }
  .rd-st.sinshot { background: var(--wash-2); color: var(--text3); }
  .rd-flag { font-size: var(--fs-xs); font-weight: 700; display: inline-flex; align-items: center; gap: var(--space-1); }
  .rd-flag.sup-ok { color: var(--green); }
  .rd-flag.stuck { color: var(--red); }
  .rd-flag.ready { color: var(--green); }
  .rd-flag.mile { color: var(--text3); font-weight: 600; }
  .rd-mat { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); font-size: var(--fs-xs); font-weight: 800;
    color: var(--red); background: var(--red-soft); border: 1px solid rgba(var(--red-rgb),0.35);
    padding: calc(2px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius: var(--radius-pill); }
  .rd-pnotes { display: flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); flex: 1 1 100%; margin-top: 2px; }
  .rd-pnotes label { font-size: var(--fs-2xs); font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--text3); flex-shrink: 0; }
  .rd-pnotes input { flex: 1; min-width: 120px; padding: var(--space-1) var(--space-2); font-size: var(--fs-sm); border-radius: var(--radius-sm);
    border: 1px solid var(--border); background: var(--wash-1); color: var(--text); font-family: inherit; }
  .rd-pnotes input:focus { outline: none; border-color: var(--accent-border); }
  .rd-sync { font-size: calc(8.5px * var(--fs-scale, 1)); color: var(--text3); flex-shrink: 0; }
  .rd-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-left: auto; }
  .rd-eta { padding: var(--space-1) calc(10px * var(--sp-scale, 1)); font-size: calc(10.5px * var(--fs-scale, 1)); font-weight: 700; border-radius: var(--radius-pill);
    background: var(--card2); border: 1px solid var(--border); color: var(--text2); cursor: pointer; }
  .rd-eta.set { background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent); }
  .rd-talk { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); padding: calc(7px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); border-radius: var(--radius-pill);
    border: 1.5px solid var(--border2); background: transparent; color: var(--text2); font-size: var(--fs-base); font-weight: 700; cursor: pointer;
    transition: all var(--dur-fast) var(--ease-out); }
  .rd-talk:hover { border-color: var(--green); color: var(--green); }
  .rd-talk.on { background: var(--green); border-color: var(--green); color: #fff; }
  .rd-bell { position: relative; }
  .rd-bell.has::after { content: ''; position: absolute; top: 2px; right: 2px; width: 7px; height: 7px; border-radius: 50%; background: var(--orange); }
  .rd-bell.alarm { border-color: rgba(var(--red-rgb),0.5); color: var(--red); animation: rdpulse 1.6s ease infinite; }
  .rd-slack:hover { background: var(--purple-soft); color: var(--purple); }
  .rd-remstrip { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-bottom: 14px; }
  .rd-remchip { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); font-size: var(--fs-sm); font-weight: 600;
    background: var(--orange-soft); border: 1px solid rgba(var(--orange-rgb),0.3); color: var(--orange);
    padding: var(--space-1) calc(11px * var(--sp-scale, 1)); border-radius: var(--radius-pill); }
  .rd-remchip button { border: none; background: none; color: var(--orange); cursor: pointer; font-size: var(--fs-base); opacity: .7; }
  .rd-pop { position: fixed; z-index: var(--z-rd-pop); background: var(--card); border: 1px solid var(--border2); border-radius: var(--radius);
    box-shadow: var(--shadow-pop); padding: var(--space-3); width: 250px; display: none; }
  .rd-pop.open { display: block; }
  .rd-pop h5 { font-size: var(--fs-sm); font-weight: 700; margin-bottom: 8px; }
  .rd-times { display: flex; gap: calc(6px * var(--sp-scale, 1)); flex-wrap: wrap; margin: 8px 0; }
  .rd-pop input { width: 100%; padding: calc(6px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius: var(--radius-sm); border: 1px solid var(--border2);
    background: var(--card2); color: var(--text); font: inherit; font-size: var(--fs-base); }
  .rd-remrow { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); font-size: var(--fs-sm); padding: calc(5px * var(--sp-scale, 1)) 0; border-top: 1px solid var(--border); }
  .rd-remrow:first-of-type { border-top: none; }
  .rd-remrow button { margin-left: auto; border: none; background: var(--red-soft); color: var(--red);
    font-size: var(--fs-xs); font-weight: 700; padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); border-radius: var(--radius-pill); cursor: pointer; }
  .rd-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: none; align-items: center; justify-content: center; z-index: var(--z-popover); padding: var(--space-5); }
  .rd-backdrop.open { display: flex; }
  .rd-modal { width: min(430px, 94vw); background: var(--card); border: 1px solid var(--border2); border-radius: var(--radius-lg);
    box-shadow: var(--shadow-modal); overflow: hidden; }
  .rd-modal-head { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); padding: calc(15px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); }
  .rd-modal-head h3 { font-size: var(--fs-lg); font-weight: 700; flex: 1; }
  .rd-modal-body { padding: var(--space-4) calc(18px * var(--sp-scale, 1)); }
  .rd-modal-foot { display: flex; justify-content: space-between; align-items: center; padding: var(--space-3) calc(18px * var(--sp-scale, 1)); border-top: 1px solid var(--border); }
  .rd-etagrid { display: flex; gap: calc(7px * var(--sp-scale, 1)); flex-wrap: wrap; margin: 8px 0 4px; }
  .rd-etaopt { padding: calc(7px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1)); font-size: var(--fs-base); font-weight: 700; border-radius: var(--radius-sm);
    background: var(--card2); border: 1px solid var(--border); color: var(--text2); cursor: pointer; }
  .rd-etaopt:hover { border-color: var(--accent-border); color: var(--accent); }
  .rd-etaopt.sel { background: var(--accent); border-color: var(--accent); color: #fff; }
  .rd-hint { font-size: calc(10.5px * var(--fs-scale, 1)); color: var(--text3); margin-top: 8px; }
  .rd-coordgrid { display: grid; grid-template-columns: 1fr 1fr; gap: calc(14px * var(--sp-scale, 1)); margin-bottom: 18px; }
  @media (max-width: 760px) { .rd-coordgrid { grid-template-columns: 1fr; } }
  .rd-coordcard { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: calc(18px * var(--sp-scale, 1)) var(--space-5); box-shadow: var(--shadow-card); }
  .rd-coordhead { display: flex; align-items: center; gap: var(--space-3); margin-bottom: 12px; }
  .rd-coordname { font-size: calc(15px * var(--fs-scale, 1)); font-weight: 700; }
  .rd-kpi { font-size: calc(26px * var(--fs-scale, 1)); font-weight: 800; letter-spacing: -1px; }
  .rd-kpi small { font-size: var(--fs-base); font-weight: 600; color: var(--text2); }
  .rd-allgood { color: var(--green); font-size: var(--fs-base); font-weight: 600; }
  .rd-tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-base); background: var(--card); border: 1px solid var(--border);
    border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-card); }
  .rd-tbl th { font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text3);
    text-align: left; padding: calc(10px * var(--sp-scale, 1)) var(--space-3); background: var(--card2); border-bottom: 1px solid var(--border); }
  .rd-tbl td { padding: calc(9px * var(--sp-scale, 1)) var(--space-3); border-bottom: 1px solid var(--border); vertical-align: top; }
  .rd-tbl tr:last-child td { border-bottom: none; }
  .rd-tbl tr.rd-nohablo td { background: var(--red-soft); }
  .rd-mini { margin: 1px 0; display: flex; gap: calc(6px * var(--sp-scale, 1)); align-items: center; flex-wrap: wrap; }
  .rd-ok.si { color: var(--green); }
  .rd-ok.no { color: var(--red); }
  .rd-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; }
  .rd-dot.green { background: var(--green); } .rd-dot.orange { background: var(--orange); } .rd-dot.red { background: var(--red); }

  /* ══ Rondín v4 — diseño portado de los mockups aprobados
     (docs/mockups/Rondin_Admin_Mockup_v4.html · Rondin_Coordinador_Mockup_v4.html).
     Estas reglas van DESPUÉS de las v3 y las sobreescriben por cascada. ══ */

  /* Banda: indicador de sync FTP + botón de configuración (admin) */
  .rd-sync-ind { display: inline-flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); font-size: var(--fs-sm); color: var(--text3);
    padding: calc(5px * var(--sp-scale, 1)) var(--space-3); border-radius: var(--radius-pill); background: var(--wash-1); border: 1px solid var(--border); }
  .rd-sync-ind .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green); }
  .rd-sync-ind.busy .dot { background: var(--accent); animation: rdblink 1.1s ease infinite; }
  @keyframes rdblink { 0%,100% { opacity: 1; } 50% { opacity: 0.25; } }
  .rd-gearbtn { display: inline-flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); padding: calc(7px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); border-radius: var(--radius-sm);
    border: 1px solid var(--border2); background: var(--card); color: var(--text); font-size: var(--fs-base); font-weight: 600;
    cursor: pointer; transition: all var(--dur-micro) var(--ease-out); font-family: inherit; white-space: nowrap; }
  .rd-gearbtn:hover { border-color: var(--accent-border); color: var(--accent); background: var(--accent-soft); }

  /* Cards de coordinador (resumen con alcance propio) */
  .rd-coordgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: calc(14px * var(--sp-scale, 1)); margin-bottom: 20px; }
  .rd-coordprojs { display: flex; gap: calc(5px * var(--sp-scale, 1)); margin-top: 4px; flex-wrap: wrap; }
  .rd-codechip { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.04em; padding: calc(2px * var(--sp-scale, 1)) var(--space-2);
    border-radius: var(--radius-pill); background: var(--wash-2); border: 1px solid var(--border); color: var(--text2);
    font-family: var(--font-mono); }
  .rd-kpi-note { font-size: var(--fs-xs); color: var(--text3); text-align: right; margin-top: 3px; }
  .rd-coordcard .rd-pbar { width: 100%; margin-top: 13px; }
  .rd-coordfoot { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; }
  .rd-misslink { font-size: var(--fs-sm); font-weight: 600; color: var(--red); background: none; border: none;
    cursor: pointer; font-family: inherit; padding: calc(3px * var(--sp-scale, 1)) 0; }
  .rd-misslink:hover { text-decoration: underline; }
  .rd-tag.warn { background: var(--orange-soft); color: var(--orange); border: 1px solid rgba(var(--orange-rgb),0.4); }
  .rd-chip.code { font-family: var(--font-mono); letter-spacing: 0.04em; font-size: var(--fs-sm); }
  .rd-chip.pend.on { background: var(--red-soft); border-color: var(--red-border); color: var(--red); }
  .rd-clear.show { display: inline; }

  /* Filas del coordinador: grid de 3 zonas fijas (identidad | trabajo | acción) */
  .rd-row { display: grid; grid-template-columns: 220px 1fr 300px; align-items: start; gap: calc(14px * var(--sp-scale, 1)); }
  @media (max-width: 900px) { .rd-row { grid-template-columns: 1fr; } .rd-actions { justify-content: flex-start; } }
  .rd-row.talked { opacity: 0.82; }
  .rd-ident { display: flex; align-items: center; gap: calc(11px * var(--sp-scale, 1)); min-width: 0; }
  .rd-actions { justify-content: flex-end; }

  /* Prod Notes colapsadas a un botón 📝 (expandibles por shot) */
  .rd-notebtn { border: none; background: none; font-family: inherit; font-size: var(--fs-xs); font-weight: 600;
    color: var(--text3); cursor: pointer; padding: calc(2px * var(--sp-scale, 1)) var(--space-1); border-radius: var(--radius-xs); white-space: nowrap;
    max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
  .rd-notebtn:hover { color: var(--accent); background: var(--accent-soft); }
  .rd-notebtn.has { color: var(--text2); font-style: italic; }
  .rd-pnotes { display: none; align-items: center; gap: calc(5px * var(--sp-scale, 1)); flex: 1 1 100%; margin-top: 3px; }
  .rd-pnotes.open { display: flex; }

  /* Skeletons shimmer (carga progresiva de FTP) */
  .sk { position: relative; overflow: hidden; background: var(--wash-2); border-radius: var(--radius-pill); display: inline-block; }
  .sk::after { content: ''; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, var(--wash-3), transparent);
    animation: skmove 1.4s ease infinite; }
  @keyframes skmove { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
  .sk.pill { width: 52px; height: 16px; }
  .sk.ver { width: 84px; height: 13px; border-radius: 4px; }
  .sk.note { width: 130px; height: 12px; border-radius: 4px; }

  /* Estado vacío: coordinador sin proyectos asignados */
  .rd-emptycard { background: var(--card); border: 1px dashed var(--border2); border-radius: var(--radius-lg);
    padding: calc(56px * var(--sp-scale, 1)) calc(30px * var(--sp-scale, 1)); text-align: center; margin-top: 8px; }
  .rd-emptycard .ico { width: 52px; height: 52px; border-radius: 50%; background: var(--wash-2);
    display: inline-flex; align-items: center; justify-content: center; font-size: calc(22px * var(--fs-scale, 1)); margin-bottom: 14px; }
  .rd-emptycard h2 { font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.3px; margin: 0 0 7px; }
  .rd-emptycard p { font-size: var(--fs-base); color: var(--text2); max-width: 420px; margin: 0 auto; line-height: 1.6; }
  .rd-emptycard .who { display: inline-flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); margin-top: 16px; font-size: var(--fs-sm);
    color: var(--text3); background: var(--wash-1); border: 1px solid var(--border); padding: calc(6px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); border-radius: var(--radius-pill); }
  .rd-empty .lnk { color: var(--accent); cursor: pointer; font-weight: 600; }
  .rd-empty b { display: block; color: var(--text2); font-size: var(--fs-md); margin-bottom: 5px; }

  /* Tabla admin v4: wrapper con radios, columnas centradas, sin fila roja completa */
  .rd-tblwrap { border-radius: var(--radius); overflow: hidden; border: 1px solid var(--border); box-shadow: var(--shadow-card); }
  .rd-tblwrap .rd-tbl { border: none; box-shadow: none; border-radius: 0; }
  .rd-tbl th.c, .rd-tbl td.c { text-align: center; }
  .rd-tbl tr:hover td { background: var(--wash-1); }
  .rd-artname { font-size: var(--fs-md); font-weight: 700; display: flex; align-items: center; }
  .rd-tbl .rd-meta { margin-left: 16px; }
  .rd-ok.si { color: var(--green); background: var(--green-soft); }
  .rd-ok.no { color: var(--red); background: var(--red-soft); }
  .rd-ok.na { color: var(--text3); background: none; font-weight: 400; }

  /* Modal Configuración (solo admin) */
  .rd-modal.rd-cfg { width: min(680px, 96vw); }
  .rd-backdrop:has(.rd-cfg) { align-items: flex-start; padding-top: 6vh; }
  .rd-modal.rd-cfg .rd-modal-head { padding: var(--space-4) var(--space-5) 0; border-bottom: none; }
  .rd-modal.rd-cfg .rd-modal-head h3 { flex: 1; }
  .rd-tabs { display: flex; gap: calc(2px * var(--sp-scale, 1)); padding: calc(14px * var(--sp-scale, 1)) var(--space-5) 0; border-bottom: 1px solid var(--border); }
  .rd-tab { border: none; background: none; font-family: inherit; font-size: var(--fs-base); font-weight: 600;
    color: var(--text3); padding: calc(9px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1)); cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
  .rd-tab:hover { color: var(--text2); }
  .rd-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
  .rd-tab .n { font-size: var(--fs-xs); font-weight: 700; background: var(--wash-2); color: var(--text3);
    border-radius: var(--radius-pill); padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); margin-left: 5px; }
  .rd-tab.on .n { background: var(--accent-soft); color: var(--accent); }
  .rd-modal.rd-cfg .rd-modal-body { padding: calc(18px * var(--sp-scale, 1)) var(--space-5); max-height: 58vh; overflow-y: auto; }
  .rd-modal.rd-cfg .rd-modal-foot { background: var(--wash-1); }
  .rd-btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
  .rd-btn.primary:hover { background: var(--accent-hover); }
  .rd-hint { font-size: calc(10.5px * var(--fs-scale, 1)); color: var(--text3); line-height: 1.5; }
  /* Tab 1: coordinadores ↔ proyectos */
  .rd-cfg-row { display: flex; align-items: center; gap: calc(14px * var(--sp-scale, 1)); padding: calc(13px * var(--sp-scale, 1)) var(--space-1); border-bottom: 1px solid var(--border); }
  .rd-cfg-row:last-child { border-bottom: none; }
  .rd-cfg-who { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); flex: 0 0 190px; min-width: 0; }
  .rd-cfg-name { font-size: var(--fs-md); font-weight: 700; }
  .rd-cfg-sub { font-size: var(--fs-xs); color: var(--text3); margin-top: 1px; }
  .rd-cfg-projs { display: flex; gap: calc(7px * var(--sp-scale, 1)); flex-wrap: wrap; flex: 1; }
  .rd-ptoggle { font-family: var(--font-mono); font-size: var(--fs-sm); font-weight: 700;
    letter-spacing: 0.05em; padding: calc(5px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1)); border-radius: var(--radius-pill); cursor: pointer; user-select: none;
    background: var(--card2); border: 1px solid var(--border); color: var(--text3); transition: all var(--dur-micro) var(--ease-out); }
  .rd-ptoggle:hover { border-color: var(--border2); color: var(--text2); }
  .rd-ptoggle.on { background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent); }
  .rd-ptoggle.on::before { content: "✓ "; font-weight: 800; }
  /* Tab 2: artistas excluidos */
  .rd-cfg-filters { display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); flex-wrap: wrap; margin-bottom: 10px; }
  .rd-cfg-search { display: flex; align-items: center; gap: var(--space-2); background: var(--card2); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: calc(7px * var(--sp-scale, 1)) var(--space-3); margin-bottom: 12px; }
  .rd-cfg-search svg { color: var(--text3); flex-shrink: 0; }
  .rd-cfg-search input { flex: 1; border: none; background: none; color: var(--text); font: inherit; font-size: var(--fs-base); outline: none; }
  .rd-cfg-search input::placeholder { color: var(--text3); }
  .rd-cfg-search:focus-within { border-color: var(--accent-border); }
  .rd-excl-row { display: flex; align-items: center; gap: calc(11px * var(--sp-scale, 1)); padding: calc(9px * var(--sp-scale, 1)) var(--space-1); border-bottom: 1px solid var(--border); }
  .rd-excl-row:last-child { border-bottom: none; }
  .rd-excl-row.out .rd-excl-name, .rd-excl-row.out .rd-avatar { opacity: 0.45; }
  .rd-excl-name { font-size: var(--fs-md); font-weight: 600; flex: 1; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
  .rd-excl-badge { font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
    color: var(--red); background: var(--red-soft); border: 1px solid var(--red-border);
    padding: calc(2px * var(--sp-scale, 1)) var(--space-2); border-radius: var(--radius-pill); display: none; }
  .rd-excl-row.out .rd-excl-badge { display: inline-block; }
  .rd-avatar.sm { width: 28px; height: 28px; font-size: var(--fs-xs); }
  .rd-sw { position: relative; width: 36px; height: 21px; border-radius: var(--radius-pill); background: var(--wash-3);
    border: 1px solid var(--border2); cursor: pointer; transition: all var(--dur-micro) var(--ease-out); flex-shrink: 0; display: inline-block; }
  .rd-sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 15px; height: 15px; border-radius: 50%;
    background: var(--text2); transition: all var(--dur-micro) var(--ease-out); }
  .rd-sw.on { background: var(--red); border-color: var(--red); }
  .rd-sw.on::after { left: 17px; background: #fff; }
  .rd-sw-label { font-size: var(--fs-xs); color: var(--text3); width: 52px; text-align: right; flex-shrink: 0; }
  /* ── Rondín — ajustes de feedback 2026-07-03 (2ª ronda) ── */
  /* Layout con panel de filtros flotante a la derecha (patrón de Artistas) */
  .rd-layout { display: flex; gap: calc(18px * var(--sp-scale, 1)); align-items: flex-start; min-width: 0; }
  .rd-maincol { flex: 1; min-width: 0; }
  .rd-aside { width: var(--filter-aside-w); flex-shrink: 0; position: sticky; top: 12px; }
  .rd-fltcard { padding: calc(14px * var(--sp-scale, 1)); }
  .rd-aside-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
    margin-top: 14px; padding-top: var(--space-3); border-top: 1px solid var(--border);
    font-size: var(--fs-sm); color: var(--text3); }
  .rd-aside-foot b { color: var(--text2); }
  .rd-aside-clear { color: var(--accent); cursor: pointer; font-weight: 600; }
  .rd-aside-clear:hover { text-decoration: underline; }
  @media (max-width: 900px) { .rd-layout { flex-direction: column-reverse; } .rd-aside { width: 100%; position: static; } }
  /* Tarjetas de coordinador compactas (~50%) */
  .rd-coordgrid { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 14px; }
  .rd-coordcard { padding: calc(10px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); }
  .rd-coordname { font-size: calc(12.5px * var(--fs-scale, 1)); }
  .rd-kpi { font-size: calc(17px * var(--fs-scale, 1)); letter-spacing: -0.5px; }
  .rd-kpi small { font-size: var(--fs-sm); }
  .rd-coordcard .rd-pbar { margin-top: 8px; height: 4px; }
  .rd-coordfoot { margin-top: 6px; }
  /* Tabla admin: shots en cajas propias, nota en línea aparte (legibilidad) */
  .rd-mini { display: block; background: var(--wash-1); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: calc(6px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); margin: 4px 0; }
  .rd-mini:first-child { margin-top: 0; }
  .rd-mini-top { display: flex; gap: calc(7px * var(--sp-scale, 1)); align-items: center; flex-wrap: wrap; }
  .rd-mini-note { margin-top: 4px; font-size: var(--fs-sm); color: var(--text2); font-style: italic;
    border-top: 1px dashed var(--border); padding-top: var(--space-1); }
  /* Columna única "Coordinador": chip por coordinador que cubre al artista */
  .rd-coordtag { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); font-size: var(--fs-sm); font-weight: 700;
    padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-radius: var(--radius-pill); margin: 2px 4px 2px 0;
    background: var(--red-soft); color: var(--red); border: 1px solid rgba(var(--red-rgb),0.3); }
  .rd-coordtag.ok { background: var(--green-soft); color: var(--green); border-color: rgba(var(--green-rgb),0.3); }
  /* Botón de Slack compacto: alineado a la DERECHA de la celda para que quede
     en la misma posición en todos los artistas (feedback 2026-07-03 #1) */
  .rd-slack-sm { width: 22px; height: 22px; margin-left: auto; flex-shrink: 0; }
  .rd-mini-note .rd-pnotes { display: flex; margin-top: 0; }

  /* VFX Planner: sin steppers en inputs numéricos — en Safari los steppers
     desplazan el texto y desalinean la columna contra el Total (feedback). */
  #page-calendar-crew input.cell.n::-webkit-outer-spin-button,
  #page-calendar-crew input.cell.n::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
  #page-calendar-crew input.cell.n[type=number] { -moz-appearance: textfield; appearance: textfield; }

  /* VFX Planner: selección múltiple + edición masiva */
  #page-calendar-crew tr.vp-row-sel td { background: rgba(var(--accent-rgb),0.07); }
  /* CC-3 (2026-07-17): bandera de atención por artista — fila naranja suave +
     acento en el borde; la bandera gana sobre la selección azul (va después). */
  #page-calendar-crew tr.vp-row-flag td { background: rgba(var(--orange-rgb),0.07); }
  #page-calendar-crew tr.vp-row-flag td:first-child { box-shadow: inset 3px 0 0 var(--orange); }
  /* Fix CuePin 2026-07-17: fila con bandera Y seleccionada — el azul de la
     selección debe NOTARSE (antes el naranja lo tapaba); el borde izquierdo
     naranja y la bandera conservan la marca de atención. */
  #page-calendar-crew tr.vp-row-sel.vp-row-flag td { background: rgba(var(--accent-rgb),0.13); }
  /* CC-7 (CuePin 2026-07-17): invisible hasta hover en la fila — MISMO patrón
     que los checkboxes de arriba; la bandera activa siempre se ve. */
  #page-calendar-crew .vp-flag { cursor: pointer; color: var(--text3); opacity: 0; transition: opacity var(--dur-micro); display: inline-flex; vertical-align: -2px; margin-left: 6px; }
  /* A11y (2026-07-23): la bandera también se revela con foco de teclado —
     el retrofit [data-action] la vuelve enfocable; hover-only la escondía. */
  #page-calendar-crew table.ft tbody tr:hover .vp-flag,
  #page-calendar-crew table.ft tbody tr:focus-within .vp-flag,
  #page-calendar-crew .vp-flag:focus-visible { opacity: 0.9; }
  #page-calendar-crew .vp-flag.on { color: var(--orange); opacity: 1; }
  /* Condiciones por persona (2026-08-31): el reloj se pinta fijo de acento
     SOLO cuando la persona tiene más de un periodo (pedido UX del usuario);
     para el resto aparece al pasar el mouse por la fila, como la bandera. */
  #page-calendar-crew .vp-flag.vp-cond.on { color: var(--accent); }
  /* ── Modal Condiciones (UX 2026-08-31, auditoría apple-design) ──
     La regla global input.cell.n capa el ancho a 90px y en la tabla de
     periodos cortaba "$45,000" mientras las fechas (96–110px) se veían más
     anchas. Aquí las columnas mandan (table-layout fixed + colgroup) y los
     inputs llenan su celda con caja visible (patrón .vpc-param). */
  #page-calendar-crew .vp-art-sec + .vp-art-sec { margin-top: var(--space-4); }
  #page-calendar-crew .vp-art-info { display: inline-flex; vertical-align: -2px; color: var(--text3); cursor: help; }
  #page-calendar-crew .vp-art-info:hover { color: var(--text2); }
  #page-calendar-crew .vp-art-empty { color: var(--text3); font-size: var(--fs-sm); padding: calc(10px * var(--sp-scale, 1)) 0 calc(2px * var(--sp-scale, 1)); }
  #page-calendar-crew .vp-art-warn { color: var(--orange); font-size: var(--fs-sm); margin-top: calc(6px * var(--sp-scale, 1)); }
  #page-calendar-crew .vp-art-add { margin-top: calc(10px * var(--sp-scale, 1)); }
  /* ── Auditoría UX 2026-09-01 · B1: qué se captura vs qué calcula la app ──
     Las celdas editables eran transparentes sin borde: en reposo se veían
     igual que el texto. Ahora llevan un subrayado tenue («aquí se escribe»),
     las de solo lectura se ven claramente bloqueadas, y el Booked —que es un
     DERIVADO— baja de peso para no ser lo más prominente de la fila (la
     jerarquía estaba invertida). El subtotal conserva el peso 700. */
  #page-calendar-crew input.cell:not([readonly]),
  #page-calendar-crew select.cell { border-bottom-color: var(--border); }
  #page-calendar-crew input.cell[readonly] { color: var(--text2); background: var(--wash-1);
    border-color: transparent; cursor: not-allowed; }
  #page-calendar-crew table.ft tbody td.calc b { font-weight: 600; }
  #page-calendar-crew table.ft tr.vp-subtot td.calc b { font-weight: 700; }
  /* B6: al hacer scroll horizontal se perdía de quién era la fila y qué
     columna se tocaba — en una tabla donde cada celda es dinero. El
     calendario de abajo ya fijaba su columna de nombres. */
  /* Capas dentro de la tabla (valores del allowlist de ds-lint para sticky
     intra-tabla): 2 = columna fija · 5 = encabezado · 8 = su esquina. */
  #page-calendar-crew #vp-tbl-artists thead th,
  #page-calendar-crew #vp-tbl-pkg thead th { position: sticky; top: 0; z-index: 5; background: var(--card); }
  #page-calendar-crew #vp-tbl-artists tbody td:nth-child(2),
  #page-calendar-crew #vp-tbl-artists thead th:nth-child(2) { position: sticky; left: 46px; z-index: 2; background: var(--card); }
  #page-calendar-crew #vp-tbl-artists thead th:nth-child(2) { z-index: 8; }
  #page-calendar-crew #vp-tbl-artists tr.vp-grp-hdr td:nth-child(2),
  #page-calendar-crew #vp-tbl-artists tr.vp-sub-hdr td:nth-child(2),
  #page-calendar-crew #vp-tbl-artists tr.vp-sub2-hdr td:nth-child(2),
  #page-calendar-crew #vp-tbl-artists tr.vp-subtot td:nth-child(2) { position: static; }
  /* B5 (2026-09-01): «Condiciones» — una columna en vez de tres (Ag./Lic/Mach).
     Solo habla cuando la persona se sale de lo normal; con lo normal, un guion
     tenue. Abre el modal del reloj, donde se editan. */
  #page-calendar-crew .vp-terms { border: none; background: none; color: var(--text3); font: inherit;
    font-size: var(--fs-2xs); cursor: pointer; padding: calc(1px * var(--sp-scale, 1)) var(--space-1);
    border-radius: var(--radius-xs); white-space: nowrap; }
  #page-calendar-crew .vp-terms:hover { color: var(--accent); background: var(--wash-1); }
  #page-calendar-crew .vp-terms.on { color: var(--orange); font-weight: 600; }
  /* Casillas del modal de condiciones: una por línea, con blanco para leerse. */
  #page-calendar-crew .vp-art-chk { display: flex; align-items: center; gap: var(--space-2);
    padding: calc(3px * var(--sp-scale, 1)) 0; color: var(--text2); cursor: pointer; }
  #page-calendar-crew .vp-art-chk input { cursor: pointer; }
  /* B2 (2026-09-01): estado del guardado en la barra del show. Discreto por
     defecto; solo se pinta cuando hay algo que decir (sin guardar / falló). */
  #page-calendar-crew .vp-savestate { margin-left: var(--space-3); font-size: var(--fs-sm); color: var(--text3); font-variant-numeric: tabular-nums; }
  #page-calendar-crew .vp-savestate.vp-sv-pending { color: var(--text2); }
  #page-calendar-crew .vp-savestate.vp-sv-failed { color: var(--orange); font-weight: 600; }
  /* A2: cuántos artistas quedan tras filtrar (los subtotales se ocultan). */
  #page-calendar-crew .vp-art-count { margin-left: var(--space-2); color: var(--text3); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
  #page-calendar-crew .vp-art-count.vp-nores { color: var(--orange); }
  /* Renglón repetido (2026-09-01): dos filas con el MISMO usuario de FPT —
     las dos suman al booked, así que el nombre se marca hasta que se borre
     una. Borde ámbar: es un aviso, no un error de datos. */
  #page-calendar-crew input.cell.vp-dup { border-color: var(--orange); background: var(--orange-soft); }
  /* El selector de vínculo no necesita todo el ancho del modal (CuePin 1). */
  #page-calendar-crew .vp-art-sec select { max-width: 330px; padding-top: var(--space-1); padding-bottom: var(--space-1); }
  /* En pantallas angostas la tabla scrollea DENTRO del modal, no lo desborda. */
  #page-calendar-crew .vp-art-tblwrap { overflow-x: auto; }
  #page-calendar-crew .vp-art-tbl { width: 100%; min-width: 620px; table-layout: fixed; }
  /* Anchos por contenido REAL, medidos con el reporte CuePin del 2026-09-01:
     dd/mm/yyyy se cortaba a 104px (nota 5) y el dinero sobraba (nota 4). */
  #page-calendar-crew .vp-art-tbl col.c-d { width: 118px; }   /* fechas dd/mm/yyyy */
  #page-calendar-crew .vp-art-tbl col.c-m { width: 92px; }    /* sueldo / rate */
  #page-calendar-crew .vp-art-tbl col.c-p { width: 72px; }    /* % ded + sufijo */
  #page-calendar-crew .vp-art-tbl col.c-x { width: 34px; }    /* ✕ */
  #page-calendar-crew .vp-art-tbl td { padding-left: var(--space-1); padding-right: var(--space-1); }
  #page-calendar-crew .vp-art-tbl input.cell { width: 100%; min-width: 0; max-width: none; box-sizing: border-box;
    background: var(--wash-1); border: 1px solid var(--border); }
  #page-calendar-crew .vp-art-tbl input.cell:hover { border-color: var(--border2); }
  #page-calendar-crew .vp-art-tbl input.cell:focus { border-color: var(--accent); }
  /* Ded. con su símbolo % DENTRO de la caja (CuePin 2): el input pierde su
     borde y la caja entera es la que se ilumina al enfocar. */
  #page-calendar-crew .vp-ded-box { display: flex; align-items: center; box-sizing: border-box;
    background: var(--wash-1); border: 1px solid var(--border); border-radius: var(--radius-xs);
    padding-right: calc(6px * var(--sp-scale, 1)); transition: border-color var(--dur-micro); }
  #page-calendar-crew .vp-ded-box:hover { border-color: var(--border2); }
  #page-calendar-crew .vp-ded-box:focus-within { border-color: var(--accent); }
  #page-calendar-crew .vp-ded-box input.cell { background: none; border-color: transparent; padding-right: calc(2px * var(--sp-scale, 1)); }
  #page-calendar-crew .vp-ded-box input.cell:hover,
  #page-calendar-crew .vp-ded-box input.cell:focus { border-color: transparent; background: none; }
  #page-calendar-crew .vp-ded-box i { font-style: normal; color: var(--text3); font-size: var(--fs-sm); }
  /* Chip "real N%" junto a Ded.: dedicación real calculada por Project Cost.
     Botón mínimo, mismo lenguaje que los chips .pct de los totales. */
  #page-calendar-crew .vp-realded { cursor: pointer; border: 1px solid var(--accent-border); background: var(--accent-soft); color: var(--accent); border-radius: var(--radius-pill); font-size: var(--fs-2xs); font-weight: 600; padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); margin-left: 5px; vertical-align: 1px; white-space: nowrap; }
  #page-calendar-crew .vp-realded:hover { background: var(--accent-border); }
  /* Variante informativa (2026-09-01): en filas con periodos el chip no aplica
     nada — solo informa el % real; sin cursor de botón ni hover. */
  #page-calendar-crew .vp-realded-info { cursor: help; }
  #page-calendar-crew .vp-realded-info:hover { background: var(--accent-soft); }
  #page-calendar-crew .cal-rowlabel .vp-flag-cal { color: var(--orange); display: inline-flex; vertical-align: -1px; margin-left: 4px; }
  /* CC-6 (CuePin 2026-07-17): jerarquía visual de los agrupamientos de la tabla
     de booking — mejora ligera, sin rediseño: el grupo principal (MX/NON MX/SUP)
     lleva el wash más fuerte, el subgrupo (2D/3D/PLANNED) un wash suave con
     borde, y el nivel 3 (Depto plan) solo sangría + borde punteado. */
  #page-calendar-crew #vp-tbl-artists tr.vp-grp-hdr td { background: var(--wash-2); color: var(--text2); font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; padding-top: calc(7px * var(--sp-scale, 1)); padding-bottom: calc(7px * var(--sp-scale, 1)); border-top: 1px solid var(--border2); }
  #page-calendar-crew #vp-tbl-artists tr.vp-sub-hdr td { background: var(--wash-1); color: var(--text3); font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; padding-top: calc(5px * var(--sp-scale, 1)); padding-bottom: calc(5px * var(--sp-scale, 1)); border-top: 1px solid var(--border); }
  #page-calendar-crew #vp-tbl-artists tr.vp-sub2-hdr td { color: var(--text3); font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; padding-top: var(--space-1); padding-bottom: calc(3px * var(--sp-scale, 1)); border-top: 1px dashed var(--border); }
  /* Revisión UX 2026-07-17: la sangría del nivel 3 vive AQUÍ (no inline en el JS). */
  #page-calendar-crew #vp-tbl-artists tr.vp-sub2-hdr td:nth-child(2) { padding-left: var(--space-4); }
  /* CC-9 (CuePin 2026-07-17): subtítulos de sección del modal Show settings —
     ocupan todo el ancho del grid y separan Show / Global / P&L. */
  /* Revisión UX 2026-07-17: text2 + fs-xs para que la cabecera de sección pese
     MÁS que los labels de campo (text3/fs-xs) y no se lea como otro label. */
  #page-calendar-crew .cfg-grid .cfg-sec { grid-column: 1 / -1; font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text2); border-bottom: 1px solid var(--border); padding-bottom: var(--space-1); margin-top: var(--space-2); }
  #page-calendar-crew .cfg-grid .cfg-sec:first-child { margin-top: 0; }
  #page-calendar-crew input[type="checkbox"] { accent-color: var(--accent); cursor: pointer; }
  .vp-selbar { position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%) translateY(12px);
    display: flex; align-items: center; gap: var(--space-3); background: var(--card2); border: 1px solid var(--accent-border);
    color: var(--text); border-radius: var(--radius-pill); padding: calc(9px * var(--sp-scale, 1)) var(--space-3) calc(9px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1)); font-size: var(--fs-base);
    box-shadow: var(--shadow-pop); opacity: 0; pointer-events: none; transition: all var(--dur-base) var(--ease-out); z-index: var(--z-tooltip-pop); }
  .vp-selbar.open { opacity: 1; transform: translateX(-50%); pointer-events: auto; }
  .vp-selbar b { color: var(--accent); }
  .vp-selbar button { border: 1px solid var(--border2); background: var(--card); color: var(--text2);
    border-radius: var(--radius-pill); font-size: var(--fs-sm); font-weight: 600; padding: var(--space-1) var(--space-3); cursor: pointer; font-family: inherit; }
  .vp-selbar button:hover { color: var(--text); background: var(--wash-2); }

  /* VFX Planner: celdas de dinero editables in-place (se ven como los totales) */
  #page-calendar-crew .vp-money-edit { cursor: text; border-radius: var(--radius-xs); padding: calc(2px * var(--sp-scale, 1)) var(--space-1); margin: -2px -4px; }
  #page-calendar-crew .vp-money-edit:hover { color: var(--accent); background: var(--wash-1); }

  /* Privacidad "compartir pantalla" (CuePin 2026-07-16): con .vpm-hide en la
     sección, todo monto (span/input .vpm) se difumina; solo visual. */
  #page-calendar-crew.vpm-hide .vpm { filter: blur(0.45em); user-select: none; pointer-events: none; }
  #page-calendar-crew .vp-priv-btn.active { background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent); }

  /* ADM Dashboard (CuePin 2026-07-16): aire entre las 4 KPI cards. */
  #page-adm-dashboard .stats-grid.adm-grid4 { gap: var(--space-5); margin-bottom: var(--space-5); }

  /* VFX Planner · Show Budget: REMAINING TO HIRE (allowance − actual) —
     verde cuando queda dinero; el sobregiro usa la clase .over existente. */
  #page-calendar-crew .bline .val.vp-rem-ok { color: var(--green); }

  /* VFX Planner: botones de acción junto a los Actuals del Show Budget
     (usar booked ⧉ + importar Outsource). CuePin 2026-07-16: mitad del tamaño
     original (24 → 16px) con icono Lucide siempre visible (svg 9px, sin
     depender de glifos de texto). */
  .vp-import-btn { width: 16px; height: 16px; margin-left: 6px; vertical-align: middle;
    display: inline-flex; align-items: center; justify-content: center; padding: 0; flex-shrink: 0;
    color: var(--accent); background: var(--accent-soft); border: 1px solid var(--accent-border);
    border-radius: var(--radius-xs); }
  .vp-import-btn svg { width: 9px; height: 9px; display: block; }
  .vp-import-btn:hover { background: var(--accent); color: #fff; }

  /* Fallback cuando la app de escritorio de Slack no responde al deep link */
  .rd-slackfb { position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%) translateY(12px);
    display: flex; align-items: center; gap: var(--space-3); background: var(--card2); border: 1px solid var(--border2);
    color: var(--text); border-radius: var(--radius-pill); padding: calc(9px * var(--sp-scale, 1)) var(--space-3) calc(9px * var(--sp-scale, 1)) calc(18px * var(--sp-scale, 1)); font-size: var(--fs-base);
    font-weight: 600; box-shadow: var(--shadow-pop); opacity: 0; pointer-events: none;
    transition: all var(--dur-base) var(--ease-out); z-index: var(--z-tooltip-pop); }
  .rd-slackfb.open { opacity: 1; transform: translateX(-50%); pointer-events: auto; }

  /* ── Banner "Ver como" (impersonación de admin) — visible siempre, arriba ── */
  #impersonation-banner {
    position: fixed; top: 0; left: 50%; transform: translateX(-50%);
    z-index: var(--z-impersonation); display: flex; align-items: center; gap: var(--space-3);
    background: var(--orange-soft); border: 1px solid rgba(var(--orange-rgb),0.45);
    border-top: none; border-radius: 0 0 var(--radius) var(--radius);
    padding: calc(7px * var(--sp-scale, 1)) var(--space-4); font-size: var(--fs-base); color: var(--orange); font-weight: 600;
    box-shadow: var(--shadow-pop); backdrop-filter: blur(6px);
  }
  #impersonation-banner button {
    border: none; border-radius: var(--radius-pill); background: var(--orange); color: #fff;
    font-size: var(--fs-sm); font-weight: 700; padding: var(--space-1) var(--space-3); cursor: pointer;
  }
  #impersonation-banner button:hover { filter: brightness(1.1); }

/* ══ CAPACITY CROSS-SHOW — estilos (scoped, tokens del sistema) ══ */
#page-capacity { overflow-y: auto; }
#page-capacity .page-body { max-width: 1180px; margin: 0 auto; }
.cap-kpi .v { font-size: var(--fs-kpi); font-weight: 700; font-variant-numeric: tabular-nums; }
.cap-kpi .l { font-size: var(--fs-sm); color: var(--text2); margin-top: 3px; }
.cap-kpi.warn { border-color: var(--red-border); } .cap-kpi.warn .v { color: var(--red); }
.cap-kpi.freek .v { color: var(--green); }
.cap-filters .chip { font-size: var(--fs-sm); font-weight: 600; padding: calc(5px * var(--sp-scale, 1)) var(--space-3); border-radius: var(--radius-pill);
  border: 1px solid var(--border); background: var(--wash-1); color: var(--text2); cursor: pointer; }
.cap-filters .chip:hover { background: var(--wash-2); color: var(--text); }
.cap-filters .chip.active { background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent); }
.cap-filters .chip.warnf.active { background: var(--red-soft); border-color: var(--red-border); color: var(--red); }
.cap-filters .chip .n { opacity: .7; margin-left: 4px; font-variant-numeric: tabular-nums; }
.cap-lane.a { top: 3px; } .cap-lane.b { bottom: 3px; }
.cap-pill.conflict { color: var(--red); background: var(--red-soft); border: 1px solid var(--red-border); }
.cap-pill.full { color: var(--orange); background: var(--orange-soft); border: 1px solid var(--orange-border); }
.cap-pill.ok { color: var(--green); background: var(--green-soft); border: 1px solid var(--green-border); }
.cap-pill.freep { color: var(--text2); background: var(--wash-2); border: 1px solid var(--border); }
@media (max-width: 900px) {
}

/* ══════════════════════════════════════════════════════════
   ICONOS (LAB) v2 — page-icons-lab (admin y modo dev)
   Rediseño 2026-07-05 (mockup IconLab_Redesign_Mockup_v1 aprobado):
   3 zonas ① secciones (réplica sidebar) ② biblioteca ③ estética global,
   cabecera fija con Guardar, modo asignación explícito, popovers.
   Reutiliza .il-cat-chip/.il-hex (definidos al final del archivo).
   ══════════════════════════════════════════════════════════ */
#page-icons-lab { padding: 0; }
.il2 { min-height: 100%; }

.il2-head { position: sticky; top: 0; z-index: var(--z-menu); display: flex; align-items: center; justify-content: space-between;
  gap: calc(14px * var(--sp-scale, 1)); padding: var(--space-3) calc(22px * var(--sp-scale, 1)); background: var(--bg); border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.il2-head h1 { font-size: calc(16px * var(--fs-scale, 1)); }
.il2-head p { font-size: var(--fs-sm); color: var(--text3); margin-top: 2px; }
.il2-head-actions { display: flex; align-items: center; gap: var(--space-2); }
.il2-pending-pill { font-size: calc(10.5px * var(--fs-scale, 1)); font-weight: 700; color: var(--orange);
  background: var(--orange-soft); border: 1px solid var(--orange-border); border-radius: var(--radius-pill); padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); }

.il2-guide { display: flex; align-items: center; gap: calc(18px * var(--sp-scale, 1)); flex-wrap: wrap; margin: 12px 22px 0;
  background: rgba(var(--accent-rgb), 0.06); border: 1px solid rgba(var(--accent-rgb), 0.25); border-radius: 10px;
  padding: calc(9px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); font-size: calc(11.5px * var(--fs-scale, 1)); color: var(--text2); }
.il2-guide b { display: inline-flex; align-items: center; justify-content: center; width: 17px; height: 17px;
  border-radius: 50%; background: var(--accent); color: #fff; font-size: var(--fs-xs); margin-right: 5px; }
.il2-guide button { margin-left: auto; }

.il2-assignbar { position: sticky; top: 54px; z-index: var(--z-il2-assignbar); display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); margin: 10px 22px 0; padding: calc(9px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); border-radius: 10px;
  background: rgba(var(--accent-rgb), 0.14); border: 1.5px solid var(--accent);
  font-size: calc(12.5px * var(--fs-scale, 1)); color: var(--text); }
.il2-assignbar kbd { font-family: var(--font-mono); font-size: calc(9.5px * var(--fs-scale, 1));
  background: var(--wash-2); border: 1px solid var(--border); border-radius: 4px; padding: calc(1px * var(--sp-scale, 1)) calc(5px * var(--sp-scale, 1)); margin-left: 4px; }
.il2-cancel { background: var(--card); border: 1px solid var(--border); color: var(--text2); }

.il2-cols { display: grid; grid-template-columns: 248px minmax(0, 1fr) 276px; gap: calc(14px * var(--sp-scale, 1)); padding: calc(14px * var(--sp-scale, 1)) calc(22px * var(--sp-scale, 1)); align-items: start; }
@media (max-width: 1250px) { .il2-cols { grid-template-columns: 218px minmax(0, 1fr) 244px; } }
@media (max-width: 1000px) { .il2-cols { grid-template-columns: 1fr; } }

.il2-zone-tag { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); font-size: var(--fs-xs);
  font-weight: 700; letter-spacing: .06em; color: var(--text3); }
.il2-zone-tag b { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px;
  border-radius: 50%; background: var(--accent); color: #fff; font-size: calc(9.5px * var(--fs-scale, 1)); }
.il2-zone-hint { font-size: calc(10.5px * var(--fs-scale, 1)); color: var(--text3); line-height: 1.5; margin: 6px 0 12px; }

/* ── ① panel de secciones (réplica del sidebar) ── */
.il2-side-group { margin-bottom: 14px; }
.il2-side-label { font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text3); margin: 0 2px 6px; }
.il2-sidebar-replica { background: var(--card); border: 1px solid var(--border); border-radius: 11px; padding: var(--space-2) calc(6px * var(--sp-scale, 1)); }
.il2-replica-brand { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); font-size: var(--fs-base);
  font-weight: 700; color: var(--text); padding: var(--space-1) var(--space-2) calc(10px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.il2-brand-dot { width: 10px; height: 10px; border-radius: 3px; background: var(--accent); }

.il2-row { display: flex; align-items: center; gap: calc(9px * var(--sp-scale, 1)); padding: calc(6px * var(--sp-scale, 1)) var(--space-2); border-radius: 7px; cursor: pointer;
  font-size: var(--fs-base); color: var(--text2); border: 1.5px solid transparent;
  transition: background var(--dur-micro), border-color var(--dur-micro); }
.il2-row:hover { background: var(--wash-2); color: var(--text); }
.il2-row.active { border-color: var(--accent); background: rgba(var(--accent-rgb), 0.10); color: var(--text); }
.il2-row.flash { animation: il2flash 1.6s ease; }
@keyframes il2flash {
  0%, 55% { background: var(--green-soft); border-color: var(--green); }
  100% { background: transparent; border-color: transparent; }
}
.il2-row-ico { display: flex; align-items: center; justify-content: center; width: 18px; flex-shrink: 0; }
.il2-row-ico.mini-btn { width: 24px; height: 24px; background: var(--wash-2); border: 1px solid var(--border); border-radius: var(--radius-xs); }
.il2-row-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.il2-row-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--orange); flex-shrink: 0; }
/* Control de color individual por slot (galería de iconos) */
.il2-row-color { width: 20px; height: 20px; border-radius: var(--radius-xs); border: 1px solid var(--border); background: var(--wash-2);
  display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; padding: 0; transition: border-color var(--dur-micro), transform var(--dur-micro); }
.il2-row-color:hover { border-color: var(--border2); transform: scale(1.08); }
.il2-row-color.has-indiv { border-color: var(--text2); }
.il2-row-color-sw { width: 12px; height: 12px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18); }
.il2-row-color-sw.auto { background: repeating-linear-gradient(45deg, var(--text3) 0 2px, transparent 2px 4px); box-shadow: inset 0 0 0 1px var(--border2); }
.il2-colorpop { position: fixed; z-index: var(--z-menu); width: 218px; background: var(--card); border: 1px solid var(--border2);
  border-radius: 10px; box-shadow: var(--shadow-modal, 0 8px 30px rgba(0,0,0,0.3)); padding: calc(11px * var(--sp-scale, 1)) var(--space-3); }
.il2-cp-head { font-size: var(--fs-sm); font-weight: 600; color: var(--text2); margin-bottom: 9px; }
.il2-cp-sub { font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text3); margin: 0 0 7px; }
.il2-cp-swatches { display: flex; flex-wrap: wrap; align-items: center; gap: calc(6px * var(--sp-scale, 1)); }

/* ── ② biblioteca ── */
.il2-lib { position: relative; border: 2px solid transparent; border-radius: var(--radius); transition: border-color var(--dur-fast), box-shadow var(--dur-fast); }
.il2-lib.assigning { border-color: var(--accent); box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.12); padding: calc(10px * var(--sp-scale, 1)); }
.il2-toolbar { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; padding-bottom: calc(10px * var(--sp-scale, 1)); }
.il-search { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); background: var(--card); border: 1px solid var(--border);
  border-radius: 8px; padding: calc(7px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); flex: 1; min-width: 170px; max-width: 340px; color: var(--text3); }
.il-search input { flex: 1; border: none; outline: none; background: transparent; color: var(--text); font-size: var(--fs-md); }
.il2-cat-btn { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); }
.il2-cat-btn.active { color: var(--accent); border-color: var(--accent); }
.il2-zoom { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); font-size: calc(10.5px * var(--fs-scale, 1)); color: var(--text3); white-space: nowrap; }
.il2-zoom input[type="range"] { width: 90px; accent-color: var(--text3); }
.il-count { font-size: var(--fs-sm); color: var(--text3); margin-left: auto; }
.il2-catpop { position: absolute; top: 46px; left: 0; right: 0; z-index: var(--z-il2-catpop); display: flex; flex-wrap: wrap; gap: calc(5px * var(--sp-scale, 1));
  background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: var(--space-3);
  max-height: 260px; overflow-y: auto; box-shadow: var(--shadow-pop, 0 8px 30px rgba(0,0,0,.35)); }

.il-grid { display: grid; align-content: start; grid-template-columns: repeat(auto-fill, minmax(56px, 1fr)); gap: calc(6px * var(--sp-scale, 1));
  padding: calc(2px * var(--sp-scale, 1)); --il-size: 24px; --il-stroke: 2; --il-color: currentColor; }
.il-card { display: flex; align-items: center; justify-content: center; aspect-ratio: 1;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm); cursor: pointer;
  color: var(--text2); transition: border-color var(--dur-micro), color var(--dur-micro); padding: 0; }
.il-card:hover { border-color: var(--accent); color: var(--text); }
.il-card svg { width: var(--il-size); height: var(--il-size); stroke-width: var(--il-stroke); color: var(--il-color); }

/* ── ③ estética global + cambios ── */
.il2-right { display: flex; flex-direction: column; gap: calc(14px * var(--sp-scale, 1)); }
.il2-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: calc(14px * var(--sp-scale, 1)); }
.il2-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-2); }
.il2-card-title { font-size: var(--fs-base); font-weight: 700; color: var(--text); }
.il2-global-badge { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-2xs);
  font-weight: 700; letter-spacing: .05em; color: var(--orange); background: var(--orange-soft);
  border: 1px solid var(--orange-border); border-radius: var(--radius-pill); padding: calc(2px * var(--sp-scale, 1)) var(--space-2); white-space: nowrap; }
.il2-card-desc { font-size: calc(10.5px * var(--fs-scale, 1)); color: var(--text3); line-height: 1.5; margin: 6px 0 12px; }
.il2-aes-ctl { display: block; font-size: calc(11.5px * var(--fs-scale, 1)); color: var(--text2); margin-bottom: 12px; }
.il2-aes-ctl em { font-style: normal; color: var(--accent); font-variant-numeric: tabular-nums; margin-left: 4px; }
.il2-aes-ctl input[type="range"] { display: block; width: 100%; margin-top: 7px; accent-color: var(--accent); }
.il2-swatches { display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); flex-wrap: wrap; margin-top: 7px; }
.il2-sw-auto { font-size: var(--fs-xs); font-weight: 600; font-family: inherit; color: var(--text2);
  background: var(--wash-2); border: 1.5px solid var(--border); border-radius: var(--radius-pill); padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); cursor: pointer; }
.il2-sw-auto.sel { border-color: var(--accent); color: var(--accent); }
.il2-color-row { display: flex; align-items: center; gap: var(--space-2); margin-top: 8px; }
.il2-color-row input[type="color"] { width: 34px; height: 26px; border: 1px solid var(--border); border-radius: var(--radius-xs);
  padding: calc(1px * var(--sp-scale, 1)); background: var(--card); cursor: pointer; }
.il2-aes-preview { display: flex; align-items: center; justify-content: center; gap: var(--space-3);
  border: 1px dashed var(--border); border-radius: 8px; padding: calc(10px * var(--sp-scale, 1)); margin-top: 4px; color: var(--text2); }
.il2-aes-note { font-size: calc(9.5px * var(--fs-scale, 1)); color: var(--text3); text-align: center; margin-top: 5px; }

.il2-pending-empty { font-size: var(--fs-sm); color: var(--text3); line-height: 1.55; margin-top: 8px; }
.il2-pend-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: calc(7px * var(--sp-scale, 1)) 0;
  border-bottom: 1px solid var(--border); font-size: var(--fs-sm); color: var(--text2); line-height: 1.4; }
.il2-pend-row:last-child { border-bottom: none; }
.il2-pend-row code { color: var(--accent); font-size: calc(10.5px * var(--fs-scale, 1)); }
.il2-pend-undo { border: none; background: transparent; color: var(--accent); cursor: pointer;
  font-size: var(--fs-lg); padding: 0 calc(3px * var(--sp-scale, 1)); flex-shrink: 0; }

.il2-assignpop { position: fixed; z-index: var(--z-modal); width: 250px; max-height: 420px; overflow-y: auto;
  background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: var(--space-2);
  box-shadow: var(--shadow-pop, 0 10px 34px rgba(0,0,0,.4)); }
.il2-ap-head { font-size: var(--fs-sm); font-weight: 700; color: var(--text); padding: var(--space-1) calc(6px * var(--sp-scale, 1)) var(--space-2); }
.il2-ap-label { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text3); padding: calc(6px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)) calc(3px * var(--sp-scale, 1)); }
.il2-ap-row { display: block; width: 100%; text-align: left; font-family: inherit; font-size: calc(11.5px * var(--fs-scale, 1));
  color: var(--text2); background: transparent; border: none; border-radius: var(--radius-xs); padding: calc(6px * var(--sp-scale, 1)) var(--space-2); cursor: pointer; }
.il2-ap-row:hover { background: var(--wash-2); color: var(--text); }

/* ══════════════════════════════════════════════════════════
   EDITOR UI (Personalización, solo admin) — page-ui-editor
   Rediseño 2026-07-05: guía visible, controles explicados, temas con
   botones de palabras. Visibilidad de nav .adm-only: admin O modo dev.
   ══════════════════════════════════════════════════════════ */
#view-app .adm-only { display: none; }
/* Fase A (2026-08-20): el área Administration la ve quien puede LEER algo de
   ella (can-adm-area = platform.read | budget.read | finance.read, p.ej. el
   executive-producer en solo lectura §7). role-admin queda como respaldo del
   arranque en frío. Las escrituras las corta el server con 403. */
#view-app.role-admin .adm-only { display: block; }
#view-app.can-adm-area .adm-only { display: block; }
body.dev-mode #view-app .adm-only { display: block; }

#page-ui-editor { padding: calc(18px * var(--sp-scale, 1)) calc(22px * var(--sp-scale, 1)); overflow-y: auto; }
.ue-savestate.dirty { color: var(--orange); font-weight: 600; }
@media (max-width: 1150px) { }

.ue-ctl { display: block; margin-bottom: 16px; }
.ue-ctl-name { display: block; font-size: calc(12.5px * var(--fs-scale, 1)); font-weight: 600; color: var(--text); }
.ue-ctl-name em { font-style: normal; color: var(--accent); font-variant-numeric: tabular-nums; margin-left: 4px; }
.ue-ctl-desc { display: block; font-size: var(--fs-sm); color: var(--text3); line-height: 1.5; margin-top: 2px; }
.ue-ctl input[type="range"] { display: block; width: 100%; margin-top: 8px; accent-color: var(--accent); }
.ue-range-row { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); margin-top: 8px; color: var(--text3); }
.ue-range-row small { font-size: var(--fs-xs); } .ue-range-row big { font-size: calc(16px * var(--fs-scale, 1)); }
.ue-range-row input[type="range"] { flex: 1; margin-top: 0; }
.ue-ctl select, .ue-ctl input[type="number"] { display: block; width: 100%; margin-top: 8px; font-size: var(--fs-base);
  padding: var(--space-2) calc(10px * var(--sp-scale, 1)); border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--text); font-family: inherit; }
.ue-swatch { width: 24px; height: 24px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; padding: 0;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.15); transition: transform var(--dur-micro); }
.ue-swatch:hover { transform: scale(1.15); }
.ue-swatch.sel { border-color: var(--text); }

.ue-details > summary { cursor: pointer; list-style: none; }
.ue-details > summary::-webkit-details-marker { display: none; }
.ue-details > summary .ue-panel-title::before { content: "▸ "; color: var(--text3); }
.ue-details[open] > summary .ue-panel-title::before { content: "▾ "; }
.ue-details[open] > summary { margin-bottom: 12px; }

.ue-active-name { font-size: calc(15px * var(--fs-scale, 1)); font-weight: 700; color: var(--accent); }

.ue-theme-row { border: 1px solid var(--border); border-radius: 10px; padding: calc(10px * var(--sp-scale, 1)) var(--space-3); margin-bottom: 8px; }
.ue-theme-row.active { border-color: rgba(var(--accent-rgb), 0.45); background: rgba(var(--accent-rgb), 0.06); }
.ue-theme-top { display: flex; align-items: center; gap: var(--space-2); }
.ue-theme-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border); flex-shrink: 0; }
.ue-theme-row.active .ue-theme-dot { background: var(--accent); }
.ue-theme-name { flex: 1; font-size: var(--fs-md); font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ue-theme-badge { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .05em; color: var(--accent); text-transform: uppercase;
  background: rgba(var(--accent-rgb), 0.12); border-radius: var(--radius-pill); padding: calc(2px * var(--sp-scale, 1)) var(--space-2); }
.ue-theme-actions { display: flex; gap: var(--space-1); margin-top: 8px; flex-wrap: wrap; }
.ue-theme-actions .btn { padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); font-size: var(--fs-sm); }
.ue-theme-actions .ue-del { color: var(--red); }
.ue-theme-top .btn { padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); }

.ue-norm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: calc(10px * var(--sp-scale, 1)); }
.ue-norm-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; margin: 4px 0 12px; }
.ue-audit-sum { font-size: var(--fs-base); color: var(--text2); margin-bottom: 8px; line-height: 1.5; }
.ue-audit-tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); color: var(--text2); }
.ue-audit-tbl th { text-align: left; color: var(--text3); font-weight: 600; padding: var(--space-1) calc(6px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); }
.ue-audit-tbl td { padding: calc(5px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); border-bottom: 1px solid var(--border); vertical-align: top; }
.ue-audit-ej { color: var(--text3); font-size: var(--fs-xs); }
.ue-audit-note { font-size: var(--fs-sm); color: var(--text3); margin-top: 10px; line-height: 1.5; }

/* ══ Galería de iconos: categorías (como lucide.dev) + campos HEX ══ */
.il-cats { display: flex; flex-wrap: wrap; gap: calc(5px * var(--sp-scale, 1)); padding: calc(2px * var(--sp-scale, 1)) calc(2px * var(--sp-scale, 1)) var(--space-3); }
.il-cat-chip { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); padding: var(--space-1) calc(10px * var(--sp-scale, 1));
  font-size: var(--fs-sm); font-family: inherit; color: var(--text2);
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-pill);
  cursor: pointer; transition: border-color var(--dur-micro), background var(--dur-micro), color var(--dur-micro); }
.il-cat-chip span { font-size: calc(9.5px * var(--fs-scale, 1)); color: var(--text3); font-variant-numeric: tabular-nums; }
.il-cat-chip:hover { border-color: var(--accent); color: var(--text); }
.il-cat-chip.active { background: rgba(var(--accent-rgb), 0.12); border-color: var(--accent); color: var(--accent); }
.il-cat-chip.active span { color: var(--accent); }

.il-hex, .ue-hex { width: 86px; font-size: calc(11.5px * var(--fs-scale, 1));
  font-family: var(--font-mono); text-transform: uppercase;
  padding: calc(5px * var(--sp-scale, 1)) var(--space-2); border: 1px solid var(--border); border-radius: var(--radius-xs);
  background: var(--card); color: var(--text); outline: none; }
.il-hex:focus, .ue-hex:focus { border-color: var(--accent); }
.il-hex.bad, .ue-hex.bad { border-color: var(--red); color: var(--red); }

/* ══════════════════════════════════════════════════════════
   EDITOR UI v2 (uev-) — mockup UIEditor_Redesign_Mockup_v1 aprobado.
   Reutiliza il2- (cabecera, tarjetas, pendientes) y ue- (controles, temas).
   La mini-app (.uev-app) usa variables --pv-* que fija ui-editor.js según
   el modo editado + tokens en curso — NO usa los tokens reales del docto.
   ══════════════════════════════════════════════════════════ */
#page-ui-editor { padding: 0; }
.uev-cols { display: grid; grid-template-columns: 300px minmax(0, 1fr) 280px; gap: calc(14px * var(--sp-scale, 1)); padding: calc(14px * var(--sp-scale, 1)) calc(22px * var(--sp-scale, 1)); align-items: start; }
@media (max-width: 1280px) { .uev-cols { grid-template-columns: 260px minmax(0, 1fr) 250px; } }
@media (max-width: 1020px) { .uev-cols { grid-template-columns: 1fr; } }
.uev-ctrls { display: flex; flex-direction: column; gap: calc(14px * var(--sp-scale, 1)); min-width: 0; }

.uev-mode-chip { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); font-family: inherit; cursor: pointer;
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .04em;
  color: #b18cff; background: rgba(140, 100, 255, 0.12); border: 1px solid rgba(140, 100, 255, 0.4);
  border-radius: var(--radius-pill); padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); }
.uev-seg { display: inline-flex; gap: 0; margin-top: 8px; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.uev-seg button { font-family: inherit; font-size: var(--fs-sm); color: var(--text2);
  background: transparent; border: none; padding: calc(6px * var(--sp-scale, 1)) var(--space-3); cursor: pointer; }
.uev-seg button + button { border-left: 1px solid var(--border); }
.uev-seg button.sel { background: rgba(var(--accent-rgb), 0.15); color: var(--accent); font-weight: 600; }
.uev-contrast { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); font-size: var(--fs-xs);
  font-weight: 600; color: var(--orange); background: var(--orange-soft); border: 1px solid var(--orange-border);
  border-radius: var(--radius-pill); padding: calc(2px * var(--sp-scale, 1)) var(--space-2); margin-left: 6px; }
.uev-contrast button { font-family: inherit; font-size: inherit; font-weight: 700; color: var(--orange);
  background: transparent; border: none; text-decoration: underline; cursor: pointer; padding: 0; }

.uev-center { min-width: 0; }
.uev-pv-head { display: flex; align-items: center; justify-content: space-between; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 6px; }
.uev-pv-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.uev-pv-toggle button { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); font-family: inherit;
  font-size: var(--fs-sm); color: var(--text2); background: transparent; border: none;
  padding: calc(6px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); cursor: pointer; }
.uev-pv-toggle button + button { border-left: 1px solid var(--border); }
.uev-pv-toggle button.sel { background: var(--wash-2); color: var(--text); font-weight: 600; }

/* ── mini-app ── */
.uev-app { display: flex; min-height: 420px; border: 1px solid var(--border2); border-radius: 14px; overflow: hidden;
  background: var(--pv-bg); color: var(--pv-text); font-family: var(--pv-font); line-height: var(--pv-lh);
  box-shadow: 0 6px 24px rgba(0,0,0,0.25); }
.uev-sb { width: 168px; flex-shrink: 0; background: var(--pv-bg2); border-right: 1px solid var(--pv-border);
  padding: calc(14px * var(--pv-sp)) calc(10px * var(--pv-sp)); }
.uev-sb-brand { display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1)); font-size: calc(12.5px * var(--pv-fs)); font-weight: 700;
  color: var(--pv-text); margin-bottom: calc(14px * var(--pv-sp)); }
.uev-sb-dot { width: 11px; height: 11px; border-radius: 3px; background: var(--pv-accent); }
.uev-sb-item { display: flex; align-items: center; gap: var(--space-2); font-size: calc(11.5px * var(--pv-fs)); color: var(--pv-text2);
  padding: calc(6px * var(--pv-sp)) calc(8px * var(--pv-sp)); border-radius: 7px; margin-bottom: 2px; }
.uev-sb-item.active { background: color-mix(in srgb, var(--pv-accent) 16%, transparent); color: var(--pv-accent); font-weight: 600; }
.uev-sb-item svg { flex-shrink: 0; }

.uev-main { flex: 1; min-width: 0; padding: calc(16px * var(--pv-sp)) calc(18px * var(--pv-sp)); }
.uev-page-head { display: flex; align-items: center; justify-content: space-between; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: calc(14px * var(--pv-sp)); }
.uev-h1 { font-size: calc(17px * var(--pv-fs)); font-weight: 700; color: var(--pv-text); }
.uev-btns { display: flex; gap: var(--space-2); }
.uev-b { zoom: var(--pv-btn); font-family: inherit; font-size: calc(11.5px * var(--pv-fs)); font-weight: 500;
  border-radius: var(--pv-btnrad); padding: calc(7px * var(--pv-sp)) calc(13px * var(--pv-sp)); cursor: pointer; border: none; }
.uev-b.pri { background: var(--pv-accent); color: #fff; }
.uev-b.sec { background: var(--pv-card2); color: var(--pv-text); border: 1px solid var(--pv-border2); }
.uev-b.ghost { background: transparent; color: var(--pv-text2); border: 1px solid transparent; }
.uev-b.danger { background: transparent; color: #d4544f; border: 1px solid rgba(212, 84, 79, 0.45); }
.uev-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: calc(10px * var(--pv-sp)); margin-bottom: calc(14px * var(--pv-sp)); }
.uev-kpi { background: var(--pv-card); border: 1px solid var(--pv-border); border-radius: var(--pv-radius);
  padding: calc(12px * var(--pv-sp)) calc(14px * var(--pv-sp)); }
.uev-kpi small { display: block; font-size: calc(9px * var(--pv-fs)); font-weight: 700; letter-spacing: .06em; color: var(--pv-text3); margin-bottom: 5px; }
.uev-kpi b { font-size: calc(21px * var(--pv-fs)); font-weight: 700; color: var(--pv-text); }
.uev-kpi b.acc { color: var(--pv-accent); }
.uev-table { background: var(--pv-card); border: 1px solid var(--pv-border); border-radius: var(--pv-radius);
  overflow: hidden; margin-bottom: calc(14px * var(--pv-sp)); }
.uev-tr { display: grid; grid-template-columns: 120px 1fr auto; gap: calc(10px * var(--sp-scale, 1)); align-items: center;
  padding: calc(9px * var(--pv-sp)) calc(13px * var(--pv-sp)); border-bottom: 1px solid var(--pv-border);
  font-size: calc(11.5px * var(--pv-fs)); color: var(--pv-text2); }
.uev-tr:last-child { border-bottom: none; }
.uev-th { font-size: calc(9px * var(--pv-fs)); font-weight: 700; letter-spacing: .06em; color: var(--pv-text3); background: var(--pv-card2); }
.uev-code { font-family: var(--font-mono); font-size: calc(10.5px * var(--pv-fs)); color: var(--pv-text); font-weight: 600; }
.uev-pill { font-style: normal; font-size: calc(9.5px * var(--pv-fs)); font-weight: 700; border-radius: 20px; padding: calc(2px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); }
.uev-pill.blue { color: #6db2ff; background: rgba(10, 132, 255, 0.16); }
.uev-pill.green { color: #4fce7f; background: rgba(47, 177, 112, 0.16); }
.uev-pill.orange { color: #eda45c; background: rgba(224, 138, 60, 0.16); }
.uev-btnrow { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-bottom: calc(12px * var(--pv-sp)); }
.uev-sec-txt { font-size: calc(10.5px * var(--pv-fs)); color: var(--pv-text2); line-height: var(--pv-lh); }
.uev-sec-txt a { color: var(--pv-accent); text-decoration: underline; cursor: pointer; }

/* ══ Fase E: posición de elementos (Editor UI) ══ */
.uev-pos-zone { margin-bottom: 12px; }
.uev-pos-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  padding: calc(5px * var(--sp-scale, 1)) var(--space-2); border: 1px solid var(--border);
  border-radius: 7px; margin-bottom: 4px; font-size: calc(11.5px * var(--fs-scale, 1)); color: var(--text2);
  background: var(--card); }
.uev-pos-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uev-pos-btns { display: flex; gap: calc(3px * var(--sp-scale, 1)); flex-shrink: 0; }
.uev-pos-btns button { width: 22px; height: 22px; font-family: inherit; font-size: var(--fs-base);
  color: var(--text2); background: var(--wash-2); border: 1px solid var(--border); border-radius: 5px; cursor: pointer; }
.uev-pos-btns button:hover:not(:disabled) { color: var(--accent); border-color: var(--accent); }
.uev-pos-btns button:disabled { opacity: 0.3; cursor: default; }


/* ══════════════════════════════════════════════════════════
   ÁREA ADMINISTRATION (Plataforma Producción · "FileMaker 2.0")
   Fase 1 Cotización — espejo del Mockup_v2 validado 2026-07-10.
   Todo tokenizado (fs/space/radius/z) para pasar los gates DS.
   ══════════════════════════════════════════════════════════ */

/* ── Selector de área (sidebar) ── */
.areasel { display: flex; background: var(--wash-2); border-radius: var(--radius-sm); padding: calc(3px * var(--sp-scale, 1)); margin: 0 12px 8px; }
/* El .adm-only genérico pone display:block al mostrarse a admins — el selector
   de área necesita flex, así que se re-especifica aquí (misma condición). */
#view-app.role-admin .areasel.adm-only { display: flex; }
#view-app.can-adm-area .areasel.adm-only { display: flex; }
body.dev-mode #view-app .areasel.adm-only { display: flex; }
/* B1 (auditoría UX 2026-07-11): comprimido no hay ancho para los dos botones —
   el selector se oculta (el área activa se conserva; expandir para cambiar). */
#view-app.sb-collapsed .areasel.adm-only,
body.dev-mode #view-app.sb-collapsed .areasel.adm-only { display: none; }
.areasel button { flex: 1; border: 0; background: transparent; padding: calc(6px * var(--sp-scale, 1)) var(--space-2); border-radius: var(--radius-xs); color: var(--text2); font-weight: 600; font-size: var(--fs-sm); cursor: pointer; }
.areasel button.on { background: var(--card); color: var(--text); box-shadow: var(--shadow-card); }

/* ── Visibilidad por área: en area-admin solo se ven las secciones .adm-area ── */
#view-app .sidebar-nav .nav-section.adm-area { display: none; }
#view-app.role-admin.area-admin .sidebar-nav .nav-section.adm-area { display: block; }
#view-app.can-adm-area.area-admin .sidebar-nav .nav-section.adm-area { display: block; }
body.dev-mode #view-app.area-admin .sidebar-nav .nav-section.adm-area { display: block; }
#view-app.role-admin.area-admin .sidebar-nav .nav-section:not(.adm-area) { display: none; }
#view-app.can-adm-area.area-admin .sidebar-nav .nav-section:not(.adm-area) { display: none; }
body.dev-mode #view-app.area-admin .sidebar-nav .nav-section:not(.adm-area) { display: none; }

/* ── Roles simulados ("View as" del modal FX; solo visual, sesión intacta) ── */
#view-app[data-admrole="production"] [data-priv="cost"] { display: none !important; }
#view-app[data-admrole="readonly"] .adm-page .edit-only,
#view-app[data-admrole="readonly"] .modal .edit-only { opacity: 0.4; pointer-events: none; }
.rolechip { font-size: var(--fs-xs); font-weight: 700; padding: calc(2px * var(--sp-scale, 1)) var(--space-2); border-radius: var(--radius-pill); }
.rolechip.admin { background: rgba(var(--purple-rgb), 0.14); color: var(--purple); }
.rolechip.production { background: rgba(var(--accent-rgb), 0.14); color: var(--accent); }
.rolechip.readonly { background: var(--wash-3); color: var(--text2); }

/* ── Básicos de página (espejo del mockup, con alcance .adm-page/.adm-modal) ── */
.adm-page .spacer, .adm-modal .spacer { flex: 1; }
.adm-page .subhead { font-size: calc(15px * var(--fs-scale, 1)); font-weight: 650; margin: 0; }
.adm-page .note, .adm-modal .note { font-size: var(--fs-base); color: var(--text2); }
.adm-page .hr, .adm-modal .hr { height: 1px; background: var(--border); margin: 14px 0; }
.adm-page .hr.adm-hr-tight { margin: 10px 0; }
.adm-page .pill, .adm-modal .pill { font-size: var(--fs-sm); background: var(--wash-2); color: var(--text2); border-radius: var(--radius-pill); padding: calc(3px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); font-weight: 500; }
.adm-page .info { background: rgba(var(--accent-rgb), 0.06); border: 1px solid var(--accent-border); color: var(--text2); border-radius: var(--radius-sm); padding: calc(11px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); font-size: var(--fs-base); margin-bottom: 16px; }
.adm-page .crumb { color: var(--text2); font-size: var(--fs-base); padding: calc(14px * var(--sp-scale, 1)) calc(28px * var(--sp-scale, 1)) 0; }
.adm-page .crumb b { color: var(--accent); cursor: pointer; }
.adm-page .thumb { width: 58px; height: 33px; border-radius: var(--radius-xs); background: linear-gradient(135deg, var(--wash-3), var(--wash-4)); background-size: cover; background-position: center; display: block; }
.adm-page .thumb.adm-le-thumb { width: 100%; height: 280px; }
.adm-page .alias-chip, .adm-modal .alias-chip { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-sm); background: var(--wash-2); border: 1px solid var(--border); color: var(--text2); border-radius: var(--radius-pill); padding: calc(2px * var(--sp-scale, 1)) var(--space-2); margin: 2px 3px 2px 0; font-family: var(--font-mono); }
.adm-page .fxchip { font-size: var(--fs-sm); color: var(--text2); background: var(--wash-2); border-radius: var(--radius-xs); padding: calc(5px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); }
/* Tipografía/padding de las acciones primarias del header ADM. El `width:auto`
   que esta regla traía se RETIRÓ el 2026-07-24 junto con el full-width de
   .btn-primary (ver la nota junto a esa clase). No toca height: hereda .btn-sm. */
.adm-page .page-header-actions .btn-primary { padding: var(--space-2) var(--space-4); font-size: var(--fs-md); }
.adm-page .page-header-actions .btn-primary.btn-sm { padding: calc(5px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1)); font-size: var(--fs-base); }
.adm-clickable { cursor: pointer; }

/* ── Inputs / campos ── */
.adm-page .inp, .adm-modal .inp { background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-xs); padding: calc(5px * var(--sp-scale, 1)) var(--space-2); font-size: var(--fs-md); color: var(--text); text-align: right; font-variant-numeric: tabular-nums; width: 64px; outline: none; }
.adm-page .inp:focus, .adm-modal .inp:focus { border-color: var(--accent); }
/* .inp nace angosto (64px) porque su uso mayoritario es capturar cifras. Los
   controles que llevan TEXTO o un widget nativo necesitan su ancho natural.
   `type=month` se sumó el 2026-07-24 (filtro del historial de FX): sin esto
   el selector de mes queda cortado a 64px y el spinner nativo no cabe. */
.adm-page select.inp, .adm-page input.inp[type=text], .adm-page input.inp[type=month],
.adm-modal select.inp, .adm-modal input.inp[type=text], .adm-modal input.inp[type=month] { text-align: left; width: auto; }
.adm-page select.inp, .adm-modal select.inp { -webkit-appearance: none; appearance: none; padding-right: calc(26px * var(--sp-scale, 1)); cursor: pointer; background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23909096' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 9px center; }
.adm-page textarea.inp, .adm-modal textarea.inp { text-align: left; font-family: inherit; resize: vertical; width: 100%; min-height: 36px; }
.adm-page .fld, .adm-modal .fld { margin-bottom: 13px; }
.adm-page .fld label, .adm-modal .fld label { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--text2); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 5px; }
.adm-page .fld .inp, .adm-modal .fld .inp { width: 100%; text-align: left; }
.adm-modal .adm-monofield { font-family: var(--font-mono); }
.adm-page .adm-label-note, .adm-modal .adm-label-note { text-transform: none; font-weight: 400; }

/* ── Segmentado (espejo del mockup: .seg) ── */
.adm-page .seg, .adm-modal .seg { display: inline-flex; background: var(--wash-2); border-radius: var(--radius-sm); padding: calc(3px * var(--sp-scale, 1)); }
.adm-page .seg button, .adm-modal .seg button { border: 0; background: transparent; padding: calc(6px * var(--sp-scale, 1)) calc(13px * var(--sp-scale, 1)); border-radius: var(--radius-xs); color: var(--text2); font-weight: 600; font-size: var(--fs-base); cursor: pointer; }
.adm-page .seg button.on, .adm-modal .seg button.on { background: var(--card); color: var(--text); box-shadow: var(--shadow-card); }

/* ── Tabs ── */
/* .adm-modal se sumó el 2026-07-24: el modal de FX usa el mismo componente de
   pestañas y sin esto quedaba sin línea inferior, pegado al contenido. */
.adm-page .tabs, .adm-modal .tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin-bottom: 16px; }

/* ── Tablas: alineación + grouprows + filas clickeables ── */
.adm-page .data-table th.right, .adm-page .data-table td.right, .adm-modal .data-table th.right, .adm-modal .data-table td.right { text-align: right; }
.adm-page .data-table th.center, .adm-page .data-table td.center { text-align: center; }
.adm-page .data-table td.right, .adm-page .data-table td.mono { font-variant-numeric: tabular-nums; }
.adm-page .grouprow td { background: var(--wash-2); font-weight: 700; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text3); }
.adm-page .data-table tr.clk { cursor: pointer; }
.adm-page .data-table tr.clk:hover td { background: var(--wash-1); }
.adm-page .card.adm-tablecard { padding: calc(6px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); }
/* Separación vertical entre tarjetas de tabla apiladas (Portfolio P&L / Recent
   bids en el Dashboard): antes quedaban pegadas porque .adm-tablecard solo define
   padding. Se iguala al ritmo de la grilla de KPIs (margin-bottom: 18px). */
.adm-page .card.adm-tablecard + .card.adm-tablecard { margin-top: 18px; }
.adm-page .adm-scroll-x { overflow-x: auto; }

/* ── Cards / grids ── */
.adm-page .card.pad, .adm-modal .card.pad { padding: var(--space-4); }
.adm-page .stats-grid.adm-grid4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.adm-page .stats-grid.adm-grid6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
@media (max-width: 1500px) { .adm-page .stats-grid.adm-grid6 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1200px) { .adm-page .stats-grid.adm-grid4, .adm-page .stats-grid.adm-grid6 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.adm-page .stat-card .value.adm-val-sm { font-size: var(--fs-xl); }
.adm-page .adm-disc-in { width: 60px; }
.adm-page .ratecards { grid-template-columns: repeat(3, 1fr); }
.adm-page .ratecard { cursor: pointer; transition: 0.12s; }
.adm-page .ratecard:hover { border-color: var(--accent-border); box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18); }
.adm-page .ratecard h3 { margin: 0 0 3px; font-size: calc(15px * var(--fs-scale, 1)); }
.adm-page .tmpl-grid { grid-template-columns: repeat(3, 1fr); }
.adm-page .tmpl { cursor: pointer; position: relative; }
.adm-page .tmpl:hover { border-color: var(--accent-border); }
.adm-page .tmpl .delx { position: absolute; top: -8px; right: -8px; width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--border2); background: var(--card2); color: var(--text2); font-size: var(--fs-sm); cursor: pointer; display: none; align-items: center; justify-content: center; box-shadow: var(--shadow-card); }
.adm-page .tmpl:hover .delx { display: flex; }
.adm-page .tmpl .delx:hover { background: rgba(var(--red-rgb), 0.15); color: var(--red); border-color: rgba(var(--red-rgb), 0.4); }

/* ── Line editor ── */
.adm-page .adm-le-grid { display: grid; grid-template-columns: 260px minmax(380px, 620px) 300px; gap: var(--space-3); align-items: start; justify-content: start; }
.adm-page.adm-page .adm-le-body { padding-top: calc(6px * var(--sp-scale, 1)); }
.adm-page .adm-crumb-pad { padding-bottom: calc(14px * var(--sp-scale, 1)); }
#page-adm-line .fld { margin-bottom: 9px; }
#page-adm-line .fld label { margin-bottom: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#page-adm-line .inp { padding: var(--space-1) var(--space-2); font-size: var(--fs-base); }
#page-adm-line .subhead { font-size: calc(13.5px * var(--fs-scale, 1)); }
#page-adm-line .data-table td { padding: calc(5px * var(--sp-scale, 1)) var(--space-2); }
.adm-page .ratepanel td { padding: var(--space-1) var(--space-2); font-size: var(--fs-base); }
.adm-page .ratepanel .inp { width: 66px; padding: calc(2px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); font-size: var(--fs-sm); }
.adm-page .rate-active td { background: rgba(var(--green-rgb), 0.10) !important; color: var(--text); font-weight: 700; }
.adm-page .le-total { display: flex; justify-content: space-between; padding: calc(7px * var(--sp-scale, 1)) 0; font-size: var(--fs-md); color: var(--text2); }
.adm-page .le-total.big { font-size: var(--fs-xl); font-weight: 700; color: var(--text); border-top: 2px solid var(--border); margin-top: 6px; padding-top: var(--space-3); }
.adm-page .adm-strong { color: var(--text); }

/* ── Wizard ── */
.adm-modal .wsteps { display: flex; gap: var(--space-1); align-items: center; margin-right: 8px; margin-left: auto; }
.adm-modal .wdot { width: 22px; height: 22px; border-radius: 50%; background: var(--wash-3); color: var(--text3); font-size: var(--fs-sm); font-weight: 700; display: flex; align-items: center; justify-content: center; }
.adm-modal .wdot.on { background: var(--accent); color: #fff; }
.adm-modal .wdot.done { background: rgba(var(--green-rgb), 0.18); color: var(--green); }
.adm-modal .wline { width: 18px; height: 1.5px; background: var(--border2); }
.adm-modal .opt-grid, .adm-page .opt-grid { display: grid; grid-template-columns: 1fr 1fr; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 14px; }
.adm-modal .opt-card, .adm-page .opt-card { border: 1.5px solid var(--border); border-radius: var(--radius-sm); padding: var(--space-3) calc(14px * var(--sp-scale, 1)); cursor: pointer; transition: 0.12s; background: var(--wash-1); }
.adm-modal .opt-card:hover, .adm-page .opt-card:hover { border-color: var(--border2); }
.adm-modal .opt-card.on, .adm-page .opt-card.on { border-color: var(--accent); background: var(--accent-soft); }
.adm-modal .opt-card b, .adm-page .opt-card b { display: block; font-size: var(--fs-md); }
.adm-modal .opt-card span, .adm-page .opt-card span { font-size: var(--fs-sm); color: var(--text2); }
.adm-modal .adm-wz-name { width: 100%; text-align: left; font-family: var(--font-mono); color: var(--accent); }
.adm-modal .adm-wiz-summary { background: var(--wash-1); }

/* ── Modales del área (estructura head/body/foot del mockup) ── */
.adm-modal { width: 640px; max-width: 94vw; max-height: 88vh; display: flex; flex-direction: column; }
.adm-modal.adm-modal-wide { width: 900px; }
.adm-modal.adm-modal-sm { width: 400px; }
.adm-modal .modal-header { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); }
.adm-modal .modal-body { padding: calc(18px * var(--sp-scale, 1)) var(--space-5); overflow-y: auto; flex: 1; }
.adm-modal .modal-foot { padding: var(--space-3) var(--space-5); border-top: 1px solid var(--border); display: flex; gap: var(--space-2); justify-content: flex-end; align-items: center; }
.adm-modal .adm-mr-auto { margin-right: auto; }
.adm-modal .adm-ex-bg { background: var(--bg2); }
.adm-modal .adm-dropzone { border: 1.5px dashed var(--border2); border-radius: var(--radius); padding: calc(34px * var(--sp-scale, 1)); text-align: center; color: var(--text2); cursor: pointer; transition: 0.12s; }
.adm-modal .adm-dropzone:hover { border-color: var(--accent); background: var(--accent-soft); }

/* ── Export "paper" (blanco a propósito: es el documento para el cliente) ── */
.adm-modal .paper { background: #fff; color: #1d1d1f; border-radius: var(--radius-sm); padding: calc(26px * var(--sp-scale, 1)) calc(30px * var(--sp-scale, 1)); font-size: var(--fs-base); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35); max-width: 820px; margin: 0 auto; }
.adm-modal .paper h2 { margin: 0; font-size: calc(17px * var(--fs-scale, 1)); letter-spacing: -0.3px; }
.adm-modal .paper .phead { display: flex; justify-content: space-between; align-items: flex-start; border-bottom: 2px solid #1d1d1f; padding-bottom: calc(10px * var(--sp-scale, 1)); margin-bottom: 14px; }
.adm-modal .paper table { width: 100%; border-collapse: collapse; margin: 8px 0 16px; }
.adm-modal .paper th { text-align: left; font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.06em; color: #6e6e73; border-bottom: 1px solid #d2d2d7; padding: var(--space-1) var(--space-2); }
.adm-modal .paper td { padding: calc(5px * var(--sp-scale, 1)) var(--space-2); border-bottom: 1px solid #f0f0f2; font-size: var(--fs-sm); }
.adm-modal .paper .tot td { border-top: 2px solid #1d1d1f; border-bottom: none; font-weight: 700; font-size: var(--fs-base); }
.adm-modal .paper .psec { font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: #6e6e73; margin: 14px 0 2px; }
.adm-modal .adm-paper-dim { color: #6e6e73; }
.adm-modal .adm-paper-for { text-align: right; font-size: var(--fs-sm); color: #6e6e73; }
.adm-modal .adm-paper-for b { color: #1d1d1f; }
.adm-modal .adm-paper-assume { font-size: var(--fs-sm); color: #3c3c43; line-height: 1.6; }
.adm-modal .mgrid { overflow: auto; }
.adm-modal .mgrid table { border-collapse: collapse; font-size: var(--fs-sm); min-width: 100%; }
.adm-modal .mgrid th, .adm-modal .mgrid td { padding: var(--space-1) calc(7px * var(--sp-scale, 1)); border: 1px solid var(--wash-3); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.adm-modal .mgrid th { background: var(--wash-2); font-size: var(--fs-2xs); text-transform: uppercase; color: var(--text3); }
.adm-modal .mgrid td:first-child, .adm-modal .mgrid th:first-child { text-align: left; position: sticky; left: 0; background: var(--card); z-index: 1; }

/* ── Utilerías de layout del área (reemplazan estilos inline del mockup) ── */
.adm-page .adm-rowhead, .adm-modal .adm-rowhead { display: flex; align-items: center; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: 12px; flex-wrap: wrap; }
.adm-page .adm-filterrow { display: flex; gap: var(--space-2); margin-bottom: 14px; flex-wrap: wrap; align-items: center; }
.adm-page .adm-bulkrow { display: flex; gap: calc(10px * var(--sp-scale, 1)); align-items: flex-end; flex-wrap: wrap; }
.adm-page .adm-selfcenter { align-self: center; }
.adm-page .adm-grid2col { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
.adm-page .adm-grid3f { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); }
.adm-page .adm-grid2f { display: grid; grid-template-columns: 1fr 1fr; gap: calc(10px * var(--sp-scale, 1)); }
.adm-page .adm-flex8 { display: flex; gap: var(--space-2); }
.adm-page .adm-flex1, .adm-page .adm-flex8 .adm-flex1 { flex: 1; }
.adm-page .adm-w100, .adm-modal .adm-w100 { width: 100% !important; }
.adm-page .adm-w70 { width: 70px !important; }
.adm-page .adm-w80, .adm-modal .adm-w80 { width: 80px !important; }
.adm-page .adm-w110, .adm-modal .adm-w110 { width: 110px !important; }
.adm-page .adm-maxw640 { max-width: 640px; }
.adm-page .adm-maxw720 { max-width: 720px; }
.adm-page .adm-mt14, .adm-modal .adm-mt14 { margin-top: 14px; }
.adm-page .adm-mt16 { margin-top: 16px; }
.adm-page .adm-mt12, .adm-modal .adm-mt12 { margin-top: 12px; }
.adm-page .adm-mt10, .adm-modal .adm-mt10 { margin-top: 10px; }
.adm-page .adm-mt8, .adm-modal .adm-mt8 { margin-top: 8px; }
.adm-page .adm-mt6, .adm-modal .adm-mt6 { margin-top: 6px; }
.adm-page .adm-mb0, .adm-modal .adm-mb0 { margin-bottom: 0 !important; }
.adm-page .adm-mb6, .adm-modal .adm-mb6 { margin-bottom: 6px; }
.adm-page .adm-mb8 { margin-bottom: 8px; }
.adm-page .adm-mb10, .adm-modal .adm-mb10 { margin-bottom: 10px; }
.adm-page .adm-mb12, .adm-modal .adm-mb12 { margin-bottom: 12px; }
.adm-page .adm-mb14 { margin-bottom: 14px; }
.adm-modal .adm-ml10 { margin-left: 10px; }
.adm-page .adm-ml8, .adm-modal .adm-ml8 { margin-left: 8px; }
.adm-page .adm-pad14, .adm-modal .adm-pad14 { padding: calc(14px * var(--sp-scale, 1)); }
.adm-page .adm-dim, .adm-modal .adm-dim { color: var(--text3); }
.adm-page .adm-wrap, .adm-modal .adm-wrap { flex-wrap: wrap; }
.adm-page .adm-ta-cc { width: 100%; text-align: left; min-height: 52px; font-family: inherit; }
.adm-page .adm-ta-md { min-height: 52px; }
.adm-page .adm-alias-btn { padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); font-size: var(--fs-sm); }
.adm-page .mono, .adm-modal .mono { font-variant-numeric: tabular-nums; }

/* ── VFX Planner híbrido (pestañas Calculadora/OT sobre Calendar Crew) ── */
/* Pestañas reales del DS (asesoría UX 2026-07-14): el markup usa .tabs/.tab-btn
   (línea de acento bajo la activa); aquí solo el riel inferior y el margen. */
#page-calendar-crew .vpc-tabs { margin-bottom: 18px; border-bottom: 1px solid var(--border); }
#page-calendar-crew .vpc-row { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
#page-calendar-crew .vpc-badge { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-sm); font-weight: 500; border-radius: var(--radius-pill); padding: calc(2px * var(--sp-scale, 1)) calc(9px * var(--sp-scale, 1)); background: var(--wash-3); color: var(--text2); }
#page-calendar-crew .vpc-badge.ok { background: rgba(var(--green-rgb), 0.12); color: var(--green); }
#page-calendar-crew .vpc-badge.warn { background: rgba(var(--yellow-rgb), 0.12); color: var(--yellow); }
#page-calendar-crew .vpc-badge.red { background: rgba(var(--red-rgb), 0.12); color: var(--red); }
#page-calendar-crew .vpc-badge.blue { background: rgba(var(--accent-rgb), 0.12); color: var(--accent); }
#page-calendar-crew .vpc-badge.yellow { background: rgba(var(--yellow-rgb), 0.12); color: var(--yellow); }
#page-calendar-crew .vpc-badge.clk { cursor: pointer; }
#page-calendar-crew .vpc-badge.clk:hover { filter: brightness(1.25); }
#page-calendar-crew .vpc-params { display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--space-3); }
#page-calendar-crew .vpc-param label { display: block; font-size: var(--fs-xs); font-weight: 600; color: var(--text2); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 4px; }
#page-calendar-crew .vpc-param .cell { width: 100%; }
#page-calendar-crew .vpc-param .hint { font-size: var(--fs-xs); color: var(--text3); margin-top: 3px; text-transform: none; letter-spacing: 0; font-weight: 400; }
#page-calendar-crew .vpc-thg { text-align: center; font-size: var(--fs-2xs); letter-spacing: 0.1em; color: var(--text2); border-bottom: none; padding-bottom: calc(3px * var(--sp-scale, 1)); }
#page-calendar-crew .ft th.vpc-bsep, #page-calendar-crew .ft td.vpc-bsep { border-left: 1px solid var(--border2); }
#page-calendar-crew .vpc-grp td { background: var(--wash-1); font-weight: 700; font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text3); }
#page-calendar-crew .vpc-total td { border-top: 2px solid var(--border2); font-weight: 700; }
/* Barras Window/Occupancy como cápsulas (asesoría UX 2026-07-14): 8px de
   grosor, radio pill y degradado sutil al color activo — antes 5-6px planas. */
#page-calendar-crew .vpc-winbar { position: relative; width: 84px; height: 8px; border-radius: var(--radius-pill); background: var(--wash-3); display: inline-block; vertical-align: middle; margin-right: 6px; overflow: hidden; }
#page-calendar-crew .vpc-winbar i { position: absolute; top: 0; bottom: 0; border-radius: var(--radius-pill); background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.95), rgba(var(--accent-rgb), 0.6)); }
#page-calendar-crew .vpc-occ { position: relative; width: 64px; height: 8px; border-radius: var(--radius-pill); background: var(--wash-3); display: inline-block; vertical-align: middle; margin-right: 6px; overflow: hidden; }
#page-calendar-crew .vpc-occ i { display: block; height: 100%; border-radius: var(--radius-pill); background: linear-gradient(180deg, var(--green), rgba(var(--green-rgb), 0.65)); }
#page-calendar-crew .vpc-occ.warn i { background: linear-gradient(180deg, var(--yellow), rgba(var(--yellow-rgb), 0.65)); }
#page-calendar-crew .vpc-occ.hot i { background: linear-gradient(180deg, var(--red), rgba(var(--red-rgb), 0.65)); }
#page-calendar-crew .vpc-neg { color: var(--red); font-weight: 700; }
#page-calendar-crew .vpc-ok { color: var(--green); font-weight: 700; }
#page-calendar-crew .vpc-staff { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
#page-calendar-crew .vpc-staff ul { margin: 8px 0 0; padding-left: calc(18px * var(--sp-scale, 1)); font-size: var(--fs-base); color: var(--text2); }
#page-calendar-crew .vpc-staff li { margin-bottom: 4px; }
#page-calendar-crew .vpc-staff li b { color: var(--text); }
#page-calendar-crew .vpc-curve { display: flex; gap: var(--space-1); align-items: flex-end; overflow-x: auto; padding: var(--space-1) 0; }
#page-calendar-crew .vpc-wk { flex: 1; min-width: 60px; text-align: center; }
#page-calendar-crew .vpc-bar { position: relative; height: 110px; display: flex; align-items: flex-end; justify-content: center; gap: calc(2px * var(--sp-scale, 1)); }
#page-calendar-crew .vpc-fill { width: 56%; border-radius: 5px 5px 0 0; background: var(--accent); opacity: 0.85; min-height: 2px; display: block; }
#page-calendar-crew .vpc-fill-real { width: 26%; border-radius: 5px 5px 0 0; background: var(--green); opacity: 0.9; min-height: 2px; display: block; }
#page-calendar-crew .vpc-wk.ramp .vpc-fill { background: var(--wash-4); }
#page-calendar-crew .vpc-wk.buffer .vpc-fill { background: rgba(var(--red-rgb), 0.45); }
#page-calendar-crew .vpc-capline { position: absolute; left: 6%; right: 6%; border-top: 2px dashed rgba(var(--green-rgb), 0.7); }
#page-calendar-crew .vpc-curve-in { width: 52px; text-align: center; margin-top: 5px; -moz-appearance: textfield; appearance: textfield; }
#page-calendar-crew .vpc-curve-in::-webkit-inner-spin-button, #page-calendar-crew .vpc-curve-in::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
#page-calendar-crew .vpc-wk .lbl { font-size: var(--fs-xs); color: var(--text3); margin-top: 4px; line-height: 1.3; }
#page-calendar-crew .vpc-wk .tag { font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; }
#page-calendar-crew .vpc-wk.ramp .tag { color: var(--text3); }
#page-calendar-crew .vpc-wk.finals .tag { color: var(--accent); }
#page-calendar-crew .vpc-wk.buffer .tag { color: var(--red); }
#page-calendar-crew .vpc-files { margin-bottom: 12px; }
/* KPIs de Calculadora / Required OT: tarjetas del DS (.stats-grid + .stat-card).
   Antes usaban clases .kpi/.kpi-row sin CSS → texto plano (fix 2026-07-12). */
#page-calendar-crew .stats-grid.vpc-grid5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
#page-calendar-crew .stats-grid.vpc-grid4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1500px) { #page-calendar-crew .stats-grid.vpc-grid5 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1100px) {
  #page-calendar-crew .stats-grid.vpc-grid5,
  #page-calendar-crew .stats-grid.vpc-grid4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Acento por tarjeta (franja + tile + glifo, vía --c del DS) */
#page-calendar-crew .stat-card[data-accent="vpc-k-md"]     { --c: var(--accent); --c-rgb: var(--accent-rgb); }
#page-calendar-crew .stat-card[data-accent="vpc-k-ovh"]    { --c: var(--purple); --c-rgb: var(--purple-rgb); }
#page-calendar-crew .stat-card[data-accent="vpc-k-cap"]    { --c: var(--cyan);   --c-rgb: var(--cyan-rgb); }
#page-calendar-crew .stat-card[data-accent="vpc-k-crew"]   { --c: var(--green);  --c-rgb: var(--green-rgb); }
#page-calendar-crew .stat-card[data-accent="vpc-k-fin"]    { --c: var(--orange); --c-rgb: var(--orange-rgb); }
#page-calendar-crew .stat-card[data-accent="vpc-k-ok"]     { --c: var(--green);  --c-rgb: var(--green-rgb); }
#page-calendar-crew .stat-card[data-accent="vpc-k-bad"]    { --c: var(--red);    --c-rgb: var(--red-rgb); }
#page-calendar-crew .stat-card[data-accent="vpc-k-def"]    { --c: var(--red);    --c-rgb: var(--red-rgb); }
#page-calendar-crew .stat-card[data-accent="vpc-k-ot"]     { --c: var(--orange); --c-rgb: var(--orange-rgb); }
#page-calendar-crew .stat-card[data-accent="vpc-k-nocrew"] { --c: var(--purple); --c-rgb: var(--purple-rgb); }
/* Estas KPI no son clickeables: sin hover "lift" (misma regla que Administration) */
#page-calendar-crew .stat-card:not(.clickable):hover { transform: none; box-shadow: var(--shadow-card); border-color: var(--border); }
/* Veredicto OT: texto, no cifra → no usa el tamaño --fs-kpi */
#page-calendar-crew .stat-card .value.vpc-val-sm { font-size: var(--fs-xl); white-space: normal; }

/* ── F0 (SPEC 2026-07-17): fila de KPIs permanentes + panel de salud ──
   Todo scoped con id (#page-calendar-crew / #vpph) por la regla del reset
   legacy: cualquier clase global usada en esta página necesita espejo. */
#page-calendar-crew .vpph-top { display: flex; align-items: flex-start; gap: calc(10px * var(--sp-scale, 1)); margin-bottom: calc(10px * var(--sp-scale, 1)); }
#page-calendar-crew .vpph-top .stats-grid { flex: 1; }
#page-calendar-crew .stats-grid.vpc-grid3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1100px) { #page-calendar-crew .stats-grid.vpc-grid3 { grid-template-columns: repeat(1, minmax(0, 1fr)); } }
#page-calendar-crew .vpph-btn { white-space: nowrap; display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); }
#page-calendar-crew .vpph-btn.warn { color: var(--orange); border-color: rgba(var(--orange-rgb), 0.55); }
#page-calendar-crew .vpph-btn.red { color: var(--red); border-color: rgba(var(--red-rgb), 0.55); }
#vpph .vpph-item { display: flex; align-items: flex-start; gap: calc(10px * var(--sp-scale, 1)); padding: calc(10px * var(--sp-scale, 1)) 0; border-bottom: 1px solid var(--border); }
#vpph .vpph-ico { display: flex; flex-shrink: 0; color: var(--orange); padding-top: calc(2px * var(--sp-scale, 1)); }
#vpph .vpph-item.red .vpph-ico { color: var(--red); }
#vpph .vpph-item.info .vpph-ico { color: var(--text3); }
#vpph .vpph-msg { flex: 1; min-width: 0; font-size: var(--fs-base); line-height: 1.45; color: var(--text2); }
#vpph .vpph-actions { display: flex; flex-shrink: 0; flex-wrap: wrap; gap: calc(6px * var(--sp-scale, 1)); }
#vpph .vpph-item.acked { opacity: 0.55; }
#vpph .vpph-sec { font-size: var(--fs-sm); color: var(--text3); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; margin: calc(14px * var(--sp-scale, 1)) 0 var(--space-1); }
#vpph .vpph-empty { color: var(--text2); text-align: center; padding: var(--space-6) 0; }

/* ── Compensación del reset legacy (2026-07-14) ──
   El bloque portado del mockup declara `#page-calendar-crew * {margin:0;padding:0}`
   (especificidad 1-0-0), que APLASTA las métricas de caja de cualquier clase
   GLOBAL del DS usada dentro de esta página (0-1-0): .tab-btn quedaba sin
   padding (pestañas encimadas), .stat-card sin padding interno (texto pegado
   a los bordes) y .aso-head/.aso-body sin padding en el slide-over. Se
   re-declaran aquí las métricas con el id delante. Regla: TODO componente
   global del DS que se use en esta página necesita su espejo aquí. */
#page-calendar-crew .tabs { display: flex; gap: 0; }
#page-calendar-crew .tab-btn {
  padding: calc(9px * var(--sp-scale, 1)) calc(15px * var(--sp-scale, 1));
  font-size: var(--fs-md); font-weight: 500; font-family: inherit;
  background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--text2); cursor: pointer; transition: all var(--dur-micro);
}
#page-calendar-crew .tab-btn:hover { color: var(--text); }
#page-calendar-crew .tab-btn.active { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }
#page-calendar-crew .stats-grid { margin-bottom: 18px; }
#page-calendar-crew .stat-card { padding: calc(15px * var(--sp-scale, 1)); }
#page-calendar-crew .stat-card .label { margin-top: 3px; }
#page-calendar-crew .stat-breakdown { margin-top: 3px; }
#page-calendar-crew .aso-head { padding: var(--space-4) calc(18px * var(--sp-scale, 1)); }
#page-calendar-crew .aso-body { padding: var(--space-4) calc(18px * var(--sp-scale, 1)); }

/* ── Asesoría UX 2026-07-14 (Calculadora / Required OT) ──
   KPI: "borde de luz" — border2 (blanco 14% en oscuro, vía token: el tema claro
   lo pisa solo) para despegar las tarjetas del fondo + cifra con peso 800. */
#vpc-calc .stat-card, #vpc-ot .stat-card { border-color: var(--border2); }
#vpc-calc .stat-card:not(.clickable):hover, #vpc-ot .stat-card:not(.clickable):hover { border-color: var(--border2); }
#vpc-calc .stat-card .value, #vpc-ot .stat-card .value { font-weight: 800; }
/* Respiración de tablas: padding vertical de celda 5px → 8px (escala --space),
   SOLO en Calculadora/OT — las tablas de Calendar Crew se conservan tal cual. */
#vpc-calc .ft td, #vpc-ot .ft td, #vpp-so .ft td { padding: var(--space-2) calc(10px * var(--sp-scale, 1)); }
/* Banner de alerta (antes texto rojo clickeable = antipatrón): contenedor con
   fondo del color al 8%, ícono a la izquierda y botón de acción a la derecha. */
#page-calendar-crew .vpc-alert { display: flex; align-items: center; gap: var(--space-3); width: 100%; background: rgba(var(--red-rgb), 0.08); border: 1px solid rgba(var(--red-rgb), 0.25); border-radius: var(--radius-sm); padding: calc(10px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); font-size: var(--fs-base); color: var(--text2); }
#page-calendar-crew .vpc-alert .vpc-alert-ico { display: flex; flex-shrink: 0; color: var(--red); }
#page-calendar-crew .vpc-alert .vpc-alert-msg { flex: 1; min-width: 0; }
#page-calendar-crew .vpc-alert .vpc-alert-msg b { color: var(--red); }
#page-calendar-crew .vpc-alert .btn { flex-shrink: 0; }
#page-calendar-crew .vpc-alert.warn { background: rgba(var(--yellow-rgb), 0.08); border-color: rgba(var(--yellow-rgb), 0.3); }
#page-calendar-crew .vpc-alert.warn .vpc-alert-ico, #page-calendar-crew .vpc-alert.warn .vpc-alert-msg b { color: var(--yellow); }
/* Parámetros del plan: affordance de edición (feedback 2026-07-14 — en el
   mockup v3 era obvio que se podían editar; en vivo parecían texto plano
   porque input.cell nace con borde transparente). Caja visible tipo input. */
#page-calendar-crew .vpc-param .cell { background: var(--wash-1); border: 1px solid var(--border); }
#page-calendar-crew .vpc-param .cell:hover { border-color: var(--border2); }
#page-calendar-crew .vpc-param .cell:focus { border-color: var(--accent); }
/* Slide-over de cobertura de booking (reusa .aso-panel) */
#page-calendar-crew .vpp-so-dept { margin-bottom: var(--space-4); }
#page-calendar-crew .vpp-so-dept-head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: 4px; }
#page-calendar-crew .vpp-so-meta { font-size: var(--fs-sm); color: var(--text3); margin-bottom: 6px; }
#page-calendar-crew .vpp-so-empty { color: var(--text2); font-size: var(--fs-base); padding: calc(6px * var(--sp-scale, 1)) 0; }
#page-calendar-crew .vpp-so-cta { width: 100%; margin-top: var(--space-3); }

/* ── Auditoría UX Administration (2026-07-11) ── */
/* badge-cyan no existía en el DS (lo usa el badge Episodic) */
.badge-cyan { background: rgba(var(--cyan-rgb), 0.12); color: var(--cyan); }
/* las KPI de Administration no son clickeables: sin hover "lift" (affordance falsa) */
.adm-page .stat-card:not(.clickable):hover { transform: none; box-shadow: var(--shadow-card); border-color: var(--border); }
/* estados vacíos de tablas: padding tokenizado único (antes inline styles) */
.adm-page .data-table td.note { padding: var(--space-4) var(--space-3); }
/* acción destructiva diferenciada (Delete bid / Delete lines) */
.adm-page .btn.adm-danger { color: var(--red); border-color: rgba(var(--red-rgb), 0.35); }
.adm-page .btn.adm-danger:hover { background: rgba(var(--red-rgb), 0.12); }
/* encabezado dentro de la tarjeta-tabla del dashboard */
.adm-page .adm-tablecard .adm-rowhead-pad { padding: var(--space-2) var(--space-2) 0; margin-bottom: var(--space-2); }
/* FTP Sync v2: marcas de diff entre syncs (campo actualizado / shot nuevo) */
.adm-page td.adm-ftp-chg { background: rgba(var(--yellow-rgb), 0.10); box-shadow: inset 2px 0 0 var(--yellow); }
.adm-page tr.adm-ftp-new td { background: rgba(var(--green-rgb), 0.06); }
/* fila seleccionada para edición masiva (misma señal visual que el VFX Planner) */
.adm-page tr.adm-row-sel td { background: var(--accent-soft); }

/* ══════════════════════════════════════════════════════════
   STUDIO RESOURCES (page-adm-resources · Mockup_Resources.html v4 · 2026-07-12)
   Scoped a #page-adm-resources; .rsc-tgl se comparte con las columnas Lic/Mach
   del booking del VFX Planner (#page-calendar-crew). 100% tokenizado.
   ══════════════════════════════════════════════════════════ */
#page-adm-resources .stats-grid.rsc-grid5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 1500px) { #page-adm-resources .stats-grid.rsc-grid5 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1100px) { #page-adm-resources .stats-grid.rsc-grid5 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
#page-adm-resources .rsc-sec { margin-top: var(--space-5); }
#page-adm-resources .rsc-note { margin-top: calc(6px * var(--sp-scale, 1)); }
#page-adm-resources .rsc-mt10, #page-calendar-crew .rsc-mt10 { margin-top: calc(10px * var(--sp-scale, 1)); }
#page-adm-resources th .rsc-th-plain { text-transform: none; letter-spacing: 0; font-weight: 500; }
#page-adm-resources td.rsc-miss { color: var(--red); font-weight: 700; }
#page-adm-resources .rsc-warn-txt { color: var(--yellow); }
#page-adm-resources .data-table td.empty { padding: var(--space-5); text-align: center; color: var(--text3); }
/* V2 del mockup: hover de fila = guía de lectura + revela el ✕ */
#page-adm-resources .data-table tbody tr:hover td { background: var(--wash-1); }
#page-adm-resources .data-table td .btn-ghost { opacity: 0; transition: opacity var(--dur-micro, 0.1s); }
#page-adm-resources .data-table tr:hover td .btn-ghost, #page-adm-resources .data-table td .btn-ghost:focus-visible { opacity: 1; }
#page-adm-resources .data-table td .btn-ghost:hover { color: var(--red); border-color: rgba(var(--red-rgb), 0.4); background: rgba(var(--red-rgb), 0.08); }
/* tamaños de input del mockup (base .inp del área adm) */
#page-adm-resources .inp.tiny { width: 46px; padding: calc(2px * var(--sp-scale, 1)) calc(5px * var(--sp-scale, 1)); font-size: var(--fs-sm); }
#page-adm-resources .inp.txt { text-align: left; width: 130px; }
#page-adm-resources .inp.txt.wide { width: 190px; }
#page-adm-resources .inp.rsc-name { font-weight: 600; width: 96%; }
#page-adm-resources .inp.rsc-vendor { width: 96%; }
#page-adm-resources input.inp[type=number] { -moz-appearance: textfield; appearance: textfield; }
#page-adm-resources input.inp[type=number]::-webkit-inner-spin-button, #page-adm-resources input.inp[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
/* V1: inputs "fantasma" dentro de tablas — dato en reposo, marco al hover, accent al focus.
   OJO (fix CuePin ronda 3 nota 1): usar background-COLOR, nunca el shorthand, para no
   resetear el no-repeat/position del chevron de los selects (se azulejaba en zigzag). */
#page-adm-resources .data-table .inp { background-color: transparent; background-image: none; border-color: transparent; transition: background-color var(--dur-micro, 0.1s), border-color var(--dur-micro, 0.1s); }
#page-adm-resources .data-table tr:hover .inp { background-color: var(--wash-1); border-color: var(--border); }
#page-adm-resources .data-table .inp:hover { border-color: var(--border2); }
#page-adm-resources .data-table .inp:focus { background-color: var(--wash-2); border-color: var(--accent); }
#page-adm-resources .data-table tr:hover select.inp { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23909096' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 8px center; }
/* V3: campo de dinero — símbolo prefijo dentro del marco, cifras a la derecha */
#page-adm-resources .rsc-money { display: inline-flex; align-items: center; gap: calc(2px * var(--sp-scale, 1)); border: 1px solid transparent; border-radius: var(--radius-xs); padding: 0 var(--space-2) 0 calc(7px * var(--sp-scale, 1)); width: 104px; transition: background-color var(--dur-micro, 0.1s), border-color var(--dur-micro, 0.1s); }
#page-adm-resources .rsc-money .cur { font-weight: 500; color: var(--text3); font-size: var(--fs-sm); }
#page-adm-resources .rsc-money input { border: none; background: none; padding: var(--space-1) 0; width: 100%; text-align: right; color: var(--text); font-size: calc(12.5px * var(--fs-scale, 1)); font-variant-numeric: tabular-nums; outline: none; font-family: inherit; }
#page-adm-resources tr:hover .rsc-money { background-color: var(--wash-1); border-color: var(--border); }
#page-adm-resources .rsc-money:focus-within { background-color: var(--wash-2); border-color: var(--accent); }
/* Toggle ✓/— (compartido con las columnas Lic/Mach del booking del planner) */
#page-adm-resources .rsc-tgl, #page-calendar-crew .rsc-tgl { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 20px; border-radius: var(--radius-xs); cursor: pointer; font-weight: 700; font-size: var(--fs-base); background: var(--wash-2); color: var(--text3); transition: 0.1s; }
#page-adm-resources .rsc-tgl:hover, #page-calendar-crew .rsc-tgl:hover { background: var(--wash-4); box-shadow: inset 0 0 0 1px var(--border2); }
#page-adm-resources .rsc-tgl.on, #page-calendar-crew .rsc-tgl.on { background: rgba(var(--green-rgb), 0.14); color: var(--green); }
#page-adm-resources .rsc-tgl.ro { cursor: default; }
#page-adm-resources .rsc-tgl.ro:hover { background: var(--wash-2); box-shadow: none; }
#page-adm-resources .rsc-tgl.ro.on:hover { background: rgba(var(--green-rgb), 0.14); }
/* V6: celdas clickeables (Assigned / Expiry) con affordance permanente tenue */
#page-adm-resources .rsc-asg { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); flex-wrap: wrap; cursor: pointer; border: 1px dashed var(--border); border-radius: var(--radius-xs); padding: calc(2px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1)); min-width: 60px; transition: 0.1s; }
#page-adm-resources .rsc-asg:hover { border-color: var(--border2); background: var(--wash-1); }
#page-adm-resources .rsc-asg .cnt { font-size: calc(10.5px * var(--fs-scale, 1)); color: var(--text3); font-variant-numeric: tabular-nums; }
#page-adm-resources .rsc-asg .cnt.over { color: var(--red); font-weight: 700; }
#page-adm-resources .rsc-asg .ico { opacity: 0.5; display: inline-flex; }
#page-adm-resources .rsc-asg.rsc-dp-trigger { white-space: nowrap; flex-wrap: nowrap; }
#page-adm-resources .rsc-asg-chip { background: var(--wash-2); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: calc(1px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); font-size: var(--fs-sm); white-space: nowrap; }
/* Popover compartido (picker · receta · datepicker) — V5: click-fuera y Escape cierran */
#page-adm-resources .rsc-pop, #page-adm-projcost .rsc-pop { position: fixed; z-index: var(--z-popover); background: var(--card2); border: 1px solid var(--border2); border-radius: var(--radius-sm); box-shadow: var(--shadow-modal); padding: calc(10px * var(--sp-scale, 1)); width: 250px; max-height: 340px; overflow: auto; }
#page-adm-resources .rsc-pop h5, #page-adm-projcost .rsc-pop h5 { margin: 0 0 8px; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text3); display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); }
#page-adm-resources .rsc-pop h5 .x, #page-adm-projcost .rsc-pop h5 .x { margin-left: auto; cursor: pointer; color: var(--text3); font-size: var(--fs-md); }
#page-adm-resources .rsc-pop h5 .x:hover, #page-adm-projcost .rsc-pop h5 .x:hover { color: var(--text); }
#page-adm-resources .rsc-pop .row, #page-adm-projcost .rsc-pop .row { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-1); border-radius: var(--radius-xs); cursor: pointer; font-size: calc(12.5px * var(--fs-scale, 1)); }
#page-adm-resources .rsc-pop .row:hover, #page-adm-projcost .rsc-pop .row:hover { background: var(--wash-2); }
#page-adm-resources .rsc-pop .row small, #page-adm-projcost .rsc-pop .row small { margin-left: auto; color: var(--text3); font-size: calc(10.5px * var(--fs-scale, 1)); }
#page-adm-resources .rsc-pop .grp, #page-adm-projcost .rsc-pop .grp { font-size: calc(9.5px * var(--fs-scale, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text3); margin: 8px 2px 3px; }
#page-adm-resources .rsc-pop .manual, #page-adm-projcost .rsc-pop .manual { display: flex; gap: calc(6px * var(--sp-scale, 1)); margin-top: 8px; border-top: 1px solid var(--border); padding-top: var(--space-2); }
#page-adm-resources .rsc-pop .manual input, #page-adm-projcost .rsc-pop .manual input { flex: 1; width: auto; text-align: left; }
#page-adm-resources .rsc-pop .search, #page-adm-projcost .rsc-pop .search { width: 100%; text-align: left; margin-bottom: 6px; background-color: var(--wash-2); border-color: var(--border2); }
#page-adm-resources .rsc-pop-addrow, #page-adm-projcost .rsc-pop-addrow { display: flex; gap: calc(6px * var(--sp-scale, 1)); align-items: center; margin-top: 4px; }
#page-adm-resources .rsc-pop-addrow select, #page-adm-projcost .rsc-pop-addrow select { flex: 1; }
#page-adm-resources .rsc-pop-foot, #page-adm-projcost .rsc-pop-foot { margin-top: 8px; text-align: right; }
#page-adm-resources .rsc-pop-note, #page-adm-projcost .rsc-pop-note { margin-top: 6px; }
/* V4/nota 3: datepicker propio (el #vp-dp del planner vive dentro de
   #page-calendar-crew y no es desacoplable — ver comentario en resources.js) */
#page-adm-resources .rsc-dp-hdr, #page-adm-projcost .rsc-dp-hdr { display: flex; align-items: center; gap: var(--space-1); margin-bottom: 8px; }
#page-adm-resources .rsc-dp-hdr .nav, #page-adm-projcost .rsc-dp-hdr .nav { width: 24px; height: 24px; border-radius: 8px; border: 1px solid var(--wash-3); background: var(--wash-2); color: var(--text2); cursor: pointer; font-size: var(--fs-md); line-height: 1; transition: background var(--dur-micro), color var(--dur-micro), transform var(--dur-micro); }
#page-adm-resources .rsc-dp-hdr .nav:hover, #page-adm-projcost .rsc-dp-hdr .nav:hover { background: var(--wash-4); color: var(--text); transform: scale(1.08); }
#page-adm-resources .rsc-dp-hdr select, #page-adm-projcost .rsc-dp-hdr select { flex: 1; background-color: var(--wash-2); border-color: var(--border2); }
#page-adm-resources .rsc-dp-grid, #page-adm-projcost .rsc-dp-grid { display: grid; grid-template-columns: repeat(7, 28px); gap: calc(2px * var(--sp-scale, 1)); justify-content: center; }
#page-adm-resources .rsc-dp-grid b, #page-adm-projcost .rsc-dp-grid b { font-size: calc(9.5px * var(--fs-scale, 1)); color: var(--text3); text-align: center; font-weight: 600; }
/* (2026-07-29) Celdas unificadas con el picker canónico OTDP: círculo, hoy con punto, selección accent. */
#page-adm-resources .rsc-dp-d, #page-adm-projcost .rsc-dp-d { height: 28px; border-radius: 50%; position: relative; display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--text2); font-size: calc(12.5px * var(--fs-scale, 1)); font-variant-numeric: tabular-nums; transition: background var(--dur-micro), color var(--dur-micro), transform var(--dur-micro); }
#page-adm-resources .rsc-dp-d:hover, #page-adm-projcost .rsc-dp-d:hover { background: var(--wash-3); color: var(--text); transform: scale(1.08); }
#page-adm-resources .rsc-dp-d.sel, #page-adm-projcost .rsc-dp-d.sel { background: var(--accent); color: #fff; font-weight: 600; box-shadow: 0 2px 8px rgba(var(--accent-rgb),.5), 0 0 0 1px rgba(var(--accent-rgb),.3); }
#page-adm-resources .rsc-dp-d.today, #page-adm-projcost .rsc-dp-d.today { color: var(--accent); font-weight: 700; }
#page-adm-resources .rsc-dp-d.today::after, #page-adm-projcost .rsc-dp-d.today::after { content: ''; position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%); width: 3.5px; height: 3.5px; border-radius: 50%; background: var(--accent); }
#page-adm-resources .rsc-dp-d.sel.today::after, #page-adm-projcost .rsc-dp-d.sel.today::after { background: #fff; }
#page-adm-resources .rsc-dp-d.out, #page-adm-projcost .rsc-dp-d.out { color: var(--text3); opacity: 0.35; }
#page-adm-resources .rsc-dp-foot, #page-adm-projcost .rsc-dp-foot { display: flex; justify-content: space-between; margin-top: 8px; border-top: 1px solid var(--border); padding-top: var(--space-2); }
/* coverage heat strip — V10: bloques de 4 semanas */
#page-adm-resources .rsc-heat { display: flex; gap: calc(1.5px * var(--sp-scale, 1)); align-items: flex-end; }
#page-adm-resources .rsc-heat i { display: block; width: 9px; height: 16px; border-radius: 2px; background: var(--wash-2); }
#page-adm-resources .rsc-heat i:nth-child(4n) { margin-right: 4px; }
#page-adm-resources .rsc-heat i.ok { background: rgba(var(--green-rgb), 0.35); }
#page-adm-resources .rsc-heat i.warn { background: rgba(var(--yellow-rgb), 0.5); }
#page-adm-resources .rsc-heat i.bad { background: rgba(var(--red-rgb), 0.6); }
#page-adm-resources .rsc-heat i.zero { background: var(--wash-1); }
/* V8: columna de reconciliación FPT */
#page-adm-resources th.rsc-vsinv, #page-adm-resources td.rsc-vsinv { text-align: left; }
#page-adm-resources td.rsc-vsinv { max-width: 210px; }
#page-adm-resources td.rsc-vsinv .note { font-size: calc(10.5px * var(--fs-scale, 1)); line-height: 1.35; margin-top: 2px; color: var(--yellow); opacity: 0.85; }
#page-adm-resources .rsc-fpt-empty { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
#page-adm-resources .rsc-fpt-summary { margin-top: 8px; display: flex; gap: calc(6px * var(--sp-scale, 1)); flex-wrap: wrap; }
/* Seat recipes */
#page-adm-resources .rsc-recipe-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); }
@media (max-width: 1100px) { #page-adm-resources .rsc-recipe-grid { grid-template-columns: repeat(2, 1fr); } }
#page-adm-resources .rsc-recipe-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: calc(13px * var(--sp-scale, 1)); }
#page-adm-resources .rsc-recipe-card h4 { margin: 0 0 8px; font-size: calc(12.5px * var(--fs-scale, 1)); letter-spacing: -0.2px; }
#page-adm-resources .rsc-recipe-card h4 small { color: var(--text3); font-weight: 500; }
#page-adm-resources .rsc-chips { display: flex; flex-wrap: wrap; gap: calc(5px * var(--sp-scale, 1)); }
#page-adm-resources .rsc-chip { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); background: var(--wash-2); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: calc(2px * var(--sp-scale, 1)) var(--space-2); font-size: var(--fs-sm); }
#page-adm-resources .rsc-chip b { font-variant-numeric: tabular-nums; }
#page-adm-resources .rsc-chip .x { cursor: pointer; color: var(--text3); font-weight: 700; }
#page-adm-resources .rsc-chip .x:hover { color: var(--red); }
#page-adm-resources .rsc-chip.addon { border-style: dashed; color: var(--text2); }
#page-adm-resources .rsc-chip.add { cursor: pointer; color: var(--accent); }
#page-adm-resources .rsc-chip.add:hover { background: var(--accent-soft); }
/* Strip de detalle del resource-check en el planner (Calculadora).
   Asesoría UX 2026-07-14: banner con ícono + botón de acción (antes toda la
   franja era clickeable con "click to open" en el texto — antipatrón). */
#page-calendar-crew .rsc-strip { display: flex; align-items: center; gap: var(--space-3); background: rgba(var(--red-rgb), 0.08); border: 1px solid rgba(var(--red-rgb), 0.3); color: var(--text2); border-radius: var(--radius-sm); padding: calc(10px * var(--sp-scale, 1)) calc(14px * var(--sp-scale, 1)); font-size: var(--fs-base); margin-top: calc(10px * var(--sp-scale, 1)); }
#page-calendar-crew .rsc-strip b { color: var(--red); }
#page-calendar-crew .rsc-strip .rsc-strip-ico { display: flex; flex-shrink: 0; color: var(--red); }
#page-calendar-crew .rsc-strip .rsc-strip-msg { flex: 1; min-width: 0; }
#page-calendar-crew .rsc-strip .btn { flex-shrink: 0; }

/* ══ SALUD FINANCIERA (adm-projcost, F1) — preview del % de dedicación ══ */
#page-adm-projcost .fin-controls { display: flex; gap: var(--space-4); align-items: flex-end; flex-wrap: wrap; }
#page-adm-projcost .fin-controls .fld { margin: 0; }
#page-adm-projcost .rsc-sec { margin-top: var(--space-5); }
/* Celda de % editable: alineada a las métricas de .btn-sm (regla global: no hardcodear alturas) */
#page-adm-projcost .fin-pct { width: 76px; text-align: center; }
#page-adm-projcost .fin-pct.fin-ovr { border-style: dashed; border-color: var(--accent); }
#page-adm-projcost .fin-pct.fin-pre { background: rgba(var(--yellow-rgb), 0.10); }
#page-adm-projcost .fin-add { max-width: 240px; }
#page-adm-projcost .fin-table td.empty { padding: var(--space-5); text-align: center; color: var(--text3); }
/* Bandas de departamento (paridad visual con el XLSX del Project Cost) */
#page-adm-projcost .fin-dept td { font-weight: 700; color: var(--text2); background: var(--wash-1); }
#page-adm-projcost .fin-dept-sup td { box-shadow: inset 3px 0 0 var(--orange, #e8833a); }
#page-adm-projcost .fin-dept-2d td  { box-shadow: inset 3px 0 0 var(--accent); }
#page-adm-projcost .fin-dept-3d td  { box-shadow: inset 3px 0 0 var(--purple, #8e7cc3); }

/* Salud Financiera — datepicker trigger, spinner y barra de progreso del job */
#page-adm-projcost .fin-date { max-width: 130px; cursor: pointer; }
#page-adm-projcost .fin-prog { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3); background: var(--card); border: 1px solid var(--border);
  border-left: 3px solid var(--accent); border-radius: var(--radius-xs); font-size: var(--fs-base); color: var(--text2); }
#page-adm-projcost .fin-spin { width: 13px; height: 13px; flex-shrink: 0; border-radius: 50%;
  border: 2px solid var(--border2); border-top-color: var(--accent); animation: spin 1s linear infinite; }
#page-adm-projcost .fin-prog-track { flex: 0 0 160px; height: 4px; margin-left: auto; border-radius: 2px;
  background: var(--wash-2); overflow: hidden; }
#page-adm-projcost .fin-prog-bar { display: block; height: 100%; width: 0; border-radius: 2px;
  background: var(--accent); opacity: .8; transition: width .4s ease; }
#page-adm-projcost .fin-status.fin-err { color: var(--red); }

/* Salud Financiera — chips de shows detectados */
#page-adm-projcost .fin-shows { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
#page-adm-projcost .fin-chip { border: 1px solid var(--border2); background: var(--wash-1); color: var(--text2);
  border-radius: var(--radius-pill); padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1));
  font-size: var(--fs-sm); cursor: pointer; }
#page-adm-projcost .fin-chip small { color: var(--text3); font-size: var(--fs-xs); }
#page-adm-projcost .fin-chip:hover { border-color: var(--accent); }
#page-adm-projcost .fin-chip.on { background: rgba(var(--accent-rgb), 0.12); border-color: var(--accent); color: var(--text); }
#page-adm-projcost .fin-chip.on small { color: var(--accent); }

/* ══ Salud Financiera — matriz alineada, selección múltiple y coherencia ∑ ══ */
/* Alineación entre proyectos: anchos FIJOS via colgroup + table-layout fixed
   (auditoría UX P0-1). La 1ª columna útil (artista) queda sticky (P0-2). */
#page-adm-projcost .fin-table { table-layout: fixed; width: max-content; }
#page-adm-projcost .fin-col-sel  { width: 34px; }
#page-adm-projcost .fin-col-name { width: 220px; }
#page-adm-projcost .fin-col-mo   { width: 96px; }
/* Meses anteriores plegados en UNA columna «+N ⋯» (2026-08-31) */
#page-adm-projcost .fin-col-fold { width: 64px; }
#page-adm-projcost .fin-td-fold  { color: var(--text3); }
/* v3 (N7): pill punteada para que se lea como clickeable, no como texto */
#page-adm-projcost .fin-mo-more  { border: 1px dashed var(--border2); background: var(--wash-1);
  color: var(--text3); border-radius: var(--radius-pill); font-size: var(--fs-xs);
  cursor: pointer; padding: calc(2px * var(--sp-scale, 1)) var(--space-2); white-space: nowrap; }
#page-adm-projcost .fin-mo-more:hover { color: var(--accent); border-color: var(--accent); }

/* Botón «enteros» por mes (2026-08-31): redondea el mes completo. Se revela
   con hover/focus del th; visibility (no display) para no brincar el alto. */
#page-adm-projcost .fin-th-round { display: block; margin: 2px auto 0; visibility: hidden;
  border: 1px dashed var(--border2); background: var(--wash-1); color: var(--text3);
  border-radius: var(--radius-pill); font-size: var(--fs-xs); cursor: pointer;
  padding: 1px var(--space-2); font-weight: 400; text-transform: none; letter-spacing: 0; }
#page-adm-projcost .fin-th-mo:hover .fin-th-round,
#page-adm-projcost .fin-th-round:focus-visible { visibility: visible; }
#page-adm-projcost .fin-th-round:hover { color: var(--accent); border-color: var(--accent); }

/* ── Menú "Publicar ▾" (N5, 2026-08-31 v3): anclado al botón, alineado a la
   derecha para no cortarse contra el borde de la ventana ── */
#page-adm-projcost .fin-pub-wrap { position: relative; }
#page-adm-projcost .fin-pub-menu { position: absolute; right: 0; top: calc(100% + 6px);
  z-index: var(--z-popover); min-width: 300px; background: var(--card2);
  border: 1px solid var(--border2); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-modal); padding: var(--space-1); }
#page-adm-projcost .fin-pub-menu [role="menuitem"] { display: block; width: 100%;
  text-align: left; border: 0; background: none; color: var(--text); cursor: pointer;
  border-radius: var(--radius-sm); padding: var(--space-2) calc(10px * var(--sp-scale, 1)); }
#page-adm-projcost .fin-pub-menu [role="menuitem"]:hover { background: var(--wash-1); }
#page-adm-projcost .fin-pub-menu [role="menuitem"] b { display: block; font-size: var(--fs-sm); font-weight: 600; }
#page-adm-projcost .fin-pub-menu [role="menuitem"] small { display: block; color: var(--text3); font-size: var(--fs-xs); margin-top: 1px; }
#page-adm-projcost .fin-pub-caret { color: var(--text3); font-size: var(--fs-xs); }

/* ── Panel de config plegado a línea resumen (N1, 2026-08-31 v3) ── */
#page-adm-projcost .fin2-panel-sum { grid-column: 1 / -1; display: flex; align-items: center;
  gap: var(--space-3); border: 1px solid var(--border2); background: var(--card);
  border-radius: var(--radius); padding: var(--space-2) calc(14px * var(--sp-scale, 1)); }
#page-adm-projcost .fin2-panel-sum b { font-size: var(--fs-sm); }
#page-adm-projcost .fin2-panel.fin2-panel-min .fin2-group { display: none; }

/* ── Salto alerta→celda (N2): resaltado breve de la celda destino ── */
#page-adm-projcost td.fin-jump-hi { animation: finJumpHi 2s ease-out; }
@keyframes finJumpHi {
  0%, 35% { background: rgba(var(--accent-rgb), 0.28); }
  100% { background: transparent; }
}
#page-adm-projcost .fin-table th { font-variant-numeric: tabular-nums; }
#page-adm-projcost .fin-td-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#page-adm-projcost .fin-table th:nth-child(-n+2),
#page-adm-projcost .fin-table td:nth-child(-n+2) { position: sticky; z-index: 1; background: var(--card); }
#page-adm-projcost .fin-table th:first-child, #page-adm-projcost .fin-table td:first-child { left: 0; }
#page-adm-projcost .fin-table th:nth-child(2), #page-adm-projcost .fin-table td:nth-child(2) { left: 34px; }
#page-adm-projcost .fin-dept td { background: var(--wash-1); }
#page-adm-projcost .fin-row-sel td { background: rgba(var(--accent-rgb), 0.07); }
#page-adm-projcost .fin-td-sel { text-align: center; }
#page-adm-projcost .fin-td-sel input { accent-color: var(--accent); cursor: pointer; }

/* Celda: input + marcas (⚠ pre-snapshot visible, ∑ cuando no cierra en 100) */
#page-adm-projcost .fin-cell { position: relative; }
#page-adm-projcost .fin-wrap { position: relative; display: inline-block; }
#page-adm-projcost .fin-flag { position: absolute; top: -5px; right: -7px; font-size: var(--fs-xs); color: var(--yellow); cursor: pointer; }
/* ⚑ revisada (2026-07-22): sigue visible pero atenuada — la alerta está silenciada */
#page-adm-projcost .fin-flag.fin-flag-ack { opacity: .35; }
#page-adm-projcost .fin-sum { display: block; font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
#page-adm-projcost .fin-sum:empty { display: none; }
#page-adm-projcost .fin-sum.over  { color: var(--red); font-weight: 700; }
#page-adm-projcost .fin-sum.under { color: var(--yellow); font-weight: 600; }

/* Barra de filtros */
#page-adm-projcost .fin-filterbar { margin-bottom: var(--space-3); gap: var(--space-3); }
#page-adm-projcost .fin-q { width: 280px; max-width: 100%; }

/* Barra flotante de selección múltiple (patrón cal-selbar/vp-selbar) */
#page-adm-projcost .fin-selbar { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(18px * var(--sp-scale, 1));
  z-index: var(--z-popover); display: flex; align-items: center; gap: var(--space-2);
  background: var(--card2); border: 1px solid var(--border2); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-modal); padding: var(--space-2) var(--space-3); font-size: var(--fs-base); color: var(--text2); }
#page-adm-projcost .fin-selbar .inp { width: auto; }
#page-adm-projcost .fin-selbar #fin-bulk-val { width: 76px; }
#page-adm-projcost .fin-selbar-sep { width: 1px; align-self: stretch; background: var(--border); margin: 0 var(--space-1); }

/* Botones del encabezado alineados y del mismo tamaño (feedback nota 3) */
#page-adm-projcost .page-header-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: nowrap; white-space: nowrap; }
#page-adm-projcost .fin-controls { justify-content: flex-start; column-gap: var(--space-4); }
#page-adm-projcost .fin-dept td { font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.05em; }

/* ══ SALUD FINANCIERA v2 — UI del Mockup_ProjectCost_UX_2026-07-13 ══
   (aprobado por el usuario; las reglas fin2-* + overrides de fin-* de abajo
   SUSTITUYEN el look anterior — mismo funcionamiento, nueva presentación). */

/* #1 Header: pill de cambios sin guardar + separador; un solo primario */
#page-adm-projcost .fin2-dirty { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1));
  font-size: var(--fs-sm); color: var(--yellow); background: rgba(var(--yellow-rgb), 0.12);
  border: 1px solid rgba(var(--yellow-rgb), 0.28); border-radius: var(--radius-pill);
  padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); font-weight: 600; white-space: nowrap; }
#page-adm-projcost .fin2-hdr-sep { width: 1px; height: 22px; background: var(--border); margin: 0 var(--space-2); }
#page-adm-projcost .kbd { font-size: var(--fs-2xs); opacity: .65; border: 1px solid currentColor;
  border-radius: 3px; padding: 0 calc(3px * var(--sp-scale, 1)); font-weight: 700; }

/* #2 Panel superior en dos grupos delimitados */
#page-adm-projcost .fin2-panel { display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: var(--space-4); margin-bottom: var(--space-5); }
@media (max-width: 1200px) { #page-adm-projcost .fin2-panel { grid-template-columns: 1fr; } }
#page-adm-projcost .fin2-group { border: 1px solid var(--border2); background: var(--card);
  border-radius: var(--radius); padding: var(--space-4); box-shadow: var(--shadow-card); position: relative; }
#page-adm-projcost .fin2-group > .gh { display: flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-3); }
#page-adm-projcost .fin2-group > .gh h3 { margin: 0; font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: var(--tracking-overline); text-transform: uppercase; color: var(--text2); }
#page-adm-projcost .fin2-group > .gh .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
#page-adm-projcost .fin2-group.g-src > .gh .dot { background: var(--purple, #bf5af2); }
#page-adm-projcost .fin2-row { display: flex; align-items: flex-end; gap: var(--space-3); flex-wrap: wrap; }
#page-adm-projcost .fin2-row .fld { margin: 0; }
#page-adm-projcost .fin2-grow { flex: 1; min-width: 170px; }
#page-adm-projcost .fin2-grow .inp { width: 100%; }
#page-adm-projcost .fin2-dash { display: flex; align-items: center; color: var(--text3); padding-bottom: calc(7px * var(--sp-scale, 1)); }
#page-adm-projcost .fin2-sub { margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px solid var(--border); }
/* ── Rediseño Fuente de datos (2026-07-14) — todo refluye sin deformar ──
   Inputs en grilla auto-fit (3→2→1) y acciones de importar como grupo
   segmentado que se apila EN BLOQUE cuando falta ancho. Sin alturas
   hardcodeadas: los botones conservan sus métricas globales .btn-sm. */
#page-adm-projcost .fin2-inputs { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--space-3); align-items: end; }
#page-adm-projcost .fin2-inputs .fld { margin: 0; min-width: 0; }
#page-adm-projcost .fin2-inputs .inp { width: 100%; box-sizing: border-box; }
#page-adm-projcost .fin2-imports { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--border); }
#page-adm-projcost .fin2-imports-lbl { display: block; font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: var(--tracking-overline); text-transform: uppercase; color: var(--text3); margin-bottom: var(--space-2); }
#page-adm-projcost .fin2-imports-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
/* Grupo segmentado: auto-fit → 2 columnas cuando cabe, 1 (apiladas) cuando no.
   El gap de 1px sobre fondo border2 dibuja la divisoria; overflow hidden + radio
   en el contenedor mantiene el look "pegado" en ambas orientaciones. Los botones
   llevan white-space:nowrap → su texto nunca se parte. */
#page-adm-projcost .fin2-btngroup { flex: 1 1 320px; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: calc(1px * var(--sp-scale, 1));
  background: var(--border2); border: 1px solid var(--border2);
  border-radius: var(--radius-sm); overflow: hidden; }
#page-adm-projcost .fin2-btngroup .btn { border: 0; border-radius: 0; width: 100%;
  background: var(--card2); white-space: nowrap; box-shadow: none; }
#page-adm-projcost .fin2-btngroup .btn:hover { background: var(--wash-2); }
#page-adm-projcost .fin2-mem { flex: 0 0 auto; margin-left: auto; white-space: nowrap; }
#page-adm-projcost .meta-line { margin-top: var(--space-3); font-size: var(--fs-sm); color: var(--text3);
  line-height: 1.6; font-variant-numeric: tabular-nums; flex-basis: 100%; }
#page-adm-projcost .meta-line b, #page-adm-projcost .fin-status b { color: var(--text2); font-weight: 600; }

/* ── Estado de los datos (2026-08-31): "¿estoy al día?" de un vistazo ──
   Una fila por fuente (vendor bids / compras / push / cálculo) con su fecha,
   quién y su acción al lado. Chip de frescura: verde ≤7d, ámbar ≤30d, rojo
   más viejo o nunca. Grid auto-fit: 4 → 2 → 1 columnas sin deformarse. */
#page-adm-projcost .fin-state { border: 1px solid var(--border2); background: var(--card);
  border-radius: var(--radius); box-shadow: var(--shadow-card);
  padding: var(--space-3) var(--space-4); margin-bottom: var(--space-5); }
#page-adm-projcost .fin-state-head { display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: var(--space-2); }
#page-adm-projcost .fin-state-head h3 { margin: 0; font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: var(--tracking-overline); text-transform: uppercase; color: var(--text2); }
#page-adm-projcost .fin-state-grid { display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-2) var(--space-5); }
#page-adm-projcost .fin-state-row { display: flex; align-items: center; gap: var(--space-2);
  min-width: 0; padding: var(--space-1) 0; }
#page-adm-projcost .fin-state-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
#page-adm-projcost .fin-state-dot.ok { background: var(--green); }
#page-adm-projcost .fin-state-dot.warn { background: var(--yellow); }
#page-adm-projcost .fin-state-dot.bad { background: var(--red); }
#page-adm-projcost .fin-state-txt { min-width: 0; display: flex; flex-direction: column; }
#page-adm-projcost .fin-state-lbl { font-size: var(--fs-sm); font-weight: 600; color: var(--text2); }
#page-adm-projcost .fin-state-meta { font-size: var(--fs-sm); color: var(--text3);
  font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#page-adm-projcost .fin-state-act { margin-left: auto; flex: 0 0 auto; }

/* ── Shows activos/terminados (2026-08-31) ──
   Chip gris de show terminado (sin selección) + badge en la toolbar de su
   tabla + lista Activos/Terminados en el engrane (patrón .fin-bl-*). */
#page-adm-projcost .fin-chip.fin-chip-fin { opacity: .55; cursor: help; }
#page-adm-projcost .fin-finished-chip { font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text3); background: var(--wash-2);
  border: 1px solid var(--border2); border-radius: var(--radius-pill);
  padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); }
#page-adm-projcost .fin-ss-sec { font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: var(--tracking-overline); text-transform: uppercase; color: var(--text3);
  padding: var(--space-3) 0 var(--space-1); }
#page-adm-projcost .fin-ss-item { display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1) 0; border-bottom: 1px solid var(--border); }
#page-adm-projcost .fin-ss-item:last-child { border-bottom: none; }
#page-adm-projcost .fin-ss-code { font-size: var(--fs-sm); font-weight: 700; letter-spacing: .01em; }
#page-adm-projcost .fin-ss-item.fin-ss-fin .fin-ss-code { color: var(--text3); font-weight: 600; }
#page-adm-projcost .fin-ss-name { flex: 1; min-width: 0; font-size: var(--fs-sm); color: var(--text3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#page-adm-projcost .fin-ss-btn { flex: 0 0 auto; }
/* Badge de status FPT: en el chip (Bidding/Hold) y en la lista del engrane */
#page-adm-projcost .fin-chip-st { font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--yellow); }
#page-adm-projcost .fin-ss-st { flex: 0 0 auto; font-size: var(--fs-2xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--text3);
  background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-pill);
  padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); white-space: nowrap; }
#page-adm-projcost .fin-ss-st small { font-weight: 400; text-transform: none; letter-spacing: 0; }

/* ── Fase 3 (2026-08-31): leyenda escaneable + empty state guiado + campo
      de nombre del respaldo (adiós window.prompt) ── */
#page-adm-projcost .fin-legend { display: grid; gap: var(--space-1); margin-top: var(--space-3); }
#page-adm-projcost .fin-legend-item { display: flex; align-items: baseline; gap: var(--space-2); }
#page-adm-projcost .fin-legend-item > b { flex: 0 0 auto; min-width: 20px; text-align: center; color: var(--text2); }
#page-adm-projcost .fin-empty { border: 1px dashed var(--border2); border-radius: var(--radius);
  background: var(--card); padding: var(--space-6) var(--space-5); max-width: 560px;
  margin: var(--space-6) auto; display: flex; flex-direction: column; gap: var(--space-4); }
#page-adm-projcost .fin-empty h3 { margin: 0; font-size: var(--fs-lg); font-weight: 700; }
#page-adm-projcost .fin-empty-steps { display: flex; flex-direction: column; gap: var(--space-3); }
#page-adm-projcost .fin-empty-step { display: flex; align-items: baseline; gap: var(--space-3); font-size: var(--fs-md); color: var(--text2); }
#page-adm-projcost .fin-empty-step > b { flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--accent); font-size: var(--fs-sm); }
#page-adm-projcost .fin-bk-saverow { display: flex; align-items: center; gap: var(--space-2); width: 100%; }
#page-adm-projcost .fin-bk-saverow .inp { flex: 1; min-width: 0; text-align: left; }

/* ── Fase 4 (2026-08-31): Vendors/Freelance solo lectura ──
   Reusa fin2-tablewrap/fin2-toolbar/fin-table; aquí solo lo propio. */
#page-adm-projcost .fin-vendors { margin-top: var(--space-6); }
#page-adm-projcost .finv-head { margin-bottom: var(--space-3); display: flex; align-items: center; gap: var(--space-2); }
#page-adm-projcost .finv-total { font-size: var(--fs-md); font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--text2); white-space: nowrap; }
#page-adm-projcost .finv-name { font-size: var(--fs-md); color: var(--text2); min-width: 0;
  max-width: 40ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#page-adm-projcost .finv-table td { padding: var(--space-2) var(--space-3); }
#page-adm-projcost .finv-ep td { font-size: var(--fs-sm); font-weight: 700; color: var(--text2);
  background: var(--wash-2); text-transform: uppercase; letter-spacing: .03em; }
#page-adm-projcost .finv-vendor td { font-weight: 700; background: var(--wash-1); }
#page-adm-projcost .finv-bid { max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#page-adm-projcost .finv-meta { color: var(--text3); text-align: center; white-space: nowrap; font-variant-numeric: tabular-nums; }
#page-adm-projcost .finv-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
#page-adm-projcost .finv-ok { color: var(--green); font-weight: 700; }
#page-adm-projcost .finv-no { color: var(--text3); }

/* #3 Caja por show: toolbar (título + filtros + agregar) pegada a su tabla */
#page-adm-projcost .fin2-tablewrap { border: 1px solid var(--border2); border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow-card); overflow: hidden; }
#page-adm-projcost .fin2-toolbar { display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); background: var(--wash-1); border-bottom: 1px solid var(--border2); }
#page-adm-projcost .fin2-showtitle { display: flex; align-items: baseline; gap: var(--space-2); }
#page-adm-projcost .fin2-showtitle .code { font-size: var(--fs-lg); font-weight: 700; letter-spacing: .01em; }
#page-adm-projcost .fin-q { width: 230px; max-width: 100%; }
#page-adm-projcost .tscroll { overflow-x: auto; }

/* #4 Respiración de tabla + inputs de % sin caja (borde solo hover/focus) */
#page-adm-projcost .fin-table { min-width: 100%; }
#page-adm-projcost .fin-table th { font-size: var(--fs-2xs); letter-spacing: var(--tracking-overline);
  text-transform: uppercase; color: var(--text3); padding: var(--space-3) var(--space-4); background: var(--card); }
#page-adm-projcost .fin-table td { padding: var(--space-2) var(--space-4); vertical-align: middle; }
#page-adm-projcost .fin-table tbody tr:hover td { background: var(--wash-1); }
#page-adm-projcost .fin-col-sel { width: 44px; }
#page-adm-projcost .fin-col-name { width: 260px; }
#page-adm-projcost .fin-col-mo { width: 104px; }
#page-adm-projcost .fin-td-sel input { width: 15px; height: 15px; }
#page-adm-projcost .fin-pct { width: 78px; background: transparent; border: 1px solid transparent;
  font-size: calc(12.4px * var(--fs-scale, 1)); font-weight: 600; font-variant-numeric: tabular-nums;
  letter-spacing: .01em; padding: calc(6px * var(--sp-scale, 1)) var(--space-2);
  border-radius: var(--radius-xs); color: var(--text); -moz-appearance: textfield; appearance: textfield; }
#page-adm-projcost .fin-pct::-webkit-outer-spin-button,
#page-adm-projcost .fin-pct::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
#page-adm-projcost .fin-pct:hover { background: var(--wash-2); }
#page-adm-projcost .fin-pct:focus { background: var(--wash-2); border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft); outline: none; }
#page-adm-projcost .fin-pct::placeholder { color: var(--text3); font-weight: 400; }
#page-adm-projcost .fin-pct.fin-ovr { border-color: var(--accent-border); border-style: dashed; }
#page-adm-projcost .fin-pct.fin-pre { background: transparent; color: var(--yellow); }
#page-adm-projcost .fin-flag { top: -2px; right: -2px; opacity: .85; }

/* #3b Bottom bar en 3 zonas (glass) */
#page-adm-projcost .fin-selbar { border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--card2) 86%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(160%); backdrop-filter: blur(18px) saturate(160%); }
#page-adm-projcost .fin-selbar .count { display: flex; align-items: center; gap: var(--space-2);
  padding: 0 var(--space-2) 0 var(--space-3); font-size: var(--fs-base); color: var(--text2); white-space: nowrap; }
#page-adm-projcost .fin-selbar .count b { color: var(--text); font-size: var(--fs-lg); font-variant-numeric: tabular-nums; }
#page-adm-projcost .fin-selbar .zone { display: flex; align-items: center; gap: var(--space-2); }
#page-adm-projcost .fin-selbar .zone-label { font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: var(--tracking-overline); text-transform: uppercase; color: var(--text3); margin-right: 2px; }
#page-adm-projcost .fin-selbar-sep { background: var(--border2); }
#page-adm-projcost .fin-selbar #fin-bulk-val { width: 64px; text-align: center; font-variant-numeric: tabular-nums; }

/* #5 Slide-over "+ Agregar artista" (base .aso-* del DS) */
#page-adm-projcost .fin2-so-head { position: relative; padding: var(--space-5) var(--space-5) var(--space-3);
  border-bottom: 1px solid var(--border); }
#page-adm-projcost .fin2-so-head h2 { margin: 0 0 2px; font-size: var(--fs-xl); font-weight: 700; }
#page-adm-projcost .fin2-so-head .close-btn { position: absolute; top: 14px; right: 14px; }
#page-adm-projcost .fin2-so-filters { padding: var(--space-3) var(--space-5); display: flex;
  flex-direction: column; gap: var(--space-3); border-bottom: 1px solid var(--border); }
#page-adm-projcost .fin2-so-filters .inp { width: 100%; }
#page-adm-projcost .fin2-so-filters .seg { align-self: flex-start; }
#page-adm-projcost .fin2-so-cap { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; }
#page-adm-projcost .fin2-so-cap input { accent-color: var(--accent); }
#page-adm-projcost .fin2-so-list { flex: 1; overflow-y: auto; padding: var(--space-2) var(--space-3); }
#page-adm-projcost .fin2-so-sec { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: var(--tracking-overline);
  text-transform: uppercase; color: var(--text3); padding: var(--space-3) var(--space-2) var(--space-2); }
#page-adm-projcost .fin2-so-item { display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2); border-radius: var(--radius-sm); cursor: pointer; }
#page-adm-projcost .fin2-so-item:hover { background: var(--wash-2); }
#page-adm-projcost .fin2-so-item input { accent-color: var(--accent); width: 15px; height: 15px; }
#page-adm-projcost .fin2-so-item .nm { flex: 1; font-size: var(--fs-md); }
#page-adm-projcost .fin2-so-item .av { font-size: var(--fs-sm); font-variant-numeric: tabular-nums; font-weight: 600; }
#page-adm-projcost .fin2-so-item .av.free { color: var(--green); }
#page-adm-projcost .fin2-so-item .av.tight { color: var(--yellow); }
#page-adm-projcost .fin2-so-item .av.full { color: var(--text3); }
#page-adm-projcost .fin2-so-item.dis { opacity: .45; cursor: not-allowed; }
#page-adm-projcost .fin2-so-foot { padding: var(--space-4) var(--space-5); border-top: 1px solid var(--border);
  display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3); background: var(--card); }
/* El slide-over debe quedar por ENCIMA de la bottom bar (z-popover) */
#page-adm-projcost .aso-backdrop { z-index: var(--z-popover); }
#page-adm-projcost .fin2-so { z-index: calc(var(--z-popover) + 1); }
/* ✕ por fila (quitar del show): oculto en reposo, aparece al hover de la fila
   o con foco de teclado; rojo al hover del propio botón. Métricas .btn-sm. */
#page-adm-projcost .fin-td-x { text-align: right; padding-right: var(--space-3); white-space: nowrap; }
#page-adm-projcost .fin-row-x { opacity: 0; transition: opacity var(--dur-fast, .12s); color: var(--text3); }
#page-adm-projcost .fin-table tbody tr:hover .fin-row-x,
#page-adm-projcost .fin-row-x:focus-visible { opacity: 1; }
#page-adm-projcost .fin-row-x:hover { color: var(--red); background: rgba(var(--red-rgb), 0.12); }
/* Barra de filtros GLOBAL (una sola para todas las tablas de shows) */
#page-adm-projcost .fin2-globalbar { display: flex; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-3); flex-wrap: wrap; }
/* Plegado por show + chip "eliminado antes" */
#page-adm-projcost .fin-fold { padding-left: var(--space-2); padding-right: var(--space-2); color: var(--text3); }
#page-adm-projcost .fin-fold:hover { color: var(--text); }
#page-adm-projcost .fin2-tablewrap.fin-folded .fin2-toolbar { border-bottom: none; }
#page-adm-projcost .fin-removed-chip { font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--orange); background: rgba(var(--orange-rgb), 0.12);
  border: 1px solid rgba(var(--orange-rgb), 0.30); border-radius: var(--radius-pill);
  padding: calc(2px * var(--sp-scale, 1)) calc(7px * var(--sp-scale, 1)); margin-left: calc(6px * var(--sp-scale, 1));
  cursor: pointer; font-family: inherit; }
#page-adm-projcost .fin-removed-chip:hover { background: rgba(var(--orange-rgb), 0.22); }
/* El buscador es type=search y el DS alinea .inp del área admin a la derecha
   (numéricos): se fuerza a la izquierda como pidió el usuario. */
#page-adm-projcost .fin-q { text-align: left; }
/* ── Memoria de imports (F2, 2026-07-14): lista + detalle en slide-over ── */
#page-adm-projcost .fin-mem-pad { padding: var(--space-3) var(--space-2); }
#page-adm-projcost .fin-mem-item { display: flex; flex-direction: column; gap: var(--space-1);
  width: 100%; text-align: left; padding: var(--space-3) var(--space-2);
  background: none; border: 0; border-bottom: 1px solid var(--border);
  border-radius: var(--radius-sm); cursor: pointer; font-family: inherit; color: var(--text); }
#page-adm-projcost .fin-mem-item:hover { background: var(--wash-2); }
#page-adm-projcost .fin-mem-line { display: flex; align-items: center; gap: var(--space-2); }
#page-adm-projcost .fin-mem-file { font-size: var(--fs-md); font-weight: 600; overflow-wrap: anywhere; }
#page-adm-projcost .fin-mem-meta { font-size: var(--fs-sm); color: var(--text3); }
#page-adm-projcost .fin-mem-table { width: 100%; }
#page-adm-projcost .fin-mem-table th, #page-adm-projcost .fin-mem-table td { padding: var(--space-1) var(--space-2); }
/* Ventana MÁS ANCHA que el aso-panel base (usuario 2026-07-13: no se leía la
   info, aplica a lista y detalle) */
#page-adm-projcost #fin-mem { width: min(760px, 94vw); }
/* Encabezado de sección con botón "Eliminar todos" a la derecha */
#page-adm-projcost .fin-mem-sec { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
#page-adm-projcost .fin-mem-delall { color: var(--red); }
#page-adm-projcost .fin-mem-x { color: var(--text3); padding: 0 var(--space-2); }
#page-adm-projcost .fin-mem-x:hover { color: var(--red); }
/* ── F3 Push a Google Sheets (2026-07-14): fila del ID del Sheet destino
   (vive en el slide-over Configuración desde el rediseño Sr. UX) ── */
#page-adm-projcost .fin-cfg-fieldrow { display: flex; align-items: center; gap: var(--space-2); }
#page-adm-projcost .fin-cfg-fieldrow .inp { flex: 1; min-width: 0; text-align: left; font-size: var(--fs-sm); }
/* ── Memoria → pestaña Respaldos (2026-07-14) ── */
#page-adm-projcost .fin-mem-tabs { margin-top: var(--space-2); }
#page-adm-projcost .fin-bk-head { display: flex; flex-direction: column; gap: var(--space-2);
  align-items: flex-start; border-bottom: 1px solid var(--border); }
#page-adm-projcost .fin-bk-item { cursor: default; }
#page-adm-projcost .fin-bk-item:hover { background: var(--wash-1); }
#page-adm-projcost .fin-bk-actions { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-1); }
#page-adm-projcost .fin-bk-auto { color: var(--orange); background: rgba(var(--orange-rgb), 0.12); }
/* ── Monitoreo Artistas: selector de departamentos (2026-07-14; el modal ⚙
      de settings reutiliza los mismos chips — v2 2026-07-21) ── */
#page-report-monitoring .mon-depts { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
#mon-settings-modal .mon-depts { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
#page-report-monitoring .mon-dept-chk, #mon-settings-modal .mon-dept-chk { display: flex; align-items: center; gap: var(--space-1);
  cursor: pointer; font-weight: 500; border: 1px solid var(--border); }
#page-report-monitoring .mon-dept-chk input, #mon-settings-modal .mon-dept-chk input { margin: 0; cursor: pointer; }
#page-report-monitoring .mon-dept-chk:has(input:checked), #mon-settings-modal .mon-dept-chk:has(input:checked) { border-color: var(--accent);
  color: var(--accent); background: rgba(var(--accent-rgb), 0.10); }
/* ── Monitoreo Artistas v2 (spec 2026-07-21 §5, mockup Propuesta_UI_Monitoreo):
      layout lineal + panel derecho, pill del diario automático, badges de
      estado soft+border y semáforo de eficiencia (ÚNICO color fuerte). ── */
.mon-v2-layout { display: grid; grid-template-columns: minmax(0, 1fr) 400px; gap: var(--space-4); align-items: start; }
.mon-v2-main   { display: flex; flex-direction: column; gap: calc(10px * var(--sp-scale, 1)); min-width: 0; }
.mon-v2-side   { position: sticky; top: 0; }
.mon-v2-row    { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
/* ── Monitoreo v2 · consistencia de controles + tarjetas con aire e igualadas
   (2026-07-22, validado en vivo con Chrome MCP). Todo ACOTADO a
   #page-report-monitoring: no toca el DS global. El usuario pidió controles del
   MISMO tamaño y tarjetas más grandes/legibles, así que aquí se unifica la
   altura de TODOS los controles (~34px) por encima del btn-sm global. ── */
/* (El override `#page-report-monitoring .mon-v2-row .btn-primary { width:auto }`
   se retiró el 2026-07-24: .btn-primary ya no es full-width en el núcleo.) */
/* Altura uniforme de todos los controles interactivos de la vista */
#page-report-monitoring .mon-v2-main .btn,
#page-report-monitoring .mon-v2-side .btn,
#page-report-monitoring .otdp-trigger,
#page-report-monitoring #mon-ind-artist,
#page-report-monitoring .mon-dept-chk { min-height: 34px; box-sizing: border-box; }
#page-report-monitoring #mon-settings-btn { width: 34px; height: 34px; }
/* Tarjetas con más aire */
#page-report-monitoring .mon-v2-main > .ot-section,
#page-report-monitoring .mon-v2-side { padding: calc(22px * var(--sp-scale, 1)) var(--space-6); }
#page-report-monitoring .mon-v2-row { gap: var(--space-3); }
/* Fechas del reporte individual apiladas (el formato largo no cabe en 2 columnas) */
#page-report-monitoring .mon-v2-side .mon-v2-row { flex-direction: column; align-items: stretch; gap: var(--space-2); }
/* Dos tarjetas de la MISMA altura (aligned) sin estirar el panel al mostrar
   resultados: min-height compartido en vez de align-items:stretch. */
#page-report-monitoring .mon-v2-main > .ot-section:first-of-type,
#page-report-monitoring .mon-v2-side { min-height: 312px; }
/* Card izquierda: reparte el aire y ancla la fila de Sheets al fondo */
#page-report-monitoring .mon-v2-main > .ot-section:first-of-type { display: flex; flex-direction: column; gap: calc(14px * var(--sp-scale, 1)); }
#page-report-monitoring .mon-v2-main > .ot-section:first-of-type .mon-v2-sep { margin: calc(6px * var(--sp-scale, 1)) 0 0; }
#page-report-monitoring .mon-v2-main > .ot-section:first-of-type .mon-v2-sep ~ .mon-v2-row { margin-top: auto; }
.mon-v2-hint   { font-size: var(--fs-base); color: var(--text2); }
.mon-v2-sep    { height: 1px; background: var(--border); margin: var(--space-2) 0; }
.mon-v2-legend { font-size: var(--fs-base); color: var(--text2); margin-top: var(--space-3); line-height: 1.6; }
/* ── Monitoreo · modal ⚙ de Configuración (rediseño 2026-07-27) ──────────
   Todo acotado por id: no toca el DS global. */
#mon-settings-modal .modal-body { display: flex; flex-direction: column; gap: var(--space-4); }
#mon-settings-modal .modal-body .field { margin-bottom: 0; }   /* manda el gap del body */
#mon-settings-modal .help b { color: var(--text2); font-weight: 600; }
#mon-settings-modal .mon-set-sep { height: 1px; background: var(--border); }
#mon-settings-modal .mon-set-switch { display: flex; align-items: flex-start; gap: var(--space-2); margin: 0; cursor: pointer; }
#mon-settings-modal .mon-set-switch input[type="checkbox"] { flex-shrink: 0; margin: 0; cursor: pointer; accent-color: var(--accent); }
#mon-settings-modal .mon-set-switch-txt { display: flex; flex-direction: column; gap: calc(2px * var(--sp-scale, 1)); min-width: 0; }
#mon-settings-modal .mon-set-switch-txt b    { font-size: var(--fs-md); font-weight: 600; color: var(--text); }
#mon-settings-modal .mon-set-switch-txt span { font-size: var(--fs-sm); color: var(--text3); line-height: 1.4; }
/* Hora y departamentos SUBORDINADOS: sangría + guía vertical dicen "esto
   depende del interruptor" sin una sola palabra. Apagado ⇒ atenuado pero
   LEGIBLE (ocultarlos movería los botones del pie bajo el cursor y borraría la
   respuesta a "¿a qué hora estaba puesto antes de apagarlo?"). */
#mon-settings-modal .mon-set-sub {
  display: flex; align-items: flex-start; flex-wrap: wrap; gap: var(--space-5);
  margin: var(--space-3) 0 0 calc(7px * var(--sp-scale, 1));
  padding-left: var(--space-4); border-left: 2px solid var(--border);
  transition: opacity var(--dur-slow);
}
#mon-settings-modal .mon-set-group:not(:has(#mon-set-auto:checked)) .mon-set-sub { opacity: .45; pointer-events: none; }
#mon-settings-modal .mon-set-field-time input[type="time"] { width: 118px; }
/* Pie: el metadato de estado a la izquierda; las acciones siguen a la derecha. */
#mon-settings-modal .mon-set-lastrun {
  margin-right: auto; align-self: center; min-width: 0;
  font-size: var(--fs-sm); color: var(--text3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 520px) {
  #mon-settings-modal .mon-set-sub { flex-direction: column; gap: var(--space-3); }
  #mon-settings-modal .mon-set-lastrun { display: none; }
}

/* ── Monitoreo · modal Excluidos del reporte (2026-08-28) ──
   Espejo del picker de iOS: encabezado por depto, fila = label completo
   clicable con checkbox, tachado en rojo suave. `.ghost` = nombre que sigue
   en la lista del server pero ya no está en la plantilla activa. */
#mon-omit-modal #mon-omit-list {
  max-height: 52vh; overflow-y: auto;
  border: 1px solid var(--border); border-radius: 8px;
  padding: var(--space-1) 0;
}
#mon-omit-modal .mon-omit-dept {
  position: sticky; top: 0; z-index: 1;
  padding: var(--space-1) var(--space-3);
  background: var(--bg); color: var(--text3);
  font-size: var(--fs-2xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em;
}
#mon-omit-modal .mon-omit-row {
  display: flex; align-items: center; gap: var(--space-2);
  padding: calc(5px * var(--sp-scale, 1)) var(--space-3);
  margin: 0; cursor: pointer;
  font-size: var(--fs-md); color: var(--text);
}
#mon-omit-modal .mon-omit-row:hover { background: var(--bg); }
#mon-omit-modal .mon-omit-row input[type="checkbox"] {
  flex-shrink: 0; margin: 0; cursor: pointer; accent-color: var(--red);
}
#mon-omit-modal .mon-omit-row span {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#mon-omit-modal .mon-omit-row.on span { color: var(--red); }
#mon-omit-modal .mon-omit-row.ghost span { opacity: .6; font-style: italic; }
/* El badge del botón "Excluidos" hereda tamaño del .btn; solo se atenúa. */
#mon-omit-count { color: inherit; opacity: .75; }

/* Botonera del Reporte individual (usuario 2026-07-26: "los dos botones en el
   mismo renglón" y "a 1/4 de su tamaño"). Clase PROPIA y no .mon-v2-row porque
   esa, dentro del panel lateral, se fuerza a columna para apilar las fechas. */
.mon-ind-actions {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-2); margin-top: var(--space-2);
}
#page-report-monitoring .mon-ind-actions .btn { width: auto; flex: 0 0 auto; }

/* Bitácora del lote: resumen + una fila por artista con el motivo COMPLETO. */
.mon-batch-kpis { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-4); }
.mon-batch-kpi {
  flex: 1 1 120px; background: var(--card2); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-3); text-align: center;
}
.mon-batch-kpi b { display: block; font-size: var(--fs-lg); line-height: 1.3; }
.mon-batch-kpi span { font-size: var(--fs-sm); color: var(--text2); }
.mon-batch-kpi.warn b { color: var(--orange); }
.mon-batch-kpi.err b  { color: var(--red); }
.mon-batch-list { display: flex; flex-direction: column; max-height: 52vh; overflow: auto; }
.mon-batch-row {
  display: grid; grid-template-columns: minmax(150px, 1.1fr) 128px minmax(0, 1.6fr);
  gap: var(--space-3); align-items: start; padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border); font-size: var(--fs-sm);
}
.mon-batch-row:last-child { border-bottom: 0; }
.mon-batch-row .bn { font-weight: 500; }
.mon-batch-row .bd { color: var(--text2); word-break: break-word; white-space: pre-wrap; }
.mon-batch-tag {
  display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1));
  padding: 1px var(--space-2); border-radius: var(--radius-pill);
  font-size: var(--fs-sm); border: 1px solid var(--border2); color: var(--text2); white-space: nowrap;
}
.mon-batch-tag.ok   { color: var(--green);  border-color: var(--green); }
.mon-batch-tag.zero { color: var(--orange); border-color: var(--orange); }
.mon-batch-tag.err  { color: var(--red);    border-color: var(--red); }

/* Selector de departamento del lote individual (usuario 2026-07-26: "un solo
   botón, minimalista"). El botón usa el tamaño GLOBAL (.btn.btn-sm) — aquí solo
   se posiciona el menú; nunca se fija height. */
.mon-dept-pick { position: relative; display: inline-flex; }
.mon-dept-pick .mon-dept-btn { gap: calc(5px * var(--sp-scale, 1)); white-space: nowrap; }
.mon-dept-pick .mon-dept-btn > span { min-width: 2.2em; text-align: left; }
.mon-dept-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: var(--z-otdp);
  min-width: 132px; padding: var(--space-1); display: none; flex-direction: column;
  background: var(--card2); border: 1px solid var(--wash-4); border-radius: 10px;
  box-shadow: 0 2px 4px rgba(0,0,0,.3), 0 8px 20px rgba(0,0,0,.45);
}
.mon-dept-menu.open { display: flex; }
.mon-dept-menu > button {
  display: flex; align-items: center; gap: var(--space-2); width: 100%;
  padding: var(--space-2) var(--space-3); border: 0; border-radius: 7px;
  background: transparent; color: var(--text); font: inherit; font-size: var(--fs-sm);
  text-align: left; cursor: pointer;
}
.mon-dept-menu > button:hover { background: var(--wash-2); }
.mon-dept-menu > button::before {
  content: ''; width: 13px; height: 13px; flex: 0 0 13px; border-radius: 4px;
  border: 1.5px solid var(--border2); box-sizing: border-box;
}
.mon-dept-menu > button.on::before { background: var(--accent); border-color: var(--accent); }
.mon-dept-menu > button.on { color: var(--text); font-weight: 500; }
.mon-auto-pill { display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); background: var(--card2); border: 1px solid var(--border2);
  border-radius: var(--radius-pill); padding: var(--space-1) var(--space-3); font-size: var(--fs-sm); color: var(--text2);
  cursor: pointer; font-family: inherit; line-height: 1.4; transition: border-color .12s, color .12s; }
.mon-auto-pill:hover { border-color: var(--accent); color: var(--text); }
.mon-auto-pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mon-auto-pill i { width: 7px; height: 7px; border-radius: 50%; background: var(--green); display: inline-block; flex-shrink: 0; }
/* Apagado: el punto pierde el verde y el texto baja de peso — se sigue viendo
   y se sigue pudiendo abrir la configuración desde aquí. */
.mon-auto-pill.off        { color: var(--text3); }
.mon-auto-pill.off:hover  { color: var(--text2); }   /* después de .off: si no, la regla de hover no gana */
.mon-auto-pill.off i      { background: var(--text3); opacity: .55; }
.mon-btn-sheets { background: rgba(var(--green-rgb), 0.15); border: 1px solid rgba(var(--green-rgb), 0.30); color: var(--green); }
.mon-b { display: inline-block; font-size: var(--fs-sm); font-weight: 700; padding: calc(3px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1)); border-radius: var(--radius-pill);
  border: 1px solid; white-space: nowrap; }
.mon-b.na  { background: var(--card2); border-color: var(--border2); color: var(--text3); }
.mon-b.mt  { background: rgba(var(--orange-rgb), 0.15); border-color: rgba(var(--orange-rgb), 0.30); color: var(--orange); }
.mon-b.dt  { background: rgba(var(--red-rgb), 0.15);    border-color: rgba(var(--red-rgb), 0.30);    color: var(--red); }
.mon-b.vac { background: var(--purple-soft);            border-color: var(--purple-border);          color: var(--purple); }
.mon-pct { font-weight: 800; font-size: var(--fs-md); }
.mon-pct.g { color: var(--green); } .mon-pct.o { color: var(--orange); } .mon-pct.r { color: var(--red); } .mon-pct.mut { color: var(--text3); }
/* KPI Eficiencia global: semáforo de .mon-pct sin encoger el número (UX 2026-07-21) */
.ot-kpi-val.mon-pct { font-size: var(--fs-kpi); font-weight: 700; }
.mon-row-off td { opacity: .45; }
.mon-note-ic { color: var(--text2); cursor: help; display: inline-flex; align-items: center; gap: var(--space-1); }
@media (max-width: 1100px) { .mon-v2-layout { grid-template-columns: 1fr; } .mon-v2-side { position: static; } }
/* ── Blacklist de shows en Detectar shows (2026-07-14) ── */
#page-adm-projcost .fin-chip-wrap { position: relative; display: inline-flex; }
#page-adm-projcost .fin-chip-x { position: absolute; top: calc(-6px * var(--sp-scale, 1)); right: calc(-6px * var(--sp-scale, 1));
  width: 16px; height: 16px; padding: 0; border: 1px solid var(--border2); border-radius: var(--radius-pill);
  background: var(--card); color: var(--text3); font-size: var(--fs-2xs); line-height: 1;
  cursor: pointer; opacity: 0; transition: opacity var(--dur-fast, .12s); font-family: inherit; }
#page-adm-projcost .fin-chip-wrap:hover .fin-chip-x,
#page-adm-projcost .fin-chip-x:focus-visible { opacity: 1; }
#page-adm-projcost .fin-chip-x:hover { color: var(--red); border-color: rgba(var(--red-rgb), 0.4); }
#page-adm-projcost .fin-bl-link { border: none; background: none; padding: 0; color: var(--accent);
  cursor: pointer; font: inherit; text-decoration: underline; }
#page-adm-projcost .fin-bl-list { display: flex; flex-wrap: wrap; gap: var(--space-2); }
#page-adm-projcost .fin-bl-item { display: inline-flex; align-items: center; gap: var(--space-1);
  padding: var(--space-1) var(--space-1) var(--space-1) var(--space-3);
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  font-size: var(--fs-sm); font-weight: 600; color: var(--text2); background: var(--wash-2); }
#page-adm-projcost .fin-bl-item:hover { border-color: var(--border2); }
/* ── Slide-over Configuración (rediseño Sr. UX 2026-07-14): secciones con
   overline, descripciones con wrap real y zona de riesgo encajonada ── */
#page-adm-projcost .fin-cfg-body { flex: 1; overflow-y: auto; display: flex; flex-direction: column;
  gap: var(--space-6); padding: var(--space-4) var(--space-5); }
#page-adm-projcost .fin-cfg-sec { display: flex; flex-direction: column; gap: var(--space-2); }
#page-adm-projcost .fin-cfg-sec h3 { margin: 0; font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: var(--tracking-overline, .08em); text-transform: uppercase; color: var(--text3); }
#page-adm-projcost .fin-cfg-sec h3.fin-cfg-danger-h { color: var(--red); }
#page-adm-projcost .fin-cfg-desc { margin: 0; font-size: var(--fs-sm); color: var(--text3); line-height: 1.45; }
#page-adm-projcost .fin-cfg-danger { border: 1px solid rgba(var(--red-rgb), 0.3); border-radius: var(--radius-sm);
  background: rgba(var(--red-rgb), 0.05); padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
#page-adm-projcost .fin-cfg-danger strong { font-size: var(--fs-md); color: var(--text); }
#page-adm-projcost .fin-cfg-danger-btn { color: var(--red); align-self: flex-start; }
/* ✕ del chip excluido: SIEMPRE visible (el usuario viene a gestionarlos) */
#page-adm-projcost .fin-bl-x { display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; border-radius: var(--radius-pill); color: var(--text3);
  cursor: pointer; padding: var(--space-1); min-width: var(--space-5); min-height: var(--space-5);
  font-family: inherit; font-size: var(--fs-2xs); line-height: 1; }
#page-adm-projcost .fin-bl-x:hover { color: var(--red); background: rgba(var(--red-rgb), 0.12); }
#page-adm-projcost .fin-bl-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
#page-adm-projcost .fin-bl-empty { font-size: var(--fs-sm); color: var(--text3); }

/* ══════════════════════════════════════════════════════════
   MÓVIL — Fase 0: shell responsive (2026-07-23)
   ────────────────────────────────────────────────────────
   El shell desktop (sidebar fija de 216px) no cabe en un teléfono. En ≤820px
   el sidebar se vuelve un DRAWER off-canvas que se abre con la clase
   `sb-mobile-open` en #view-app (botón flotante + backdrop creados por
   lib/mobile-nav.js). Fuera del media query todo es inerte: cero efecto en
   desktop (goldens visuales intactos). Las secciones se adaptan por fases;
   este bloque solo cubre navegación y patrones base.
   ══════════════════════════════════════════════════════════ */
.sb-mobile-btn { display: none; }
.sb-mobile-backdrop { display: none; }

@media (max-width: 820px) {
  /* ── Sidebar → drawer ── */
  .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; height: 100%;
    width: min(290px, 86vw);
    z-index: var(--z-panel);
    transform: translateX(-102%);
    transition: transform var(--dur-base) var(--ease-out);
    box-shadow: 24px 0 64px rgba(0, 0, 0, 0.35);
  }
  #view-app.sb-mobile-open .sidebar { transform: translateX(0); }
  /* El main ocupa todo el ancho (el sidebar ya no está en el flujo) */
  .main-content { height: 100dvh; }

  /* ── Backdrop + botón flotante ── */
  .sb-mobile-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.45); z-index: var(--z-backdrop); }
  #view-app.sb-mobile-open .sb-mobile-backdrop { display: block; }
  .sb-mobile-btn {
    display: flex; align-items: center; justify-content: center;
    position: fixed; left: var(--space-3); bottom: var(--space-3);
    width: 46px; height: 46px; border-radius: var(--radius-pill);
    background: var(--accent); color: #fff; border: none; cursor: pointer;
    z-index: var(--z-panel); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
  }
  #view-app.sb-mobile-open .sb-mobile-btn { display: none; }

  /* ── El colapsado (66px) es un modo de DESKTOP: dentro del drawer el menú
        va siempre completo, aunque localStorage traiga sb-collapsed ── */
  #view-app.sb-collapsed .sidebar { width: min(290px, 86vw); }
  #view-app.sb-collapsed .sb-toggle { display: none; }
  .sb-toggle { display: none; }   /* colapsar no aplica en móvil */
  #view-app.sb-collapsed .sidebar-header {
    flex-direction: row; justify-content: flex-start; align-items: center;
    gap: calc(10px * var(--sp-scale, 1));
    padding: calc(15px * var(--sp-scale, 1)) var(--space-3) var(--space-3);
  }
  #view-app.sb-collapsed .sidebar-brand { display: block; }
  #view-app.sb-collapsed .sidebar .nav-item {
    font-size: var(--fs-md); justify-content: flex-start; gap: var(--space-2);
    padding: calc(7px * var(--sp-scale, 1)) var(--space-2);
  }
  #view-app.sb-collapsed .sidebar .nav-item svg { font-size: inherit; }
  #view-app.sb-collapsed .sidebar .nav-label { display: block; }
  #view-app.sb-collapsed .sidebar .subnav { display: flex; }
  #view-app.sb-collapsed #quick-access-section { display: block; }
  #view-app.sb-collapsed .sidebar-footer {
    flex-direction: row; align-items: center; gap: var(--space-1);
    padding: var(--space-2) var(--space-2);
  }

  /* ── Patrones base táctiles ── */
  .nav-item { min-height: 42px; }                      /* target táctil ≥42px */
  .subnav .nav-item { min-height: 38px; }
  .sidebar-nav { -webkit-overflow-scrolling: touch; }
  /* Wrappers de tabla existentes: scroll horizontal con inercia táctil */
  .table-scroll, #dash-table-wrap, .ot-table-wrap, .mon-table-wrap,
  .payroll-table-wrap, .u-table-wrap, .page-body { -webkit-overflow-scrolling: touch; }
}

/* Accesibilidad: sin animación del drawer si el usuario lo pide */
@media (prefers-reduced-motion: reduce) {
  .sidebar { transition: none; }
}

/* ══════════════════════════════════════════════════════════
   MÓVIL — Fase 1: páginas de consulta diaria (2026-07-23)
   Dashboard · Shots · Artistas · Monitoreo (Artistas/Prod)
   ────────────────────────────────────────────────────────
   NOTA sobre !important: los tabs de Shots/Artistas traen layout en style=""
   inline en el HTML estático (que no se edita a mano); un inline gana a
   cualquier regla normal, así que dentro de ESTE media query el !important
   es la única vía. Fuera de aquí sigue prohibido.
   ══════════════════════════════════════════════════════════ */

@media (max-width: 820px) {
  /* ── Transversal: que la última fila no quede bajo el botón flotante ── */
  .page-body { padding-bottom: calc(72px * var(--sp-scale, 1)); }

  /* ── Shots: filtros a lo ancho (debajo de la tabla); padding compacto.
        El flex-wrap inline del contenedor hace el resto. ── */
  #active-shots-scroll { padding: var(--space-3) !important; gap: var(--space-3) !important; }
  #page-active-shots aside { width: 100% !important; }

  /* ── Artistas: cada tab pasa de [contenido | aside 224px] a UNA columna
        con scroll continuo (artistas arriba, filtros abajo). Los hijos
        pierden su scroll propio para no anidar scrolls en táctil. ── */
  #page-artists .artists-tab { flex-direction: column !important; overflow-y: auto !important;
    padding: var(--space-3) !important; }
  #page-artists .artists-tab > .vscroll-quiet { flex: none !important; overflow-y: visible !important; }
  #page-artists .artists-tab > aside { width: 100% !important; }
  #page-artists .artists-subnav-row { flex-wrap: wrap; gap: var(--space-2); }
  /* El título de sección sticky pierde sentido cuando el scroll es del tab */
  #page-artists .dept-ov-sec-title { position: static; }

  /* ── Monitoreo Artistas: ya colapsa a 1 col en ≤1100px; refinamientos ── */
  #page-report-monitoring .mon-v2-side { min-height: 0; }
  #page-report-monitoring .page-header-actions { flex-wrap: wrap; }
}

@media (max-width: 600px) {
  /* Monitoreo Prod: datepickers apilados (2 columnas no caben en ~390px) */
  #page-report-prod .ot-grid-2 { grid-template-columns: 1fr; }
}

/* ── Utilidad global: solo para lectores de pantalla ──
   Texto que debe anunciarse pero no ocupar espacio ni verse. `clip-path` +
   1px en vez de `display:none`, que lo sacaría del árbol de accesibilidad y
   lo volvería mudo (que es justo lo contrario de lo que se busca). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ══════════════════════════════════════════════════════════════════
   TAREAS — tablero colaborativo (Herramientas → Tareas, 2026-07-24)
   Se copia la MECÁNICA de Trello, no su aspecto: aquí no hay fondos con
   foto ni columnas grises. Superficies, radios, tipografía y acentos salen
   del design system, así que el tablero cambia solo con el tema y con el
   Editor UI (--fs-scale / --sp-scale) igual que el resto de la app.
   Reglas del gate DS: cero z-index numérico y cero font-size en px crudos.
   ══════════════════════════════════════════════════════════════════ */

/* El badge de avisos va pegado a la derecha del título de la tarjeta del hub.
   OJO (a11y/DS 2026-07-25): `.nbadge` NO tiene definición base en app.css —
   solo existe `.nav-item .nbadge{display:none}` y la variante `.active`. Al
   reusarla fuera del sidebar el contador salía como TEXTO PELADO (el mismo
   bug que `.kpi`/`.kpi-row` del 2026-07-12). Aquí se le da cuerpo, acotado al
   header de la tarjeta para no tocar el núcleo. Sin `display`: eso rompería
   el atributo `hidden` con el que JS lo apaga cuando no hay avisos.
   El texto va en --text (no en --accent, que sobre --accent-soft da 3.4:1). */
.report-card-header .nbadge {
  margin-left: auto;
  background: var(--accent-soft); color: var(--text);
  border: 1px solid var(--accent-border); border-radius: var(--radius-pill);
  padding: 0 var(--space-2); font-size: var(--fs-2xs); font-weight: 700;
  line-height: calc(16px * var(--fs-scale, 1)); font-variant-numeric: tabular-nums;
}

#page-tasks { overflow: hidden; }
#page-tasks .page-body { padding: 0; display: flex; flex-direction: column; overflow: hidden; }
.tb-head-actions { display: flex; align-items: center; gap: var(--space-2); }
.tb-view { flex: 1; min-height: 0; }

/* ── Vista 1 · índice de tableros ───────────────────────────────── */
/* (2026-07-29, pase premium) ESCALA ESTRICTA de espacios en toda la sección:
   24px (--space-6) para contenedores principales, 16px (--space-4) para
   subelementos. Es la regla que más hace por que el tablero «respire». */
#tb-index {
  overflow-y: auto;
  padding: var(--space-6) var(--space-6) calc(60px * var(--sp-scale, 1));
}
.tb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: calc(10px * var(--sp-scale, 1)); }
.tb-bcard {
  position: relative; overflow: hidden; width: 100%;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm);
  transition: transform var(--dur-fast) var(--ease-out), border-color var(--dur-fast);
}
/* El hover NO cambia el fondo a --card2 a propósito: sobre esa superficie
   «N vencidas» en --red cae a 4.42:1 en tema oscuro (falla AA). Se levanta con
   sombra + borde, que no dependen del contraste del texto. */
.tb-bcard:hover { transform: translateY(-2px); border-color: var(--border2); box-shadow: var(--shadow-pop); }
.tb-bcard-name { font-size: calc(13.5px * var(--fs-scale, 1)); font-weight: 700; letter-spacing: -0.2px; }
/* Metadatos en Regular y atenuados (jerarquía premium): el ojo va del nombre
   al detalle sin que compitan. --text3 es el «opacity .6» del DS ya medido
   contra AA (4.51:1 sobre card) — un opacity crudo no tiene esa garantía. */
.tb-bcard-meta { font-size: var(--fs-sm); font-weight: 400; color: var(--text3); display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: auto; }
/* «N vencidas» con LED encendido: punto con halo, no solo texto rojo. El halo
   es decorativo (el estado ya viaja en el texto); el punto usa el token. */
.tb-bcard-meta .tb-alerta { color: var(--red); font-weight: 650; display: inline-flex; align-items: center; gap: var(--space-1); }
.tb-bcard-meta .tb-alerta::before {
  content: ""; width: calc(6px * var(--sp-scale, 1)); height: calc(6px * var(--sp-scale, 1));
  border-radius: var(--radius-pill); background: var(--red);
  box-shadow: 0 0 8px rgba(var(--red-rgb), .55);
}
.tb-retry { margin-top: var(--space-3); }

/* ── Vista 2 · el tablero ───────────────────────────────────────── */
#tb-board { display: flex; flex-direction: column; overflow: hidden; }
.tb-cols {
  flex: 1; min-height: 0; display: flex; align-items: flex-start; gap: var(--space-3);
  overflow-x: auto; overflow-y: hidden;
  padding: var(--space-5) var(--space-6) var(--space-6);
}
/* Contenedor con scroll propio → foco de teclado (WCAG 2.1.1): sin tabindex,
   Chrome y Safari no dejan desplazarlo con las flechas. Firefox ya lo hace. */
.tb-cols:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.tb-col {
  flex: 0 0 auto; width: 272px; max-height: 100%; display: flex; flex-direction: column;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
/* Columna fantasma «+ Nueva lista» (antes iba con estilos inline en el JS) */
.tb-col-new { background: transparent; border-style: dashed; }
.tb-col-new .tb-col-foot { padding-top: var(--space-2); }
.tb-col.tb-drop { border-color: var(--accent); background: var(--accent-soft); }
/* La cabecera de la columna se delimita con una línea fina del área de
   trabajo (mismo gesto que separa navegación de contenido): el borde atrapa
   la vista sin sumar sombras. */
.tb-col-head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-4) var(--space-2);
  border-bottom: 1px solid var(--border);
}
.tb-col-name { font-size: var(--fs-base); font-weight: 650; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Contador como número de impacto: peso contundente, tono atenuado. */
.tb-col-count { font-size: var(--fs-xs); font-weight: 700; color: var(--text2); font-variant-numeric: tabular-nums; }
/* position:relative — ancla de la línea de inserción del arrastre (A4). */
.tb-col-cards { flex: 1; min-height: var(--space-6); overflow-y: auto; padding: var(--space-2) var(--space-3) var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); position: relative; }
.tb-col-foot { padding: 0 var(--space-3) var(--space-3); }

/* Tarjeta: <button> real — todo lo clicable es botón (regla §7 de a11y) */
/* La tarjeta es un contenedor con TRES controles: círculo, cuerpo y lápiz.
   Anidar <button> dentro de <button> es HTML inválido, así que el envoltorio
   es un <div> y lo clicable son los tres botones. */
/* (2026-07-29, pase premium) La tarjeta es PLANA con borde fino: el volumen lo
   da el hairline (--border), no la sombra — la sombra queda solo para el
   hover, donde sí comunica algo (esto se puede agarrar). */
.tb-card {
  width: 100%; text-align: left; display: flex; align-items: flex-start;
  gap: var(--space-1); position: relative;
  background: var(--card2); border: 1px solid var(--border); border-radius: var(--radius-xs);
  padding: var(--space-3) calc(9px * var(--sp-scale, 1));
  transition: transform var(--dur-micro) var(--ease-out), border-color var(--dur-micro), box-shadow var(--dur-micro);
}
.tb-card:hover { border-color: var(--border2); box-shadow: var(--shadow-pop); }
/* El filtro (2026-07-29) esconde con el ATRIBUTO hidden, y el display:flex de
   arriba le gana a la regla [hidden] del navegador: sin esto, el filtro no
   escondía nada (la trampa clásica que vigila el test «lo que se apaga con
   hidden se apaga de verdad»). */
.tb-card[hidden] { display: none; }
.tb-card.tb-dragging { opacity: .45; }
.tb-card-titulo { font-size: var(--fs-base); line-height: 1.35; word-break: break-word; }
.tb-card-tags { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-bottom: calc(5px * var(--sp-scale, 1)); }
/* CONTRASTE (a11y 2026-07-25) — el color va al FONDO y al BORDE, nunca al texto.
   Texto de color sobre su propio color al 16% daba 3.4-3.8:1 en oscuro y hasta
   2.2:1 en claro (naranja/cian/amarillo del tema claro no llegan a 4.5:1 ni
   sobre blanco puro). Con --text el mismo componente da >12:1 en ambos temas y
   la etiqueta se sigue identificando por el lavado + el borde + su propio texto
   (que ES el nombre del color, así que no hay información SOLO por color). */
.tb-tag {
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
  padding: calc(1px * var(--sp-scale, 1)) var(--space-2); border-radius: var(--radius-pill);
  background: rgba(var(--tg-rgb, var(--accent-rgb)), .18); color: var(--text);
  border: 1px solid rgba(var(--tg-rgb, var(--accent-rgb)), .5);
}
.tb-card-foot { display: flex; align-items: center; gap: var(--space-2); margin-top: calc(6px * var(--sp-scale, 1)); flex-wrap: wrap; }
.tb-chip {
  display: inline-flex; align-items: center; gap: calc(3px * var(--sp-scale, 1));
  font-size: var(--fs-2xs); font-weight: 650; color: var(--text2);
  font-variant-numeric: tabular-nums;
}
/* Fecha límite: misma familia de tokens de estado que el Rondín, pero el estado
   NO se comunica solo con color (WCAG 1.4.1): el JS cambia el GLIFO del icono
   (alert-triangle = vencida · clock = hoy/pronto · calendar = el resto) y el
   texto queda en --text. Sobre --card2 el rojo daba 4.42:1 en oscuro y el
   naranja 2.50:1 en claro — ninguno de los dos llega a AA como texto. */
.tb-chip.due-vencida, .tb-chip.due-hoy, .tb-chip.due-pronto {
  color: var(--text); border-radius: var(--radius-pill);
  padding: 0 var(--space-2); font-weight: 700;
}
/* LED encendido (pase premium 2026-07-29): halo suave del color de estado.
   DECORATIVO — el estado sigue viajando en glifo + texto (WCAG 1.4.1); por
   eso la opacidad es baja y no hay información nueva en la luz. */
.tb-chip.due-vencida { background: rgba(var(--red-rgb), .18); border: 1px solid rgba(var(--red-rgb), .5); box-shadow: 0 0 8px rgba(var(--red-rgb), .30); }
.tb-chip.due-hoy, .tb-chip.due-pronto { background: rgba(var(--orange-rgb), .18); border: 1px solid rgba(var(--orange-rgb), .5); box-shadow: 0 0 8px rgba(var(--orange-rgb), .22); }
/* Prioridad P1–P4 (2026-07-29, modelo Todoist). MISMO criterio de contraste
   que la fecha: el color va al fondo/borde, el texto («P1») queda en --text y
   viaja junto al color (WCAG 1.4.1). P4 = baja no lleva lavado: es el estado
   tranquilo y pintarlo lo haría parecer especial. */
.tb-chip.tb-prio-1, .tb-chip.tb-prio-2, .tb-chip.tb-prio-3, .tb-chip.tb-prio-4 {
  color: var(--text); border-radius: var(--radius-pill);
  padding: 0 var(--space-2); font-weight: 700;
}
.tb-chip.tb-prio-1 { background: rgba(var(--red-rgb), .18); border: 1px solid rgba(var(--red-rgb), .5); box-shadow: 0 0 8px rgba(var(--red-rgb), .22); }
.tb-chip.tb-prio-2 { background: rgba(var(--orange-rgb), .18); border: 1px solid rgba(var(--orange-rgb), .5); }
.tb-chip.tb-prio-3 { background: rgba(var(--accent-rgb), .16); border: 1px solid rgba(var(--accent-rgb), .5); }
.tb-chip.tb-prio-4 { background: transparent; border: 1px solid var(--border2); color: var(--text2); }
.tb-avatars { display: flex; gap: calc(3px * var(--sp-scale, 1)); margin-left: auto; }
.tb-av {
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .02em;
  background: var(--accent-soft); color: var(--text); border: 1px solid var(--accent-border);
}
/* «Yo» se marca con ANILLO, no invirtiendo el relleno: el acento es editable
   desde el Editor UI, así que texto sobre --accent no tiene contraste garantizado
   (con el azul del tema oscuro, blanco da 3.66:1 y --bg en claro 4.46:1). */
.tb-av.tb-av-yo { border: 2px solid var(--accent); background: var(--accent-soft); }
/* Barra de progreso como CÁPSULA (pase premium 2026-07-29): más gruesa
   (8px = --space-2), radio completo y degradado sutil hacia el acento — la
   percepción táctil sube sin tocar la información. El degradado usa el token
   editable (--accent-rgb), así que sigue al Editor UI y a ambos temas. */
.tb-prog { height: var(--space-2); border-radius: var(--radius-pill); background: var(--wash-2); border: 1px solid var(--border); overflow: hidden; margin-top: calc(6px * var(--sp-scale, 1)); }
.tb-prog > i { display: block; height: 100%; background: linear-gradient(90deg, rgba(var(--accent-rgb), .65), var(--accent)); border-radius: var(--radius-pill); }

/* ── Detalle de tarjeta ─────────────────────────────────────────── */
.tb-det { display: flex; flex-direction: column; gap: var(--space-3); }
.tb-det .field { margin-bottom: 0; }
/* `.tb-det-grid`, `.tb-pickers` y `.tb-pick` se retiraron el 2026-07-25: los
   selectores de etiqueta y responsable dejaron de vivir en el cuerpo del
   detalle y pasaron a los popovers de la fila de acciones (`.tb-lbl-sw` y
   `.tb-mem`). Cero referencias en `modules/` — CSS muerto no es inofensivo:
   es la próxima clase que alguien copia creyendo que es el patrón vigente. */
.tb-bcard-open:focus-visible, .tb-bcard-new:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.tb-check { display: flex; align-items: center; gap: var(--space-2); }
.tb-check-txt { flex: 1; font-size: var(--fs-base); }
.tb-check.done .tb-check-txt { text-decoration: line-through; color: var(--text3); }
.tb-coms { display: flex; flex-direction: column; gap: calc(9px * var(--sp-scale, 1)); }
.tb-com { border-left: 2px solid var(--border); padding-left: var(--space-3); }
.tb-com-meta { font-size: var(--fs-2xs); color: var(--text3); margin-bottom: calc(2px * var(--sp-scale, 1)); }
.tb-com-txt { font-size: var(--fs-sm); white-space: pre-wrap; word-break: break-word; }
.tb-empty { font-size: var(--fs-sm); color: var(--text3); }

/* ── Avisos ─────────────────────────────────────────────────────── */
/* Cada aviso es un `.btn.btn-secondary.btn-sm.btn-block` del núcleo (lleva a
   SU tarjeta), así que aquí solo hace falta la pila. Las reglas `.tb-aviso` /
   `.tb-aviso-tipo` / `.t-vencida` del primer boceto quedaron sin usar cuando
   los avisos pasaron de <div> a botón, y se retiraron el 2026-07-25. */
.tb-avisos { display: flex; flex-direction: column; gap: calc(6px * var(--sp-scale, 1)); }

/* ── Botón de retroceso «Todos los tableros» (pase premium 2026-07-29) ──
   Sin recuadro contenedor: chevron + texto puros, con un cambio de opacidad
   muy sutil al hover. CONSERVA `.btn.btn-sm` (regla del productor: el TAMAÑO
   de los botones es global) — aquí solo se apaga el chrome, no la caja de
   golpe ni el foco visible. */
.tb-back { background: transparent; border-color: transparent; opacity: .72; gap: calc(3px * var(--sp-scale, 1)); }
.tb-back:hover { background: transparent; border-color: transparent; opacity: 1; color: var(--text); }

/* ── Breadcrumb Herramientas / Tareas / {tablero} (2026-07-29, C2) ──
   Un solo rastro de navegación a la izquierda, un nivel a la vez. El <h1>
   sigue siendo el título de la vista (y presta su nombre a #tb-cols vía
   aria-labelledby); las migas son .btn.btn-sm con el chrome apagado
   (.tb-back), nunca padding inline (regla del productor). */
.tb-crumbs { display: flex; align-items: center; gap: var(--space-1); min-width: 0; }
.tb-crumbs h1 { margin: 0 0 0 calc(6px * var(--sp-scale, 1)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tb-crumb-sep { color: var(--text3); font-size: var(--fs-md); user-select: none; }
/* Jerarquía moderada (decisión del productor 2026-07-29): las migas suben a
   13px (solo el TEXTO — padding/altura siguen siendo los globales de
   .btn-sm, regla del productor) y, con un tablero abierto (.tb-nivel, lo
   pone TB._migas), el <h1> baja de 22px a 16px semibold: es el último nivel
   de una ruta, no el título suelto de una página. En el índice no hay
   .tb-nivel y «Tareas» conserva los 22px de .page-header h1, como todas
   las demás páginas. */
.tb-crumbs .tb-back { font-size: var(--fs-md); }
.tb-crumbs.tb-nivel h1 {
  font-size: calc(16px * var(--fs-scale, 1)); font-weight: 600; letter-spacing: -0.3px;
}

/* ── Filtro/búsqueda del tablero (2026-07-29, C3) ────────────────── */
/* Chips P1–P4 + «Mías» + lupa que expande la caja. La caja es el patrón
   canónico .search-box del DS (Projects/Artistas/Rondín); aquí solo se le
   quita el margen de columna, porque el encabezado es una fila. Tamaños del
   DS: nada de height hardcodeada (regla del productor: tamaño GLOBAL). */
.tb-filtros { display: inline-flex; align-items: center; gap: var(--space-2); }
/* La lupa Y la caja son UN solo control (pedido del productor 2026-07-29):
   colapsado se ve como el botón de icono de siempre (30px, sin chrome, como
   .btn-icon.btn-ghost); con `.open` el MISMO contenedor se ensancha a 200px
   con transición y aparece el campo. La caja base ES un .search-box del DS;
   aquí pierde el margen de columna (el encabezado es una fila).
   NOTA sobre la regla «no animar width» (§6): esa regla es para HOVER (el
   puntero provoca reflow en cadena y parpadea); aquí es un gesto DISCRETO de
   clic entre dos anchos fijos, el patrón clásico del buscador expandible.
   overflow:hidden para que el campo no «flote» fuera mientras crece. */
.tb-buscador {
  margin-bottom: 0; width: 200px; overflow: hidden; flex-wrap: nowrap;
  transition: width .2s ease, background .2s ease, border-color .2s ease,
    padding .2s ease;
}
.tb-buscador input {
  min-width: 0;                       /* deja encoger el flex item al colapsar */
  opacity: 1; transition: opacity .15s ease .05s;
}
/* La lupa es un botón SIN chrome propio: el contenedor pone la caja. El
   margen negativo + padding espejo extienden su ÁREA DE CLIC sobre el padding
   del contenedor: colapsado, el objetivo es el control completo (30px), no
   el glifo de 14 (WCAG 2.5.8). */
.tb-lupa {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; background: none; border: 0;
  margin: calc(-6px * var(--sp-scale, 1)) calc(-8px * var(--sp-scale, 1));
  padding: calc(6px * var(--sp-scale, 1)) var(--space-2);
  color: var(--text3); cursor: pointer; font: inherit;
}
.tb-lupa:hover { color: var(--text); }
.tb-lupa:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-xs); }
/* Colapsado: solo la lupa, sin fondo ni borde — indistinguible de un
   .btn-icon.btn-ghost (30px del núcleo). El padding vertical se conserva
   para que el alto no cambie entre estados. */
.tb-buscador:not(.open) {
  width: 30px; background: transparent; border-color: transparent;
  padding-left: var(--space-2); padding-right: var(--space-2);
  cursor: pointer;
}
.tb-buscador:not(.open) input { opacity: 0; transition: opacity .1s ease; }
.tb-buscador.open .tb-lupa { color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .tb-buscador, .tb-buscador input { transition: none; }
}

/* ── Estados de carga del Tablero (auditoría 2026-07-29, H8/A8) ──
   Siluetas con el shimmer `.skeleton` del núcleo: tarjetas de tablero en el
   índice, columnas en el board. Nada interactivo; aria-busy hace el anuncio. */
.tb-skel { display: flex; flex-direction: column; gap: var(--space-4); }
.tb-skel-bcard { height: calc(150px * var(--sp-scale, 1)); border-radius: var(--radius-sm); }
.tb-cols.tb-skel { flex-direction: row; }
.tb-skel-col {
  flex: 0 0 calc(270px * var(--sp-scale, 1));
  height: calc(220px * var(--sp-scale, 1));
  border-radius: var(--radius-sm);
}

/* ── Alta de lista en la columna fantasma (auditoría 2026-07-29, H10) ──
   Composer inline: campo + Añadir/Cancelar donde va a nacer la lista. El
   input hereda el estilo de `.field input` del núcleo. */
.tb-lista-alta { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: 0; }
.tb-lista-alta-f { display: flex; gap: var(--space-2); }

/* ── Botón «Añadir» del detalle (auditoría 2026-07-29, H9) ──
   Duplica la fila de acciones que tiene al lado; solo existe donde la fila
   no cabe (pantallas angostas — iPhone y ventanas partidas). */
.tb-act-add { display: none; }
@media (max-width: 640px) { .tb-act-add { display: inline-flex; } }
/* El interruptor «Mías» y la lupa activos: mismo trato que los segmentos. */
.tb-filtros .btn.active { border-color: var(--accent); color: var(--accent); }
@media (max-width: 820px) { .tb-buscador { width: 140px; } }

/* ── Menú contextual del tablero y de la lista (2026-07-29, C4) ──
   Compacto y anclado a su kebab, con el look del .split-menu-panel del
   núcleo. position:fixed y colgado de <body>: sobrevive al repintado del
   encabezado (polling cada 12 s) y a los kebabs al fondo del scroll. */
.tb-menu {
  position: fixed; z-index: var(--z-menu); min-width: 210px;
  padding: calc(5px * var(--sp-scale, 1));
  background: var(--card); border: 1px solid var(--border2);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-modal);
  display: flex; flex-direction: column; gap: calc(2px * var(--sp-scale, 1));
}
.tb-menu-item {
  display: flex; align-items: center; gap: calc(9px * var(--sp-scale, 1));
  padding: var(--space-2) calc(10px * var(--sp-scale, 1));
  border: none; border-radius: var(--radius-xs); background: transparent;
  color: var(--text); cursor: pointer; font-family: inherit;
  font-size: var(--fs-md); text-align: left;
}
.tb-menu-item:hover, .tb-menu-item:focus-visible { background: var(--wash-3); }
.tb-menu-item svg { flex-shrink: 0; color: var(--text2); }
.tb-menu-danger { color: var(--red); }
.tb-menu-danger svg { color: var(--red); }

/* ── Línea de inserción del arrastre (2026-07-29, A4) ──
   Marca el hueco EXACTO donde caerá la tarjeta (misma lógica que el drop).
   Absoluta para no entrar al flujo: insertarla entre tarjetas las empujaría
   y el cálculo del vecino oscilaría bajo el cursor. */
.tb-drop-line {
  position: absolute; left: var(--space-3); right: var(--space-3);
  height: 3px; border-radius: 2px; background: var(--accent);
  pointer-events: none; z-index: 1;
}

/* Lista de destinos de «Mover» y del menú de lista: la separación va aquí, no
   con un margin-bottom inline por botón (regla §6: inline solo para dinámicos). */
.tb-move-list { display: flex; flex-direction: column; gap: var(--space-2); }
.tb-move-list > p { margin-bottom: var(--space-1); }

@media (max-width: 820px) {
  /* En móvil las columnas ocupan casi toda la pantalla: el scroll horizontal
     por columna es el gesto natural, igual que en la app de Trello. */
  .tb-cols { padding-left: var(--space-4); padding-right: var(--space-4); }
  .tb-col { width: 82vw; max-width: 300px; }
  #tb-index { padding-left: var(--space-4); padding-right: var(--space-4); }
}

/* Objetivos táctiles (iPad/iPhone). Solo en punteros gruesos: en escritorio
   una píldora de 44px de alto rompería la densidad del detalle. Los .btn del
   núcleo NO se tocan (regla §6: su tamaño es global). */
@media (pointer: coarse) {
  .tb-check { min-height: 44px; }
  .tb-check input[type="checkbox"] { width: 20px; height: 20px; }
}

/* ══════════════════════════════════════════════════════════════════
   TAREAS · v2 (2026-07-25) — creación de tablero con fondo y visibilidad,
   círculo de completada y edición rápida en la tarjeta.
   Los fondos son TOKENS, no hex: un lavado sobre --bg que se adapta solo al
   tema claro/oscuro y a las escalas del Editor UI.
   ══════════════════════════════════════════════════════════════════ */

/* ── Fondo del tablero ── */
#tb-board { background: rgba(var(--tb-bg-rgb, var(--accent-rgb)), .05); }
/* La columna hereda el mismo matiz para que no flote sobre el lavado */
#tb-board .tb-col { background: var(--card); }

/* ── Selector de fondo del modal de creación ── */
.tb-fondos { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.tb-fondo {
  width: 34px; height: 34px; border-radius: var(--radius-xs); cursor: pointer;
  background: rgba(var(--tg-rgb, var(--accent-rgb)), .35);
  border: 1px solid rgba(var(--tg-rgb, var(--accent-rgb)), .55);
  position: relative; padding: 0;
}
.tb-fondo:hover { border-color: var(--tg, var(--accent)); }
/* La selección NO viaja solo en el borde (WCAG 1.4.1): se dibuja una palomita.
   CONTRASTE (a11y 2026-07-25): la palomita se dibuja con bordes en --text y a
   .75 se perdía sobre el propio lavado — 2.13:1 con el amarillo, 2.54:1 con el
   cian, 2.93:1 con el verde en tema oscuro, por debajo del 3:1 que pide WCAG
   1.4.11 para un gráfico que ES la única marca de estado. A .55 el peor caso
   sube a 3.40:1 y el escalón contra el .35 sin pulsar se sigue viendo. */
.tb-fondo[aria-pressed="true"] {
  background: rgba(var(--tg-rgb, var(--accent-rgb)), .55);
  border-color: var(--tg, var(--accent));
}
.tb-fondo[aria-pressed="true"]::after {
  content: ""; position: absolute; left: 50%; top: 46%;
  width: 11px; height: 6px; margin: -6px 0 0 -6px;
  border-left: 2.2px solid var(--text); border-bottom: 2.2px solid var(--text);
  transform: rotate(-45deg);
}
.tb-fondo:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── Selector de visibilidad ── */
.tb-viss { display: flex; flex-direction: column; gap: var(--space-2); }
.tb-vis {
  display: grid; grid-template-columns: auto 1fr; gap: 0 var(--space-2);
  align-items: center; text-align: left; cursor: pointer;
  /* --wash-1 y no --wash-2: sobre wash-2 la descripción en --text2 medía
     4.49:1 en tema claro — a una centésima de AA, que es fallar. Con wash-1
     sube a 4.70:1 sin tocar el color del texto ni la jerarquía. */
  background: var(--wash-1); border: 1px solid var(--border);
  border-radius: var(--radius-xs); padding: var(--space-2) var(--space-3);
  color: var(--text2);
}
.tb-vis:hover { border-color: var(--border2); }
.tb-vis[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent-border); color: var(--text); }
.tb-vis svg { grid-row: span 2; }
.tb-vis-t { font-size: var(--fs-base); font-weight: 650; color: var(--text); }
/* --text2, NO --text3: sobre un lavado el text3 se queda en 3.87:1 (oscuro) y
   4.20:1 (claro) — por debajo del 4.5:1 de AA (§7). Con text2 sobre --wash-1
   da 5.88:1 (oscuro) y 4.70:1 (claro). En el estado seleccionado el fondo
   cambia a --accent-soft y ahí se pasa a --text (12.49:1 / 14.71:1). */
.tb-vis-d { font-size: var(--fs-xs); color: var(--text2); }
.tb-vis[aria-pressed="true"] .tb-vis-d { color: var(--text); }
.tb-vis:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── Tarjeta: círculo de completada y edición rápida ── */
.tb-card-main {
  flex: 1; min-width: 0; text-align: left; cursor: pointer; display: block;
  background: none; border: 0; padding: 0; color: inherit; font: inherit;
}
.tb-card-check, .tb-card-edit {
  flex: 0 0 auto; cursor: pointer; padding: 0; background: none; border: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; color: var(--text3);
}
.tb-card-check:hover, .tb-card-edit:hover { background: var(--wash-3); color: var(--text); }
.tb-card-check[aria-pressed="true"] { color: var(--green); }
/* El lápiz solo asoma con el puntero encima, PERO también con el foco de
   teclado: un botón invisible y funcional es peor que no tenerlo. */
.tb-card-edit { opacity: 0; transition: opacity var(--dur-micro); }
.tb-card:hover .tb-card-edit,
.tb-card-edit:focus-visible { opacity: 1; }
.tb-card-main:focus-visible, .tb-card-check:focus-visible, .tb-card-edit:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
/* Completada: se tacha y se apaga, pero sigue legible (no baja de 4.5:1) */
.tb-card.tb-done .tb-card-titulo { text-decoration: line-through; color: var(--text2); }

/* En pantallas táctiles no hay hover: el lápiz se queda siempre visible o no
   habría forma de llegar a él con el dedo. */
@media (pointer: coarse) {
  .tb-card-edit { opacity: 1; }
  .tb-card-check, .tb-card-edit { width: 32px; height: 32px; }
}

/* Candado del tablero privado, pegado al nombre en el índice */
.tb-bcard-name { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); }
.tb-bcard-name svg { flex-shrink: 0; color: var(--text3); }

/* ── Detalle de tarjeta: dos columnas (contenido | conversación) ── */
.tb-det { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.tb-det-main, .tb-det-side { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.tb-det-side { border-left: 1px solid var(--border); padding-left: var(--space-4); }
.tb-det-head { display: flex; align-items: center; gap: var(--space-2); }
.tb-det-head-txt { flex: 1; min-width: 0; }
/* Chevron propio y ancho AJUSTADO al contenido. Con la flecha nativa el
   navegador reserva su propio hueco y el resultado era una píldora con un
   agujero entre el texto y el icono. `width:auto` + `padding-right` medido
   deja los dos pegados y centrados, como el resto de píldoras de la app. */
.tb-det-head select {
  -webkit-appearance: none; appearance: none;
  background-color: var(--wash-2);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23909096' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--space-2) center;
  border: 1px solid var(--border2); border-radius: var(--radius-pill);
  color: var(--text); font-size: var(--fs-sm); font-weight: 650; font-family: inherit;
  padding: var(--space-1) var(--space-6) var(--space-1) var(--space-3);
  width: auto; max-width: 100%; outline: none; cursor: pointer;
}
.tb-det-head select:hover { border-color: var(--accent-border); }
.tb-det-head select:focus-visible { border-color: var(--accent); outline: 2px solid var(--accent); outline-offset: 1px; }
.tb-det-head .tb-card-check { width: 26px; height: 26px; }
/* Fila de acciones: Etiquetas · Fechas · Checklist · Responsables */
.tb-acts { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-2); }
.tb-act { display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1)); }

/* En pantallas estrechas la conversación baja debajo del contenido: dos
   columnas de 300px no caben y partirlas hace ilegibles las dos. */
@media (max-width: 900px) {
  .tb-det { grid-template-columns: 1fr; }
  .tb-det-side { border-left: 0; border-top: 1px solid var(--border); padding-left: 0; padding-top: var(--space-4); }
}

/* Actividad dentro del feed de la tarjeta: es un hecho del sistema, no algo
   que alguien escribió. Mismo bloque, borde y tono más tenues. */
.tb-com.tb-evento { border-left-color: var(--border2); }
.tb-com.tb-evento .tb-com-txt { color: var(--text2); font-size: var(--fs-xs); }

/* ══════════════════════════════════════════════════════════════════
   TAREAS · v3 (2026-07-25) — índice en secciones (Workspace / Your boards),
   borrado permanente, animación de la tarjeta al pasar el mouse.
   ══════════════════════════════════════════════════════════════════ */

/* ── Índice por secciones ── */
.tb-sec { margin-bottom: calc(26px * var(--sp-scale, 1)); }
.tb-sec-h {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-md); font-weight: 650; color: var(--text);
  margin-bottom: var(--space-3);
}
.tb-sec-h svg { color: var(--text3); flex-shrink: 0; }

/* Tarjeta de tablero: cabecera de color + cuerpo, como la maqueta. El color
   es un lavado del token, no un hex: se adapta solo al tema claro/oscuro. */
.tb-bcard:hover .tb-bcard-top { filter: brightness(1.12); }
.tb-bcard-open {
  display: block; width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; padding: 0; color: inherit; font: inherit;
}
.tb-bcard-top {
  display: block; height: calc(64px * var(--sp-scale, 1));
  background: rgba(var(--tg-rgb, var(--accent-rgb)), .30);
  border-bottom: 1px solid var(--border);
  transition: filter var(--dur-fast);
}
.tb-bcard-body {
  display: flex; flex-direction: column; gap: var(--space-1);
  padding: var(--space-3) var(--space-4) var(--space-4);
}
/* Borrar: solo asoma con el puntero encima o con el foco de teclado. Un botón
   destructivo permanentemente visible se pulsa sin querer. */
.tb-bcard-del {
  position: absolute; top: var(--space-2); right: var(--space-2);
  width: 26px; height: 26px; border-radius: var(--radius-xs); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--card); border: 1px solid var(--border); color: var(--text2);
  opacity: 0; transition: opacity var(--dur-fast), color var(--dur-micro), border-color var(--dur-micro);
}
.tb-bcard:hover .tb-bcard-del, .tb-bcard-del:focus-visible { opacity: 1; }
.tb-bcard-del:hover { color: var(--red); border-color: var(--red); }
.tb-bcard-del:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Tarjeta «Create new board»: mismo tamaño que las demás, tratamiento de hueco */
.tb-bcard-new {
  display: flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: calc(120px * var(--sp-scale, 1)); cursor: pointer;
  background: var(--wash-2); border: 1px dashed var(--border2); border-radius: var(--radius-sm);
  /* --text, no --text2: sobre el lavado y el lienzo del índice el text2 se
     queda en 4.26:1 en tema claro (falla AA). Además es una acción primaria:
     apagarla no la hacía más discreta, la hacía menos legible. */
  color: var(--text); font-size: var(--fs-base); font-weight: 600; font-family: inherit;
  transition: background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
}
.tb-bcard-new:hover { background: var(--wash-3); color: var(--text); border-color: var(--accent); }

/* ── Tarjeta de tarea: los controles solo con el puntero encima ──
   El título se desplaza a la derecha para hacerle sitio al círculo, y el
   lápiz entra desde la derecha. Con `prefers-reduced-motion` el bloque global
   de app.css anula las transiciones: los botones siguen apareciendo, sin
   movimiento. Y con `:focus-within` aparecen también para quien navega con
   teclado — si no, tendría dos botones invisibles pero enfocables. */
/* OJO (a11y 2026-07-25): el selector va con `>` y anclado a `.tb-card` A
   PROPÓSITO. Escrito como `.tb-card-check` a secas, el colapso (width:0 +
   flex-basis:0 + opacity:0) alcanzaba TAMBIÉN al círculo del encabezado del
   detalle (`.tb-det-head .tb-card-check`): ahí no hay `.tb-card` que haga
   :hover, así que el botón se quedaba a cero de ancho e invisible — un
   control funcional que no se ve, que es justo lo que el resto de este
   bloque se esfuerza en evitar. `.tb-det-head .tb-card-check` sí ganaba el
   `width`, pero en un contenedor flex manda `flex-basis`, y esa venía de la
   regla sin anclar. */
/* CANALONES FIJOS, no ancho animado (recomendación del pase UI/UX, aplicada).
   Animar `width`/`flex-basis` de los controles le quitaba 22px al título
   MIENTRAS dura el hover: con un título de dos líneas, una palabra envuelve,
   la tarjeta crece de alto, empuja a las de abajo y el puntero puede salirse
   de la tarjeta → parpadeo. Aquí el hueco de los dos controles está SIEMPRE
   reservado con padding, los botones van en posición absoluta dentro de él y
   lo único que se anima es `opacity` + `translateX`: cero reflow, el mismo
   efecto de «el título se corre para hacerles sitio». */
.tb-card { position: relative; padding-left: calc(30px * var(--sp-scale, 1)); padding-right: calc(28px * var(--sp-scale, 1)); }
.tb-card > .tb-card-check,
.tb-card > .tb-card-edit {
  /* top acompaña al padding vertical de la tarjeta (12px desde el pase
     premium): con el valor viejo de 6px los controles quedaban descolgados
     por encima de la primera línea del título. */
  position: absolute; top: calc(10px * var(--sp-scale, 1));
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-fast), transform var(--dur-fast) var(--ease-out);
}
.tb-card > .tb-card-check { left: var(--space-2); transform: translateX(-4px); }
.tb-card > .tb-card-edit { right: var(--space-2); transform: translateX(4px); }
/* `:focus-within` además de `:hover`: quien navega con Tab tendría si no dos
   botones invisibles pero enfocables, que es peor que no tenerlos. Y una
   tarjeta ya completada muestra su círculo siempre: es el estado, no un
   control que aparece y desaparece. */
.tb-card:hover > .tb-card-check,
.tb-card:focus-within > .tb-card-check,
.tb-card.tb-done > .tb-card-check,
.tb-card:hover > .tb-card-edit,
.tb-card:focus-within > .tb-card-edit {
  opacity: 1; pointer-events: auto; transform: translateX(0);
}

/* En táctil no hay hover: los controles se quedan siempre a la vista o no
   habría forma de llegar a ellos con el dedo. */
@media (pointer: coarse) {
  .tb-card { padding-left: var(--space-8); padding-right: calc(38px * var(--sp-scale, 1)); }
  .tb-card > .tb-card-check, .tb-card > .tb-card-edit {
    opacity: 1; pointer-events: auto; transform: none; width: 32px; height: 32px;
  }
}

/* ── Popovers de la fila de acciones (Add / Labels / Dates / Checklist /
   Members). Anclados bajo la fila, NO modales: un diálogo dentro de otro es
   una trampa de foco. El host es relativo para posicionarlos. ── */
.tb-pop-host { position: relative; }
.tb-pop {
  position: absolute; top: 0; left: 0; width: 300px; max-width: 100%;
  z-index: var(--z-popover);
  background: var(--card2); border: 1px solid var(--border2);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-pop);
  display: flex; flex-direction: column; max-height: calc(360px * var(--sp-scale, 1));
}
.tb-pop-h {
  display: flex; align-items: center; justify-content: center; position: relative;
  padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--border);
  font-size: var(--fs-base); font-weight: 650; color: var(--text);
}
.tb-pop-h .close-btn { position: absolute; right: var(--space-2); top: 50%; transform: translateY(-50%); }
.tb-pop-b { padding: var(--space-4); overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-2); }
.tb-pop-b input, .tb-pop-b select, .tb-pop-b textarea {
  background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-xs);
  color: var(--text); font-size: var(--fs-base); font-family: inherit;
  padding: calc(6px * var(--sp-scale, 1)) var(--space-2); outline: none; width: 100%;
}
.tb-pop-b input:focus, .tb-pop-b select:focus { border-color: var(--accent); }
/* CONTRASTE (a11y 2026-07-25): --text3 vive medido contra --card/--bg, pero el
   popover se dibuja sobre --card2, que es MÁS claro en oscuro y más gris en
   claro: ahí el mismo token cae a 4.14:1 (oscuro) y 4.31:1 (claro). Todo el
   texto del popover pasa a --text2 → 5.85:1 / 4.61:1. */
.tb-pop-sub { font-size: var(--fs-2xs); font-weight: 700; color: var(--text2);
  text-transform: uppercase; letter-spacing: var(--tracking-overline); }
.tb-pop-nota { font-size: var(--fs-2xs); color: var(--text2); line-height: 1.45; }

/* «Add to card»: icono + título + descripción, como la maqueta */
.tb-pop-item {
  display: flex; align-items: flex-start; gap: var(--space-3); width: 100%; cursor: pointer;
  background: none; border: 0; padding: var(--space-2); border-radius: var(--radius-xs);
  color: var(--text); font-family: inherit; text-align: left;
}
.tb-pop-item:hover { background: var(--wash-3); }
.tb-pop-item svg { margin-top: calc(2px * var(--sp-scale, 1)); color: var(--text2); flex-shrink: 0; }
.tb-pop-it { display: flex; flex-direction: column; }
.tb-pop-t { font-size: var(--fs-base); font-weight: 650; }
.tb-pop-d { font-size: var(--fs-2xs); color: var(--text2); }
/* Con el puntero encima el fondo sube a --wash-3 y ahí --text2 se queda en
   3.86:1 en tema claro: la descripción pasa a --text mientras dura el hover. */
.tb-pop-item:hover .tb-pop-d, .tb-pop-item:focus-visible .tb-pop-d { color: var(--text); }

/* Etiquetas: barra de color con su nombre + lápiz para renombrar */
.tb-lbls { display: flex; flex-direction: column; gap: calc(6px * var(--sp-scale, 1)); }
.tb-lbl-row { display: flex; align-items: center; gap: var(--space-2); }
.tb-lbl-sw {
  flex: 1; min-width: 0; height: calc(30px * var(--sp-scale, 1)); cursor: pointer;
  border-radius: var(--radius-xs); text-align: left; padding: 0 var(--space-3);
  background: rgba(var(--tg-rgb, var(--accent-rgb)), .30);
  border: 1px solid rgba(var(--tg-rgb, var(--accent-rgb)), .55);
  color: var(--text); font-size: var(--fs-sm); font-weight: 650; font-family: inherit;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; position: relative;
}
/* CONTRASTE (a11y 2026-07-25) — el lavado del estado pulsado era .60 y ahí el
   NOMBRE de la etiqueta (en --text) caía a 2.89:1 con el amarillo, 3.39:1 con
   el cian, 3.85:1 con el verde y 3.90:1 con el naranja en tema oscuro: por
   debajo de AA justo en el estado que más se mira. Con .42 el peor caso sube a
   4.52:1 y el estado se sigue distinguiendo por el tono MÁS el borde MÁS la
   palomita de abajo (nunca solo por color, WCAG 1.4.1). */
.tb-lbl-sw[aria-pressed="true"] {
  background: rgba(var(--tg-rgb, var(--accent-rgb)), .42);
  border-color: rgba(var(--tg-rgb, var(--accent-rgb)), .9);
}
/* La selección no puede viajar solo en el tono (WCAG 1.4.1): va una palomita */
.tb-lbl-sw[aria-pressed="true"]::after {
  content: ""; position: absolute; right: var(--space-3); top: 50%;
  width: 10px; height: 5px; margin-top: -4px;
  border-left: 2px solid var(--text); border-bottom: 2px solid var(--text);
  transform: rotate(-45deg);
}
.tb-lbl-sw:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Miembros */
.tb-mems { display: flex; flex-direction: column; gap: calc(3px * var(--sp-scale, 1)); }
.tb-mem {
  display: flex; align-items: center; gap: var(--space-2); width: 100%; cursor: pointer;
  background: none; border: 0; padding: var(--space-2); border-radius: var(--radius-xs);
  color: var(--text); font-size: var(--fs-base); font-family: inherit; text-align: left;
}
.tb-mem:hover { background: var(--wash-3); }
.tb-mem-n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tb-mem svg { opacity: 0; color: var(--green); flex-shrink: 0; }
.tb-mem[aria-pressed="true"] svg { opacity: 1; }
.tb-mem:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ── Resumen de la tarjeta (lo que ya tiene, a la vista) ── */
.tb-resumen { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-bottom: var(--space-2); }
.tb-res-b { display: flex; flex-direction: column; gap: var(--space-1); }
.tb-res-t { font-size: var(--fs-2xs); font-weight: 700; color: var(--text3);
  text-transform: uppercase; letter-spacing: var(--tracking-overline); }
.tb-res-c { display: flex; align-items: center; gap: var(--space-1); flex-wrap: wrap; }

/* ── Quick-add: resaltado de la fecha detectada DENTRO del input (2026-07-28) ──
   Un <input> no puede colorear un tramo de su propio texto, así que encima
   lleva un ESPEJO con el mismo texto y la misma métrica (fuente/padding/borde
   los copia JS del estilo computado): el texto del espejo es transparente y
   solo se ve la píldora sobre la frase detectada. pointer-events: none — el
   input de abajo sigue recibiendo todo. */
.tb-qa-wrap { position: relative; }
.tb-qa-wrap input { width: 100%; }
.tb-qa-mirror {
  position: absolute; inset: 0; overflow: hidden;
  pointer-events: none; color: transparent;
}
.tb-qa-mirror-in {
  white-space: pre; display: inline-block; min-width: 100%; box-sizing: border-box;
}
/* La píldora: un lavado del acento con radio; translúcida a propósito, el
   texto REAL del input se lee a través de ella en los dos temas. */
.tb-qa-hl {
  background: rgba(var(--accent-rgb), .18);
  border-radius: var(--radius-xs);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb), .18);
}

/* ── Bloque de checklist ── */
/* Bloque de checklist: envoltorio propio para separarlo del resto de campos */
.tb-chk { gap: var(--space-2); }
.tb-chk-h { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.tb-chk-h label { margin: 0; }
.tb-chk-acts { display: flex; gap: var(--space-2); }
.tb-chk-bar { display: flex; align-items: center; gap: var(--space-2); }
/* «NN%» como número de impacto: peso 700, tono atenuado (jerarquía premium). */
.tb-chk-pct { font-size: var(--fs-2xs); font-weight: 700; color: var(--text2); font-variant-numeric: tabular-nums;
  min-width: calc(30px * var(--sp-scale, 1)); }
.tb-chk-bar .tb-prog { flex: 1; margin-top: 0; }
.tb-check-meta { display: flex; align-items: center; gap: var(--space-1); margin-left: auto; }
.tb-chk-alta { display: flex; flex-direction: column; gap: var(--space-2); }
.tb-chk-alta-f { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.tb-chk-alta-f select, .tb-chk-alta-f input[type="date"] {
  background: var(--wash-2); border: 1px solid var(--border2); border-radius: var(--radius-xs);
  color: var(--text); font-size: var(--fs-sm); font-family: inherit;
  padding: calc(5px * var(--sp-scale, 1)) var(--space-2); outline: none;
}
.tb-chk-alta-f select:focus, .tb-chk-alta-f input:focus { border-color: var(--accent); }

/* ── `hidden` tiene que GANAR ────────────────────────────────────
   El atributo `hidden` se apaga con `[hidden]{display:none}` de la hoja del
   NAVEGADOR, y cualquier `display` escrito por nosotros le gana. El módulo
   apaga tres cosas con `hidden` y las tres tenían un `display` propio, así que
   ninguna se apagaba de verdad:
     · #tb-board (display:flex) — la vista del tablero NUNCA se ocultaba. Al
       entrar a Tareas, un contenedor vacío con `flex:1` se comía media
       pantalla debajo del índice, y al volver de un tablero sus columnas
       seguían pintadas ahí abajo.
     · #tb-avisos (.field → display:flex) — el hueco de «Para ti» ocupaba sitio
       aunque no hubiera ni un aviso.
     · .tb-mem (display:flex) — el buscador de personas marcaba `hidden` a
       quien no coincidía y no desaparecía nadie: el filtro no filtraba.
   `.report-card-header .nbadge` ya lo evita NO declarando display (ver su nota
   más arriba); estos tres lo necesitan porque su display sí es estructural.
   2026-07-29 (reporte del productor): la MISMA trampa mordió también a
     · #tb-crumb-tareas (.btn → display:inline-flex) — la miga «Tareas» del
       breadcrumb se veía TAMBIÉN en el índice, junto al <h1> «Tareas»: se
       leía doble («Tools Tasks Tasks»).
   (La caja de filtro .tb-buscador ya no se apaga con hidden: lupa y caja son
   un solo control siempre visible que colapsa/expande por clase `.open`.) */
#tb-board[hidden], #tb-avisos[hidden], .tb-mem[hidden],
#tb-crumb-tareas[hidden] { display: none; }

/* Objetivos táctiles de los controles nuevos del popover (heredan la regla de
   la v1: 44px solo con punteros gruesos, para no engordar el escritorio).
   Van DESPUÉS de sus definiciones a propósito: escritas antes, el bloque
   agrupado se colaba como «la regla» del componente en cualquier lectura del
   CSS por selector — incluida la del test de contraste. */
@media (pointer: coarse) {
  .tb-pop-item, .tb-mem, .tb-lbl-sw { min-height: 44px; }
}

/* El encabezado del checklist lleva el NOMBRE que le puso el usuario; el
   contador va aparte para que su RULE de i18n siga haciendo match exacto. */
.tb-chk-cnt { font-size: var(--fs-2xs); color: var(--text2); font-variant-numeric: tabular-nums; margin-left: auto; }
.tb-chk-h .tb-chk-acts { margin-left: var(--space-2); }

/* Encabezado de la columna de conversación: la etiqueta a la izquierda y el
   botón «Log» a la derecha, en la misma línea. */
.tb-side-h { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.tb-side-h label { margin: 0; }

/* ══════════ SEGUIMIENTO DE SHOTS (F2, 2026-07-30) ══════════ */
#page-seguimiento .page-header-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
/* Los <select> se alinean a las métricas de .btn-sm — sin height fijo, que es
   lo que los descuadraba medio píxel contra los botones de al lado. */
#page-seguimiento .seg-select, .seg-fselect {
  padding: calc(5px * var(--sp-scale, 1)) calc(11px * var(--sp-scale, 1));
  border-radius: var(--radius-xs);
  border: 1px solid var(--border); background: var(--bg2); color: var(--text);
  font-size: var(--fs-base); font-family: inherit;
  /* Si aun con el tope el nombre no cabe, se corta con "…" y no a media letra.
     El nombre completo va en el title (lo pone _renderProjSelect). */
  text-overflow: ellipsis;
}
/* (El <select> de "Ordenar por" se retiró el 2026-07-30: ahora es un botón con
   panel, igual que las dimensiones de filtro. Desentonaba contra los botones de
   su misma fila.) */
/* El selector de proyecto lleva NOMBRES DE SHOW, que son texto libre: "UFPE:
   The Continuing Adventures of Cliff Booth" son 44 caracteres y a 220px se
   veía "UFPE: The Continuing Adv…". Un <select> mide lo que su opción MÁS
   LARGA, así que dejarlo crecer hasta un techo hace tres cosas a la vez: los
   estudios con nombres cortos siguen con un control chico, los largos caben
   enteros, y el ancho NO salta al cambiar de proyecto (lo fija la lista, no la
   selección). El suelo evita que con nombres de 5 letras quede un muñón junto
   al botón Sync, y el techo (más lo que puede encogerse hasta el suelo) impide
   que la fila del header se parta en dos renglones.
   NO se baja la tipografía: encoger el texto de un control para "hacer caber"
   es así como una vista se vuelve ilegible sin que nadie sepa cuándo pasó. */
#page-seguimiento .seg-select {
  min-width: calc(150px * var(--sp-scale, 1));
  max-width: calc(340px * var(--sp-scale, 1));
}

/* El contenedor scrolleable va SIN padding propio: el aire lo ponen los hijos.
   Con padding el sticky de abajo solo tapaba la caja de CONTENIDO — las
   tarjetas asomaban por los costados y por la franja de arriba, que es el
   "hueco cortado" que se reportó. Sin padding, el scrollport y el contenido
   empiezan en el mismo punto y la barra puede sangrar de borde a borde. */
#page-seguimiento .page-body { overflow-y: auto; padding: 0; }
#seg-kpis { padding: var(--space-3) var(--space-4) 0; }
#seg-grid { padding: 0 var(--space-4) var(--space-3); }

/* ══ Zona única de filtrado (F3/F4, 2026-07-30) ══
   Sticky: con la tarjeta más chica caben más columnas y se hace más scroll;
   la barra tiene que seguir ahí cuando decides quitar un filtro. */
.seg-fbar {
  position: sticky; top: 0; z-index: var(--z-filter-pop);
  display: flex; flex-direction: column; gap: var(--space-2);
  /* A sangre: el padding lateral que antes ponía .page-body vive AQUÍ, así que
     el fondo y el borde llegan a los dos extremos del scrollport. Antes la
     banda terminaba donde terminaba la caja de contenido y el borde inferior
     se leía como una línea cortada a medias. */
  padding: var(--space-2) var(--space-4) var(--space-3);
  margin-bottom: var(--space-3);
  background: var(--bg); border-bottom: 1px solid var(--border);
  transition: box-shadow var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
/* Despegada del sitio donde nació: gana elevación para que se lea como una
   capa POR ENCIMA de la rejilla. En reposo, un borde limpio basta; una sombra
   permanente sobre contenido que no se está tapando es ruido.
   La clase la pone un IntersectionObserver en seguimiento.js — sin él (jsdom,
   navegador viejo) la barra se queda en su estado de reposo, que es correcto. */
.seg-fbar.pegada { border-bottom-color: var(--border2); box-shadow: var(--shadow-pop); }
.seg-fbar-row  { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.seg-fbar-row2 { gap: var(--space-3); }
.seg-fbar-sep  { flex: 1; }                 /* empuja orden/agrupar a la derecha */
/* .btn es inline-flex: [hidden] por sí solo NO lo oculta. */
.seg-fbar [hidden] { display: none; }
/* Buscador colapsable: la lupa ES la caja. Mismo patrón que .tb-buscador del
   Tablero; se escribe aparte para no acoplar dos vistas por el CSS (la deuda de
   promover el componente al núcleo sigue anotada). */
.seg-buscador {
  margin-bottom: 0; flex-shrink: 0; position: relative;
  display: flex; align-items: center; overflow: hidden;
  width: calc(220px * var(--sp-scale, 1));
  transition: width var(--dur-base) var(--ease-out);
}
.seg-buscador:not(.open) {
  width: calc(30px * var(--sp-scale, 1));
  background: transparent; border-color: transparent; padding: 0;
}
.seg-buscador:not(.open) input { opacity: 0; transition: opacity .1s ease; }
.seg-buscador input { min-width: 0; }
.seg-lupa {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--text3); transition: color var(--dur-micro);
}
.seg-lupa:hover { color: var(--text); }
.seg-lupa:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-xs); }
.seg-buscador.open .seg-lupa { color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .seg-buscador, .seg-buscador input { transition: none; }
}
.seg-fdims   { display: flex; align-items: center; gap: var(--space-1); flex-wrap: wrap; }

/* Botón de dimensión y de agrupar: heredan .btn .btn-sm, CERO métricas propias. */
.seg-fbtn.on, #seg-agrupar.on {
  background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent);
}
/* El botón dice qué está filtrando ("Status: In Progress"), así que su texto
   puede crecer: se trunca en vez de estirar la barra. El valor completo va en
   el title y, sin depender del hover, dentro del propio popover. */
.seg-fbtn-t {
  max-width: calc(150px * var(--sp-scale, 1));
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.seg-fbtn-n {
  margin-left: var(--space-1); padding: 0 var(--space-1);
  border-radius: var(--radius-pill); background: rgba(var(--accent-rgb), .22);
  font-size: var(--fs-2xs); font-weight: 700;
}
.seg-fresumen { margin-left: auto; font-size: var(--fs-sm); color: var(--text2);
                font-variant-numeric: tabular-nums; white-space: nowrap; }
.seg-chipbar  { margin-bottom: 0; }
/* Los chips en cero se atenúan, NO se esconden: si desaparecieran al filtrar
   por otra alerta parecería que el problema dejó de existir. */
.seg-chip-cero { opacity: .45; }

/* Popover de dimensión (uno solo, reposicionado bajo el botón que lo abre) */
.seg-fpop {
  position: absolute; top: 100%; left: 0; z-index: var(--z-filter-pop);
  width: calc(272px * var(--sp-scale, 1)); max-height: 52vh; overflow-y: auto;
  padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2);
  background: var(--card); border: 1px solid var(--border2);
  border-radius: var(--radius); box-shadow: var(--shadow-pop);
}
.seg-fpop-head  { display: flex; align-items: center; gap: var(--space-2); }
.seg-fpop-head .filter-label { margin-bottom: 0; flex: 1; }
.seg-fpop-clear { font-size: var(--fs-xs); color: var(--text3); background: none;
                  border: none; cursor: pointer; padding: 0; }
.seg-fpop-clear:hover, .seg-fpop-clear:focus-visible { color: var(--accent); }
.seg-frango     { display: flex; flex-direction: column; gap: var(--space-1); }
.seg-frango-lbl { font-size: var(--fs-xs); color: var(--text3); }

/* Lista de opciones con buscador, checkbox y contador.
   DEUDA DS declarada: este patrón ya existe como .cal-fs-* (clases globales con
   prefijo de Calendario). Promoverlas al núcleo es lo correcto, pero tocar los
   selectores del Calendario en el mismo commit que estrena esta barra mezcla
   dos riesgos; queda anotado para su propio commit. */
.fs-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.fs-chip {
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill); border: 1px solid var(--border);
  background: var(--wash-2); color: var(--text2);
  font-size: var(--fs-xs); font-family: inherit; cursor: pointer;
  transition: background var(--dur-micro), color var(--dur-micro), border-color var(--dur-micro);
}
.fs-chip:hover { background: var(--wash-3); color: var(--text); }
.fs-chip.active { background: var(--accent-soft); border-color: var(--accent-border); color: var(--accent); }
.fs-search {
  width: 100%; box-sizing: border-box; outline: none;
  padding: calc(6px * var(--sp-scale, 1)) calc(10px * var(--sp-scale, 1));
  background: var(--wash-2); border: 1px solid var(--border);
  border-radius: var(--radius-xs); color: var(--text);
  font-size: var(--fs-sm); font-family: inherit;
  transition: border-color var(--dur-fast);
}
.fs-search:focus { border-color: var(--accent); }
.fs-search::placeholder { color: var(--text3); }
.fs-list { display: flex; flex-direction: column; gap: calc(1px * var(--sp-scale, 1)); }
.fs-item {
  display: flex; align-items: center; gap: calc(7px * var(--sp-scale, 1));
  padding: calc(5px * var(--sp-scale, 1)) calc(6px * var(--sp-scale, 1));
  border-radius: var(--radius-xs); cursor: pointer; font-size: var(--fs-sm);
  transition: background var(--dur-micro);
}
.fs-item:hover { background: var(--wash-2); }
/* Radio del panel de orden: mismo cuerpo que la casilla, redondo y con punto
   en vez de palomita — selección única frente a múltiple, dicho por la forma. */
.fs-item input[type="radio"] {
  width: 13px; height: 13px; flex-shrink: 0; margin: 0;
  appearance: none; -webkit-appearance: none;
  background: var(--wash-3); border: 1.5px solid var(--wash-5);
  border-radius: 50%; cursor: pointer; position: relative; vertical-align: middle;
  transition: background var(--dur-micro), border-color var(--dur-micro);
}
.fs-item input[type="radio"]:hover { background: var(--wash-4); }
.fs-item input[type="radio"]:checked { background: var(--accent); border-color: var(--accent); }
.fs-item input[type="radio"]:checked::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--card);
}
.fs-item input[type="radio"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fs-item-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fs-item-n { color: var(--text3); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }

.seg-kpis { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-3); }
.seg-kpi {
  background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--space-2) var(--space-3); min-width: 150px;
}
.seg-kpi .v { font-size: var(--fs-xl); font-weight: 700; display: block; }
.seg-kpi .l { font-size: var(--fs-xs); color: var(--text3); }

.seg-chipbar { margin-bottom: var(--space-3); }
.seg-chip-n { opacity: .65; font-size: var(--fs-xs); margin-left: 2px; }

/* Tarjeta -10% de ancho (280 → 252) para ganar una columna por pantalla.
   El póster manda la altura, así que esto NO cambia la densidad vertical. */
#page-seguimiento { --seg-card-min: 252px; }
.seg-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--seg-card-min), 1fr));
  gap: var(--space-2); margin-bottom: var(--space-3);
}
/* Los ítems de grid nacen con min-width:auto → sin esto NINGÚN text-overflow
   funciona dentro y un nombre largo ensancha o desborda la tarjeta. */
.seg-card, .seg-card > * { min-width: 0; }
.seg-card { cursor: pointer; padding: var(--space-2); display: flex; flex-direction: column; gap: var(--space-2); }
.seg-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* El borde de la tarjeta lo pinta el NIVEL DE RIESGO (lib/seguimiento-estado),
   no "tiene o no tiene alerta": una toma sin artista y una atrasada tres días
   no son el mismo problema. El color es REDUNDANTE (la píldora de urgencia y
   las píldoras de alerta lo dicen con palabras) — nunca es el único portador. */
.seg-card.r3 { border-color: rgba(var(--red-rgb), .55); }
.seg-card.r2 { border-color: rgba(var(--orange-rgb), .45); }
/* Póster: la imagen manda en la tarjeta (decisión del productor 07-30). El
   contenedor recorta el <a> del thumbnail para que el borde redondeado
   coincida con el de la tarjeta. */
.seg-card-poster { display: block; width: 100%; overflow: hidden; border-radius: var(--radius-xs); }
.seg-card-top { display: flex; align-items: center; gap: var(--space-2); }
.seg-card-id { display: flex; flex-direction: column; gap: calc(2px * var(--sp-scale, 1)); min-width: 0; }
.seg-code { font-weight: 600; font-size: var(--fs-sm); color: var(--text); text-decoration: none; }
.seg-code:hover { color: var(--accent); }
.seg-status { font-size: var(--fs-xs); color: var(--text3); text-transform: uppercase; }
.seg-badges { margin-left: auto; display: flex; gap: var(--space-1); }
.seg-badge { width: 9px; height: 9px; border-radius: 50%; display: inline-block; background: var(--text3); }
.seg-badge-atorado, .seg-badge-vencido { background: var(--red); }
.seg-badge-sinArtista, .seg-badge-sinFecha { background: var(--orange); }
/* "Sin tarea activa" es un problema de flujo, no de asignación: color propio
   para que no se lea como una variante de "Sin artista". */
.seg-badge-sinTareaActiva { background: var(--cyan, var(--accent)); }
.seg-badge-sinProximaEntrega { background: var(--yellow, var(--orange)); }

.seg-bar { height: 8px; border-radius: var(--radius-pill); background: var(--bg3, var(--border)); overflow: hidden; }
.seg-bar.sm { height: 5px; margin-top: 6px; }
.seg-bar-fill { height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--accent), var(--green)); }
.seg-card-meta { display: flex; align-items: baseline; gap: var(--space-2); }
.seg-pct { font-weight: 700; font-size: var(--fs-md); }
.seg-frac { font-size: var(--fs-xs); color: var(--text3); }
/* Artista legible: sube un paso de escala y de --text3 a --text2. La jerarquía
   contra .seg-code se mantiene con PESO y color, no con tamaño (ambos --fs-sm,
   el código en 600/--text y el artista en 500/--text2). */
.seg-card-artist {
  display: flex; align-items: center; gap: var(--space-1); min-width: 0;
  font-size: var(--fs-sm); font-weight: 500; color: var(--text2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.seg-art-mas { color: var(--text3); flex-shrink: 0; }
.seg-badge-mas { font-size: var(--fs-2xs); color: var(--text3); }
.seg-card-dates { display: flex; flex-direction: column; gap: calc(2px * var(--sp-scale, 1)); font-size: var(--fs-xs); color: var(--text2); }
/* "Sin artista": el naranja pasa a ser DECORACIÓN (punto), no información.
   Como texto sobre tarjeta clara daba ~2.6:1 — debajo de AA. */
.seg-sin { color: var(--text2); }
.seg-sin::before {
  content: ''; width: calc(6px * var(--sp-scale, 1)); height: calc(6px * var(--sp-scale, 1));
  border-radius: 50%; background: var(--orange); flex-shrink: 0;
}
.seg-vacio { color: var(--text3); padding: var(--space-4); text-align: center; }

/* Pedido del cliente (sg_director_notes) en el slide-over: recortado a 3
   renglones con "Ver más". pre-wrap respeta los saltos que escribió el
   supervisor SIN insertar <br> (cero superficie de inyección). */
.seg-cr { background: var(--wash-1); border: 1px solid var(--border);
          border-radius: var(--radius-sm); padding: var(--space-3); }
.seg-cr-txt {
  font-size: var(--fs-base); color: var(--text2); line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden;
}
.seg-cr-txt.abierto { display: block; -webkit-line-clamp: none; line-clamp: none; overflow: visible; }
.seg-cr-mas { margin-top: var(--space-2); }

.seg-seq-head { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-3) 0 var(--space-2); }
.seg-seq-dot { width: 10px; height: 10px; border-radius: 50%; }
.seg-seq-dot.verde { background: var(--green); }
.seg-seq-dot.rojo { background: var(--red); }
.seg-seq-dot.gris { background: var(--text3); }
.seg-seq-code { font-weight: 700; }
.seg-seq-meta { font-size: var(--fs-xs); color: var(--text3); }

/* Slide-over: filas de entregas */
.seg-ms-row { display: flex; align-items: center; gap: var(--space-2); padding: calc(6px * var(--sp-scale, 1)) 0; border-bottom: 1px solid var(--border); }
.seg-ms-row.done { opacity: .6; }
.seg-ms-row.vencida .seg-ms-name { color: var(--red); }
.seg-ms-check { width: 16px; color: var(--green); font-weight: 700; }
.seg-ms-name { font-weight: 600; min-width: 52px; }
.seg-ms-tipo { font-size: var(--fs-xs); color: var(--text3); }
.seg-ms-due { margin-left: auto; font-size: var(--fs-sm); color: var(--text2); }
.seg-ms-row .otdp { margin-left: auto; }
.seg-ms-row .btn { flex-shrink: 0; }
.seg-step { font-size: var(--fs-xs); color: var(--text3); text-transform: uppercase; }
.seg-nueva { display: flex; align-items: center; gap: calc(6px * var(--sp-scale, 1)); margin-top: var(--space-2); flex-wrap: wrap; }
.seg-nueva-nombre { width: 72px; height: 28px; padding: 0 var(--space-2); border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--bg2); color: var(--text); font-size: var(--fs-sm); }
.seg-nueva select { height: 28px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--bg2); color: var(--text); font-size: var(--fs-sm); }

/* ══════════ SEGUIMIENTO · REDISEÑO «ágil + reconocible» (2026-08-19) ══════════
   Encargo del productor: ver el status de las tomas de manera ágil y reconocer
   qué toma es cada una. Tres piezas nuevas:
     · MAPA DEL PIPELINE     — etapas en palabras, no códigos de Flow
     · IDENTIDAD EN EL PÓSTER— el código de la toma SOBRE la imagen
     · URGENCIA Y RIESGO     — cuánto falta / cuánto lleva de atraso
   Ningún color es el único portador de información (§7). */

/* ── Mapa del pipeline (fila superior de la barra) ── */
.seg-etapas { display: flex; align-items: center; gap: var(--space-1); flex-wrap: wrap; }
.seg-etapa-seg {
  display: inline-flex; align-items: center; gap: calc(6px * var(--sp-scale, 1));
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--wash-1); color: var(--text2);
  font-family: inherit; font-size: var(--fs-sm); cursor: pointer;
  transition: background var(--dur-micro), border-color var(--dur-micro), color var(--dur-micro);
}
.seg-etapa-seg:hover { background: var(--wash-2); color: var(--text); }
.seg-etapa-seg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Etapa sin tomas: se ATENÚA, no se esconde (misma regla que los chips de
   alerta). Que una etapa desaparezca al filtrar hace creer que el show no
   tiene nada ahí. */
.seg-etapa-seg.vacia { opacity: .45; }
.seg-etapa-n { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text); }
.seg-etapa-seg.on { background: var(--wash-3); border-color: var(--border2); color: var(--text); font-weight: 600; }
.seg-etapa-seg.e-enCurso.on      { background: var(--accent-soft); border-color: var(--accent-border); }
.seg-etapa-seg.e-correcciones.on { background: var(--orange-soft); border-color: var(--orange-border); }
.seg-etapa-seg.e-enRevision.on   { background: var(--purple-soft); border-color: var(--purple-border); }
.seg-etapa-seg.e-aprobado.on     { background: var(--cyan-soft);   border-color: var(--cyan-border); }
.seg-etapa-seg.e-entregado.on    { background: var(--green-soft);  border-color: var(--green-border); }

/* ── Etapa como píldora dentro de una toma ──
   El TEXTO va en color de texto normal y el color vive en el punto: así la
   etiqueta pasa AA en los dos temas sin depender del tono de cada etapa. */
.seg-etapa {
  display: inline-flex; align-items: center; gap: calc(5px * var(--sp-scale, 1));
  font-size: var(--fs-xs); font-weight: 600; color: var(--text2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.seg-etapa-dot { width: var(--space-2); height: var(--space-2);
                 border-radius: 50%; background: var(--text3); flex-shrink: 0; }
.e-enCurso      .seg-etapa-dot { background: var(--accent); }
.e-correcciones .seg-etapa-dot { background: var(--orange); }
.e-enRevision   .seg-etapa-dot { background: var(--purple); }
.e-aprobado     .seg-etapa-dot { background: var(--cyan); }
.e-entregado    .seg-etapa-dot { background: var(--green); }

/* ── Píldora de urgencia ──
   "Atrasada 3 d" / "Hoy" / "En 4 d" / "Sin fecha". Es el reemplazo de tener
   que restar fechas mentalmente. Los tonos: rojo solo para el atraso (el único
   que pasa AA sobre su propio lavado en los dos temas); "Hoy" lleva el lavado
   naranja pero el texto en color de texto, porque el naranja del tema claro se
   queda en ~2.7:1 y eso no se pone como texto. */
.seg-urg {
  padding: calc(2px * var(--sp-scale, 1)) var(--space-2); border-radius: var(--radius-pill);
  background: var(--wash-2); color: var(--text2);
  font-size: var(--fs-xs); font-variant-numeric: tabular-nums; white-space: nowrap; flex-shrink: 0;
}
.seg-urg.u-atrasada { background: var(--red-soft); color: var(--red); font-weight: 700; }
.seg-urg.u-hoy      { background: var(--orange-soft); color: var(--text); font-weight: 700; }
.seg-urg.u-pronto   { background: var(--wash-3); color: var(--text); }
.seg-urg.u-sinFecha { color: var(--text3); }
.seg-card-top .seg-urg { margin-left: auto; }

/* ── Identidad de la toma: el código SOBRE el póster ──
   Reconocer la toma no debería costar bajar la vista a un renglón de 11px. El
   degradado es un velo sobre una FOTO (no sobre una superficie del tema), por
   eso es un rgba negro y no un token: no cambia con el tema claro/oscuro.
   pointer-events:none deja pasar el clic al enlace del thumbnail (Flow). */
.seg-card-poster { position: relative; }
.seg-poster-code {
  position: absolute; left: 0; right: 0; bottom: 0; pointer-events: none;
  padding: calc(14px * var(--sp-scale, 1)) var(--space-2) calc(5px * var(--sp-scale, 1));
  background: linear-gradient(to top, rgba(0,0,0,.78), rgba(0,0,0,0));
  color: #fff; font-size: var(--fs-md); font-weight: 700; letter-spacing: .01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.seg-seq-tag { margin-left: auto; font-size: var(--fs-2xs); color: var(--text3); }
.seg-card-meta .seg-frac { margin-left: var(--space-1); }
.seg-next  { font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seg-final { color: var(--text3); }

/* ── Píldoras de alerta CON TEXTO (adiós puntos anónimos) ── */
.seg-alertas { display: flex; align-items: center; gap: var(--space-1); flex-wrap: wrap; }
.seg-al {
  padding: calc(1px * var(--sp-scale, 1)) var(--space-2); border-radius: var(--radius-pill);
  border: 1px solid var(--border); background: var(--wash-2); color: var(--text2);
  font-size: var(--fs-2xs); white-space: nowrap;
}
.seg-al-vencido, .seg-al-atorado { background: var(--red-soft); border-color: var(--red-border); color: var(--red); }
.seg-al-sinArtista, .seg-al-sinFecha { background: var(--orange-soft); border-color: var(--orange-border); color: var(--text); }
.seg-kpi-riesgo.alto .v { color: var(--red); }

/* Cabecera de estado del slide-over: lo mismo que dice la tarjeta, para no
   tener que recordarlo al abrir el panel. */
.seg-so-estado { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-2); }
.seg-so-art { font-size: var(--fs-sm); color: var(--text2); }
.seg-so-estado + .seg-alertas { margin-bottom: var(--space-3); }

/* ── Densidad: cómoda (default) / compacta / lista ──
   Solo presentación; el filtrado y el agrupado no se enteran. */
#page-seguimiento.density-compacta { --seg-card-min: 176px; }
#page-seguimiento.density-compacta .seg-poster-code { font-size: var(--fs-sm); }
#page-seguimiento.density-compacta .seg-card { gap: calc(6px * var(--sp-scale, 1)); }

/* Lista: una toma por renglón. Las columnas se declaran una sola vez y el
   renglón entero es el objetivo del clic (role="button" + Enter/Espacio). */
#page-seguimiento.density-lista .seg-grid { display: flex; flex-direction: column; gap: 0; }
.seg-row {
  display: grid; align-items: center; gap: var(--space-3);
  grid-template-columns: auto minmax(110px, 1.1fr) minmax(96px, 130px) minmax(90px, 120px)
                         minmax(90px, 1fr) auto minmax(90px, 1fr) auto;
  padding: var(--space-2) var(--space-2);
  border-bottom: 1px solid var(--border); cursor: pointer;
  transition: background var(--dur-micro);
}
.seg-row > * { min-width: 0; }
.seg-row:hover { background: var(--wash-1); }
.seg-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.seg-row.r3 { box-shadow: inset 3px 0 0 var(--red); }
.seg-row.r2 { box-shadow: inset 3px 0 0 var(--orange); }
.seg-row-code { display: flex; flex-direction: column; font-weight: 700; font-size: var(--fs-md); color: var(--text);
                white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.seg-row-seq  { font-size: var(--fs-2xs); font-weight: 400; color: var(--text3); }
.seg-row-prog { display: flex; align-items: center; gap: var(--space-2); }
.seg-row-prog .seg-bar { flex: 1; display: block; }
.seg-row-prog .seg-bar-fill { display: block; }
.seg-row-next, .seg-row-art { font-size: var(--fs-sm); color: var(--text2);
                              white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.seg-row .seg-badges { margin-left: 0; }
/* En lista el título de secuencia y el separador respiran menos. */
#page-seguimiento.density-lista .seg-seq-head { margin-bottom: var(--space-1); }

/* Matriz de permisos (Configuración → Seguridad, solo admin) */
.seg-perms-grid { display: flex; flex-direction: column; gap: var(--space-1); max-width: 460px; }
.seg-perm-row { display: grid; grid-template-columns: 1fr repeat(3, 96px); align-items: center; gap: calc(6px * var(--sp-scale, 1)); font-size: var(--fs-sm); }
.seg-perm-row.seg-perm-head span { font-size: var(--fs-xs); color: var(--text3); }
.seg-perm-row input[type="checkbox"] { accent-color: var(--accent); }

/* ══════════════ CALENDARIO · REDISEÑO «qué, de quién, cuándo» (2026-08-19) ══════════════
   Encargo del productor: que se entienda de un vistazo QUÉ se entrega, DE QUÉ
   SHOW, CUÁNDO y qué está en riesgo. Mismo lenguaje visual que el rediseño de
   Seguimiento y que el modal de Entregas de la semana: el código SOBRE el
   póster, la etapa en palabras (.seg-etapa) y la urgencia en una píldora con
   texto (.seg-urg). Ningún color es el único portador de información (§7). */

/* ── Semáforo del período: las tarjetas de arriba ahora FILTRAN ── */
.cal-kpi {
  font-family: inherit; text-align: left; cursor: pointer;
  display: flex; flex-direction: column; gap: calc(1px * var(--sp-scale, 1));
  transition: background var(--dur-micro), border-color var(--dur-micro);
}
.cal-kpi:hover { background: var(--card2); border-color: var(--border2); }
.cal-kpi:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cal-kpi-value { display: block; font-variant-numeric: tabular-nums; }
.cal-kpi-label { display: block; }
.cal-kpi-sub { font-size: var(--fs-2xs); color: var(--text3); font-variant-numeric: tabular-nums; }
.cal-kpi-sub b { color: var(--text2); font-weight: 700; }
/* Acento por nivel: el borde superior y la cifra. El significado lo lleva el
   rótulo ("Vencidas", "Atoradas"), no el tono. */
.cal-kpi.k-vencida { border-top-color: var(--red); }
.cal-kpi.k-hoy     { border-top-color: var(--yellow); }
.cal-kpi.k-atorado { border-top-color: var(--orange); }
.cal-kpi.k-listo   { border-top-color: var(--green); }
.cal-kpi.k-vencida .cal-kpi-value { color: var(--red); }
.cal-kpi.k-hoy     .cal-kpi-value { color: var(--text); }
.cal-kpi.k-atorado .cal-kpi-value { color: var(--orange); }
.cal-kpi.k-listo   .cal-kpi-value { color: var(--green); }
.cal-kpi.active { border-color: rgba(var(--accent-rgb), .45); background: rgba(var(--accent-rgb), .06); }
.cal-kpi.cal-kpi-total { flex: 1.3; }
/* Un nivel en cero se atenúa, NO se esconde: que desaparezca haría creer que
   la pantalla no sabe contarlo (misma regla que las etapas de Seguimiento). */
.cal-kpi.k-vencida .cal-kpi-value:empty { color: var(--text3); }

/* Subtítulo de la página: "N tomas · N shows · N artistas" */
#cal-subtitle .v { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ── Avisos bajo la barra: atraso acumulado y entregas apartadas ── */
.cal-avisos { display: flex; flex-wrap: wrap; gap: var(--space-2);
  padding: var(--space-2) calc(18px * var(--sp-scale, 1)) 0; flex-shrink: 0; }
/* §6: `[hidden]` NO apaga un contenedor con `display` de autor (el «aparece
   dividido en 2» del Tablero salió justo de aquí). Estos dos ocultamientos van
   por selector propio, y hay un test que lo vigila. */
.cal-avisos[hidden] { display: none; }
.cal-limpiar-btn[hidden] { display: none; }
.cal-aviso { display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-sm); color: var(--text2);
  border: 1px solid var(--border); background: var(--wash-1);
  border-radius: var(--radius-pill); padding: calc(3px * var(--sp-scale, 1)) var(--space-3); }
.cal-aviso b { color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; }
.cal-aviso.a-vencidas { border-color: rgba(var(--red-rgb), .35); background: rgba(var(--red-rgb), .07); }
.cal-aviso.a-vencidas b { color: var(--red); }
.cal-aviso.a-vencidas svg, .cal-aviso.a-vencidas i { color: var(--red); flex-shrink: 0; }
.cal-aviso-btn { font-family: inherit; font-size: var(--fs-sm); font-weight: 600;
  color: var(--accent); background: none; border: none; cursor: pointer; padding: 0; }
.cal-aviso-btn:hover { text-decoration: underline; }

/* ── Buscador de toma (barra de navegación) ── */
.cal-busca { position: relative; display: inline-flex; align-items: center; }
.cal-busca-ico { position: absolute; left: var(--space-2); color: var(--text3); pointer-events: none; }
.cal-busca-input {
  height: 26px; box-sizing: border-box; width: calc(200px * var(--sp-scale, 1));
  padding: 0 calc(26px * var(--sp-scale, 1)) 0 calc(26px * var(--sp-scale, 1));
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  background: var(--card2); color: var(--text); font-family: inherit; font-size: var(--fs-sm);
  outline: none; transition: border-color var(--dur-fast);
}
.cal-busca-input:focus { border-color: var(--accent); }
.cal-busca-input::placeholder { color: var(--text3); }
.cal-busca-input::-webkit-search-cancel-button { display: none; }
/* La × solo aparece cuando hay algo que limpiar (la clase la pone
   _renderCalFilterBadge). */
.cal-busca-x { display: none; }
.cal-busca.con-texto .cal-busca-x { display: block; position: absolute; right: calc(2px * var(--sp-scale, 1));
  width: 20px; height: 20px; border: none; background: none; color: var(--text3);
  font-family: inherit; font-size: var(--fs-md); line-height: 1; cursor: pointer; border-radius: var(--radius-xs); }
.cal-busca-x:hover { color: var(--text); background: var(--wash-3); }
.cal-limpiar-btn { color: var(--orange); border-color: rgba(var(--orange-rgb), .35); }

/* ── Tarjeta: identidad de la toma ──
   El código va SOBRE el póster (igual que en Seguimiento): reconocer la toma no
   debería costar bajar la vista a un renglón de 11 px. El degradado es un velo
   sobre una FOTO, no sobre una superficie del tema: por eso es rgba negro y no
   un token — no cambia con el tema claro/oscuro. */
.cal-task-thumb { position: relative; }
.cal-task-code {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--space-3) calc(6px * var(--sp-scale, 1)) calc(3px * var(--sp-scale, 1));
  background: linear-gradient(to top, rgba(0,0,0,.80), rgba(0,0,0,0));
  font-size: var(--fs-sm); font-weight: 700; letter-spacing: -.2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cal-task-code .vfx-link { color: #fff; border-bottom-color: rgba(255,255,255,.4); }
.cal-task-code .vfx-link:hover, .cal-task-code .vfx-link:focus { color: #fff; border-bottom-color: #fff; }
/* El SHOW en la tarjeta: sin esto había que agrupar por proyecto para saber de
   quién era la entrega (hallazgo de la auditoría 2026-08-19). */
.cal-task-show { flex: 1; min-width: 0; font-size: var(--fs-xs); font-weight: 600; color: var(--text2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-task-foot { display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-1); margin-top: calc(3px * var(--sp-scale, 1)); min-width: 0; }
.cal-task-foot .seg-etapa { min-width: 0; }
.cal-task-foot .seg-urg { flex-shrink: 0; }
/* Riesgo en el borde: refuerza lo que la píldora ya dice con palabras. */
.cal-task.r-vencida { border-color: rgba(var(--red-rgb), .55); }
.cal-task.r-atorado { border-color: rgba(var(--orange-rgb), .45); }
.cal-task.r-listo   { opacity: .72; }
.cal-task.r-listo .cal-task-code { text-decoration: line-through; text-decoration-color: rgba(255,255,255,.5); }
/* Densidad compacta: sin póster grande, el código vuelve al renglón y la
   píldora de urgencia cierra la fila. */
#cal-content.density-compact .cal-task-code { display: none; }
#cal-content.density-compact .cal-task > .seg-urg { flex-shrink: 0; margin-left: auto; }
#cal-content.density-compact .cal-task-artist .cal-task-show { display: inline; font-size: inherit; }

/* ── Columna-día: resumen de riesgo y tope de tarjetas ── */
.cal-day-risk { font-size: var(--fs-2xs); color: var(--red); font-weight: 600; margin-top: calc(2px * var(--sp-scale, 1)); }
.cal-day-risk .n { font-variant-numeric: tabular-nums; font-weight: 800; }
.cal-dia-vacio { height: calc(26px * var(--sp-scale, 1)); border-radius: var(--radius-xs);
  border: 1px dashed var(--border); margin: var(--space-1) 0; }
.cal-mas-btn { width: 100%; font-family: inherit; font-size: var(--fs-xs); font-weight: 600;
  color: var(--text2); background: var(--wash-2); border: 1px solid var(--border);
  border-radius: var(--radius-xs); padding: calc(5px * var(--sp-scale, 1)) 0; cursor: pointer;
  transition: background var(--dur-micro), color var(--dur-micro); }
.cal-mas-btn:hover { background: var(--wash-3); color: var(--text); }
/* Cabecera dentro de la columna: solo se ve cuando la rejilla se apila. */
.cal-day-inline { display: none; }
.cal-vacio { display: flex; align-items: center; justify-content: center; gap: var(--space-3);
  padding: var(--space-4); font-size: var(--fs-base); color: var(--text3);
  border-top: 1px solid var(--border); }

/* ── Vista mensual: «+N más» es un botón real (antes era texto muerto) ── */
.cal-mc-more { font-family: inherit; background: none; border: none; padding: 0; cursor: pointer;
  font-size: var(--fs-2xs); color: var(--text2); text-align: left; margin-top: calc(1px * var(--sp-scale, 1)); }
.cal-mc-more:hover { color: var(--accent); text-decoration: underline; }
.cal-mc-card.r-vencida { box-shadow: inset 0 0 0 1px rgba(var(--red-rgb), .45); }
.cal-mc-card.r-listo   { opacity: .6; }

/* ── Vista lista: etapa + urgencia, y el riesgo en el filo ── */
.cal-list-thumb { padding: var(--space-1) calc(6px * var(--sp-scale, 1)) var(--space-1) 0; width: calc(50px * var(--sp-scale, 1)); }
.cal-list-art { max-width: calc(180px * var(--sp-scale, 1)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-list-due { display: flex; align-items: center; gap: var(--space-2); white-space: nowrap; }
.cal-list-fecha { font-size: var(--fs-xs); color: var(--text3); font-variant-numeric: tabular-nums; }
.cal-list-nd { color: var(--text3); }
.cal-list-row.r-vencida td:first-child { box-shadow: inset 3px 0 0 var(--red); }
.cal-list-row.r-atorado td:first-child { box-shadow: inset 3px 0 0 var(--orange); }
.cal-list-row.r-listo   { opacity: .68; }

/* Panel de detalle: la fecha exacta junto a la píldora de urgencia */
.cal-detail-fecha { font-size: var(--fs-xs); color: var(--text3); margin-left: var(--space-1); font-variant-numeric: tabular-nums; }

/* ── Pantallas angostas: la rejilla de 5 columnas se APILA ──
   A 393 px cada columna medía ~70 px: ni el código de la toma cabía. Ahora la
   semana se lee como agenda, un día debajo de otro, y cada bloque conserva su
   [data-date] (el drag & drop y su ruta de teclado siguen intactos). */
@media (max-width: 820px) {
  .cal-week-header { display: none; }
  .cal-week-body { grid-template-columns: minmax(0, 1fr); gap: var(--space-2); background: transparent; }
  .cal-day-col { min-height: 0; border: 1px solid var(--border); border-radius: var(--radius-sm); }
  .cal-day-inline { display: flex; align-items: baseline; gap: var(--space-2);
    font-size: var(--fs-sm); font-weight: 700; color: var(--text2);
    text-transform: uppercase; letter-spacing: .06em;
    padding-bottom: calc(5px * var(--sp-scale, 1)); margin-bottom: calc(5px * var(--sp-scale, 1));
    border-bottom: 1px solid var(--border); }
  .cal-day-inline .n { font-size: var(--fs-lg); color: var(--text); font-variant-numeric: tabular-nums; }
  .cal-day-inline .c { margin-left: auto; font-size: var(--fs-xs); color: var(--text3);
    background: var(--wash-2); border-radius: var(--radius-pill); padding: 0 var(--space-2); }
  .cal-day-col.today .cal-day-inline .n { color: var(--accent); }
  .cal-busca-input { width: calc(150px * var(--sp-scale, 1)); }
  .cal-kpis { gap: var(--space-1); }
  .cal-kpi { min-width: calc(78px * var(--sp-scale, 1)); }
}

/* ══════════════════════════════════════════════════════════
   BITÁCORA DEL SERVIDOR (Administración → Bitácora, 2026-08-27)
   Paridad con la pantalla de iOS. La franja de resumen reutiliza el
   componente .seg-kpis/.seg-kpi (mismo look de tarjeta-cifra que
   Seguimiento); aquí solo va lo que ese componente no cubre: la cifra
   CLICABLE y el rojo de las fallas.
   Todo con tokens (--red-*, --text3): el gate ds-lint aborta el build ante
   hex crudo o font-size en px, y la tabla lee 200+ renglones de corrido, así
   que la única señal fuerte permitida es la de error.
   ══════════════════════════════════════════════════════════ */
.seg-kpi.bitac-kpi { font: inherit; color: inherit; text-align: left; cursor: pointer; }
/* Sin errores no hay nada que filtrar: el botón queda inerte en vez de llevar
   a una tabla vacía. */
.seg-kpi.bitac-kpi[disabled] { cursor: default; opacity: 0.55; }
.seg-kpi .v.bitac-hay { color: var(--red); }
.seg-kpi .bitac-kpi-sub { display: block; color: var(--text3); }
/* Fila con error: tinte rojo suave + la acción en rojo. El :hover se sube de
   tono para no perder la señal de "sobre esta fila estoy". */
.adm-page .data-table tr.bitac-err td { background: var(--red-soft); }
.adm-page .data-table tr.bitac-err:hover td { background: rgba(var(--red-rgb), 0.22); }
.adm-page .data-table tr.bitac-err td.bitac-acc { color: var(--red); font-weight: 600; }
