:root {
    --navy-950: #07182b;
    --navy-900: #0b2239;
    --navy-800: #14324d;
    --ink: #102a43;
    --ink-soft: #486581;
    /* Terciario sobre superficie CLARA. Era #829ab1, que sobre blanco da 2.91
       de contraste -- por debajo del 4.5 que pide texto chico. Y no es un
       detalle de un rincon: es el color de TODA etiqueta chica del panel (los
       rotulos de los tiles, la ayuda de cada campo, los `small` de la tabla).
       Treinta y dos textos por debajo de AA en la herramienta que el equipo
       mira todo el dia, y nadie lo habia medido nunca.
       #5f7387 da 4.90 sobre blanco y 4.64 sobre la cabecera de tabla.
       El rail oscuro NO usa este token: tiene sus propios grises, porque un
       solo valor no puede servir a un fondo blanco y a uno casi negro. */
    --muted: #5f7387;
    --canvas: #f4f7fb;
    --surface: #ffffff;
    --surface-soft: #f8fafc;
    --line: #dfe7ef;
    --line-strong: #cbd7e3;
    --violet: #5b5cf0;
    --cyan: #0aa6c2;
    --mint: #18a779;
    --lime: #b9e769;
    --amber: #e9a23b;
    --rose: #d94a70;
    --shadow-soft: 0 1px 2px rgba(7, 24, 43, .05), 0 10px 30px rgba(7, 24, 43, .05);
    --shadow-float: 0 22px 70px rgba(7, 24, 43, .16), 0 4px 14px rgba(7, 24, 43, .08);
}

html {
    scroll-behavior: smooth;
    scroll-padding-top: 24px;
}

body {
    min-width: 320px;
    min-height: 100vh;
    margin: 0;
    background: var(--canvas);
    color: var(--ink);
    font-family: "Inter Variable", Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 14px;
    line-height: 1.5;
    letter-spacing: 0;
    -webkit-font-smoothing: antialiased;
}

body:before,
body:after {
    display: none;
}

button,
input,
select,
textarea {
    font: inherit;
    letter-spacing: 0;
}

a,
button,
input,
select,
textarea {
    transition: color .16s ease, background-color .16s ease, border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 3px solid rgba(91, 92, 240, .25);
    outline-offset: 2px;
}

h1,
h2 {
    color: var(--ink);
    font-weight: 760;
    letter-spacing: 0;
}

h1 {
    font-size: 34px;
    line-height: 1.12;
}

h2 {
    font-size: 19px;
    line-height: 1.25;
}

.eyebrow,
.section-kicker {
    margin: 0 0 7px;
    color: var(--accent);
    font-size: 10px;
    font-weight: 800;
    line-height: 1.2;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.muted,
.panel p {
    color: var(--ink-soft);
}

.grid,
.form-grid,
.method-grid {
    display: grid;
}

.checkout-head,
.brand-lockup,
.lang-switcher,
.checkout-actions {
    display: flex;
}

.checkout-head {
    justify-content: space-between;
    gap: 14px;
}

.brand-lockup {
    align-items: center;
}

.lang-switcher {
    justify-content: flex-end;
}

.checkout-actions {
    gap: 9px;
    flex-wrap: wrap;
}

.methods {
    display: grid;
    margin: 14px 0 0;
    padding: 0;
    list-style: none;
}

.methods li {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 3px 10px;
}

.methods em {
    grid-column: 2;
    font-style: normal;
}

.method-choice {
    position: relative;
    display: block;
}

.method-choice input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

.method-choice span {
    display: grid;
    gap: 5px;
    cursor: pointer;
    letter-spacing: 0;
    text-transform: none;
}

.method-choice em {
    font-style: normal;
}

.login form {
    display: grid;
}

.preview {
    display: grid;
}

.fine {
    color: var(--muted);
    font-size: 12px;
    line-height: 1.55;
}

/* Operator workspace */
/*
 * La columna oscura se pinta en el SHELL, no en la barra.
 *
 * `.app-rail` es `position: sticky` con `height: 100vh`, asi que su fondo llega
 * hasta donde llega el elemento: una pantalla. En cualquier pagina mas larga que
 * eso —el dashboard lo es siempre— la columna izquierda se cortaba a media
 * altura con un borde duro y debajo aparecia el canvas claro. Se ve en cualquier
 * captura del panel completo.
 *
 * Pintar la franja en el contenedor la hace independiente del alto del sticky.
 */
.app-shell {
    display: grid;
    grid-template-columns: 252px minmax(0, 1fr);
    min-height: 100vh;
    background: linear-gradient(90deg, var(--navy-950) 0 252px, var(--canvas) 252px);
}

.app-rail {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    height: 100vh;
    padding: 22px 16px 18px;
    overflow: auto;
    background: var(--navy-950);
    color: #fff;
}

.rail-brand {
    display: flex;
    align-items: center;
    gap: 11px;
    min-height: 50px;
    padding: 5px 8px;
    color: #fff;
    text-decoration: none;
}

.brand-mark {
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
    display: inline-grid;
    place-items: center;
    border: 0;
    border-radius: 8px;
    /* Identica a la del checkout (`--pv-mark-*`). El degrade es corto a
       proposito: uno que cruza medio rango de luminancia no tiene tinta
       posible -- la clara falla contra el extremo claro y la oscura contra el
       oscuro. */
    background: linear-gradient(150deg, #a8542a, #8e4220);
    color: #fff6ee;
    box-shadow: 0 10px 24px rgba(217, 133, 68, .28);
    font-size: 12px;
    font-weight: 900;
}

.rail-brand strong,
.login-brand strong {
    display: block;
    font-size: 14px;
    line-height: 1.2;
}

.rail-brand small,
.login-brand small {
    display: block;
    margin-top: 3px;
    color: #8fa8bd;
    font-size: 10px;
    line-height: 1.2;
}

.admin-nav {
    position: static;
    display: grid;
    width: auto;
    max-width: none;
    margin: 34px 0 24px;
    padding: 0;
    gap: 4px;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    backdrop-filter: none;
}

.admin-nav:before {
    content: "Workspace";
    padding: 0 12px 9px;
    color: #627d94;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: .14em;
    text-transform: uppercase;
}

.admin-nav a {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr);
    align-items: center;
    min-height: 42px;
    padding: 6px 10px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: #b8c8d6;
    font-size: 13px;
    font-weight: 650;
    text-decoration: none;
}

.admin-nav a:hover,
.admin-nav a:focus-visible {
    background: rgba(255, 255, 255, .08);
    color: #fff;
}

/* El numerito de cada seccion, sobre el rail oscuro. Era #5f7b93: 4.04, corto
   para 9px. El rail lleva sus propios grises justamente porque un solo token
   no puede servir a un fondo blanco y a uno casi negro. */
.nav-glyph {
    color: #6a88a1;
    font-size: 9px;
    font-variant-numeric: tabular-nums;
    letter-spacing: .08em;
}

.admin-nav a:hover .nav-glyph {
    color: var(--lime);
}

.rail-footer {
    margin-top: auto;
    padding: 16px 10px 6px;
    border-top: 1px solid rgba(255, 255, 255, .1);
}

.environment {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-height: 27px;
    padding: 5px 9px;
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 999px;
    color: #dce7f0;
    font-size: 10px;
    font-weight: 750;
    text-transform: uppercase;
}

.environment i,
.status-orb,
.login-trust i {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--mint);
    box-shadow: 0 0 0 4px rgba(24, 167, 121, .13);
}

.environment.test i {
    background: var(--amber);
    box-shadow: 0 0 0 4px rgba(233, 162, 59, .13);
}

.rail-footer p {
    margin: 10px 0 13px;
    color: #7891a7;
    font-size: 11px;
}

.rail-logout {
    width: 100%;
    min-height: 38px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 10px;
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 6px;
    background: rgba(255, 255, 255, .05);
    color: #dbe7f0;
    box-shadow: none;
    font-size: 12px;
}

.rail-logout:hover {
    border-color: rgba(255, 255, 255, .22);
    background: rgba(255, 255, 255, .1);
    color: #fff;
    transform: none;
}

.workspace {
    min-width: 0;
    background: var(--canvas);
}

/*
 * El encabezado de las pantallas que NO usan el layout de workspace.
 *
 * Las capas inline del shell pintan `.top h1` de blanco porque ahi arriba habia
 * una banda diagonal oscura (`body:before`). Esta hoja la apaga —dos reglas mas
 * arriba— y nunca repuso el color del titulo fuera de `.workspace`, que si lo
 * tiene propio. Resultado: "Detalle de pago" quedaba blanco sobre el canvas
 * claro, invisible, y su bajada en blanco al 78% directamente no se leia. Es la
 * pantalla donde ops pasa el dia.
 *
 * El alto tambien venia calculado para esa banda que ya no existe: 190px de
 * minimo dejaban un hueco vacio antes del titulo.
 */
.wrap > .top {
    min-height: 0;
    align-items: center;
    gap: 24px;
    margin: 0 0 22px;
    padding: 26px 0 20px;
    border-bottom: 1px solid var(--line);
}

.wrap > .top:before {
    display: none;
}

.wrap > .top h1 {
    max-width: 720px;
    color: var(--ink);
    font-size: clamp(28px, 3.4vw, 36px);
    line-height: 1.1;
}

/* El eyebrow de la cabecera del workspace.
   Una capa anterior lo pinta `#b4f7ff` —cian palido— porque en SU layout
   estaba sobre una banda diagonal oscura. Esa banda ya no existe, asi que el
   texto quedo cian sobre blanco: 1.18 de contraste, o sea invisible. La regla
   de aca abajo solo alcanzaba al layout viejo (`.wrap > .top`); el panel de
   hoy es `.app-shell > .workspace > .top` y no la agarraba. */
.workspace > .top .eyebrow,
.wrap > .top .eyebrow {
    color: var(--accent);
}

.wrap > .top .muted {
    max-width: 680px;
    margin-top: 6px;
    color: var(--ink-soft);
    font-size: 13.5px;
    line-height: 1.5;
}


.workspace .top {
    min-height: 94px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    margin: 0;
    padding: 20px 34px;
    border-bottom: 1px solid var(--line);
    background: rgba(255, 255, 255, .88);
    backdrop-filter: blur(18px);
}

.workspace .top:before {
    display: none;
}

.workspace .top h1 {
    max-width: none;
    color: var(--ink);
    font-size: 27px;
    line-height: 1.15;
}

.workspace .top .muted {
    max-width: 680px;
    margin-top: 4px;
    color: var(--ink-soft);
    font-size: 13px;
    line-height: 1.45;
}

.top-status {
    display: flex;
    align-items: center;
    gap: 11px;
    min-width: 190px;
    padding: 10px 13px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: #fff;
}

.top-status span:last-child {
    display: grid;
}

.top-status strong {
    color: var(--ink);
    font-size: 11px;
    line-height: 1.2;
}

.top-status small {
    margin-top: 2px;
    color: var(--muted);
    font-size: 10px;
}

.workspace-body {
    width: min(100%, 1420px);
    margin: 0 auto;
    padding: 26px 34px 64px;
}

.grid {
    gap: 14px;
}

.kpis {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    margin: 0 0 14px;
}

.kpi {
    position: relative;
    min-height: 122px;
    padding: 18px;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--surface);
    box-shadow: var(--shadow-soft);
}

.kpi:before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 3px;
    height: auto;
    background: var(--accent);
}

/* El color de la barra lo decide el ESTADO del dato, no su posición en la
   fila. Antes eran cuatro colores repartidos por `nth-child`: el tercer tile
   era verde por ser el tercero. Ver la regla en el bloque del sistema. */

.kpi span,
.kpi em,
label span {
    color: var(--muted);
    font-size: 10px;
    font-style: normal;
    font-weight: 720;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.kpi strong {
    display: block;
    margin-top: 13px;
    color: var(--ink);
    font-size: 26px;
    font-weight: 760;
    line-height: 1.1;
}

.kpi em {
    display: block;
    margin-top: 10px;
    color: var(--ink-soft);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
}

.two {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    margin-top: 14px;
}

.panel {
    margin-top: 14px;
    padding: 22px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--surface);
    box-shadow: 0 1px 2px rgba(7, 24, 43, .035);
}

.panel-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 24px;
    margin-bottom: 20px;
    padding-bottom: 17px;
    border-bottom: 1px solid #edf2f7;
}

.panel-head h2 {
    margin: 0;
}

.panel-head p:not(.section-kicker) {
    max-width: 720px;
    margin: 5px 0 0;
    font-size: 12px;
}

.panel-index {
    color: #d6e0e9;
    font-size: 26px;
    font-weight: 760;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.form-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 14px;
}

label {
    color: var(--ink);
}

input,
select,
textarea {
    width: 100%;
    min-height: 43px;
    margin-top: 7px;
    padding: 10px 11px;
    border: 1px solid var(--line-strong);
    border-radius: 6px;
    background: #fff;
    color: var(--ink);
    box-shadow: inset 0 1px 1px rgba(7, 24, 43, .025);
    outline: 0;
}

textarea {
    min-height: 92px;
    resize: vertical;
}

input:hover,
select:hover,
textarea:hover {
    border-color: #aebdcb;
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(168, 84, 42, .13);
}

input::placeholder,
textarea::placeholder {
    color: #9babb9;
}

input[readonly] {
    background: var(--surface-soft);
}

.wide {
    grid-column: 1 / -1;
}

.actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 9px;
}

button,
.button-link,
.ghost,
.ghost-link {
    min-height: 41px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 9px 14px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 740;
    text-decoration: none;
    cursor: pointer;
}

button,
.button-link {
    border: 1px solid var(--navy-900);
    background: var(--navy-900);
    color: #fff;
    box-shadow: 0 7px 16px rgba(11, 34, 57, .14);
}

button:hover,
.button-link:hover {
    border-color: var(--navy-800);
    background: var(--navy-800);
    transform: translateY(-1px);
}

button:active,
.button-link:active {
    transform: translateY(0);
}

.ghost,
.ghost-link {
    border: 1px solid var(--line-strong);
    background: #fff;
    color: var(--ink);
    box-shadow: none;
}

.ghost:hover,
.ghost-link:hover {
    border-color: #abbaff;
    background: #f7f7ff;
    color: #4143c7;
}

.danger {
    border-color: #f2c6d2;
    background: #fff;
    color: #b62f55;
    box-shadow: none;
}

.danger:hover {
    border-color: #ebaab9;
    background: #fff6f8;
    color: #982144;
}

.mini {
    min-height: 31px;
    padding: 6px 9px;
    font-size: 10px;
}

/* El form de revocar es block: sin esto la accion segura y la destructiva
   quedan apiladas, y la roja se lee como la unica de la fila. */
.row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}

.row-actions form {
    margin: 0;
}

.flash {
    margin: 0 0 10px;
    padding: 11px 13px 11px 38px;
    border: 1px solid #bde3eb;
    border-radius: 7px;
    background: #effbfd;
    color: #176277;
    box-shadow: none;
    font-size: 12px;
    position: relative;
}

.flash:before {
    content: "i";
    position: absolute;
    left: 13px;
    top: 11px;
    width: 16px;
    height: 16px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: #cceff5;
    font-size: 10px;
    font-weight: 850;
}

.flash.error {
    border-color: #f4cad5;
    background: #fff4f7;
    color: #9c2d4c;
}

.flash.error:before {
    content: "!";
    background: #f8dce4;
}

.flash.warn {
    border-color: #f0c36d;
    background: #fff8e8;
    color: #7a5310;
}

.flash.warn:before {
    content: "!";
    background: #f0c36d;
    color: #4a3208;
}

.flash.success {
    border-color: #bce7d8;
    background: #effbf7;
    color: #087653;
}

.flash.success:before {
    content: "OK";
    background: #d2f2e7;
    font-size: 7px;
}

.table {
    margin-top: 16px;
    overflow: auto;
    border: 1px solid var(--line);
    border-radius: 7px;
    background: #fff;
}

table {
    width: 100%;
    min-width: 900px;
    border-collapse: collapse;
}

th,
td {
    padding: 11px 12px;
    border-bottom: 1px solid #edf2f7;
    text-align: left;
    vertical-align: middle;
}

th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: #f7f9fc;
    /* Era #6f8294: 3.76 sobre su propio fondo. Un encabezado de columna que
       no se lee obliga a deducir que hay en cada columna. */
    color: var(--text-3);
    font-size: 9px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
}

td {
    color: #334e68;
    font-size: 12px;
}

td strong {
    color: var(--ink);
}

td small {
    color: var(--muted);
}

tbody tr:hover {
    background: #fafcff;
}

tbody tr:last-child td {
    border-bottom: 0;
}

.compact table {
    min-width: 560px;
}

/*
 * Una tabla dentro de un panel a media pagina no puede pedir 900px.
 *
 * El minimo global existe para que las tablas anchas del listado no se
 * apelmacen, pero en los paneles de `.two` la columna mide ~380px: la ultima
 * celda —que casi siempre es el estado o el monto— quedaba cortada al medio
 * ("$0 CLF", "PROCESS"). Con scroll horizontal seguia estando, pero nadie
 * descubre un scroll dentro de una tarjeta.
 */
.two .panel table {
    min-width: 0;
}

.two .panel th,
.two .panel td {
    padding: 10px;
}

.two .panel td {
    overflow-wrap: anywhere;
}

.status-pill {
    min-height: 24px;
    display: inline-flex;
    align-items: center;
    padding: 4px 8px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: #f4f7fa;
    color: var(--ink-soft);
    font-size: 9px;
    font-weight: 800;
    white-space: nowrap;
    text-transform: uppercase;
}

.status-pill.success {
    border-color: #bce7d8;
    background: #effbf7;
    color: #087653;
}

.status-pill.warning {
    border-color: #f2daa9;
    background: #fff9eb;
    color: #946018;
}

.status-pill.danger {
    border-color: #f3c6d1;
    background: #fff4f7;
    color: #a72a4d;
}

.methods {
    gap: 7px;
}

.methods li {
    padding: 10px 11px;
    border: 1px solid var(--line);
    border-radius: 7px;
    background: #fff;
    box-shadow: none;
}

.methods strong {
    color: var(--ink);
    font-size: 12px;
}

.methods em {
    color: var(--muted);
    font-size: 10px;
}

.dot {
    width: 8px;
    height: 8px;
}

.dot.ok {
    background: var(--mint);
    box-shadow: 0 0 0 3px rgba(24, 167, 121, .11);
}

.safety {
    grid-template-columns: 180px minmax(0, 1fr);
    margin-top: 6px;
    padding: 0;
    border: 0;
    background: transparent;
}

.safety dt {
    color: var(--muted);
    font-size: 9px;
    font-weight: 760;
}

.safety dd {
    color: #334e68;
    font-size: 12px;
}

.empty {
    padding: 16px;
    border: 1px dashed var(--line-strong);
    border-radius: 7px;
    background: var(--surface-soft);
    color: var(--muted);
    font-size: 12px;
}

.form-grid.filters {
    margin-top: 16px;
    padding: 14px;
    border: 1px solid var(--line);
    border-radius: 7px;
    background: var(--surface-soft);
}

/* Public checkout */
.checkout {
    position: relative;
    width: min(1180px, calc(100% - 36px));
    max-width: none;
    min-height: calc(100vh - 64px);
    display: grid;
    grid-template-columns: minmax(0, 1fr) 380px;
    align-items: stretch;
    gap: 0;
    margin: 32px auto;
    padding: 0;
    border: 1px solid rgba(7, 24, 43, .1);
    border-radius: 8px;
    overflow: hidden;
    background: #fff;
    box-shadow: var(--shadow-float);
}

.checkout-main,
.checkout-side {
    border: 0;
    border-radius: 0;
    background: #fff;
    box-shadow: none;
    backdrop-filter: none;
}

.checkout-main {
    position: relative;
    padding: 38px 44px 42px;
    overflow: visible;
}

.checkout-main:before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 5px;
    height: auto;
    background: var(--accent);
}

.checkout-head {
    align-items: center;
}

.brand-lockup {
    gap: 11px;
}

.brand-lockup .brand-mark {
    background: var(--navy-950);
    color: #fff;
}

.brand-lockup strong {
    color: var(--ink);
    font-size: 13px;
}

.checkout h1 {
    max-width: 620px;
    margin-top: 44px;
    color: var(--ink);
    font-size: 36px;
    font-weight: 760;
    line-height: 1.13;
}

.checkout .muted {
    max-width: 650px;
    color: var(--ink-soft);
    font-size: 14px;
    line-height: 1.6;
}

.lang-switcher {
    gap: 4px;
    padding: 3px;
    border: 1px solid var(--line);
    border-radius: 7px;
    background: var(--surface-soft);
}

.lang-switcher .ghost-link {
    min-height: 30px;
    padding: 5px 8px;
    border: 0;
    background: transparent;
    color: var(--ink-soft);
    font-size: 9px;
    box-shadow: none;
}

.lang-switcher .ghost-link.active {
    border: 0;
    background: #fff;
    color: var(--ink);
    box-shadow: 0 1px 3px rgba(7, 24, 43, .1);
}

.trust-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    margin: 20px 0 4px;
}

.trust-strip span {
    min-height: 28px;
    display: inline-flex;
    align-items: center;
    padding: 5px 9px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface-soft);
    color: #486581;
    font-size: 10px;
    font-weight: 680;
}

.preview {
    grid-template-columns: minmax(120px, .35fr) minmax(0, 1fr);
    margin: 23px 0;
    padding: 0;
    gap: 0;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: 7px;
    background: #fff;
}

.preview dt,
.preview dd {
    margin: 0;
    padding: 11px 13px;
    border-bottom: 1px solid #edf2f7;
}

.preview dt {
    background: var(--surface-soft);
    color: var(--muted);
    font-size: 10px;
}

.preview dd {
    color: var(--ink);
    font-size: 12px;
    font-weight: 700;
}

.preview dt:last-of-type,
.preview dd:last-of-type {
    border-bottom: 0;
}

.pay-methods {
    margin-top: 24px;
}

.method-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 9px;
    margin-top: 13px;
}

.method-choice span {
    min-height: 90px;
    align-content: center;
    padding: 13px;
    border: 1px solid var(--line);
    border-radius: 7px;
    background: #fff;
    color: var(--ink);
    box-shadow: none;
}

.method-choice span:hover {
    border-color: #aeb2f7;
    background: #fbfbff;
    transform: translateY(-1px);
}

.method-choice strong {
    color: var(--ink);
    font-size: 13px;
}

.method-choice em {
    color: var(--muted);
    font-size: 10px;
}

.method-choice input:checked + span {
    border-color: var(--accent);
    background: #fdf6f1;
    box-shadow: 0 0 0 1px var(--accent) inset;
}

.checkout-actions {
    margin-top: 18px;
}

/* ---- Monto abierto: elegir cuanto pagar ---- */

.range-label {
    margin: 0 0 10px;
    color: var(--muted);
    font-size: 10px;
    font-weight: 780;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.range-presets {
    margin-top: 26px;
}

.range-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 9px;
}

/* Cada sugerido es un submit: un clic cobra ese monto. Se dibujan como
   tarjetas y no como botones chicos porque son la accion principal de la
   pantalla, no un accesorio del campo de abajo. */
.range-grid button {
    min-height: 62px;
    padding: 14px 12px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: #fff;
    color: var(--ink);
    font-size: 17px;
    font-weight: 760;
    letter-spacing: -.01em;
    box-shadow: none;
    transition: border-color .12s, background .12s, transform .12s, box-shadow .12s;
}

.range-grid button:hover {
    border-color: var(--accent);
    background: #fdf6f1;
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(168, 84, 42, .16);
}

.range-grid button:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.range-custom {
    margin-top: 26px;
    padding-top: 24px;
    border-top: 1px solid var(--line);
}

.range-field {
    display: flex;
    align-items: stretch;
    gap: 9px;
    flex-wrap: wrap;
}

.range-currency {
    display: inline-flex;
    align-items: center;
    padding: 0 13px;
    border: 1px solid var(--line);
    border-radius: 7px;
    background: var(--surface-soft);
    color: var(--muted);
    font-size: 11px;
    font-weight: 760;
}

.range-field input[type="number"] {
    flex: 1 1 160px;
    min-width: 0;
    min-height: 48px;
    font-size: 19px;
    font-weight: 720;
}

.range-field button {
    min-height: 48px;
    padding: 0 22px;
}

.checkout-side {
    position: relative;
    top: auto;
    padding: 38px 30px;
    border-left: 1px solid rgba(255, 255, 255, .1);
    background: var(--navy-950);
    color: #fff;
}

.checkout-side:before {
    content: "";
    display: block;
    width: 44px;
    height: 4px;
    margin-bottom: 32px;
    border-radius: 999px;
    background: var(--lime);
}

.checkout-side h2 {
    color: #fff;
    font-size: 23px;
}

.side-kicker {
    color: #8fb0c9;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: .12em;
}

.checkout-side .methods {
    margin-top: 24px;
}

.checkout-side .methods li {
    border-color: rgba(255, 255, 255, .11);
    background: rgba(255, 255, 255, .055);
}

.checkout-side .methods strong {
    color: #fff;
}

.checkout-side .methods em,
.checkout-side .fine {
    color: #91a9bd;
}

.checkout-side .fine {
    position: absolute;
    right: 30px;
    bottom: 26px;
    left: 30px;
    margin: 0;
    padding-top: 16px;
    border-top: 1px solid rgba(255, 255, 255, .1);
}

/* Login and standalone states */
.login-stage {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 28px;
    background: var(--navy-950);
}

.login-stage:before {
    content: "";
    position: fixed;
    inset: 0 0 auto;
    height: 5px;
    background: linear-gradient(90deg, #e59a5b, #a8542a);
}

.login {
    position: relative;
    width: min(480px, calc(100% - 28px));
    max-width: none;
    margin: 8vh auto 0;
    padding: 32px;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: #fff;
    box-shadow: var(--shadow-float);
}

.login:before,
.login:after {
    display: none;
}

.operator-login {
    width: min(500px, 100%);
    margin: 0;
    padding: 34px;
}

.login-brand {
    display: flex;
    align-items: center;
    gap: 11px;
    padding-bottom: 23px;
    border-bottom: 1px solid #edf2f7;
}

.login-brand .brand-mark {
    background: var(--navy-950);
    color: #fff;
}

.login-brand strong {
    color: var(--ink);
}

.login-copy {
    padding-top: 30px;
}

.login h1 {
    max-width: none;
    color: var(--ink);
    font-size: 32px;
    line-height: 1.15;
}

.login .muted {
    color: var(--ink-soft);
    font-size: 13px;
}

.login form {
    margin-top: 24px;
    gap: 13px;
}

.login input {
    height: 48px;
    font-size: 14px;
}

.login button {
    width: 100%;
    min-height: 46px;
    justify-content: space-between;
    padding-right: 16px;
    padding-left: 16px;
}

.login-trust {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 21px;
    padding-top: 17px;
    border-top: 1px solid #edf2f7;
    color: var(--ink-soft);
    font-size: 10px;
    font-weight: 650;
}

.login-trust span:first-child {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.login .fine {
    margin: 15px 0 0;
}

@media (max-width: 1100px) {
    .app-shell {
        grid-template-columns: 214px minmax(0, 1fr);
        background: linear-gradient(90deg, var(--navy-950) 0 214px, var(--canvas) 214px);
    }

    .workspace .top,
    .workspace-body {
        padding-right: 24px;
        padding-left: 24px;
    }

    .kpis {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .form-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .checkout {
        grid-template-columns: minmax(0, 1fr) 340px;
    }

    .method-grid {
        grid-template-columns: 1fr 1fr;
    }

    /* Cuatro montos en fila necesitan ancho: apenas se angosta, dos filas de
       dos antes de que el numero empiece a partirse. */
    .range-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 820px) {
    /* Sin dos columnas no hay franja que pintar: la barra pasa a ser una
       cabecera y su propio fondo alcanza. */
    .app-shell {
        display: block;
        background: var(--canvas);
    }

    .app-rail {
        position: relative;
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) auto;
        align-items: center;
        height: auto;
        padding: 10px 12px;
        overflow: visible;
    }

    .rail-brand small,
    .rail-footer p,
    .rail-footer .environment,
    .admin-nav:before,
    .admin-nav a span:last-child {
        display: none;
    }

    .admin-nav {
        display: flex;
        justify-content: center;
        gap: 3px;
        margin: 0 10px;
        overflow: auto;
    }

    .admin-nav a {
        display: grid;
        grid-template-columns: 1fr;
        width: 36px;
        min-width: 36px;
        min-height: 36px;
        place-items: center;
        padding: 5px;
    }

    .nav-glyph {
        font-size: 9px;
    }

    .rail-footer {
        margin: 0;
        padding: 0;
        border: 0;
    }

    .rail-logout {
        width: 38px;
        min-height: 36px;
        padding: 5px;
        justify-content: center;
        font-size: 0;
    }

    .rail-logout span {
        font-size: 15px;
    }

    .workspace .top {
        min-height: 86px;
    }

    .top-status {
        min-width: auto;
    }

    .top-status span:last-child {
        display: none;
    }

    .two {
        grid-template-columns: 1fr;
    }

    .checkout {
        width: min(720px, calc(100% - 24px));
        min-height: 0;
        grid-template-columns: 1fr;
        margin: 12px auto;
    }

    .checkout-side {
        min-height: 340px;
        border-top: 1px solid rgba(255, 255, 255, .1);
        border-left: 0;
    }

    .checkout-side .fine {
        position: static;
        margin-top: 30px;
    }
}

@media (max-width: 620px) {
    .app-rail {
        grid-template-columns: auto minmax(0, 1fr) auto;
    }

    .rail-brand > span:last-child {
        display: none;
    }

    .workspace .top {
        min-height: 80px;
        padding: 16px;
    }

    .workspace .top h1 {
        font-size: 24px;
    }

    .workspace .top .muted {
        display: none;
    }

    .workspace-body {
        padding: 16px 12px 42px;
    }

    .kpis,
    .form-grid,
    .safety,
    .method-grid {
        grid-template-columns: 1fr;
    }

    .kpi {
        min-height: 106px;
    }

    .panel {
        padding: 17px;
    }

    .panel-head {
        gap: 12px;
    }

    .panel-index {
        font-size: 21px;
    }

    .actions {
        align-items: stretch;
        flex-direction: column-reverse;
    }

    .actions button,
    .actions .ghost-link,
    .actions .button-link {
        width: 100%;
    }

    .checkout-main,
    .checkout-side {
        padding: 24px 20px;
    }

    .checkout h1 {
        margin-top: 32px;
        font-size: 29px;
    }

    .checkout-head {
        display: flex;
        align-items: flex-start;
    }

    .brand-lockup > div {
        display: none;
    }

    .preview {
        grid-template-columns: 1fr;
    }

    .preview dt,
    .preview dd {
        padding: 9px 11px;
    }

    .preview dt {
        border-bottom: 0;
        padding-bottom: 2px;
    }

    .preview dd {
        padding-top: 2px;
    }

    .login-stage {
        padding: 12px;
    }

    .operator-login,
    .login {
        width: 100%;
        margin: 0;
        padding: 24px 20px;
    }

    .login h1 {
        font-size: 29px;
    }

    .login-trust {
        align-items: flex-start;
        flex-direction: column;
    }
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *,
    *:before,
    *:after {
        transition-duration: .01ms !important;
    }
}

/* ── Comprobante · acciones y version imprimible ─────────────────────────
   El comprobante es la ultima pantalla que ve el cliente. Antes terminaba
   sin salida: ni forma de guardarlo ni de volver.
   "Descargar" usa el dialogo de impresion del navegador, que ofrece
   "Guardar como PDF"; por eso hay estilos de impresion, para que lo que se
   guarda sea el comprobante y no la interfaz alrededor. */
.receipt-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
    align-items: stretch;
    margin: 1.25rem 0 .5rem;
}

/* Los dos botones con el mismo peso visual: ninguno de los dos es "el
   secundario". Con `flex: 1 1 200px` van lado a lado cuando entran y se apilan
   —los dos del mismo ancho— cuando no. Antes quedaban con anchos distintos, que
   en la ultima pantalla que ve el cliente se lee como algo a medio terminar. */
.receipt-actions > * {
    flex: 1 1 200px;
}

@media print {
    /* Fuera todo lo que no es el comprobante: acciones, selector de idioma y
       cualquier navegacion. En papel no se puede hacer click. */
    .receipt-actions,
    .lang-switcher,
    .app-rail,
    .admin-nav {
        display: none !important;
    }
    /* Fondo claro y texto negro: el tema oscuro en papel gasta tinta y se lee
       peor. */
    body {
        background: #fff !important;
        color: #000 !important;
    }
    .login {
        box-shadow: none !important;
        border: 0 !important;
        margin: 0 !important;
        max-width: none !important;
    }
    /* Una fila de la tabla partida entre dos hojas deja un comprobante que no
       se entiende. */
    tr, .kpi {
        break-inside: avoid;
    }
}

/* ═════════════════════════════════════════════════════════════════════════
   TOUREVO PAY V2 · pantallas publicas
   Esta seccion es DUEÑA del look de todo lo que ve un cliente
   (.public-checkout y los estados sueltos .login). Va al final a proposito:
   gana la cascada sobre las capas historicas sin tocar el panel interno.
   Direccion: private travel + fintech. Menos cajas, mas jerarquia.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── CORDILLERA · el mundo visual de las pantallas del cliente ───────────
   Paso 2 del rediseño. El checkout deja de ser un formulario sobre fondo
   blanco y pasa a ser una pantalla con lugar: pizarra fría, el relieve de la
   cordillera al fondo y cobre como único acento.

   ── Por qué se puede ir a oscuro en una pantalla de pago ─────────────────

   Porque acá NO se tipea una tarjeta. Tourevo Pay nunca toca datos de tarjeta:
   el cliente elige un medio y sale a paypal.com o a Webpay, donde vuelve el
   marco de confianza de siempre. Un checkout oscuro sería mal consejo en una
   pantalla de captura; ésta es de elección.

   ── Por qué cobre ────────────────────────────────────────────────────────

   Chile es cobre. Ninguna pasarela lo usa, y el acento sale del amanecer que
   está dibujado detrás de la cadena — no aparece de la nada en el botón.
   Va en UN solo lugar: la acción primaria. Todo lo demás es pizarra.

   ── La regla que hace esto reversible ────────────────────────────────────

   Ningún color literal vive fuera de este bloque. Los diez que quedaban
   sueltos en la sección (el radio, el hover, el CTA, el placeholder, el error)
   se tokenizaron para que el tema fuera redefinir esto y nada más. Si algún
   día hay que volver a claro, o encender un claro/oscuro por preferencia del
   sistema, se cambia acá — y en `@media print`, que ya lo hace.
   ───────────────────────────────────────────────────────────────────────── */
:root {
  --pv-bg: #0b1119;            /* pizarra fria, con sesgo azul */
  --pv-card: rgba(20, 28, 39, .86);
  --pv-card-solid: #141c27;    /* el mismo, opaco, donde no puede haber vidrio */
  --pv-ink: #eaf0f7;
  --pv-soft: #a7b8ca;
  --pv-faint: #8598ab;
  --pv-line: rgba(255, 255, 255, .11);
  --pv-line-soft: rgba(255, 255, 255, .06);
  --pv-line-hover: rgba(255, 255, 255, .22);
  --pv-accent: #e59a5b;        /* cobre · SOLO la accion primaria y la seleccion */
  --pv-accent-soft: rgba(217, 133, 68, .13);
  --pv-ok: #35c491;
  --pv-radius: 12px;
  --pv-shadow: 0 1px 2px rgba(0,0,0,.28), 0 30px 70px rgba(0,0,0,.45);
  --pv-focus: 0 0 0 3px rgba(217, 133, 68, .38);

  /* Controles */
  --pv-tile-bg: rgba(255, 255, 255, .045);   /* lo que se apoya SOBRE la tarjeta */
  /* Y lo que se HUNDE en ella. En claro un panel de datos se aclara; en
     oscuro se oscurece, y ademas hace falta: sobre el tono levantado, los
     rotulos de 10px del comprobante quedaban en 2.84 de contraste. */
  --pv-sunken: rgba(0, 0, 0, .24);
  --pv-logo-plate: #ffffff;                  /* las marcas se publican para fondo claro */
  --pv-control-bg: rgba(255, 255, 255, .06);
  --pv-control-line: rgba(255, 255, 255, .26);
  --pv-placeholder: #6d8095;

  /* Accion primaria */
  --pv-cta-bg: linear-gradient(180deg, #e79352, #cf7534);
  --pv-cta-bg-hover: linear-gradient(180deg, #efa062, #d97f3d);
  --pv-cta-ink: #1c1207;
  --pv-cta-shadow: 0 10px 26px rgba(217, 133, 68, .26);
  --pv-cta-shadow-hover: 0 14px 32px rgba(217, 133, 68, .34);
  --pv-cta-shadow-active: 0 6px 14px rgba(217, 133, 68, .24);

  /* Marca */
  /* El degrade de la marca es CORTO a proposito. El primero iba de #d98544 a
     #a8542a y ninguna tinta servia: la clara fallaba contra el extremo claro
     (3.6) y la oscura contra el oscuro (3.5). Un degrade que cruza medio rango
     de luminancia no tiene tinta posible -- hay que angostarlo, no elegir
     mejor el color. */
  --pv-mark-bg: linear-gradient(150deg, #a8542a, #8e4220);
  /* Tinta clara y no oscura: "TP" son 13px sobre el extremo mas oscuro del
     degrade, y con tinta oscura quedaba en 3.54 -- por debajo del 4.5 que
     pide texto chico. El boton se banca tinta oscura porque su cobre es mas
     claro; este no. */
  --pv-mark-ink: #fff6ee;
  --pv-mark-shadow: 0 10px 24px rgba(217, 133, 68, .28);

  /* Error */
  --pv-danger-bg: rgba(225, 76, 112, .12);
  --pv-danger-ink: #ffabc0;
  --pv-danger-line: rgba(225, 76, 112, .34);
}

/* El fondo: la cadena abajo, el cielo arriba.
   `background-attachment: fixed` NO: en iOS repinta en cada scroll y el
   checkout tironea justo cuando el cliente esta leyendo el monto. Va anclado
   al pie del documento, que es donde la cordillera tiene sentido. */
body:has(main.public-checkout),
body:has(.login) {
  background: var(--pv-bg) url("cordillera.svg") no-repeat bottom center;
  background-size: 100% auto;
  color: var(--pv-ink);
}
body:has(main.public-checkout)::before,
body:has(main.public-checkout)::after,
body:has(.login)::before { display: none; }

/* ── Marco general ─────────────────────────────────────────────────────── */
main.public-checkout {
  /* Una capa anterior convertia .checkout entero en una tarjeta blanca de
     100vh: doble marco. Aca se anula y la tarjeta es SOLO la columna de pago. */
  width: auto;
  min-height: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
  max-width: 1020px;
  margin: 0 auto;
  padding: 40px 24px 72px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 316px;
  gap: 24px;
  align-items: start;             /* la columna lateral deja de ser un telon */
}

.public-checkout .checkout-main {
  background: var(--pv-card);
  /* Vidrio: la tarjeta deja pasar la cordillera de atras, apenas. Si el
     navegador no soporta backdrop-filter queda el color translucido solo, que
     sigue siendo legible -- por eso el token ya trae .86 de opacidad y no una
     transparencia que dependa del desenfoque. */
  -webkit-backdrop-filter: blur(20px) saturate(1.25);
  backdrop-filter: blur(20px) saturate(1.25);
  border: 1px solid var(--pv-line);
  border-radius: 16px;
  box-shadow: var(--pv-shadow);
  padding: 36px 40px 40px;
  overflow: visible;
}
.public-checkout .checkout-main::before { display: none; }  /* fuera la franja arcoiris */

.public-checkout h1 {
  font-size: 22px;
  font-weight: 750;
  letter-spacing: -.01em;
  color: var(--pv-ink);
  margin-top: 26px;
}
.public-checkout .checkout-main > .muted {
  font-size: 13.5px;
  color: var(--pv-soft);
  margin-top: 6px;
  max-width: 56ch;
}

/* Marca y idioma */
.public-checkout .brandbar { align-items: center; }
.public-checkout .brand-mark {
  width: 38px; height: 38px; border-radius: 10px;
  background: var(--pv-mark-bg); color: var(--pv-mark-ink);
  box-shadow: var(--pv-mark-shadow);
  font-size: 13px;
}
.public-checkout .brand-lockup .eyebrow { color: var(--pv-accent); letter-spacing: .14em; margin: 0 0 2px; }
.public-checkout .brand-lockup strong { color: var(--pv-ink); font-size: 13px; }
/* El contenedor del selector de idioma, no solo sus botones.
   La seccion publica estilaba los `<a>` pero se olvidaba de la pastilla que
   los envuelve, que heredaba `--surface-soft` (#f8fafc) de la capa del panel.
   Sobre fondo claro pasaba disimulado; sobre pizarra quedaba una pastilla
   blanca con ES casi invisible adentro -- ratio 1.1 contra el 4.5 que hace
   falta. Lo encontro el barrido de contraste, no el ojo. */
.public-checkout .lang-switcher,
body:has(.login) .lang-switcher {
  background: var(--pv-tile-bg);
  border-color: var(--pv-line);
}
.public-checkout .lang-switcher .ghost-link,
body:has(.login) .lang-switcher .ghost-link {
  min-height: 30px; padding: 4px 9px; font-size: 10px;
  background: transparent; border-color: transparent; color: var(--pv-soft);
}
/* La regla vieja de la pastilla activa es `.lang-switcher .ghost-link.active`
   (0,3,0) y le gana a cualquier cosa colgada de `body:has(.login)` (0,2,1).
   Por eso el selector repite las tres clases: no alcanza con envolver. */
.public-checkout .lang-switcher .ghost-link.active,
body:has(.login) .lang-switcher .ghost-link.active {
  background: var(--pv-tile-bg); border-color: var(--pv-line); color: var(--pv-ink); box-shadow: none;
}

/* ── El hero del pago: el monto manda ──────────────────────────────────── */
.pay-hero {
  margin: 22px 0 6px;
  padding: 24px 0 20px;
  border-top: 1px solid var(--pv-line-soft);
  border-bottom: 1px solid var(--pv-line-soft);
}
.pay-concept {
  margin: 0 0 6px;
  font-size: 11px; font-weight: 800;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--pv-accent);
}
.pay-amount {
  margin: 0;
  font-size: clamp(34px, 5vw, 44px);
  line-height: 1.04;
  font-weight: 780;
  letter-spacing: -.025em;
  color: var(--pv-ink);
  font-variant-numeric: tabular-nums;
}
.pay-sub {
  margin: 8px 0 0;
  font-size: 13.5px; color: var(--pv-soft);
  font-variant-numeric: tabular-nums;
}
/* El codigo de moneda acompaña; el numero manda.
   En `$1.810.560 CLP` a 44px, esas tres letras pesan lo mismo que la cifra y
   son lo unico de la linea que el cliente no necesita leer. */
.pay-amount .cur {
  font-size: .5em; font-weight: 700;
  letter-spacing: .01em; color: var(--pv-soft);
}
.pay-sub .cur,
.public-checkout .method-choice em .cur {
  font-size: .86em; font-weight: 640; color: var(--pv-faint);
}
.public-checkout .method-choice input:checked + span em .cur { color: inherit; opacity: .72; }
.pay-dot { color: var(--pv-faint); }
.pay-total { white-space: nowrap; }
/* En pantalla angosta la sublinea no entra en un renglon y el punto queda
   colgando al final del primero —"…com cartão chileno ·"—, que se lee como
   una frase que se corto. Son dos datos distintos: abajo van uno debajo del
   otro y el separador sobra. */
@media (max-width: 560px) {
  .pay-total { display: block; }
  .pay-sub .pay-dot { display: none; }
}

.pay-meta {
  display: flex; flex-wrap: wrap; gap: 6px 36px;
  margin: 18px 0 0; padding: 0;
}
.pay-meta > div { min-width: 0; }
.pay-meta dt {
  font-size: 10px; font-weight: 750; letter-spacing: .09em;
  text-transform: uppercase; color: var(--pv-faint); margin: 0 0 2px;
}
.pay-meta dd {
  margin: 0; font-size: 13px; font-weight: 620; color: var(--pv-ink);
  overflow-wrap: anywhere;
}
.pay-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; letter-spacing: .04em;
}

/* ── Metodos de pago: lista, no mosaico ────────────────────────────────── */
.public-checkout .pay-methods { margin-top: 22px; }

/* Los medios agrupados por moneda.
   Sin el encabezado, tres filas parejas donde dos son la misma cosa
   disfrazada: el cliente tiene que deducir que Webpay y Mercado Pago le cobran
   lo mismo en pesos, y que la decision de fondo era la moneda. El separador
   entre grupos es aire, no una linea: son dos caminos, no dos secciones. */
.public-checkout .method-groups {
  display: flex; flex-direction: column; gap: 22px;
}
.public-checkout .method-group-head {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px;
  margin: 0 0 9px;
}
.public-checkout .method-group-head span {
  font-size: 13px; font-weight: 700; color: var(--pv-ink); letter-spacing: -.005em;
}
.public-checkout .method-group-head em {
  font-style: normal; font-size: 12px; font-weight: 550; color: var(--pv-faint);
}
.public-checkout .method-grid {
  display: grid; grid-template-columns: 1fr; gap: 10px; margin-top: 0;
}
.public-checkout .method-choice span {
  min-height: 60px;
  display: flex; align-items: center; gap: 14px;
  padding: 14px 18px;
  background: var(--pv-tile-bg);
  border: 1px solid var(--pv-line);
  border-radius: var(--pv-radius);
  box-shadow: none;
  transition: border-color .14s ease, background .14s ease, box-shadow .14s ease;
}
/* El radio se dibuja: la seleccion se entiende sin leer */
.public-checkout .method-choice span::before {
  content: "";
  flex: 0 0 18px; width: 18px; height: 18px;
  border-radius: 50%;
  border: 1.5px solid var(--pv-control-line);
  background: var(--pv-control-bg);
  transition: border-color .14s ease, box-shadow .14s ease;
}
.public-checkout .method-choice span:hover { border-color: var(--pv-line-hover); transform: none; }
.public-checkout .method-choice input:checked + span {
  border-color: var(--pv-accent);
  background: var(--pv-accent-soft);
  box-shadow: 0 0 0 1px var(--pv-accent) inset;
}
.public-checkout .method-choice input:checked + span::before {
  border-color: var(--pv-accent);
  border-width: 5.5px;
}
.public-checkout .method-choice input:focus-visible + span { box-shadow: var(--pv-focus); }
.public-checkout .method-choice strong {
  font-size: 14.5px; font-weight: 680; color: var(--pv-ink);
}
/* El logo de la marca: tamano fijo desde el HTML (evita saltos al cargar),
   contenido sin deformar, y en escala de grises muy leve para que ninguna
   marca grite mas que otra dentro de la lista. Al elegirla recupera su color. */
.public-checkout .method-choice .method-logo {
  flex: 0 0 auto;
  object-fit: contain;
  filter: grayscale(.15);
  transition: filter .14s ease;
}
.public-checkout .method-choice input:checked + span .method-logo { filter: none; }
/* Cluster de marcas (hub /pago): pegado a la derecha, antes de la moneda.
   Es un span DENTRO del span del tile, asi que hereda todas las reglas de
   ".method-choice span" de las capas historicas (tarjeta blanca, min-height,
   hasta el radio dibujado en ::before). Se neutraliza todo eso aca. */
.public-checkout .method-choice .brand-row {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 9px;
  min-height: 0; padding: 0; border: 0; background: transparent;
  box-shadow: none; cursor: inherit;
}
.public-checkout .method-choice .brand-row::before { content: none; }
.public-checkout .method-choice .brand-row img { object-fit: contain; }
.public-checkout .method-choice .brand-row + em { margin-left: 12px; }
.public-checkout .method-choice em {
  margin-left: auto;
  font-size: 14px; font-weight: 700; font-style: normal;
  color: var(--pv-ink); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.public-checkout .method-choice input:checked + span em { color: var(--pv-accent); }

/* CTA */
.public-checkout .checkout-actions { margin-top: 18px; }
.public-checkout .checkout-actions button {
  width: 100%; min-height: 52px;
  border-radius: var(--pv-radius);
  background: var(--pv-cta-bg); color: var(--pv-cta-ink); border: 0;
  font-size: 15px; font-weight: 720; letter-spacing: .01em;
  box-shadow: var(--pv-cta-shadow);
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
}
.public-checkout .checkout-actions button:hover {
  background: var(--pv-cta-bg-hover); transform: translateY(-1px);
  box-shadow: var(--pv-cta-shadow-hover);
}
.public-checkout .checkout-actions button:active { transform: translateY(0); box-shadow: var(--pv-cta-shadow-active); }
.public-checkout .checkout-actions button:focus-visible { outline: 0; box-shadow: var(--pv-focus), var(--pv-cta-shadow); }

/* Confianza: una linea serena, no tres pastillas */
.public-checkout .trust-strip { margin: 16px 0 0; gap: 6px 22px; }
.public-checkout .trust-strip span {
  min-height: 0; padding: 0; border: 0; background: transparent;
  color: var(--pv-faint); font-size: 12px; font-weight: 550;
}
/* Sin punto separador, y no por gusto: las tres frases son items de un flex
   que envuelve, asi que el separador siempre queda del lado equivocado del
   corte. Con `::after` en el que no es ultimo, el punto colgaba al final del
   renglon —"…tu tarjeta ·"—; moverlo a `::before` del siguiente lo deja
   abriendo el renglon de abajo. Las dos versiones se leen como una lista que
   se corto a la mitad.
   El espacio separa igual y no se rompe al envolver: 22px de gap. */
.public-checkout .fine { color: var(--pv-faint); font-size: 12px; }

/* Los enlaces del checkout no estaban estilados: salian con el azul por
   defecto del navegador (#0000EE). Sobre el fondo claro pasaba disimulado;
   sobre pizarra, "Términos del pago" quedaba en un azul que casi no se lee
   —y es el enlace que dice cuanto te van a cobrar y que pasa si cancelas. */
.public-checkout a:not(.ghost-link):not(.button-link),
body:has(.login) .login a:not(.ghost-link):not(.button-link) {
  color: var(--pv-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--pv-line-hover);
  transition: color .14s ease, text-decoration-color .14s ease;
}
.public-checkout a:not(.ghost-link):not(.button-link):hover,
body:has(.login) .login a:not(.ghost-link):not(.button-link):hover {
  color: var(--pv-accent);
  text-decoration-color: var(--pv-accent);
}

/* Las marcas van sobre una placa clara.
   Los SVG oficiales estan dibujados para fondo blanco: el de Webpay es tinta
   oscura y sobre pizarra desaparece. Teñirlos de blanco los haria legibles
   pero les sacaria el color, que es justo lo que el cliente reconoce -- el
   azul de PayPal, el celeste de Mercado Pago. La placa resuelve las dos cosas
   y es como las publican los propios proveedores.

   Alto fijo y ancho automatico para que las tres placas midan igual: los SVG
   tienen proporciones muy distintas (Webpay 66x22, los otros cuadrados). */
.public-checkout .method-choice .method-logo,
.public-checkout .method-choice .brand-row img {
  height: 20px; width: auto;
  padding: 6px 8px;
  background: var(--pv-logo-plate);
  border-radius: 6px;
}

/* ── El pie de la tarjeta ───────────────────────────────────────────────
   Debajo del boton habia cuatro bloques de gris chico seguidos —que va a
   pasar, el aviso de cambio, las tres garantias y los terminos— todos del
   mismo tamano y del mismo color. Cuatro cosas dichas con la misma voz se
   leen como una sola mancha, y la que importa (que te van a cobrar en otra
   moneda) desaparecia entre las otras tres.

   No se agrega nada: se ordena. El aviso de cambio sube de contraste y se
   apoya en una linea; el resto queda de fondo. */
.public-checkout .pay-methods > .fine { margin: 12px 0 0; }
.public-checkout [data-fx-note] {
  margin-top: 12px;
  padding: 10px 0 10px 14px;
  border-left: 2px solid var(--pv-line);
  color: var(--pv-soft);
  line-height: 1.5;
}
.public-checkout .tp-terms-link { margin-top: 18px; }

/* Via expresa (Smart Buttons) */
.express-divider {
  display: flex; align-items: center; gap: 14px;
  margin: 22px 0 14px; color: var(--pv-faint);
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
}
.express-divider::before, .express-divider::after {
  content: ""; flex: 1; height: 1px; background: var(--pv-line-soft);
}

/* ── Columna lateral: guia, no telon ───────────────────────────────────── */
.public-checkout .checkout-side {
  position: static;
  background: transparent; border: 0; box-shadow: none;
  padding: 36px 8px 0 12px; color: var(--pv-soft);
}
.public-checkout .checkout-side::before { display: none; }
.public-checkout .side-kicker {
  color: var(--pv-faint); font-size: 10px; font-weight: 800;
  letter-spacing: .14em; margin-bottom: 6px;
}
.public-checkout .checkout-side h2 { color: var(--pv-ink); font-size: 16px; font-weight: 720; }
.public-checkout .steps { margin-top: 14px; gap: 14px; }
.public-checkout .steps li { color: var(--pv-soft); font-size: 13px; line-height: 1.55; padding-left: 34px; }
.public-checkout .steps li::before {
  background: var(--pv-tile-bg); color: var(--pv-ink);
  border: 1px solid var(--pv-line); font-weight: 750;
}
.public-checkout .checkout-side .fine {
  position: static;               /* una capa vieja lo clavaba al fondo del telon */
  right: auto; bottom: auto; left: auto;
  margin-top: 22px; padding-top: 16px;
  border-top: 1px solid var(--pv-line-soft);
}

/* ── Inputs (reserva · monto abierto) ──────────────────────────────────── */
.public-checkout label span {
  color: var(--pv-soft); font-size: 11px; font-weight: 750;
  letter-spacing: .08em;
}
.public-checkout input[type="text"],
.public-checkout input[type="email"],
.public-checkout input[type="number"] {
  min-height: 52px; padding: 12px 16px;
  background: var(--pv-tile-bg); color: var(--pv-ink);
  border: 1px solid var(--pv-line); border-radius: var(--pv-radius);
  font-size: 16px;
  transition: border-color .14s ease, box-shadow .14s ease;
}
.public-checkout input:hover { border-color: var(--pv-line-hover); }
.public-checkout input:focus { border-color: var(--pv-accent); box-shadow: var(--pv-focus); outline: 0; }
.public-checkout input::placeholder { color: var(--pv-placeholder); }
#tp-reserva-ref {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  text-transform: uppercase; letter-spacing: .06em;
}
.public-checkout .flash.error {
  background: var(--pv-danger-bg); color: var(--pv-danger-ink);
  border: 1px solid var(--pv-danger-line); box-shadow: none;
  font-size: 13.5px;
}

/* ── Monto abierto ─────────────────────────────────────────────────────── */
.public-checkout .range-label { color: var(--pv-faint); }
.public-checkout .range-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.public-checkout .range-grid button {
  min-height: 58px; background: var(--pv-tile-bg);
  border: 1px solid var(--pv-line); border-radius: var(--pv-radius);
  color: var(--pv-ink); font-size: 15.5px; font-weight: 700;
  font-variant-numeric: tabular-nums; box-shadow: none;
}
.public-checkout .range-grid button:hover {
  border-color: var(--pv-accent); background: var(--pv-accent-soft);
  transform: none; box-shadow: none; color: var(--pv-accent);
}
.public-checkout .range-grid button:focus-visible { outline: 0; box-shadow: var(--pv-focus); }
.public-checkout .range-custom { border-top: 1px solid var(--pv-line-soft); }
.public-checkout .range-currency {
  border: 0; background: transparent; color: var(--pv-faint);
  font-size: 12px; font-weight: 750; padding: 0 4px;
}
.public-checkout .range-field button {
  min-height: 52px; padding: 0 26px; border-radius: var(--pv-radius);
  background: var(--pv-cta-bg); color: var(--pv-cta-ink); font-weight: 720;
}
.public-checkout .range-field button:hover { background: var(--pv-cta-bg-hover); }

/* ── El comprobante y los estados sueltos (.login) ─────────────────────
   `.login` no es un login: es la caja que usan el comprobante y las pantallas
   de error del cliente. La seccion publica le fijaba borde y sombra pero no
   fondo ni color, asi que se quedaba con el `rgba(255,255,255,.94)` de la capa
   del panel. Con el tema claro coincidia de casualidad; con pizarra quedo una
   tarjeta blanca con texto claro adentro -- el monto del comprobante en 1.15
   de contraste, o sea invisible.

   Es la ultima pantalla que ve el cliente, la que a veces guarda. Va con la
   misma tarjeta que el checkout, no con una parecida. */
.login {
  background: var(--pv-card);
  -webkit-backdrop-filter: blur(20px) saturate(1.25);
  backdrop-filter: blur(20px) saturate(1.25);
  color: var(--pv-ink);
  border-radius: 16px; border: 1px solid var(--pv-line);
  box-shadow: var(--pv-shadow);
}
body:has(.login) .login h1,
body:has(.login) .login .muted { color: var(--pv-ink); }
body:has(.login) .login .muted { color: var(--pv-soft); }
body:has(.login) .login .eyebrow { color: var(--pv-accent); }

/* La tabla del comprobante: rotulo, valor y sus lineas. */
body:has(.login) .preview {
  background: var(--pv-sunken);
  border-color: var(--pv-line);
}
/* El rotulo trae fondo propio (`--surface-soft`, casi blanco) y la linea que
   separa las filas es clara. Pintar solo el contenedor no alcanzaba: cada
   rotulo se quedaba con su franja blanca debajo del texto claro -- 1.94 de
   contraste, peor que antes de tocar nada. La cifra la dio el barrido; a ojo
   parecia arreglado. */
body:has(.login) .preview dt,
body:has(.login) .preview dd { border-bottom-color: var(--pv-line-soft); }
body:has(.login) .preview dt { background: transparent; color: var(--pv-soft); }
body:has(.login) .preview dd { color: var(--pv-ink); }
body:has(.login) .ghost,
body:has(.login) .ghost-link {
  background: var(--pv-tile-bg);
  border-color: var(--pv-line);
  color: var(--pv-ink);
  box-shadow: none;
}
body:has(.login) .ghost:hover,
body:has(.login) .ghost-link:hover {
  border-color: var(--pv-accent);
  color: var(--pv-accent);
  background: var(--pv-accent-soft);
}

/* ── Responsive ────────────────────────────────────────────────────────── */
@media (max-width: 1000px) {
  main.public-checkout { grid-template-columns: 1fr; max-width: 640px; gap: 8px; }
  .public-checkout .checkout-side { padding: 26px 8px 0; }
}
@media (max-width: 640px) {
  main.public-checkout { padding: 14px 14px 48px; }
  .public-checkout .checkout-main { padding: 22px 20px 26px; border-radius: 14px; }
  /* La marca no se esconde en el telefono: es la señal de confianza mas barata */
  .public-checkout .brand-lockup > div { display: block; }
  .public-checkout h1 { font-size: 19px; margin-top: 20px; }
  .public-checkout .checkout-main > .muted { font-size: 13px; }
  .pay-amount { font-size: 34px; }
  .pay-meta { gap: 10px 22px; }
  .public-checkout .method-choice span { min-height: 56px; padding: 13px 14px; gap: 11px; }
  .public-checkout .method-choice strong { font-size: 13.5px; }
  .public-checkout .method-choice em { font-size: 13px; }
  /* En pantalla angosta el cluster de marcas baja a su propia linea: si
     compite en la misma fila, aplasta el label a tres lineas. Solo aplica a
     los tiles del hub (los que TIENEN cluster, via :has); los del checkout
     mantienen su fila unica de logo + nombre + monto. Un navegador viejo sin
     :has se queda con la fila unica apretada: funcional, solo menos aireado. */
  .public-checkout .method-choice span:has(.brand-row) {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    row-gap: 9px;
  }
  .public-checkout .method-choice span:has(.brand-row) strong { grid-column: 2; }
  .public-checkout .method-choice span:has(.brand-row) em { grid-column: 3; }
  .public-checkout .method-choice span:has(.brand-row) .brand-row {
    grid-column: 2 / 4; grid-row: 2;
    justify-content: flex-start; margin: 0;
  }
  .public-checkout .range-grid { grid-template-columns: 1fr 1fr; }
  .public-checkout .trust-strip span { width: auto; justify-content: flex-start; }
  .public-checkout .checkout-actions button { min-height: 54px; }
}

/* ── En papel, el comprobante vuelve a claro ────────────────────────────
   El comprobante es la última pantalla del cliente y la que a veces imprime o
   guarda en PDF: un fondo oscuro gasta un cartucho y se lee peor.

   Se redefinen los TOKENS, no se pisan las reglas una por una. El bloque de
   `@media print` que ya existía más arriba forzaba `body { background: #fff }`
   con `!important`, pero no la tarjeta — que hasta ahora salía blanca de pura
   suerte, porque `--pv-card` era blanco. Con el tema oscuro esa suerte se
   terminó, y el arreglo tiene que ser el mismo mecanismo que el tema: los
   tokens.

   Va DESPUÉS de la sección pública a propósito: misma especificidad, gana el
   último. */
@media print {
  :root {
    --pv-bg: #ffffff;
    --pv-card: #ffffff;
    --pv-card-solid: #ffffff;
    --pv-tile-bg: #ffffff;
    --pv-sunken: #ffffff;
    --pv-ink: #101f30;
    --pv-soft: #414d58;
    --pv-faint: #5c6874;
    --pv-line: rgba(16, 31, 48, .28);
    --pv-line-soft: rgba(16, 31, 48, .16);
    --pv-accent: #8a4a17;
    --pv-accent-soft: #ffffff;
    --pv-control-bg: #ffffff;
    --pv-control-line: rgba(16, 31, 48, .45);
    --pv-mark-bg: #101f30;
    --pv-mark-ink: #ffffff;
    --pv-mark-shadow: none;
    --pv-shadow: none;
    --pv-logo-plate: transparent;  /* en papel el fondo ya es blanco */
  }
  body:has(main.public-checkout),
  body:has(.login) {
    background: #fff !important;
    color: var(--pv-ink);
  }
  /* El vidrio en papel es una mancha gris. Las DOS tarjetas: la del checkout
     y la del comprobante, que es la que de verdad se imprime. */
  .public-checkout .checkout-main,
  .login {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* ═════════════════════════════════════════════════════════════════════════
   SISTEMA · tokens semánticos, escalas y utilidades
   ═════════════════════════════════════════════════════════════════════════

   Fase 2 del rediseño del panel. Esta sección NO cambia cómo se ve nada:
   cada token toma el valor que ya estaba en pantalla. Es a propósito — si
   algo se rompe con este cambio, sabemos que fueron los tokens y no un
   rediseño encima.

   ── El problema que resuelve ──────────────────────────────────────────

   El panel ya estaba tokenizado, pero los tokens se llamaban por cómo se
   ven, no por lo que dicen: `--mint`, `--amber`, `--violet`, `--rose`.
   Nombrar por apariencia tiene dos costos que ya se pagaron acá:

     · El mismo color termina significando cosas distintas. `--mint` marca
       "entorno productivo" (semántico) y también el borde del tercer tile
       de KPI (decorativo, sólo porque es el tercero).

     · Y los estados terminan escritos con hex sueltos, porque ningún token
       se llamaba como el estado. Los tres chips —éxito, atención, crítico—
       llevan tres hex cada uno, repetidos en tres capas de CSS.

   Ahora hay un nombre por SIGNIFICADO. Los viejos siguen existiendo como
   valores crudos de la paleta; se van cuando no queden usos.

   ── Los estados vienen de a cuatro ────────────────────────────────────

   Un estado no es un color, son cuatro: el sólido (puntos, barras), el
   fondo suave, el borde y el texto sobre ese fondo. Con un solo token por
   estado, quien pinta un chip termina inventando los otros tres —que es
   exactamente cómo aparecieron los hex sueltos.

   ── Tema oscuro ───────────────────────────────────────────────────────

   Todavía no. El panel arrastra un tema oscuro muerto debajo del claro
   (dos capas de CSS que se sobrescriben), y agregar un tercero encima
   sería apilar sobre el problema. Estos tokens están armados para que el
   día que esas capas se limpien, el tema oscuro sea redefinir este bloque
   y nada más.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
    /* ── Superficies y texto ────────────────────────────────────────── */
    --bg: var(--canvas);              /* fondo de la página */
    --surface-1: var(--surface);      /* tarjetas, paneles, tiles */
    --surface-2: var(--surface-soft); /* cabeceras de tabla, zonas hundidas */
    --border: var(--line);            /* borde por defecto */
    --border-strong: var(--line-strong);
    --text: var(--ink);               /* texto primario */
    --text-2: var(--ink-soft);        /* secundario: descripciones */
    --text-3: var(--muted);           /* terciario: labels, pies */

    /* ── Acento de marca · SOLO acciones primarias ──────────────────── */
    /* Cobre, el mismo de las pantallas del cliente.
       El `TP` era cobre para quien paga y azul marino para quien opera: el
       mismo logo dibujado de dos maneras. Un producto, una marca.

       Y son DOS coppers por el mismo motivo que hay dos grises: #a8542a da
       5.29 sobre blanco y 3.38 sobre el rail; el claro da 6.29 sobre el rail
       y 2.84 sobre blanco. Ninguno sirve para los dos fondos. */
    --accent: #a8542a;          /* sobre superficie clara */
    --accent-on-dark: #e59a5b;  /* sobre el rail y el checkout */
    --accent-ink: #ffffff;
    --accent-bg: #eef0fe;

    /* ── Estados · el color dice qué pasa, nunca decora ─────────────── */
    /* Éxito · pagado · conciliado · entorno productivo */
    --ok: #18a779;
    --ok-bg: #effbf7;
    --ok-border: #bce7d8;
    --ok-ink: #087653;

    /* Atención · saldo pendiente · por vencer · entorno de prueba */
    --warn: #e9a23b;
    --warn-bg: #fff9eb;
    --warn-border: #f2daa9;
    --warn-ink: #946018;

    /* Crítico · revocado · fallido · acción destructiva */
    --danger: #d94a70;
    --danger-bg: #fff4f7;
    --danger-border: #f3c6d1;
    --danger-ink: #a72a4d;

    /* Informativo · en proceso · avisos neutros */
    --info: #0aa6c2;
    --info-bg: #effbfd;
    --info-border: #bde3eb;
    --info-ink: #176277;

    /* ── Tipografía · seis pasos, ni uno más ────────────────────────── */
    --fs-micro: 11px;   /* labels en mayúsculas, pies */
    --fs-small: 12px;   /* texto de ayuda, celdas secundarias */
    --fs-body: 14px;    /* cuerpo · tamaño base del panel */
    --fs-lead: 16px;    /* entradillas */
    --fs-title: 20px;   /* títulos de panel */
    --fs-display: 26px; /* la cifra de un KPI */

    /* ── Espaciado · múltiplos de 4 ─────────────────────────────────── */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 20px;
    --sp-6: 24px;
    --sp-8: 32px;

    /* ── Forma · dos radios, y ya ───────────────────────────────────── */
    --radius-control: 6px;   /* botones, inputs, chips */
    --radius-surface: 8px;   /* tarjetas, paneles, tablas */

    /* ── Elevación · dos niveles, no más ────────────────────────────── */
    /* La sombra marca una capa real: apoyado en la página, o flotando
       sobre ella. Un tercer nivel no se distingue y sólo agrega ruido. */
    --elev-1: 0 1px 2px rgba(7, 24, 43, .05), 0 10px 30px rgba(7, 24, 43, .05);
    --elev-2: 0 22px 70px rgba(7, 24, 43, .16), 0 4px 14px rgba(7, 24, 43, .08);
}

/* ── Dinero ─────────────────────────────────────────────────────────────
   `tabular-nums` no es cosmético: sin él cada dígito trae su propio ancho,
   las columnas de plata dejan de alinear y una cifra que se actualiza
   "salta" al cambiar. Es obligatorio en todo número que viva en columna. */
.money,
.kpi strong,
td.money,
th.money {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* `nowrap` porque un monto partido en dos líneas deja de leerse como un
   número: "USD 9.629," arriba y "00" abajo son dos cosas.

   OJO con dónde se aplica. `.kpi` tiene `overflow: hidden`, así que en el
   tile un `nowrap` no impide el corte: lo empeora. Hoy el tile "Cobrado"
   muestra dos monedas en un solo valor y envuelve; con `nowrap` quedaría
   RECORTADA — media cifra de plata, sin aviso, en producción.
   Envolver es feo; recortar es mentir.

   Por eso el tile todavía no lo lleva. Llega en la Fase 3, junto con la
   separación en dos tiles, que es lo que quita el motivo para envolver. */
.money,
td.money,
th.money {
    white-space: nowrap;
}

/* La moneda acompaña, el número manda. */
.money .cur {
    font-size: .82em;
    font-weight: 600;
    color: var(--text-3);
    letter-spacing: .02em;
}

/* Columna de plata: siempre a la derecha, para que los órdenes de
   magnitud se comparen de un vistazo. */
td.money,
th.money {
    text-align: right;
}

/* ── Foco ───────────────────────────────────────────────────────────────
   Un panel que se opera con teclado necesita saber dónde está parado.
   Va sobre :focus-visible para no molestar al clic con mouse. */
.money:focus-visible,
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-control);
}

/* ═════════════════════════════════════════════════════════════════════════
   FASE 3 · componentes contra los tokens
   ═════════════════════════════════════════════════════════════════════════ */

/* ── Tiles de KPI ───────────────────────────────────────────────────────
   Tres reglas, y las tres vienen de un problema visto en pantalla:

     · Altura idéntica. El tile "Cobrado" traía dos monedas en un solo
       valor, envolvía a dos líneas y estiraba la fila entera. Ahora va una
       moneda por tile y el alto se fija acá, para que ningún número futuro
       pueda volver a descuadrar la fila.

     · El color dice el estado. Ver el comentario de `tp_kpi()`.

     · Jerarquía interna: label discreto → cifra → contexto. Los tres
       niveles tienen que distinguirse entre sí o el tile se lee como un
       bloque de texto. */

.kpis {
    /* `auto-fit` en vez de cuatro columnas fijas: la cantidad de tiles ya no
       es cuatro, depende de en cuántas monedas haya plata. Con columnas
       fijas, un quinto tile se metía en una fila nueva de ancho completo.

       240px, y el numero sale de medir, no de elegir. Con 180 entraban los
       cinco tiles en una fila — y "USD 9.629,00" a 26px se RECORTABA contra
       el `overflow: hidden` del tile: se leia "9.629,0(".

       210 arreglo ESE caso y dejo otro peor: "CLP 15.400.000" —un grupo grande
       cotizado en pesos— pide 202px y recibia 175. La medicion anterior se
       hizo contra el monto equivocado.

       Y el patron no es el que uno supone: con 210 el recorte aparecia a 1920,
       1440 y 1280 pero NO a 1366 ni a 1100. No depende del tamaño de pantalla
       sino de donde cae el salto de fila — cuantas mas columnas entran, mas
       angosta es cada una. Por eso se prueba en varios anchos y no en uno.

       230 es el minimo que no recorta en ninguno; 240 da el mismo reparto de
       columnas con margen. Entre un tile mas por fila y la cifra completa,
       gana la cifra completa: envolver es feo; recortar plata es mentir. */
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.kpi {
    display: flex;
    flex-direction: column;
    /* El contexto queda pegado abajo aunque la cifra sea corta: así las tres
       líneas de todos los tiles caen a la misma altura y la fila se lee como
       una fila, no como cuatro cajas sueltas. */
    justify-content: flex-start;
}

/* El label reserva DOS líneas, ocupe una o dos.
   Visto en una captura: "COTIZACIONES" ocupa una línea y "RESERVAS CON PAGOS"
   dos, así que el 48 y el 12 quedaban a distinta altura y la fila se leía
   torcida. Los tiles medían igual —eso ya estaba— pero sus cifras no
   arrancaban en el mismo renglón, que es lo que el ojo compara. */
.kpi span {
    min-height: 2.1em;
}

.kpi strong {
    /* Ahora sí. Con una moneda por tile ya no hay motivo para envolver, así
       que `nowrap` protege sin recortar. Ver el comentario del bloque del
       sistema sobre por qué no podía ir antes. */
    white-space: nowrap;
    margin-top: 0;
    padding-top: var(--sp-2);

    /* Y si aun así no entra, que se NOTE.
       Medido: `CLP 15.400.000` —un grupo grande cotizado en pesos— pide 202px
       y el tile da 192. Sin esto, `overflow: hidden` se comía el último dígito
       en silencio y "15.400.000" se leía como "15.400.00". Una cifra de plata
       recortada sin aviso es la peor falla posible en esta pantalla.

       Con puntos suspensivos el recorte se anuncia solo: quien lo ve sabe que
       falta algo y va a buscarlo. El valor completo está en el `title`. */
    overflow: hidden;
    text-overflow: ellipsis;
}

/* El contexto se pega abajo: con la cifra fija arriba y el contexto fijo
   abajo, los tres niveles caen a la misma altura en todos los tiles. */
.kpi em {
    margin-top: auto;
    padding-top: var(--sp-2);
}

/* La moneda acompaña; el número manda — al lado, no arriba.
   `display: inline` no sobra: una de las capas viejas declara
   `.kpi span, .kpi em, label span { display: block }`, y ese selector también
   agarra al span de la moneda. Resultado medido: `CLP` caía en su propio
   renglón y el número quedaba 27px más abajo que el `48` del tile de al lado.
   Los tiles medían igual y las cifras no arrancaban juntas. */
.kpi strong .cur {
    display: inline;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-3);
    letter-spacing: .04em;
}

/* Sin datos: una raya, no un cero. Un cero afirma que se cobró cero; la raya
   dice que todavía no hay nada, que es distinto. */
.kpi-none {
    color: var(--text-3);
    font-weight: 500;
}

/* La barra de estado, por tono. Neutro no lleva color: si todo lleva color,
   ninguno destaca. */
.kpi[data-tone="neutral"]:before { background: var(--border-strong); }
.kpi[data-tone="ok"]:before      { background: var(--ok); }
.kpi[data-tone="warn"]:before    { background: var(--warn); }
.kpi[data-tone="danger"]:before  { background: var(--danger); }
.kpi[data-tone="info"]:before    { background: var(--info); }

/* ── Chips de estado ────────────────────────────────────────────────────
   Los mismos tokens que todo lo demás. Antes eran tres hex sueltos por
   chip, repetidos en tres capas de CSS: cambiar el verde de "pagado"
   exigía encontrar los tres. */
.status-pill {
    border-radius: var(--radius-control);
}

.status-pill.success {
    border-color: var(--ok-border);
    background: var(--ok-bg);
    color: var(--ok-ink);
}

.status-pill.warning {
    border-color: var(--warn-border);
    background: var(--warn-bg);
    color: var(--warn-ink);
}

.status-pill.danger {
    border-color: var(--danger-border);
    background: var(--danger-bg);
    color: var(--danger-ink);
}

/* ── Formulario del panel · Fase 4 ──────────────────────────────────────
   El label nombra el campo; la aclaración va debajo. Un label de dos
   líneas no es un label largo: es una aclaración en el lugar equivocado,
   y descuadra la grilla del formulario. */

.field-help {
    display: block;
    margin-top: var(--sp-1);
    color: var(--text-3);
    font-size: var(--fs-micro);
    line-height: 1.45;
}

/* Campos de la misma fila: misma altura y misma línea base, tengan o no
   texto de ayuda. Sin esto, el que lleva ayuda empuja al de al lado. */
.form-grid .field {
    display: flex;
    flex-direction: column;
    align-self: start;
}

.form-grid .field input,
.form-grid .field select {
    /* El control queda pegado abajo del label aunque el label envuelva:
       así todos los inputs de la fila arrancan a la misma altura. */
    margin-top: auto;
}

/* Un campo oculto no ocupa lugar — pero su valor SE SIGUE ENVIANDO.
   `hidden` es display:none, no `disabled`. Ver assets/panel-form.js. */
.form-grid .field[hidden] {
    display: none;
}

/* ── Reglas de cálculo, fuera del flujo de captura ──────────────────────
   Eran tres párrafos entre el último campo y el botón. La documentación no
   vive dentro de un formulario: el último elemento del form tiene que ser
   la acción, no un texto que nadie lee dos veces. */

.panel-help {
    margin-top: var(--sp-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-surface);
    background: var(--surface-2);
}

.panel-help > summary {
    padding: var(--sp-3) var(--sp-4);
    color: var(--text-2);
    font-size: var(--fs-small);
    font-weight: 700;
    cursor: pointer;
    list-style-position: inside;
}

.panel-help > summary:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
    border-radius: var(--radius-surface);
}

.panel-help[open] > summary {
    border-bottom: 1px solid var(--border);
}

.panel-help p {
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    color: var(--text-2);
    font-size: var(--fs-small);
    line-height: 1.6;
}

.panel-help p + p {
    padding-top: 0;
}

.panel-help strong {
    color: var(--text);
}

/* ── Franja de entorno · Fase 5 ─────────────────────────────────────────
   Eran dos banners apilados que se comían la primera pantalla: había que
   bajar para ver una sola cifra. Un aviso permanente que tapa los datos
   deja de leerse a la semana, y encima empuja hacia abajo lo que se vino
   a mirar. El de cobro real se queda —es una advertencia de producción—
   pero en una línea. */

.env-strip {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-1) var(--sp-2);
    align-items: baseline;
    margin: 0 0 var(--sp-3);
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--info-border);
    border-radius: var(--radius-control);
    background: var(--info-bg);
    color: var(--info-ink);
    font-size: var(--fs-small);
    line-height: 1.4;
}

.env-strip.live {
    border-color: var(--danger-border);
    background: var(--danger-bg);
    color: var(--danger-ink);
}

.env-strip strong {
    font-weight: 800;
}

/* ── Nota dentro de un panel ────────────────────────────────────────────
   Para los avisos que explican la sección donde están, en vez de vivir
   arriba de todo tapando los datos. */

.panel-note {
    margin: 0 0 var(--sp-4);
    padding: var(--sp-2) var(--sp-3);
    border-left: 3px solid var(--border-strong);
    border-radius: 0 var(--radius-control) var(--radius-control) 0;
    background: var(--surface-2);
    color: var(--text-2);
    font-size: var(--fs-small);
    line-height: 1.55;
}

.panel-note.ok   { border-left-color: var(--ok);   background: var(--ok-bg);   color: var(--ok-ink); }
.panel-note.warn { border-left-color: var(--warn); background: var(--warn-bg); color: var(--warn-ink); }
.panel-note strong { font-weight: 800; }

/* ── La celda del link ──────────────────────────────────────────────────
   La URL entera hacía crecer la columna y empujaba la tabla a lo ancho.
   Se trunca; el botón de copiar da la URL completa sin mostrarla. */

.link-cell {
    max-width: 280px;
}

.link-cell input {
    width: 100%;
    min-height: 32px;
    padding: 4px 8px;
    border: 1px solid var(--border);
    border-radius: var(--radius-control);
    background: var(--surface-2);
    color: var(--text-2);
    font-size: var(--fs-micro);
    /* La URL se corta con puntos suspensivos en vez de estirar la columna. */
    text-overflow: ellipsis;
}

.link-cell .copy-link {
    margin-top: var(--sp-1);
    min-height: 28px;
    padding: 3px 9px;
    font-size: var(--fs-micro);
}

.link-cell .copy-link.is-done {
    border-color: var(--ok-border);
    background: var(--ok-bg);
    color: var(--ok-ink);
}

/* ── Acciones de fila · la destructiva se ve distinta ───────────────────
   "Revocar" no puede parecerse a "Ver pago". Una abre una pantalla; la
   otra deja un link inservible para siempre. */

.row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    align-items: center;
}

.row-actions form {
    display: inline;
    margin: 0;
}

.row-actions .danger {
    border-color: var(--danger-border);
    background: transparent;
    color: var(--danger-ink);
    font-weight: 700;
}

.row-actions .danger:hover,
.row-actions .danger:focus-visible {
    border-color: var(--danger);
    background: var(--danger-bg);
    color: var(--danger-ink);
}

/* ── Montos en tabla ────────────────────────────────────────────────────
   A la derecha y con cifras tabulares, para comparar órdenes de magnitud
   de un vistazo. `small` es el "de USD X" del total de la cotización. */

td.money strong {
    display: block;
    font-variant-numeric: tabular-nums;
}

td.money small {
    display: block;
    margin-top: 2px;
    color: var(--text-3);
    font-variant-numeric: tabular-nums;
}

/* ── El atributo `hidden` gana siempre ──────────────────────────────────
   Encontrado mirando una captura del panel: el botón "Copiar" de la tabla
   nace con `hidden` y se veía igual.

   El motivo es de cascada. El navegador trae `[hidden] { display: none }`,
   pero eso vive en su hoja de estilos por defecto — la de menor prioridad.
   Cualquier regla del sitio que fije `display` le gana, y `.ghost` fija
   `display: inline-flex`. O sea que en TODO botón `.ghost`, el atributo
   `hidden` no hacía nada.

   No es sólo el botón nuevo: el de imprimir del comprobante
   (`data-receipt-print hidden`) usa el mismo patrón desde antes, y venía
   mostrándose aunque su script no hubiera corrido. Justo el "botón muerto"
   que el patrón existía para evitar.

   `!important` acá está bien puesto y es de los pocos lugares donde lo
   está: `hidden` no es una sugerencia de estilo, es "esto no existe para
   el usuario". Nada debería poder contradecirlo. */
[hidden] {
    display: none !important;
}
