/* ============================================================
   INDIPCD-R2 — "Panel con barra lateral" design (Option C)
   Sidebar-based dashboard theme. The sidebar fragment
   (fragments/common.html :: nav) renders an <aside class="sidebar">;
   every authenticated page's <main> immediately follows it in the
   DOM, so `.sidebar + main` is what turns that page's content into
   the right-hand panel. Pages with no sidebar (login.html) keep the
   plain, centered `main` layout below.
   ============================================================ */

:root {
    --sidebar: #1a1f2e;
    --sidebar-hover: #252b3d;
    --sidebar-text: #a9aec4;
    --sidebar-text-active: #ffffff;

    /* Calm Clinical Blue — tuned darker than the original #4f7cff so white button
       text clears 4.5:1 AA (see DESIGN.md §2). */
    --primary: #466de0;
    --primary-dark: #3d63d9;

    --bg: #f4f6fa;
    --surface: #ffffff;
    --text: #1b2233;
    --text-muted: #6b7280;
    --border: #e6e9f0;

    /* Semantic fg values are the DESIGN.md accessibility-pass colors — each
       re-darkened from its original to clear 4.5:1 AA against its -bg pairing.
       --danger-fg-dark is the separate, deliberately-darker hover/active shade
       for danger buttons/links; it is not the default danger fg (see DESIGN.md
       §2 Semantic). */
    --ok-bg: #e6f7ee;   --ok-fg: #0d7c43;
    --warn-bg: #fff4e0; --warn-fg: #9a5d0a;
    --danger-bg: #fdeaea; --danger-fg: #c43131; --danger-fg-dark: #b32b2b;

    /* Clinical risk language, deliberately distinct from --danger-*: a "Riesgo
       importante" result is not the same thing as "this permanently deletes
       data," and reusing the destructive-action red made a screening result
       read as alarming/punitive rather than calm-and-precise. A rust/burnt-
       orange sits between --warn (moderate risk) and --danger (destructive
       actions/errors) on the hue wheel so all three stay visually distinct.
       #9a3412 on #fdeee0 clears 4.5:1 AA. */
    --riesgo-alto-bg: #fdeee0; --riesgo-alto-fg: #9a3412;

    /* Alert border tints, one shade per semantic pair (previously inline one-off
       hex on each .alerta.* rule below). */
    --danger-border: #f3c6c6;
    --ok-border: #bfe8d2;
    --warn-border: #f0dca0;

    /* A fourth semantic pair for neutral informational messages (login.html's
       session/notice banner) — previously an undocumented inline hex with no
       token backing it. --info-fg is a muted slate-indigo, NOT --primary: every
       other semantic pair (ok/warn/danger) uses a dedicated matching-hue fg
       rather than borrowing the interactive accent, and info previously broke
       that pattern by reusing --primary-dark for passive status text — a One
       Accent Rule violation flagged in the 2026 critique (P1). 5.5:1 on
       --info-bg. */
    --info-bg: #eef2ff;
    --info-border: #d3ddfc;
    --info-fg: #51618c;

    /* Sidebar "Salir" (log out) is the only danger-toned text on the dark
       sidebar background, so it needs its own lighter shade — --danger-fg is
       tuned for light surfaces and would be too dark to read here. */
    --sidebar-danger: #ff9b9b;
    --sidebar-danger-hover: #ffb3b3;

    /* Remaining one-off hex swept in during the polish pass: a hover tint for
       table rows, the secondary button's resting/hover shades, the disabled-
       control background, and the input surface — none had a token before. */
    --row-hover: #f8f9fc;
    --text-muted-dark: #565d6b;
    --disabled-bg: #b7bec9;
    --input-bg: #fcfdfe;

    /* The cookie-consent banner sits on the same dark --sidebar background but
       was styled independently of it — its link color gets its own token
       rather than reusing --sidebar-text, which is a cooler gray built for
       plain nav links, not an underlined clickable link on a dark surface. */
    --cookie-link: #cfe0ff;

    --sidebar-width: 220px;
}

* { box-sizing: border-box; }

body {
    font-family: -apple-system, "Segoe UI", Arial, sans-serif;
    background: var(--bg);
    color: var(--text);
    margin: 0;
}

/* Skip-to-content link (fragments/common.html :: nav, first element in the
   fragment) — off-screen until keyboard-focused, so a screen-reader/keyboard
   user isn't forced to tab through the full sidebar nav on every page load
   before reaching <main id="main-content">. Visually hidden rather than
   display:none so it still receives focus. */
.skip-link {
    position: absolute;
    top: -3rem;
    left: 0.5rem;
    z-index: 100;
    background: var(--primary);
    color: #ffffff;
    padding: 0.6rem 1rem;
    border-radius: 0 0 8px 8px;
    font-size: 0.88rem;
    font-weight: 600;
    text-decoration: none;
    transition: top 0.1s ease-out;
}

.skip-link:focus {
    top: 0;
}

/* Heading scale (DESIGN.md §3 — previously undefined, falling back to the
   browser default scale). h1 = Headline, h2 = Title, h3 = Subtitle. */
h1, h2, h3 {
    color: var(--text);
    line-height: 1.3;
    text-wrap: balance;
    margin: 1.5rem 0 0.75rem;
}

h1:first-child, h2:first-child, h3:first-child { margin-top: 0; }

h1 { font-size: 1.5rem; font-weight: 700; }
h2 { font-size: 1.2rem; font-weight: 700; }
h3 { font-size: 1.05rem; font-weight: 600; }

/* ---------- Sidebar (fragments/common.html :: nav) ---------- */

.sidebar {
    background: var(--sidebar);
    color: var(--sidebar-text);
    padding: 1.4rem 1rem;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: var(--sidebar-width);
    overflow-y: auto;
}

.sidebar .titulo {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    color: white;
    font-weight: 700;
    font-size: 1.05rem;
    margin-bottom: 1.6rem;
    padding: 0 0.5rem;
}

.sidebar .titulo .acento { color: var(--primary); }

/* Brand mark (fragments/common.html's sidebar, login.html/legal/aviso_privacidad.html's
   header.app-header) — see the fragment comment for what it is and why. Fixed accent
   blue regardless of the white heading text it sits in, same reasoning as .acento
   above: the mark is brand, not body copy, so it doesn't inherit currentColor. */
.marca-icono {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    stroke: var(--primary);
    color: var(--primary);
    fill: none;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Logged-in-user identity, between the brand title and the nav links — quiet, on the
   existing muted --sidebar-text color rather than a new accent, per the One Accent Rule.
   One line (name · role), not two: keeps the sidebar's fixed vertical space in check now
   that a 5th admin nav link (Configuración) exists, and reads as a compact status line
   rather than a second heading competing with .titulo above it. The border-bottom is the
   same hairline-divider device .idiomas already uses (border-top there, on itself, ahead
   of its own content) — applied here as border-bottom instead, since the next sibling is
   <nav> and its many <a> children aren't a sensible place to hang a top border. */
.sidebar-usuario {
    display: flex;
    align-items: baseline;
    gap: 0.3rem;
    padding: 0 0.5rem 0.7rem;
    margin-bottom: 0.6rem;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    overflow: hidden;
}

.sidebar-usuario-nombre {
    color: var(--sidebar-text-active);
    font-size: 0.82rem;
    font-weight: 500;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar-usuario-separador {
    color: var(--sidebar-text);
    font-size: 0.75rem;
    flex-shrink: 0;
}

.sidebar-usuario-rol {
    color: var(--sidebar-text);
    font-size: 0.75rem;
    flex-shrink: 0;
    white-space: nowrap;
}

.sidebar nav {
    display: flex;
    flex-direction: column;
}

.sidebar nav a {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    color: var(--sidebar-text);
    text-decoration: none;
    font-size: 0.88rem;
    padding: 0.6rem 0.7rem;
    border-radius: 8px;
    margin-bottom: 0.15rem;
}

.sidebar nav a:hover { background: var(--sidebar-hover); color: var(--sidebar-text-active); }

/* One-stroke icon set on the main nav links only (not .idiomas/.salir) — see the
   fragment comment in fragments/common.html for why this is the system's one
   deliberate warmth/personality device rather than a second accent color. */
.nav-icono {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    stroke: currentColor;
    stroke-width: 1.6;
    fill: none;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.sidebar nav .idiomas {
    margin-top: 0.6rem;
    padding-top: 0.6rem;
    border-top: 1px solid rgba(255,255,255,0.08);
    display: flex;
    gap: 0.4rem;
    padding-left: 0.7rem;
}

.sidebar nav .idiomas a {
    display: inline-block;
    padding: 0.3rem 0.6rem;
    margin: 0;
    font-size: 0.78rem;
}

.sidebar nav .salir-form { margin-top: 0.6rem; }

.sidebar nav .salir {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    font: inherit;
    margin: 0;
    padding: 0.6rem 0.7rem;
    border-radius: 8px;
    color: var(--sidebar-danger);
    cursor: pointer;
}

.sidebar nav .salir:hover { background: rgba(255,80,80,0.12); color: var(--sidebar-danger-hover); }

/* Sidebar footer: contact info + copyright. Same hairline-divider device as
   .idiomas (border-top on itself, not margin-collapse against nav), kept well below
   nav's own hover/focus styling since these links aren't nav items. */
.sidebar-contacto {
    margin-top: 1.2rem;
    padding-top: 0.8rem;
    padding-left: 0.7rem;
    border-top: 1px solid rgba(255,255,255,0.08);
    font-size: 0.72rem;
    line-height: 1.5;
}

.sidebar-contacto-titulo {
    margin: 0 0 0.4rem 0;
    font-weight: 600;
    color: var(--sidebar-text-active);
}

.sidebar-contacto a {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--sidebar-text);
    margin-bottom: 0.3rem;
}

.sidebar-contacto a:hover { color: var(--sidebar-text-active); }

.sidebar-contacto a .nav-icono { width: 14px; height: 14px; flex-shrink: 0; }

.sidebar-contacto-copyright {
    margin: 0.5rem 0 0 0;
    color: var(--sidebar-text);
    opacity: 0.75;
}

/* Content area to the right of the sidebar */
.sidebar + main {
    margin-left: var(--sidebar-width);
    padding: 1.75rem clamp(1rem, 3vw, 2.5rem) 3rem;
    min-height: 100vh;
    max-width: none;
}

/* ---------- Plain top bar + centered main (login.html only) ---------- */

header.app-header {
    background: var(--sidebar);
    color: white;
    padding: 0.9rem 1.5rem;
}

header.app-header .titulo {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-weight: 700;
    font-size: 1.05rem;
}

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

/* ---------- Cards ---------- */

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 1.6rem;
    margin-bottom: 1.5rem;
    box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04);
}

/* ---------- Summary stat cards (optional, used on dashboards) ---------- */

.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 0.9rem;
    margin-bottom: 1.3rem;
}

.stat {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 0.9rem 1rem;
}

.stat .n { font-size: 1.4rem; font-weight: 700; color: var(--primary); }
.stat .l { font-size: 0.78rem; color: var(--text-muted); }

/* ---------- Tables ---------- */

table {
    border-collapse: collapse;
    width: 100%;
    margin: 1rem 0;
    font-size: 0.88rem;
}

table caption { caption-side: top; text-align: left; font-weight: 600; margin-bottom: 0.5rem; }

th {
    text-align: left;
    color: var(--text-muted);
    font-weight: 600;
    font-size: 0.76rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding: 0.6rem 0.7rem;
    border-bottom: 2px solid var(--border);
}

td {
    padding: 0.7rem 0.7rem;
    border-bottom: 1px solid var(--border);
}

/* Responsive table: scroll horizontally instead of forcing columns to crush
   their content (which is what `overflow-wrap` on td did — it broke short
   words like "Pagado" letter-by-letter instead of just wrapping the one
   genuinely long unbreakable string, an email address). Natural column
   widths are preserved; the table scrolls within its own card instead of
   pushing the page wider or mangling text. */
.tabla-scroll {
    overflow-x: auto;
}

/* Caps a table's height and scrolls vertically within its own card instead of letting
   the row count push the whole page taller without bound — reporte/lista.html, whose
   row count grows with every finalized evaluation system-wide. Sticky header row keeps
   column headings visible while scrolling, same device as .tabla-test's sticky header
   on the 68-item test screen. */
.tabla-scroll-vertical {
    max-height: 65vh;
    overflow-y: auto;
}

.tabla-scroll-vertical thead th {
    position: sticky;
    top: 0;
    background: var(--surface);
    z-index: 1;
}

tbody tr:hover { background: var(--row-hover); }

/* ---------- Buttons ---------- */

.btn {
    display: inline-block;
    background: var(--primary);
    color: white;
    border: none;
    padding: 0.6rem 1.2rem;
    border-radius: 8px;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
}

.btn:hover { background: var(--primary-dark); }
.btn.secundario { background: var(--text-muted); }
.btn.secundario:hover { background: var(--text-muted-dark); }
.btn.peligro { background: var(--danger-fg); }
.btn.peligro:hover { background: var(--danger-fg-dark); }
.btn:disabled, .btn.deshabilitado {
    background: var(--disabled-bg);
    cursor: not-allowed;
    pointer-events: none;
}

/* "Large centered CTA" — previously the same inline style repeated verbatim
   on three separate buttons (home.html x2, instrucciones.html). */
.btn-lg { font-size: 1.1rem; padding: 0.9rem 2rem; }

/* "Flex header row" — a card's title + action button on one line, previously
   the same inline style repeated verbatim across three admin/report screens. */
.card-header-row { display: flex; justify-content: space-between; align-items: center; }

/* Narrow centered card (login.html) — the login page was the one screen still
   using an inline style instead of a class for this. */
.card-angosta { max-width: 420px; margin: 3rem auto; }

/* Centered card text (home.html, resultado.html) — previously the same
   inline style repeated verbatim in both places. */
.texto-centrado { text-align: center; }

/* Narrow table column (evaluacion/test.html's F/AV/N headers) — previously
   the same inline style repeated verbatim on all three. */
.col-estrecha { width: 1rem; }

/* ---------- Badges ---------- */

.badge {
    display: inline-block;
    padding: 0.2rem 0.65rem;
    border-radius: 999px;
    font-size: 0.76rem;
    font-weight: 600;
}

.badge.ok { background: var(--ok-bg); color: var(--ok-fg); }
.badge.warn { background: var(--warn-bg); color: var(--warn-fg); }
.badge.danger { background: var(--danger-bg); color: var(--danger-fg); }
.badge.riesgo-importante { background: var(--riesgo-alto-bg); color: var(--riesgo-alto-fg); }

/* ---------- Forms ---------- */

.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1rem;
}

/* reporte/lista.html's filter form: a .form-grid whose buttons (Filtrar/Limpiar/
   Descargar Excel completo) span every column instead of occupying one of them, with
   space below it before the results table. */
.form-filtros-reporte {
    margin-bottom: 1.4rem;
}

.form-filtros-reporte-acciones {
    grid-column: 1 / -1;
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
}

/* Generic full-width grid cell — a field (e.g. a <textarea>) that shouldn't share a
   row with its form-grid siblings. */
.campo-ancho { grid-column: 1 / -1; }

.form-grid label, .form-row label, .form-agregar-destinatario label, .etiqueta-campo {
    display: block;
    font-weight: 600;
    font-size: 0.82rem;
    margin-bottom: 0.35rem;
    color: var(--text);
}

/* Sized for comfortable reading and a real touch target (~44px tall at the default
   16px root), not just "fits the label": font-size matches body text (1rem) rather
   than running smaller than it — form content is exactly the data this clinical tool
   exists to collect accurately, and PRODUCT.md names sustained legibility on
   shared/older hardware as a requirement, not a nicety. Previously 0.9rem/0.55rem —
   smaller and tighter than the content around it. */
input[type=text], input[type=email], input[type=tel], input[type=password],
input[type=number], input[type=date], select, textarea {
    width: 100%;
    padding: 0.65rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 1rem;
    line-height: 1.4;
    background: var(--input-bg);
    color: var(--text);
}

input:focus, select:focus, textarea:focus {
    outline: 2px solid var(--primary);
    outline-offset: 1px;
    border-color: var(--primary);
}

/* General keyboard-focus ring for every plain link/button (nav links, Editar/
   Eliminar, primary/secondary/danger buttons) — previously only form fields and
   the custom Sí/No/calendar controls had an explicit focus style, so a
   keyboard user tabbing through the sidebar or a table's action links got
   nothing but the browser's unstyled default. Uses the same accent/offset as
   the field focus ring above for one consistent focus signal site-wide. */
a:focus-visible, button:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* On the dark sidebar, the light accent outline reads fine on its own, but the
   hover background makes focus harder to spot — pair it with the same
   background hover already uses so keyboard and mouse users see the same
   affordance. */
.sidebar nav a:focus-visible, .sidebar nav .salir:focus-visible {
    background: var(--sidebar-hover);
    outline-offset: -2px;
}

/* Per-field validation error marking — the "revise los campos marcados" banner
   on nino/nuevo.html and admin/usuario_form.html used to say this while no
   field was ever actually marked. */
.campo-error { border-color: var(--danger-fg); }
.campo-error:focus { outline-color: var(--danger-fg); }

.mensaje-error {
    display: block;
    font-size: 0.78rem;
    color: var(--danger-fg);
    margin-top: 0.3rem;
}

fieldset {
    border: 1px solid var(--border);
    border-radius: 10px;
    margin: 0.5rem 0 1.2rem;
    padding: 0.9rem 1rem;
}

legend { font-weight: 600; color: var(--text); padding: 0 0.4rem; font-size: 0.9rem; }

/* ---------- Alerts ---------- */

.alerta {
    padding: 0.8rem 1rem;
    border-radius: 8px;
    margin-bottom: 1rem;
    font-size: 0.9rem;
}

.alerta.error { background: var(--danger-bg); color: var(--danger-fg); border: 1px solid var(--danger-border); }
.alerta.exito { background: var(--ok-bg); color: var(--ok-fg); border: 1px solid var(--ok-border); }
.alerta.info { background: var(--info-bg); color: var(--info-fg); border: 1px solid var(--info-border); }
.alerta.warn { background: var(--warn-bg); color: var(--warn-fg); border: 1px solid var(--warn-border); }

/* ---------- Secondary/helper text (DESIGN.md: no one-off inline colors) ---------- */

.nota { font-size: 0.85rem; color: var(--text-muted); }
.nota.pequena { font-size: 0.75rem; }

/* publico/informacion.html's "¿Quién puede aplicar el INDIPCD-R2?" audience list — a
   plain definition list rather than a table, since there are no real columns, just a
   term and its description. */
.lista-definicion dt { font-weight: 600; color: var(--text); margin-top: 1rem; }
.lista-definicion dt:first-child { margin-top: 0; }
.lista-definicion dd { margin: 0.3rem 0 0; }

/* publico/contacto.html's spam honeypot — visually hidden (not display:none, which
   some bots already know to skip) rather than type="hidden" for the same reason.
   Off-screen via position, not opacity/visibility, so it never flashes into view. */
.campo-trampa {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* reporte/detalle.html's administrador-only "Correos adicionales" field on the
   "Enviar por correo" form — spacing to separate it from the copiaExaminador
   checkbox above and the submit button below, since it isn't inside a .form-grid. */
.campo-correos-adicionales {
    margin: 0.7rem 0 1rem 0;
    max-width: 420px;
}

/* ---------- Destructive inline links/buttons (DESIGN.md §6 Do's) ---------- */

.enlace-peligro { color: var(--danger-fg); }
.enlace-peligro:hover { color: var(--danger-fg-dark); }

/* Same treatment as .enlace-peligro, but resets a real <button> down to plain-link
   chrome first — for a destructive action that has to be its own <form> (a per-row
   "Quitar" delete, e.g. nino/detalle.html's destinatarios list) rather than a plain
   <a>, since only a real submit button can trigger a POST without JavaScript. */
.enlace-peligro-boton {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    cursor: pointer;
    color: var(--danger-fg);
}
.enlace-peligro-boton:hover { color: var(--danger-fg-dark); }

/* ---------- Niño email recipients (nino/detalle.html) ---------- */

.form-agregar-destinatario {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: 1rem;
}
.form-agregar-destinatario input[type=email] { width: auto; min-width: 240px; }

/* ---------- Instrument-specific bits (evaluacion/test.html, admin/catalogo.html) ---------- */

.reactivo-row td { vertical-align: top; }
.reactivo-row .opciones { white-space: nowrap; }
.reactivo-row .opciones label { display: inline-block; font-weight: normal; margin-right: 0.8rem; }

.instrucciones-lista { line-height: 1.6; }
.form-iniciar-prueba { margin-top: 1.5rem; }

/* Administrador-only clinical note chat log (evaluacion/test.html). */
.observaciones-lista { list-style: none; margin: 0 0 1rem; padding: 0; }
.observaciones-lista li {
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--border);
}
.observaciones-lista li:first-child { padding-top: 0; }
.observacion-meta {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.75rem;
}
.observacion-texto { margin: 0.3rem 0 0.5rem; white-space: pre-wrap; }

/* The indicator-number cell is a <th scope="row"> for correct table semantics
   (screen-reader row context), not a column header — strip the generic `th`
   rule's header styling so it reads identically to a plain `td` in the row. */
.reactivo-row th {
    vertical-align: top;
    text-align: left;
    color: var(--text);
    font-weight: normal;
    font-size: inherit;
    text-transform: none;
    letter-spacing: normal;
    padding: 0.7rem 0.7rem;
    border-bottom: 1px solid var(--border);
}

/* Answered-row cue (2026 critique, P1): previously only the aggregate "N de 68
   respondidos" counter showed progress — individual rows looked identical
   whether answered or not, which is exactly the wrong gap on the highest-
   frequency, highest-time-pressure screen in the product. Reuses --row-hover
   (the same subtle tint already used for table-row hover elsewhere) rather
   than a new color, so "this row has input" reads as the system's existing
   "attention" language, not a second accent. :has() is a progressive
   enhancement: on a browser old enough not to support it, the row simply
   stays plain — no functional loss, just no tint. */
.reactivo-row:has(input:checked) { background: var(--row-hover); }

/* Sticky progress/save-state row + column headers on the 68-item test screen
   (evaluacion/test.html) — the examiner shouldn't lose track of which column
   is F/AV/N, how much is answered, or whether "Guardar progreso" worked, mid-scroll. */
.tabla-test thead { position: sticky; top: 0; z-index: 5; }
.tabla-test thead th, .tabla-test thead td { background: var(--surface); }

.progreso-row td { padding: 0; border-bottom: 1px solid var(--border); }

.test-progreso {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
    padding: 0.6rem 0.7rem;
}

.test-progreso .alerta { margin: 0; padding: 0.4rem 0.8rem; font-size: 0.82rem; }

.progreso-contador {
    margin-left: auto;
    font-size: 0.82rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.progreso-contador strong { color: var(--text); font-size: 0.95rem; }

/* Visually-hidden but screen-reader-accessible label (evaluacion/test.html radios).
   Overrides `.reactivo-row .opciones label` above via matching specificity —
   without the second selector, that rule's `display: inline-block` would win
   and make these labels visible. */
.sr-only,
.reactivo-row .opciones label.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Pre-finalize review list (evaluacion/test.html) — a scannable, editable
   summary of every answer before it's submitted. */
.revision-lista {
    list-style: none;
    margin: 0 0 1rem;
    padding: 0;
    max-height: 60vh;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: 8px;
}

.revision-lista li { border-bottom: 1px solid var(--border); }
.revision-lista li:last-child { border-bottom: none; }

.revision-lista a {
    display: block;
    padding: 0.6rem 0.8rem;
    color: var(--text);
    text-decoration: none;
}

.revision-lista a:hover { background: var(--row-hover); }

.revision-respuesta { font-weight: 600; color: var(--primary-dark); }

.grupo-edad-sep td {
    background: var(--info-bg);
    font-weight: 600;
    color: var(--primary-dark);
}

/* Checkbox inputs shouldn't stretch to the shared 100%-width input rule above. */
.chk { width: auto; }

.intro-instrumento p { line-height: 1.5; text-align: justify; }

/* Institutional history/citations, collapsed by default (home.html) — a
   returning examiner shouldn't scroll past unchangeable copy on every visit
   to reach the catalog and the CTA below it. */
.intro-instrumento details { margin-top: 0.5rem; }

.intro-instrumento summary {
    cursor: pointer;
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--primary);
    padding: 0.3rem 0;
}

.intro-instrumento summary:hover { color: var(--primary-dark); }

.intro-instrumento details[open] summary { margin-bottom: 0.4rem; }

footer {
    text-align: center;
    color: var(--text-muted);
    font-size: 0.8rem;
    padding: 1.5rem;
}

.footer-contacto { margin: 0.8rem 0 0.2rem 0; }

.footer-copyright { margin: 0; font-size: 0.75rem; opacity: 0.85; }

/* ---------- Cookie-consent banner (fragments/common.html, login.html) ---------- */

.cookie-banner {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1000;
    background: var(--sidebar);
    color: white;
    padding: 0.9rem 1.25rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.15);
}

.cookie-banner[hidden] { display: none; }

.cookie-banner p { margin: 0; font-size: 0.85rem; max-width: 720px; }

.cookie-banner-acciones {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-shrink: 0;
}

.cookie-banner-acciones a { color: var(--cookie-link); font-size: 0.82rem; text-decoration: underline; }

.cookie-banner .btn { padding: 0.45rem 1rem; font-size: 0.85rem; }

/* ---------- Small screens: collapse sidebar to a top bar ---------- */

@media (max-width: 820px) {
    .sidebar {
        position: static;
        width: 100%;
        bottom: auto;
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;
        padding: 0.8rem 1rem;
    }
    .sidebar .titulo { margin-bottom: 0; }
    /* The border-bottom divider only makes sense against the stacked desktop layout — in
       this wrapped horizontal top bar it would just be a stray line under one flex item.
       max-width caps it so a long name actually truncates here too instead of the flex
       item sizing to its full content and crowding .titulo/nav on the same wrapped row. */
    .sidebar-usuario { margin-bottom: 0; padding: 0; border-bottom: none; max-width: 45vw; }
    .sidebar nav { flex-direction: row; flex-wrap: wrap; }
    .sidebar nav .idiomas { border-top: none; margin-top: 0; padding-top: 0; padding-left: 0; }
    .sidebar + main {
        margin-left: 0;
        padding: 1.25rem 1rem 3rem;
    }
}

/* ---------- Sí/No (nino/nuevo.html) ---------- */

/* Rótulo de un grupo de opciones. No puede ser un <label> porque no apunta a
   un único control (un radiogroup se etiqueta con aria-labelledby), pero debe
   leerse exactamente igual que los <label> de los campos vecinos — de ahí que
   comparta la regla de `.form-grid label` más arriba en este archivo. */

/* Interruptor Sí/No que sustituye a las antiguas casillas de verificación: una
   casilla marcada es indistinguible de una sin contestar, y en una historia
   clínica "no" y "sin dato" no son lo mismo. Con dos radios siempre hay una
   respuesta visible. Nota: el modelo (`boolean` primitivo) no distingue null,
   así que "No" aparece preseleccionado, igual que la casilla vacía de antes.
   Colores: la opción elegida usa Ink Navy sobre blanco, no Calm Clinical Blue —
   el azul acento queda reservado para la acción primaria y el foco (Regla del
   Acento Único, DESIGN.md §2), y con nueve grupos en la misma pantalla nueve
   pastillas azules lo habrían gastado por completo. */
.grupo-si-no {
    display: flex;
    gap: 0.25rem;
    max-width: 200px;
    padding: 0.2rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
}

.grupo-si-no .opcion-si-no {
    position: relative;
    flex: 1;
    margin: 0;
}

/* Oculto visualmente pero sigue siendo el control real: recibe el foco, se
   maneja con las flechas y es lo que lee un lector de pantalla. El anillo de
   foco se dibuja sobre el <span> de al lado. */
.grupo-si-no input[type=radio] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

.grupo-si-no .opcion-si-no span {
    display: block;
    padding: 0.4rem 0.2rem;
    border: 1px solid transparent;
    border-radius: 6px;
    font-size: 0.85rem;
    font-weight: 600;
    text-align: center;
    color: var(--text-muted);
    cursor: pointer;
    user-select: none;
}

.grupo-si-no .opcion-si-no span:hover { color: var(--text); }

.grupo-si-no input[type=radio]:checked + span {
    background: var(--text);
    border-color: var(--text);
    color: #ffffff;
}

.grupo-si-no input[type=radio]:focus-visible + span {
    outline: 2px solid var(--primary);
    outline-offset: 1px;
}

/* ---------- Calendario con selector de mes y año (js/calendario.js) ---------- */

/* Sólo existe una vez que el script ha reemplazado el <input type="date">; sin
   JavaScript el campo sigue siendo el nativo y nada de esto se aplica. */
.campo-calendario {
    position: relative;
    display: block;
}

.campo-calendario .entrada-calendario { padding-right: 2.4rem; }

.calendario-boton {
    position: absolute;
    top: 50%;
    right: 0.45rem;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    background: none;
    border: none;
    border-radius: 6px;
    color: var(--text-muted);
    cursor: pointer;
}

.calendario-boton:hover { color: var(--text); }
.calendario-boton svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6; }

.calendario-popup {
    position: absolute;
    z-index: 20;
    top: calc(100% + 0.35rem);
    left: 0;
    width: 17rem;
    max-width: calc(100vw - 2rem);
    padding: 0.7rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    /* Misma sombra susurro que `.card` (Regla Borde-Sobre-Sombra): aquí el
       borde solo no bastaría, porque el popup se superpone a la tarjeta blanca
       que tiene detrás y se confundiría con ella. */
    box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04);
}

.calendario-popup[hidden] { display: none; }
.calendario-popup.hacia-arriba { top: auto; bottom: calc(100% + 0.35rem); }

.calendario-cabecera {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    margin-bottom: 0.6rem;
}

.calendario-nav {
    flex-shrink: 0;
    width: 1.8rem;
    height: 1.8rem;
    padding: 0;
    background: none;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 1rem;
    line-height: 1;
    color: var(--text);
    cursor: pointer;
}

.calendario-nav:hover:not(:disabled) { background: var(--row-hover); }
.calendario-nav:disabled { color: var(--disabled-bg); cursor: default; }

.calendario-selectores {
    display: flex;
    flex: 1;
    gap: 0.3rem;
    min-width: 0;
}

/* Los dos <select> ya heredan el estilo de campo de la regla general de inputs;
   aquí sólo se ajusta el reparto del ancho y la densidad, más apretada que en
   un formulario porque viven dentro de un popup. */
.calendario-selectores select {
    min-width: 0;
    padding: 0.3rem 0.35rem;
    font-size: 0.85rem;
}

.calendario-mes { flex: 1 1 60%; }
.calendario-anio { flex: 1 1 40%; }

.calendario-semana,
.calendario-dias {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
}

.calendario-semana {
    margin-bottom: 2px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-align: center;
    color: var(--text-muted);
}

.calendario-dia {
    padding: 0.35rem 0;
    background: none;
    border: 1px solid transparent;
    border-radius: 6px;
    font-size: 0.82rem;
    color: var(--text);
    cursor: pointer;
}

.calendario-dia:hover:not(:disabled) { background: var(--row-hover); }
.calendario-dia:focus-visible { outline: 2px solid var(--primary); outline-offset: -1px; }
.calendario-dia:disabled { color: var(--disabled-bg); cursor: default; }
.calendario-dia.es-hoy { border-color: var(--border); font-weight: 600; }

.calendario-dia.elegido {
    background: var(--text);
    border-color: var(--text);
    color: #ffffff;
    font-weight: 600;
}

.calendario-acciones {
    display: flex;
    justify-content: space-between;
    margin-top: 0.6rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--border);
}

.calendario-accion {
    padding: 0.2rem 0.4rem;
    background: none;
    border: none;
    border-radius: 6px;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--primary);
    cursor: pointer;
}

.calendario-accion:hover { color: var(--primary-dark); }
.calendario-accion:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.calendario-popup.hacia-izquierda { left: auto; right: 0; }

/* ---------- Aviso de Privacidad gate (legal/aviso_privacidad.html) ---------- */

/* Wider than .card-angosta (login.html, 420px) — this card holds a full legal
   document's worth of scrollable text, not a two-field form. */
.card-aviso-privacidad { max-width: 720px; margin: 2rem auto; }

/* Same scrollable-box treatment as .revision-lista (evaluacion/test.html's
   pre-finalize review list): a hairline border in place of a page-length scroll,
   so the accept control stays reachable without hunting for it below a few
   thousand words of legal text. */
.aviso-texto {
    max-height: 50vh;
    overflow-y: auto;
    padding: 0 1rem;
    margin: 1rem 0;
    border: 1px solid var(--border);
    border-radius: 8px;
}

.aviso-texto h2:first-child { margin-top: 0.75rem; }

/* ---------- Análisis de Indicadores de Riesgo (reporte/detalle.html) ---------- */

/* A table cell can list several indicators (Cuadro indicadores de riesgo's SNS/
   desfase columns aren't one-to-one with a Nivel/Dimensión row) — a tight list
   reads better here than comma-joining long clinical sentences into one paragraph. */
.lista-indicadores-riesgo {
    margin: 0;
    padding-left: 1rem;
}
.lista-indicadores-riesgo li { margin-bottom: 0.3rem; }
.lista-indicadores-riesgo li:last-child { margin-bottom: 0; }
