/*
 * GrupoProdex ERP — design scale on top of Tabler tokens.
 *
 * RULE: this named scale and the semantic components below are the only
 * typography vocabulary for the interactive ERP. Printable documents keep
 * their own scale. Never add an arbitrary font size to an admin template.
 *
 * Font scale:
 *   .fs-meta  — 0.6875rem / 11px  (timestamps, fine print, metadata)
 *   .fs-small — 0.75rem   / 12px  (secondary text, table details)
 *   .fs-body  — 0.875rem  / 14px  (default body copy)
 *   .fs-title — 1.125rem  / 18px  (section/card titles)
 *
 * State badges (wrap Tabler's soft "-lt" tokens, valid in light AND dark —
 * Tabler 1.4 defines --tblr-*-lt as color-mix(... 10%, transparent), so the
 * same value adapts to both themes, exactly like .bg-*-lt does):
 *   .badge-state-inactive — grey   (draft, archived, off)
 *   .badge-state-progress — blue   (in progress, pending review)
 *   .badge-state-done     — green  (validated, completed)
 *   .badge-state-action   — orange (needs action, waiting on us)
 *   .badge-state-blocked  — red    (rejected, blocked, error)
 */

/* ── Prodex brand palette ───────────────────────────────────────
 * Colors lifted from the existing brand assets (report PDFs + logo):
 *   ink #1a1a1a · gold #b5940b · taupe #8a8371 · cream #eae4d6
 *   night blue #1d273b (manifest theme_color) · terracotta #c0392b
 * Mapping: gold becomes Tabler's primary accent (darkened to #8a6f08
 * for text-on-white contrast), the page canvas warms up to a faint
 * cream, the sidebar stays night blue. Semantic colors (green/orange/
 * red state badges) stay stock Tabler — brand never overrides meaning.
 */

:root,
[data-bs-theme="light"] {
    --prodex-font-meta: 0.6875rem;    /* 11px: labels and compact metadata */
    --prodex-font-small: 0.75rem;     /* 12px: secondary information */
    --prodex-font-body: 0.875rem;     /* 14px: reading and controls */
    --prodex-font-section: 1rem;      /* 16px: card and section headings */
    --prodex-font-title: 1.125rem;    /* 18px: highlighted headings */
    --prodex-font-page: 1.5rem;       /* 24px: one page title */
    --prodex-font-metric: 1.875rem;   /* 30px: dashboard figures only */

    --prodex-gold: #b5940b;
    --prodex-gold-ink: #8a6f08;      /* gold dark enough for text on white */
    --prodex-night: #1d273b;
    /* App chrome — menu bar and phone capsule (Pedro, 21-sep: «Noche y oro»,
     * the home-screen icon carried to the whole app). Text keeps night blue. */
    --prodex-noche: #111214;
    --prodex-oro-noche: #c9a54a;         /* gold that reads on --prodex-noche */
    --prodex-cream-page: #faf8f2;    /* report cream, heavily diluted */

    --tblr-primary: var(--prodex-gold);
    --tblr-primary-rgb: 181, 148, 11;
    --tblr-primary-lt: rgba(181, 148, 11, 0.1);
    --tblr-primary-darken: var(--prodex-gold-ink); /* button hover */
    --tblr-primary-fg: #ffffff;

    /* Full brand remap (Pedro, 04-ago): EVERYTHING blue or green — text,
     * links, icons, badges — moves to brand colors. Blue → night blue,
     * green/success → gold. Tabler derives all of it from these tokens. */
    --tblr-blue: var(--prodex-night);
    --tblr-blue-rgb: 29, 39, 59;
    --tblr-blue-lt: rgba(29, 39, 59, 0.08);
    --tblr-blue-darken: #16202f;
    --tblr-blue-fg: #ffffff;
    --tblr-azure: #2c3b55; /* lifted night for info accents */
    --tblr-azure-rgb: 44, 59, 85;
    --tblr-azure-lt: rgba(44, 59, 85, 0.08);
    --tblr-info: #2c3b55;
    --tblr-info-rgb: 44, 59, 85;
    --tblr-green: var(--prodex-gold);
    --tblr-green-rgb: 181, 148, 11;
    --tblr-green-lt: rgba(181, 148, 11, 0.1);
    --tblr-green-darken: var(--prodex-gold-ink);
    --tblr-green-fg: #ffffff;
    --tblr-success: var(--prodex-gold);
    --tblr-success-rgb: 181, 148, 11;
    --tblr-success-lt: rgba(181, 148, 11, 0.1);
    --tblr-success-darken: var(--prodex-gold-ink);
    --tblr-success-fg: #ffffff;
    /* Pedro (04-ago, cierre): NINGUNA letra amarilla en todo el ERP.
     * Los enlaces —la mayor fuente de texto dorado fuera de Hoy— pasan
     * al gris secundario, con hover en el color del cuerpo. Los RELLENOS
     * dorados (botón primario con letra blanca, barras) se quedan. */
    --tblr-link-color: #616876;
    --tblr-link-color-rgb: 97, 104, 118;
    --tblr-link-hover-color: #1d273b;
    --tblr-link-hover-color-rgb: 29, 39, 59;
}

[data-bs-theme="light"] body,
body {
    background-color: var(--prodex-cream-page);
    font-size: var(--prodex-font-body);
    line-height: 1.45;
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

[data-bs-theme="dark"] {
    /* On dark ground the darkened gold vanishes; use the true brand gold */
    --tblr-primary: #cfa91e;
    --tblr-primary-rgb: 207, 169, 30;
    --tblr-primary-lt: rgba(207, 169, 30, 0.15);
    /* Enlaces también grises en oscuro (Pedro: ninguna letra amarilla) */
    --tblr-link-color: #9aa5b8;
    --tblr-link-color-rgb: 154, 165, 184;
    --tblr-link-hover-color: #e4e8ef;
    --tblr-link-hover-color-rgb: 228, 232, 239;
    --tblr-primary-darken: #b8941a;
    --tblr-primary-fg: #ffffff; /* Pedro 26-ago: white text on gold, everywhere */

    /* Dark ground: night blue is invisible on itself — lift to steel; gold
     * brightens (same treatment as primary above). */
    --tblr-blue: #8fa4c9;
    --tblr-blue-rgb: 143, 164, 201;
    --tblr-blue-lt: rgba(143, 164, 201, 0.12);
    --tblr-blue-fg: #ffffff;
    --tblr-azure: #8fa4c9;
    --tblr-azure-rgb: 143, 164, 201;
    --tblr-azure-lt: rgba(143, 164, 201, 0.12);
    --tblr-info: #8fa4c9;
    --tblr-info-rgb: 143, 164, 201;
    --tblr-green: #cfa91e;
    --tblr-green-rgb: 207, 169, 30;
    --tblr-green-lt: rgba(207, 169, 30, 0.15);
    --tblr-green-fg: #ffffff;
    --tblr-success: #cfa91e;
    --tblr-success-rgb: 207, 169, 30;
    --tblr-success-lt: rgba(207, 169, 30, 0.15);
    --tblr-success-fg: #ffffff;
}

[data-bs-theme="dark"] body {
    background-color: var(--tblr-bg-surface-dark, #151f2c);
}

/* Meeting plan: a generated preparation must answer what to do first, while
 * its source corpus stays available but visually secondary. */
.meeting-plan-focus,
.meeting-plan-closing {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: 1rem;
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius);
    background: var(--tblr-primary-lt);
}
.meeting-plan-closing { background: var(--tblr-blue-lt); }
.meeting-plan-icon {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    flex: 0 0 2.25rem;
    border-radius: 50%;
    background: var(--tblr-bg-surface);
    color: var(--prodex-night);
    font-size: 1.25rem;
}
.meeting-plan-steps { list-style: none; padding: 0; counter-reset: meeting-step; }
.meeting-plan-steps li {
    counter-increment: meeting-step;
    display: flex;
    gap: .75rem;
    align-items: center;
    min-height: 2.5rem;
}
.meeting-plan-steps li::before {
    content: counter(meeting-step);
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    flex: 0 0 1.75rem;
    border-radius: 50%;
    background: var(--tblr-blue-lt);
    color: var(--prodex-night);
    font-weight: 700;
}
.meeting-document { display: flex; align-items: center; gap: .75rem; padding: .75rem 0; }
.meeting-document + .meeting-document { border-top: 1px solid var(--tblr-border-color); }
.meeting-sources-summary { cursor: pointer; color: var(--tblr-secondary); }

/* ── Gold TEXT darkens, gold boxes stay ──────────────────────────
 * Pedro (04-ago): the soft gold boxes are right, but gold letters on
 * them read too yellow. Text-role usages of the gold drop to the dark
 * brand gold (the link color); fills and tints keep the true gold.
 * Dark mode keeps the bright gold — there the dark one would vanish.
 *
 * Segunda vuelta (Pedro, 04-ago, «sigue sin convencerme»): el texto
 * DENTRO de los recuadros dorados pasa al azul noche de la marca —
 * contraste real y conjunta con el menú. El texto dorado sobre fondo
 * blanco (text-*) se queda en oro oscuro, que ahí sí funciona.
 */
/* Tercera y definitiva (Pedro, 04-ago: «todas las letras amarillas, en
 * todas las pantallas»): cualquier texto con rol dorado pasa al gris
 * secundario de Tabler, que se adapta solo en oscuro. */
.text-primary,
.text-success,
.text-green {
    color: var(--tblr-secondary) !important;
}

.bg-primary-lt,
.bg-success-lt,
.bg-green-lt,
.badge-state-done {
    color: var(--prodex-night) !important;
}

[data-bs-theme="dark"] .bg-primary-lt,
[data-bs-theme="dark"] .bg-success-lt,
[data-bs-theme="dark"] .bg-green-lt,
[data-bs-theme="dark"] .badge-state-done {
    color: #c8d2e4 !important; /* acero claro: legible sobre el tinte oscuro */
}

/* The Hoy pills and quick-capture buttons paint their text with
 * var(--tblr-primary) in their own <style> blocks; :not() guards keep
 * their hover/active whites intact. */
/* Pedro (04-ago, cierre): las pestañas de arriba llevan el MISMO gris
 * oscuro que los chips del cajón (btn-soft-muted -> --tblr-secondary),
 * para que arriba y abajo hablen igual. La pestaña activa no cambia. */
.dash-tabs .nav-link:not(.active):not(:hover) {
    color: var(--tblr-secondary) !important;
}

.dash-actions > .nav-link:not(:hover) {
    color: var(--tblr-secondary) !important;
}

/* .btn-soft-accent colours live in admin.css («Un solo dorado», 20-sep-2026). */
/* ── Prodex brand bar ────────────────────────────────────────────
 * ONLY the menu bar wears the night blue (Pedro, 04-ago: painting the
 * page header too duplicated it). The vertical sidebar IS the mobile
 * top bar (same <aside>, collapsed by Bootstrap under lg), so one rule
 * covers both.
 */
.navbar-vertical.navbar {
    background-color: var(--prodex-noche);
}

.navbar-brand-logo {
    height: 40px;
    width: auto;
    display: block;
    /* trim the PNG's generous transparent margins */
    margin: -6px 0;
}

/* ── Font scale ─────────────────────────────────────────────── */

.fs-meta {
    font-size: var(--prodex-font-meta);
    line-height: 1.35;
}

.small,
small,
.fs-small {
    font-size: var(--prodex-font-small);
    line-height: 1.4;
}

.fs-body {
    font-size: var(--prodex-font-body);
    line-height: 1.45;
}

.fs-section {
    font-size: var(--prodex-font-section);
    line-height: 1.35;
}

.fs-title {
    font-size: var(--prodex-font-title);
    line-height: 1.3;
}

.fs-metric {
    font-size: var(--prodex-font-metric);
    line-height: 1.1;
}

/* Absolute tokens prevent nested tables, badges and secondary text from
 * shrinking below the readable scale. */
.card-title {
    font-size: var(--prodex-font-section);
    line-height: 1.35;
}

.table {
    font-size: var(--prodex-font-body);
}

.badge {
    /* There are hundreds of legacy inline sizes. The component owns its
     * typography so a nested table or an old style cannot shrink it. */
    font-size: var(--prodex-font-meta) !important;
    line-height: 1.25;
}

.form-label,
.form-control,
.form-select,
.btn {
    font-size: var(--prodex-font-body);
}

.btn-sm {
    font-size: var(--prodex-font-small);
}

code {
    font-size: var(--prodex-font-small);
}

/* ── State badge vocabulary ─────────────────────────────────── */

.badge-state-inactive {
    color: var(--tblr-secondary) !important;
    background-color: var(--tblr-secondary-lt) !important;
}

.badge-state-progress {
    color: var(--tblr-blue) !important;
    background-color: var(--tblr-blue-lt) !important;
}

.badge-state-done {
    color: var(--tblr-green) !important;
    background-color: var(--tblr-green-lt) !important;
}

.badge-state-action {
    color: var(--tblr-orange) !important;
    background-color: var(--tblr-orange-lt) !important;
}

.badge-state-blocked {
    color: var(--tblr-red) !important;
    background-color: var(--tblr-red-lt) !important;
}

/* ── Móvil — la página no se va de lado ─────────────────────────
 *
 * POR QUÉ EXISTE ESTA REGLA (13-ago-2026).
 *
 * Medido con Chrome a 375 px en /ventas y en /dia-a-dia:
 * document.documentElement.scrollWidth = 379 sobre un clientWidth de 375. La
 * página se iba 4 px de lado, y cuando eso pasa el navegador encoge la página
 * entera para meter lo que sobra: por eso las tarjetas parecían acabar antes
 * del borde.
 *
 * La causa es aritmética, y NO es que falte contenedor —las filas cuelgan de
 * su .container-xl—: es que el canalón del .row es más ancho que el padding
 * que debería absorberlo.
 *
 *   · Tabler baja --tblr-page-padding a 0,5rem por debajo de 992 px (regla
 *     suya, no nuestra), y el padding de cualquier .container-* es justo ese
 *     valor: 8 px por lado.
 *   · Un .row.g-4 fija su --tblr-gutter-x en 1,5rem y se resta 12 px de margen
 *     por lado, contando con que alguien se los devuelva.
 *   · 12 > 8 → sobresale 4 px por cada lado.
 *
 * En escritorio no ocurre: a partir de 992 px --tblr-page-padding vale 1rem,
 * el padding son 16 px y el g-4 cabe de sobra. Por eso la regla vive dentro de
 * su @media y el PC no se entera: medido a 1280 px, contenedor, fila, columna
 * y tarjeta dan exactamente los mismos números con la regla y sin ella.
 *
 * EL ARREGLO: por debajo de 992 px el g-4 usa el mismo canalón que usa el
 * contenedor —calc(--tblr-page-padding * 2), que es literalmente la definición
 * de --tblr-gutter-x de .container-*—. Así el margen negativo de la fila y el
 * padding del contenedor son el mismo número POR CONSTRUCCIÓN, y lo seguirán
 * siendo el día que Tabler cambie el valor.
 *
 * No se toca dónde acaba el contenido: la posición de una tarjeta es
 * «padding del padre − margen de la fila + padding de la columna», y esos dos
 * últimos se anulan siempre (el margen es −gutter/2 y el padding +gutter/2).
 * Medido: la tarjeta sigue a 8 px del borde antes y después. Lo único que
 * desaparece son los 4 px que sobraban.
 *
 * Se toca SOLO la X. El --tblr-gutter-y del g-4 sigue en 1,5rem, que es la
 * separación que de verdad se ve en el móvil, donde las columnas van apiladas.
 * Entre 768 y 991 px, donde algún col-md-* sí va en paralelo, el hueco
 * horizontal pasa de 24 a 16 px.
 *
 * POR QUÉ SIN COMBINADOR DE HIJO. El primer intento fue
 * `.container-xl > .row.g-4`, que suena más prudente. Se le escapó
 * /admin/configuracion/redes, donde hay un <form> entre el contenedor y la
 * fila. Y no hacía falta afinar: la regla es inofensiva en las filas anidadas
 * (dentro de un .col o de un .card-body) precisamente por lo de arriba —el
 * contenido no se mueve—, así que se aplica a todas y se acaba el problema.
 *
 * Se arregla aquí y no fila a fila porque el patrón está repetido en 19 sitios
 * de las plantillas: el contenido de TODAS las pantallas entra por
 * .page-body > .container-xl. Si algún día aparece un .row.g-5 (hoy no existe
 * ninguno) volverá a pasar lo mismo y habrá que sumarlo a esta regla.
 *
 * Y no se usa overflow-x: hidden en el body: eso esconde el síntoma y el día
 * que algo se salga de verdad nadie lo encuentra.
 */

@media (max-width: 991.98px) {
    .row.g-4 {
        --tblr-gutter-x: calc(var(--tblr-page-padding) * 2);
    }
}

/* ══════════════════════════════════════════════════════════════════
 * REDISEÑO 26-ago-2026 — capa de diseño
 *
 * Tres colores y solo tres, decididos con Pedro:
 *   oro   #cfa91e  actuar y reclamar atención (botones, activo, «te falta»)
 *   acero #8fa4c9  informar (etapa, tipo, dato de contexto)
 *   rojo  #d63939  SOLO retraso (vencido, parado, fuera de plazo)
 * El naranja desaparece del ERP: --tblr-orange y --tblr-warning pasan al oro.
 * Va al final del fichero a propósito: en CSS gana la última regla, así esta
 * capa se impone a los parches de julio y agosto sin tener que borrarlos.
 * ══════════════════════════════════════════════════════════════════ */

/* ── 1. Fuera el naranja, en los dos temas ── */
:root,
[data-bs-theme="light"] {
    --tblr-orange: var(--prodex-gold);
    --tblr-orange-rgb: 181, 148, 11;
    --tblr-orange-lt: rgba(181, 148, 11, 0.1);
    --tblr-warning: var(--prodex-gold);
    --tblr-warning-rgb: 181, 148, 11;
    --tblr-warning-lt: rgba(181, 148, 11, 0.1);
    --tblr-warning-fg: #ffffff;
}

/* ── 2. Oscuro: superficies azul noche ── */
[data-bs-theme="dark"] {
    --tblr-orange: #cfa91e;
    --tblr-orange-rgb: 207, 169, 30;
    --tblr-orange-lt: rgba(207, 169, 30, 0.15);
    --tblr-warning: #cfa91e;
    --tblr-warning-rgb: 207, 169, 30;
    --tblr-warning-lt: rgba(207, 169, 30, 0.15);
    --tblr-warning-fg: #ffffff;

    --tblr-body-bg: #16202f;
    --tblr-bg-surface: #1d273b;
    --tblr-bg-surface-dark: #16202f;
    --tblr-bg-surface-secondary: #253045;
    --tblr-bg-surface-tertiary: #253045;
    --tblr-border-color: #2c3b55;
    --tblr-border-color-translucent: rgba(44, 59, 85, 0.75);
    --tblr-body-color: #e4e8ef;
    --tblr-secondary: #9aa5b8;
}

[data-bs-theme="dark"] body,
[data-bs-theme="dark"] .page {
    background-color: #16202f;
}

[data-bs-theme="dark"] .card,
[data-bs-theme="dark"] .modal-content,
[data-bs-theme="dark"] .dropdown-menu,
[data-bs-theme="dark"] .list-group-item {
    background-color: #1d273b;
    border-color: #2c3b55;
}

[data-bs-theme="dark"] .navbar-vertical,
[data-bs-theme="dark"] .navbar.navbar-vertical {
    background-color: var(--prodex-noche);
    border-color: #2a2b2f;
}

[data-bs-theme="dark"] .form-control,
[data-bs-theme="dark"] .form-select {
    background-color: #253045;
    border-color: #2c3b55;
    color: #e4e8ef;
}

.card {
    border-radius: 10px;
}

/* ── 3. Barra lateral: el destino activo, en oro ── */
.navbar-vertical .nav-link.active,
.navbar-vertical .nav-link.active .nav-link-icon,
.navbar-vertical .nav-link.active .nav-link-title {
    color: var(--tblr-primary) !important;
}

.navbar-vertical .nav-item .nav-link.active {
    background-color: rgba(207, 169, 30, 0.12);
    border-radius: 8px;
    font-weight: 600;
}

/* ── 4. Píldoras de estado: oro relleno = actúa · acero perfilado = hecho ──
 * El 26-ago «hecho» era oro perfilado, y en una lista donde casi todo está
 * hecho (Interacciones) la columna entera salía dorada. Desde el 20-sep lo
 * hecho INFORMA y va en acero; el oro se reserva a lo que pide algo. */
.badge-state-action {
    background-color: var(--tblr-primary) !important;
    color: #ffffff !important;
    border: 0;
}

.badge-state-done {
    background-color: transparent !important;
    border: 1px solid #8fa4c9 !important;
    color: #5c7396 !important;
}

[data-bs-theme="dark"] .badge-state-done {
    border-color: rgba(143, 164, 201, .5) !important;
    color: #8fa4c9 !important;
}

.badge-state-progress {
    background-color: #5c7396 !important; /* steel deep enough for white text */
    color: #ffffff !important;
}

.badge-state-blocked {
    background-color: #d63939 !important;
    color: #ffffff !important;
}

.badge-state-inactive {
    background-color: var(--tblr-bg-surface-secondary) !important;
    color: var(--tblr-secondary) !important;
}

/* ── 5. Táctil: nada por debajo de 40px ni de 12px en el móvil ── */
/* A round button keeps its shape: 28px on the desktop, 40px on the phone —
   the same minimum height every .btn gets below, so it stays a circle
   instead of stretching into an oval. */
.btn-circulo {
    height: 28px;
    width: 28px;
}

@media (max-width: 767.98px) {
    .btn-circulo {
        height: 40px;
        width: 40px;
    }

    .btn,
    button:not(.btn-close) {
        min-height: 40px;
    }

    .btn {
        min-width: 40px;
    }

    .btn-icon {
        min-width: 40px;
    }

    .dropdown-item,
    .nav-link {
        align-items: center;
        display: flex;
        min-height: 40px;
        min-width: 40px;
    }

    .btn-list {
        flex-wrap: wrap;
    }

    .form-control,
    .form-select {
        min-height: 44px;
        font-size: 1rem; /* 16px: por debajo, iOS hace zoom al enfocar */
    }

    .table td,
    .table th {
        font-size: var(--prodex-font-body);
    }

    .table-responsive {
        -webkit-overflow-scrolling: touch;
    }

    .card-header {
        flex-wrap: wrap;
        gap: .5rem;
    }

    .card-body,
    .modal-body {
        overflow-wrap: anywhere;
    }
}

/* ── 6. Menú principal arriba ───────────────────────────────────
 * El lateral es también el menú de móvil. El texto evita que el icono solo
 * parezca una acción secundaria y no hay una segunda navegación superpuesta. */
.menu-principal-toggle-text {
    display: none;
}

/* ── Agenda visual ────────────────────────────────────────────── */
.agenda-calendar {
    background: var(--tblr-bg-surface);
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius-lg);
    overflow: hidden;
}

.agenda-calendar-toolbar {
    align-items: center;
    border-bottom: 1px solid var(--tblr-border-color);
    display: flex;
    gap: 1rem;
    justify-content: space-between;
    padding: .75rem 1rem;
}

.agenda-calendar-range { font-size: .9375rem; text-transform: capitalize; }
.agenda-view-switch { flex-wrap: wrap; }
.agenda-period-button { height: 2rem; width: 2rem; }

.agenda-month {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
}

.agenda-month-weekday {
    background: var(--tblr-bg-surface-secondary);
    border-bottom: 1px solid var(--tblr-border-color);
    color: var(--tblr-secondary);
    font-size: .75rem;
    font-weight: 700;
    padding: .5rem;
    text-align: center;
}

.agenda-month-day {
    border-bottom: 1px solid var(--tblr-border-color);
    border-right: 1px solid var(--tblr-border-color);
    min-height: 8rem;
    padding: .35rem;
}

.agenda-month-day:nth-child(7n) { border-right: 0; }
.agenda-month-day.is-outside { background: var(--tblr-bg-surface-secondary); opacity: .58; }
.agenda-month-day.is-today { background: var(--tblr-primary-lt); }
.agenda-month-date { color: inherit; display: inline-block; font-size: .8125rem; font-weight: 700; margin-bottom: .25rem; text-decoration: none; }

.agenda-event-chip {
    border-left: 3px solid currentColor;
    border-radius: 3px;
    display: block;
    font-size: .7rem;
    line-height: 1.25;
    margin: 2px 0;
    overflow: hidden;
    padding: 2px 4px;
    text-decoration: none;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Two colours and only two (Pedro, 1-oct-2026): work and personal. He picks
   them in the agenda toolbar; they arrive as --agenda-trabajo / --agenda-personal
   on .agenda-calendar. The tint and the text are derived from the one colour,
   so any pick stays readable on the white and on the dark surface. */
.agenda-event-chip.is-trabajo, .agenda-time-event.is-trabajo { --agenda-c: var(--agenda-trabajo, #b5940b); }
.agenda-event-chip.is-personal, .agenda-time-event.is-personal { --agenda-c: var(--agenda-personal, #4f6f8f); }
.agenda-event-chip.is-trabajo, .agenda-time-event.is-trabajo,
.agenda-event-chip.is-personal, .agenda-time-event.is-personal {
    background: color-mix(in srgb, var(--agenda-c) 15%, var(--tblr-bg-surface, #fff));
    color: color-mix(in srgb, var(--agenda-c) 78%, var(--tblr-body-color, #1f2937));
}
.agenda-time-event.is-trabajo, .agenda-time-event.is-personal { border-left-color: var(--agenda-c); }
.agenda-time-event.is-borrador:not(.is-trabajo):not(.is-personal) { background: var(--tblr-secondary-lt); color: var(--tblr-secondary); }
.agenda-color-input { background: none; border: 1px solid var(--tblr-border-color); border-radius: 4px; cursor: pointer; height: 1.5rem; padding: 1px; width: 1.75rem; }
.agenda-pop-ambito { display: flex; gap: .25rem; }
.agenda-pop-ambito .btn { flex: 1 1 0; }
.agenda-pop-ambito .btn-check:checked + .btn { border-color: var(--agenda-c-sel); box-shadow: inset 0 0 0 1px var(--agenda-c-sel); color: var(--tblr-body-color); font-weight: 600; }

/* Circuito comercial: deliberately uses the same quiet cards and typography as
   the ERP.  The coloured line is a cue for planning, not a second dashboard. */
.commercial-circuit-hero { border-left: 3px solid var(--tblr-primary); }
.commercial-circuit-hero .card-title { font-size: 1.05rem; }

/* Like Google (1-oct): the page stays put, only the hour grid scrolls; the
   day titles, the all-day strip and the hours column stay in sight. */
.agenda-time-scroll { height: calc(100dvh - var(--agenda-top, 12rem) - .5rem); max-height: calc(100dvh - var(--agenda-top, 12rem) - .5rem); min-height: 14rem; overflow: auto; overscroll-behavior: contain; }
/* With the grid on screen the page itself must not move (Pedro, 1-oct): the
   header and the footer are what used to leave it scrollable. */
html.agenda-fija, html.agenda-fija body { height: 100%; overflow: hidden; }
html.agenda-fija .page-header { padding-bottom: .5rem; padding-top: .75rem; }
html.agenda-fija .page-body { margin-bottom: 0; margin-top: .5rem; padding-bottom: 0; padding-top: 0; }
html.agenda-fija .footer { display: none; }
html.agenda-fija .agenda-calendar { margin-bottom: 0; }
.agenda-time-corner, .agenda-time-day-title { position: sticky; top: 0; z-index: 8; }
.agenda-allday-corner, .agenda-allday-day { position: sticky; top: 3.25rem; z-index: 8; }
.agenda-time-corner, .agenda-allday-corner { left: 0; z-index: 11; }
.agenda-hours { background: var(--tblr-bg-surface); left: 0; position: sticky; z-index: 7; }
.agenda-allday-day { background: var(--tblr-bg-surface-secondary); }
.agenda-allday-day .agenda-event-chip { margin: 0; }
.agenda-time-grid { padding-bottom: 3rem; display: grid; grid-template-columns: 3.5rem repeat(var(--agenda-days), minmax(8rem, 1fr)); min-width: calc(3.5rem + var(--agenda-days) * 8rem); }
.agenda-time-corner, .agenda-time-day-title { background: var(--tblr-bg-surface); border-bottom: 1px solid var(--tblr-border-color); min-height: 3.25rem; }
.agenda-time-day-title { align-items: center; border-left: 1px solid var(--tblr-border-color); display: flex; flex-direction: column; justify-content: center; }
.agenda-time-day-title span { color: var(--tblr-secondary); font-size: .6875rem; font-weight: 700; }
.agenda-time-day-title strong { font-size: 1.125rem; line-height: 1.1; }
.agenda-time-day-title.is-today strong { align-items: center; background: var(--tblr-primary); border-radius: 50%; color: #fff; display: inline-flex; height: 1.8rem; justify-content: center; width: 1.8rem; }
.agenda-allday-corner, .agenda-allday-day { background: var(--tblr-bg-surface); border-bottom: 1px solid var(--tblr-border-color); min-height: 1.75rem; padding: .2rem .25rem; }
.agenda-allday-corner { color: var(--tblr-secondary); font-size: .625rem; font-weight: 700; line-height: 1.1; text-align: right; }
.agenda-allday-day { border-left: 1px solid var(--tblr-border-color); display: flex; flex-direction: column; gap: 2px; }
.agenda-event-chip.is-all-day { border-left: 3px solid currentColor; }
.agenda-event-chip { cursor: grab; }
.agenda-event-chip.is-dragging { cursor: grabbing; opacity: .5; }
.agenda-month-day.is-drop, .agenda-allday-day.is-drop { background: color-mix(in srgb, var(--tblr-primary) 12%, transparent); }
.agenda-hours { height: 1440px; position: relative; }
.agenda-hours span { color: var(--tblr-secondary); font-size: .6875rem; position: absolute; right: .5rem; top: calc(var(--hour) * 60px - .45rem); }
.agenda-time-day { background-image: repeating-linear-gradient(to bottom, transparent 0, transparent 59px, var(--tblr-border-color) 60px); border-left: 1px solid var(--tblr-border-color); height: 1440px; position: relative; }
.agenda-time-slot { height: 30px; left: 0; position: absolute; right: 0; top: calc(var(--slot) * 1px); z-index: 1; }
.agenda-time-slot:hover { background: color-mix(in srgb, var(--tblr-primary) 8%, transparent); }
.agenda-time-event { border-left: 3px solid currentColor; border-radius: 4px; display: block; height: calc(var(--duration) * 1px - 3px); left: 3px; overflow: hidden; padding: .2rem .35rem; position: absolute; right: 3px; text-decoration: none; top: calc(var(--start) * 1px + 2px); z-index: 2; }
.agenda-time-event strong, .agenda-time-event > span { display: block; font-size: .75rem; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agenda-time-event > span { font-size: .6875rem; opacity: .85; }

/* Calendar interaction (1-oct): drag to move, bottom edge to resize, popover.
   Overlapping citas share the column side by side, like Google Calendar. */
.agenda-time-event { --col: 0; --cols: 1; cursor: grab; left: calc(3px + (100% - 6px) * var(--col) / var(--cols)); right: auto; user-select: none; width: calc((100% - 6px) / var(--cols) - 2px); }
@media (pointer: fine) { .agenda-time-event { touch-action: none; } }
.agenda-time-event, .agenda-time-event:hover, .agenda-event-chip:hover { text-decoration: none; }
.agenda-time-event:hover { box-shadow: 0 1px 4px rgba(0, 0, 0, .14); }
.agenda-time-event.is-dragging { box-shadow: 0 6px 18px rgba(0, 0, 0, .22); cursor: grabbing; left: 3px; opacity: .92; transition: none; width: calc(100% - 8px); z-index: 6; }
/* Under half an hour (Pedro, 1-oct): never shorter than one readable line,
   and that line is start + title, as Google does. */
.agenda-time-event.is-corta { align-items: center; display: flex; gap: .3rem; min-height: 19px; padding: 0 .35rem; }
.agenda-time-event.is-corta strong { flex: 0 1 auto; font-size: .6875rem; line-height: 17px; min-width: 0; }
.agenda-time-event.is-corta > .agenda-time-hora { flex: 0 1000 auto; line-height: 17px; min-width: 0; text-overflow: clip; }
.agenda-time-event.is-corta > span:not(.agenda-resize):not(.agenda-time-hora) { display: none; }
.agenda-time-event.is-corta .agenda-resize { height: 5px; }
.agenda-time-event.is-saving { opacity: .6; }
.agenda-time-event.is-borrador { box-shadow: 0 6px 18px rgba(0, 0, 0, .18); cursor: default; z-index: 5; }
.agenda-time-event.is-selected { outline: 2px solid currentColor; outline-offset: 1px; z-index: 5; }
.agenda-resize { bottom: 0; cursor: ns-resize; height: 8px; left: 0; position: absolute !important; right: 0; }
.agenda-resize::after { background: currentColor; border-radius: 2px; bottom: 2px; content: ""; height: 3px; left: 50%; opacity: 0; position: absolute; transform: translateX(-50%); width: 16px; }
.agenda-time-event:hover .agenda-resize::after { opacity: .5; }
.agenda-calendar.is-dragging, .agenda-calendar.is-dragging * { cursor: grabbing !important; }
.agenda-calendar.is-resizing, .agenda-calendar.is-resizing * { cursor: ns-resize !important; }
.agenda-now { border-top: 2px solid var(--tblr-danger); left: 0; pointer-events: none; position: absolute; right: 0; top: calc(var(--now) * 1px); z-index: 4; }
.agenda-now::before { background: var(--tblr-danger); border-radius: 50%; content: ""; height: 10px; left: -5px; position: absolute; top: -6px; width: 10px; }

.agenda-pop { background: var(--tblr-bg-surface); border: 1px solid var(--tblr-border-color); border-radius: 10px; box-shadow: 0 12px 32px rgba(0, 0, 0, .18); max-height: calc(100vh - 16px); max-width: calc(100vw - 16px); overflow-y: auto; padding: .875rem 1rem 1rem; position: fixed; width: 27rem; z-index: 1080; }
.agenda-pop-campos { display: grid; gap: .5rem; margin-top: .75rem; }
.agenda-pop .ts-wrapper.form-select-sm .ts-control { font-size: .875rem; min-height: calc(1.5em + .5rem + 2px); padding: .125rem .5rem; }
.agenda-pop-cabecera { align-items: center; display: flex; gap: .25rem; justify-content: flex-end; margin: -.375rem -.5rem .25rem 0; }
.agenda-pop-cabecera .btn { height: 2rem; width: 2rem; }
.agenda-pop-titulo { background: transparent; border: 0; color: inherit; border-bottom: 1px solid var(--tblr-border-color); border-radius: 0; font-size: 1.125rem; font-weight: 600; padding: .25rem 0; width: 100%; }
.agenda-pop-titulo:focus { border-bottom-color: var(--tblr-primary); box-shadow: none; outline: 0; }
.agenda-pop-horas { align-items: center; display: grid; gap: .375rem; grid-template-columns: 1fr auto auto auto; margin-top: .75rem; }
.agenda-pop-horas input { font-variant-numeric: tabular-nums; }
.agenda-pop-dato { color: var(--tblr-secondary); font-size: .8125rem; margin-top: .5rem; }
.agenda-pop-dato a { color: inherit; }
.agenda-pop-pie { align-items: center; display: flex; gap: .5rem; justify-content: space-between; margin-top: 1rem; }
.agenda-pop-error { color: var(--tblr-danger); font-size: .8125rem; margin-top: .5rem; }

@media (max-width: 767.98px) {
    .agenda-calendar-toolbar { align-items: flex-start; flex-direction: column; }
    .agenda-view-switch .btn { padding-inline: .45rem; }
    .agenda-month { min-width: 42rem; }
    .agenda-calendar { overflow-x: auto; }
    .agenda-month-day { min-height: 6.5rem; }
}

@media (max-width: 991.98px) {
    .menu-principal-toggle {
        align-items: center;
        display: inline-flex;
        gap: .35rem;
        min-height: 40px;
        min-width: 78px;
        padding-inline: .625rem;
        width: auto;
    }

    .menu-principal-toggle-text {
        display: inline;
        font-size: .8125rem;
        font-weight: 700;
    }
}

/* Monthly closing: the native month field needs more room than Chromium's
 * desktop rendering suggests. On the phone, label and controls use two rows. */
.accounting-close-period-input {
    max-width: 12.5rem;
}

@media (max-width: 767.98px) {
    .accounting-close-period {
        display: grid !important;
        grid-template-columns: minmax(0, 1fr) auto;
    }

    .accounting-close-period label {
        grid-column: 1 / -1;
    }

    .accounting-close-period-input {
        max-width: none;
        min-width: 0;
        width: 100%;
    }

    .accounting-close-actions {
        display: grid;
        gap: .5rem;
    }

    .accounting-close-actions > form,
    .accounting-close-actions > a,
    .accounting-close-actions button {
        display: block !important;
        margin-inline: 0 !important;
        width: 100%;
    }
}

@media (min-width: 992px) {
    .sidebar-hidden #btn-sidebar-toggle {
        align-items: center;
        display: inline-flex;
        gap: .35rem;
        width: auto;
        padding-inline: .625rem;
    }

    .sidebar-hidden #btn-sidebar-toggle .menu-principal-toggle-text {
        display: inline;
        font-size: .8125rem;
        font-weight: 700;
    }
}

/* ── 7. Franja de acción fija en las fichas (móvil) ──
 * Al desaparecer la barra inferior, ocupa el borde inferior por sí sola. */
@media (max-width: 767.98px) {
    .franja-accion {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1029;
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
        background: var(--tblr-bg-surface);
        border-top: 1px solid var(--tblr-border-color);
    }

    .franja-accion .btn {
        flex: 1;
    }

    body.con-franja {
        padding-bottom: 76px;
    }
}

/* ── 8. Cabecera de página: dice qué pasa, no cómo se llama la sección ── */
.page-header .page-title {
    font-size: var(--prodex-font-page);
    font-weight: 800;
    letter-spacing: -0.01em;
    line-height: 1.2;
}

.page-header .page-subtitle,
.page-header .text-secondary {
    font-size: var(--prodex-font-body);
    color: var(--tblr-secondary);
}

/* ── 9. Tablas: fila más alta y cabecera que se lee como etiqueta ── */
.table > :not(caption) > * > * {
    padding: 0.75rem 0.75rem;
}

.table thead th {
    font-size: var(--prodex-font-meta);
    text-transform: uppercase;
    letter-spacing: 0.09em;
    font-weight: 700;
    color: var(--tblr-secondary);
}

/* Ninguna tabla empuja la página de lado: se desplaza dentro de su caja. */
.table-responsive,
.card > .table-responsive {
    overflow-x: auto;
}

/* ── 10. La acción principal de CADA página, fija abajo en el móvil ──
 * No hace falta tocar 200 plantillas: todas heredan la misma cabecera de
 * layout/admin.html.twig, y el bloque page_actions siempre cae en esta
 * columna. Se recoloca con CSS, así que los botones son LOS MISMOS —
 * conservan sus manejadores, sus modales y sus formularios.
 * :has() evita la franja vacía en las páginas que no tienen acciones. */
@media (max-width: 767.98px) {
    .page-header .col-auto.ms-auto:has(.btn) {
        position: fixed;
        left: 0;
        right: 0;
        bottom: calc(64px + env(safe-area-inset-bottom, 0px));
        z-index: 1029;
        width: 100%;
        max-width: none;
        margin: 0;
        padding: 10px 14px;
        display: flex;
        gap: 8px;
        overflow-x: auto;
        background: var(--tblr-bg-surface);
        border-top: 1px solid var(--tblr-border-color);
    }

    [data-bs-theme="dark"] .page-header .col-auto.ms-auto:has(.btn) {
        background: #1a2334;
    }

    .page-header .col-auto.ms-auto:has(.btn) > .btn,
    .page-header .col-auto.ms-auto:has(.btn) > .btn-list > .btn {
        flex: 1 0 auto;
    }

    .page-header .col-auto.ms-auto:has(.btn) > .btn-list {
        display: flex;
        gap: 8px;
        width: 100%;
    }

    body:has(.page-header .col-auto.ms-auto .btn) {
        padding-bottom: 130px;
    }
}

/* ── 11. Botón trabajando: apagado y girando ── */
.btn[data-enviando] {
    pointer-events: none;
    opacity: 0.62;
}

.btn .girando {
    display: inline-block;
    width: 0.95em;
    height: 0.95em;
    margin-right: 0.45em;
    border-radius: 50%;
    border: 2px solid currentColor;
    border-top-color: transparent;
    vertical-align: -0.12em;
    animation: prodex-gira 0.7s linear infinite;
}

@keyframes prodex-gira {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .btn .girando { animation-duration: 2.4s; }
}

/* ── 12. Los 800 badges existentes, remapeados a los tres colores ──
 * Decidido con Pedro (26-ago): oro relleno = actúa · oro perfilado = hecho ·
 * acero = informa · rojo = SOLO retraso. Las plantillas usan las utilidades
 * de Tabler (bg-*-lt) en ~800 sitios; en vez de editar 800 llamadas, se
 * remapean aquí las clases por su SIGNIFICADO de uso en este ERP:
 *   verdes  -> hecho    · amarillos/naranjas -> actúa
 *   azules/púrpura -> informa · rojos -> retraso/error
 * El día que una vista quiera salirse del mapa, que use badge-state-*. */

/* hecho: ACERO perfilado (20-sep). Era oro, y en cualquier lista donde casi
   todo está hecho el oro dejaba de señalar nada. Lo hecho informa. */
.badge.bg-green-lt,
.badge.bg-success-lt,
.badge.bg-teal-lt,
.badge.bg-lime-lt {
    background-color: transparent !important;
    border: 1px solid #8fa4c9 !important;
    color: #5c7396 !important;
}

[data-bs-theme="dark"] .badge.bg-green-lt,
[data-bs-theme="dark"] .badge.bg-success-lt,
[data-bs-theme="dark"] .badge.bg-teal-lt,
[data-bs-theme="dark"] .badge.bg-lime-lt {
    border-color: rgba(143, 164, 201, .5) !important;
    color: #8fa4c9 !important;
}

/* actúa: oro relleno */
.badge.bg-yellow-lt,
.badge.bg-orange-lt,
.badge.bg-warning-lt,
.badge.bg-green,
.badge.bg-yellow,
.badge.bg-orange {
    background-color: var(--tblr-primary) !important;
    border-color: var(--tblr-primary) !important;
    color: #ffffff !important;
}

/* informa: acero en tinta suave */
.badge.bg-blue-lt,
.badge.bg-azure-lt,
.badge.bg-purple-lt,
.badge.bg-indigo-lt,
.badge.bg-cyan-lt,
.badge.bg-primary-lt {
    background-color: rgba(143, 164, 201, 0.16) !important;
    color: #5c7396 !important;
}

[data-bs-theme="dark"] .badge.bg-blue-lt,
[data-bs-theme="dark"] .badge.bg-azure-lt,
[data-bs-theme="dark"] .badge.bg-purple-lt,
[data-bs-theme="dark"] .badge.bg-indigo-lt,
[data-bs-theme="dark"] .badge.bg-cyan-lt,
[data-bs-theme="dark"] .badge.bg-primary-lt {
    color: #8fa4c9 !important;
}

.badge.bg-blue,
.badge.bg-azure,
.badge.bg-purple {
    background-color: #5c7396 !important; /* steel deep enough for white text */
    color: #ffffff !important;
}

/* retraso o error: rojo relleno, el único que grita */
.badge.bg-red-lt,
.badge.bg-danger-lt,
.badge.bg-red,
.badge.bg-danger {
    background-color: #d63939 !important;
    border-color: #d63939 !important;
    color: #ffffff !important;
}

/* pasado / apagado: gris hundido */
.badge.bg-secondary-lt,
.badge.bg-muted-lt,
.badge.bg-gray-lt {
    background-color: var(--tblr-bg-surface-secondary) !important;
    color: var(--tblr-secondary) !important;
}

/* ── 13. Botones: una sola voz para «guardar/confirmar» ──
 * El parche de julio pintaba .btn-success de azul noche; con el sistema
 * nuevo la acción principal es SIEMPRE oro, sea btn-primary o btn-success
 * (el «Guardar» de los formularios). El resto de variantes —incluidos
 * danger, warning y outline-success— se definen en admin.css («Un solo
 * dorado», 20-sep-2026): neutras, con el rojo y el verde solo en el texto. */
.btn-success {
    --tblr-btn-color: #ffffff;
    --tblr-btn-bg: var(--tblr-primary);
    --tblr-btn-border-color: var(--tblr-primary);
    --tblr-btn-hover-color: #ffffff;
    --tblr-btn-hover-bg: var(--tblr-primary-darken, #b8941a);
    --tblr-btn-hover-border-color: var(--tblr-primary-darken, #b8941a);
    --tblr-btn-active-color: #ffffff;
    --tblr-btn-active-bg: var(--tblr-primary-darken, #b8941a);
}

[data-bs-theme="dark"] .btn-success {
    --tblr-btn-bg: #cfa91e;
    --tblr-btn-border-color: #cfa91e;
    --tblr-btn-hover-bg: #b8941a;
    --tblr-btn-hover-border-color: #b8941a;
}

/* Pestañas y píldoras de navegación: la activa habla en oro */
.nav-tabs .nav-link.active,
.nav-pills .nav-link.active {
    color: var(--tblr-primary);
    border-bottom-color: var(--tblr-primary);
    font-weight: 700;
}

.nav-pills .nav-link.active {
    background-color: rgba(207, 169, 30, 0.14);
}

/* ── 14. Alertas sin fondo de color: borde que dice el estado ──
 * Pedro (26-ago): fuera los fondos marrones/ámbar de los avisos. Toda alerta
 * es superficie normal con borde semántico; solo el retraso lleva rojo. */
.alert-warning,
.alert-success,
.alert-info,
.alert-secondary {
    background-color: var(--tblr-bg-surface) !important;
    color: var(--tblr-body-color) !important;
}

.alert-warning,
.alert-success {
    border-color: var(--tblr-primary) !important;
}

.alert-info,
.alert-secondary {
    border-color: #8fa4c9 !important;
}

.alert-danger {
    background-color: var(--tblr-bg-surface) !important;
    color: var(--tblr-body-color) !important;
    border-color: #d63939 !important;
}

.alert .alert-title,
.alert-warning .alert-title,
.alert-success .alert-title {
    color: inherit;
}

/* ── Menú lateral plegable (solo lg+) ──────────────────────────────
 * El <aside> ocupa 15rem fijos: en un MacBook de 13" eso es el 17 %
 * del ancho útil. Plegado, el contenido se queda con la pantalla
 * entera y el menú vuelve de tres formas: pasando el ratón por el
 * borde izquierdo, con el botón de la cabecera o con ⌘\ / Ctrl+\.
 * La clase vive en <html> (no en <body>) para poder aplicarla desde
 * el <head>, antes del primer pintado, y que no haya salto.
 * Por debajo de lg no se toca nada: ahí el mismo <aside> ES la barra
 * superior del móvil, con su propio collapse de Bootstrap.
 */
.sidebar-peek { display: none; }

@media (min-width: 992px) {
    .navbar-vertical.navbar-expand-lg ~ .page-wrapper {
        transition: margin-left .3s;
    }

    .sidebar-hidden .navbar-vertical.navbar-expand-lg {
        transform: translateX(-100%);
    }

    .sidebar-hidden .navbar-vertical.navbar-expand-lg ~ .page-wrapper {
        margin-left: 0;
    }

    /* Franja sensible del borde izquierdo. Va DEBAJO del aside
       (z-index 1029 < 1030) para no interceptar clics del menú una vez
       abierto; cuando el aside lo tapa, el :hover pasa de una a otro y
       el segundo selector lo mantiene abierto. */
    .sidebar-hidden .sidebar-peek {
        display: block;
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        width: 10px;
        z-index: 1029;
    }

    /* El retardo evita que un roce al ir a por el Dock abra el menú */
    .sidebar-hidden .sidebar-peek:hover + .navbar-vertical,
    .sidebar-hidden .navbar-vertical:hover {
        transform: none;
        transition-delay: .15s;
        box-shadow: 0 0 28px rgba(0, 0, 0, .28);
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   Mobile rows ("renglón")

   Narrow-screen counterpart of a table row. Listings keep their <table> for
   md and up (wrapped in .d-none.d-md-block) and render the same records with
   templates/_piezas/_renglon.html.twig below md, so a phone never has to
   scroll a table sideways. Type sizes come from the .fs-* scale only.
   ────────────────────────────────────────────────────────────────────────── */
.renglon {
    align-items: flex-start;
    border-bottom: 1px solid var(--tblr-border-color);
    color: inherit;
    display: flex;
    gap: .75rem;
    min-height: 3.25rem;
    padding: .625rem 1rem;
    text-decoration: none;
}

.renglon:last-child {
    border-bottom: 0;
}

.renglon:active,
.renglon:focus-visible {
    background-color: var(--tblr-bg-surface-secondary);
}

.renglon-cuerpo {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: .1rem;
    min-width: 0;
}

.renglon-titulo {
    font-weight: 600;
    overflow-wrap: anywhere;
}

.renglon-sub,
.renglon-meta {
    color: var(--tblr-secondary);
    overflow-wrap: anywhere;
}

.renglon-insignia {
    flex: none;
    margin-top: .15rem;
}

/* ──────────────────────────────────────────────────────────────────────────
   Toasts ("tostadas")

   A confirmation floats here and leaves on its own; problems keep using the
   inline .alert. When the action can be undone the toast carries the button,
   which is what lets a reversible action skip the confirmation dialog.
   ────────────────────────────────────────────────────────────────────────── */
.tostadas {
    bottom: 1rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    left: 50%;
    max-width: min(30rem, calc(100vw - 2rem));
    position: fixed;
    transform: translateX(-50%);
    width: 100%;
    z-index: 1080;
}

.tostada {
    align-items: center;
    background-color: var(--prodex-night);
    border-radius: var(--tblr-border-radius);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .28);
    color: #e4e8ef;
    display: flex;
    gap: .75rem;
    padding: .625rem .5rem .625rem .875rem;
}

.tostada-texto {
    flex: 1;
    min-width: 0;
    overflow-wrap: anywhere;
}

.tostada-deshacer {
    flex: none;
    margin: 0;
}

.tostada-boton {
    background: none;
    border: 1px solid var(--tblr-primary);
    border-radius: var(--tblr-border-radius-sm);
    color: var(--tblr-primary);
    cursor: pointer;
    font-weight: 600;
    padding: .25rem .625rem;
}

.tostada-boton:hover {
    background-color: var(--tblr-primary);
    color: #ffffff;
}

.tostada-cerrar {
    background: none;
    border: 0;
    color: #9aa5b8;
    cursor: pointer;
    flex: none;
    line-height: 1;
    padding: .25rem .5rem;
}

.tostada-cerrar:hover {
    color: #e4e8ef;
}

/* Above a page's fixed action bar, plus the phone's safe area. */
@media (max-width: 767.98px) {
    .tostadas {
        bottom: calc(4.25rem + env(safe-area-inset-bottom, 0px));
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   Action palette ("paleta")

   Cmd/Ctrl+K on the operation file. It lists the actions that are already
   rendered on the page and takes you to the one you pick — it never presses
   it, so an irreversible step is still seen in its context first.
   ────────────────────────────────────────────────────────────────────────── */
.paleta {
    align-items: flex-start;
    background-color: rgba(29, 39, 59, .45);
    display: flex;
    inset: 0;
    justify-content: center;
    padding: 4rem 1rem 1rem;
    position: fixed;
    z-index: 1090;
}

.paleta-caja {
    background-color: var(--tblr-bg-surface);
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius-lg);
    box-shadow: 0 16px 48px rgba(0, 0, 0, .28);
    display: flex;
    flex-direction: column;
    max-height: min(32rem, calc(100vh - 6rem));
    max-width: 34rem;
    overflow: hidden;
    width: 100%;
}

.paleta-entrada {
    background-color: transparent;
    border: 0;
    border-bottom: 1px solid var(--tblr-border-color);
    color: var(--tblr-body-color);
    padding: .875rem 1rem;
    width: 100%;
}

.paleta-entrada:focus {
    outline: 0;
}

.paleta-lista {
    list-style: none;
    margin: 0;
    overflow-y: auto;
    padding: .375rem;
}

.paleta-fila {
    align-items: baseline;
    border-radius: var(--tblr-border-radius);
    cursor: pointer;
    display: flex;
    gap: .75rem;
    justify-content: space-between;
    padding: .5rem .625rem;
}

.paleta-fila.elegida {
    background-color: var(--tblr-primary-lt);
}

.paleta-accion {
    font-weight: 500;
    overflow-wrap: anywhere;
}

.paleta-seccion {
    color: var(--tblr-secondary);
    flex: none;
    text-align: right;
}

.paleta-vacio {
    color: var(--tblr-secondary);
    padding: 1rem .625rem;
}

.paleta-pie {
    border-top: 1px solid var(--tblr-border-color);
    color: var(--tblr-secondary);
    padding: .5rem 1rem;
}

/* Where the palette left you. */
.paleta-senalada {
    box-shadow: 0 0 0 3px var(--tblr-primary);
    position: relative;
    z-index: 1;
}

/* ──────────────────────────────────────────────────────────────────────────
   Filter chips ("fichas de filtro" y "filtros puestos")

   A dropdown hides both the options and the choice. The chip row shows the
   options; the "puestos" line shows what is applied and takes it off with one
   tap. Both scroll sideways inside themselves, never widening the page.
   ────────────────────────────────────────────────────────────────────────── */
.fichas-filtro,
.filtros-puestos {
    align-items: center;
    display: flex;
    gap: .375rem;
    overflow-x: auto;
    padding-bottom: .125rem;
    scrollbar-width: none;
}

.fichas-filtro::-webkit-scrollbar,
.filtros-puestos::-webkit-scrollbar {
    display: none;
}

.ficha-filtro {
    background-color: var(--tblr-bg-surface);
    border: 1px solid var(--tblr-border-color);
    border-radius: 999px;
    color: var(--tblr-body-color);
    flex: none;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.4;
    padding: .3125rem .75rem;
    text-decoration: none;
    white-space: nowrap;
}

.ficha-filtro:hover {
    border-color: var(--tblr-primary);
    color: var(--tblr-body-color);
}

/* Un solo dorado: a chosen filter is state, not the action of the screen. */
.ficha-filtro.puesta {
    background-color: var(--tblr-body-color);
    border-color: var(--tblr-body-color);
    color: var(--tblr-body-bg);
}

.filtros-puestos {
    margin-top: .5rem;
}

.filtros-puestos-t {
    color: var(--tblr-secondary);
    flex: none;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.filtro-puesto {
    align-items: baseline;
    background-color: var(--tblr-primary-lt);
    border: 1px solid transparent;
    border-radius: var(--tblr-border-radius);
    color: var(--tblr-body-color);
    display: flex;
    flex: none;
    font-size: .75rem;
    gap: .375rem;
    padding: .25rem .5rem;
    text-decoration: none;
}

.filtro-puesto:hover {
    border-color: var(--tblr-primary);
    color: var(--tblr-body-color);
}

.filtro-puesto-k {
    color: var(--tblr-secondary);
    letter-spacing: .05em;
    text-transform: uppercase;
}

.filtro-puesto-v {
    font-weight: 600;
}

.filtro-puesto-x {
    color: var(--tblr-secondary);
    font-weight: 700;
}

.filtros-puestos-n {
    color: var(--tblr-secondary);
    flex: none;
    white-space: nowrap;
}

/* «Siguiente paso» column of the listings: one colour per state. */
.siguiente-paso { display: inline-flex; align-items: center; gap: .375rem; font-size: .8125rem; max-width: 16rem; }
.siguiente-paso-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.siguiente-paso.vencido { color: var(--tblr-danger); font-weight: 600; }
.siguiente-paso.hoy { color: var(--tblr-success); font-weight: 600; }
.siguiente-paso.futuro { color: var(--tblr-body-color); }
.siguiente-paso.nada { color: var(--tblr-secondary); }

/* Bulk selection in the contact list (Trabajo 4). */
.fila-marcada > td { background-color: var(--tblr-primary-lt) !important; }
.barra-lote { position: sticky; bottom: 0; z-index: 5; }

.filtro-puesto-todo {
    background-color: transparent;
    border-color: var(--tblr-border-color);
    color: var(--tblr-secondary);
    letter-spacing: .05em;
    text-transform: uppercase;
}

/* Task title: one truncated line on the desktop; on the phone it wraps to two
   lines so it can be read whole — there the row has no width to spare. */
.task-titulo {
    max-width: 40rem;
}

@media (max-width: 767.98px) {
    .task-titulo {
        display: -webkit-box;
        max-width: none;
        overflow: hidden;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        white-space: normal;
    }
}

/* Phone: the task row is two lines instead of one. On 390px a single line
   left the title 34px once the date, the two scope toggles and the menu had
   taken theirs. The circle and the menu span both lines; the title gets the
   width; date and scope toggles sit underneath. The same children live either
   directly in the row or, once the swipe is armed, inside .deslizar-contenido,
   so both containers get the grid. */
@media (max-width: 767.98px) {
    .task-row > .deslizar-contenido,
    .task-row:not(.deslizable) {
        align-items: center;
        column-gap: .5rem;
        display: grid;
        grid-template-areas:
            "circulo titulo   titulo  titulo menu"
            "circulo fecha    personal trabajo menu";
        grid-template-columns: auto minmax(0, 1fr) auto auto auto;
        row-gap: .375rem;
    }

    .task-row > .deslizar-contenido > :nth-child(1),
    .task-row:not(.deslizable) > :nth-child(1) { grid-area: circulo; }

    .task-row > .deslizar-contenido > :nth-child(2),
    .task-row:not(.deslizable) > :nth-child(2) { grid-area: titulo; }

    .task-row > .deslizar-contenido > :nth-child(3),
    .task-row:not(.deslizable) > :nth-child(3) { grid-area: fecha; }

    .task-row > .deslizar-contenido > :nth-child(4),
    .task-row:not(.deslizable) > :nth-child(4) { grid-area: personal; }

    .task-row > .deslizar-contenido > :nth-child(5),
    .task-row:not(.deslizable) > :nth-child(5) { grid-area: trabajo; }

    /* The menu goes by class: a done task has no bell, so its position moves. */
    .task-row > .deslizar-contenido > .task-row-menu,
    .task-row:not(.deslizable) > .task-row-menu { grid-area: menu; justify-self: end; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Swipe on a row ("deslizar")

   Below lg the row can be dragged to the left to fire the form it already
   carries. The label underneath only shows once the drag is past the point of
   no return, so a half gesture says "not yet" by itself.
   ────────────────────────────────────────────────────────────────────────── */
.deslizable {
    overflow: hidden;
    position: relative;
    touch-action: pan-y;
}

.deslizar-fondo {
    align-items: center;
    background-color: var(--tblr-primary);
    bottom: 0;
    color: #ffffff;
    display: flex;
    font-size: .6875rem;
    font-weight: 700;
    justify-content: center;
    letter-spacing: .08em;
    opacity: 0;
    position: absolute;
    right: 0;
    text-transform: uppercase;
    top: 0;
    width: 10rem;
}

.deslizable.armado .deslizar-fondo {
    opacity: 1;
}

/* Commercial candidates use independent native disclosure controls. */
.commercial-candidates .commercial-candidate-summary {
    align-items: flex-start;
    cursor: pointer;
    display: flex;
    gap: .5rem;
    list-style: none;
}
.commercial-candidates .commercial-candidate-summary::-webkit-details-marker {
    display: none;
}
.commercial-candidates .commercial-candidate-summary::before {
    color: var(--tblr-secondary);
    content: '›';
    flex: 0 0 auto;
    font-weight: 600;
    transition: transform .15s ease;
}
.commercial-candidates .commercial-candidate[open] > summary::before {
    transform: rotate(90deg);
}
.commercial-candidates .commercial-candidate-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
    white-space: normal;
}
.commercial-candidates .commercial-candidate-body {
    min-width: 0;
    overflow-wrap: anywhere;
}
.commercial-candidates summary:focus-visible {
    outline: 2px solid var(--tblr-primary);
    outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
    .commercial-candidates .commercial-candidate-summary::before {
        transition: none;
    }
}

/* The wrapper takes the row's children, so it must lay them out the way the
   row did: a flex line, inheriting the row's own alignment and gap. Without
   this every child stacks on its own line (5-sep, seen on the iPhone). */
.deslizar-contenido {
    align-items: inherit;
    background-color: var(--tblr-bg-surface);
    display: flex;
    flex: 1 1 auto;
    gap: inherit;
    min-width: 0;
    position: relative;
    transition: transform .18s ease;
}

@media (prefers-reduced-motion: reduce) {
    .deslizar-contenido {
        transition: none;
    }
}

/* Poner al día el circuito: one quiet line per contact, no cards. */
.commercial-review { max-width: 780px; }
.commercial-review-row { display: grid; grid-template-columns: 1fr auto; gap: .25rem 1rem; align-items: center; padding: 1rem 0; border-top: 1px solid var(--tblr-border-color); }
.commercial-review-row:last-of-type { border-bottom: 1px solid var(--tblr-border-color); }
.commercial-review-edit { grid-column: 1 / -1; }
.commercial-review-edit > summary { cursor: pointer; list-style: none; text-decoration: underline; text-underline-offset: 3px; width: fit-content; }
.commercial-review-edit > summary::-webkit-details-marker { display: none; }
.commercial-review-ask { border: 0; border-bottom: 1px solid currentColor; background: transparent; color: inherit; width: 11rem; padding: 0 2px; outline: none; }
.commercial-group { border-top: 1px solid var(--tblr-border-color); }
.commercial-group:last-of-type { border-bottom: 1px solid var(--tblr-border-color); }
.commercial-group > summary { list-style: none; cursor: pointer; padding: .7rem 0; display: flex; gap: .6rem; align-items: center; }
.commercial-group > summary::-webkit-details-marker { display: none; }

/* ══════════════════════════════════════════════════════════════════
 * 20-sep-2026 — SE CIERRA LA REGLA DE TRES (Pedro: «sigue habiendo
 * diferentes colores al abrir, unifiquemos todo»).
 *
 * La capa del 26-ago dejó el ERP en oro · acero · rojo, pero solo tocó
 * naranja y aviso. Medido hoy sobre 15 pantallas reales (Hoy, contactos,
 * operaciones, inmuebles, tareas, interacciones, facturas, gastos,
 * proveedores, alquileres, partners, finanzas, objetivos, circuitos y
 * agenda), seguían pintándose SIETE tintas más: lima en las iniciales de
 * /interactions, morado en las de circuitos y contactos, ámbar en los
 * contadores de Hoy, petróleo en las campanas de espera, y de fondo las
 * familias amarilla, cian, rosa, azul-verdosa e índigo que Tabler trae de
 * serie y nadie había remapeado.
 *
 * Aquí se remapean TODAS a la paleta, sin tocar una sola plantilla:
 *   · lo que INFORMA (etiquetas, iniciales, tipos) → acero
 *   · lo que RECLAMA (pendiente, salvedad, «te falta») → oro
 *   · el retraso sigue siendo rojo, y no se toca
 * Los gráficos no usan estas familias (comprobado): nada que perder ahí.
 * La única excepción viva es el verde de WhatsApp en su propio botón: es
 * un logo, no un estado — se queda para poder encontrarlo de un vistazo.
 * ══════════════════════════════════════════════════════════════════ */
:root,
[data-bs-theme="light"] {
    --tblr-yellow: var(--prodex-gold);
    --tblr-yellow-rgb: 181, 148, 11;
    --tblr-yellow-lt: rgba(181, 148, 11, .1);
    --tblr-yellow-fg: #ffffff;

    --tblr-lime: #5c7396;
    --tblr-lime-rgb: 92, 115, 150;
    --tblr-lime-lt: rgba(143, 164, 201, .16);
    --tblr-lime-fg: #ffffff;
    --tblr-purple: #5c7396;
    --tblr-purple-rgb: 92, 115, 150;
    --tblr-purple-lt: rgba(143, 164, 201, .16);
    --tblr-purple-fg: #ffffff;
    --tblr-teal: #5c7396;
    --tblr-teal-rgb: 92, 115, 150;
    --tblr-teal-lt: rgba(143, 164, 201, .16);
    --tblr-teal-fg: #ffffff;
    --tblr-cyan: #5c7396;
    --tblr-cyan-rgb: 92, 115, 150;
    --tblr-cyan-lt: rgba(143, 164, 201, .16);
    --tblr-cyan-fg: #ffffff;
    --tblr-pink: #5c7396;
    --tblr-pink-rgb: 92, 115, 150;
    --tblr-pink-lt: rgba(143, 164, 201, .16);
    --tblr-pink-fg: #ffffff;
    --tblr-indigo: #5c7396;
    --tblr-indigo-rgb: 92, 115, 150;
    --tblr-indigo-lt: rgba(143, 164, 201, .16);
    --tblr-indigo-fg: #ffffff;
}
[data-bs-theme="dark"] {
    --tblr-yellow: #cfa91e;
    --tblr-yellow-rgb: 207, 169, 30;
    --tblr-yellow-lt: rgba(207, 169, 30, .15);

    --tblr-lime: #8fa4c9;
    --tblr-lime-rgb: 143, 164, 201;
    --tblr-lime-lt: rgba(143, 164, 201, .18);
    --tblr-purple: #8fa4c9;
    --tblr-purple-rgb: 143, 164, 201;
    --tblr-purple-lt: rgba(143, 164, 201, .18);
    --tblr-teal: #8fa4c9;
    --tblr-teal-rgb: 143, 164, 201;
    --tblr-teal-lt: rgba(143, 164, 201, .18);
    --tblr-cyan: #8fa4c9;
    --tblr-cyan-rgb: 143, 164, 201;
    --tblr-cyan-lt: rgba(143, 164, 201, .18);
    --tblr-pink: #8fa4c9;
    --tblr-pink-rgb: 143, 164, 201;
    --tblr-pink-lt: rgba(143, 164, 201, .18);
    --tblr-indigo: #8fa4c9;
    --tblr-indigo-rgb: 143, 164, 201;
    --tblr-indigo-lt: rgba(143, 164, 201, .18);
}

/* ── «Hecho» deja de ser oro (Pedro, 20-sep) ──────────────────────────
 * Al cerrar la regla de tres, el oro acabó haciendo dos trabajos: «esto te
 * reclama» y «esto ya está». Pantallas enteras —Interacciones, con su
 * columna de «Hecha»— se veían doradas de arriba abajo, y un acento que
 * aparece en todas las filas deja de ser un acento.
 * Lo hecho, lo confirmado y lo recibido INFORMAN: van a acero. El oro
 * queda solo para lo que pide una acción tuya. Esto reemplaza el mapeo
 * verde→oro del 4-ago, que nació cuando el verde era el problema.
 * ──────────────────────────────────────────────────────────────────── */
:root,
[data-bs-theme="light"] {
    --tblr-green: #5c7396;
    --tblr-green-rgb: 92, 115, 150;
    --tblr-green-lt: rgba(143, 164, 201, .16);
    --tblr-green-darken: #495c79;
    --tblr-green-fg: #ffffff;
    --tblr-success: #5c7396;
    --tblr-success-rgb: 92, 115, 150;
    --tblr-success-lt: rgba(143, 164, 201, .16);
    --tblr-success-darken: #495c79;
    --tblr-success-fg: #ffffff;
}
[data-bs-theme="dark"] {
    --tblr-green: #8fa4c9;
    --tblr-green-rgb: 143, 164, 201;
    --tblr-green-lt: rgba(143, 164, 201, .18);
    --tblr-success: #8fa4c9;
    --tblr-success-rgb: 143, 164, 201;
    --tblr-success-lt: rgba(143, 164, 201, .18);
}


/* ── UN SOLO MARCO (Pedro, 20-sep: «ponle los marcos a todo del mismo
 * color») ────────────────────────────────────────────────────────────
 * Convivían tres: el gris de serie de Tabler en las tarjetas, el verde
 * azulado #789da0 del marcador de Hoy y el acero de las cabeceras del
 * panel. Ahora hay uno, y es el acero de la paleta a media tinta: enmarca
 * sin pesar y no añade una cuarta tinta al ERP.
 * ─────────────────────────────────────────────────────────────────── */
:root,
[data-bs-theme="light"] {
    --prodex-marco: rgba(143, 164, 201, .5);
}
[data-bs-theme="dark"] {
    --prodex-marco: rgba(143, 164, 201, .28);
}
.card,
.card-header,
.card-footer,
.list-group-item {
    border-color: var(--prodex-marco);
}

/* Commercial block (22-sep-2026): one card per person, the current one lifted, the settled ones quiet. */
.commercial-block-card.is-current { box-shadow: 0 0 0 2px var(--tblr-primary); }
.commercial-block-card.is-settled { opacity: .72; }
.commercial-block-card.is-settled:hover { opacity: 1; }
.commercial-block-steps { display: grid; gap: .75rem; padding-left: calc(3.25rem + 1rem); }
.commercial-block-step { background: var(--tblr-bg-surface-secondary); border-radius: var(--tblr-border-radius); padding: .75rem; }
.commercial-block-step-title { font-weight: 600; margin-bottom: .5rem; display: flex; align-items: center; gap: .5rem; }
.commercial-block-step-n { display: inline-grid; place-items: center; width: 1.35rem; height: 1.35rem; border-radius: 50%; background: var(--tblr-primary); color: var(--tblr-primary-fg, #fff); font-size: .75rem; }
.commercial-block-result { padding-left: calc(3.25rem + 1rem); }
.commercial-block-steps > .btn { justify-self: start; }
@media (max-width: 575.98px) {
    .commercial-block-steps, .commercial-block-result { padding-left: 0; }
}
