/* ===== TRACKER CONTAINER ===== */
.tracker-container {
    /* Los design tokens de Variant A (re-skin UX-TRK-01) se PROMOVIERON a :root
       en wwwroot/css/design-system/tokens.css (Epic UX-DS-01 / DS-01.01).
       Este contenedor ahora SOLO los consume vía var(--token), igual que el
       resto de la app — ya no están atrapados aquí. */
    /* UX-DS-03.01 — worksheet header (variant-A thead th es blanco + labels gris).
       Override PAGE-SCOPED de los tokens que DsDataGrid consume para el header;
       las tablas legacy fuera del tracker (site.css) conservan el navy global. */
    --table-header-bg: var(--bg-white);
    --table-header-text: var(--med-gray-medium);
    padding: 20px;
    /* FIX (2026-07): este contenedor vive DENTRO de <main>, debajo del top-row de 64px
       (--header-height). Con height:100vh el contenido medía 100vh + 64px y desbordaba el
       viewport: el <body> hacía scroll y el .sidebar (sticky, 100vh) no cubría el sobrante,
       dejando espacio en blanco bajo el menú, bajo el contenido y el gutter de scroll a la
       derecha. Restar el header hace que main = top-row + este contenedor = 100vh exacto. */
    height: calc(100vh - var(--header-height));
    display: flex;
    flex-direction: column;
    /* UX-DS-03.04 — variant-A --bg-page (era #f5f5f5 literal) */
    background: var(--bg-page);
    /* Anchor for the full-view initial-loading overlay (.tracker-initial-loading). */
    position: relative;
}

/* Full-view initial loading (2026-07) — covers the entire tracker while OnInitializedAsync resolves the
   views/tabs/columns and loads the first page, so the user never sees the empty-table → tabs → data flash. */
.tracker-initial-loading {
    position: absolute;
    inset: 0;
    z-index: 50;
    background: var(--bg-page);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
}
.tracker-initial-loading__spinner {
    width: 2.75rem;
    height: 2.75rem;
    color: var(--med-blue-interactive, #0067b8);
}
.tracker-initial-loading__text {
    margin: 0;
    font-size: .95rem;
    font-weight: 600;
    color: var(--med-gray-medium, #666);
}

/* ===== HEADER =====
   H-03 (feedback 2026-08-08) — el encabezado del tracker (.tracker-header, su h1 y .tracker-actions)
   se retiró: repetía el nombre de la pantalla y su franja —16px de margen inferior más el alto del
   título— se la comía a la tabla. Las acciones globales viven ahora en el panel de la vista
   (ranura Actions de ViewTabBar). Las reglas se borran con el marcado para que nadie las reviva
   por accidente. */

/* ===== CIERRE DERECHO DE LA BARRA DE FILTROS =====
   Hospeda el contador de filas y el disparador de "seleccionar esta columna en todas las filas
   filtradas" (H-04). Los dos en la MISMA línea, alineados a la base de los controles: el bloque
   mide lo que mide un botón chico, menos que un grupo de filtro, así que no fija el alto de la
   barra ni agrega renglón. Es el equivalente de .ds-filter-bar__meta del sistema de diseño. */
.filter-trailing {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    /* Alinea con la base de los controles, no con la de las etiquetas. */
    padding-bottom: 2px;
}

.bulk-column-actions { display: flex; }

/* Botón chico calcado de .ds-filter-bar__add: contorno punteado, tamaño xs, sin relleno. Antes
   era un `btn btn-outline-secondary btn-sm` de Bootstrap con la etiqueta larga completa, y ese
   par —alto de botón mediano más texto de treinta caracteres— era justo lo que no dejaba entrar
   el cierre en la línea de los filtros. La explicación completa vive en el `title`. */
.bulk-column-btn {
    background: none;
    border: 1px dashed var(--med-blue-interactive);
    color: var(--med-blue-interactive);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    padding: 3px var(--spacing-sm);
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--transition-fast), color var(--transition-fast);
}
.bulk-column-btn:hover { background: var(--selection-bg); }

/* Hints de descubribilidad (NOTA-PENDIENTE 2026-08-13, punto 1) — el anuncio de los filtros
   avanzados por entidad (Has Phase / Task Name / Task Status / Part). Mismo lenguaje visual que
   .bulk-column-btn (contorno punteado xs) para que el cierre derecho se lea como una familia. */
/* (TRK-OLA1A.05/.06 — .advanced-filters-btn retired with its button.) */

/* ===== TRK-OLA1A.02 — CHIP ZONE (functional layout; the mtmp skin lands in story .06) ===== */
.tracker-chip-zone {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    flex: 2 1 auto;
    padding: 2px 4px;
    border-radius: 10px;
}
.tracker-chips-empty {
    font-size: var(--font-size-xs);
    color: var(--med-gray-tertiary, #6B7A90);
}
.tracker-chip-wrap { position: relative; display: inline-flex; }
.trk-chip {
    display: inline-flex;
    align-items: center;
    border: 1px solid #BFD8F7;
    background: #EAF3FE;
    border-radius: 999px;
    font-size: var(--font-size-xs);
    line-height: 1;
    overflow: hidden;
}
.trk-chip--editing { border-color: #117BFF; }
.trk-chip__body {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border: 0;
    background: transparent;
    padding: 5px 4px 5px 10px;
    cursor: pointer;
    font-size: inherit;
}
.trk-chip__val {
    font-family: var(--font-mono, ui-monospace, monospace);
    /* T-05 (heredado de los selects retirados): un valor largo se trunca, el chip no rompe la línea. */
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.trk-chip__body:hover .trk-chip__val { text-decoration: underline; }
.trk-chip__key { font-weight: 600; }
.trk-chip__x {
    border: 0;
    background: transparent;
    padding: 5px 8px;
    cursor: pointer;
    font-size: inherit;
    color: #4a5a72;
}
.trk-chip__x:hover { color: #B3261E; }
.trk-value-picker {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 60;
    /* 240→320 (2026-08-21): con 240 los valores largos ("CDP/SCC Closure - Sustaining (CDP)")
       envolvían en dos y tres líneas. La escala tipográfica común vive más abajo. */
    min-width: 320px;
    max-width: 440px;
    max-height: 360px;
    overflow: auto;
    background: #fff;
    border: 1px solid #DCE5F2;
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(7, 26, 61, 0.14);
    padding: 12px;
}
.trk-picker__title {
    font-size: var(--font-size-xs);
    font-weight: 600;
    margin-bottom: 6px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.trk-picker__sub { font-weight: 400; color: #6B7A90; }
.trk-picker__options { display: flex; flex-direction: column; }
.trk-picker__opt {
    text-align: left;
    border: 0;
    background: transparent;
    padding: 6px 8px;
    border-radius: 6px;
    cursor: pointer;
    font-size: var(--font-size-xs);
}
.trk-picker__opt:hover { background: #F1F7FF; }
.trk-picker__opt--on { background: #EAF3FE; font-weight: 600; }
.trk-picker__empty { font-size: var(--font-size-xs); color: #6B7A90; padding: 4px 8px; }
.trk-picker__footer { display: flex; gap: 8px; justify-content: flex-end; margin-top: 8px; }
.trk-picker__apply {
    border: 0;
    background: #117BFF;
    color: #fff;
    border-radius: 8px;
    padding: 5px 12px;
    cursor: pointer;
    font-size: var(--font-size-xs);
}
.trk-picker__apply:disabled { opacity: 0.5; cursor: not-allowed; }
.trk-picker__cancel {
    border: 0;
    background: transparent;
    color: #4a5a72;
    cursor: pointer;
    font-size: var(--font-size-xs);
}

/* ===== TRK-OLA1A.04 — unsaved cluster + amber dirty zone (functional; mtmp skin in .06) ===== */
.tracker-chip-zone--dirty {
    background: var(--pill-amber-bg, #FFF4D6);
    box-shadow: inset 0 0 0 1px var(--mtmp-warning, #F5A623);
    border-radius: 10px;
    padding-bottom: 6px;
}
.trk-unsaved { display: inline-flex; align-items: center; gap: 8px; margin-left: 6px; }
.trk-unsaved__label {
    color: var(--pill-amber-text, #B07E10);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.trk-unsaved__save {
    border: 0;
    background: var(--mtmp-primary, #117BFF);
    color: #fff;
    border-radius: var(--mtmp-radius-md, 12px);
    padding: 4px 12px;
    font-size: var(--font-size-xs);
    cursor: pointer;
}
.trk-unsaved__save:disabled { opacity: 0.5; cursor: not-allowed; }
.trk-unsaved__discard {
    border: 0;
    background: transparent;
    color: #4a5a72;
    text-decoration: underline;
    font-size: var(--font-size-xs);
    cursor: pointer;
}
.trk-save-toast { font-size: var(--font-size-xs); color: #1D7A3E; margin-left: 6px; }

/* ===== TRK-OLA1A.03 — "+ Add filter" + field palette (functional; mtmp skin in .06) ===== */
.tracker-add-filter-anchor { position: relative; }
.add-filter-btn {
    border: 1px dashed #9DB8DC;
    background: transparent;
    color: #2A5AA2;
    border-radius: var(--mtmp-radius-pill, 999px);
    font-size: var(--font-size-xs);
    padding: 5px 12px;
    cursor: pointer;
    white-space: nowrap;
}
.add-filter-btn:hover { background: #F1F7FF; }
.trk-palette { min-width: 320px; max-width: 400px; }
.trk-palette__input {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid var(--mtmp-border-gray, #DCE5F2);
    border-radius: 8px;
    padding: 6px 10px;
    font-size: var(--font-size-xs);
    margin-bottom: 6px;
}
.trk-palette__results { max-height: 240px; overflow: auto; display: flex; flex-direction: column; }
.trk-palette__group {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--mtmp-text-gray, #6B7A90);
    padding: 6px 8px 2px;
}
.trk-palette__gcount { opacity: 0.7; }
.trk-palette__item {
    text-align: left;
    border: 0;
    background: transparent;
    padding: 6px 8px;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.trk-palette__item:hover { background: #F1F7FF; }
.trk-palette__item--hi { background: var(--pill-blue-bg, #EAF3FE); }
.trk-palette__label { font-size: var(--font-size-xs); font-weight: 600; }
.trk-palette__sub { font-size: 11px; color: var(--mtmp-text-gray, #6B7A90); }
.trk-palette__empty { font-size: var(--font-size-xs); padding: 8px; color: var(--mtmp-dark-text, #1D2C48); }
.trk-palette__footer {
    border-top: 1px solid #EDF2F7;
    margin-top: 6px;
    padding-top: 6px;
    font-size: 10px;
    color: var(--mtmp-text-gray, #6B7A90);
}

/* TRK-OLA1A.06 — motion is decorative only; honor reduced-motion (spec §Accessibility). */
.trk-value-picker, .trk-save-toast, .trk-unsaved { transition: opacity 200ms ease; }
@media (prefers-reduced-motion: reduce) {
    .trk-value-picker, .trk-save-toast, .trk-unsaved { transition: none; }
}

/* ===== FILTERS =====
   ⚠ PENDIENTE DE REDISEÑO — docs/design/NOTA-PENDIENTE-BARRA-FILTROS-TRACKER-2026-08-11.md
   El apretón de abajo resuelve el espacio pero no convenció; se dejó así para no frenar la
   corrección de los defectos de Medtronic. La nota trae qué explorar (chips + DsFilterBar en vez
   de siete selects permanentes) y qué NO se puede deshacer sin reabrir H-03, H-04 y FD-02.

   Sesión Medtronic 2026-08-11 — la barra se apretó a las proporciones del sistema de diseño
   (DsFilterBar): controles más chicos, etiquetas más chicas y huecos de token en vez de 16px.
   El motivo no es estética: con siete controles a 120px de ancho mínimo y 54px de alto, el
   cierre derecho (contador + disparador de selección) no cabía en la misma línea y se envolvía,
   dejando un renglón casi vacío dentro del card. Achicando los controles todo entra en una
   línea y la barra baja de ~86px a ~62px, que es alto que gana la tabla. */
/* TRK-OLA1A.06 (G7/FD-03) — THE bar is one mtmp-card row (radius 16, soft shadow, white on the
   cloud ground). Chip zone (left, the only side that ever goes amber) · divider · View-lens pill
   (TRK-OLA1B.01 — the reserved end, delivered) · counter · column-select trigger. The
   GRID below keeps its skin — the card is the whole scope of the re-skin. Derived pill families
   are declared as local custom properties over the mtmp tokens. */
.tracker-bar {
    --pill-blue-bg: #EAF3FE;          /* soft fill derived from --mtmp-electric-blue over white */
    --pill-blue-border: #BFD8F7;
    --pill-amber-bg: #FFF4D6;
    --pill-amber-text: #B07E10;       /* AA on --pill-amber-bg (spec §Accessibility) */
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-sm) var(--spacing-md);
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--mtmp-white, #FFFFFF);
    border: 1px solid var(--mtmp-border-gray, #DCE5F2);
    border-radius: var(--mtmp-radius-lg, 16px);
    box-shadow: var(--mtmp-shadow-soft, 0 8px 24px rgba(6, 20, 44, 0.08));
    margin-bottom: var(--spacing-sm);
}
.tracker-bar__divider {
    align-self: stretch;
    width: 1px;
    background: var(--mtmp-border-gray, #DCE5F2);
}
.tracker-filters {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm) var(--spacing-md);
    align-items: flex-end;
    flex: 1 1 auto;
}

.filter-group {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.filter-group label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    color: var(--text-secondary);
    text-transform: uppercase;
}

/* (TRK-OLA1A.06 — the retired selects/search-input rules removed with their controls.) */

/* (TRK-OLA1A.05/.06 — phase-filter multi-select styles retired with the control.) */

/* Story TRK-OLA1B.01 (AC1/AC2, FD-08) — the View lens: microlabel + OUTLINED pill (mode grammar,
   never a chip) past the bar divider, and its popover (the visualization family's ONE home). The
   PRT-1B.09 detail-level <details> died here — its checkboxes live inside the popover now. Grammar:
   white pill, --mtmp-border-gray border, ◐, no ×; active = primary border + soft-sky tint. */
/* flex-direction explícita: el elemento también es .filter-group, cuya regla (columna) ganaría por
   orden de cascada sin esta declaración — el microlabel debe quedar EN LÍNEA con la pill (FD-08). */
.tracker-lens-anchor { position: relative; display: flex; flex-direction: row; align-items: center; gap: 6px; }
.lens-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 700;
    color: var(--mtmp-text-gray, #6B7A90);
    white-space: nowrap;
}
.lens-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--mtmp-white, #FFFFFF);
    border: 1px solid var(--mtmp-border-gray, #DCE5F2);
    color: var(--mtmp-light-navy, #22456F);
    border-radius: var(--mtmp-radius-pill, 999px);
    font-size: 12px;
    font-weight: 700;
    padding: 4px 12px;
    white-space: nowrap;
    cursor: pointer;
}
.lens-pill:hover { border-color: var(--mtmp-primary, #117BFF); }
.lens-pill .lens-state {
    font-weight: 500;
    /* AA (AC2): el resumen es texto SIEMPRE visible — --mtmp-text-gray (4.37:1) no alcanza el piso
       4.5:1 en 12px; light-navy (~8:1 sobre blanco y sobre soft-sky) sí (review .01, hallazgo 9). */
    color: var(--mtmp-light-navy, #274B85);
    max-width: 26ch;
    overflow: hidden;
    text-overflow: ellipsis;
}
.lens-pill.lens-active {
    border: 1.5px solid var(--mtmp-primary, #117BFF);
    background: var(--mtmp-soft-sky, #EAF3FE);
}
.popover-lens {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 60;
    /* Ancho estilo prototipo: los catálogos traen nombres largos (tareas ~115) y a 340px
       cada renglón envolvía en 2-3 líneas. Acotado al viewport en pantallas chicas. */
    min-width: 420px;
    max-width: min(640px, calc(100vw - 48px));
    max-height: 440px;
    overflow: auto;
    background: var(--mtmp-white, #FFFFFF);
    border: 1px solid var(--mtmp-border-gray, #DCE5F2);
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(7, 26, 61, 0.14);
    padding: 10px;
}
.popover-lens .pop-title {
    font-size: var(--font-size-xs);
    font-weight: 700;
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 6px;
    border-left: 3px solid var(--mtmp-primary, #117BFF);
    padding-left: 8px;
}
.popover-lens .pop-sub { font-weight: 400; color: var(--mtmp-text-gray, #6B7A90); }
.popover-lens .pop-group {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--mtmp-text-gray, #6B7A90);
    margin: 8px 0 2px;
}
.popover-lens .pop-groupsub { font-weight: 400; text-transform: none; letter-spacing: normal; }
.popover-lens .pop-item {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    width: 100%;
    text-align: left;
    border: 0;
    background: transparent;
    padding: 6px 8px;
    border-radius: 6px;
    cursor: pointer;
    font-size: var(--font-size-xs, 12px);
    /* La regla de microlabels de la barra (.filter-group label) alcanza los labels anidados
       del popover — sin este reset, fases y tareas se pintan EN ALTAS con tracking de rótulo. */
    text-transform: none;
    letter-spacing: normal;
    color: var(--mtmp-dark-text, #1D2C48);
}
.popover-lens .pop-item:hover { background: #F1F7FF; }
/* Preset encendido — afordance visual además del aria-pressed (review .03, hallazgo 6). */
.popover-lens .pop-item-on { background: var(--mtmp-soft-sky, #EAF3FE); }
/* Tamaño fijado en el span: una regla global de labels (create-project-enhanced.css) infla
   la fuente heredada a 14px — el prototipo lista los nombres más compactos. */
.popover-lens .pop-item-label { font-weight: 600; font-size: var(--font-size-xs, 12px); }
.popover-lens .pop-item-sub { flex-basis: 100%; color: var(--mtmp-text-gray, #6B7A90); }
.popover-lens .pop-pending {
    font-size: var(--font-size-xs);
    color: var(--mtmp-text-gray, #6B7A90);
    padding: 2px 8px 4px;
}
.popover-lens .pop-footer {
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid var(--mtmp-border-gray, #DCE5F2);
    font-size: 10px;
    color: var(--mtmp-text-gray, #6B7A90);
}
/* Buscador de los catálogos largos del popover (fases/tareas) — filtro de display. */
.popover-lens .pop-filter {
    width: 100%;
    margin: 2px 0 4px;
    padding: 4px 8px;
    font-size: var(--font-size-xs, 12px);
    color: var(--mtmp-dark-text, #1D2C48);
    background: var(--mtmp-white, #FFFFFF);
    border: 1px solid var(--mtmp-border-gray, #DCE5F2);
    border-radius: 6px;
}
.popover-lens .pop-filter:focus {
    outline: 2px solid var(--mtmp-primary, #117BFF);
    outline-offset: 1px;
    border-color: var(--mtmp-primary, #117BFF);
}

/* Checkbox plano estilo prototipo (☐/☑): caja delineada + palomita de glifo, sin el
   checkbox nativo azul del navegador. El input sigue siendo real (test ids intactos). */
.lens-detail-opt input {
    min-width: auto;
    appearance: none;
    -webkit-appearance: none;
    flex: none;
    width: 15px;
    height: 15px;
    margin: 0;
    display: inline-grid;
    place-content: center;
    background: var(--mtmp-white, #FFFFFF);
    border: 1.5px solid var(--mtmp-text-gray, #6B7A90);
    border-radius: 3px;
    cursor: pointer;
}
.lens-detail-opt input:checked { border-color: var(--mtmp-dark-text, #1D2C48); }
.lens-detail-opt input:checked::before {
    content: "✓";
    font-size: 11px;
    line-height: 1;
    font-weight: 700;
    color: var(--mtmp-dark-text, #1D2C48);
}
.lens-detail-opt input:focus-visible {
    outline: 2px solid var(--mtmp-primary, #117BFF);
    outline-offset: 1px;
}

/* Story PRT-1B.09 (AC1) — contador k/n de la línea agregada. Monoespaciado para que "2/5" y "10/12"
   no bailen de ancho al conmutar el detalle. */
.task-part-aggregate {
    font-family: var(--font-mono);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    padding: 1px 6px;
    border-radius: 3px;
    background: var(--row-task-bg);
    color: var(--med-gray-medium);
    border: 1px solid var(--grid-line);
    flex-shrink: 0;
    white-space: nowrap;
    cursor: help;
}

/* El empuje a la derecha lo hace ahora .filter-trailing, que envuelve al contador junto con el
   disparador de selección por columna (2026-08-11). Cifras tabulares para que el número no
   cambie de ancho al filtrar y el botón de al lado no baile. */
.filter-count {
    font-size: var(--font-size-xs);
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ===== TABLE WRAPPER ===== */
/* Feedback 2026-08-20 (1a978554) — el grid ahora tiene DOS cajas: un shell exterior que NO
   scrollea (ancla de los indicadores de scroll horizontal — ver HORIZONTAL SCROLL INDICATORS
   abajo) y el wrapper interior, que sigue siendo el scroll container. flex:1 y el margen para
   la barra de cambios sin guardar suben al shell (ahora él es el hijo flex de .tracker-container);
   el wrapper llena el shell por completo para que los overlays del shell coincidan con los
   bordes visibles del grid. */
.tracker-grid-shell {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    margin-bottom: 60px; /* Space for unsaved changes bar */
}

.tracker-table-wrapper {
    flex: 1;
    min-height: 0;
    overflow: auto;
    background: white;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

/* ===== TABLE ===== */
/* table-layout: fixed (perf quick-win 3.4, PROPOSAL-TRACKER-SCROLL-PERF-2026-07-06): with ~400 columns in
   wide views, the auto table-layout algorithm re-measures cell CONTENT on every DOM patch/reflow (each
   Virtualize windowing pass); fixed layout sizes columns from the first header row only — O(columns), no
   content measuring — and keeps the table width stable across windowing (no layout shift as rows realize).
   Column widths come from the <th>s: the frozen/special columns keep their explicit widths below; every
   other column gets the :where() low-specificity default (140px) so ANY existing class width rule still
   wins. Content that used to auto-widen its column now ellipsizes (see .project-row td below). */
.tracker-table {
    table-layout: fixed;
    width: max-content;
    min-width: 100%;
    border-collapse: collapse;
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
}

/* Default column width under fixed layout. :where() keeps specificity at (0,0,1) so every existing
   width rule (.col-checkbox, .col-id, .col-tool, .col-wide, …) overrides it. */
:where(.tracker-table) th {
    width: 140px;
}

/* UX-DS-03.01 — worksheet header (Variant A thead th): white bg + 2px blue underline +
   small gray uppercase labels. Height from the DS token (--grid-header-h = 38px).
   background/color viajan vía --table-header-* (override en .tracker-container) porque
   la regla scoped de DsDataGrid (.ds-grid__head[b-x] th) gana en especificidad. */
.tracker-table th {
    background: var(--bg-white);
    color: var(--med-gray-medium);
    font-weight: 700;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    padding: 0 12px;
    height: var(--grid-header-h);
    border-bottom: 2px solid var(--med-blue-primary);
    text-align: left;
    white-space: nowrap;
    /* fixed table-layout (3.4): headers no longer widen their column, so long labels must
       ellipsize instead of bleeding over the neighbor th. */
    overflow: hidden;
    text-overflow: ellipsis;
    user-select: none;
    position: sticky;
    top: 0;
    z-index: 10;
}

/* UX-DS-03.01 — la regla scoped de DsDataGrid declara font-weight:var(--font-weight-semibold)
   con especificidad (0,2,1) y su hoja viene después; este selector (0,2,2) la supera
   sin tocar el token global de tipografía. */
.tracker-table-wrapper table.tracker-table th {
    font-weight: 700;
}

/* Sortable Headers */
.tracker-table th.sortable {
    cursor: pointer;
    user-select: none;
    transition: background 0.15s ease;
}

/* UX-DS-03.01 — sortable hover/sorted al lenguaje del prototipo (variant-A.html:494):
   hover = texto azul + fondo amarillo suave; sorted = texto azul sobre blanco. */
.tracker-table th.sortable:hover {
    color: var(--med-blue-primary);
    background: var(--med-yellow-bg);
}

.tracker-table th.sortable.sorted {
    color: var(--med-blue-primary);
    background: var(--bg-white);
}

/* L-01 — el encabezado ahora entra al orden de tabulación, así que necesita un foco visible.
   `focus-visible` deja el anillo solo para la navegación por teclado, no para el clic. */
.tracker-table th.sortable:focus-visible {
    outline: 2px solid var(--med-blue-interactive);
    outline-offset: -2px;
    color: var(--med-blue-primary);
    background: var(--med-yellow-bg);
}

.tracker-table th.sortable::after {
    content: '';
    display: inline-block;
    margin-left: 4px;
    opacity: 0.4;
}

.tracker-table td {
    padding: 0 12px;
    border-bottom: 1px solid var(--grid-line);
    vertical-align: middle;
}

/* Densidad de fila de proyecto (Variant A: 32px). Fase/tarea fijan su propia altura. */
/* nowrap+ellipsis (perf quick-win 3.4): under fixed table-layout a column no longer auto-widens to fit
   its content, so long values must truncate instead of wrapping (wrapping would break the 32px density
   AND the Virtualize ItemSize="32" hint). Bonus: single-line rows keep the spacer math exact. */
.project-row td {
    height: 32px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ===== FROZEN COLUMNS ===== */
.frozen {
    position: sticky;
    background: white;
    z-index: 5;
}

/* UX-DS-03.01 — frozen header cells: opaque white (variant-A.html:532) so the
   non-frozen columns don't bleed through under horizontal scroll. z-index preserved. */
th.frozen {
    background: var(--bg-white);
    z-index: 15;
}

.col-checkbox { left: 0; width: 40px; min-width: 40px; }

/* OLA2.06 (C1=b) — ROW selection rides the BLUE axis: a left rail on the selected row + the
   checkbox accent, so a selected ROW reads as "whole row marked" and can never be confused with
   the TEAL per-cell selection (see .cell-selected). Class names untouched (UX-DS-05 diffing). */
.tracker-table tr.selected > td.col-checkbox { box-shadow: inset 3px 0 0 var(--mtmp-electric-blue, #117BFF); }
.tracker-table td.col-checkbox input[type="checkbox"],
.tracker-table th.col-checkbox input[type="checkbox"] { accent-color: var(--mtmp-electric-blue, #117BFF); }
.col-expand { left: 40px; width: 30px; min-width: 30px; }
/* Story 11B.14 (Q9) — frozen primary identity column now carries ProjectDisplayId (+ Intake badge)
   instead of the legacy int "#", so it is wider. col-tool shifts right to keep the sticky offsets exact. */
.col-id { left: 70px; width: 150px; min-width: 150px; max-width: 150px; overflow: hidden; }
/* 300→400 (2026-08-21): la sub-fila de tarea ganó el selector de estado (~104px) además de la
   sangría del árbol, y a 300px el nombre de la tarea quedaba cortado a media palabra. Si este
   número cambia, actualiza TAMBIÉN la sombra de scroll `.has-scroll-left::before` (left = suma de
   las 4 congeladas) — es el único valor derivado a mano. */
.col-tool { left: 220px; width: 400px; min-width: 400px; max-width: 400px; overflow: hidden; text-overflow: ellipsis; }

/* Fix (2026-07-06, found while validating the perf quick wins — PRE-EXISTING since the DS-02.01 DsDataGrid
   retrofit): the scoped primitive rule `.ds-grid[b-…] .ds-grid__cell--frozen { left: 0 }` (specificity
   (0,3,0) — the [b-…] scope attribute counts at class level — and its bundle
   MtmpProjectsPoc.Web.styles.css loads AFTER this file) beats the per-column offsets above ((0,1,0)) —
   so ALL four frozen columns computed left:0 and stacked on top of each other under horizontal scroll
   (only col-tool remained visible; checkbox/expand/id buried underneath). Confirmed live with a
   styleSheets walker. th/td variants make these (0,3,1) > (0,3,0), re-winning the staggered offsets. */
.tracker-table-wrapper .tracker-table th.col-checkbox, .tracker-table-wrapper .tracker-table td.col-checkbox { left: 0; }
.tracker-table-wrapper .tracker-table th.col-expand, .tracker-table-wrapper .tracker-table td.col-expand { left: 40px; }
.tracker-table-wrapper .tracker-table th.col-id, .tracker-table-wrapper .tracker-table td.col-id { left: 70px; }
.tracker-table-wrapper .tracker-table th.col-tool, .tracker-table-wrapper .tracker-table td.col-tool { left: 220px; }
/* Punto #7 — la razón del último replan, pegada al contador: chip discreto que cabe en la casilla. */
.phase-delay-reason {
    display: inline-block;
    max-width: 100%;
    margin-top: 1px;
    padding: 0 4px;
    border-radius: var(--radius-sm);
    background: var(--med-gray-light, #edf2f7);
    color: var(--med-gray-dark, #4a5568);
    font-size: 0.65rem;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Story 11B.14 (Q9) — ProjectDisplayId cell: single-line ellipsis text + the warning "Intake" chip. */
.col-display-id .display-id-text {
    display: inline-block;
    max-width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
    font-weight: 600;
}

/* ProjectDisplayId is a link that opens the project detail in a new tab. Styled as an
   interactive link (brand blue, underline on hover) so the affordance reads as clickable. */
.col-display-id a.display-id-link {
    color: var(--med-blue-interactive, #0067b8);
    text-decoration: none;
    cursor: pointer;
}
.col-display-id a.display-id-link:hover,
.col-display-id a.display-id-link:focus-visible {
    text-decoration: underline;
}

/* Opción E (2026-07) — styled hover tooltip for truncated Tool/Phase/Task names.
   Rendered at <body> level by tracker-tooltip.js (a "portal") so the frozen col-tool's
   overflow:hidden never clips it. position:fixed because JS positions it in viewport
   coords (getBoundingClientRect). Matches the dark .comment-preview look already in the grid. */
.tracker-tooltip {
    position: fixed;
    z-index: 3000;
    max-width: 360px;
    background: #1e293b;
    color: #fff;
    padding: 6px 10px;
    border-radius: 6px;
    font-size: 0.75rem;
    line-height: 1.35;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
    pointer-events: none;
    white-space: normal;
    word-break: break-word;
}

/* UX-DS-05.02 (CB-1.a) — divisor frozen como barra 1px compuesta (background), SIN box-shadow.
   El box-shadow sobre position:sticky repinta la columna congelada en cada frame de scroll
   horizontal; una barra de background es un fill barato y el ::after es overlay (no afecta el
   layout, los offsets frozen de 520px quedan intactos). Look idéntico. */
.col-tool::after {
    content: '';
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--frozen-divider);
}

/* ===== ROWS ===== */
/* Zebra (Variant A --row-zebra). Va ANTES de hover/selected/expanded a propósito:
   misma especificidad → el orden de fuente deja ganar a los estados interactivos. */
.project-row.zebra,
.project-row.zebra .frozen {
    background: var(--row-zebra);
}

.project-row:hover {
    background: var(--row-hover);
}

/* UX-DS-05.02 (CB-1.b) — el hover del cuerpo se conserva (regla de arriba); el highlight del
   spine frozen se ELIMINA a propósito: repintar el background de la celda sticky mientras el
   cursor recorre el grid la repinta por frame. Decisión Ivan 2026-07-04 (diseño §7.2). */

.project-row.selected {
    background: var(--row-selected);
}

.project-row.selected .frozen {
    background: var(--row-selected);
}

.project-row.expanded {
    background: var(--row-hover);
}

.project-row.expanded .frozen {
    background: var(--row-hover);
}

/* Feedback 2026-08-20 (1a978554.c) — el fondo de la celda sticky SIGUE el color de su fila,
   determinísticamente. Las reglas de arriba (.project-row.zebra .frozen etc., (0,3,0)) pierden
   contra la regla del primitivo `.ds-grid[b-…] .ds-grid__cell--frozen { background: var(--bg-white) }`
   ((0,3,0) pero su bundle MtmpProjectsPoc.Web.styles.css carga DESPUÉS de este archivo), y la
   paridad quedaba a merced de las reglas de sincronía del bundle ((0,4,0)). Estas cuatro reglas
   ((0,4,2)/(0,5,2)) ganan a todo lo del bundle y fijan la cascada sin importar orden de carga.
   Orden zebra → selected → expanded = el mismo de arriba y el del primitivo (los estados
   interactivos ganan por orden de fuente a igual especificidad).
   HOVER omitido a propósito: CB-1.b (UX-DS-05.02, decisión Ivan 2026-07-04) eliminó el repintado
   del spine congelado en hover porque repinta la celda sticky por frame; la regla hover del
   primitivo (DsDataGrid.razor.css:95) queda ahora también superada por estas, aplicando por fin
   esa decisión de manera consistente. */
.tracker-table-wrapper .tracker-table tr.project-row > td.frozen {
    background: var(--bg-white);
}
.tracker-table-wrapper .tracker-table tr.project-row.zebra > td.frozen {
    background: var(--row-zebra);
}
.tracker-table-wrapper .tracker-table tr.project-row.selected > td.frozen {
    background: var(--row-selected);
}
.tracker-table-wrapper .tracker-table tr.project-row.expanded > td.frozen {
    background: var(--row-hover);
}

/* ===== ROW VARIANTS (Variant A) ===== */
/* Intake: SIN tratamiento visual por fila (decisión 2026-07-03). Antes las filas de fase
   "Intake Form" llevaban franja azul + tool-name azul negrita (clase `npd-row`), que se leía
   inconsistente (aparecía en una mezcla de INT-* y PRJ en DRAFT) y multi-barra. Se eliminó:
   las filas intake se ven uniformes; el estado read-only se comunica por el checkbox
   deshabilitado (`IsIntake` sigue gateando bulk-selection). NPD es un badge propio, no una fila. */

/* Completed: fila atenuada + Tool Name tachado (Variant A). */
.project-row.completed td {
    color: var(--med-gray-medium);
}
.project-row.completed .tool-name-text {
    text-decoration: line-through;
    text-decoration-color: var(--med-gray-light);
    text-decoration-thickness: 1px;
}

/* Tool Name en una sola línea + ellipsis para no romper la densidad de 32px.
   Opción B (2026-07): la columna congelada pasó de 220px→300px; el texto sube su
   max-width en el mismo delta (150→230) para aprovechar el ancho extra. */
.col-tool .tool-name-text {
    display: inline-block;
    max-width: 230px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

/* ===== PHASES CONTAINER ROW ===== */
.phases-container-row {
    background: #f8fafc;
}

.phases-container-row .frozen {
    background: #f8fafc;
}

.phases-indent {
    border-right: 2px solid #e2e8f0;
}

.phases-cell {
    padding: 12px 16px !important;
}

/* ===== PHASES TIMELINE ===== */
.phases-timeline {
    display: flex;
    align-items: stretch;
    gap: 0;
    overflow-x: auto;
    padding: 4px 0;
}

.phase-connector {
    width: 24px;
    min-width: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
}

.phase-connector::before {
    content: '';
    width: 100%;
    height: 2px;
    background: linear-gradient(90deg, #cbd5e1, #94a3b8);
}

/* ===== PHASE CARD (Tracker Timeline Only) ===== */
/* Scoped to .phases-timeline to avoid conflicts with PhaseCard component */
.phases-timeline .phase-card {
    background: white;
    border-radius: 8px;
    padding: 10px 14px;
    min-width: 160px;
    max-width: 180px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
    border: 1px solid #e2e8f0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    transition: all 0.2s ease;
}

.phases-timeline .phase-card:hover {
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
    transform: translateY(-1px);
}

.phases-timeline .phase-card-complete {
    border-color: #10b981;
    background: linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 100%);
}

.phases-timeline .phase-card-active {
    border-color: #3b82f6;
    background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
    box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);
}

.phases-timeline .phase-card-pending {
    border-color: #e2e8f0;
    background: #f8fafc;
    opacity: 0.7;
}

/* ===== PHASE HEADER ===== */
.phase-header {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* C-27 — aquí vivía la PRIMERA de las dos generaciones de puntos de fase que este mismo archivo
   traía: `.phase-status-dot` con `.dot-complete` / `.dot-active` / `.dot-pending` en hex crudo, y
   más abajo `.phase-status-indicator.dot-*` con tokens. Ninguna de las clases de esta generación
   tenía consumidor: el marcado emite siempre `phase-status-indicator dot-*`
   (`ProjectTracker.razor:1157`), así que la generación tokenizada ganaba por especificidad y esta
   solo servía para confundir a quien buscara "de qué color es un punto de fase". Se borra entera;
   el fix de contraste de C-07 se mudó a la regla viva, más abajo.
   El keyframe `pulse` se va con ella: sus otros tres consumidores
   (project-detail.css, ownership.css, site.css) declaran el suyo en su propio archivo. */

.phase-title {
    font-size: 0.75rem;
    font-weight: 600;
    color: #334155;
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.phase-progress-badge {
    font-size: 0.65rem;
    font-weight: 700;
    padding: 2px 6px;
    border-radius: 10px;
    white-space: nowrap;
}

.progress-badge-complete {
    background: #10b981;
    color: white;
}

.progress-badge-good {
    background: #3b82f6;
    color: white;
}

.progress-badge-started {
    background: #f59e0b;
    color: white;
}

.progress-badge-pending {
    background: #e2e8f0;
    color: #64748b;
}

/* ===== PHASE PROGRESS BAR ===== */
.phase-progress-bar {
    height: 4px;
    background: #e2e8f0;
    border-radius: 2px;
    overflow: hidden;
}

.phase-progress-fill {
    height: 100%;
    border-radius: 2px;
    transition: width 0.3s ease;
}

.fill-complete {
    background: linear-gradient(90deg, #10b981, #059669);
}

.fill-active {
    background: linear-gradient(90deg, #3b82f6, #2563eb);
}

.fill-pending {
    background: #cbd5e1;
}

/* ===== PHASE DATES ===== */
.phase-dates {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-top: 2px;
}

.phase-date-input {
    font-size: 0.65rem;
    padding: 2px 4px;
    border: 1px solid #e2e8f0;
    border-radius: 4px;
    background: white;
    color: #475569;
    width: 90px;
}

.phase-date-input:focus {
    border-color: #3b82f6;
    outline: none;
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
}

.phase-date-separator {
    color: #94a3b8;
    font-size: 0.7rem;
}

/* ===== PHASE COMMENT ===== */
.phase-comment {
    font-size: 0.65rem;
    color: #64748b;
    background: #f1f5f9;
    padding: 3px 6px;
    border-radius: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ===== PHASE ROWS V2 (Compact Table Format) ===== */
/* UX-DS-03.03 — filas phase al lenguaje variant-A (tr.row-phase): bg unificado
   (el ESTADO vive en el dot + color del nombre, no en el bg de la fila), tree-line
   └─ mono, dot 9px con phasePulse. Hex Tailwind tokenizados. */
.phase-row-v2 {
    background: var(--row-phase-bg);
    font-size: 11.5px;
    line-height: 1.2;
}

.phase-row-v2 td {
    padding: 4px 6px !important;
    border-bottom: 1px solid var(--grid-line);
    height: 28px;
    vertical-align: middle;
}

.phase-row-v2 .frozen,
.phase-row-v2.phase-complete .frozen,
.phase-row-v2.phase-in-progress .frozen,
.phase-row-v2.phase-pending .frozen {
    background: var(--row-phase-bg);
}

.phase-row-v2.phase-complete,
.phase-row-v2.phase-in-progress,
.phase-row-v2.phase-pending {
    background: var(--row-phase-bg);
}

/* Phase ID column */
.phase-row-v2 .phase-id {
    color: var(--med-gray-light);
    font-size: 0.7rem;
}

/* Phase Name Cell — indentación variant-A (18px). Especificidad (0,2,0) para
   ganar al `.phase-row-v2 td { padding: 4px 6px !important }` (0,1,1). */
.phase-row-v2 .phase-name-cell {
    padding-left: 18px !important;
}

.phase-name-content {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Tree-line └─ (variant-A .phase-tree) */
.phase-tree {
    font-family: var(--font-mono);
    color: var(--med-gray-light);
    letter-spacing: -0.5px;
    font-size: 0.9rem;
}

/* Dot de estado 9px (variant-A .phase-status-icon) */
.phase-status-indicator {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
}

/* C-27 — la generación superviviente, ahora contra el diccionario de estado de fase. */
.phase-status-indicator.dot-complete {
    background: var(--state-phase-completed-accent);
}

.phase-status-indicator.dot-active {
    background: var(--state-phase-inprogress-accent);
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--state-phase-inprogress-accent) 45%, transparent);
    animation: phasePulse 1.5s ease-in-out infinite;
}

/* C-07 — el punto de fase pendiente era un relleno claro sobre blanco: 1.48:1, prácticamente
   invisible. Un relleno claro no se rescata sin oscurecerlo hasta confundirlo con "completada",
   así que el estado pasa a un patrón de contorno — que además es el segundo portador de
   significado que pide el frente de accesibilidad. Borde a 7.38:1. */
.phase-status-indicator.dot-pending {
    background: var(--bg-white);
    border: 2px solid var(--state-phase-notstarted-fg);
    box-sizing: border-box;
}

@keyframes phasePulse {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--med-blue-interactive) 40%, transparent); }
    50%      { box-shadow: 0 0 0 5px transparent; }
}

@media (prefers-reduced-motion: reduce) {
    .phase-status-indicator.dot-active { animation: none; box-shadow: none; }
}

/* Nombre por estado (variant-A .phase-name) */
/* T-03 — el nombre de fase se cortaba contra la celda sin puntos suspensivos. */
.phase-name-text {
    font-weight: 600;
    color: var(--med-gray-dark);
    white-space: nowrap;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.phase-row-v2.phase-complete .phase-name-text { color: var(--status-success-deep); }
.phase-row-v2.phase-in-progress .phase-name-text { color: var(--med-blue-medium); }
.phase-row-v2.phase-pending .phase-name-text { color: var(--med-gray-medium); }

/* Phase Progress Cell */
.phase-progress-cell {
    min-width: 120px;
}

.phase-progress-wrapper {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* La celda adelantada abarca 4 columnas (ver ProjectTracker.razor): sin esto la barra, que es
   `flex: 1`, se estiraría a todo ese ancho y el porcentaje volvería a irse a la derecha. Se le
   fija un largo sobrio y el grupo se ancla al inicio, junto al nombre de la fase. */
.phase-progress-cell--lead .phase-progress-wrapper {
    justify-content: flex-start;
}
.phase-progress-cell--lead .phase-progress-bar-v2 {
    flex: none;
    width: 120px;
}

.phase-progress-bar-v2 {
    flex: 1;
    height: 4px;
    background: #e2e8f0;
    border-radius: 2px;
    overflow: hidden;
    min-width: 50px;
}

.phase-progress-fill-v2 {
    height: 100%;
    border-radius: 3px;
    transition: width 0.3s ease;
}

.phase-progress-fill-v2.fill-complete {
    background: linear-gradient(90deg, #10b981, #059669);
}

.phase-progress-fill-v2.fill-active {
    background: linear-gradient(90deg, #3b82f6, #2563eb);
}

.phase-progress-fill-v2.fill-pending {
    background: #cbd5e1;
}

.phase-progress-text {
    font-size: 0.7rem;
    font-weight: 600;
    min-width: 32px;
    text-align: right;
}

.phase-progress-text.progress-badge-complete {
    color: #059669;
}

.phase-progress-text.progress-badge-good {
    color: #2563eb;
}

.phase-progress-text.progress-badge-started {
    color: #d97706;
}

.phase-progress-text.progress-badge-pending {
    color: #94a3b8;
}

/* Fase fuera de alcance (Skipped / NotApplicable): sin barra ni porcentaje. */
.phase-progress-text--out-of-scope {
    color: #94a3b8;
    font-weight: 500;
}

/* Phase Status Badge */
.phase-status-cell {
    min-width: 90px;
}

.phase-status-badge {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 0.6rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.phase-badge-complete {
    background: #d1fae5;
    color: #065f46;
}

.phase-badge-active {
    background: #dbeafe;
    color: #1e40af;
}

.phase-badge-pending {
    background: #f1f5f9;
    color: #64748b;
}

/* ---------------------------------------------------------------------------------------------
   Story ft.02 — las TRES fechas de la sub-fila de fase, y el replan en la celda.

   Los dos <input type="date"> que vivían aquí (.phase-date-input-v2) se RETIRARON con su regla:
   mostraban la fecha real bajo encabezado de plan y descartaban lo tecleado. Hoy la línea base y
   la real se pintan como DATO (no como campo) y la única superficie editable es la fecha viva,
   que abre el popover de replan.

   Todo con tokens: cero valores de color en crudo, cero !important (FD-08 mantiene separados los
   dos diccionarios de semáforo, así que aquí no se usa ninguna paleta de estado).
   --------------------------------------------------------------------------------------------- */
.phase-date-cell {
    min-width: 100px;
}

/* Línea base: referencia atenuada. Es el compromiso congelado, no el titular de la fila. */
.phase-date-cell.is-baseline {
    color: var(--med-gray-medium);
}

.phase-baseline-lock {
    margin-right: 4px;
    font-size: 0.7rem;
}

/* Fecha real: la sella el sistema. Atenuada por la misma razón. */
.phase-date-cell.is-actual {
    color: var(--med-gray-medium);
}

/* Fecha viva + contador: la pieza central del finalista 1. */
.phase-live-cell {
    position: relative;
    white-space: nowrap;
}

.phase-live-trigger {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 4px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    font: inherit;
    font-size: 0.72rem;
    color: var(--med-gray-dark);
    cursor: pointer;
}

.phase-live-trigger:hover {
    border-color: var(--grid-line);
    background: var(--bg-white);
}

.phase-live-trigger:focus-visible {
    outline: 2px solid var(--med-blue-interactive);
    outline-offset: 1px;
}

/* El lápiz solo aparece al acercarse: la fila ya carga tres fechas, un candado y un contador. */
.phase-live-pencil {
    opacity: 0;
    font-size: 0.65rem;
    color: var(--med-blue-interactive);
}

.phase-live-trigger:hover .phase-live-pencil,
.phase-live-trigger:focus-visible .phase-live-pencil {
    opacity: 1;
}

/* Contador de replanes: SIEMPRE pegado a la fecha viva, nunca columna suelta (FD-07). */
.phase-replan-counter {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    margin-left: 4px;
    padding: 0 4px;
    border-radius: 8px;
    background: var(--med-yellow-bg);
    color: var(--med-yellow-deep);
    font-size: 0.62rem;
    font-weight: var(--font-weight-semibold);
}

/* ---- Popover de replan: anclado a la celda, no un modal de pantalla completa (FD-03) ---- */
.phase-replan-popover {
    position: absolute;
    z-index: 40;
    top: calc(100% + 4px);
    left: 0;
    width: 300px;
    border: 1px solid var(--med-blue-interactive);
    border-radius: var(--radius-md);
    background: var(--bg-white);
    box-shadow: 0 8px 24px var(--med-gray-lighter);
    text-align: left;
    white-space: normal;
}

.phase-replan-popover .replan-head {
    padding: 8px 12px;
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    background: var(--med-blue-primary);
    color: var(--bg-white);
    font-size: 0.75rem;
    font-weight: var(--font-weight-semibold);
}

.phase-replan-popover .replan-body {
    padding: 12px;
}

.phase-replan-popover .replan-label {
    display: block;
    margin-bottom: 4px;
    color: var(--med-gray-medium);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.phase-replan-popover .replan-hint {
    text-transform: none;
    letter-spacing: normal;
}

.phase-replan-popover .replan-required {
    color: var(--status-error-deep);
}

.phase-replan-popover .replan-baseline {
    margin-bottom: 12px;
    color: var(--med-gray-medium);
    font-size: 0.75rem;
}

.phase-replan-popover .replan-input,
.phase-replan-popover .replan-textarea {
    width: 100%;
    margin-bottom: 10px;
    padding: 6px 8px;
    border: 1px solid var(--grid-line);
    border-radius: var(--radius-sm);
    font-family: inherit;
    font-size: 0.78rem;
}

.phase-replan-popover .replan-textarea {
    min-height: 54px;
    resize: vertical;
}

.phase-replan-popover .replan-count {
    margin: -6px 0 10px;
    font-size: 0.65rem;
}

.phase-replan-popover .replan-count.is-valid {
    color: var(--status-success-deep);
}

.phase-replan-popover .replan-count.is-short {
    color: var(--med-gray-medium);
}

.phase-replan-popover .replan-error {
    margin-bottom: 10px;
    padding: 6px 8px;
    border-radius: var(--radius-sm);
    background: var(--status-error-bg);
    color: var(--status-error-deep);
    font-size: 0.7rem;
}

.phase-replan-popover .replan-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* Phase Comment Input */
.phase-comment-cell {
    min-width: 180px;
}

.phase-comment-input {
    width: 100%;
    padding: 2px 6px;
    border: 1px solid #e2e8f0;
    border-radius: 3px;
    font-size: 0.7rem;
    color: #475569;
    background: white;
    height: 22px;
}

.phase-comment-input::placeholder {
    color: #94a3b8;
    font-style: italic;
}

.phase-comment-input:focus {
    border-color: #3b82f6;
    outline: none;
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
}

/* ===== LEGACY PHASE ROWS (keeping for compatibility) ===== */
.phase-row {
    background: #fafafa;
}

.phase-row .frozen {
    background: #fafafa;
}

.phase-row .phase-name {
    padding-left: 24px;
    color: #666;
    font-size: 0.8rem;
    white-space: nowrap;
}

.phase-row.phase-complete {
    background: #f0fff4;
}

.phase-row.phase-complete .frozen {
    background: #f0fff4;
}

.phase-row.phase-in-progress {
    background: #fff8e6;
}

.phase-row.phase-in-progress .frozen {
    background: #fff8e6;
}

.phase-row.phase-pending {
    background: #fafafa;
}

/* ===== EXPAND BUTTON ===== */
.expand-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 0.75rem;
    color: #666;
    padding: 4px;
    border-radius: 4px;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.expand-btn:hover {
    background: #e5e5e5;
}

/* ===== EDITABLE CELLS ===== */
.cell-editable input,
.cell-editable select,
.cell-editable textarea {
    width: 100%;
    padding: 4px 8px;
    border: 1px dashed #d4d4d4;
    border-radius: 4px;
    background: transparent;
    font-size: 0.8rem;
    font-family: inherit;
}

.cell-editable input:focus,
.cell-editable select:focus,
.cell-editable textarea:focus {
    /* UX-DS-05.03b (feedback Ivan) — single focus rectangle. The old `border` + offset `outline` drew TWO
       concentric rectangles (the outline sits outside the border with a gap); with CB-2 auto-focusing the
       editor on activate it showed immediately as a "double rectangle". Keep one crisp solid-blue border as
       the focus affordance (dashed-grey → solid-blue is a clear state change); no separate outline. */
    border-color: #1010EB;
    border-style: solid;
    outline: none;
    background: white;
}

/* UX-DS-05.03b/05.05 (feedback Ivan) — fix the "double rectangle" on the ACTIVE editing cell. DevTools pinned
   the two frames: the <td>.cell-selected 2px blue inset ring (OUTER) + the editor input's own border (INNER),
   the latter forced by GLOBAL app-wide rules in create-project-hotfix.css (`input[type=…] { border: 1.5px …
   !important; padding: 10px 14px !important }` + `input:focus { border-color/box-shadow glow !important;
   transform: translateY(-1px) }`).
   WHY specificity alone could never win: since UX-DS-02.03 the hotfix is imported into `@layer overrides`
   (design-system/index.css) — and for `!important` declarations the layer cascade INVERTS: a layered
   !important beats ANY unlayered !important regardless of specificity. This file is unlayered, so its
   previous (0,3,2) !important rule silently lost to the hotfix's (0,1,1). The fix must therefore live
   INSIDE `@layer overrides` too — same layer, so specificity decides again and (0,3,2) beats (0,1,1).
   Validated live (Playwright, styleSheets walker + computed styles) on 2026-07-06.
   Result: the td's blue ring is the single frame; the input fills it borderless, flat and white (the editor
   auto-focuses on mount, CB-2). Padding reset so the input fits the 32px row; transform/box-shadow reset to
   kill the hotfix's focus glow + 1px lift. */
@layer overrides {
    .tracker-table-wrapper td.cell-editable.cell-selected input,
    .tracker-table-wrapper td.cell-editable.cell-selected select,
    .tracker-table-wrapper td.cell-editable.cell-selected textarea {
        border: 0 !important;
        box-shadow: none !important;
        outline: none !important;
        padding: 4px 8px !important;
        transform: none !important;
        background: #fff !important;
    }

    /* <select> only: with `appearance: auto` Chrome/macOS paints the NATIVE menulist bezel, which ignores
       `border: 0` — the surviving "inner rectangle" on dropdown editors (feedback Ivan, screenshot 2026-07-06;
       date/text/textarea editors draw no bezel, which is why they were already clean). appearance:none drops
       the bezel AND the native arrow, so a small CSS chevron takes its place (background-image beats the base
       rule's `background: #fff` shorthand above by source order at equal specificity, same layer). */
    .tracker-table-wrapper td.cell-editable.cell-selected select {
        appearance: none !important;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23555' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E") !important;
        background-repeat: no-repeat !important;
        background-position: right 6px center !important;
        padding-right: 22px !important;
    }

    /* Dirty (unsaved) active editor keeps its yellow fill — the base rule's `background: #fff` shorthand
       above would otherwise override the unlayered `.cell-editable .dirty` marker. (0,4,1) > (0,3,2). */
    .tracker-table-wrapper td.cell-editable.cell-selected .dirty {
        background-color: #fffde7 !important;
    }
}

.cell-editable .dirty {
    background: #fffde7 !important;
    border-color: #ffc107 !important;
    border-style: solid !important;
}

.cell-editable textarea {
    resize: none;
    min-height: 28px;
}

.col-wide {
    /* fixed table-layout sizes columns from the header row's `width` (min-width alone no longer widens
       the column) — keep min-width for safety, width is what the fixed algorithm reads. */
    width: 240px;
    min-width: 200px;
}

/* ===== UX-DS-05.05 (CB-4) — <Virtualize> loading skeleton (feedback Ivan) ===== */
/* The momentary blank on fast vertical scroll is Blazor Server's RENDER round-trip (the newly-scrolled
   window is patched over SignalR AFTER the scroll), NOT data loading — so <Virtualize>'s Placeholder slot
   (which only fills an ASYNC ItemsProvider's data gap) does not apply.
   WHY the skeleton must live on the <table> and nowhere lower: per the CSS table painting model, the
   background of a row / row-group (tr, tbody) is only ever painted BEHIND CELLS — the Virtualize spacer
   <tr> has NO cells, so a tbody/tr background never paints in the spacer area (confirmed live: the tbody
   had the gradient in computed styles yet the viewport stayed white; elementFromPoint mid-scroll returned
   the TABLE, whose white background was what the user saw). The <table> element is the only one whose
   background paints its full box regardless of cells, so the stripes go here. Static stripes (no
   animation), so prefers-reduced-motion needs no special casing. Validated live (Playwright mid-scroll
   screenshot) on 2026-07-06. !important beats the scoped DsDataGrid bundle's `.ds-grid { background:
   var(--bg-white) }` (MtmpProjectsPoc.Web.styles.css, loaded after this file). */
.tracker-table-wrapper table.tracker-table {
    background-color: #f6f6f8 !important;
    background-image: repeating-linear-gradient(
        to bottom,
        #e4e4ea 0,
        #e4e4ea 18px,          /* skeleton "row" band */
        #f6f6f8 18px,
        #f6f6f8 32px           /* gap → 32px stripe = ItemSize (row height) */
    ) !important;
}
/* Real rows (any <tr> WITH cells) get an opaque row background so they cover the table skeleton; the empty
   Virtualize spacer <tr>s (no cells) are excluded (their background would not paint anyway), so the skeleton
   shows through them. Zebra/hover/selected cell backgrounds sit on top of this per-cell, so striping and
   states are unaffected. thead cells keep their own opaque header background, covering the stripes up top. */
.tracker-table-wrapper .ds-grid__body tr:not(:empty) {
    background-color: #fff !important;
}

/* ===== BADGES ===== */
/* T-02 — `nowrap` sin recorte propio: la insignia empujaba la celda en vez de recortarse.
   Trío canónico (el mismo de .col-tool): nowrap + overflow + ellipsis. */
.badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 4px;
    font-size: 0.7rem;
    font-weight: 600;
    white-space: nowrap;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: bottom;
}

/* C-13 / C-15 / C-26 — aquí vivían las familias legacy `.badge-priority-*` y `.badge-status-*`,
   siete clases con su propia paleta en hex crudo. La nota decía que quedaban "para consumidores
   residuales fuera del grid"; no había ninguno: `grep` sobre Pages/, Components/ y Shared/ no
   encuentra ni una. Los únicos helpers que las emitían eran los tres helpers muertos del
   code-behind del tracker, borrados en esta misma fase.
   Eran deuda con detonador: `.badge-priority-medium` pintaba de amarillo lo que el panel lateral
   pintaba de azul, y `.badge-priority-low` usaba el VERDE de "completado" para decir "prioridad
   baja". Cualquiera que las hubiera reconectado habría reintroducido la contradicción entera.
   El vocabulario vigente es `.state-badge--*` (state-tokens.css) vía StatusBadgeClass. */

/* Type — legacy (ver nota arriba) */
.badge-type-replacement { background: #e2e3e5; color: #383d41; }
.badge-type-refurbishment { background: #d1ecf1; color: #0c5460; }
.badge-type-repair { background: #fff3cd; color: #856404; }
.badge-type-eol { background: #f8d7da; color: #721c24; }
.badge-type-duplication { background: #d4edda; color: #155724; }

/* ============================================================================
   UX-DS-03.02 — DsBadge dentro del grid del tracker: geometría + paleta soft
   variant-A (.badge del prototipo: 2px 8px, radius 3, 10px/700, ls 0.5px).
   Los VALORES PRE-EXISTENTES solid de DsBadge (draft/on-hold/completed/on-track/
   at-risk/delayed/active) NO se voltean globalmente (FD-G) — aquí se re-visten
   SOLO dentro del tracker con override page-scoped. Especificidad (0,3,0)+ para
   ganar a la regla scoped del bundle (.ds-badge--*[b-x] = 0,2,0).
   ============================================================================ */
.tracker-container .tracker-table .ds-badge {
    padding: 2px 8px;
    border-radius: 3px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.5px;
}
.tracker-container .tracker-table .ds-badge:hover { transform: none; }
.tracker-container .tracker-table .ds-badge--status-draft {
    background-color: var(--med-gray-lightest);
    color: var(--med-gray-medium);
}
.tracker-container .tracker-table .ds-badge--status-on-hold {
    background-color: var(--status-warning-bg);
    color: var(--med-yellow-deep);
}
.tracker-container .tracker-table .ds-badge--status-completed {
    background-color: var(--badge-status-complete-bg);
    color: var(--badge-status-complete-text);
}
.tracker-container .tracker-table .ds-badge--status-active,
.tracker-container .tracker-table .ds-badge--status-on-track {
    background-color: var(--status-success-bg);
    color: var(--status-success-deep);
}
.tracker-container .tracker-table .ds-badge--status-at-risk {
    background-color: var(--status-warning-bg);
    color: var(--med-yellow-deep);
    animation: none;
}
.tracker-container .tracker-table .ds-badge--status-delayed {
    background-color: var(--status-error-bg);
    color: var(--status-error-deep);
    animation: none;
}

/* Phase */
.badge-phase { background: var(--med-blue-interactive); color: var(--text-inverse); }

/* ────────────────────────────────────────────────────────────────────────────
   Story 8.6 — derived per-phase SCHEDULE-HEALTH indicator (read-only).
   Two surfaces: (a) a left-border accent on the Current Phase badge, and
   (b) a dedicated "Phase Status" chip. Palette reuses the tracker dot/badge
   tokens; chips use light bg + dark text for AA contrast (>= 4.5:1).
   ──────────────────────────────────────────────────────────────────────────── */

/* (a) Current Phase badge accent — keeps the white-on-blue name legible, adds a schedule tint.
   C-06 — los seis acentos eran hex saturados sobre un fondo azul intenso, y el peor estado de
   salud era el menos visible: `offtrack` con #dc3545 quedaba en 2.02:1 sobre el badge. La
   corrección es la que pide el plan (aclarar el acento, no cambiar el fondo): cada tinte pasa
   a la variante clara del mismo token de estado, con lo que los seis superan 3:1 sin perder el
   código de color. `atrisk` conserva el amarillo saturado porque ya pasaba (6.13:1). */
.badge-phase.schedule-completed   { box-shadow: inset 3px 0 0 var(--state-schedule-completed-bg); }
.badge-phase.schedule-ontrack     { box-shadow: inset 3px 0 0 var(--state-schedule-ontrack-bg); }
.badge-phase.schedule-atrisk      { box-shadow: inset 3px 0 0 var(--state-schedule-atrisk-bg); }
.badge-phase.schedule-offtrack    { box-shadow: inset 3px 0 0 var(--state-schedule-offtrack-bg); }
.badge-phase.schedule-notstarted  { box-shadow: inset 3px 0 0 var(--state-schedule-notstarted-bg); }
/* `notstarted` y `unscheduled` comparten tinte en ESTE acento de 3px: los dos acentos oscuros que
   los distinguirían no alcanzan 3:1 sobre el azul de la insignia. Es el mismo empate que había
   antes (#cbd5e1 vs #e2e8f0, indistinguibles a simple vista); la diferencia entre los dos estados
   la lleva el texto de la insignia dedicada `.schedule-badge`, que sí los separa. */
.badge-phase.schedule-unscheduled { box-shadow: inset 3px 0 0 var(--state-schedule-unscheduled-bg); }

/* (b) Dedicated Phase Status chip. */
.schedule-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    border: 1px solid transparent;
}
/* C-28 — estas seis líneas estaban copiadas CARÁCTER POR CARÁCTER en dos archivos
   (`tracker-view.css` y `Components/Tasks/TaskListItem.razor.css`): la misma familia de salud de
   calendario, mantenida a mano por duplicado. Ahora las dos apuntan al mismo dominio del
   diccionario, así que un cambio de paleta las mueve juntas. */
.schedule-badge.schedule-completed   { background: var(--state-schedule-completed-bg);   color: var(--state-schedule-completed-fg);   border-color: var(--state-schedule-completed-accent); }
.schedule-badge.schedule-ontrack     { background: var(--state-schedule-ontrack-bg);     color: var(--state-schedule-ontrack-fg);     border-color: var(--state-schedule-ontrack-accent); }
.schedule-badge.schedule-atrisk      { background: var(--state-schedule-atrisk-bg);      color: var(--state-schedule-atrisk-fg);      border-color: var(--state-schedule-atrisk-accent); }
.schedule-badge.schedule-offtrack    { background: var(--state-schedule-offtrack-bg);    color: var(--state-schedule-offtrack-fg);    border-color: var(--state-schedule-offtrack-accent); }
.schedule-badge.schedule-notstarted  { background: var(--state-schedule-notstarted-bg);  color: var(--state-schedule-notstarted-fg);  border-color: var(--state-schedule-notstarted-accent); }
.schedule-badge.schedule-unscheduled { background: var(--state-schedule-unscheduled-bg); color: var(--state-schedule-unscheduled-fg); border-color: var(--state-schedule-unscheduled-accent); }

/* FY */
.badge-fy { background: #FFCE00; color: black; font-weight: 700; }

/* ABC Codes */
.badge-abc-aplus { background: #7c3aed; color: white; font-weight: 700; }
.badge-abc-a { background: #10b981; color: white; }
.badge-abc-b { background: #3b82f6; color: white; }
.badge-abc-c { background: #94a3b8; color: white; }

/* CDP/SCC Code */
.cdp-code {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.75rem;
    background: #f1f5f9;
    padding: 2px 6px;
    border-radius: 3px;
    color: #475569;
    white-space: nowrap;
}

/* Confidence - for select styling */
.select-confidence-high { background: #f8d7da; }
.select-confidence-medium { background: #fff3cd; }
.select-confidence-low { background: #d4edda; }
.select-confidence-no-chance { background: #e2e3e5; }
.select-confidence-na { background: #f8f9fa; }

/* ===== CHECKLIST STATUS (CDP/SCC, PPAP, GRR/TMV/MSA) ===== */
.select-checklist-not-ready { background: #e2e8f0; color: #475569; }
.select-checklist-development { background: #dbeafe; color: #1e40af; }
.select-checklist-wip { background: #fef3c7; color: #92400e; }
.select-checklist-approved { background: #d1fae5; color: #065f46; }
.select-checklist-drafted { background: #ede9fe; color: #5b21b6; }

/* ===== EXECUTION STATUS (Supplier OQ Pass) ===== */
.select-execution-not-started { background: #f1f5f9; color: #64748b; }
.select-execution-in-progress { background: #dbeafe; color: #1e40af; }
.select-execution-passed { background: #d1fae5; color: #065f46; }
.select-execution-failed { background: #fee2e2; color: #b91c1c; }
.select-execution-no-data { background: #fef3c7; color: #92400e; }

/* ===== DATE CHANGES BADGE ===== */
.badge-date-changes {
    background: #f59e0b;
    color: white;
    padding: 2px 6px;
    border-radius: 10px;
    font-size: 0.7rem;
    font-weight: 700;
}

/* ===== PART/ASSET CODES ===== */
.part-code {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.7rem;
    background: #f1f5f9;
    padding: 2px 4px;
    border-radius: 3px;
    color: #475569;
    white-space: nowrap;
}

/* ===== CURRENCY FORMATTING ===== */
.cell-currency {
    text-align: right;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.8rem;
    color: #059669;
    font-weight: 500;
}

/* ===== PROGRESS BAR ===== */
.progress-bar-container {
    display: flex;
    align-items: center;
    gap: 4px;
    width: 70px;
}

.progress-bar-container.small {
    width: 60px;
}

.progress-bar-fill {
    height: 6px;
    background: #e5e5e5;
    border-radius: 3px;
    flex: 1;
    position: relative;
    overflow: hidden;
}

.progress-bar-fill::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: inherit;
    background: #1010EB;
    border-radius: 3px;
}

.progress-bar-text {
    font-size: 0.7rem;
    color: #666;
    min-width: 28px;
    text-align: right;
}

/* Alternative progress bar implementation */
.progress-bar-container {
    display: flex;
    align-items: center;
    gap: 6px;
}

.progress-bar-container .progress-bar-fill {
    width: 40px;
    height: 6px;
    background: linear-gradient(to right, #1010EB var(--progress, 0%), #e5e5e5 var(--progress, 0%));
    border-radius: 3px;
}

/* ===== PHASE ICONS ===== */
.phase-icon {
    font-size: 0.9rem;
}

/* ===== TOAST ===== */
.toast-success {
    position: fixed;
    top: 20px;
    right: 20px;
    background: #d4edda;
    color: #155724;
    padding: 12px 24px;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    z-index: 2000;
    animation: slideIn 0.3s ease-out;
}

@keyframes slideIn {
    from {
        transform: translateX(100%);
        opacity: 0;
    }
    to {
        transform: translateX(0);
        opacity: 1;
    }
}

/* Story 11B.05 — warning-style toast for partial saves (some rows skipped/failed). */
.toast-warning {
    position: fixed;
    top: 20px;
    right: 20px;
    background: #FFF4D0;
    color: #7a5b00;
    border: 1px solid var(--med-yellow, #FFCE00);
    padding: 12px 24px;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    z-index: 2000;
    animation: slideIn 0.3s ease-out;
}

/* Story 11B.05 — inline Save spinner (fallback if Bootstrap's .spinner-border is unavailable). */
.spinner-border {
    display: inline-block;
    width: 0.9rem;
    height: 0.9rem;
    vertical-align: -0.125em;
    border: 0.15em solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: spinner-border 0.75s linear infinite;
}

.spinner-border-sm {
    width: 0.8rem;
    height: 0.8rem;
    border-width: 0.13em;
}

@keyframes spinner-border {
    to { transform: rotate(360deg); }
}

/* ===== Story 11B.05 — BULK SAVE RESULT SUMMARY MODAL (3 buckets) ===== */
.bulk-result-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 2500;
}

.bulk-result-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(640px, 92vw);
    max-height: 84vh;
    overflow: auto;
    background: #fff;
    border-radius: 10px;
    box-shadow: 0 12px 40px rgba(0,0,0,0.25);
    z-index: 2600;
    display: flex;
    flex-direction: column;
}

.bulk-result-modal .modal-header,
.bulk-result-modal .modal-footer {
    display: flex;
    align-items: center;
    padding: 14px 20px;
}

.bulk-result-modal .modal-header {
    border-bottom: 1px solid #e5e7eb;
    justify-content: space-between;
}

.bulk-result-modal .modal-footer {
    border-top: 1px solid #e5e7eb;
    justify-content: flex-end;
}

.bulk-result-modal .modal-body {
    padding: 16px 20px;
}

.bulk-result-headline {
    font-weight: 600;
    margin-bottom: 12px;
}

.bulk-result-bucket {
    margin-bottom: 14px;
}

.bulk-result-bucket .bucket-title {
    font-size: 0.95rem;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

.bulk-result-bucket .bucket-count {
    font-family: var(--font-mono, monospace);
    background: #eef0f4;
    border-radius: 9px;
    padding: 1px 9px;
    font-size: 12px;
}

.bucket-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.bucket-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 5px 0;
    border-bottom: 1px dashed #eee;
    font-size: 0.85rem;
}

.bucket-row-project { font-weight: 600; }
.bucket-row-field { font-family: var(--font-mono, monospace); color: #475569; }
.bucket-row-detail { color: #94a3b8; }
.bucket-failed .bucket-count { background: #fde2e1; color: #991b1b; }
.bucket-skipped .bucket-count { background: #fff4d0; color: #7a5b00; }
.bucket-succeeded .bucket-count { background: #d4edda; color: #155724; }

/* ===== UNSAVED CHANGES BAR ===== */
.unsaved-changes-bar {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: linear-gradient(90deg, var(--med-yellow-bg), #FFF4D0);
    border-top: 2px solid var(--med-yellow);
    color: var(--med-yellow-deep);
    font-weight: 600;
    padding: 11px 24px;
    display: flex;
    align-items: center;
    gap: 12px;
    box-shadow: var(--shadow-up);
    z-index: 1000;
}

.unsaved-changes-bar .warning-icon {
    font-size: 1.25rem;
}

/* Pill de conteo (Variant A): mono, fondo amarillo translúcido, texto azul. */
.unsaved-changes-bar .changes-count {
    background: rgba(255, 206, 0, 0.5);
    color: var(--med-blue-primary);
    font-family: var(--font-mono);
    font-weight: 700;
    border-radius: 9px;
    padding: 1px 9px;
    font-size: 11.5px;
}

.unsaved-changes-bar .actions {
    margin-left: auto;
    display: flex;
    gap: 12px;
}

/* ===== BUTTONS ===== */
.btn {
    padding: 8px 16px;
    border-radius: 4px;
    font-weight: 500;
    cursor: pointer;
    border: none;
    font-size: 0.875rem;
    transition: background 0.2s;
}

.btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.btn-primary {
    background: #1010EB;
    color: white;
}

.btn-primary:hover:not(:disabled) {
    background: #0d0dbd;
}

.btn-secondary {
    background: #e5e5e5;
    color: #333;
}

.btn-secondary:hover:not(:disabled) {
    background: #d4d4d4;
}

.btn-outline-secondary {
    background: transparent;
    border: 1px solid #d4d4d4;
    color: #333;
}

.btn-outline-secondary:hover:not(:disabled) {
    background: #f5f5f5;
}

.btn-outline-primary {
    background: transparent;
    border: 1px solid #1010EB;
    color: #1010EB;
}

.btn-outline-primary:hover:not(:disabled) {
    background: #f0f0ff;
}

/* ===== SCROLLBAR STYLING ===== */
.tracker-table-wrapper::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

.tracker-table-wrapper::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 4px;
}

.tracker-table-wrapper::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 4px;
}

.tracker-table-wrapper::-webkit-scrollbar-thumb:hover {
    background: #a8a8a8;
}

/* ===== COMMENT INDICATOR ===== */
.comment-indicator-wrapper {
    position: relative;
    display: inline-flex;
}

.comment-indicator {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 6px;
    border: 1px solid #e2e8f0;
    border-radius: 4px;
    background: #f8fafc;
    cursor: pointer;
    transition: all 0.15s ease;
    font-size: 0.75rem;
    color: #64748b;
}

.comment-indicator:hover {
    background: #f1f5f9;
    border-color: #cbd5e1;
}

.comment-indicator.has-comments {
    background: #eff6ff;
    border-color: #bfdbfe;
    color: #3b82f6;
}

.comment-indicator.has-comments:hover {
    background: #dbeafe;
}

.comment-indicator.has-new {
    background: #fef3c7;
    border-color: #fcd34d;
    color: #d97706;
    animation: pulse-new 2s ease-in-out infinite;
}

@keyframes pulse-new {
    0%, 100% { box-shadow: 0 0 0 0 rgba(251, 191, 36, 0.4); }
    50% { box-shadow: 0 0 0 4px rgba(251, 191, 36, 0); }
}

.comment-icon {
    font-size: 0.85rem;
    line-height: 1;
}

.comment-count {
    font-weight: 600;
    font-size: 0.7rem;
}

.comment-new-badge {
    width: 6px;
    height: 6px;
    background: #ef4444;
    border-radius: 50%;
    position: absolute;
    top: -2px;
    right: -2px;
}

/* Size variations */
.comment-indicator.size-sm {
    padding: 2px 5px;
    font-size: 0.7rem;
}

.comment-indicator.size-md {
    padding: 4px 8px;
    font-size: 0.8rem;
}

.comment-indicator.size-lg {
    padding: 6px 10px;
    font-size: 0.9rem;
}

/* Comment Preview (on hover) */
.comment-preview {
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    background: #1e293b;
    color: white;
    padding: 8px 12px;
    border-radius: 6px;
    font-size: 0.7rem;
    width: 220px;
    z-index: 100;
    margin-bottom: 6px;
    opacity: 0;
    visibility: hidden;
    transition: all 0.2s ease;
    box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}

.comment-indicator-wrapper:hover .comment-preview {
    opacity: 1;
    visibility: visible;
}

.comment-preview::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-top-color: #1e293b;
}

.preview-header {
    display: flex;
    justify-content: space-between;
    margin-bottom: 4px;
    font-size: 0.65rem;
    opacity: 0.8;
}

.preview-author {
    font-weight: 600;
}

.preview-text {
    line-height: 1.4;
}

/* ===== COMMENTS MODAL ===== */
.comments-modal-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    animation: fadeIn 0.2s ease;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

.comments-modal {
    background: white;
    border-radius: 12px;
    width: 90%;
    max-width: 520px;
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
    animation: slideUp 0.25s ease;
}

@keyframes slideUp {
    from { transform: translateY(20px); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
}

.comments-modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 20px;
    border-bottom: 1px solid #e5e7eb;
    background: linear-gradient(135deg, #001E46 0%, #002855 100%);
    border-radius: 12px 12px 0 0;
}

.header-info {
    display: flex;
    align-items: center;
    gap: 12px;
}

.modal-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    color: white;
    display: flex;
    align-items: center;
    gap: 8px;
}

.context-badge {
    font-size: 0.65rem;
    padding: 2px 8px;
    border-radius: 10px;
    font-weight: 600;
    text-transform: uppercase;
}

.context-project {
    background: #dbeafe;
    color: #1e40af;
}

.context-phase {
    background: #d1fae5;
    color: #065f46;
}

.context-task {
    background: #fef3c7;
    color: #92400e;
}

.close-btn {
    background: transparent;
    border: none;
    color: rgba(255,255,255,0.8);
    cursor: pointer;
    padding: 4px;
    border-radius: 4px;
    transition: all 0.15s ease;
}

.close-btn:hover {
    background: rgba(255,255,255,0.1);
    color: white;
}

.comments-modal-subheader {
    padding: 10px 20px;
    background: #f8fafc;
    border-bottom: 1px solid #e5e7eb;
    display: flex;
    align-items: center;
    gap: 10px;
}

.item-name {
    font-weight: 600;
    color: #1e293b;
    font-size: 0.9rem;
}

.item-id {
    font-size: 0.75rem;
    padding: 2px 6px;
    background: #e2e8f0;
    border-radius: 4px;
    color: #475569;
}

.comments-modal-body {
    flex: 1;
    overflow-y: auto;
    padding: 16px 20px;
    max-height: 350px;
}

.no-comments {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;
    color: #94a3b8;
    text-align: center;
}

.no-comments i {
    font-size: 2.5rem;
    margin-bottom: 12px;
    opacity: 0.5;
}

.no-comments p {
    margin: 0;
    font-weight: 600;
    color: #64748b;
}

.no-comments span {
    font-size: 0.85rem;
    margin-top: 4px;
}

.comments-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.comment-item {
    display: flex;
    gap: 12px;
    padding: 12px;
    background: #f8fafc;
    border-radius: 8px;
    border: 1px solid #e5e7eb;
    transition: all 0.15s ease;
}

.comment-item:hover {
    background: #f1f5f9;
}

.comment-item.is-new {
    background: #fffbeb;
    border-color: #fcd34d;
}

.comment-item.legacy {
    background: #f5f5f5;
    border-style: dashed;
}

.comment-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: 700;
    color: white;
    flex-shrink: 0;
}

.comment-item.legacy .comment-avatar {
    background: #94a3b8;
}

.comment-content {
    flex: 1;
    min-width: 0;
}

.comment-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
    flex-wrap: wrap;
}

.comment-author {
    font-weight: 600;
    font-size: 0.85rem;
    color: #1e293b;
}

.comment-date {
    font-size: 0.75rem;
    color: #94a3b8;
}

.comment-type-badge {
    font-size: 0.6rem;
    padding: 2px 6px;
    border-radius: 4px;
    font-weight: 600;
}

.comment-type-badge.status {
    background: #dbeafe;
    color: #1e40af;
}

.comment-type-badge.delay {
    background: #fee2e2;
    color: #b91c1c;
}

.comment-type-badge.escalation {
    background: #fef3c7;
    color: #92400e;
}

.comment-type-badge.resolution {
    background: #d1fae5;
    color: #065f46;
}

.new-badge {
    font-size: 0.6rem;
    padding: 1px 5px;
    background: #ef4444;
    color: white;
    border-radius: 3px;
    font-weight: 700;
}

.comment-text {
    font-size: 0.85rem;
    color: #374151;
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-word;
}

.comments-modal-footer {
    padding: 16px 20px;
    border-top: 1px solid #e5e7eb;
    background: #f8fafc;
    border-radius: 0 0 12px 12px;
}

.new-comment-form {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.comment-type-selector {
    display: flex;
    gap: 4px;
}

.type-btn {
    padding: 6px 10px;
    border: 1px solid #e2e8f0;
    background: white;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.15s ease;
    font-size: 0.85rem;
}

.type-btn:hover {
    background: #f1f5f9;
}

.type-btn.active {
    background: #001E46;
    color: white;
    border-color: #001E46;
}

.comment-input-wrapper {
    display: flex;
    gap: 8px;
}

.comment-input {
    flex: 1;
    padding: 10px 12px;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    font-size: 0.875rem;
    resize: none;
    font-family: inherit;
    transition: border-color 0.15s ease;
}

.comment-input:focus {
    outline: none;
    border-color: #3b82f6;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}

.send-btn {
    padding: 10px 16px;
    background: #001E46;
    color: white;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.15s ease;
}

.send-btn:hover:not(:disabled) {
    background: #002855;
}

.send-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ===== HORIZONTAL SCROLL INDICATORS ===== */
/* Feedback 2026-08-20 (1a978554) — los degradados viven en el SHELL (que no scrollea), no en el
   wrapper: un pseudo-elemento absoluto dentro del scroll container se posiciona en coordenadas de
   CONTENIDO y viaja con él (el degradado derecho quedaba flotando a media tabla al scrollear).
   Anclados al shell quedan pegados a los bordes VISIBLES del grid. Las clases has-scroll-left/right
   las alterna tracker-scroll-indicators.js según scrollLeft/scrollWidth reales (antes
   has-scroll-right venía hardcodeada en el markup y has-scroll-left no se activaba nunca).
   bottom:8px respeta la franja del scrollbar horizontal del wrapper. */
.tracker-grid-shell.has-scroll-right::after {
    content: '';
    position: absolute;
    right: 0;
    top: 0;
    bottom: 8px;
    width: 40px;
    background: linear-gradient(to left, rgba(0,0,0,0.08), transparent);
    pointer-events: none;
    z-index: 20;
}

.tracker-grid-shell.has-scroll-left::before {
    content: '';
    position: absolute;
    left: 620px; /* After frozen columns (checkbox 40 + expand 30 + id 150 + tool 400) — Story 11B.14; tool widened 220→300 (opción B, 2026-07) y 300→400 (2026-08-21, cabe el selector de estado) */
    top: 0;
    bottom: 8px;
    width: 20px;
    background: linear-gradient(to right, rgba(0,0,0,0.05), transparent);
    pointer-events: none;
    z-index: 20;
}

/* UX-DS-05.02 (CB-1.c) — animación scrollHint ELIMINADA. Una animación opacity infinita sobre
   la franja de 40px (sin capa propia) repinta esa región de forma continua, incluso en reposo.
   El gradiente estático de .has-scroll-right::after (arriba) ya comunica "hay más a la derecha". */

/* ================================
   TASK ROWS - UX SPECIFICATION
   Medtronic Design System Compliant
   ================================ */

/* UX-DS-03.03 — filas task al lenguaje variant-A (tr.row-task): tree ├─/└─,
   task-cb span 12px (complete=check verde / progress=dot azul), assignee pill,
   line-through en completadas. Hex tokenizados. */
.task-row {
    background: var(--row-task-bg);
    font-size: 11.5px;
    transition: background-color 150ms ease-out;
}

.task-row td {
    /* UX-DS-03.04 — variant-A tr.row-task td: height 26px + padding 0 12px
       (la altura la fija el token, no el padding vertical). */
    padding: 0 12px;
    height: var(--grid-row-h-task);
    border-bottom: 1px solid var(--grid-line);
    vertical-align: middle;
}

.task-row .frozen {
    background: var(--row-task-bg);
}

.task-row:hover {
    background: var(--row-hover);
}

.task-row:hover .frozen {
    background: var(--row-hover);
}

/* Task Name Cell — indentación variant-A (36px) */
/* #778 — el selector estaba SIN acotar y `.task-name-cell` no es exclusiva del tracker: la misma
   clase la emite `Components/Tasks/TaskListItem.razor`, el renglón de tarea de la tarjeta de fase.
   Resultado: una sangría pensada para la jerarquía del tracker le comía 36px al nombre de cada
   tarea en el detalle de proyecto, en una columna que ya iba corta. Se acota al renglón del
   tracker (`.task-row`, que es donde vive el `<td>` de ProjectTracker.razor:1235). */
.task-row .task-name-cell {
    padding-left: 36px !important;
}

.task-name-content {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Tree-line ├─/└─ (variant-A .task-tree) */
.task-tree {
    font-family: var(--font-mono);
    color: var(--med-gray-light);
    letter-spacing: -0.5px;
    font-size: 0.9rem;
}

/* Checkbox visual (variant-A .task-cb). Story TOP.01 — ahora es un BUTTON operable:
   mismo dibujo del grid (FD-T6, embebido en fila), con reset de apariencia de botón. */
.task-cb {
    display: inline-block;
    width: 12px;
    height: 12px;
    border: 1.4px solid var(--med-gray-lighter);
    border-radius: 2px;
    background: var(--bg-white);
    position: relative;
    flex-shrink: 0;
    padding: 0;
    appearance: none;
    cursor: pointer;
}

.task-cb:disabled {
    cursor: not-allowed;
    opacity: 0.75;
}

.task-cb:focus-visible {
    outline: 2px solid var(--med-blue-interactive);
    outline-offset: 1px;
}

/* Story TOP.01 — operación en vuelo: pulso discreto mientras el server responde.
   El selector de estado hereda el mismo pulso (misma clase modificadora). */
.task-cb.task-cb-busy,
.trk-task-status-select.task-cb-busy {
    animation: task-cb-pulse 0.9s ease-in-out infinite;
}

@keyframes task-cb-pulse {
    50% { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
    .task-cb.task-cb-busy,
    .trk-task-status-select.task-cb-busy { animation: none; opacity: 0.5; }
}

/* Selector de estado de la sub-fila de tarea (decisión Iván 2026-08-21, sustituye al checkbox).
   Embebido en fila ⇒ piel del grid, no `--mtmp-*` (FD-T6): compacto y discreto, para que una
   columna de 300px siga cabiendo el nombre de la tarea. Las clases del detalle
   (`.task-status-select`) NO sirven aquí: están acotadas a `.task-list-item`/`.pc2-card`. */
/* DENTRO de `@layer overrides` a propósito, por la misma razón documentada arriba en el bloque de
   la celda en edición (:1584-1596): `create-project-hotfix.css` —que impone a TODO select
   `padding: 10px 14px !important; font-size: 14px !important`— se importa en esa capa, y para
   declaraciones !important la cascada de capas se INVIERTE: un !important con capa gana a
   cualquier !important sin capa, sin importar la especificidad.
   Fuera de la capa, ese padding de 10px empujaba el texto FUERA de la caja de 22px y el combo se
   veía VACÍO aunque el estado estuviera bien seleccionado (validado en vivo: selectedIndex correcto,
   texto invisible). Mismo layer ⇒ decide la especificidad, y (0,3,2) le gana a (0,1,1).
   El propio hotfix ya excluye .task-status-select y hermanos por este mismo motivo. */
@layer overrides {
    .tracker-table .task-row select.trk-task-status-select {
        flex-shrink: 0;
        width: auto !important;
        max-width: 108px;
        box-sizing: border-box;
        /* Sin alto fijo: lo define el contenido. Relleno vertical 0 + fuente chica ⇒ ~18px, que
           cabe en la sub-fila de 26px sin estirarla (verificado en vivo). */
        padding: 0 15px 0 4px !important;
        margin: 0;
        font-size: 0.7rem !important;
        line-height: 1.5;
        font-family: inherit;
        color: var(--text-secondary) !important;
        background-color: var(--bg-white) !important;
        border: 1px solid var(--med-gray-lighter) !important;
        border-radius: 3px;
        cursor: pointer;
        /* Apariencia propia: la flecha nativa no cabe en una caja de este alto. SVG inline. */
        appearance: none;
        -webkit-appearance: none;
        background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236B7A90' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 4px center;
        background-size: 8px 5px;
        transition: none !important;
    }

    .tracker-table .task-row select.trk-task-status-select:disabled {
        cursor: not-allowed;
        opacity: 0.75;
    }

    .tracker-table .task-row select.trk-task-status-select:focus-visible {
        outline: 2px solid var(--med-blue-interactive);
        outline-offset: 1px;
    }
}

/* El chip de la tarea saltada ocupa el lugar del selector (no se ofrece para Skipped): el
   estado se reabre por el menú ⋯. Mismo peso visual que el selector para no saltar la fila. */
.task-row .task-status-chip--cell {
    flex-shrink: 0;
    padding: 1px 6px;
    font-size: 0.72rem;
    border-radius: 3px;
    background: var(--row-hover, #f1f5f9);
    color: var(--text-secondary);
    white-space: nowrap;
}

/* Story TOP.01 — rechazo del server anclado a la fila (patrón replanError): visible, discreto. */
.task-op-error {
    color: var(--status-danger, #b3261e);
    font-size: 0.72rem;
    margin-left: 6px;
    white-space: nowrap;
}

/* ===== Story TOP.02 — menú ⋯ de tarea + fechas inline ===== */

/* El popover se ancla a la celda del nombre (patrón phase-live-cell del replan).
   :not(.frozen) — en la celda CONGELADA este `position: relative` pisaba el `position: sticky`
   de `.frozen`, y como la columna lleva `left: 220px` (offset de congelación), en `relative` ese
   left deja de anclar y CORRE la celda 220px a la derecha: el árbol de fases/tareas se pintaba
   desfasado de la columna Tool Name, destapando el skeleton de fondo, y las sub-filas no se
   congelaban al hacer scroll. `sticky` ya crea contexto de posicionamiento, así que el popover
   sigue anclando igual. Fuera del tracker (TaskListItem) la celda no es frozen y conserva relative. */
.task-name-cell:not(.frozen) {
    position: relative;
}

/* Disparador ⋯ — embebido en fila: piel del grid (FD-T6). Descubrible en hover/foco. */
.trk-task-menu-trigger {
    appearance: none;
    border: none;
    background: transparent;
    padding: 0 4px;
    margin-left: 4px;
    color: var(--med-gray-light);
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    border-radius: 3px;
    opacity: 0;
    transition: opacity 120ms ease;
}

.task-row:hover .trk-task-menu-trigger,
.phase-row-v2:hover .trk-task-menu-trigger,
.trk-task-menu-trigger:focus-visible,
.trk-task-menu-trigger[aria-expanded="true"] {
    opacity: 1;
}

/* Story TOP.03 — el menú de fase ancla en su celda de nombre; el panel de cierre es más ancho.
   :not(.frozen) por la misma razón que .task-name-cell (ver arriba). */
.phase-name-cell:not(.frozen) {
    position: relative;
}

.trk-phasemenu--wide {
    min-width: 360px;
}

.trk-phaseclose__ready {
    color: var(--status-success, #2e7d32);
    font-size: 12px;
}

.trk-phaseclose__blockers {
    font-size: 12px;
    color: var(--mtmp-dark-text, #1D2C48);
}

.trk-phaseclose__list {
    margin: 4px 0 0;
    padding-left: 18px;
}

.trk-phaseclose__list li {
    margin-bottom: 2px;
}

.trk-phaseclose__missing {
    color: var(--status-danger, #b3261e);
}

/* ===== Story TOP.05 — drawer de estructura de fase (mtmp) ===== */

.trk-structure__sub {
    font-size: 12px;
    color: var(--mtmp-text-gray, #6B7A90);
    margin: 0 0 12px;
}

.trk-structure__section {
    padding: 10px 0;
    border-top: 1px solid var(--mtmp-border-gray, #DCE5F2);
}

.trk-structure__heading {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mtmp-text-gray, #6B7A90);
    margin: 0 0 8px;
}

.trk-structure__actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.trk-structure__notice {
    margin-top: 6px;
    font-size: 11px;
    color: var(--status-success, #2e7d32);
}

.trk-task-menu-trigger:hover:not(:disabled) {
    color: var(--med-blue-interactive);
    background: var(--med-gray-lightest, #f2f5f9);
}

.trk-task-menu-trigger:disabled {
    cursor: not-allowed;
    color: var(--med-gray-lighter);
}

@media (prefers-reduced-motion: reduce) {
    .trk-task-menu-trigger { transition: none; }
}

/* El menú — superficie FLOTANTE nueva ⇒ lenguaje mtmp (FD-T6), como los popovers de la barra. */
.trk-taskmenu {
    position: absolute;
    top: 100%;
    left: 28px;
    z-index: 60;
    min-width: 280px;
    background: var(--mtmp-white, #FFFFFF);
    border: 1px solid var(--mtmp-border-gray, #DCE5F2);
    border-radius: var(--mtmp-radius-md, 12px);
    box-shadow: var(--mtmp-shadow-soft, 0 8px 24px rgba(6, 20, 44, 0.08));
    padding: 10px 12px;
    text-align: left;
    white-space: normal;
    font-size: 12px;
}

.trk-taskmenu__head {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
    color: var(--mtmp-dark-text, #1D2C48);
}

.trk-taskmenu__part {
    font-size: 10px;
    padding: 1px 6px;
    border-radius: var(--mtmp-radius-pill, 999px);
    background: #EAF3FE;
    color: var(--mtmp-primary, #117BFF);
}

.trk-taskmenu__sub {
    font-size: 11px;
    color: var(--mtmp-text-gray, #6B7A90);
    margin: 2px 0 8px;
}

.trk-taskmenu__items {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.trk-taskmenu__item {
    appearance: none;
    border: none;
    background: transparent;
    border-radius: 8px;
    padding: 6px 8px;
    text-align: left;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.trk-taskmenu__item:hover:not(:disabled) {
    background: var(--mtmp-soft-sky, #F1F7FF);
}

.trk-taskmenu__item:disabled {
    cursor: not-allowed;
    opacity: 0.55;
}

.trk-taskmenu__verb {
    font-weight: 600;
    color: var(--mtmp-dark-text, #1D2C48);
}

.trk-taskmenu__itemsub {
    font-size: 10.5px;
    color: var(--mtmp-text-gray, #6B7A90);
}

.trk-taskmenu__form { display: flex; flex-direction: column; gap: 4px; }
.trk-taskmenu__label { font-weight: 600; color: var(--mtmp-dark-text, #1D2C48); }
.trk-taskmenu__hint { font-weight: 400; color: var(--mtmp-text-gray, #6B7A90); margin-left: 4px; }
.trk-taskmenu__textarea {
    min-height: 56px;
    border: 1px solid var(--mtmp-border-gray, #DCE5F2);
    border-radius: 8px;
    padding: 6px;
    font-size: 12px;
    resize: vertical;
}
.trk-taskmenu__count { font-size: 10.5px; }
.trk-taskmenu__count.is-short { color: var(--mtmp-text-gray, #6B7A90); }
.trk-taskmenu__count.is-valid { color: var(--status-success, #2e7d32); }
.trk-taskmenu__select {
    border: 1px solid var(--mtmp-border-gray, #DCE5F2);
    border-radius: 8px;
    padding: 5px 6px;
    font-size: 12px;
    background: var(--mtmp-white, #FFFFFF);
}
.trk-taskmenu__loading { color: var(--mtmp-text-gray, #6B7A90); font-size: 11px; padding: 4px 0; }
.trk-taskmenu__actions { display: flex; justify-content: flex-end; gap: 6px; margin-top: 8px; }
.trk-taskmenu__error {
    margin-top: 6px;
    color: var(--status-danger, #b3261e);
    font-size: 11px;
}

/* Fechas inline — EMBEBIDAS en fila: piel del grid, no mtmp (FD-T6). */
.task-date-trigger {
    appearance: none;
    border: none;
    background: transparent;
    padding: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
    border-bottom: 1px dashed var(--med-gray-lighter);
}

.task-date-trigger:hover {
    color: var(--med-blue-interactive);
    border-bottom-color: var(--med-blue-interactive);
}

.task-date-input {
    width: 110px;
    font-size: 11px;
    border: 1px solid var(--med-gray-lighter);
    border-radius: 3px;
    padding: 1px 2px;
    background: var(--bg-white);
}

.task-cb.complete {
    background: var(--status-success);
    border-color: var(--status-success);
}

.task-cb.complete::after {
    content: "";
    position: absolute;
    top: 0;
    left: 3px;
    width: 3px;
    height: 7px;
    border: solid var(--bg-white);
    border-width: 0 1.6px 1.6px 0;
    transform: rotate(45deg);
}

.task-cb.progress {
    background: var(--bg-white);
    border-color: var(--med-blue-interactive);
}

.task-cb.progress::after {
    content: "";
    position: absolute;
    top: 1px;
    left: 1px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--med-blue-interactive);
}

/* Task name text */
.task-name-text {
    color: var(--med-gray-medium);
    font-weight: 500;
    line-height: 1.3;
}

/* Completada = line-through + gris (variant-A tr.row-task.task-complete .task-name) */
.task-row.task-complete .task-name-text {
    color: var(--med-gray-light);
    text-decoration: line-through;
}

/* Assignee pill + avatar (variant-A .task-assignee / .av) */
.task-assignee {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10.5px;
    background: var(--bg-white);
    border: 1px solid var(--grid-line);
    border-radius: 10px;
    padding: 1px 7px 1px 4px;
    color: var(--med-blue-medium);
    font-weight: 600;
    white-space: nowrap;
    /* T-04 — el pill de asignado crecía con el nombre y empujaba la columna. */
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.task-assignee .av {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--med-blue-medium), var(--med-blue-interactive));
    color: var(--text-inverse);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 9px;
    font-weight: 700;
    flex-shrink: 0;
}

/* Story PRT-1B.08 — la parte de una sub-fila de tarea. Neutra a propósito: la parte CLASIFICA
   (FD-02), no es un estado, y robarle contraste a la insignia de opcional o al checkbox de estado
   sería mentir sobre su importancia. Tokens ya usados en esta hoja — cero valores nuevos. */
.task-part-chip {
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    padding: 1px 6px;
    border-radius: 3px;
    background: var(--row-task-bg);
    color: var(--med-gray-medium);
    border: 1px solid var(--grid-line);
    flex-shrink: 0;
    white-space: nowrap;
}

/* Story PRT-1B.08 (AC5) — separador de SECCIÓN dentro de la fase expandida. Es un rótulo entre
   tareas: sin celdas de datos, sin estado, sin fechas (FD-01). Por eso ocupa una fila propia con un
   solo colspan en vez de sumar una columna a la rejilla. */
.task-section-separator-row {
    background: var(--row-phase-bg);
}

.task-section-separator-cell {
    padding: 2px 8px;
    border-bottom: 1px solid var(--grid-line);
}

.task-section-separator-name {
    font-size: 0.625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--med-gray-medium);
    margin-left: 6px;
}

/* Optional badge */
.task-optional-badge {
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding: 1px 6px;
    border-radius: 3px;
    background: rgba(255, 193, 7, 0.15);
    color: #856404;
    border: 1px solid rgba(255, 193, 7, 0.3);
    flex-shrink: 0;
}

/* Status badges */
.task-status-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 2px 8px;
    border-radius: 4px;
    font-size: 0.6875rem;
    font-weight: 500;
    white-space: nowrap;
    min-width: 70px;
    transition: transform 100ms ease;
}

.task-row:hover .task-status-badge {
    transform: scale(1.02);
}

.task-badge-pending {
    background: #E9ECEF;
    color: #6C757D;
}

.task-badge-active {
    background: #17A2B8;
    color: #FFFFFF;
}

.task-badge-complete {
    background: #28A745;
    color: #FFFFFF;
}

.task-badge-skipped {
    background: #FFC107;
    color: #3C3C3C;
}

/* Row status variations — UX-DS-03.03: variant-A unifica el bg de task rows;
   el estado vive en el task-cb + line-through (tr.row-task.task-complete .task-name). */
.task-row.task-complete .task-name-text {
    color: var(--med-gray-light);
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

.task-row.task-complete .frozen {
    background: var(--row-task-bg);
}

.task-row.task-in-progress {
    background: var(--row-task-bg);
}

.task-row.task-in-progress .frozen {
    background: var(--row-task-bg);
}

.task-row.task-skipped {
    opacity: 0.6;
}

.task-row.task-skipped .task-name-text {
    text-decoration: line-through;
    color: var(--med-gray-light);
}

/* Metadata cells */
.task-assigned-cell {
    font-size: 0.75rem;
    color: #555555;
}

.task-date-cell {
    font-size: 0.75rem;
    color: #555555;
    font-variant-numeric: tabular-nums;
}

/* Task ID */
.task-id {
    font-size: 0.6875rem;
    color: #979797;
    font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
}

/* Focus state for accessibility */
.task-row:focus-within {
    outline: 2px solid #1010EB;
    outline-offset: -2px;
}

/* Status cell */
.task-status-cell {
    min-width: 90px;
}

/* ===== Story 11B.14 (Q9) — Frozen ProjectDisplayId + responsive System-IDs collapse ===== */

/* "Intake" warning chip in the frozen ProjectDisplayId cell (pre-transition: ProjectCode == null).
   This story OWNS the chip; 11B.16 reuses .badge-intake-warning. Text + icon + aria carry meaning
   (not color alone). Token --warning-100 with an amber fallback. */
.tracker-table .badge-intake-warning {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    margin-left: 6px;
    background: var(--warning-100, #fff3cd);
    color: var(--warning-700, #8a6d00);
    border: 1px solid var(--warning-300, #ffe08a);
    font-size: .66rem;
    font-weight: 700;
    letter-spacing: .02em;
    padding: 1px 6px;
    border-radius: 10px;
    text-transform: uppercase;
    vertical-align: middle;
    white-space: nowrap;
}
.tracker-table .badge-intake-warning .bi { font-size: .68rem; }

/* The two secondary system-id columns + the collapsed dropdown column. Each ID is a read-only
   <code> token. The columns themselves are scrollable (NOT frozen). */
.tracker-table .col-intake-form-id,
.tracker-table .col-project-code { min-width: 130px; white-space: nowrap; }
.tracker-table .id-code {
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: .8rem;
    color: var(--med-blue-primary, #170f5f);
}

/* Avoid per-row layout shift when toggling the responsive dropdown popover. */
.tracker-table .ids-system-dropdown { contain: layout; transition: width 200ms ease; }
.ids-popover-wrapper { position: relative; display: inline-block; }
.ids-popover-trigger {
    background: none;
    border: none;
    padding: 2px 6px;
    cursor: pointer;
    color: var(--med-blue-interactive, #0077c8);
}
.ids-popover-panel {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 30;
    min-width: 200px;
    margin-top: 4px;
    padding: 8px 10px;
    background: #fff;
    border: 1px solid var(--grid-line, #dee2e6);
    border-radius: 6px;
    box-shadow: 0 6px 18px rgba(0,0,0,.16);
}
.ids-popover-list { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; }
.ids-popover-list dt { font-size: .7rem; color: var(--med-gray-medium, #6c757d); font-weight: 600; }
.ids-popover-list dd { margin: 0; font-size: .8rem; }

/* Colapso responsive de los ids de sistema (§Q9, 11B.14): RETIRADO el 2026-08-27 — las dos columnas
   entraron al catálogo configurable y ocultarlas es decisión del usuario, por vista. */

/* ============================================================================
   Story 11B.18 (FD-07) — MoldCell + MoldPopover (single scalar mold)
   Read-only display column + right-side slide-in drawer. The multi-mold badge
   and the IsFinalAsset star are DEFERRED (no scalar backs them) — not styled.
   ============================================================================ */

.tracker-table .col-mold {
    min-width: 140px;
    max-width: 220px;
}

/* Empty (no scalar mold) — selectable em-dash, matches the EmDashWithTooltip look. */
.mold-cell-empty {
    color: var(--med-gray-medium, #999);
    user-select: text;
}

/* Single mold — clickable inline chip. */
.mold-cell-single {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    max-width: 100%;
    padding: 2px 6px;
    border: none;
    border-radius: 4px;
    background: transparent;
    cursor: pointer;
    font: inherit;
    text-align: left;
    color: inherit;
    transition: background 0.15s ease;
}

.mold-cell-single:hover,
.mold-cell-single:focus-visible {
    /* repo has no --primary-50; --row-hover (#F0F4F9) is the project's light primary tint. */
    background: var(--row-hover, #F0F4F9);
    outline: none;
}

.mold-cell-icon {
    color: var(--med-blue-primary, #001E46);
    font-size: 0.85rem;
    flex: 0 0 auto;
}

.mold-cell-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mold-cell-asset {
    font-size: 0.72rem;
    color: var(--med-gray-medium, #777);
    flex: 0 0 auto;
}

/* ---- Drawer ---- */
.mold-popover-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.25);
    z-index: 1050;
}

.mold-popover-drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 360px;
    max-width: 90vw;
    background: #fff;
    box-shadow: -4px 0 18px rgba(0, 0, 0, 0.18);
    z-index: 1051;
    display: flex;
    flex-direction: column;
    animation: mold-popover-slide-in 0.2s ease;
}

@keyframes mold-popover-slide-in {
    from { transform: translateX(100%); }
    to { transform: translateX(0); }
}

.mold-popover-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 18px;
    background: var(--med-blue-primary, #001E46);
    color: #fff;
}

.mold-popover-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
}

.mold-popover-close {
    border: none;
    background: transparent;
    color: #fff;
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    padding: 4px;
}

.mold-popover-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 18px;
}

.mold-popover-fields {
    margin: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: 4px 0;
}

.mold-popover-fields dt {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--med-gray-medium, #777);
    margin-top: 12px;
}

.mold-popover-fields dt:first-child {
    margin-top: 0;
}

.mold-popover-fields dd {
    margin: 0;
    font-size: 0.95rem;
    color: var(--text-primary, #222);
}

.mold-popover-status-badge {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 12px;
    font-size: 0.78rem;
    font-weight: 600;
    background: var(--row-hover, #F0F4F9);
    color: var(--med-blue-primary, #001E46);
}

.mold-popover-empty {
    color: var(--med-gray-medium, #999);
}

/* ============================================================================
   Story 11B.19 (FD-07) — MoldExpandInlinePreview (single scalar mold, read-only)
   Rendered by 11B.17's BulkConfirmationModal under each affected project row when
   a bulk edit touches a scalar mold field. Shows Current → New for the affected
   field; the new value is highlighted. The N-mold sub-table and SameSupplier /
   IsFinalAsset-max-1 warnings are DEFERRED (no scalar backs them) — not styled.
   ============================================================================ */

.mold-inline-preview {
    font-size: 0.85rem;
}

.mold-inline-preview-header {
    display: flex;
    align-items: center;
}

.mold-inline-expand-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: none;
    background: transparent;
    cursor: pointer;
    padding: 2px 4px;
    font: inherit;
    color: var(--med-blue-primary, #001E46);
}

.mold-inline-expand-toggle:hover,
.mold-inline-expand-toggle:focus-visible {
    background: var(--row-hover, #F0F4F9);
    outline: none;
    border-radius: 4px;
}

.mold-inline-chevron {
    font-size: 0.7rem;
    flex: 0 0 auto;
}

.mold-inline-project-id {
    font-weight: 600;
}

.mold-inline-preview-body {
    padding: 8px 10px 8px 26px;
}

.mold-inline-empty {
    color: var(--med-gray-medium, #999);
}

.mold-inline-fields {
    margin: 0;
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 4px 14px;
    align-items: baseline;
}

.mold-inline-fields dt {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--med-gray-medium, #777);
}

.mold-inline-fields dd {
    margin: 0;
    color: var(--text-primary, #222);
}

.mold-inline-change {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.mold-inline-current {
    color: var(--med-gray-medium, #777);
}

.mold-inline-arrow {
    color: var(--med-gray-medium, #777);
    flex: 0 0 auto;
}

/* Highlight the changed (post-bulk) value. Token --warning-50 with an amber fallback;
   repo defines --warning-100/300/700 (see badge-intake-warning) but not --warning-50. */
.mold-inline-new {
    background: var(--warning-50, #fff8e1);
    color: var(--warning-700, #8a6d00);
    border: 1px solid var(--warning-300, #ffe08a);
    padding: 1px 6px;
    border-radius: 4px;
    font-weight: 600;
}

.mold-popover-footer {
    padding: 14px 18px;
    border-top: 1px solid #e5e5e5;
}

.mold-popover-detail-link {
    color: var(--med-blue-primary, #001E46);
    font-weight: 600;
    text-decoration: none;
}

.mold-popover-detail-link:hover {
    text-decoration: underline;
}

/* ============================================================================
   Story 11B.11 (FD) — RESPONSIVE ADJUSTMENTS
   CSS-first. Goal: grid usable on a 1366px laptop and on tablets, without
   breaking the dense desktop layout or the existing breakpoints.

   Coexistence with 11B.14:
     • 11B.14 owns the <1440px ID-block collapse (line ~2014): it hides
       .col-intake-form-id + .col-project-code and shows .ids-system-dropdown.
       Nothing below re-declares those selectors, so the collapse keeps working.
     • The frozen sticky offsets (.col-checkbox 0 / .col-expand 40 / .col-id 70 /
       .col-tool 220, width 400) and the scroll-shadow ::before left:620px are NOT changed
       here — they stay exact at every width, so frozen columns never overlap
       the scrollable content (AC1/AC2).
   ============================================================================ */

/* --- AC1: Horizontal scroll at 1366px (standard laptop) -------------------- */
/* The wrapper already has overflow:auto and the table is width:max-content, so
   horizontal scrolling exists at any width. At <=1366px we make the scrollbar
   touch-/trackpad-friendly and force momentum scrolling on iOS, and we keep the
   frozen offsets verbatim (no re-declaration) so the sticky columns stay put. */
@media (max-width: 1366px) {
    .tracker-table-wrapper {
        -webkit-overflow-scrolling: touch; /* momentum scroll on iOS/iPadOS */
        scrollbar-width: thin;
    }

    .tracker-table-wrapper::-webkit-scrollbar {
        height: 10px;
    }
}

/* --- AC4: Pagination controls stay accessible at narrow widths -------------- */
/* The .pagination-bar already declares flex-wrap:wrap (inline in ProjectTracker
   .razor <style>); below 768px we stack it into a centred column so no control
   overflows off-screen. Selector is global so it reaches the inline-styled bar. */
@media (max-width: 767px) {
    .pagination-bar {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
    }

    .pagination-bar .pagination-controls {
        justify-content: center;
    }
}

/* --- AC3: Touch-friendly row height + 44px tap targets on tablets ---------- */
/* Applied under a coarse pointer (tablets/touch laptops). Bumps the interactive
   targets (checkboxes, the expand chevron, filter selects/inputs, buttons) to a
   ~44px minimum WITHOUT touching .project-row td height for fine-pointer desktop,
   so the dense desktop layout is preserved. font-size:16px on inputs avoids the
   iOS focus-zoom. */
@media (pointer: coarse) {
    .expand-btn {
        min-width: 44px;
        min-height: 44px;
    }

    .tracker-filters .filter-group select,
    .tracker-filters .filter-group input {
        min-height: 44px;
        font-size: 16px;
    }

    .tracker-filters .filter-group input[type="checkbox"],
    .tracker-table .row-checkbox,
    .tracker-table input[type="checkbox"] {
        width: 20px;
        height: 20px;
    }

    /* H-03 — .tracker-actions desapareció con el encabezado; el objetivo táctil de 44px lo heredan
       las acciones del panel de la vista, que es donde viven ahora esos botones. */
    .pagination-bar .pagination-btn,
    .vtb-actions .btn {
        min-height: 44px;
    }
}

/* Tablet-width fallback for devices that don't report pointer:coarse — the same
   44px targets apply between 768px and 1024px (iPad portrait/landscape). */
@media (min-width: 768px) and (max-width: 1024px) {
    .tracker-filters .filter-group select,
    .tracker-filters .filter-group input {
        min-height: 44px;
    }

    .expand-btn {
        min-width: 44px;
        min-height: 44px;
    }
}

/* --- AC2 (narrow): Filters stack vertically below 768px -------------------- */
/* The .tracker-filters flex row becomes a single column; each control and its
   group go full width so nothing is cut off on a phone/narrow split-screen. */
@media (max-width: 767px) {
    .tracker-filters {
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
    }

    .tracker-filters .filter-group {
        width: 100%;
    }

    .tracker-bar { flex-direction: column; align-items: stretch; }
    .tracker-bar__divider { width: auto; height: 1px; }

    /* En columna, el cierre derecho deja de empujarse a la derecha, pero contador y botón siguen
       compartiendo renglón: separados ocuparían dos de los pocos que hay en un teléfono. */
    .tracker-filters .filter-trailing {
        margin-left: 0;
        justify-content: space-between;
        padding-bottom: 0;
    }

    .tracker-filters .bulk-column-btn {
        white-space: normal;
        text-align: left;
    }
}

/* --- AC5: Epic-34 column configurator modal scrollable on small screens ---- */
/* The configurator (.cc-modal / .cc-body) is an Epic 34 component — its markup is
   NOT touched here. .cc-modal already caps at max-height:86vh and .cc-body is
   overflow-y:auto, so it scrolls; below 768px we collapse the two-pane grid into
   one column (so the Available/Visible panes stack instead of squeezing) and
   tighten padding. Purely a CSS override against the component's global classes. */
@media (max-width: 767px) {
    .cc-modal {
        width: 96vw;
        max-height: 90vh;
    }

    .cc-body {
        grid-template-columns: 1fr;
        max-height: 70vh;
        overflow-y: auto;
    }
}

/* ============================================================================
   ESCALA TIPOGRÁFICA ÚNICA DE LAS SUPERFICIES FLOTANTES DEL TRACKER
   (petición Iván 2026-08-21: "estandariza las fuentes para los modales, y también
   puedes hacerlos un poco más grandes".)

   El problema medido en vivo: dentro del MISMO popover de filtro el título salía a
   12px/600 y sus opciones a 14px/700 EN MAYÚSCULAS, mientras el popover del lens usaba
   12px — tres tipografías para la misma familia de controles. Los componentes ya pedían
   ~13px (FilterDraftControl declara .82rem), pero las reglas globales de formulario
   (`label, .form-label { font-size: 14px; font-weight: 600 }` en create-project-enhanced,
   `.filter-group label { text-transform: uppercase }` aquí) los pisaban.

   Por qué DENTRO de `@layer overrides` y con !important: create-project-hotfix.css se
   importa en esa capa, y para declaraciones !important la cascada de capas se INVIERTE —
   una regla !important con capa gana a cualquiera sin capa, sin importar la especificidad
   (mismo mecanismo documentado arriba para la celda en edición y el selector de estado).

   Escala: ítems y títulos 13px, texto auxiliar 12px, rótulos de grupo 11px en altas.
   ============================================================================ */
@layer overrides {
    .popover-lens,
    .trk-value-picker {
        font-size: 13px;
    }

    /* Títulos de la superficie */
    .popover-lens .pop-title,
    .trk-value-picker .trk-picker__title {
        font-size: 13px !important;
        font-weight: 600 !important;
        text-transform: none !important;
        letter-spacing: normal !important;
    }

    /* Ítems seleccionables: la línea que el usuario lee y clickea */
    .popover-lens .pop-item,
    .popover-lens .pop-item-label,
    .trk-value-picker .fdc-check,
    .trk-value-picker .trk-picker__opt {
        font-size: 13px !important;
        font-weight: 500 !important;
        text-transform: none !important;
        letter-spacing: normal !important;
        line-height: 1.45;
    }

    /* Texto auxiliar: subtítulos, notas, pie y contadores */
    .popover-lens .pop-sub,
    .popover-lens .pop-item-sub,
    .popover-lens .pop-groupsub,
    .popover-lens .pop-pending,
    .popover-lens .pop-footer,
    .trk-value-picker .trk-picker__sub,
    .trk-value-picker .trk-picker__empty,
    .trk-value-picker .fdc-range-lbl {
        font-size: 12px !important;
        font-weight: 400 !important;
        text-transform: none !important;
        letter-spacing: normal !important;
    }

    /* Rótulos de grupo (PRESET, VISIBLE PHASES…): siguen en altas, es su gramática. */
    .popover-lens .pop-group {
        font-size: 11px !important;
        font-weight: 700 !important;
        text-transform: uppercase !important;
        letter-spacing: 0.06em !important;
    }

    /* Controles de entrada embebidos en estas superficies (buscador del lens, operadores y
       campos del constructor de filtros): misma escala, sin el padding de 10px del hotfix. */
    .popover-lens .pop-filter,
    .trk-value-picker .fdc-op,
    .trk-value-picker .fdc-input {
        font-size: 13px !important;
        padding: 4px 8px !important;
    }
}
