/* ============================================================
   brand.css — la hoja de estilos de ADOS y Alianz Virtual (spec #261, ADR 0026, docs/brand.md).

   Una copia en cada sitio: sites/app/brand.css y sites/ados/brand.css, iguales byte por byte
   (la revisión del gancho lo exige). Un cambio se hace en las dos. Las páginas la ligan sin ?v=:
   el navegador pregunta en cada carga si cambió (ops/TRAPS.md, la caché de Cloudflare).

   Cómo la usa una página:
     <html lang="es" data-device="phone|tablet|desktop">   el aparato elige la escala
     la hoja va antes del <style> propio de la página, que usa solo estas variables.

   Aquí, y solo aquí, se escriben colores. Fondo blanco, sin sombras, bordes finos.
   ============================================================ */

/* ---------- Colores: la paleta de brand.md, nada más ---------- */
:root {
  --navy: #0E1B2D;
  --navy-deep: #08111F;
  --gold: #C9A961;
  --cream: #F2EDE4;
  --cream-line: #E4DCCD;
  --white: #FFFFFF;
  --text: #0E1B2D;
  --muted: #6B645A;
  --line: #E8E2D7;
  --tint: #FAF7F1;
  --neutral-soft: #F0EBE2;
  --green: #2F6B4F;
  --green-soft: #E4EFE8;
  --amber: #8A5A12;
  --amber-soft: #F7ECD6;
  --red: #A3342B;
  --red-soft: #F7E6E3;
  /* Velo sobre la pantalla detrás de una hoja abierta: el azul, transparente. */
  --scrim: rgba(14, 27, 45, .45);
  /* Sobre azul: fila activa de la barra lateral. */
  --on-navy-hover: rgba(255, 255, 255, .08);
  --on-navy-muted: rgba(255, 255, 255, .72);
  /* Sobre azul: borde fino y fondo al pasar el ratón de una tarjeta (el selector de cuenta de ADOS). */
  --on-navy-line: rgba(255, 255, 255, .14);

  /* ---------- Letra ---------- */
  --serif: 'Playfair Display', Georgia, serif;
  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  /* ---------- Espacios ---------- */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 20px;
  --s6: 24px;
  --s7: 32px;
  --s8: 48px;

  /* ---------- Esquinas ---------- */
  --r-field: 10px;
  --r-btn: 12px;
  --r-card: 14px;
  --r-pill: 999px;

  /* ---------- Escala del celular (también la de una página sin aparato) ---------- */
  --title: 28px;
  --name: 20px;
  --body: 15px;
  --small: 13px;
  --label: 12px;
  --btn: 16px;
  --big: 44px;
  --btn-h: 52px;
  --field-h: 48px;
  --field-text: 16px;   /* con menos de 16 px, el navegador del celular acerca la pantalla al poner el cursor en el campo */
  --pad: var(--s5);
}

/* Tablet del juez: se lee a un brazo de distancia, de pie. Botón del alto del celular. */
:root[data-device="tablet"] {
  --title: 32px;
  --name: 24px;
  --body: 18px;
  --small: 15px;
  --label: 14px;
  --btn: 20px;
  --big: 96px;
  --btn-h: 52px;
  --field-text: 18px;
  --pad: var(--s7);
}

/* Computadora. */
:root[data-device="desktop"] {
  --title: 28px;
  --name: 20px;
  --body: 14px;
  --small: 13px;
  --label: 12px;
  --btn: 14px;
  --big: 28px;
  --btn-h: 40px;
  --field-text: 14px;
  --pad: var(--s7);
}
/* Una página de computadora abierta con el dedo (la entrada de pista en la tablet o en el teléfono): campos de 16 px,
   para que el navegador no acerque la pantalla al poner el cursor. */
@media (pointer: coarse) {
  :root[data-device="desktop"] { --field-text: 16px; }
}

/* ---------- Escala de la hoja del número ---------- */
/* La hoja carta que se imprime y se dobla en tres (#340, #362): mide lo mismo en cualquier aparato, porque es papel.
   La usan Alianz Virtual y la página del club. */
:root {
  --sheet-micro: 10px;     /* etiqueta de celda, doblez, esquinas */
  --sheet-label: 11px;     /* federación, «Número», pie */
  --sheet-cell: 12.5px;    /* dato de una celda */
  --sheet-text: 13px;      /* fecha, Número ACW, línea bajo el número */
  --sheet-event: 20px;     /* nombre del evento */
  --sheet-name: 22px;      /* nombre del ejemplar */
  --sheet-tab: 30px;       /* el número arriba a la derecha */
  --sheet-number: 236px;   /* el número grande del tercio de abajo */
}

/* ---------- Base ---------- */
/* Lo escondido se queda escondido: .btn, .notice y otras piezas ponen display, que le gana al
   atributo hidden. Una página muestra y esconde con hidden, no con style.display. */
[hidden] { display: none !important; }

/* Dos toques rápidos (marcar números seguidos en el pase de lista) no acercan la pantalla; pellizcar sí. Va en la página
   y en lo que se toca, porque Chrome lo lee en el elemento tocado y en los de arriba. */
html, button, a, label, input, textarea, select, [onclick], [role="button"] { touch-action: manipulation; }

body {
  background: var(--white);
  color: var(--text);
  font-family: var(--sans);
  font-size: var(--body);
  line-height: 1.4;
  -webkit-text-size-adjust: 100%;
}

/* ---------- Letra ---------- */
/* Título de pantalla. */
.t-title { font-family: var(--serif); font-weight: 600; font-size: var(--title); line-height: 1.15; }
/* Nombres: perro, exposición, categoría, título, «Número 49». Pesan como un nombre en Inter 600. */
.t-name { font-family: var(--serif); font-weight: 700; font-size: var(--name); line-height: 1.2; font-size-adjust: ex-height 0.546; }
/* Dato secundario. */
.t-small { font-size: var(--small); color: var(--muted); }
/* Etiqueta de sección. */
.t-section { font-size: var(--label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
/* Número grande: en Inter, cifras del mismo ancho. */
.t-big { font-family: var(--sans); font-weight: 700; font-size: var(--big); line-height: 1; font-variant-numeric: tabular-nums; }
/* Cifras en columna: fechas, registros, montos. */
.num { font-family: var(--sans); font-variant-numeric: tabular-nums; }

/* ---------- Botones ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  box-sizing: border-box;
  min-height: var(--btn-h);
  padding: 0 var(--s5);
  border: 0;
  border-radius: var(--r-btn);
  font: 600 var(--btn)/1.2 var(--sans);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
}
.btn-primary { background: var(--navy); color: var(--white); }
.btn-secondary { background: var(--white); color: var(--navy); box-shadow: inset 0 0 0 1px var(--navy); }
.btn-danger { background: var(--red); color: var(--white); }
/* Peligro callado: blanco con la letra y el borde rojos, sin el bloque rojo lleno. Una acción de peligro que no es la
   de la pantalla, junto a un dato («Cerrar inscripciones en línea», #359). */
.btn-danger-quiet { background: var(--white); color: var(--red); box-shadow: inset 0 0 0 1px var(--red); }
/* El principal sobre un fondo azul: blanco con letra azul. */
.btn-on-navy { background: var(--white); color: var(--navy); }
.btn:disabled, .btn[aria-disabled="true"], .btn.is-disabled { opacity: .4; cursor: default; pointer-events: none; }
.btn:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
/* Botón que ocupa el ancho. */
.btn-block { display: flex; width: 100%; }
/* Botón chico: una acción sobre un dato de una fila (copiar, ver completo), no la acción de la pantalla. */
:root { --btn-small-h: 40px; }
.btn-small { min-height: var(--btn-small-h); padding: 0 var(--s4); font-size: var(--small); }

/* Grupo de botones: el principal primero en el HTML. En celular y tablet van en columna, el
   principal arriba; en computadora en fila, a la derecha, el secundario a la izquierda. */
.actions { display: flex; flex-direction: column; gap: var(--s2); }
.actions > .btn { width: 100%; }
:root[data-device="desktop"] .actions { flex-direction: row-reverse; justify-content: flex-start; }
:root[data-device="desktop"] .actions > .btn { width: auto; }
/* dos botones en una línea, el secundario a la izquierda («Volver» · «Firmar libro»), también en el teléfono */
.actions.actions-row { flex-direction: row; }
.actions.actions-row > .btn { flex: 1; width: auto; }

/* ---------- Tarjetas ---------- */
.card { box-sizing: border-box; background: var(--white); border: 1px solid var(--line); border-radius: var(--r-card); padding: var(--s4); }
/* La tarjeta destacada: una por pantalla, la elige la spec de cada pantalla. */
.card-featured { background: var(--cream); border-color: var(--cream-line); }
/* Tarjeta que solo lleva filas: la fila pone su propio aire arriba y abajo. */
.card-rows { padding-top: var(--s1); padding-bottom: var(--s1); }

/* ---------- Fila etiqueta–valor ---------- */
.kv { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); padding: var(--s3) 0; border-bottom: 1px solid var(--line); }
.kv:last-child { border-bottom: 0; }
.card-featured .kv { border-bottom-color: var(--cream-line); }
.card-featured .kv:last-child { border-bottom: 0; }
.kv-label { color: var(--muted); }
.kv-value { font-weight: 500; text-align: right; font-variant-numeric: tabular-nums; }
/* Una línea debajo de la fila, dentro de la misma fila: <div class="kv kv-has-note">…</div><div class="kv-note">…</div>. */
.kv-has-note { border-bottom: 0; padding-bottom: 0; }
.kv-note { padding: var(--s1) 0 var(--s3); border-bottom: 1px solid var(--line); font-size: var(--small); color: var(--muted); }

/* ---------- Fila de lista ---------- */
/* Un renglón sin etiqueta (un título, un logro, una frase), con el aire y la línea de la fila etiqueta–valor. */
.list-row { padding: var(--s3) 0; border-bottom: 1px solid var(--line); }
.list-row:last-child, .kv-note:last-child { border-bottom: 0; }
.card-featured .list-row, .card-featured .kv-note { border-bottom-color: var(--cream-line); }

/* ---------- Fila con número ---------- */
/* El número de catálogo en su columna a la izquierda (Inter 700, cifras del mismo ancho) y, a la derecha, el nombre,
   sus sellos y sus datos (spec #334): <div class="num-row"><span class="num-row-n">47</span><div class="num-row-text">…</div></div>.
   La fila elegida (el perro del socio) lleva .is-selected: el fondo de fila elegida, como en las tablas. */
:root { --num-col: 44px; }
.num-row { display: flex; gap: var(--s3); padding: var(--s3) var(--s2); border-bottom: 1px solid var(--line); }
.num-row:last-child { border-bottom: 0; }
.num-row-n { flex: none; min-width: var(--num-col); font: 700 var(--name)/1.2 var(--sans); font-variant-numeric: tabular-nums; }
.num-row-text { flex: 1; min-width: 0; }
.num-row-text .t-small { display: block; margin-top: 2px; }
.num-row.is-selected { background: var(--tint); }

/* ---------- Sellos ---------- */
.seal {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  font: 600 var(--label)/1.2 var(--sans);
  white-space: nowrap;
}
/* VERIFICADO: azul, letra blanca, palomita dorada (<span class="check">✓</span>). */
.seal-verified { background: var(--navy); color: var(--white); }
.seal-verified .check { color: var(--gold); }
/* La palomita como ícono de trazo (<span class="check"><svg>…</svg></span>), para que el texto del sello sea solo la palabra. */
.seal .check svg { display: block; width: 1em; height: 1em; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.seal-neutral { background: var(--neutral-soft); color: var(--muted); }
.seal-green { background: var(--green-soft); color: var(--green); }
.seal-amber { background: var(--amber-soft); color: var(--amber); }
.seal-red { background: var(--red-soft); color: var(--red); }
/* «Tuyo»: el perro del socio en una lista de otros (#252). Azul, letra blanca y el punto dorado:
   <span class="seal seal-mine"><span class="seal-dot"></span>Tuyo</span>. */
:root { --seal-dot: 6px; }
.seal-mine { background: var(--navy); color: var(--white); }
.seal-mine .seal-dot { flex: none; width: var(--seal-dot); height: var(--seal-dot); border-radius: 50%; background: var(--gold); }

/* ---------- Franja de estado ---------- */
/* El estado a todo lo ancho de la columna, con su frase (spec #279). VERIFICADO: azul, letra blanca y
   la palomita dorada (<span class="status-strip-check"><svg>…</svg></span>). SIN VERIFICAR: el fondo
   suave neutro, letra azul, sin palomita. */
:root { --status-check: 28px; }
.status-strip { display: flex; align-items: center; gap: var(--s3); padding: var(--s4); border-radius: var(--r-card); }
.status-strip-word { font: 700 var(--name)/1.1 var(--sans); letter-spacing: .04em; }
.status-strip-line { margin-top: var(--s1); font-size: var(--small); line-height: 1.35; }
.status-strip-check { flex: none; display: flex; width: var(--status-check); height: var(--status-check); color: var(--gold); }
.status-strip-check svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.status-strip-verified { background: var(--navy); color: var(--white); }
.status-strip-verified .status-strip-line { color: var(--on-navy-muted); }
.status-strip-neutral { background: var(--neutral-soft); color: var(--navy); }
.status-strip-neutral .status-strip-line { color: var(--muted); }

/* ---------- Campos ---------- */
/* El aro rojo de un campo con error (y de lo que se marca igual, como el cuadro para subir una portada). */
:root { --ring-error: 1.5px; }
.field + .field { margin-top: var(--s4); }
.field > label, .field-label { display: block; margin-bottom: var(--s2); font-size: var(--small); font-weight: 500; }
.input, .field input:not([type="checkbox"]):not([type="radio"]), .field select, .field textarea {
  box-sizing: border-box;
  width: 100%;
  min-height: var(--field-h);
  padding: 0 var(--s3);
  background: var(--white);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--r-field);
  font: 400 var(--field-text) var(--sans);
  font-variant-numeric: tabular-nums;
  outline: none;
}
.field textarea, textarea.input { padding: var(--s3); line-height: 1.4; }
.input::placeholder, .field input::placeholder, .field textarea::placeholder { color: var(--muted); }
.input:focus, .field input:focus, .field select:focus, .field textarea:focus { border-color: transparent; box-shadow: 0 0 0 2px var(--navy); }
.field.is-error .input, .field.is-error input, .field.is-error select, .field.is-error textarea,
.input.is-error { border-color: transparent; box-shadow: 0 0 0 var(--ring-error) var(--red); }
.field-hint { margin-top: 6px; font-size: var(--small); color: var(--muted); }
.field-error, .field.is-error .field-hint { margin-top: 6px; font-size: var(--small); color: var(--red); }
/* «Opcional» en la etiqueta de un campo que se puede dejar vacío (#366): sin asteriscos en los obligatorios. */
.field-opt { font-weight: 400; color: var(--muted); }
/* El buscador sobre una lista (la raza del registro, #366): el campo y, debajo, las opciones que coinciden, cada una con
   su dato secundario a la derecha (el grupo). Sin coincidencias, .pick-empty. La página pone y quita [hidden]. */
.pick { position: relative; }
.pick-list { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 30; max-height: 260px; overflow-y: auto; background: var(--white); border: 1px solid var(--line); border-radius: var(--r-field); }
.pick-opt { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); box-sizing: border-box; width: 100%; min-height: var(--tap); padding: var(--s3) var(--s4); border: 0; border-bottom: 1px solid var(--line); background: none; color: var(--text); font: 400 var(--body)/1.3 var(--sans); text-align: left; cursor: pointer; }
.pick-opt:last-child { border-bottom: 0; }
.pick-opt.is-active, .pick-opt:hover { background: var(--tint); }
.pick-opt small { flex: none; font-size: var(--small); color: var(--muted); white-space: nowrap; }
.pick-empty { padding: var(--s3) var(--s4); color: var(--muted); }

/* ---------- Avisos ---------- */
/* Listo (verde), pendiente (ámbar), error (rojo). El ícono va a la izquierda y lo pone la hoja:
   la página solo escribe la frase. */
.notice { position: relative; display: block; padding: var(--s3) var(--s3) var(--s3) calc(var(--s3) + 18px + var(--s2)); border-radius: var(--r-field); font-size: var(--small); line-height: 1.4; }
.notice::before { content: ""; position: absolute; left: var(--s3); top: calc(var(--s3) + 0.7em - 9px); width: 18px; height: 18px; background: currentColor; -webkit-mask: var(--notice-icon) center / contain no-repeat; mask: var(--notice-icon) center / contain no-repeat; }
.notice-green { background: var(--green-soft); color: var(--green); --notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M8 12.5l2.5 2.5L16 9.5'/%3E%3C/svg%3E"); }
.notice-amber { background: var(--amber-soft); color: var(--amber); --notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E"); }
.notice-red { background: var(--red-soft); color: var(--red); --notice-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 7v6M12 16.5v.5'/%3E%3C/svg%3E"); }
/* La acción del aviso, a la derecha y subrayada. Se toca en todo el alto de --tap; los márgenes negativos la dejan
   ocupar en el aviso solo su línea de texto. */
.notice-action { float: right; display: inline-flex; align-items: center; min-height: var(--tap); margin: calc((1.4em - var(--tap)) / 2) 0 calc((1.4em - var(--tap)) / 2) var(--s3); font-weight: 600; text-decoration: underline; white-space: nowrap; color: inherit; background: none; border: 0; padding: 0; font-size: inherit; line-height: 1.4; cursor: pointer; }

/* ---------- Tablas ---------- */
.table { width: 100%; border-collapse: collapse; }
.table th { padding: 10px; text-align: left; font-size: var(--label); font-weight: 600; letter-spacing: .03em; text-transform: uppercase; color: var(--muted); border-bottom: 1px solid var(--line); }
.table td { padding: var(--s3) 10px; border-bottom: 1px solid var(--line); font-variant-numeric: tabular-nums; }
/* Fila elegida. */
.table tr.is-selected td, .table tr[aria-selected="true"] td { background: var(--tint); }

/* ---------- Carga ---------- */
/* Lo que se ve en el lugar de lo que todavía no llega: un aro que gira, sin texto ni «…». Lleva
   role="status" y aria-label="Cargando" para quien no ve la pantalla. Sin movimiento si el teléfono lo pide. */
/* 58 px con línea de 6 en toda la app (#412); quien lo quiere más chico lo acota a su pieza (.switch-wait .loader). */
:root { --loader: 58px; --loader-w: 6px; }
.loader { display: block; width: var(--loader); height: var(--loader); margin: var(--s8) auto; border-radius: 50%; border: var(--loader-w) solid var(--line); border-top-color: var(--navy); animation: loader-giro .8s linear infinite; }
@keyframes loader-giro { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .loader { animation-duration: 2.4s; } }

/* ============================================================
   Verificación pública (spec #279): las medidas de verify.html, que las usa con sus clases.
   ============================================================ */
:root {
  /* La columna de la página en una pantalla más ancha que el celular. */
  --column: 540px;
  /* La fotografía oficial del perro y su aro dorado fino. */
  --photo: 96px;
  --photo-ring: 2px;
  /* El árbol, de los padres (1) a los tatarabuelos (4): ancho de la columna, tamaño del aro y su grosor. */
  --tree-col-1: 96px;
  --tree-col-2: 84px;
  --tree-col-3: 46px;
  --tree-col-4: 32px;
  --tree-node-1: 64px;
  --tree-node-2: 52px;
  --tree-node-3: 38px;
  --tree-node-4: 26px;
  --tree-ring: 2.5px;
  --tree-ring-3: 2px;
  --tree-ring-4: 1.5px;
  /* El aro de la leyenda. */
  --tree-legend: 20px;
  --tree-legend-ring: 2px;
  /* Las líneas de unión: a un ancestro y a un lugar desconocido. */
  --tree-line: 1.5px;
  --tree-line-faint: 1.2px;
  /* El alto del árbol según su generación más honda: cabe la columna más llena (4 abuelos con nombre, 8, 16). */
  --tree-h-2: 310px;
  --tree-h-3: 380px;
  --tree-h-4: 480px;
}

/* ============================================================
   Alianz Virtual: la cáscara (spec #272, prototipos #246 variante A1 y #256 tamaño 6).
   Encabezado blanco, barra de cinco pestañas y la pieza PRONTO.
   ============================================================ */
:root {
  /* Lo mínimo que mide todo lo que se toca. */
  --tap: 48px;
  /* Íconos de trazo: del encabezado y de la barra de pestañas. */
  --icon: 22px;
  --icon-tab: 24px;
  /* Alto de la barra de pestañas, sin la orilla segura del teléfono. */
  --tabbar-h: 60px;
  /* La rayita dorada bajo la pestaña activa. */
  --rule: 3px;
  --rule-w: 18px;
  /* El logo de #256, tamaño 6: globo, «Alianz», VIRTUAL y su rayita dorada. */
  --logo-globe: 38px;
  --logo-word: 18px;
  --logo-sub: 8px;
  --logo-rule: 11px;
  /* El logo grande del panel azul de las entradas de ADOS: globo, «ADOS», ALIANZ y su rayita dorada. */
  --brand-ados-globe: 96px;
  --brand-ados-word: 40px;
  --brand-ados-sub: 11px;
  --brand-ados-rule: 18px;
}

/* Íconos de trazo, del color del texto que los rodea. */
.icon-btn svg, .back-btn svg, .tabbar-tab svg { fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* ---------- Encabezado ---------- */
/* Blanco, fijo arriba, libra la hora y la isla del teléfono. */
.apphead { position: sticky; top: 0; z-index: 50; background: var(--white); padding: env(safe-area-inset-top) var(--s5) 0; }
.apphead-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); min-height: var(--tap); }
.apphead-icons { display: flex; align-items: center; margin-right: calc(var(--s3) * -1); }
/* Botón de ícono: 48 de toque, ícono de 22. */
.icon-btn { position: relative; display: grid; place-items: center; width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: 50%; background: none; color: var(--navy); cursor: pointer; }
.icon-btn svg { width: var(--icon); height: var(--icon); stroke-width: 1.8; }
.icon-btn:focus-visible, .back-btn:focus-visible, .logo-av:focus-visible, .tabbar-tab:focus-visible { outline: 2px solid var(--navy); outline-offset: -2px; }
/* «‹ Volver»: la flecha es ícono, el texto es la palabra. */
.back-btn { display: inline-flex; align-items: center; gap: 2px; min-height: var(--tap); min-width: var(--tap); margin-left: calc(var(--s2) * -1); padding: 0 var(--s2) 0 0; border: 0; background: none; color: var(--navy); font: 500 var(--body)/1 var(--sans); cursor: pointer; }
.back-btn svg { width: var(--icon); height: var(--icon); stroke-width: 2; }
/* Punto rojo de algo nuevo, sobre un ícono o una pestaña. */
.dot-new { position: absolute; width: 8px; height: 8px; border-radius: 50%; background: var(--red); box-shadow: 0 0 0 2px var(--white); }

/* ---------- Logo de Alianz Virtual ---------- */
/* El globo lo pone la página (la imagen); aquí su tamaño y la palabra. */
.logo-av { display: inline-flex; align-items: center; gap: var(--s2); min-height: var(--tap); padding: 0; border: 0; background: none; color: var(--navy); cursor: pointer; text-align: left; }
.logo-av-globe { width: var(--logo-globe); height: var(--logo-globe); flex: none; }
.logo-av-word { display: flex; flex-direction: column; line-height: 1; }
.logo-av-word b { font: 700 var(--logo-word)/1 var(--serif); }
.logo-av-word small { display: flex; align-items: center; gap: 5px; margin-top: var(--s1); font: 600 var(--logo-sub)/1 var(--sans); letter-spacing: .3em; color: var(--muted); }
.logo-av-word small::before { content: ""; width: var(--logo-rule); height: 2px; background: var(--gold); }

/* ---------- Logo grande, arriba de las pantallas fuera de sesión (spec #411, variante B de #412) ---------- */
/* Centrado arriba: el globo (la copia grande, app-assets/alianz-logo-432.png) y, debajo, «Alianz» / VIRTUAL o, con
   &ados, «ADOS» / ALIANZ. Las letras van a la medida de un logo de 120 aunque el globo mida 144:
   <header class="logo-hero"><span class="logo-hero-mark" role="img" aria-label="Alianz Virtual">
     <img class="logo-hero-globe" src="/app-assets/alianz-logo-432.png" alt="">
     <span class="logo-hero-word"><b>Alianz</b><small>VIRTUAL</small></span></span></header> */
:root {
  --logo-hero-globe: 144px;
  --logo-hero-measure: 120px;
  --logo-hero-gap: calc(var(--s3) * .9);
}
.logo-hero { display: flex; justify-content: center; padding: calc(env(safe-area-inset-top) + var(--s7)) var(--pad) var(--s2); }
.logo-hero-mark { display: flex; flex-direction: column; align-items: center; gap: var(--logo-hero-gap); color: var(--navy); }
.logo-hero-globe { display: block; width: var(--logo-hero-globe); height: var(--logo-hero-globe); }
.logo-hero-word { display: flex; flex-direction: column; align-items: center; line-height: 1; }
.logo-hero-word b { font: 700 calc(var(--logo-hero-measure) * .39)/1 var(--serif); }
.logo-hero-word small { display: flex; align-items: center; gap: calc(var(--logo-hero-measure) * .11); margin-top: calc(var(--logo-hero-measure) * .11); font: 600 calc(var(--logo-hero-measure) * .14)/1 var(--sans); letter-spacing: .3em; color: var(--muted); }
.logo-hero-word small::before { content: ""; width: calc(var(--logo-hero-measure) * .2); height: 2px; background: var(--gold); }
/* La pantalla de carga con el logo: el círculo (.loader) en el centro exacto de la pantalla y el logo encima, a
   --s8 del círculo. <div class="logo-wait"><header class="logo-hero">…</header><span class="loader" …></span></div> */
.logo-wait { position: fixed; inset: 0; }
.logo-wait .logo-hero { position: absolute; left: 0; right: 0; bottom: calc(50% + var(--loader) / 2 + var(--s8)); padding: 0 var(--pad); }
.logo-wait .loader { position: absolute; left: 50%; top: 50%; margin: 0; translate: -50% -50%; }

/* ---------- Liga de texto debajo de un botón ---------- */
/* «Recuperar contraseña», «Conservar mi correo»: subrayada, centrada, con el alto de un toque. */
.text-link { display: flex; align-items: center; justify-content: center; width: 100%; min-height: var(--tap); margin-top: var(--s2); padding: 0; border: 0; background: none; color: var(--navy); font: 600 var(--body)/1.2 var(--sans); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.text-link:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }

/* ---------- Barra de pestañas ---------- */
/* Fija abajo, libra la barra de gestos. Ícono y nombre siempre; la activa en azul con rayita dorada. */
.tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 40; background: var(--white); border-top: 1px solid var(--line); padding-bottom: env(safe-area-inset-bottom); }
.tabbar-row { display: flex; height: var(--tabbar-h); }
.tabbar-tab { position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: var(--tap); padding: var(--s2) 0 0; border: 0; background: none; color: var(--muted); font: 500 var(--label)/1.2 var(--sans); white-space: nowrap; cursor: pointer; }
.tabbar-tab svg { width: var(--icon-tab); height: var(--icon-tab); stroke-width: 1.8; }
.tabbar-tab::after { content: ""; width: var(--rule-w); height: var(--rule); border-radius: 2px; margin-top: 1px; background: transparent; }
.tabbar-tab[aria-current="page"] { color: var(--navy); font-weight: 600; }
.tabbar-tab[aria-current="page"]::after { background: var(--gold); }
.tabbar-tab .dot-new { top: 6px; left: calc(50% + 6px); }

/* ---------- Pantalla PRONTO ---------- */
/* Lo que todavía no existe: el título, el sello PRONTO y una línea de lo que va a haber. Sin datos de muestra. */
.soon { padding: var(--s6) 0; }
.soon-title { font-family: var(--serif); font-weight: 600; font-size: var(--title); line-height: 1.15; }
.soon .seal { margin-top: var(--s3); }
.soon-line { margin-top: var(--s3); font-size: var(--body); color: var(--muted); }

/* ============================================================
   Alianz Virtual: Perfil y Ajustes (spec #272; prototipos #246 variante A1 y #252 variante C).
   La fotografía o las iniciales, las pestañas de texto y las filas de navegación.
   ============================================================ */
:root {
  /* La fotografía de perfil, grande. */
  --avatar-big: 88px;
  /* El cuadro del ícono de una fila de navegación, su ícono y la flecha de la derecha. */
  --row-ic-box: 34px;
  --row-ic: 19px;
  --chev: 16px;
  /* La fotografía de un perro en una lista. */
  --thumb: 64px;
  /* La fotografía de una persona en la fila de una tabla y junto al nombre de su ficha (Equipo, spec #418). */
  --person-avatar: 36px;
  --person-avatar-md: 56px;
}

/* ---------- Fotografía de perfil o iniciales ---------- */
/* Círculo azul, letra blanca y aro dorado (#252, variante C). Con fotografía, la imagen llena el círculo. */
.avatar-big { display: grid; place-items: center; width: var(--avatar-big); height: var(--avatar-big); border-radius: 50%; overflow: hidden; background: var(--navy); color: var(--white); box-shadow: 0 0 0 2px var(--gold); font: 600 var(--title)/1 var(--sans); letter-spacing: .02em; }
.avatar-big img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* La de una persona en una tabla o una ficha (Equipo, spec #418): la misma pieza, más chica. Con fotografía, la imagen de
   fondo llena el círculo (`.person-avatar.img` con `background-image`); sin ella, las iniciales. `.person-avatar-md`,
   junto al nombre. */
.person-avatar { display: inline-flex; align-items: center; justify-content: center; flex: none; box-sizing: border-box; width: var(--person-avatar); height: var(--person-avatar); border-radius: 50%; background: var(--navy) center/cover no-repeat; color: var(--white); box-shadow: 0 0 0 2px var(--gold); font: 600 var(--label)/1 var(--sans); letter-spacing: .02em; }
.person-avatar.img { color: transparent; }
.person-avatar.person-avatar-md { width: var(--person-avatar-md); height: var(--person-avatar-md); font-size: var(--body); }

/* ---------- Pestañas de texto ---------- */
/* Debajo de una cabecera; la activa en azul con raya azul. Cada una ocupa su parte del ancho. */
.texttabs { display: flex; border-bottom: 1px solid var(--line); }
.texttab { position: relative; flex: 1; min-height: var(--tap); padding: 0 var(--s1); border: 0; background: none; color: var(--muted); font: 600 var(--body)/1.2 var(--sans); cursor: pointer; }
.texttab[aria-selected="true"] { color: var(--navy); }
.texttab[aria-selected="true"]::after { content: ""; position: absolute; left: 25%; right: 25%; bottom: -1px; height: var(--rule); border-radius: 2px; background: var(--navy); }
.texttab:focus-visible { outline: 2px solid var(--navy); outline-offset: -2px; }

/* ---------- Filas de navegación ---------- */
/* Un grupo con borde fino; cada fila: ícono en su cuadro, el nombre (y una línea chica) y la flecha.
   Una fila PRONTO lleva aria-disabled, el sello en lugar de la flecha y no abre nada. */
.nav-rows-label { margin: var(--s5) 0 var(--s2); }
.nav-rows { border: 1px solid var(--line); border-radius: var(--r-card); overflow: hidden; }
.nav-row { display: flex; align-items: center; gap: var(--s3); width: 100%; min-height: var(--tap); padding: var(--s3) var(--s4); border: 0; border-bottom: 1px solid var(--line); background: var(--white); color: var(--text); font: 400 var(--body)/1.3 var(--sans); text-align: left; cursor: pointer; }
.nav-row:last-child { border-bottom: 0; }
.nav-row:focus-visible { outline: 2px solid var(--navy); outline-offset: -2px; }
.nav-row-ic { display: grid; place-items: center; width: var(--row-ic-box); height: var(--row-ic-box); border-radius: var(--r-field); background: var(--neutral-soft); flex: none; }
.nav-row-ic svg { width: var(--row-ic); height: var(--row-ic); fill: none; stroke: var(--navy); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.nav-row-text { flex: 1; min-width: 0; }
.nav-row-text small { display: block; margin-top: 1px; font-size: var(--label); color: var(--muted); }
.nav-row-chev { width: var(--chev); height: var(--chev); flex: none; fill: none; stroke: var(--muted); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* El valor a la derecha, antes de la flecha (Mi cuenta, #390): etiqueta · valor · flecha; un valor largo se corta. */
.nav-row-value { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-variant-numeric: tabular-nums; }
/* La fila abierta en su lugar (Mi cuenta, #394; prototipo previews/ajustes.html, B): una tarjeta dentro de la lista con
   fondo de fila elegida; su cabeza es la misma fila con la flecha hacia abajo y la cierra. Compacta, para que la
   tarjeta crema y las otras filas sigan a la vista. */
.nav-open { padding: 0 var(--s4) var(--s4); border-bottom: 1px solid var(--line); background: var(--tint); }
.nav-open:last-child { border-bottom: 0; }
.nav-open-head { display: flex; align-items: center; gap: var(--s3); width: 100%; min-height: var(--tap); padding: 0; border: 0; background: none; color: var(--text); font: 600 var(--body)/1.3 var(--sans); text-align: left; cursor: pointer; }
.nav-open-head > span:first-child { flex: 1; }
.nav-open-head .nav-row-chev { transform: rotate(90deg); }
.nav-open .field + .field { margin-top: var(--s3); }
.nav-open .kv { padding-top: 0; }
.nav-open .kv + .notice, .nav-open .kv + .field, .nav-open .notice + .field { margin-top: var(--s2); }
.nav-open .t-small { margin: var(--s2) 0 0; }
.nav-open .actions { margin-top: var(--s4); }
.nav-open .actions-row > .btn-secondary { flex: none; }
.nav-row[aria-disabled="true"] { cursor: default; }
.nav-row[aria-disabled="true"] .nav-row-text { color: var(--muted); }
.nav-row[aria-disabled="true"] .nav-row-ic svg { stroke: var(--muted); }

/* ============================================================
   Alianz Virtual: Inicio y publicar (spec #272; prototipo #246 variante A1).
   Las pestañas de texto centradas, «Solo tú lo ves», el botón redondo «+» y la hoja que sube.
   ============================================================ */
:root {
  /* El botón redondo «+» y su ícono. */
  --fab: 56px;
  --icon-fab: 26px;
  /* El candado de «Solo tú lo ves». */
  --icon-small: 14px;
  /* La agarradera de la hoja que sube y la esquina de arriba de la hoja. */
  --grab-w: 40px;
  --grab-h: 5px;
  --r-sheet: 20px;
}

/* ---------- Pestañas de texto centradas ---------- */
/* Como .texttabs, pero juntas al centro con aire entre ellas (las de Inicio). */
.texttabs-center { justify-content: center; gap: var(--s6); }
.texttabs-center .texttab { flex: none; padding: 0 var(--s1); }
.texttabs-center .texttab[aria-selected="true"]::after { left: 15%; right: 15%; }

/* ---------- Solo tú lo ves ---------- */
/* Encima de lo que es solo del socio: el candado y la frase, en gris chico. */
.only-you { display: flex; align-items: center; gap: 6px; margin-bottom: var(--s2); font-size: var(--label); color: var(--muted); }
.only-you svg { width: var(--icon-small); height: var(--icon-small); flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- Botón redondo «+» ---------- */
/* Azul, abajo a la derecha, encima de la barra de pestañas. Sin sombra, como toda la hoja. */
.fab { position: fixed; right: var(--s5); bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--s4)); z-index: 45; display: grid; place-items: center; width: var(--fab); height: var(--fab); padding: 0; border: 0; border-radius: 50%; background: var(--navy); color: var(--white); cursor: pointer; }
.fab svg { width: var(--icon-fab); height: var(--icon-fab); fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.fab:focus-visible { outline: 2px solid var(--navy); outline-offset: 3px; }

/* ---------- Hoja que sube ---------- */
/* El velo azul sobre toda la pantalla (también sobre la barra) y la hoja blanca abajo, con su agarradera. */
.bottom-sheet-scrim { position: fixed; inset: 0; z-index: 96; display: flex; align-items: flex-end; justify-content: center; background: var(--scrim); }
.bottom-sheet { box-sizing: border-box; width: 100%; max-width: 560px; padding: var(--s2) var(--s5) calc(var(--s6) + env(safe-area-inset-bottom)); border-radius: var(--r-sheet) var(--r-sheet) 0 0; background: var(--white); }
.bottom-sheet-grab { width: var(--grab-w); height: var(--grab-h); margin: 0 auto var(--s3); border-radius: 3px; background: var(--line); }
.bottom-sheet .soon { padding: var(--s2) 0 var(--s5); }

/* ============================================================
   ADOS de computadora (spec #294): las medidas de la barra lateral y del Inicio del club, que usan
   ados-shell.css y la página del club.
   ============================================================ */
:root {
  /* El ancho de la barra lateral azul, abierta y encogida a íconos. */
  --side-w: 244px;
  --side-w-mini: 64px;
  /* La marca de la cuenta en el selector: el cuadro del logo o de las iniciales. */
  --account-mark: 40px;
  /* El ancho del menú «Tus cuentas». */
  --menu-w: 300px;
  /* El ancho máximo de una tarjeta sola en una pantalla ancha (la tarjeta «Próximo evento»). */
  --card-w: 620px;
}

/* ============================================================
   Eventos del club (spec #328): las medidas de la lista de Eventos y de Editar evento, que usa la página del club.
   ============================================================ */
:root {
  /* El ancho máximo de una pantalla de trabajo ancha: la lista de Eventos y Editar evento. */
  --page-w: 880px;
  /* La portada del evento: el alto máximo de la imagen y el del cuadro para subirla. */
  --cover-h: 230px;
  --cover-drop-h: 150px;
  /* El ancho de un campo de una cifra corta (la cuota de un día). */
  --field-short-w: 160px;
  /* Las cifras de un día en la lista de Eventos: el ancho de cada una y el de la de jueces, que lleva nombres. */
  --fig-w: 110px;
  --fig-w-wide: 200px;
  /* El alto de un botón píldora para elegir entre varios (los días de Jueces). */
  --pill-h: 32px;
}

/* ============================================================
   Ventana de confirmación de computadora (spec #294; guía de voz, regla 7).
   ============================================================ */
:root {
  /* El ancho de la ventana. */
  --dialog-w: 400px;
}

/* El velo azul sobre toda la pantalla y, al centro, la ventana blanca: la pregunta, lo que cambia (si hace falta)
   y los botones en .actions, el principal con el verbo y «Volver». */
.dialog-scrim { position: fixed; inset: 0; z-index: 96; display: flex; align-items: center; justify-content: center; padding: var(--s5); background: var(--scrim); }
/* La ventana nunca pasa del alto que se ve (la tablet con la barra de Chrome, 960×560): si su contenido no cabe, se
   desplaza dentro de la ventana y la fila de botones se queda pegada abajo, siempre a la vista. */
.dialog { box-sizing: border-box; width: 100%; max-width: var(--dialog-w); max-height: 100%; overflow-y: auto; overscroll-behavior: contain; padding: var(--s6); border-radius: var(--r-card); background: var(--white); color: var(--text); }
.dialog-title { margin: 0; font-family: var(--serif); font-weight: 600; font-size: var(--name); line-height: 1.2; }
.dialog-body { margin-top: var(--s2); color: var(--muted); }
.dialog .actions { position: sticky; bottom: calc(-1 * var(--s6)); margin: var(--s6) 0 calc(-1 * var(--s6)); padding-bottom: var(--s6); background: var(--white); }

/* ============================================================
   Pista: el teléfono del secretario (spec #310, ticket #317; prototipo #260, ronda 6).
   Las pestañas de abajo son las de .tabbar; aquí el número rojo sobre una pestaña: cuántos libros
   esperan la firma del secretario.
   ============================================================ */
:root {
  /* El número rojo: su alto (y ancho mínimo) y su letra. */
  --badge: 18px;
  --badge-text: 11px;
}
.tabbar-badge { position: absolute; top: 2px; left: calc(50% + 6px); display: grid; place-items: center; box-sizing: border-box; min-width: var(--badge); height: var(--badge); padding: 0 5px; border-radius: var(--r-pill); background: var(--red); color: var(--white); font: 700 var(--badge-text)/1 var(--sans); font-variant-numeric: tabular-nums; }

/* ============================================================
   Pista: la tablet del juez (spec #310, prototipo #260 ronda 6). La barra azul de arriba, el árbol de la
   izquierda y la barra de avance de Inicio.
   Verificación (spec #319) usa la barra azul en el teléfono, sin exposición ni pista.
   ============================================================ */
:root {
  /* El ancho del árbol. */
  --ring-tree-w: 280px;
  /* Ícono de una fila del árbol, el circulito de un juzgamiento y la rayita dorada de la fila actual. */
  --ring-tree-icon: 18px;
  --ring-tree-dot: 20px;
  --ring-tree-rule: 3px;
  /* El alto de la barra de avance. */
  --progress-h: 6px;
  /* El aire a los lados de la pantalla de la tablet; el de la tablet angosta. */
  --ring-pad: 28px;
  --ring-pad-narrow: 14px;
  /* La letra del número dentro del circulito del árbol. */
  --ring-tree-dot-text: 11px;
  /* La rayita de «ocupado» arriba de la tablet. */
  --busy-h: 4px;
  /* Dónde sale el aviso de arriba: bajo la barra azul. */
  --toast-top: 60px;
  /* El ancho de la columna del teléfono del secretario. */
  --ring-phone-w: 480px;
}

/* ---------- Barra de la pista ---------- */
/* Azul, a todo lo ancho: el logo, la exposición con su pista y la fecha, quién opera y «Cerrar sesión». */
.ringbar { display: flex; align-items: center; gap: var(--s3); flex: none; padding: calc(10px + env(safe-area-inset-top)) var(--s5) 10px; background: var(--navy); color: var(--white); }
.ringbar-brand { display: flex; align-items: center; gap: var(--s2); flex: none; }
.ringbar-brand img { width: 34px; height: 34px; flex: none; }
.ringbar-word { display: flex; flex-direction: column; line-height: 1; }
.ringbar-word b { font: 700 17px/1 var(--serif); }
.ringbar-word small { display: flex; align-items: center; gap: 5px; margin-top: var(--s1); font: 600 8px/1 var(--sans); letter-spacing: .3em; color: var(--on-navy-muted); }
.ringbar-word small::before { content: ""; width: 10px; height: 2px; background: var(--gold); }
.ringbar-ctx { flex: 1; min-width: 0; padding-left: var(--s3); border-left: 1px solid var(--on-navy-line); }
.ringbar-ctx b { display: block; font-size: 14px; line-height: 1.25; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ringbar-ctx small { display: block; font-size: 13px; line-height: 1.25; color: var(--on-navy-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ringbar-me { text-align: right; font-size: 14px; line-height: 1.25; font-weight: 600; white-space: nowrap; }
.ringbar-me small { display: block; font-size: 13px; font-weight: 400; color: var(--on-navy-muted); }
.ringbar-me b { display: block; font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.ringbar-out { flex: none; min-height: 34px; padding: 0 var(--s3); border: 1px solid var(--on-navy-muted); border-radius: var(--r-field); background: none; color: var(--white); font: 600 13px/1 var(--sans); cursor: pointer; }
:root[data-device="phone"] .ringbar-ctx { display: none; }
:root[data-device="phone"] .ringbar-me { flex: 1; }
/* La barra del teléfono del secretario: fija arriba al desplazar y con menos aire a los lados. */
.ringbar.ringbar-fixed { position: sticky; top: 0; z-index: 30; gap: var(--s3); padding-left: var(--s4); padding-right: var(--s4); }
.ringbar.ringbar-fixed .ringbar-me { min-width: 0; }

/* ---------- Árbol ---------- */
/* La columna de la izquierda, fondo suave: Inicio, las razas, los grupos y Mejor de Exposición. La fila actual,
   blanca con la rayita dorada (aria-current); la que no abre, atenuada (aria-disabled). Se desplaza sola. */
.tree { box-sizing: border-box; width: var(--ring-tree-w); overflow-y: auto; padding: var(--s2) 10px; background: var(--tint); border-right: 1px solid var(--line); font-size: 14px; line-height: 1.25; }
.tree-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 5px 10px; border: 0; border-radius: var(--s2); background: none; color: var(--text); font: inherit; text-align: left; cursor: pointer; }
.tree-item svg { width: var(--ring-tree-icon); height: var(--ring-tree-icon); flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.tree-item[aria-current="page"] { background: var(--white); box-shadow: inset var(--ring-tree-rule) 0 0 var(--gold); font-weight: 600; }
.tree-item.is-still { cursor: default; }
.tree-item[aria-disabled="true"] { opacity: .45; cursor: default; }
.tree-label { flex: 1; min-width: 0; }
.tree-label small { display: block; font-size: 12px; font-weight: 400; color: var(--muted); }
.tree-group { margin: var(--s3) 10px 2px; font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.tree-sub { margin: 0 0 4px 19px; padding-left: var(--s2); border-left: 1px solid var(--line); }
.tree-sub-title { padding: 6px 10px 0; font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
/* El circulito: gris con su número si está pendiente, borde azul si es el siguiente, azul con ✓ dorada si terminó. */
.tree-dot { display: grid; place-items: center; flex: none; box-sizing: border-box; width: var(--ring-tree-dot); height: var(--ring-tree-dot); border-radius: 50%; border: 1.5px solid var(--cream-line); background: var(--white); color: var(--muted); font: 700 var(--ring-tree-dot-text)/1 var(--sans); }
.tree-dot.is-next { border-color: var(--navy); color: var(--navy); }
.tree-dot.is-done { border-color: var(--navy); background: var(--navy); color: var(--gold); }

/* ---------- Barra de avance ---------- */
/* El nombre y cuántas van de cuántas, y la barra: fondo suave, relleno azul (el ancho lo pone la página). */
.ring-progress { padding: var(--s2) 0 var(--s3); }
.ring-progress-label { display: flex; justify-content: space-between; margin-bottom: var(--s2); font-size: var(--small); }
.ring-progress-count { color: var(--muted); }
.ring-progress-track { height: var(--progress-h); border-radius: var(--r-pill); background: var(--neutral-soft); overflow: hidden; }
.ring-progress-fill { display: block; height: 100%; background: var(--navy); }

/* ---------- Aviso de arriba ---------- */
/* Lo que acaba de pasar, bajo la barra azul y al centro, con el aviso de la hoja (.notice-green al terminar algo,
   .notice-red con un rechazo del servidor): un momento y se va (la página pone y quita .on). Juez y secretario. */
.toast { position: fixed; left: 50%; top: calc(var(--toast-top) + env(safe-area-inset-top)); transform: translateX(-50%); z-index: 80; margin: 0; max-width: 90vw; font-weight: 500; opacity: 0; transition: opacity .2s; pointer-events: none; }
.toast.on { opacity: 1; }

/* ============================================================
   Pista: el llamado del juez (spec #310, ticket #314; prototipo #260, ronda 6). La cabecera del llamado, los
   cuadros de números (pase de lista y lugares), el pie, la barra lateral del número que entra desde la derecha y,
   en la tablet, la ventana con sus botones en fila. Las usan también Mejor de Raza, los grupos y Mejor de Exposición.
   ============================================================ */
:root {
  /* Los colores de los lugares, solo para los lugares: 1er oro, 2do plata, 3er bronce, 4to azul claro. Cada uno con su
     línea, su fondo claro y la letra de «1er lugar». El oro es el de siempre, sobre el crema. */
  --place-1: var(--gold);
  --place-1-soft: var(--cream);
  --place-1-text: #9C7B33;
  --place-2: #A7ADB5;
  --place-2-soft: #F3F4F6;
  --place-2-text: #5F6670;
  --place-3: #B87D4B;
  --place-3-soft: #F8EDE3;
  --place-3-text: #8E5A2E;
  --place-4: #3D74C4;
  --place-4-soft: #E6EFFB;
  --place-4-text: #2C5DA3;
  /* El cuadro de un número: su lado, su esquina, la cifra y las marcas de adentro (sexo, AUSENTE, APTO), que van
     más chicas que la escala para caber en el cuadro; el punto debajo, igual. Doce números, el camino de pasos y el
     pie caben sin desplazar en la tablet del juez (960×560 CSS). */
  --ring-tile: 88px;
  --ring-tile-r: 14px;
  --ring-tile-n: 40px;
  --ring-tile-mark: 9px;
  --ring-tile-point: 10px;
  /* La barra lateral del número, su número grande y el interruptor. */
  --side-sheet-w: 360px;
  --side-sheet-big: 40px;
  --switch-w: 44px;
  --switch-h: 26px;
}

/* ---------- Cabecera del llamado ---------- */
/* A la izquierda la salida (.back-btn), al centro la raza · sexo y la categoría; la tercera columna, vacía, lo centra. */
.ring-callhead { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--s4); flex: none; padding: 7px 28px; border-bottom: 1px solid var(--line); }
.ring-callhead > :first-child { justify-self: start; }
.ring-callhead > :last-child { justify-self: end; }
.ring-callhead-mid { text-align: center; }
.ring-callhead-crumb { font-size: 14px; line-height: 1.2; color: var(--muted); }
.ring-callhead h1 { font-family: var(--serif); font-weight: 700; font-size: 22px; line-height: 1.15; font-size-adjust: ex-height 0.546; }
/* La salida, más baja que en el resto de la app: la cabecera es una franja delgada. */
.ring-callhead .back-btn { min-height: 44px; font-size: 17px; }
.ring-callhead .back-btn svg { width: 20px; height: 20px; }

/* ---------- Cuadros de números ---------- */
/* La fila de cuadros; en lugares, entre filas el lugar para el punto de arriba y el nombre del lugar de abajo, sin que
   se encimen con el cuadro vecino. En Mejor de Raza (.is-center) el punto va en una línea; en la categoría, donde el
   1er lugar queda en la orilla, el punto no pasa del aire entre columnas y baja a dos líneas, con más aire entre filas.
   Con dos puntos apilados, el doble. */
.ring-tiles { display: flex; flex-wrap: wrap; gap: 10px; }
.ring-tiles.is-ranked { gap: 26px 22px; padding: 19px 0 24px; }
.ring-tiles.is-ranked:has(.ring-tile-point + .ring-tile-point) { row-gap: 48px; padding-bottom: 48px; }
.ring-tiles.is-ranked:not(.is-center) { row-gap: 40px; padding-bottom: 40px; }
.ring-tiles.is-ranked:not(.is-center):has(.ring-tile-point + .ring-tile-point) { row-gap: 72px; padding-bottom: 72px; }
.ring-tiles.is-center { justify-content: center; }
/* El cuadro: la cifra en Inter 700 y el sexo arriba a la derecha. Se toca y se arrastra. */
.ring-tile { position: relative; box-sizing: border-box; display: flex; flex-direction: column; align-items: center; justify-content: center; width: var(--ring-tile); height: var(--ring-tile); border: 2px solid var(--line); border-radius: var(--ring-tile-r); background: var(--white); color: var(--text); cursor: pointer; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; touch-action: manipulation; }
.ring-tile-n { font: 700 var(--ring-tile-n)/1 var(--sans); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.ring-tile-sex { position: absolute; top: 6px; right: 8px; font: 600 var(--ring-tile-mark)/1 var(--sans); letter-spacing: .06em; color: var(--muted); }
/* La categoría o la raza del perro, bajo la cifra (Mejor de Raza, grupos). */
.ring-tile-tag { max-width: 92%; margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; line-height: 1.15; font-weight: 600; color: var(--muted); }
/* El lápiz de la súmula escrita, arriba a la izquierda. */
.ring-tile-note { position: absolute; top: 5px; left: 8px; font-size: 12px; color: var(--muted); }
/* Pase de lista: AUSENTE (punteado, gris) o PRESENTE (borde azul), abajo dentro del cuadro. */
.ring-tile-state { position: absolute; left: 0; right: 0; bottom: 6px; text-align: center; font: 700 var(--ring-tile-mark)/1 var(--sans); letter-spacing: .08em; }
/* con AUSENTE o PRESENTE abajo, la cifra sube un poco para dejarle lugar */
.ring-tile:has(> .ring-tile-state) { padding-bottom: 4px; }
.ring-tile.is-absent { border-style: dashed; background: var(--tint); }
.ring-tile.is-absent .ring-tile-n, .ring-tile.is-absent .ring-tile-state { color: var(--muted); opacity: .6; }
.ring-tile.is-present { border-color: var(--navy); }
.ring-tile.is-present .ring-tile-state { color: var(--navy); }
/* El lugar, arriba del cuadro, en el color del lugar. */
.ring-tile-place { position: absolute; left: -14px; right: -14px; bottom: calc(100% + 4px); text-align: center; white-space: nowrap; font-size: 12px; font-weight: 700; line-height: 1.2; color: var(--muted); }
.ring-tile.is-place-1 { border-color: var(--place-1); background: var(--place-1-soft); box-shadow: 0 0 0 2px var(--place-1-soft); }
.ring-tile.is-place-1 .ring-tile-place { color: var(--place-1-text); }
.ring-tile.is-place-2 { border-color: var(--place-2); background: var(--place-2-soft); box-shadow: 0 0 0 2px var(--place-2-soft); }
.ring-tile.is-place-2 .ring-tile-place { color: var(--place-2-text); }
.ring-tile.is-place-3 { border-color: var(--place-3); background: var(--place-3-soft); box-shadow: 0 0 0 2px var(--place-3-soft); }
.ring-tile.is-place-3 .ring-tile-place { color: var(--place-3-text); }
.ring-tile.is-place-4 { border-color: var(--place-4); background: var(--place-4-soft); box-shadow: 0 0 0 2px var(--place-4-soft); }
.ring-tile.is-place-4 .ring-tile-place { color: var(--place-4-text); }
/* La calificación del 1er lugar, abajo dentro del cuadro: SIN CALIFICAR (gris), APTO (verde), NO APTO (rojo). */
.ring-tile-grade { position: absolute; bottom: 5px; left: 50%; transform: translateX(-50%); padding: 2px 6px; border-radius: var(--r-pill); background: var(--neutral-soft); color: var(--muted); font: 700 var(--ring-tile-mark)/1.2 var(--sans); letter-spacing: .04em; white-space: nowrap; }
.ring-tile-grade.is-ok { background: var(--green); color: var(--white); }
.ring-tile-grade.is-no { background: var(--red); color: var(--white); }
/* El punto, debajo del cuadro y de su ancho: gris punteado sin otorgar, azul otorgado, rojo «NA · …». Varios, apilados. */
/* Centrado bajo el cuadro, en el aire entre filas; más ancho que el cuadro si su nombre lo pide. */
.ring-tile-points { position: absolute; top: calc(100% + 4px); left: 50%; transform: translateX(-50%); width: max-content; min-width: calc(100% + 12px); max-width: calc(100% + 44px); display: flex; flex-direction: column; gap: 2px; }
.ring-tiles.is-center .ring-tile-points { max-width: none; }
.ring-tile-point { box-sizing: border-box; padding: 2px 6px; border-radius: var(--r-field); text-align: center; font: 600 var(--ring-tile-point)/1.15 var(--sans); }
.ring-tiles.is-center .ring-tile-point { white-space: nowrap; }
.ring-tile-point.is-off { background: var(--neutral-soft); color: var(--muted); border: 1.5px dashed var(--muted); cursor: pointer; }
.ring-tile-point.is-on { background: var(--navy); color: var(--white); border: 1.5px solid var(--navy); cursor: pointer; }
.ring-tile-point.is-na { background: var(--white); color: var(--red); border: 1.5px solid var(--red); }
/* Los que no compiten en el paso se apagan; los que compiten, borde azul (Mejor de Raza). */
.ring-tile.is-dim { opacity: .28; cursor: default; }
.ring-tile.is-lit:not([class*="is-place-"]) { border-color: var(--navy); }
/* Arrastrar: el que se levanta crece con borde dorado (sin sombra); su lugar se aclara; el de abajo, punteado dorado. */
.ring-tile.is-dragging { opacity: .25; }
.ring-tile.is-over { border-color: var(--gold); border-style: dashed; }
.ring-tile.is-ghost { position: fixed; z-index: 60; margin: 0; pointer-events: none; border-color: var(--gold); transition: transform .12s ease-out; }
.ring-tile.is-ghost.is-up { transform: scale(1.08); }

/* ---------- Pie del llamado ---------- */
/* Fijo abajo: a la izquierda los botones secundarios (.ring-foot-side), al centro la guía o qué falta (hasta dos
   líneas), a la derecha la acción principal. Abajo deja la franja del sistema (barra de gestos). */
.ring-foot { display: flex; align-items: center; gap: var(--s3); flex: none; padding: 6px 28px calc(6px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--line); background: var(--white); }
.ring-foot-side { display: flex; gap: var(--s3); flex: none; }
.ring-foot-info { flex: 1; min-width: 0; font-size: 14px; line-height: 1.25; text-align: center; color: var(--muted); }
.ring-foot-info b { color: var(--text); font-weight: 700; }
.ring-foot .btn { flex: none; min-height: 44px; font-size: 17px; white-space: nowrap; }
.ring-foot .btn-secondary { font-size: 15px; }
/* Un atajo dentro de una línea («Marcar todos»): subrayado, del color de la línea. */
.ring-link { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }

/* ---------- Barra lateral ---------- */
/* El velo azul y la barra blanca a la derecha, de arriba hasta el pie (--ring-foot-h, lo mide la página), para que el
   botón del pie se vea y se toque con la barra abierta; entra desde la derecha al abrirse (.is-entering).
   Arriba lo que es y la ×, en medio lo que se decide, abajo «Listo». */
.side-sheet-scrim { position: fixed; inset: 0 0 var(--ring-foot-h, 0px); z-index: 70; background: var(--scrim); }
.side-sheet { position: fixed; top: 0; right: 0; bottom: var(--ring-foot-h, 0px); z-index: 71; box-sizing: border-box; display: flex; flex-direction: column; width: var(--side-sheet-w); max-width: 100%; background: var(--white); }
.side-sheet.is-entering { animation: side-sheet-in .28s cubic-bezier(.2, .8, .2, 1); }
.side-sheet-scrim.is-entering { animation: side-sheet-fade .2s ease-out; }
@keyframes side-sheet-in { from { transform: translateX(100%); } to { transform: none; } }
@keyframes side-sheet-fade { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .side-sheet.is-entering, .side-sheet-scrim.is-entering { animation: none; } }
.side-sheet-head { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s3) var(--s5) 0; }
.side-sheet-head > div { flex: 1; min-width: 0; }
.side-sheet-crumb { font-size: 13px; color: var(--muted); }
.side-sheet-big { margin: 2px 0; font: 700 var(--side-sheet-big)/1 var(--sans); font-variant-numeric: tabular-nums; }
.side-sheet-close { display: grid; place-items: center; flex: none; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 50%; background: var(--neutral-soft); color: var(--text); cursor: pointer; }
.side-sheet-close svg { width: var(--icon); height: var(--icon); fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.side-sheet-body { flex: 1; overflow-y: auto; padding: var(--s1) var(--s5) var(--s2); }
.side-sheet-body .t-section { margin: var(--s3) 0 6px; font-size: 12px; }
.side-sheet-body .t-section:first-child { margin-top: 6px; }
/* la súmula, de unas cuatro líneas: la barra cabe sin desplazar en la tablet */
.side-sheet .field textarea { height: 92px; }
.side-sheet-foot { padding: var(--s2) var(--s5) 10px; border-top: 1px solid var(--line); }
.side-sheet-foot .btn { min-height: 44px; font-size: 17px; }

/* ---------- Dos opciones ---------- */
/* Apto / No apto: dos botones del mismo ancho; el elegido (aria-pressed), verde o rojo con letra blanca. */
.segmented { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); }
.segmented button { min-height: 44px; border: 1px solid var(--line); border-radius: var(--r-btn); background: var(--white); color: var(--text); font: 600 16px/1.2 var(--sans); cursor: pointer; }
.segmented .is-ok[aria-pressed="true"] { background: var(--green); border-color: var(--green); color: var(--white); }
.segmented .is-no[aria-pressed="true"] { background: var(--red); border-color: var(--red); color: var(--white); }

/* ---------- Interruptor ---------- */
/* Una fila con el nombre y el interruptor a la derecha: apagado gris, encendido azul (role="switch", aria-checked). */
.switch-row { display: flex; align-items: center; gap: var(--s3); width: 100%; min-height: 40px; padding: 6px 0; border: 0; border-bottom: 1px solid var(--line); background: none; color: var(--text); font: 500 15px/1.3 var(--sans); text-align: left; cursor: pointer; }
.switch-row:last-child { border-bottom: 0; }
.switch-row > span:first-child { flex: 1; }
.switch-row .switch { position: relative; flex: none; width: var(--switch-w); height: var(--switch-h); border-radius: var(--r-pill); background: var(--cream-line); transition: background .15s; }
.switch-row .switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: calc(var(--switch-h) - 6px); height: calc(var(--switch-h) - 6px); border-radius: 50%; background: var(--white); transition: left .15s; }
.switch-row[aria-checked="true"] .switch { background: var(--navy); }
.switch-row[aria-checked="true"] .switch::after { left: calc(var(--switch-w) - var(--switch-h) + 3px); }

/* ---------- Interruptor con su línea, y el recorte cuadrado de la fotografía (#396, Alianz Virtual) ---------- */
/* El dato secundario bajo la etiqueta; desactivado (bloqueado o mientras se lee), atenuado y con la pieza de carga. */
.switch-row small { display: block; margin-top: var(--s1); font-size: var(--small); font-weight: 400; color: var(--muted); }
.switch-row[aria-disabled="true"] { cursor: default; }
.switch-row[aria-disabled="true"] .switch { opacity: .45; }
.switch-wait { display: flex; align-items: center; gap: var(--s2); }
.switch-wait .loader { --loader: 18px; --loader-w: 3px; margin: 0; }
/* El cuadro donde se mueve la fotografía: la página le pone a la imagen su tamaño y su posición. Debajo, «Acercar». */
.crop { position: relative; width: 100%; aspect-ratio: 1; overflow: hidden; border-radius: var(--r-card); background: var(--navy-deep); touch-action: none; cursor: grab; }
.crop img { position: absolute; left: 0; top: 0; max-width: none; transform-origin: 0 0; user-select: none; -webkit-user-drag: none; }
.crop-zoom { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s4); }
.crop-zoom label { color: var(--muted); }
.crop-zoom input { flex: 1; accent-color: var(--navy); }

/* ---------- La ventana en la tablet ---------- */
/* Más ancha, con los botones en fila, a la derecha, «Volver» a la izquierda del principal (el principal va primero en
   el HTML). Las filas y el aviso de la ventana, con su aire. */
:root[data-device="tablet"] { --dialog-w: 520px; }
:root[data-device="tablet"] .dialog .actions { flex-direction: row-reverse; justify-content: flex-start; }
:root[data-device="tablet"] .dialog .actions > .btn { width: auto; }
.dialog .notice { margin-top: var(--s3); }
.dialog-rows { margin-top: var(--s2); }
.dialog-rows + .dialog-body { margin-top: var(--s3); font-size: var(--small); }

/* ============================================================
   Pista: los libros y los estados del juez (spec #310, ticket #316). Las secciones dentro de la ventana (los puntos
   otorgados del libro) y la pantalla vacía.
   ============================================================ */
/* Una sección dentro de la ventana, con sus filas debajo. */
.dialog .t-section { margin: var(--s4) 0 0; }
/* La pantalla vacía de la pista («Sin inscritos»): lo que falta y, debajo, qué la llena. */
.ring-empty { margin: var(--s6) 0 var(--s3); padding: var(--s6); border: 1px dashed var(--line); border-radius: var(--r-card); text-align: center; }
.ring-empty .t-small { margin-top: var(--s1); color: var(--muted); }

/* ============================================================
   Pista: Mejor de Raza (spec #310, ticket #315; prototipo #260, ronda 6). El camino de pasos bajo la cabecera con el
   ganador de cada paso hecho (que se toca para regresar), el paso al centro con su guía, el Sexo Opuesto y el botón
   del paso anterior en el pie.
   ============================================================ */
/* Un paso hecho se toca para regresar a él; debajo de su nombre, su ganador en la letra del oro. */
.step.is-go { cursor: pointer; }
.step.is-go:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; border-radius: var(--r-field); }
.step-win { margin-top: 2px; font: 700 var(--label)/1.2 var(--sans); color: var(--navy); font-variant-numeric: tabular-nums; }
/* El paso al centro: su nombre y, debajo, quiénes compiten. La guía va al centro del pie. */
.ring-step { margin: 0; text-align: center; }
.ring-step .t-title { font-size: 22px; }
.ring-step .t-small { margin-top: 2px; font-size: 14px; color: var(--muted); }
/* El ganador del Sexo Opuesto: borde y nombre del paso en azul. */
.ring-tile.is-opposite { border-color: var(--navy); background: var(--tint); }
.ring-tile.is-opposite .ring-tile-place { color: var(--navy); }
/* El botón del paso anterior, a la izquierda del pie, con su flecha de ícono. */
.ring-foot-back svg { width: var(--icon); height: var(--icon); fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* En una ventana, el dato menor bajo la etiqueta de una fila (el punto de un paso). */
.dialog .kv-label small { display: block; font-size: var(--small); }

/* ============================================================
   Alianz Virtual: Mis perros (spec #303). La fotografía del perro y la tarjeta del perro, una sola pieza para
   Mis perros, Perfil › Perros y el feed.
   ============================================================ */

/* ---------- Fotografía del perro ---------- */
/* La fotografía oficial si el perro es VERIFICADO y la tiene; si no, el cuadro neutro con la inicial del nombre en
   Playfair. Nunca silueta ni emoji (brand.md). En una lista mide --thumb; a todo lo ancho (el feed), .dog-photo-wide. */
.dog-photo { display: grid; place-items: center; width: var(--thumb); height: var(--thumb); flex: none; overflow: hidden; border-radius: var(--r-btn); background: var(--neutral-soft); color: var(--muted); font: 700 calc(var(--thumb) / 2)/1 var(--serif); }
.dog-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.dog-photo-wide { width: 100%; height: auto; aspect-ratio: 4 / 3; border-radius: 0; font-size: calc(var(--big) * 2); }

/* ---------- Tarjeta del perro ---------- */
/* La fotografía, el nombre registrado (.t-name), raza · sexo (.t-small), los sellos y la flecha (.nav-row-chev).
   Toda la tarjeta se toca. La destacada (.card-featured) la elige cada pantalla. */
.dog-card { display: flex; align-items: center; gap: var(--s3); width: 100%; color: var(--text); font: inherit; text-align: left; cursor: pointer; }
.dog-card + .dog-card { margin-top: var(--s2); }
.dog-card:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.dog-card-text { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.dog-card-seals { display: flex; flex-wrap: wrap; gap: var(--s1); margin-top: var(--s1); }

/* ---------- Fotografía grande del perro ---------- */
/* La ficha (#305): a todo lo ancho de la tarjeta crema, con la esquina de la hoja. La oficial lleva su aro dorado fino
   (.dog-photo-ring); sin ella, el cuadro neutro dice «Sin fotografía oficial» en dato secundario. */
.dog-photo-big { width: 100%; height: auto; aspect-ratio: 4 / 3; margin-bottom: var(--s2); font: 500 var(--small)/1.3 var(--sans); }
/* Sobre la tarjeta crema, el cuadro neutro lleva un borde fino para no perderse en el fondo. */
.card-featured .dog-photo-big { box-shadow: inset 0 0 0 1px var(--cream-line); }
.dog-photo-ring, .card-featured .dog-photo-ring { box-shadow: 0 0 0 var(--photo-ring) var(--gold); }

/* ---------- Dato secundario bajo el valor de una fila ---------- */
/* La marca bajo el número del microchip: <span class="kv-value">…<span class="kv-sub">Datamars</span></span>. */
.kv-sub { display: block; margin-top: 2px; font-size: var(--small); font-weight: 400; color: var(--muted); }

/* ---------- Filas de navegación: enlace y ocupada ---------- */
/* Una fila que abre otra página (la ficha pública) es un enlace sin subrayado. Una fila ocupada (aria-busy, el
   certificado mientras se prepara) no responde a otro toque. */
a.nav-row { text-decoration: none; }
.nav-row[aria-busy="true"] { cursor: progress; pointer-events: none; }

/* ---------- La ficha y sus pantallas de adentro ---------- */
/* La cabeza de la ficha (#305): el nombre registrado (.t-title) y, debajo, el nombre de llamado y raza · sexo · edad
   (.t-small). El título de cada pantalla de adentro, .screen-title, con el mismo aire. */
.dog-head { margin: var(--s1) 0 var(--s4); }
.dog-head .t-small { margin-top: var(--s1); }
.screen-title { margin: var(--s1) 0 var(--s4); }
/* Árbol genealógico: Padre o Madre, el nombre, el número y el sello, uno debajo del otro, en una fila de navegación.
   Solo el registrado en Alianz (un enlace) se toca. Debajo, «Ver árbol completo» en .dog-tree-actions. */
.parent-row { cursor: default; }
a.parent-row { cursor: pointer; }
.parent-row .nav-row-text { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.dog-tree-actions { margin-top: var(--s4); }
/* La fotografía oficial en grande, en su hoja que sube. */
.sheet-photo { margin: var(--s3) 0 var(--s5); }
/* Revalidar pedigrí (#308): la línea bajo el título, el aviso rojo de un envío que falló y los botones. */
.reval-line { margin: 0 0 var(--s5); }
.reval-msg { margin-top: var(--s4); }
.reval-actions { margin-top: var(--s5); }

/* ---------- Tarjeta de título y barra de avance ---------- */
/* Títulos y puntos (#306): el nombre del título (.t-name) con su sello a la derecha, las filas Puntos y Jueces (.kv) y
   la barra de avance debajo: el oro es lo que lleva, la línea lo que falta. */
.title-card + .title-card { margin-top: var(--s2); }
.title-card-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s3); }
.title-card .btn, .title-card .notice { margin-top: var(--s3); }
.title-card .t-small { margin-top: var(--s2); }
.progress { height: 6px; margin-top: var(--s2); border-radius: var(--r-pill); background: var(--line); overflow: hidden; }
.progress > i { display: block; height: 100%; background: var(--gold); }
/* ---------- Exposición plegable ---------- */
/* Actividad en pista (#307): una tarjeta blanca por exposición, un <details class="card expo">. Plegada, el <summary>
   lleva el evento y la exposición (.t-name), fecha · número · categoría (.t-small), lo mejor que ganó (.expo-best) o el
   sello de su estado, y la flecha, que gira al abrirla. Abierta, .expo-body con la espera (.expo-wait) y un
   .expo-result por resultado: la calificación y los puntos son sellos (.expo-seals); el resultado anulado lleva
   .expo-annulled en rojo y su punto, .seal-struck. */
/* La liga de un correo lleva a la vista la exposición abierta: queda bajo el encabezado, no detrás. */
.card.expo { padding: 0; overflow: hidden; scroll-margin-top: calc(var(--tap) + var(--s4)); }
.expo + .expo { margin-top: var(--s2); }
.expo > summary { display: flex; align-items: center; gap: var(--s3); min-height: var(--tap); padding: var(--s4); list-style: none; cursor: pointer; }
.expo > summary::-webkit-details-marker { display: none; }
.expo > summary:focus-visible { outline: 2px solid var(--navy); outline-offset: -2px; }
.expo-text { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.expo-best { margin-top: var(--s1); font-weight: 600; color: var(--navy); }
.expo .nav-row-chev { transition: transform .15s; }
.expo[open] .nav-row-chev { transform: rotate(90deg); }
.expo-body { padding: 0 var(--s4); border-top: 1px solid var(--line); }
.expo-wait { padding: var(--s3) 0; border-bottom: 1px solid var(--line); font-size: var(--small); color: var(--muted); }
.expo-result { padding: var(--s3) 0; border-bottom: 1px solid var(--line); }
.expo-wait:last-child, .expo-result:last-child { border-bottom: 0; }
.expo-headline { display: block; font-weight: 600; }
.expo-result .kv { padding-bottom: 0; border-bottom: 0; }
.expo-result .kv-note { padding-bottom: 0; border-bottom: 0; color: var(--text); }
.expo-seals { display: flex; flex-wrap: wrap; gap: var(--s1); margin-top: var(--s2); }
.expo-seals:first-child { margin: 0 0 var(--s2); }
.expo-annulled { display: block; margin-top: var(--s2); font-size: var(--small); font-weight: 600; color: var(--red); }
.seal-struck { text-decoration: line-through; }

/* ============================================================
   El camino de pasos (prototipo #260, ronda 6): Verificación (spec #319) y Mejor de Raza en la pista (spec #310).
   ============================================================ */
:root {
  /* El circulito de cada paso, la raya que los une y el halo del paso en curso: su ancho y su color (--gold, translúcido). */
  --step-dot: 32px;
  --step-rule: 2px;
  --step-halo: 4px;
  --step-halo-color: rgba(201, 169, 97, .25);
}

/* ---------- Camino de pasos ---------- */
/* Debajo de la barra, a todo lo ancho: un circulito por paso con su nombre debajo, unidos por una raya.
   <ol class="steps"><li class="step is-done"><span class="step-dot"><svg>…</svg></span><span class="step-name">…</span></li>
   <li class="step" aria-current="step"><span class="step-dot">2</span>…</li>…</ol>
   Hecho (.is-done): azul con la palomita dorada. En curso (aria-current="step"): borde dorado con su halo. Pendiente:
   borde gris y su número. La raya llega azul hasta el paso en curso. */
.steps { display: flex; align-items: flex-start; flex: none; margin: 0; padding: var(--s4) var(--s3) 14px; list-style: none; background: var(--white); border-bottom: 1px solid var(--line); }
.step { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; text-align: center; }
.step::before { content: ""; position: absolute; top: calc((var(--step-dot) - var(--step-rule)) / 2); right: 50%; left: -50%; height: var(--step-rule); background: var(--line); }
.step:first-child::before { display: none; }
.step.is-done::before, .step[aria-current="step"]::before { background: var(--navy); }
.step-dot { position: relative; z-index: 1; display: grid; place-items: center; box-sizing: border-box; width: var(--step-dot); height: var(--step-dot); border-radius: 50%; border: var(--step-rule) solid var(--cream-line); background: var(--white); color: var(--muted); font: 700 var(--small)/1 var(--sans); font-variant-numeric: tabular-nums; }
.step-dot svg { display: block; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.step.is-done .step-dot { border-color: var(--navy); background: var(--navy); color: var(--gold); }
.step[aria-current="step"] .step-dot { border-color: var(--gold); background: var(--tint); color: var(--navy); box-shadow: 0 0 0 var(--step-halo) var(--step-halo-color); }
.step-name { margin-top: var(--s2); padding: 0 var(--s1); font: 600 var(--label)/1.25 var(--sans); color: var(--muted); }
.step.is-done .step-name { color: var(--text); }
.step[aria-current="step"] .step-name { color: var(--navy); }
/* El camino de pasos de Mejor de Raza (.steps.ring-steps): una franja delgada y circulitos chicos. Es una rejilla de
   columnas automáticas: cada paso empieza en su palabra más larga y crece hasta su nombre en una línea, así los
   nombres largos bajan a dos líneas cortas y centradas antes que juntarse. Entre dos nombres quedan al menos 12 px
   (6 de cada lado). La raya se dibuja en dos mitades (la de la derecha toma el color del paso que sigue) para que una
   a los circulitos con pasos de distinto ancho. */
.ring-steps { --step-dot: 26px; --step-halo: 3px; display: grid; grid-auto-flow: column; grid-auto-columns: auto; padding: 7px var(--s2); }
.ring-steps .step { min-width: auto; }
.ring-steps .step::before { left: 0; right: 50%; }
.ring-steps .step::after { content: ""; position: absolute; top: calc((var(--step-dot) - var(--step-rule)) / 2); left: 50%; right: 0; height: var(--step-rule); background: var(--line); }
.ring-steps .step:last-child::after { display: none; }
.ring-steps .step:has(+ .step.is-done)::after, .ring-steps .step:has(+ .step[aria-current="step"])::after { background: var(--navy); }
.ring-steps .step-dot { font-size: 12px; }
.ring-steps .step-dot svg { width: 14px; height: 14px; }
.ring-steps .step-name { margin-top: 3px; padding: 0 6px; font-size: 11.5px; line-height: 1.2; text-wrap: balance; }
.ring-steps .step-win { margin-top: 0; font-size: 12px; line-height: 1.1; }

/* ============================================================
   El ícono de cámara (spec #319): el cuadro vacío de la fotografía oficial en Verificación.
   ============================================================ */
:root {
  --icon-camera: 40px;
}

/* ---------- Ícono de cámara ---------- */
/* De trazo, como los demás íconos de la hoja, y del color del texto que lo rodea:
   <span class="icon-camera" aria-hidden="true"></span>. */
.icon-camera { display: block; flex: none; width: var(--icon-camera); height: var(--icon-camera); background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3z'/%3E%3Ccircle cx='12' cy='13' r='3.5'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3z'/%3E%3Ccircle cx='12' cy='13' r='3.5'/%3E%3C/svg%3E") center / contain no-repeat; }

/* ============================================================
   La fila que se marca (spec #334): los perros y los días de Inscribir perros.
   ============================================================ */
:root {
  /* La casilla, su esquina y la palomita de adentro. */
  --check-box: 22px;
  --check-box-r: 6px;
  --check-mark: 16px;
}

/* ---------- Fila que se marca ---------- */
/* Un grupo con borde, como las filas de navegación. Cada fila es un botón con su casilla, lo que se marca (la
   fotografía del perro, si es un perro) y el texto, con su dato secundario en <small>:
   <div class="check-rows"><button type="button" class="check-row" role="checkbox" aria-checked="false">
   <span class="check-box"><svg>…</svg></span><span class="check-row-text">…<small>…</small></span></button></div>
   Marcada (aria-checked="true"): la casilla azul con la palomita blanca y el fondo de fila elegida. Apagada (un
   <div class="check-row" aria-disabled="true">, sin casilla): no se toca y su texto va en gris. */
.check-rows { border: 1px solid var(--line); border-radius: var(--r-card); overflow: hidden; }
.check-row { display: flex; align-items: center; gap: var(--s3); box-sizing: border-box; width: 100%; min-height: var(--tap); padding: var(--s3) var(--s4); border: 0; border-bottom: 1px solid var(--line); background: var(--white); color: var(--text); font: 400 var(--body)/1.3 var(--sans); text-align: left; cursor: pointer; }
.check-row:last-child { border-bottom: 0; }
.check-row:focus-visible { outline: 2px solid var(--navy); outline-offset: -2px; }
.check-row[aria-checked="true"] { background: var(--tint); }
.check-row[aria-disabled="true"] { cursor: default; }
.check-row[aria-disabled="true"] .check-row-text, .check-row[aria-disabled="true"] .t-name { color: var(--muted); }
.check-row[aria-disabled="true"] .dog-photo { opacity: .5; }
.check-box { display: grid; place-items: center; box-sizing: border-box; flex: none; width: var(--check-box); height: var(--check-box); border: 2px solid var(--cream-line); border-radius: var(--check-box-r); background: var(--white); color: transparent; }
.check-box svg { display: block; width: var(--check-mark); height: var(--check-mark); fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.check-row[aria-checked="true"] .check-box { border-color: var(--navy); background: var(--navy); color: var(--white); }
.check-row-text { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.check-row-text small { display: block; font-size: var(--label); color: var(--muted); }
.check-row-text .seal { margin-top: var(--s1); }

/* ============================================================
   El número grande con su nombre (spec #334): Inscripción confirmada.
   ============================================================ */
:root {
  /* El ancho más chico de cada número en la rejilla: dos por renglón en el celular. */
  --big-number-min: 140px;
}

/* ---------- Número grande con su nombre ---------- */
/* Una rejilla de tarjetas; cada una lleva el número de catálogo (.t-big) y, debajo, el perro y, si hace falta,
   el día en dato secundario:
   <div class="big-numbers"><div class="card big-number"><span class="t-big">47</span>
   <span class="big-number-name">Bruno del Altiplano</span><span class="t-small">Sáb 17 oct</span></div></div> */
.big-numbers { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--big-number-min), 1fr)); gap: var(--s3); }
.big-number { display: flex; flex-direction: column; align-items: center; gap: var(--s1); text-align: center; }
.big-number .t-big { color: var(--navy); margin-bottom: var(--s1); }
.big-number-name { font-size: var(--small); font-weight: 600; color: var(--text); overflow-wrap: anywhere; }

/* ============================================================
   Alianz Virtual: la página del evento (spec #334). La portada y quién organiza.
   ============================================================ */
:root {
  /* La portada del evento: ancha y baja, para que el nombre quede a la vista. */
  --cover-ratio: 2 / 1;
}

/* ---------- Portada del evento ---------- */
/* La fotografía del evento a todo lo ancho, con la esquina de la tarjeta y sin letra encima:
   <img class="event-cover" src="…" alt="">. Sin portada, no sale. */
.event-cover { display: block; width: 100%; height: auto; aspect-ratio: var(--cover-ratio); object-fit: cover; border-radius: var(--r-card); background: var(--neutral-soft); }

/* ---------- Quién organiza ---------- */
/* El logo de quien organiza en un cuadro (el de la marca de la cuenta de ADOS) y su nombre:
   <div class="org-row"><span class="org-mark"><img src="…" alt=""></span><span class="org-name">…</span></div>.
   Sin logo, sus iniciales en blanco sobre azul con el aro dorado: <span class="org-mark org-mark-ini">CC</span>. */
.org-row { display: flex; align-items: center; gap: var(--s3); margin: var(--s3) 0; }
.org-mark { display: grid; place-items: center; width: var(--account-mark); height: var(--account-mark); flex: none; overflow: hidden; box-sizing: border-box; border-radius: var(--r-field); background: var(--white); box-shadow: inset 0 0 0 1px var(--line); }
.org-mark img { display: block; width: 100%; height: 100%; object-fit: contain; }
.org-mark-ini { background: var(--navy); color: var(--white); font-weight: 600; font-size: var(--small); box-shadow: inset 0 0 0 1px var(--gold); }
.org-name { min-width: 0; font-weight: 600; }

/* ============================================================
   Invitar socios (spec #390, ticket #397): la fila de una invitación enviada.
   ============================================================ */
/* El correo y la fecha en dato secundario a la izquierda; a la derecha el sello y, si se puede, «Reenviar»:
   <div class="card card-rows"><div class="inv-row"><div class="inv-row-text"><span>pablo@correo.mx</span>
   <span class="t-small">Vence el 14 nov</span></div><div class="inv-row-side"><span class="seal seal-amber">Pendiente</span>
   <button type="button" class="btn btn-secondary btn-small">Reenviar</button></div></div></div> */
.inv-row { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) 0; border-bottom: 1px solid var(--line); }
.inv-row:last-child { border-bottom: 0; }
.inv-row-text { flex: 1; min-width: 0; }
.inv-row-text span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.inv-row-side { display: flex; flex-direction: column; align-items: flex-end; gap: var(--s1); }
.inv-row-side .btn-small { padding: 0 var(--s3); }
