/* Pregón — hoja de estilos única. Sin build, sin framework.
 *
 * Colores y tipografía de la marca Compás Urbano (manual de comunicación visual
 * + compasurbano.com). Pregón es una herramienta interna, así que la marca se
 * aplica con sobriedad: los "colores vivos" del manual entran como acento y no
 * como fondo. */

/* Open Sans es la tipografía de la marca. Va auto-hospedada y no por CDN: el
 * proyecto no admite dependencias externas y se despliega por FTP a cPanel,
 * donde no se puede dar por hecha la salida a internet. */
@font-face {
    font-family: "Open Sans";
    font-style: normal;
    /* Fuente variable: un archivo de 48 KB cubre todo el rango de pesos, en vez
     * de un archivo por peso. Es la misma copia que usa DiagnosticoOrg. */
    font-weight: 300 800;
    font-display: swap;
    src: url("fonts/opensans-variable.woff2") format("woff2-variations"),
         url("fonts/opensans-variable.woff2") format("woff2");
}

:root {
    /* Marca: 663 C de fondo, 504 C de tinta, 7425 C de acento. */
    --bg: #f0edee;
    --panel: #ffffff;
    --ink: #3f1922;
    --muted: #6f5c63;
    --line: #ddd3d6;
    --accent: #c41f47;

    /* Los colores de estado NO son de marca, a propósito. Si --bad fuera el
     * carmín corporativo, "probable bloqueo" se confundiría con cualquier
     * enlace y el panel de salud dejaría de leerse de un vistazo. */
    --ok: #2f7a4d;
    /* Más oscuro que el ámbar habitual porque se usa como TEXTO —el distintivo
     * "Sin detalle" y el veredicto de salud—, y a #b5761a se quedaba en 3.77:1. */
    --warn: #8a5a0f;
    --bad: #b03030;

    /* Vivos del manual (1935 C, 1495 C, 116 C), para acentos puntuales. */
    --vivo-carmin: #d6003d;
    --vivo-naranja: #e8762c;
    --vivo-amarillo: #f7c531;

    --radius: 10px;
}

@media (prefers-color-scheme: dark) {
    :root {
        /* 504 C de fondo y el vinotinto medio del sitio para las superficies. */
        --bg: #2b1119;
        --panel: #3f1922;
        --ink: #f0edee;
        --muted: #b09aa1;
        --line: #573040;
        /* El carmín se aclara: sobre vinotinto no llega a 4.5:1. */
        --accent: #ff8fa6;
        --ok: #6fc08d;
        --warn: #e0b063;
        --bad: #e58080;
    }
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font: 16px/1.5 "Open Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

main { max-width: 1100px; margin: 0 auto; padding: 1.5rem 1rem 4rem; }

h1 { font-size: 1.6rem; margin: 1.5rem 0 1rem; }
h2 { font-size: 1.15rem; margin: 2rem 0 .75rem; }
h3 { font-size: 1rem; margin: 0 0 .35rem; }

a { color: var(--accent); }
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .82em; }

.muted { color: var(--muted); }
.bad-text { color: var(--bad); }

/* Barra superior --------------------------------------------------------- */
.topbar {
    display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
    padding: .85rem 1rem;
    background: var(--panel);
    border-bottom: 1px solid var(--line);
}
.topbar .brand {
    display: inline-flex; align-items: center; gap: .5rem;
    font-weight: 700; letter-spacing: .02em; text-decoration: none; color: var(--ink);
}
/* El isotipo toma el vinotinto de marca aunque el texto sea la tinta normal. */
.topbar .brand .isotipo { color: var(--accent); flex: 0 0 auto; }
.topbar nav { display: flex; gap: 1.1rem; margin-left: auto; flex-wrap: wrap; }
.topbar nav a { text-decoration: none; color: var(--muted); }
.topbar nav a.on { color: var(--ink); font-weight: 600; }

/* Login ------------------------------------------------------------------ */
.login {
    max-width: 320px; margin: 12vh auto; padding: 2rem;
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
    text-align: center;
}
.login h1 { margin: 0; }
.login p { margin: .25rem 0 1.5rem; }
.login .isologo { color: var(--ink); margin-bottom: 1.25rem; }
.login input, .login button { width: 100%; }
.google-login { display:block; padding:.8rem 1rem; border:1px solid #bbb; border-radius:6px; text-align:center; background:#fff; color:#222; text-decoration:none; font-weight:600; }
.logout-form { display:inline; margin:0; }
.link-button { background:none; border:0; color:var(--muted); padding:0; cursor:pointer; font:inherit; }
.user-email { margin-left:1rem; }
.access-grid { display:grid; grid-template-columns:minmax(240px,1fr) minmax(420px,2fr); gap:2rem; align-items:start; }
.stacked-form { display:grid; gap:.75rem; }
.stacked-form input,.stacked-form select { padding:.65rem; }
button.danger { color:#fff; background:var(--bad); }

input, select, button {
    font: inherit; padding: .5rem .7rem;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--panel); color: var(--ink);
}
button { background: var(--accent); color: #fff; border-color: transparent; cursor: pointer; }
button:disabled { opacity: .5; cursor: default; }

.filters { display: flex; gap: .6rem; flex-wrap: wrap; margin-bottom: 1rem; }
.filters input[type=search] { flex: 1 1 16rem; }

.alert {
    padding: .7rem 1rem; border-radius: 8px; border: 1px solid var(--line);
    background: var(--panel);
}
.alert.ok { border-color: var(--ok); }
.alert.error { border-color: var(--bad); }
.alert.warn { border-color: var(--warn); }

/* Tarjetas de fuentes ---------------------------------------------------- */
.cards {
    display: grid;
    gap: 1rem;
    /* min() permite que la tarjeta se encoja por debajo de 280 px cuando el
     * viewport es más angosto, sin crear scroll horizontal. */
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
}

.card {
    background: var(--panel); border: 1px solid var(--line);
    border-left: 4px solid var(--muted);
    border-radius: var(--radius); padding: 1rem 1.1rem;
    min-width: 0;
}
.card.ok   { border-left-color: var(--ok); }
.card.warn { border-left-color: var(--warn); }
.card.bad  { border-left-color: var(--bad); }
.card.off  { border-left-color: var(--line); opacity: .7; }

.card h2 {
    margin: 0; font-size: 1.05rem; display: flex; align-items: baseline;
    gap: .25rem .5rem; flex-wrap: wrap;
}
.card .key { font-size: .75rem; color: var(--muted); font-weight: 400; }
.card .state { margin: .15rem 0 .8rem; font-size: .85rem; color: var(--muted); }

.card dl { display: grid; grid-template-columns: 1fr auto; gap: .2rem .8rem; margin: 0 0 .8rem; font-size: .875rem; }
.card dt { color: var(--muted); }
.card dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }

.card .counts { font-size: .82rem; color: var(--muted); margin: 0 0 .8rem; }
.card .actions { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }
.card .actions a { font-size: .85rem; }

/* Configuración de cada fuente. Los controles necesitan columnas elásticas:
 * un flex sin wrap deja que el ancho intrínseco de los inputs atraviese la
 * tarjeta (especialmente con tres fuentes en la misma fila). */
.card .source-settings {
    display: grid;
    gap: .5rem;
    margin-top: .65rem;
    align-items: center;
}
.card .source-settings label { white-space: nowrap; }
.card .source-settings input[type="text"] { width: 100%; min-width: 0; }
.card .sheet-setting { grid-template-columns: auto minmax(0, 1fr) auto; }
.card .identity-setting {
    grid-template-columns: minmax(4.5rem, .4fr) minmax(7rem, 1fr) auto;
}
.card .identity-setting label { grid-column: 1 / -1; }

@media (max-width: 420px) {
    .card .source-settings { grid-template-columns: 1fr; }
    .card .identity-setting label { grid-column: auto; }
    .card .source-settings button { width: 100%; }
}

/* Gráfica ---------------------------------------------------------------- */
.chart {
    width: 100%; height: 120px; display: block;
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
}
.chart rect { fill: var(--accent); }

/* Tablas ----------------------------------------------------------------- */
table {
    width: 100%; border-collapse: collapse; font-size: .875rem;
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
    overflow: hidden;
}
th, td { padding: .5rem .7rem; text-align: left; border-bottom: 1px solid var(--line); }
th { font-weight: 600; color: var(--muted); font-size: .8rem; }
tr:last-child td { border-bottom: 0; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.row-bad td { background: color-mix(in srgb, var(--bad) 8%, transparent); }
.error-detail { font-size: .82rem; color: var(--bad); }
.logs td code { word-break: break-all; }

/* El popup del log de una corrida: <dialog> nativo, sin librería. */
#log-dialog {
    position: relative; width: min(720px, 92vw); max-height: 80vh; padding: 1.2rem 1.4rem;
    border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--panel); color: var(--ink);
}
#log-dialog::backdrop { background: rgba(0, 0, 0, .45); }
#log-dialog h2 { margin: 0 0 .8rem; padding-right: 2rem; font-size: 1.05rem; }
#log-dialog .log-dialog-close {
    position: absolute; top: .7rem; right: .7rem; width: 1.8rem; height: 1.8rem;
    padding: 0; line-height: 1; font-size: 1.2rem; border-radius: 50%;
}
#log-dialog-body { overflow-y: auto; max-height: calc(80vh - 4rem); }
#log-dialog-body table.logs { margin: 0; }

/* La tabla no debe empujar el ancho de la página en móvil. */
h1 + table, .filters + table, h2 + table { display: block; overflow-x: auto; white-space: nowrap; }

.pill {
    display: inline-block; padding: .1rem .5rem; border-radius: 999px;
    font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
    border: 1px solid var(--line); color: var(--muted);
}
.pill.ok      { border-color: var(--ok);   color: var(--ok); }
.pill.error   { border-color: var(--bad);  color: var(--bad); }
.pill.warn    { border-color: var(--warn); color: var(--warn); }
.pill.running { border-color: var(--warn); color: var(--warn); }
.pill.soft    { text-transform: none; letter-spacing: 0; }

/* Los cinco estados de la outbox. Se imprimen tal cual como clase —evento.php
   hace <span class="pill {status}">— y hasta ahora solo `running` tenía regla:
   pendiente, entregado y fallido se veían idénticos, que es justo lo que no se
   quiere distinguir de un vistazo. */
.pill.delivered  { border-color: var(--ok);   color: var(--ok); }
.pill.partial    { border-color: var(--warn); color: var(--warn); }
.pill.processing { border-color: var(--warn); color: var(--warn); }
.pill.failed     { border-color: var(--bad);  color: var(--bad); }
.pill.pending    { border-color: var(--line); color: var(--muted); }

/* El Id que la plataforma le dio al evento. Es el único distintivo que sale del
   panel hacia fuera: lleva a la página publicada en compasurbano.com. */
.pill.en-el-sitio { border-color: var(--accent); color: var(--accent); text-decoration: none; }
a.pill:hover      { filter: brightness(1.15); }

/* Eventos ---------------------------------------------------------------- */
.events { list-style: none; padding: 0; margin: 0; display: grid; gap: .75rem; }
.events li {
    display: flex; gap: 1rem;
    background: var(--panel); border: 1px solid var(--line);
    border-radius: var(--radius); padding: .8rem; align-items: flex-start;
}
.events img, .events .noimg {
    width: 110px; height: 80px; object-fit: cover; border-radius: 6px; flex: 0 0 auto;
    background: var(--line);
}
.events .body { min-width: 0; }
.events h3 a { text-decoration: none; }
.events .meta { margin: .1rem 0 .35rem; display: flex; gap: .35rem; flex-wrap: wrap; }
.events .when { margin: 0 0 .2rem; font-variant-numeric: tabular-nums; }
.events p { margin: 0 0 .2rem; font-size: .875rem; }
.events .price { font-weight: 600; }

@media (max-width: 560px) {
    .events li { flex-direction: column; }
    .events img, .events .noimg { width: 100%; height: 140px; }
    .access-grid { grid-template-columns:1fr; }
    .user-email { display:none; }
}

.pager { display: flex; gap: 1rem; align-items: center; justify-content: center; margin-top: 1.5rem; }

/* Estado de los datos ----------------------------------------------------- */

.small { font-size: .82rem; }
.nowrap { white-space: nowrap; }
.hidden { display: none; }

.tiles { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
.tile {
    background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--line);
    border-radius: var(--radius); padding: .8rem .9rem;
    display: flex; flex-direction: column; gap: .15rem;
    text-decoration: none; color: inherit;
}
a.tile:hover { border-color: var(--accent); }
.tile.ok   { border-left-color: var(--ok); }
.tile.warn { border-left-color: var(--warn); }
.tile.muted-tile { opacity: .7; }
.tile-n { font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.tile-l { font-size: .8rem; color: var(--muted); }

/* La barra clara es el total encontrado; la oscura, lo que quedó sin detalle. */
.chart .bar-total    { fill: var(--line); }
.chart .bar-degraded { fill: var(--warn); }

.coverage { width: 100%; }
.coverage .barcell { width: 45%; }
.coverage .bar {
    display: inline-block; height: .55rem; border-radius: 999px;
    vertical-align: middle; margin-right: .5rem; min-width: 2px;
}
.coverage .bar.ok   { background: var(--ok); }
.coverage .bar.warn { background: var(--warn); }
.coverage .bar.bad  { background: var(--bad); }

.viewswitch { display: flex; gap: 1rem; margin: 0 0 1rem; font-size: .88rem; }
.viewswitch a { text-decoration: none; color: var(--muted); }
.viewswitch a.on { color: var(--ink); font-weight: 600; border-bottom: 2px solid var(--accent); }

/* Tabla de datos: una columna por campo vigilado, marca de presente/ausente. */
.tablewrap { overflow-x: auto; }
.datagrid { min-width: 900px; font-size: .85rem; }
.datagrid .titlecell { min-width: 16rem; }
.datagrid th.rot { font-size: .7rem; color: var(--muted); font-weight: 500; text-align: center; }
.datagrid td.mark { text-align: center; font-size: 1rem; }
.datagrid td.mark.yes { color: var(--ok); }
.datagrid td.mark.no  { color: var(--bad); opacity: .55; }

/* Ficha del evento -------------------------------------------------------- */
.fields { display: grid; grid-template-columns: max-content 1fr; gap: .3rem 1rem; margin: 0 0 1rem; }
.fields dt { color: var(--muted); }
.fields dd { margin: 0; }

.fieldtable { width: 100%; }
.fieldtable td { vertical-align: top; }
.fieldtable tr.row-missing td { background: color-mix(in srgb, var(--warn) 8%, transparent); }

.edit-form { display: grid; gap: .4rem; margin: .5rem 0; min-width: 18rem; }
.edit-form textarea {
    width: 100%; padding: .5rem; font: inherit;
    border: 1px solid var(--line); border-radius: 6px;
    background: var(--panel); color: var(--ink);
}
.inline-actions { display: flex; gap: .6rem; margin: 0 0 1rem; }

/* Cobertura: a qué columna de la hoja va cada campo y qué bloquea ---------- */
.coverage .cols { line-height: 1.7; }
.coverage .cols .col { display: inline-block; margin-right: .6rem; white-space: nowrap; }
.coverage .cols .col code { color: var(--accent); }
.coverage .effect { min-width: 13rem; }
.coverage .effect .muted { display: block; }
/* Bloquea Y le faltan datos: es la fila donde hay algo que hacer hoy. */
.coverage tr.row-blocking { background: color-mix(in srgb, var(--warn) 9%, transparent); }

/* Documentación: cómo está construido cada sitio -------------------------- */

/* Estas tarjetas son prosa, no cifras. La rejilla de `.cards` está pensada para
 * columnas de 280 px y aquí dejaría renglones de cuatro palabras, así que la
 * documentación va a una sola columna con la medida limitada: ~70 caracteres es
 * lo que se lee sin perder la línea al saltar de renglón. */
.docs { display: grid; gap: 1rem; }
.card.doc { max-width: 62rem; }
.card.doc h3 {
    margin: 1.1rem 0 .3rem; font-size: .8rem; text-transform: uppercase;
    letter-spacing: .05em; color: var(--muted);
}
.doc-prosa { margin: 0; max-width: 68ch; line-height: 1.6; }

.doc-endpoints { display: grid; gap: .15rem .9rem; margin: 0; font-size: .875rem; }
.doc-endpoints dt { color: var(--muted); }
/* Una URL larga no tiene espacios donde partirse: sin esto empuja la tarjeta y
 * saca scroll horizontal a la página entera. */
.doc-endpoints dd { margin: 0 0 .4rem; overflow-wrap: anywhere; }
.doc-endpoints dd code { color: var(--accent); }

.doc-lista { margin: 0; padding-left: 1.1rem; max-width: 68ch; }
.doc-lista li { margin-bottom: .35rem; line-height: 1.55; }

/* Las trampas son el contenido que de verdad importa cuando algo se rompe: van
 * marcadas para encontrarlas sin leer la tarjeta entera. */
.doc-trampas li::marker { color: var(--warn); }
.doc-descartado li::marker { color: var(--muted); }

.doc-pie { margin: 1.1rem 0 0; padding-top: .6rem; border-top: 1px solid var(--line); }

/* `.datagrid` fuerza 900 px para las tablas de cifras, que se leen mejor con
 * scroll que apretadas. Esta es de prosa y hace lo contrario. */
.escalones { min-width: 0; white-space: normal; }

/* El embudo del inicio: cifras a la derecha y alineadas entre sí, que es lo que
 * permite comparar dos fuentes de un vistazo. El pie repite el borde superior
 * porque es una suma, no una fila más. */
.embudo td { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.embudo th:not([scope="row"]) { text-align: right; }
.embudo th[scope="row"] { text-align: left; }
.embudo tfoot th, .embudo tfoot td { border-top: 2px solid var(--line); font-weight: 600; }
.embudo td.muted a { color: var(--muted); }
.embudo .pill { margin-left: .3rem; }
.embudo th.pick, .embudo td.pick { width: 1.6rem; text-align: center; padding-right: 0; }
/* El desglose de quien lo subio va debajo de su cifra y no compite con ella. */
.embudo .origen { display: inline-block; margin-top: .15rem; font-size: .72rem; }

/* El botón de sincronizar, debajo de la tabla del embudo. Va fuera de una
 * tarjeta, asi que `.card .actions` no lo alcanza. */
.sync-actions { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin: .8rem 0 1.2rem; }

/* En móvil `.escalones` apila las filas y la alineación a la derecha deja los
 * números colgando lejos de su etiqueta. */
@media (max-width: 640px) {
    .embudo td, .embudo th:not([scope="row"]) { text-align: left; }
}
.escalones th[scope="row"] { white-space: nowrap; font-weight: 600; vertical-align: top; }
.escalones td { vertical-align: top; }

.lede { max-width: 68ch; color: var(--muted); margin: 0 0 1.5rem; line-height: 1.6; }

/* Los `h3` están pensados para vivir dentro de una tarjeta, con margen superior
 * cero. Sueltos en una sección se pegan al bloque anterior y la página deja de
 * tener respiración. */
.doc-tiempos h3 { margin-top: 1.6rem; }
.doc-tiempos ol { max-width: 76ch; line-height: 1.6; }

/* El SQL se enseña tal cual sale del código, así que puede ser largo: que haga
 * scroll él y no la página. */
.doc-sql {
    background: var(--surface-2, #f4f2f0); border: 1px solid var(--line);
    border-radius: 6px; padding: .7rem .9rem; overflow-x: auto;
    font-size: .82rem; line-height: 1.5; max-width: 100%;
}
.doc-sql code { background: none; padding: 0; white-space: pre; }

/* En el móvil la tabla de escalones cabría solo con scroll lateral, y es texto
 * explicativo: se lee de arriba abajo o no se lee. Se apila en bloques, que es
 * la misma información sin la rejilla. */
@media (max-width: 640px) {
    .escalones thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
    .escalones tr { display: block; padding: .6rem 0; border-bottom: 1px solid var(--line); }
    .escalones th[scope="row"] { display: block; white-space: normal; padding: 0 0 .2rem; }
    .escalones td { display: block; padding: 0 0 .2rem; }
    /* Solo la tabla de estrategia: acotada con su propia clase el 2026-09-09,
     * cuando aparecieron más tablas `.escalones` y esta regla les ponía
     * "Lo usa:" delante de su última celda en móvil. */
    .escalones.estrategia td:last-child::before { content: "Lo usa: "; color: var(--muted); }
    /* El checkbox de sincronizar queda sin encabezado visible en móvil (el
     * thead entero se oculta arriba): sin esta etiqueta se ve un checkbox
     * suelto antes del nombre de la fuente, sin decir para qué es. */
    .embudo td.pick { text-align: left; }
    .embudo td.pick::before { content: "Sincronizar "; color: var(--muted); }
}
