html { font-size: 17px; }
body { -webkit-tap-highlight-color: transparent; padding-bottom: 80px; }
button { min-height: 52px; font-size: 1rem; font-weight: 600; }
input, textarea, select { font-size: 1rem; min-height: 52px; }
textarea { min-height: 90px; }
/* Placeholder con el gris del sistema (--muted, 6,26:1 sobre blanco). El gris por defecto de Tailwind medía 2,54:1. */
/* "html" delante: app.css (preflight de Tailwind) carga después con la misma especificidad y ponía #9ca3af. */
html input::placeholder, html textarea::placeholder { color: rgb(var(--muted, 91 97 104)); opacity: 1; }
/* Arriba, sobre la barra de la pantalla (no sobre el título de la primera tarjeta ni sobre el botón de abajo). */
/* Posición real la fija utils.js placeToast (toast-core.js toastPlacement): ENCIMA de lo fijo de abajo (botón
   principal o barra) y centrado en la columna de contenido. Historia: abajo tapaba el botón (ronda 1), arriba el título
   de la primera tarjeta (ronda 3) y la cabecera con volver/Edit (ronda 4). Este top es sólo el respaldo sin JS. */
.toast { position: fixed; top: calc(env(safe-area-inset-top, 0px) + 8px); left: 50%; transform: translateX(-50%); width: max-content; max-width: min(92vw, 560px); display: flex; align-items: center; gap: 10px; background: #15803d; color: #fff; padding: 8px 14px; border-radius: 12px; font-size: 0.95rem; font-weight: 600; line-height: 1.35; box-shadow: 0 10px 30px rgba(0,0,0,.25); z-index: 999; animation: slideUp .3s ease; }
/* Colores por tipo: contraste medido en tests/unit/toast.test.mjs (success 5,02 · error 6,47 · warn 8,15). */
.toast-success { background: #15803d; color: #fff; pointer-events: none; } /* no bloquea: el toque pasa a lo de abajo */
.toast .toast-retry { pointer-events: auto; } /* el botón del aviso (Undo, Not sent) SÍ se toca: antes heredaba none y era imposible deshacer */
/* Texto de error que cambia con el modo (token --bad): el red-700 fijo daba ~2,9:1 sobre el papel oscuro. */
.text-bad { color: rgb(var(--bad)); }
.toast-error { background: #b91c1c; color: #fff; }
.toast-warn { background: #fef3c7; color: #78350f; border: 2px solid #f59e0b; }
.toast-icon { display: inline-flex; flex: none; }
/* Ronda 15: en la hoja de "More" el globo va junto a su etiqueta (no en left:50% como en la barra). */
/* Ronda 17: al llevar un campo a la vista (foco, Tab), que no quede debajo del botón fijo ni de la barra de abajo. */
.jd input, .jd select, .jd textarea { scroll-margin-top: 96px; scroll-margin-bottom: 170px; }
.nav-badge.nav-badge-inline { position: static; margin-left: 8px; box-shadow: none; }
/* Ronda 13: "Try again" dentro del aviso de error: 48 px, borde del color del texto (blanco sobre el rojo, 6,47:1). */
.toast > span:not(.toast-icon) { text-wrap: pretty; }
/* Con "Try again": el botón baja a una segunda fila (alineado con el texto) y el texto conserva su ancho: 1–2 líneas
   a 390 (al lado del botón quedaban 4). La X sigue en la primera fila. */
.toast-has-retry { flex-wrap: wrap; }
.toast-has-retry > span:not(.toast-icon) { flex: 1 1 calc(100% - 100px); }
.toast-has-retry .toast-retry { order: 5; margin-left: 30px; }
.toast-retry { flex: none; min-height: 48px; padding: 0 14px; border: 2px solid currentColor; border-radius: 10px; background: transparent; color: inherit; font-weight: 700; white-space: nowrap; }
.toast-close { display: inline-flex; align-items: center; justify-content: center; min-width: 48px; min-height: 48px; margin: -10px -10px -10px 0; background: transparent; color: inherit; font-size: 1.1rem; border-radius: 10px; flex: none; }
@keyframes slideUp { from { opacity: 0; transform: translate(-50%, 20px); } to { opacity: 1; transform: translate(-50%, 0); } }
.pulse { animation: pulse 1.5s infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .5; } }
.chip { flex-shrink: 0; padding: 8px 16px; border-radius: 999px; border: 2px solid transparent; font-size: .9rem; font-weight: 600; cursor: pointer; transition: all .15s; }
.chip:active { transform: scale(.95); }
.hide-scroll::-webkit-scrollbar { display: none; }
.hide-scroll { -ms-overflow-style: none; scrollbar-width: none; }
.bottom-nav { position: fixed; bottom: 0; left: 0; right: 0; background: rgb(var(--card)); border-top: 1px solid rgb(var(--line)); display: flex; justify-content: space-around; padding: 8px 0; z-index: 50; box-shadow: 0 -4px 20px rgba(0,0,0,.08); }
/* Íconos Lucide (2026-10-08). Activo: ink + barra hi-vis arriba (forma, no sólo color). Inactivo: muted (6,3:1). */
.bottom-nav button { position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; min-height: 56px; padding: 6px 4px 4px; font-size: .875rem; font-weight: 600; color: rgb(var(--muted)); background: transparent; border: none; cursor: pointer; font-family: Inter, system-ui, sans-serif; }
.bottom-nav button { min-width: 0; }
@media (max-width: 399px) { .bottom-nav button { padding-left: 2px; padding-right: 2px; } } /* 5 ítems de ≥ 64 px: a 320/360 la barra medía 362/361 px (salto-arranque.e2e) */
@media (max-width: 359px) { .bottom-nav button { font-size: .8125rem; } }
/* Fila «Quick» + «Schedule» de la tarjeta de trabajo: a 320 px (nowrap) medía 361 y ensanchaba toda la página y la barra inferior. Sin wrap (cambiaba la altura de Inicio a 390): sólo menos relleno. */
@media (max-width: 379px) { article [data-quick], article [data-schedule-job] { padding-left: .25rem; padding-right: .25rem; gap: .25rem; } }
.bottom-nav button.active { color: rgb(var(--ink)); }
.bottom-nav .nav-items > button.active::before { content: ''; position: absolute; top: -9px; left: 22%; right: 22%; height: 3px; border-radius: 0 0 3px 3px; background: rgb(var(--hivis)); }
.bottom-nav button:focus-visible { outline: 2px solid rgb(var(--ink)); outline-offset: -2px; border-radius: 10px; }
.bottom-nav button .nav-icon { display: grid; place-items: center; line-height: 1; }
.bottom-nav button .nav-icon svg { transition: transform .15s ease; }
.bottom-nav button:active .nav-icon svg { transform: scale(.92); }
@media (prefers-reduced-motion: reduce) { .bottom-nav button .nav-icon svg { transition: none; } }
/* Celular: con más de 5 secciones se muestran 4 + "More" (hoja con el resto). Escritorio: barra lateral con todo. */
.bottom-nav .nav-more { display: none; }
@media (max-width: 767px) {
  .bottom-nav .nav-extra { display: none; }
  .bottom-nav .nav-more { display: flex; }
}
.nav-sheet { margin: auto 0 0; width: 100%; max-width: 100%; border: 0; border-radius: 20px 20px 0 0; padding: 8px 16px max(16px, env(safe-area-inset-bottom)); background: rgb(var(--card)); color: rgb(var(--ink)); }
.nav-sheet::backdrop { background: rgba(15, 23, 42, .45); }
.nav-sheet-head { display: flex; align-items: center; justify-content: space-between; font-weight: 700; padding: 4px 0 8px; }
.nav-sheet-head button { min-width: 48px; min-height: 48px; font-size: 1.1rem; border-radius: 12px; }
.nav-sheet ul { display: grid; gap: 4px; }
/* La hoja vive dentro de .bottom-nav: hay que pisar el estilo de los botones de la barra (columna, centrado, gris). */
.bottom-nav .nav-sheet button { flex: none; flex-direction: row; min-height: 48px; color: rgb(var(--ink)); }
.bottom-nav .nav-sheet li button { width: 100%; display: flex; align-items: center; justify-content: flex-start; gap: 12px; min-height: 56px; padding: 0 12px; border-radius: 12px; font-weight: 600; font-size: 1rem; text-align: left; }
.nav-sheet-signout { border-top: 1px solid rgb(var(--line)); margin-top: 4px; padding-top: 4px; }
html.dark .bottom-nav .nav-sheet button { color: rgb(243 242 238); }
.bottom-nav .nav-sheet li button[aria-current="page"] { background: rgb(var(--paper)); box-shadow: inset 3px 0 0 rgb(var(--hivis)); }
.bottom-nav .nav-sheet li button .nav-sheet-icon { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; background: rgb(var(--paper)); color: rgb(var(--ink)); }
html.dark .nav-sheet { background: rgb(30 33 37); color: rgb(243 242 238); }
/* Ronda 13: calendario con los tokens (claro y oscuro). Hoy = anillo de tinta; con trabajos = borde slate-500 (4,76:1)
   y el número en tinta; elegido = tinta llena. Antes azules fijos (#3b82f6, 3,68:1) sin versión oscura. */
.cal-day { box-sizing: border-box; min-width: 0; /* T12: con aspect-ratio y el min-height de button la celda pasaba de 52 px de ancho y pisaba a la vecina a 320/390 */ border-radius: 12px; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 2px; cursor: pointer; padding: 3px 2px 3px; min-height: 44px; color: rgb(var(--ink)); background: transparent; border: 2px solid transparent; }
@media (min-width: 640px) { .cal-day { aspect-ratio: 1; } }
.cal-day:hover { background: rgb(var(--paper)); }
.cal-day.today { box-shadow: inset 0 0 0 2px rgb(var(--ink)); font-weight: 700; }
.cal-day.has-jobs { border-color: transparent; } /* los puntos ya dicen "hay trabajos"; el aro gris se confundía con la selección */
html.dark .cal-day.has-jobs { border-color: transparent; }
.cal-day .day-num { font-size: 1rem; font-weight: 600; }
.cal-day .day-count { font-size: .875rem; font-weight: 700; color: rgb(var(--muted)); }
.modal-bg { position: fixed; inset: 0; background: rgba(0,0,0,.5); display: flex; align-items: center; justify-content: center; z-index: 100; padding: 16px; }
.modal { background: white; border-radius: 20px; padding: 24px; max-width: 500px; width: 100%; max-height: 90vh; overflow-y: auto; }

/* Kanban */
.kanban-col { min-width: 260px; flex-shrink: 0; }
.kanban-card { background: white; border: 2px solid #e2e8f0; border-radius: 16px; padding: 12px; margin-bottom: 8px; cursor: pointer; }

/* Controles nativos (flechas del número, ícono del calendario, barras de scroll) en el tema de la página: sin esto el
   campo de precio mostraba un recuadro blanco en oscuro y el ícono de la fecha casi no se veía (jueces, ronda 5). */
html { color-scheme: light; }
html.dark { color-scheme: dark; }
/* Dinero no se ajusta con flechitas de 0,01: sin spinners (en oscuro eran lo más brillante de la pantalla). */
input[type=number] { -moz-appearance: textfield; appearance: textfield; }
input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

/* ==================== MODO OSCURO, POR CLASE DE COLOR ====================
   Ronda 7 (jueces 2026-10-14): los remapeos por pantalla dejaban huecos (amber-800 a 1,97:1, slate-600 a 2,43:1).
   Ahora cada clase de color de Tailwind que usa js/ tiene su equivalente oscuro, sobre los grises GRAFITO de los
   tokens (papel 18 20 23 · tarjeta 30 33 37 · línea 52 57 64), no el azul pizarra de antes (tres negros sin relación).
   Valores medidos contra la tarjeta (≥ 4,5:1 texto, ≥ 3:1 bordes de campo); los verifica la auditoría automática de
   contraste en cada captura. La pantalla nueva puede usar tokens (text-muted, bg-card) o estas clases: las dos andan. */
html.dark body { background: rgb(18 20 23); color: rgb(243 242 238); }
html.dark .bg-white { background: rgb(30 33 37) !important; }
/* El presupuesto publico NO tiene variante oscura (arriba): el marco del logo conserva su fondo blanco y su filo de 1 px claro. Sin esto, .bg-white pasaba a grafito y el relleno de 6 px
   alrededor de un logo claro se leia como un borde negro grueso. */
html.dark body.public-view [data-quote-logo-frame] { background: rgb(255 255 255) !important; }
html.dark .bg-slate-50, html.dark .bg-gray-50 { background: rgb(24 26 30) !important; }
html.dark .bg-slate-100, html.dark .bg-gray-100 { background: rgb(36 40 45) !important; }
/* Las páginas públicas (presupuesto, portal) no cambian la tinta en oscuro: el gris claro vuelve a ser claro
   ("This quote is closed" quedaba con texto oscuro sobre fondo oscuro, 1,21:1). */
html.dark body.public-view .bg-slate-100, html.dark body.public-view .bg-gray-100 { background: rgb(241 245 249) !important; }
html.dark .bg-slate-200, html.dark .bg-gray-200 { background: rgb(44 48 54) !important; }
html.dark .bg-slate-400, html.dark .bg-slate-500 { background: rgb(108 114 122) !important; }
html.dark .bg-slate-700, html.dark .bg-slate-800 { background: rgb(52 57 64) !important; }
html.dark .bg-slate-900 { background: rgb(11 12 14) !important; }
/* Texto gris: 900/800 = tinta clara (14,4:1 en tarjeta); 700 = 11:1; 600/500/400 = muted (7,1:1 tarjeta, 8,0:1 papel). */
html.dark .text-slate-900, html.dark .text-slate-800 { color: rgb(243 242 238) !important; }
html.dark .text-slate-700, html.dark .text-gray-700 { color: rgb(214 211 206) !important; }
html.dark .text-slate-600, html.dark .text-slate-500, html.dark .text-slate-400, html.dark .text-gray-500 { color: rgb(167 172 179) !important; }
html.dark .text-slate-300 { color: rgb(167 172 179) !important; }
/* Bordes: los finos (100–300) son líneas; 400/500 delimitan campos (≥ 3:1 en tarjeta y papel). */
html.dark .border-slate-100, html.dark .border-slate-200, html.dark .border-slate-300, html.dark .border-gray-300, html.dark .divide-slate-200 > * + * { border-color: rgb(52 57 64) !important; }
html.dark .border-slate-400, html.dark .border-slate-500 { border-color: rgb(138 144 153) !important; }
html.dark .border-slate-900 { border-color: rgb(243 242 238) !important; }
/* Colores con significado: texto claro del mismo tono (≥ 6:1 sobre su tinte y sobre la tarjeta). */
html.dark body:not(.public-view) :is(.text-amber-900, .text-amber-800, .text-amber-700, .text-amber-600) { color: rgb(252 211 77); }
html.dark body:not(.public-view) :is(.text-green-900, .text-green-800, .text-green-700, .text-green-600) { color: rgb(134 239 172); }
html.dark body:not(.public-view) :is(.text-red-900, .text-red-800, .text-red-700, .text-red-600, .text-red-500) { color: rgb(252 165 165); }
html.dark body:not(.public-view) :is(.text-blue-900, .text-blue-800, .text-blue-700, .text-blue-600) { color: rgb(147 197 253); }
html.dark body:not(.public-view) :is(.text-purple-900, .text-purple-800, .text-purple-700, .text-purple-600, .text-violet-900) { color: rgb(196 181 253); }
html.dark body:not(.public-view) .text-orange-800 { color: rgb(253 186 116); }
/* Tintes de fondo (-50/-100): translúcidos sobre grafito, en vez de parches crema que encandilan. */
html.dark body:not(.public-view) :is(.bg-amber-50, .bg-amber-100) { background-color: rgb(245 158 11 / .16); }
html.dark body:not(.public-view) :is(.bg-green-50, .bg-green-100) { background-color: rgb(34 197 94 / .16); }
html.dark body:not(.public-view) :is(.bg-red-50, .bg-red-100) { background-color: rgb(239 68 68 / .16); }
html.dark body:not(.public-view) :is(.bg-blue-50, .bg-blue-100) { background-color: rgb(59 130 246 / .18); }
html.dark body:not(.public-view) :is(.bg-purple-50, .bg-purple-100, .bg-violet-50) { background-color: rgb(139 92 246 / .2); }
html.dark body:not(.public-view) .bg-orange-100 { background-color: rgb(249 115 22 / .18); }
/* Bordes de color (200/300/400): el tono a media opacidad, no el pastel claro que brillaba más que los campos. */
html.dark body:not(.public-view) :is(.border-amber-200, .border-amber-300) { border-color: rgb(245 158 11 / .5); }
html.dark body:not(.public-view) :is(.border-green-200, .border-green-300, .border-green-400) { border-color: rgb(34 197 94 / .5); }
html.dark body:not(.public-view) .border-red-300 { border-color: rgb(239 68 68 / .5); }
html.dark body:not(.public-view) :is(.border-blue-200, .border-blue-300) { border-color: rgb(59 130 246 / .5); }
html.dark body:not(.public-view) .border-purple-300 { border-color: rgb(139 92 246 / .5); }
html.dark body:not(.public-view) .border-orange-300 { border-color: rgb(249 115 22 / .5); }
/* Barra de navegación, hoja y modales: los mismos grises de los tokens que el resto de la app. */
html.dark .bottom-nav { background: rgb(30 33 37); border-top-color: rgb(52 57 64); }
html.dark .bottom-nav button { color: rgb(167 172 179); }
html.dark .bottom-nav button.active { color: rgb(243 242 238); }
html.dark .modal { background: rgb(30 33 37); }
html.dark .kanban-card { background: rgb(30 33 37); border-color: rgb(52 57 64); }

.cal-day.selected { background: rgb(var(--ink)) !important; color: rgb(var(--paper)) !important; border-color: rgb(var(--ink)); font-weight: 700; }
.cal-day.selected .day-count { color: rgb(var(--paper)); }


/* ==================== DESKTOP UI ==================== */
@media (min-width: 768px) {
  body:has(#app .bottom-nav) #roBanner { margin-left: 220px; } /* T12: la barra lateral fija tapaba el inicio del aviso */
  html { font-size: 17px; }
  body { padding-bottom: 0; }

  /* Sidebar nav */
  .bottom-nav {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    right: auto;
    width: 220px;
    flex-direction: column;
    justify-content: flex-start;
    padding: 12px 0;
    border-top: none;
    border-right: 1px solid rgb(var(--line));
    box-shadow: none;
    overflow: hidden;
  }
  /* En la barra lateral los ítems no se estiran a toda la altura (antes quedaban a ~100 px uno de otro). */
  .bottom-nav button {
    flex: none;
    min-height: 48px;
    flex-direction: row;
    justify-content: flex-start;
    gap: 12px;
    padding: 12px 20px;
    min-width: 0 !important;
    width: 100%;
    font-size: 1rem;
    border-radius: 0;
  }
  /* Barra lateral: el activo se marca con fondo paper y la barra hi-vis a la izquierda (no arriba). */
  .bottom-nav .nav-items > button.active::before { top: 8px; bottom: 8px; left: 0; right: auto; width: 3px; height: auto; border-radius: 0 3px 3px 0; }
  .bottom-nav button.active { background: rgb(var(--paper)); }

  /* Content area */
  /* UNA regla de margen para toda la app (F1, hallazgos H1/H2): #app ocupa siempre el ancho entero y NO se mueve; el sitio de la
     barra lateral se reserva con padding SÓLO si la pantalla pintó una barra (.bottom-nav). Pantallas sin barra (Drive, el
     cuestionario de alta, la landing, los enlaces públicos) quedan centradas en el ancho entero; entrar o salir de ellas ya
     no desplaza #app (antes el margen pasaba de 240 a 0: CLS 0,19-0,27). Sustituye a los parches por pantalla
     (boot-public, public-view, body:has([data-intake])). */
  #app {
    max-width: none !important;
    margin-left: 0;
    width: 100%;
    padding-left: 0;
  }
  #app:has(.bottom-nav) { padding-left: 220px; }

  /* Paddings moderados */
  #app .p-5 { padding: 20px 24px; }
  #app .p-6 { padding: 24px; }
  #app .max-w-2xl { max-width: 900px; }
  #app .max-w-md { max-width: 500px; }

  /* Botones */
  button { min-height: 52px; font-size: 1rem; }
  input, textarea, select { font-size: 1rem; min-height: 52px; }

  /* Modal */
  .modal { max-width: 720px !important; padding: 32px; }

  /* Header sticky del jobDetail/form/etc */
  .sticky.top-0 { border-radius: 0; }

  /* Calendar: celdas adaptadas */
  .cal-day {
    aspect-ratio: auto;
    min-height: 56px;
    max-height: 60px;
  }
  .cal-day .day-num { font-size: 1.1rem; }
  .cal-day .day-count { font-size: .875rem; }
}

@media (min-width: 1100px) {
  .bottom-nav { width: 240px; }
  body:has(#app .bottom-nav) #roBanner { margin-left: 240px; }
  #app:has(.bottom-nav) { padding-left: 240px; }
  #app .p-5 { padding: 24px 32px; }
}

/* UNA columna de contenido (F1, H6): toda pantalla con barra lateral usa el mismo ancho máximo y el mismo borde izquierdo, así el
   título no «salta» al navegar (antes 240-1280, 284-1236, 310-1210, 352-1168, 454-1066, 510-1010 según el max-w de cada vista).
   Gana a los max-w-* de Tailwind por especificidad. La cabecera usa la misma medida. */
#app:has(.bottom-nav) :is(main:not([data-card-page]), header > .mx-auto) { max-width: var(--page-w, 56rem); margin-left: auto; margin-right: auto; width: 100%; }

/* Dark mode ajustes */
html.dark .bottom-nav {
  background: rgb(30 33 37);
  border-right-color: rgb(52 57 64);
}
/* Ronda 8: el fondo de la pestaña activa sólo en el lateral (≥768), como en claro. En el teléfono pintaba un
   rectángulo oscuro de ~78 px pegado al borde que en claro no existe. */
@media (min-width: 768px) {
  html.dark .bottom-nav button.active { background: rgb(18 20 23); }
}
/* Ronda 9: barras del gráfico. En oscuro --ink es casi blanco y la barra encandilaba: gris medio (--muted, 7,08:1 medido
   sobre la tarjeta, sobra para el 3:1 de un objeto gráfico). */
.chart-bar { background: rgb(var(--ink)); }
html.dark .chart-bar { background: rgb(var(--muted)); }
/* Ronda 9: casilla propia (la nativa no expone su borde y la auditoría no la podía medir). Borde slate-500
   (4,76:1 sobre blanco); marcada = tinta con tilde del color del papel. */
/* min-height: 0: el input{min-height:52px} global ganaba al height y la casilla salía de 22×52 (ronda 11). El área
   tocable de 48 px la da la <label> que la envuelve. */
.jd-check { appearance: none; -webkit-appearance: none; flex: none; width: 22px; height: 22px; min-height: 0; margin: 0; border: 2px solid rgb(100 116 139); border-radius: 6px; background: rgb(var(--card)) center / 16px no-repeat; cursor: pointer; }
.jd-check:checked { background-color: rgb(var(--ink)); border-color: rgb(var(--ink)); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E"); }
html.dark .jd-check { border-color: rgb(148 163 184); }
html.dark .jd-check:checked { border-color: rgb(var(--ink)); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23121417' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E"); }
/* Vistas públicas sin sidebar: ya no hace falta quitar el margen (no pintan barra); sólo se esconde una barra rezagada. */
@media (min-width: 768px) {
  body.public-view .bottom-nav { display: none !important; }
}
/* ==================== ANIMATIONS & POLISH ==================== */

/* Cambio de tema: los botones llevan transition-colors y cada uno cambiaba a su ritmo (dueño 2026-10-23: parpadeo).
   Mientras html.theme-switching está puesta (dos cuadros, la pone toggleDark) nada transiciona: todo cambia a la vez. */
html.theme-switching *, html.theme-switching *::before, html.theme-switching *::after { transition: none !important; }


/* Page transition: sólo al ENTRAR a una pantalla (render() pone data-enter ~400 ms). Antes corría en cada repintado,
   y cada toque de un botón hacía parpadear la página entera (dueño 2026-10-21, no-flicker.e2e). */
#app[data-enter] > div {
  animation: pageFadeIn 0.25s ease-out;
}
@keyframes pageFadeIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Button press feedback */
button:not(:disabled):active {
  transform: scale(0.97);
  transition: transform 0.1s;
}

/* Modal animations */
.modal-bg {
  animation: modalFadeIn 0.2s ease-out;
}
.modal {
  animation: modalSlideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes modalFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes modalSlideUp {
  from { opacity: 0; transform: translateY(20px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* Toast animation upgrade */
.toast {
  animation: toastIn 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes toastIn {
  from { opacity: 0; transform: translate(-50%, -16px) scale(0.96); }
  to { opacity: 1; transform: translate(-50%, 0) scale(1); }
}

/* Card hover on desktop */
@media (hover: hover) and (min-width: 768px) {
  #jobList > div:hover,
  .card-hover:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(0,0,0,.08);
    transition: all 0.2s ease;
  }
  #jobList > div {
    transition: all 0.2s ease;
  }
}

/* Stagger-in lists */
.stagger-in > * {
  animation: fadeSlideUp 0.3s ease-out backwards;
}
.stagger-in > *:nth-child(1) { animation-delay: 0.02s; }
.stagger-in > *:nth-child(2) { animation-delay: 0.04s; }
.stagger-in > *:nth-child(3) { animation-delay: 0.06s; }
.stagger-in > *:nth-child(4) { animation-delay: 0.08s; }
.stagger-in > *:nth-child(5) { animation-delay: 0.10s; }
.stagger-in > *:nth-child(6) { animation-delay: 0.12s; }
.stagger-in > *:nth-child(7) { animation-delay: 0.14s; }
.stagger-in > *:nth-child(8) { animation-delay: 0.16s; }
.stagger-in > *:nth-child(n+9) { animation-delay: 0.18s; }
@keyframes fadeSlideUp {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Success pulse (para cuando completás algo) */
@keyframes checkPulse {
  0% { transform: scale(0.6); opacity: 0; }
  50% { transform: scale(1.15); }
  100% { transform: scale(1); opacity: 1; }
}
.success-pulse {
  animation: checkPulse 0.5s ease-out;
}

/* Accessibility: si el usuario prefiere menos movimiento */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
/* ==================== SKELETON LOADERS ==================== */
.skeleton {
  background: linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);
  background-size: 200% 100%;
  animation: skeletonShimmer 1.5s infinite;
  border-radius: 12px;
}
html.dark .skeleton {
  background: linear-gradient(90deg, rgb(30 33 37) 25%, rgb(52 57 64) 50%, rgb(30 33 37) 75%);
  background-size: 200% 100%;
}
@keyframes skeletonShimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ==================== NAV BADGE ==================== */
.bottom-nav button {
  position: relative;
}
.nav-badge {
  position: absolute;
  top: 4px;
  left: 50%;
  margin-left: 8px;
  /* Ronda 14: 12 px blanco sobre #b91c1c = 6,47:1 (antes 10 px sobre #ef4444 = 3,76:1). Igual en claro y oscuro: en
     oscuro --bad es un rojo claro y el blanco encima no llegaría. */
  background: #b91c1c;
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  min-width: 20px;
  height: 20px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 5px;
  box-shadow: 0 0 0 2px white;
}
html.dark .nav-badge {
  box-shadow: 0 0 0 2px rgb(30 33 37);
}

/* Campo inválido (ronda 7): borde --bad visible (no sólo el texto de abajo) y el mensaje con un ícono de alerta. */
.jd [aria-invalid="true"] {
  border-color: rgb(var(--bad)) !important;
  box-shadow: 0 0 0 1px rgb(var(--bad)) !important;
}
#desc_err:not(.hidden), #price_err:not(.hidden) {
  display: flex; align-items: flex-start; gap: .375rem;
}
#desc_err::before, #price_err::before {
  content: ""; flex: none; width: 1.1em; height: 1.1em; margin-top: .1em; 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='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 8v4M12 16h.01'/%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='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 8v4M12 16h.01'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* Ronda 20: el icono de una cabecera de tarjeta no se encoge (medía 19 px junto a títulos largos). */
[data-card-h] > svg { flex-shrink: 0; }

/* Ronda 21: cabecera de tarjeta: el icono se alinea con la PRIMERA línea del título (antes centrado en dos líneas)
   y un solo espacio título → contenido en todas las tarjetas (0.75rem). La cifra va en una píldora a la derecha. */
[data-card-h] { align-items: flex-start !important; }
[data-card-h] > svg { margin-top: calc((1.75rem - 1.25rem) / 2); }
section > [data-card-h], .rounded-2xl:not(summary) > [data-card-h] { margin-bottom: 0 !important; }
section > [data-card-h] + *, .rounded-2xl:not(summary) > [data-card-h] + * { margin-top: .75rem !important; }
.count-pill { display: inline-flex; align-items: center; margin-top: .2rem; min-width: 1.75rem; justify-content: center; border-radius: 9999px; padding: 0 .5rem; font-size: .875rem; line-height: 1.5rem; font-weight: 600; font-variant-numeric: tabular-nums; color: rgb(var(--muted)); background: rgb(var(--paper)); box-shadow: inset 0 0 0 1px rgb(var(--line)); }
/* Ronda 21: un campo bloqueado se lee cerrado aunque el aviso quede arriba: candado a la derecha sobre el papel. */
.jd [data-locked] { background-color: rgb(var(--paper)); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235B6168' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='18' height='11' x='3' y='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .75rem top .95rem; background-size: 1.15rem; padding-right: 2.75rem; }
/* Ronda 21: sin palabras huérfanas en las ayudas y párrafos. */
#app p { text-wrap: pretty; }
/* El shorthand de arriba pisa el nowrap de `truncate` (id > clase): un <p class="truncate"> se partía en 2 líneas. */
#app p.truncate { text-wrap-mode: nowrap; }
/* Ronda 21: el botón fijo no "sube" al final del scroll (medido: 129 px a 390). Debajo de su caja queda justo su
   distancia fija: 8 px + 80 px del body = 88 px en el teléfono; 0 desde 768 px (bottom-0, sin barra abajo). */
main:has(> [data-sticky-cta]:last-child) { padding-bottom: calc(8px + env(safe-area-inset-bottom)) !important; }
.jd:has(> main > [data-sticky-cta]:last-child) { padding-bottom: 0 !important; }
@media (min-width: 768px) { main:has(> [data-sticky-cta]:last-child) { padding-bottom: 0 !important; } }
/* Ronda 22: las ayudas y consejos (texto chico gris) se equilibran: sin una palabra sola en la última línea. */
#app p.text-sm.text-muted, #app [data-hint-for], #app #desc_hint { text-wrap: pretty; /* T18: balance cortaba las ayudas al ~60 % del ancho (3 jueces) */ }
/* Ronda 22: en oscuro, el chevron y el candado con el gris de oscuro (#A7ACB3): con #5B6168 medían 2,58:1 y 2,95:1. */
html.dark .jd select.appearance-none { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23A7ACB3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); }
html.dark .jd [data-locked] { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23A7ACB3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='18' height='11' x='3' y='11' rx='2'/%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'/%3E%3C/svg%3E"); }
/* Ronda 22: un campo bloqueado no se estira y la fecha no muestra su calendario nativo (quedaba bajo el candado). */
.jd textarea[data-locked] { resize: none; }
.jd input[data-locked]::-webkit-calendar-picker-indicator { display: none; }
/* Ronda 22: segunda señal de "cerrado" además del candado: la palabra "Locked" junto a la etiqueta (una señal de
   texto, que no depende del color; un relleno distinto no llegaba a 1,3:1 contra la tarjeta sin parecer error). */
.locked-tag { display: inline-flex; align-items: center; gap: .25rem; margin-left: .5rem; padding: 0 .5rem; border-radius: 9999px; font-size: .875rem; line-height: 1.5rem; font-weight: 600; color: rgb(var(--muted)); box-shadow: inset 0 0 0 1px rgb(var(--line)); vertical-align: middle; }
/* Ronda 23: la caja de fotos bloqueada lleva el mismo fondo de papel que los campos bloqueados. */
.jd [data-locked-box] { background-color: rgb(var(--paper)); }
html.scroll-locked { overflow: hidden; overscroll-behavior: none; }

/* Crédito de agencia (snippet de msagbini/agency docs/credito-agencia.md). Hereda el color de donde cae. */
.dev-credit { font-size: 0.875rem; letter-spacing: 0.02em; }
.dev-credit a { display: inline-flex; align-items: center; gap: 0.4em; color: inherit; text-decoration: none; min-height: 2.75rem; }
.dev-credit a:hover, .dev-credit a:focus-visible { text-decoration: underline; text-underline-offset: 0.18em; } /* sólo "Durazno" es el enlace */
.dev-credit strong { font-weight: 600; }
.dev-credit-wrap { display: flex; justify-content: center; padding: 0.5rem 1rem 1.5rem; color: rgb(var(--muted)); background: rgb(var(--paper)); }
.dev-credit-wrap[hidden] { display: none; }
@media (min-width: 1024px) { body:has([data-signup-col]) #devCredit { display: none; } } /* alta a 2 columnas: el panel oscuro llega al pie y el credito va dentro de la columna del formulario */
/* Modo manejo: pantalla completa sin barra inferior, sin desplazamiento (js/views/drive.js). */
body:has([data-drive]) { padding-bottom: 0; }

/* ==================== LISTAS: Filter y vistas (iteración 2, F1) ==================== */
/* Hoja inferior en el teléfono (el mismo lenguaje que "More"); popover anclado al botón desde 1024 px. */
.lt-sheet { margin: auto 0 0; width: 100%; max-width: 100%; max-height: 85dvh; border: 0; border-radius: 20px 20px 0 0; padding: 0; background: rgb(var(--card)); color: rgb(var(--ink)); box-shadow: 0 -8px 30px rgba(0,0,0,.18); display: flex; flex-direction: column; }
.lt-sheet:not([open]) { display: none; }
.lt-sheet::backdrop { background: rgba(15, 23, 42, .45); }
.lt-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 8px 0 20px; }
.lt-sheet-body { overflow-y: auto; padding: 4px 20px 8px; display: grid; gap: 16px; }
.lt-sec { border: 0; margin: 0; padding: 0; min-width: 0; }
.lt-sec-h { display: block; padding: 0; font-size: .875rem; font-weight: 700; color: rgb(var(--muted)); }
.lt-sheet-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 20px max(12px, env(safe-area-inset-bottom)); border-top: 1px solid rgb(var(--line)); }
.lt-sheet.lt-pop { position: fixed; margin: 0; width: 400px; max-height: min(560px, calc(100dvh - 120px)); border-radius: 16px; box-shadow: 0 12px 40px rgba(0,0,0,.18), 0 0 0 1px rgb(var(--line)); z-index: 60; }
.lt-pop .lt-sheet-foot { padding-bottom: 12px; }
html.dark .lt-sheet { background: rgb(30 33 37); color: rgb(243 242 238); }
/* Fila de vistas: una línea; en el teléfono se desliza y el borde derecho se desvanece sólo si hay más a la derecha. */
.lt-views { scrollbar-width: none; scroll-padding-inline: 16px; }
.lt-views::-webkit-scrollbar { display: none; }
.lt-views-wrap[data-more-right]::after { content: ''; position: absolute; top: 0; bottom: 0; right: -16px; width: 72px; pointer-events: none; background: linear-gradient(to right, rgb(var(--paper) / 0), rgb(var(--paper))); }
@media (min-width: 640px) { .lt-views-wrap[data-more-right]::after { right: 0; } }
/* Móvil angosto (≤ 380 px): las pestañas de vista se aprietan un poco (menos relleno y hueco) para que quepan tres a 360 sin cortar la última. Siguen en UNA fila que scrollea (con el degradado de «hay más») cuando son 4 o más: acomodarlas en filas costaba hasta +105 px de alto antes del contenido (medido, f2-reg-*). */
@media (max-width: 380px) { .lt-views { gap: 6px; } .lt-views > button { padding-inline: 10px; } }

/* ==================== MENÚ: negocio arriba, cuenta abajo (iteración 2, F1) ==================== */
/* Teléfono: la barra de siempre (los botones de .nav-items son hijos directos del flex). Lo de la barra lateral no se ve. */
.nav-items { display: contents; }
.nav-brand, .nav-foot { display: none; }
.nav-avatar { display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: 999px; background: rgb(var(--ink)); color: rgb(var(--paper)); font-size: .875rem; font-weight: 800; letter-spacing: .02em; }
.nav-who { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; text-align: left; }
.nav-who-name { font-weight: 700; color: rgb(var(--ink)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; overflow-wrap: anywhere; }
.nav-who-role { font-size: .875rem; font-weight: 600; color: rgb(var(--muted)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-sheet-account { display: flex; align-items: center; gap: 12px; margin: 0 0 8px; padding: 12px; border-radius: 14px; background: rgb(var(--paper)); }
.nav-sheet-sep { border-top: 1px solid rgb(var(--line)); margin-top: 4px; padding-top: 4px; }
.nav-sheet .dev-credit { margin-top: 4px; text-align: center; color: rgb(var(--muted)); }
html.dark .nav-sheet-account { background: rgb(18 20 23); }
html.dark .nav-who-name { color: rgb(243 242 238); }
/* G7: en español las etiquetas son ~20 % más largas ("Presupuestos"): la barra de abajo del teléfono usa letra un poco menor,
   márgenes mínimos y "Más" con ancho fijo (con ancho por contenido quedaba de 46 px y su globo salía de la pantalla). */
@media (max-width: 767px) {
  html[lang="es"] .bottom-nav .nav-items > button { min-width: 0; padding-left: 2px; padding-right: 2px; font-size: .75rem; letter-spacing: -.02em; }
  html[lang="es"] .bottom-nav .nav-items > .nav-more { flex: 0 0 60px; }
  html[lang="es"] .bottom-nav .nav-more .nav-badge { left: auto; right: 6px; margin-left: 0; }
}
/* G7: chip de idioma en la tarjeta de cuenta (abre Language). 44 px de alto, borde como los botones secundarios. */
.nav-lang { display: inline-flex; align-items: center; gap: 4px; flex: none; margin-left: auto; min-height: 44px; min-width: 44px; justify-content: center; padding: 0 10px; border-radius: 12px; border: 2px solid rgb(100 116 139); background: rgb(var(--card)); color: rgb(var(--ink)); font-size: .8125rem; font-weight: 700; letter-spacing: .04em; }
html.dark .nav-lang { border-color: rgb(138 144 153); }
@media (min-width: 768px) {
  .bottom-nav { display: flex; flex-direction: column; padding: 0; }
  .nav-brand { display: flex; align-items: center; gap: 8px; flex: none; min-height: 76px; padding: 12px 10px 12px 14px; border-bottom: 1px solid rgb(var(--line)); font-weight: 800; color: rgb(var(--ink)); line-height: 1.25; }
  .nav-brand-icon { display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 10px; background: rgb(var(--paper)); }
  .bottom-nav .nav-brand .nav-brand-chat { flex: none; width: 44px; height: 44px; min-height: 44px; margin-left: auto; padding: 0; border: 1px solid rgb(var(--line)); border-radius: 12px; }
  .nav-brand-name { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
  .nav-items { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 8px 0; }
  .bottom-nav .nav-items .nav-in-foot { display: none; }
  .nav-foot { display: flex; flex-direction: column; flex: none; gap: 2px; padding: 8px 12px 6px; border-top: 1px solid rgb(var(--line)); background: inherit; }
  .bottom-nav .nav-foot button { flex: none; width: 100%; min-height: 44px; padding: 0 10px; gap: 10px; border-radius: 10px; font-size: .9375rem; color: rgb(var(--ink)); justify-content: flex-start; }
  .bottom-nav .nav-foot button:hover { background: rgb(var(--paper)); }
  .bottom-nav .nav-foot button svg { flex: none; }
  .bottom-nav .nav-foot .nav-foot-link.active { color: rgb(var(--ink)); background: rgb(var(--paper)); box-shadow: inset 3px 0 0 rgb(var(--hivis)); }
  .nav-account { display: flex; align-items: center; gap: 10px; margin-top: 6px; padding: 8px 10px 4px; border-top: 1px solid rgb(var(--line)); padding-top: 12px; }
  .nav-foot-row { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
  .nav-acc-row { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
  .bottom-nav .nav-foot button { font-weight: 600; }
  .bottom-nav .nav-foot .nav-acc-btn { min-height: 40px; }
  /* Sign out aparte (jueces r1): una línea encima y su propio renglón. */
  .bottom-nav .nav-foot .nav-signout { margin-top: 4px; border-top: 1px solid rgb(var(--line)); border-radius: 0 0 10px 10px; }
  .bottom-nav .nav-foot .nav-signout.text-bad { color: rgb(var(--bad)); }
  .nav-foot .dev-credit { padding: 0 10px; color: rgb(var(--muted)); }
  .nav-foot .dev-credit a { min-height: 44px; }
  html.dark .nav-brand { color: rgb(243 242 238); border-bottom-color: rgb(52 57 64); }
  html.dark .nav-brand-icon { background: rgb(18 20 23); }
  html.dark .nav-foot, html.dark .nav-account { border-color: rgb(52 57 64); }
  html.dark .bottom-nav .nav-foot button { color: rgb(243 242 238); }
  html.dark .bottom-nav .nav-foot .nav-signout.text-bad { color: rgb(var(--bad)); }
  html.dark .bottom-nav .nav-foot button:hover, html.dark .bottom-nav .nav-foot .nav-foot-link.active { background: rgb(18 20 23); }
}
.lt-sheet:focus { outline: none; }

/* ==================== Ronda de jueces 1 (F1) ==================== */
/* Elegido: tinte suave + borde de 2 px + tilde (no un relleno oscuro: sobre el pliegue sólo va rellena la acción principal). */
.lt-on { background: rgb(var(--ink) / .07); }
html.dark .lt-on { background: rgb(243 242 238 / .10); }
/* Sombras de desplazamiento (fondo "local"): sólo se ven si hay más arriba o abajo. Lista del menú lateral y cuerpo de la
   hoja/popover de Filter (jueces r1: "Stats" y "Status" quedaban cortados sin ninguna pista). */
.lt-sheet-body, .nav-items {
  background:
    linear-gradient(rgb(var(--card)) 30%, rgb(var(--card) / 0)) top / 100% 28px no-repeat local,
    linear-gradient(rgb(var(--card) / 0), rgb(var(--card)) 70%) bottom / 100% 28px no-repeat local,
    linear-gradient(rgb(0 0 0 / .10), transparent) top / 100% 10px no-repeat scroll,
    linear-gradient(transparent, rgb(0 0 0 / .10)) bottom / 100% 10px no-repeat scroll;
}
html.dark .lt-sheet-body, html.dark .nav-items {
  background:
    linear-gradient(rgb(30 33 37) 30%, rgb(30 33 37 / 0)) top / 100% 28px no-repeat local,
    linear-gradient(rgb(30 33 37 / 0), rgb(30 33 37) 70%) bottom / 100% 28px no-repeat local,
    linear-gradient(rgb(0 0 0 / .45), transparent) top / 100% 10px no-repeat scroll,
    linear-gradient(transparent, rgb(0 0 0 / .45)) bottom / 100% 10px no-repeat scroll;
}
@media (max-width: 767px) { .nav-items { background: none !important; } }
/* Lo que sólo cambia cómo se ve (Group by, Card size) va aparte de los filtros, bajo una línea. */
.lt-display { display: grid; gap: 16px; padding-top: 14px; border-top: 1px solid rgb(var(--line)); }
/* More (teléfono): la lista se desplaza; tema, Drive mode y Sign out quedan fijos abajo, siempre a la vista. */
.nav-sheet[open] { display: flex; flex-direction: column; max-height: 88dvh; }
.nav-sheet-list { overflow-y: auto; min-height: 0; flex: 1 1 auto; }
.nav-sheet-foot { display: grid; gap: 4px; flex: none; border-top: 1px solid rgb(var(--line)); margin-top: 4px; padding-top: 4px; }
.nav-sheet-foot > li:last-child { border-top: 1px solid rgb(var(--line)); padding-top: 4px; }
.nav-sheet-head, .nav-sheet-account, .nav-sheet .dev-credit { flex: none; }
/* Leads: el resumen del día en su propia línea (partido, dejaba un "·" huérfano al comienzo de la segunda). */
#app [data-day-summary] { display: block; }
/* Escritorio (ratón): el popover más compacto para que entre más sin desplazar. */
.lt-pop .lt-sheet-body { gap: 12px; }
.lt-pop .lt-sheet-body [data-lt-opt] { min-height: 40px !important; }
.lt-pop .lt-sheet-body select { min-height: 44px; }
/* Ronda de jueces 2: las pastillas de filtro con otra forma que las vistas (esquinas de 8 px, sin borde, fondo tintado);
   el elegido algo más marcado; "Dark theme" y "Drive mode" entran en una línea en el pie. */
.lt-pill { background: rgb(var(--ink) / .08); }
.lt-pill:hover { background: rgb(var(--ink) / .12); }
html.dark .lt-pill { background: rgb(243 242 238 / .12); }
.lt-on { background: rgb(var(--ink) / .10); }
html.dark .lt-on { background: rgb(243 242 238 / .14); }
@media (min-width: 768px) { .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn { font-size: .875rem; gap: 6px; padding: 0 6px; white-space: nowrap; } }
/* Ronda 2: la lista de More también avisa que se desplaza; la fila "Dark theme · Drive mode" con aire a los lados. */
.nav-sheet-list {
  background:
    linear-gradient(rgb(var(--card)) 30%, rgb(var(--card) / 0)) top / 100% 28px no-repeat local,
    linear-gradient(rgb(var(--card) / 0), rgb(var(--card)) 70%) bottom / 100% 28px no-repeat local,
    linear-gradient(rgb(0 0 0 / .06), transparent) top / 100% 10px no-repeat scroll,
    linear-gradient(transparent, rgb(0 0 0 / .06)) bottom / 100% 10px no-repeat scroll;
}
html.dark .nav-sheet-list {
  background:
    linear-gradient(rgb(30 33 37) 30%, rgb(30 33 37 / 0)) top / 100% 28px no-repeat local,
    linear-gradient(rgb(30 33 37 / 0), rgb(30 33 37) 70%) bottom / 100% 28px no-repeat local,
    linear-gradient(rgb(0 0 0 / .45), transparent) top / 100% 10px no-repeat scroll,
    linear-gradient(transparent, rgb(0 0 0 / .45)) bottom / 100% 10px no-repeat scroll;
}
@media (min-width: 768px) {
  .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn { gap: 5px; padding: 0 4px; justify-content: center; }
  .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn svg { width: 16px; height: 16px; }
}
/* Ronda 3: el pie del menú en UNA escala (14 px desde la barrida 2026-10-23; antes 13, íconos de 16 px): Settings, Help, tema, Drive mode y Sign out. */
@media (min-width: 768px) {
  .bottom-nav .nav-foot button { font-size: .875rem; gap: 8px; }
  .bottom-nav .nav-foot button svg { width: 16px; height: 16px; }
  .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn { gap: 5px; }
}
/* Ronda 3 (jueces): las pastillas quitables sin relleno, con borde punteado: no se confunden con la vista elegida
   (tinte + borde lleno + tilde). Pie del menú con blancos de 44 px. */
.lt-pill { background: transparent; box-shadow: inset 0 0 0 1px rgb(var(--muted)); }
.lt-pill { box-shadow: none; border: 1.5px dashed rgb(var(--muted)); }
.lt-pill:hover { background: rgb(var(--ink) / .05); }
html.dark .lt-pill { background: transparent; border-color: rgb(167 172 179); }
@media (min-width: 768px) { .bottom-nav .nav-foot button, .bottom-nav .nav-foot .nav-acc-btn { min-height: 44px; } }
/* Iter 3 G1 (jueces r1): en la barra lateral el número de Stats flotaba a ~40 px de la palabra (posición del ícono de la
   barra inferior). Va pegado al rótulo. Y los ítems a 44 px: a 1280×800 la lista entera entra sobre el pie. */
@media (min-width: 768px) {
  .bottom-nav .nav-items > button .nav-badge { position: static; margin-left: 0; box-shadow: none; }
  .bottom-nav .nav-items > button { min-height: 44px; padding-top: 10px; padding-bottom: 10px; }
}
/* Iter 3 G1 (jueces / coordinador): en el pie lateral "Dark theme" y "Drive mode" se leían como un solo rótulo.
   Un divisor fino entre los dos (con más espacio "Light theme" no entra en su mitad de 92 px). */
/* (divisor entre Dark theme y Drive mode: una sola línea, la ::before de más abajo; la sombra interior la duplicaba) */
/* Teclado abierto (js/keyboard.js, dueño 2026-10-21): lo fijo de abajo se esconde mientras se escribe, así no tapa
   el campo ni come la poca pantalla que deja el teclado. Vuelve al cerrar el teclado. */
html.kb-open .bottom-nav, html.kb-open [data-sticky-cta], html.kb-open .fixed[data-assistant-open], html.kb-open [data-kb-hide] { display: none !important; }
html.kb-open .jd { padding-bottom: 16px !important; }
/* ===== Hojas y modales: un solo componente (js/sheet.js, dueño 2026-10-21) =====
   Cabecera fija con la X (no se va al desplazar) y cuerpo que desplaza. En el teléfono, hoja inferior con manija
   (Material 3: 32×4; con la cabecera la zona de arrastre pasa los 48 px), se cierra deslizando hacia abajo. */
.jd-sheet:not(dialog), dialog.jd-sheet[open] { display: flex !important; flex-direction: column; overflow: hidden !important; }
.jd-sheet > .sheet-head { flex: none; }
.jd-sheet > .sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.sheet-head-row { display: flex; align-items: center; gap: 8px; }
.sheet-head-row > .sheet-title { flex: 1 1 auto; min-width: 0; margin: 0; }
.sheet-head-row > button:last-child { margin-left: auto; }
.sheet-x { display: grid; place-items: center; min-width: 48px; min-height: 48px; flex: none; margin-right: -8px; border-radius: 12px; color: rgb(var(--ink)); }
.sheet-x:hover { background: rgb(var(--paper)); }
.sheet-x:focus-visible { outline: 2px solid rgb(var(--ink)); outline-offset: -2px; }
.sheet-grab { display: none; }
.sheet-dragging { transition: none !important; user-select: none; }
@media (max-width: 639px) {
  .modal-bg.jd-sheet-host { align-items: flex-end; padding: 0; }
  .modal-bg.jd-sheet-host > .jd-sheet, [data-scroll-lock].jd-sheet-host > .jd-sheet { width: 100% !important; max-width: 100% !important; margin: 0 !important; border-radius: 20px 20px 0 0 !important; max-height: calc(100dvh - 24px - env(safe-area-inset-top, 0px)) !important; }
  dialog.jd-sheet[open] { margin: auto 0 0 !important; width: 100% !important; max-width: 100% !important; border-radius: 20px 20px 0 0 !important; max-height: calc(100dvh - 24px - env(safe-area-inset-top, 0px)) !important; }
  .jd-sheet > .sheet-body { padding-bottom: max(16px, env(safe-area-inset-bottom, 0px)) !important; }
  .jd-sheet > .sheet-grab { display: flex; flex: none; justify-content: center; align-items: flex-start; height: 20px; padding-top: 8px; cursor: grab; touch-action: none; }
  .jd-sheet > .sheet-grab > span { width: 32px; height: 4px; border-radius: 2px; background: rgb(var(--muted) / .5); }
  .jd-sheet > .sheet-grab + .sheet-head { padding-top: 4px !important; }
  .jd-sheet > .sheet-grab + .lt-sheet-head, .jd-sheet > .sheet-grab + .nav-sheet-head { padding-top: 0; }
  .jd-sheet > .sheet-head, .jd-sheet > .lt-sheet-head, .jd-sheet > .nav-sheet-head { touch-action: none; }
  /* Filter y More ya eran hojas que aparecían sin animación (sus e2e las miden al abrir): quedan así. */
  .modal-bg.jd-sheet-host > .jd-sheet, [data-scroll-lock].jd-sheet-host > .jd-sheet, dialog.jd-sheet[open]:not(.lt-sheet):not(.nav-sheet) { animation: sheetUp .32s cubic-bezier(.32, .72, 0, 1); }
}
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes sheetFade { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .modal-bg.jd-sheet-host > .jd-sheet, [data-scroll-lock].jd-sheet-host > .jd-sheet, dialog.jd-sheet[open]:not(.lt-sheet):not(.nav-sheet) { animation: sheetFade .15s linear !important; }
}
/* El menú More tiene 8 px de margen propio arriba: la manija sube a 8 px del borde como en las demás hojas. */
@media (max-width: 639px) { .nav-sheet.jd-sheet > .sheet-grab { margin-top: -8px; } }
/* En las hojas del técnico (botones de 56 px, para usar con guantes o en la camioneta) la X agregada mide lo mismo. */
/* `.jd-sheet .sheet-close` (48 px, más abajo en este archivo, misma especificidad 0,2,0) le ganaba por orden y la X medía 48: se sube a 0,3,0. */
.sheet-x.sheet-x-lg, .jd-sheet .sheet-x.sheet-x-lg { min-width: 56px; min-height: 56px; }
/* ===== Menú ⋯ de estado (js/views/statusMenu.js) =====
   Teléfono: filas de 56 px (con guantes, en la camioneta). Escritorio: popover de 240 px con filas de 40 px y el número
   del atajo a la derecha, como el menú de estado de Linear. Lo destructivo al final, separado y en rojo (Apple HIG). */
.sm-item { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; padding: 0 12px; border-radius: 12px; text-align: left; font-weight: 600; font-size: 1rem; color: rgb(var(--ink)); }
.sm-item:hover, .sm-item:focus-visible { background: rgb(var(--paper)); outline: none; }
.sm-item:focus-visible { box-shadow: inset 0 0 0 2px rgb(var(--ink)); }
.sm-item[aria-checked="true"] { color: rgb(var(--ink)); background: rgb(var(--paper)); cursor: default; }
.sm-ic { display: grid; place-items: center; width: 20px; height: 20px; flex: none; color: rgb(var(--muted)); }
.sm-item[aria-checked="true"] .sm-ic, .sm-check { color: rgb(var(--ink)); }
.sm-danger, .sm-danger .sm-ic { color: rgb(185 28 28); }
html.dark .sm-danger, html.dark .sm-danger .sm-ic { color: rgb(252 165 165); }
.sm-sep { height: 1px; margin: 4px 8px; background: rgb(var(--line)); }
.sm-kbd { min-width: 20px; padding: 0 4px; border-radius: 4px; font: 600 12px/18px ui-monospace, monospace; text-align: center; color: rgb(var(--muted)); box-shadow: inset 0 0 0 1px rgb(var(--line)); }
.sm-pop { position: fixed; width: 240px; padding: 4px; border-radius: 12px; background: rgb(var(--card)); box-shadow: 0 12px 32px rgba(0,0,0,.18), 0 0 0 1px rgb(var(--line)); animation: smIn .12s ease-out; }
.sm-pop .sm-item { min-height: 40px; font-size: .9375rem; border-radius: 8px; gap: 10px; padding: 0 10px; }
html.dark .sm-pop { background: rgb(30 33 37); }
@keyframes smIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .sm-pop { animation: none; } }
/* Prolijidad medida (iteración 4): la raíz mide 17 px, así que h-12 = 51 px y h-14 = 59,5 px, mientras los botones de
   al lado miden 48 o 56 px exactos (min-h-[48px], !min-h-[56px]). En una misma fila se veían desparejos (ops/polish-lens:
   18 filas). Los botones de ícono cuadrados de 48 quedan en 48 px como sus vecinos (h-14 se deja: forzado a 56 con zoom medía 55,99). */
button.h-12.w-12, a.h-12.w-12 { height: 48px; width: 48px; }
/* Jueces r1 (iteración 4): una sola cabecera para todas las hojas. Título de 20 px / 700 en el mismo lugar, 16 px de
   margen a los lados en el teléfono, la X sin caja (48 px de zona, 56 en las hojas del técnico) con el glifo alineado al
   borde del contenido, y 16 px de aire entre la cabecera y lo primero. */
.jd-sheet > .sheet-head :is(h1, h2, h3):first-of-type, .jd-sheet > .lt-sheet-head h2, .jd-sheet > .nav-sheet-head > span:first-child { font-size: 1.25rem !important; line-height: 1.3 !important; font-weight: 700 !important; }
.jd-sheet .sheet-close { flex-shrink: 0; min-width: 48px; min-height: 48px; background: transparent !important; border: 0 !important; box-shadow: none !important; --tw-ring-shadow: 0 0 #0000 !important; margin-right: -12px; color: rgb(var(--ink)); }
.jd-sheet .sheet-close:hover { background: rgb(var(--paper)) !important; }
.jd-sheet .sheet-close:focus-visible { outline: 2px solid rgb(var(--ink)); outline-offset: -4px; }
.jd-sheet > .sheet-head + .sheet-body { padding-top: 8px !important; }
@media (max-width: 639px) {
  .jd-sheet > .sheet-head, .jd-sheet > .sheet-body { padding-left: 16px !important; padding-right: 16px !important; }
  .jd-sheet textarea { resize: none; } /* la esquina de redimensionar es de escritorio */
}
.sm-pop .sm-item:focus-visible { box-shadow: inset 0 0 0 1.5px rgb(var(--ink) / .55); background: rgb(var(--paper)); }
/* Jueces r2: un solo anillo de foco en el popover (el global de 2 px se sumaba al propio). */
.sm-item:focus-visible { outline: none !important; }
/* Jueces r2: el aviso de "hay más" de More, más sutil (8 px y 6 %) */
.nav-sheet-list { background-size: 100% 28px, 100% 28px, 100% 8px, 100% 8px; }
/* <select> como los campos: sin el aspecto nativo (texto 4-5 px más adentro, 3 px más bajo, flecha pegada al borde):
   mismo padding, chevron propio a 14 px del borde (jueces r2, modal de cliente). */
.jd select:not([multiple]):not([size]) { -webkit-appearance: none; appearance: none; padding-right: 2.75rem !important; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235B6168' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; background-size: 18px 18px; }
html.dark .jd select:not([multiple]):not([size]) { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23A7ACB3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); }
@media (min-width: 768px) { .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn + .nav-acc-btn { position: relative; } .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn + .nav-acc-btn::before { content: ""; position: absolute; left: -3px; top: 12px; bottom: 12px; width: 1px; background: rgb(var(--line)); } }
/* 768-1099 px (barra de 220 px): a 14 px "Dark theme" y "Drive mode" ya no caben lado a lado; una debajo de la otra (barrida 2026-10-23). */
@media (min-width: 768px) and (max-width: 1099px) { .bottom-nav .nav-foot .nav-acc-row { grid-template-columns: 1fr; } .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn + .nav-acc-btn::before { display: none; } .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn { justify-content: flex-start; } }

/* Calendario en el celular: la grilla plegada muestra sólo la semana del día elegido. */
@media (max-width: 639px) { .cal-grid[data-collapsed] .cal-day:not([data-wk-sel]) { display: none; } }
/* Pro 2026-10-23, una sola regla de cierre: en el teléfono las hojas CORTAS de menú (More, Filter, el ⋯ de estado) se cierran con la
   manija, el fondo y Atrás, sin X. Las hojas largas o de formulario, y toda hoja en escritorio, llevan la X fija arriba. */
@media (max-width: 639px) { .jd-sheet[data-sheet-menu] .sheet-close { display: none !important; } }

/* Pantalla de arranque (dueño 2026-10-23: el héroe de texto sin estilo se veía feo). Marca + una línea calma + barras;
   mismo ancho que la app para que no salte. El texto SEO sigue en el HTML, fuera de la vista. */
body{margin:0}
.boot-screen{min-height:100vh;display:flex;align-items:flex-start;justify-content:center;background:rgb(var(--paper));color:rgb(var(--ink));font-family:Inter,system-ui,sans-serif}
.boot-wrap{width:100%;max-width:56rem;padding:5.5rem 1rem 0;box-sizing:border-box;text-align:center}
.boot-brand{margin:0;font-size:1.5rem;font-weight:800;letter-spacing:-.02em}
.boot-line{margin:.5rem 0 1.75rem;font-size:.95rem;color:rgb(var(--muted))}
.boot-bars{display:grid;gap:.75rem;text-align:left}
.boot-bars span{display:block;height:4.5rem;border-radius:1rem;background:rgb(var(--line)/.35);animation:bootPulse 1.4s ease-in-out infinite}
.boot-bars span:nth-child(2){animation-delay:.15s;height:3.75rem}.boot-bars span:nth-child(3){animation-delay:.3s}
@keyframes bootPulse{0%,100%{opacity:.55}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.boot-bars span{animation:none;opacity:.8}}
html[lang=es] [data-l=en],html:not([lang=es]) [data-l=es]{display:none}
.boot-seo,#app .boot-seo{position:absolute;width:1px !important;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap} /* !important: #app:has(.bottom-nav) main pone width:100% (el esqueleto de #boot trae la barra) */
/* Sin sesión, con sesión vencida o con un enlace público (js/preboot.js pone html.boot-public): NO se muestra la maqueta de Inicio
   (marca + barras), que es de la app con sesión. El fondo es el de la página que llega, para que no haya salto de color:
   tinta de la portada (boot-ink = el fondo de su cabecera y héroe), grafito de las páginas que respetan el modo oscuro (boot-dark:
   #k= #u= #lu=) y papel claro el resto (alta, legal, enlaces q/w/sq/oa/c). Valores literales a propósito: html.dark redefine
   --paper en body antes de que el router decida (boot.js aplica dark). tests/e2e/boot-screen.e2e.mjs compara estos colores con
   los de la página ya pintada; si la portada cambia de fondo, ese test lo avisa. El router quita boot-public en su primer render. */
html.boot-public #boot{display:none}
/* Arranque con sesión (js/preboot.js pone html[data-boot=app]): #boot es el esqueleto de Inicio con la MISMA forma que pinta
   js/views/home.js (cabecera de homeShell, skShape search 48 · bar 48 · card 200 · filas de 120, medida de fábrica byBucket) y
   la barra de navegación; así el paso #boot → esqueleto de la app → Inicio no mueve nada (tests/e2e/salto-arranque.e2e.mjs).
   Sin data-boot=app (sin sesión, enlace público, JS de preboot caído) #boot no se pinta: nunca el intermedio genérico. */
html:not([data-boot="app"]) #boot{display:none}
/* Portada: sin sesión y sin enlace (html.boot-ink) el primer fotograma ya lleva la cabecera de la portada (marca, enlaces, botón), no un rectángulo liso. */
#boot-pub{display:none}
html.boot-fade-ink, html.boot-fade-ink body, html.boot-fade-ink #app{background:rgb(21 23 26) !important} /* predicción «app» equivocada: la portada entra con fundido SOBRE tinta (no pasa por un gris sucio sobre el esqueleto claro) */
#boot-pub{--ink:21 23 26;--ink-2:30 33 37;--ink-3:44 48 54;--paper:247 246 242;--card:255 255 255;--line:176 173 166;--muted:91 97 104;--on-ink:243 242 238;--on-ink-muted:167 172 179} /* la portada no tiene tema oscuro: html.dark (que boot.js pone antes de pintar) volteaba --ink y dejaba logo y botón en blanco sobre blanco */
html.dark #boot-pub section.bg-ink{color:rgb(243 242 238)} /* la regla de la app en oscuro pinta de tinta el texto sobre .bg-ink: el titular quedaba invisible */
html[data-boot="public"] .jd-landing .animate-jd-fade-up{animation:none} /* el héroe ya está a la vista (#boot-pub): un fundido desde 0 lo haría desaparecer y reaparecer */
/* #boot (display:none sin sesión) trae la barra lateral dentro: sin esto `#app:has(.bottom-nav)` empujaba 220-240 px a la derecha la cabecera de la portada a 768+ hasta que el router pintaba. Se apaga sólo mientras #boot-pub sigue ahí. */
html[data-boot="public"] #app:has(> #boot-pub){padding-left:0}
html[data-boot="public"] #app:has(> #boot-pub) header > .mx-auto{max-width:72rem} /* la regla de la app con barra lo dejaba en 56rem: el logo y el botón se movían al pintar la portada */
html[data-boot="public"].boot-ink #boot-pub{display:block;background:rgb(21 23 26)}
html[data-boot="public"].boot-ink #boot-pub header{background:rgb(21 23 26)}
.boot-home .bh-ico{display:block;width:20px;height:20px;border-radius:6px;background:rgb(255 255 255/.16)}
.boot-home .bh-t1{display:block;height:15px;width:3rem;margin:0 0 6px;border-radius:.5rem;background:rgb(255 255 255/.16)}
.boot-home .bh-t2{display:block;height:12px;width:6.5rem;max-width:90%;border-radius:.5rem;background:rgb(255 255 255/.10)}
.boot-home .bh-act{display:block;flex:none;height:48px;border-radius:.75rem;background:rgb(255 255 255/.10)}
.boot-home .bh-a1{width:48px}.boot-home .bh-a2{width:117px;background:rgb(255 107 26/.35)}.boot-home .bh-a3{display:none}
@media (max-width:339px){.boot-home .bh-a2{width:48px;background:rgb(255 107 26/.35)}}
@media (min-width:768px){.boot-home .bh-t2{display:none}.boot-home .bh-a1{width:50px}.boot-home .bh-a2{width:86px;background:rgb(255 255 255/.10)}.boot-home .bh-a3{display:block;width:117px;background:rgb(255 107 26/.35)}}
.boot-home .bh-region{display:flex;flex-direction:column;gap:12px;box-sizing:border-box;height:3426px;overflow:hidden}
@media (max-width:374px){.boot-home .bh-region{height:3617px}}
@media (max-width:339px){.boot-home .bh-region{height:3745px}}
@media (min-width:640px){.boot-home .bh-region{height:2906px}}
.boot-home .bh-search{display:flex;gap:8px;height:48px}
.boot-home .bh-blk{display:block;box-sizing:border-box;height:48px;border-radius:.75rem}
.boot-home .bh-bar{height:50px} /* la fila de vistas real mide 50: el primer aviso arranca a 215 px */
.boot-home .bh-grow{flex:1}.boot-home .bh-filter{width:51px;flex:none}
@media (min-width:640px){.boot-home .bh-filter{width:101px}}
.boot-home .bh-chips{display:flex;gap:8px;height:50px;overflow:hidden}.boot-home .bh-chips .sk{display:block;height:50px;border-radius:9999px;flex:none}
.boot-home .bh-chips .sk:nth-child(1){width:112px}.boot-home .bh-chips .sk:nth-child(2){width:142px}.boot-home .bh-chips .sk:nth-child(3){width:68px}
@media (max-width:379px){.boot-home .bh-chips .sk{height:48px}.boot-home .bh-chips .sk:nth-child(1){width:100px}.boot-home .bh-chips .sk:nth-child(2){width:131px}.boot-home .bh-chips .sk:nth-child(3){width:57px}}
.boot-home .bh-card{display:flex;align-items:center;gap:12px;box-sizing:border-box;height:101px;overflow:hidden;padding:0 16px;border-radius:1rem;border-left:4px solid rgb(var(--line));background:rgb(var(--card));box-shadow:0 0 0 1px rgb(var(--line)/.6) inset}
.boot-home .bh-ci{display:block;width:44px;height:44px;border-radius:9999px;flex:none}.boot-home .bh-cw{flex:1;min-width:0;display:grid;gap:8px}
.boot-home .bh-lbl{display:block;height:20px;width:85px;margin:7px 0}
.boot-home .bh-c1{display:block;height:16px;width:70%}.boot-home .bh-c2{display:block;height:12px;width:50%}
@media (max-width:339px){.boot-home .bh-card{height:125px}}
@media (min-width:400px){.boot-home .bh-card{height:75px}}
.boot-home .bh-list{display:flex;flex-direction:column;gap:12px;flex:1;min-height:0;overflow:hidden}
.boot-home .bh-row{display:grid;align-content:center;gap:8px;flex:none;box-sizing:border-box;height:120px;padding:0 16px;border-radius:1rem;background:rgb(var(--card));box-shadow:0 0 0 1px rgb(var(--line)/.6) inset}
.boot-home .bh-l1{display:block;height:16px;width:62%}.boot-home .bh-l2{display:block;height:12px;width:40%}
.boot-home .nav-items{display:flex;flex:1}
.boot-home .bh-nav-b{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:3px;box-sizing:border-box;height:61px;padding:6px 4px 4px}
.boot-home .bh-nav-b:nth-child(n+6){display:none}
@media (max-width:359px){.boot-home .bh-nav-b{height:59px}} /* a 320 el rótulo es de 13 px: la barra real mide 76 */
.boot-home .bh-nav-i{display:block;width:24px;height:24px;border-radius:6px}.boot-home .bh-nav-t{display:block;width:40px;height:10px;margin:7px 0}
.boot-home .bh-brand,.boot-home .bh-foot{display:none}
.boot-home .bh-nav-b:first-child{position:relative}.boot-home .bh-nav-b:first-child .sk{background:rgb(var(--ink)/.55)}
.boot-home .bh-nav-b:first-child::before{content:'';position:absolute;top:-9px;left:22%;right:22%;height:3px;border-radius:0 0 3px 3px;background:rgb(var(--hivis))}
/* Barra lateral (768+): la MISMA que pinta renderBottomNav (marca de 76 px, 10 filas de 45,5, pie de 191 px con cuenta, atajos, Sign out y sello). */
@media (min-width:768px){
  .boot-home .bh-nav{display:flex}
  .boot-home .nav-items{flex-direction:column;flex:1;gap:0;padding-top:8px}
  .boot-home .bh-nav-b:nth-child(n+6){display:flex}
  .boot-home .bh-nav-b:first-child{background:rgb(var(--paper))}.boot-home .bh-nav-b:first-child::before{top:8px;bottom:8px;left:0;right:auto;width:3px;height:auto;border-radius:0 3px 3px 0}
  .boot-home .bh-nav-b{flex:none;flex-direction:row;align-items:center;justify-content:flex-start;gap:14px;height:45.5px;padding:0 20px}
  .boot-home .bh-nav-t{width:88px;height:12px;margin:0}
  .boot-home .bh-brand{display:flex;align-items:center;gap:8px;box-sizing:border-box;height:76px;padding:0 12px 0 14px;flex:none}
  .boot-home .bh-bi{display:block;width:28px;height:28px;border-radius:8px}.boot-home .bh-bn{display:block;height:16px;width:105px}.boot-home .bh-bc{display:block;width:44px;height:44px;border-radius:12px;margin-left:auto}
  .boot-home .bh-foot{display:block;box-sizing:border-box;height:191px;padding:5px 12px 6px;flex:none;box-shadow:0 1px 0 rgb(var(--line)) inset}
  .boot-home .bh-fa{display:flex;align-items:center;gap:10px;height:48px;padding:0 4px}
  .boot-home .bh-fav{display:block;width:36px;height:36px;border-radius:9999px;flex:none}
  .boot-home .bh-fw{flex:1;display:grid;gap:6px}.boot-home .bh-fw .sk{display:block;height:12px;width:70%}
  .boot-home .bh-fl{display:block;width:44px;height:44px;border-radius:12px;flex:none}
  .boot-home .bh-fr{display:flex;gap:2px;height:44px}.boot-home .bh-fr .sk{display:block;flex:1 1 0;min-width:0;max-width:52px;height:44px;border-radius:12px}
  .boot-home .bh-fs{display:flex;align-items:center;height:44px;padding:0 8px;box-shadow:0 1px 0 rgb(var(--line)/.6) inset}.boot-home .bh-fs .sk{display:block;height:14px;width:64px;margin-left:36px}
  .boot-home .bh-fc{display:flex;align-items:center;justify-content:center;height:44px}.boot-home .bh-fc .sk{display:block;height:12px;width:150px}
}
html.boot-public:root, html.boot-public:root body, html.boot-public:root #app{background:rgb(247 246 242) !important}
html.boot-public.boot-ink:root, html.boot-public.boot-ink:root body, html.boot-public.boot-ink:root #app{background:rgb(21 23 26) !important}
html.boot-public.boot-dark:root, html.boot-public.boot-dark:root body, html.boot-public.boot-dark:root #app{background:rgb(18 20 23) !important}
@media (min-width:1024px){html.boot-public.boot-split:root, html.boot-public.boot-split:root body, html.boot-public.boot-split:root #app{background:linear-gradient(90deg, rgb(21 23 26) 47.6%, rgb(247 246 242) 47.6%) !important}} /* #signup: lg:grid-cols-[1fr_1.1fr] = 47,6 % de tinta */

/* Cuestionario de alta: flujo sin barra lateral; lo centra la regla única de #app (sin barra = ancho entero). */

/* Chat de ayuda (A5 v1) */
.modal-bg.hc-scrim { background: rgba(0, 0, 0, .68); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
[data-hc-log][data-scrolled="1"] { -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 22px); mask-image: linear-gradient(to bottom, transparent 0, #000 22px); }
/* Un solo anillo de foco (antes: borde oscuro + contorno de 3 px = doble). */
#hc_q:focus, #hc_q:focus-visible { outline-offset: -3px !important; border-color: transparent; }
@media (min-width: 768px) {
  .bottom-nav .nav-brand .nav-brand-chat { display: grid; place-items: center; justify-content: center; }
  /* Pie de la barra lateral: el activo usa la misma barra hi-vis de 3 px que el resto (el inset con esquinas redondas parecía medio marco). */
  .bottom-nav .nav-foot .nav-foot-link.active { box-shadow: none; }
  .bottom-nav .nav-foot .nav-foot-link.active::before { content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; border-radius: 0 3px 3px 0; background: rgb(var(--hivis)); }
  /* Pie de la barra lateral (ronda 3): filas a todo el ancho como las secciones: ícono en x=20, barra activa en x=0, un solo tipo de separador (con sangría de 16 px). */
  .nav-foot { padding: 0 0 6px; border-top: 0; gap: 0; }
  .nav-foot::before { content: ""; display: block; height: 1px; margin: 0 16px 6px; background: rgb(var(--line)); }
  html.dark .nav-foot::before { background: rgb(52 57 64); }
  .nav-foot-row { grid-template-columns: 1fr; gap: 0; }
  .bottom-nav .nav-foot .nav-foot-link, .bottom-nav .nav-foot .nav-acc-btn { border-radius: 0; padding: 0 20px; gap: 12px; font-size: .9375rem; }
  .nav-account { margin: 6px 16px 0; padding-left: 4px; padding-right: 4px; }
  .bottom-nav .nav-foot .nav-signout { margin: 4px 16px 0; width: calc(100% - 32px); padding: 0 4px; }
  .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn { padding: 0 20px; }
  .nav-brand { padding-right: 12px; gap: 8px; }
  .nav-acc-row { grid-template-columns: 1fr; gap: 0; } /* Dark theme y Drive mode no cabían lado a lado en 207 px (el texto se salía del botón): una fila cada uno */
  .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn { justify-content: flex-start; }
  .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn + .nav-acc-btn::before { display: none; }
}

/* Cuestionario de alta: opciones con borde de interfaz >= 3:1 (--line mide 2,2:1: sirve de divisor, no de borde de control) y radio propio
   (el nativo no se ve en oscuro). Marcado = borde y anillo de tinta. */
.jd-opt { border: 1px solid rgb(100 116 139); }
html.dark .jd-opt { border-color: rgb(148 163 184); }
.jd-opt:has(:checked) { border-color: rgb(var(--ink)); box-shadow: 0 0 0 1px rgb(var(--ink)); }
.jd-radio { appearance: none; -webkit-appearance: none; flex: none; width: 22px; height: 22px; min-height: 0; margin: 0; border: 2px solid rgb(100 116 139); border-radius: 999px; background: rgb(var(--card)); cursor: pointer; }
html.dark .jd-radio { border-color: rgb(148 163 184); }
.jd-radio:checked { border-color: rgb(var(--ink)); background: radial-gradient(circle, rgb(var(--ink)) 0 42%, rgb(var(--card)) 46%); }
details[open] > summary .ik-chev { transform: rotate(180deg); }
body:has([data-intake]) { padding-bottom: 0; }
#app [data-intake] p { text-wrap: wrap; } /* el pretty global cortaba subtítulos antes del borde de la columna */
@media (min-width: 768px) { .bottom-nav .nav-account .nav-lang { width: auto; } } /* el chip EN salía de la barra (width:100% de los botones de la barra) */

.nav-sheet-text { display: grid; gap: 1px; text-align: left; line-height: 1.25; }
.nav-sheet-sub { font-size: .8125rem; font-weight: 400; color: rgb(var(--muted)); }
@media (min-width: 768px) {
  /* Un solo estilo inactivo en la barra lateral: gris y 16 px como las secciones; el color pleno sólo para el activo. */
  .bottom-nav .nav-foot button:not(.active):not(.text-bad) { color: rgb(var(--muted)); font-size: 1rem; }
  html.dark .bottom-nav .nav-foot button:not(.active):not(.text-bad) { color: rgb(167 172 179); }
  /* El chip EN baja a la fila de "Dark theme" (a la derecha) y deja el correo entero en su línea. */
  .bottom-nav .nav-foot .nav-account { position: relative; }
  .bottom-nav .nav-foot .nav-account .nav-lang { position: absolute; right: 0; bottom: -44px; z-index: 1; }
  /* F1 (solape medido: el chip EN 69x44 pisaba la caja de «Dark theme» y, en español, tapaba 11 px del texto): el botón del tema deja a la derecha el sitio del chip. */
  .bottom-nav .nav-foot .nav-acc-row > .nav-acc-btn:first-child { width: calc(100% - 60px); font-size: .9375rem; } /* el chip de idioma (44 px, sólo ícono) queda a la derecha; los iconos y el texto de TODA la fila inferior siguen la misma regla: x=20, 20 px de ícono, 12 de hueco, 15 px de letra */
  .bottom-nav .nav-foot .nav-account .nav-lang { padding: 0; width: 44px; } .bottom-nav .nav-foot .nav-account .nav-lang .nav-lang-code { display: none; }
  .bottom-nav .nav-foot .nav-who { flex: 1; min-width: 0; }
}

/* ==================== ESPERAR BIEN: esqueletos con forma real y botón pendiente ==================== */
.sk { background-color: rgb(var(--line)/.35); background-image: linear-gradient(90deg, transparent 0%, rgb(var(--paper)/.55) 50%, transparent 100%); background-size: 200% 100%; background-repeat: no-repeat; animation: skShimmer 1.4s linear infinite; border-radius: .5rem; }
@keyframes skShimmer { 0% { background-position: 200% 0; } 100% { background-position: -100% 0; } }
.sk-hold { opacity: 0; } /* nace invisible (conserva el espacio y el texto para el lector) y aparece sólo si la espera pasa de ~150 ms */
.sk-region { display: block; }
.sk-reveal { animation: skReveal .12s ease-out; }
@keyframes skReveal { from { opacity: .55; } to { opacity: 1; } } /* desde .55, no 0: el paso esqueleto → contenido no deja un fotograma en blanco (salto-arranque.e2e) */
.pend-spin { display: inline-block; width: 1em; height: 1em; margin-right: .5em; vertical-align: -.15em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 9999px; animation: pendSpin .7s linear infinite; }
@keyframes pendSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .sk { animation: none; background-image: none; }
  .sk-reveal { animation: none; }
  .pend-spin { animation: none; border: 0; width: auto; height: auto; }
  .pend-spin::after { content: "\2022\2022\2022"; letter-spacing: .1em; }
}

/* Hoja con scroll interno (vista previa de factura): una sombra suave en el borde por el que aún hay contenido. Desaparece al llegar al final. */
.jd-sheet > .sheet-body:has([data-invoice-essentials]) {
  background:
    linear-gradient(rgb(var(--card)) 30%, rgb(var(--card) / 0)) 0 0 / 100% 36px no-repeat local,
    linear-gradient(rgb(var(--card) / 0), rgb(var(--card)) 70%) 0 100% / 100% 36px no-repeat local,
    radial-gradient(farthest-side at 50% 0, rgb(var(--ink) / .22), rgb(var(--ink) / 0)) 0 0 / 100% 12px no-repeat scroll,
    radial-gradient(farthest-side at 50% 100%, rgb(var(--ink) / .22), rgb(var(--ink) / 0)) 0 100% / 100% 12px no-repeat scroll;
  background-color: rgb(var(--card));
}

/* Un ícono dentro de un botón, enlace o ficha nunca se encoge: con el texto en una línea (nowrap) el flex lo apretaba a un punto de 7-13 px. */
button > svg, label > svg, a > svg, summary > svg, button > span > svg { flex-shrink: 0; }

/* ==================== CAMPO ÚNICO (F1: H3 / H4 / H5; js/field-core.js) ==================== */
/* Una sola definición de caja para texto, número, fecha, hora, lista y área de texto. Alto natural 64 px (relleno 1rem + línea 1.5);
   fecha y hora llevan el alto fijo porque Chrome les suma 2 px por el ícono del selector (66 contra 64). */
.jd-field { display: block; width: 100%; padding: 1rem; border: 2px solid rgb(100 116 139); border-radius: 1rem; background-color: rgb(var(--card)); color: rgb(var(--ink)); font-size: 1rem; line-height: 1.5; min-height: 48px; }
html.dark .jd-field { border-color: rgb(138 144 153); }
.jd-field.jd-select { appearance: none; -webkit-appearance: none; }
/* UN solo buscador y UNA altura de campo (F1, juicio G): el buscador es un campo con el ícono a la izquierda; la caja mide lo mismo que cualquier campo. */
.jd-field.jd-search { height: 48px; min-height: 48px; padding: 0 .75rem 0 2.75rem; border: 0; border-radius: .75rem; box-shadow: 0 0 0 1px rgb(var(--muted) / .75); }
.jd-field.jd-search:focus-visible { box-shadow: 0 0 0 2px rgb(var(--ink)); outline: none; } /* misma altura (48) y mismo borde fino que el botón Filter; el borde grueso sólo es el foco (A1) */
.jd-field:is([type=date], [type=time], [type=datetime-local], [type=month]) { height: calc(1.5em + 2rem + 4px); }
.jd-field:disabled { cursor: not-allowed; border-style: dashed; background-color: rgb(var(--paper)); }
.jd-field[aria-invalid=true] { border-color: rgb(var(--bad)); }
.jd-field.jd-field-52 { height: 52px; min-height: 52px; padding: .75rem; border-radius: .75rem; } /* ronda 4: el alta, el acceso y el presupuesto publico usan la MISMA altura de campo (52 px) */
/* Presupuesto publico: UN solo anillo al enfocar (borde + halo suave), no el contorno grueso de .jd encima del borde; en error, el mismo anillo en rojo. */
.pq-input:focus-visible, .jd .pq-input:focus-visible { outline: 0; border-color: rgb(var(--ink)); box-shadow: 0 0 0 3px rgb(var(--ink) / .16); }
.pq-input[aria-invalid=true], .pq-input[aria-invalid=true]:focus-visible, .jd .pq-input[aria-invalid=true]:focus-visible { border-color: rgb(var(--bad)); }
.jd .pq-input[aria-invalid=true]:focus-visible { box-shadow: 0 0 0 3px rgb(var(--bad) / .18); }
.jd-label { display: block; margin-bottom: .5rem; font-size: 1rem; font-weight: 500; color: rgb(var(--muted)); }

/* F1 ronda 3 (R3-3): pie de la barra lateral compacto: cuenta (avatar, nombre, idioma) + UNA fila de íconos (Settings, Help, tema, Drive) con tooltip y nombre accesible + Sign out + crédito.
   Antes ~344 px (cada acción era una fila); ahora <= ~170 px. Con las filas en `display: contents` los botones son hijos de la rejilla del pie. */
@media (min-width: 768px) {
  .bottom-nav .nav-foot { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0 2px; padding: 0 12px 4px; }
  .bottom-nav .nav-foot::before { grid-column: 1 / -1; margin: 0 4px 4px; }
  .bottom-nav .nav-foot .nav-foot-row, .bottom-nav .nav-foot .nav-acc-row { display: contents; }
  .bottom-nav .nav-foot .nav-account { grid-column: 1 / -1; order: 0; margin: 0; padding: 2px 4px; border-top: 0; position: static; }
  .bottom-nav .nav-foot .nav-account .nav-lang { position: static; margin-left: auto; width: 44px; padding: 0; }
  .bottom-nav .nav-foot .nav-foot-link, .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn, .bottom-nav .nav-foot .nav-acc-row > .nav-acc-btn:first-child { order: 1; grid-column: auto; width: auto; min-height: 44px; height: 44px; padding: 0; margin: 0; justify-content: center; font-size: 0 !important; gap: 0; border-radius: 10px; position: relative; overflow: hidden; }
  .bottom-nav .nav-foot .nav-foot-link svg, .bottom-nav .nav-foot .nav-acc-row .nav-acc-btn svg { width: 22px; height: 22px; flex: none; }
  .bottom-nav .nav-foot .nav-foot-link.active { background: rgb(var(--paper)); box-shadow: inset 0 -3px 0 rgb(var(--hivis)); }
  .bottom-nav .nav-foot .nav-foot-link.active::before { display: none; }
  .bottom-nav .nav-foot .nav-signout { grid-column: 1 / -1; order: 2; margin: 2px 0 0; width: 100%; padding: 0 8px; font-size: .9375rem; gap: 22px; justify-content: flex-start; min-height: 44px; }
  .bottom-nav .nav-foot .dev-credit { grid-column: 1 / -1; order: 3; padding: 0 8px; margin: 0; font-size: .875rem; line-height: 1.2; } /* piso 14 px de texto (pixel-sweep-1) */
  .bottom-nav .nav-foot .dev-credit a { display: inline-flex; min-height: 44px; } /* objetivo táctil >= 44 px: el compacto de F1 lo dejó en 18 px */
}

/* Asistente: el punto del saludo "respira" (Jarvis, 2026-10-31). Sin movimiento si la persona lo pidió. */
/* Rediseño 2026-10-31: orbe con tres estados (data-state = idle | listening | thinking). Reposo: respira despacio;
   escuchando: anillos rápidos + onda; pensando: arco que gira. Con prefers-reduced-motion no hay animación y el estado se
   ve igual (anillo grueso al escuchar, arco fijo al pensar). */
.asst-orb { position: relative; width: 64px; height: 64px; border-radius: 9999px; display: grid; place-items: center;
  background: radial-gradient(circle at 34% 30%, rgb(255 190 140), rgb(var(--hivis)) 52%, rgb(194 65 12) 100%);
  box-shadow: 0 0 0 1px rgb(194 65 12 / .25), 0 6px 22px -4px rgb(255 107 26 / .55); animation: asst-breathe 3.2s ease-in-out infinite; }
.asst-orb::before, .asst-orb::after { content: ''; position: absolute; inset: -5px; border-radius: inherit; border: 2px solid rgb(255 107 26 / .45); opacity: 0; pointer-events: none; }
.asst-orb::before { animation: asst-ring 3.2s ease-out infinite; }
.asst-orb::after { animation: asst-ring 3.2s ease-out 1.6s infinite; }
.asst-orb[data-state="listening"] { animation: asst-listen .9s ease-in-out infinite; }
.asst-orb[data-state="listening"]::before, .asst-orb[data-state="listening"]::after { animation: asst-ring-live 1s ease-out infinite; border-width: 3px; }
.asst-orb[data-state="listening"]::after { animation-delay: .5s; }
.asst-orb[data-state="thinking"] { animation: none; }
.asst-orb[data-state="thinking"]::before { opacity: 1; inset: -6px; border: 3px solid rgb(255 107 26 / .18); border-top-color: rgb(var(--hivis)); animation: asst-spin .9s linear infinite; }
.asst-orb[data-state="thinking"]::after { display: none; }
.asst-wave { display: none; gap: 4px; align-items: center; height: 34px; }
.asst-wave i { display: block; width: 5px; height: 100%; border-radius: 2px; background: rgb(21 23 26 / .85); transform: scaleY(.35); animation: asst-wave 0.9s ease-in-out infinite; }
.asst-wave i:nth-child(2) { animation-delay: .12s; } .asst-wave i:nth-child(3) { animation-delay: .24s; } .asst-wave i:nth-child(4) { animation-delay: .36s; } .asst-wave i:nth-child(5) { animation-delay: .48s; }
.asst-orb[data-state="listening"] .asst-wave { display: flex; }
@keyframes asst-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.045); } }
@keyframes asst-listen { 0%, 100% { transform: scale(1); box-shadow: 0 0 0 1px rgb(194 65 12 / .25), 0 6px 22px -4px rgb(255 107 26 / .55); } 50% { transform: scale(1.09); box-shadow: 0 0 0 1px rgb(194 65 12 / .25), 0 0 38px 8px rgb(255 107 26 / .6); } }
@keyframes asst-ring-live { 0% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(1.38); } }
@keyframes asst-ignite { 0% { opacity: 0; transform: scale(.55); filter: brightness(1.6); } 60% { opacity: 1; transform: scale(1.08); } 100% { opacity: 1; transform: scale(1); filter: none; } }
@keyframes asst-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes asst-ring { 0% { opacity: .9; transform: scale(1); } 100% { opacity: 0; transform: scale(1.45); } }
@keyframes asst-spin { to { transform: rotate(360deg); } }
@keyframes asst-wave { 0%, 100% { transform: scaleY(.35); } 50% { transform: scaleY(1); } }
@media (prefers-reduced-motion: reduce) {
  .asst-orb, .asst-orb::before, .asst-orb::after, .asst-wave i, .asst-hero [data-asst-hello], .asst-hero [data-asst-day], [data-asst-examples] { animation: none !important; }
  .asst-orb[data-state="listening"]::before { opacity: 1; transform: none; border-width: 4px; }
  .asst-orb[data-state="listening"] .asst-wave i { transform: scaleY(.7); }
  .asst-orb[data-state="thinking"]::before { transform: rotate(45deg); }
}
/* Burbuja de JobDock, tarjeta y resultado: superficie elevada sutil con borde de 1 px (claro y oscuro). */
.asst-bot { background: rgb(var(--paper)); color: rgb(var(--ink)); }
.asst-card, [data-asst-result] { background: rgb(var(--card)); border: 1px solid rgb(var(--line)); box-shadow: 0 1px 2px rgb(0 0 0 / .05), 0 8px 24px -12px rgb(0 0 0 / .18); }
html.dark body:not(.public-view) .asst-bot { background: rgb(40 44 49); }
html.dark body:not(.public-view) :is(.asst-card, [data-asst-result]) { background: rgb(38 42 47); border-color: rgb(80 86 94); box-shadow: 0 8px 24px -12px rgb(0 0 0 / .6); }
.asst-ok { background: rgb(var(--ok)); color: #fff; }
html.dark body:not(.public-view) .asst-ok { color: rgb(21 23 26); }
.asst-err { background: rgb(254 242 242); color: rgb(153 27 27); border: 1px solid rgb(252 165 165); }
.asst-err-btn { background: rgb(var(--card)); color: rgb(var(--ink)); box-shadow: inset 0 0 0 1px rgb(252 165 165); }
html.dark body:not(.public-view) .asst-err { background: rgb(239 68 68 / .14); color: rgb(254 202 202); border-color: rgb(239 68 68 / .45); }
html.dark body:not(.public-view) .asst-err-btn { background: rgb(38 42 47); color: rgb(244 245 247); box-shadow: inset 0 0 0 1px rgb(239 68 68 / .45); }
/* Cuenta atrás del Undo: barra que se vacía en 10 s (sin movimiento: queda el texto con los segundos). */
.asst-undo-bar { position: absolute; left: 0; bottom: 0; height: 4px; width: 100%; background: rgb(var(--hivis)); transform-origin: left; transform: scaleX(1); }
.asst-undo-bar.run { transform: scaleX(0); transition: transform 10s linear; }
@media (prefers-reduced-motion: reduce) { .asst-undo-bar.run { transition: none; transform: scaleX(1); opacity: .5; } }
/* Asistente compacto tras el primer intercambio: el saludo cede el lugar a la conversación. */
[data-asst-panel][data-compact] .asst-orb { width: 40px; height: 40px; }
[data-asst-panel][data-compact] [data-asst-hello] { font-size: 18px; }
[data-asst-panel][data-compact] [data-asst-day] { display: none; }
/* Ronda 2 de jueces: héroe centrado y más grande con halo; "Stop" en contorno; con una tarjeta pendiente la voz baja a secundaria. */
.asst-hero .asst-orb { width: 96px; height: 96px; animation: asst-ignite .8s cubic-bezier(.2, .8, .2, 1) 1 both, asst-breathe 3.2s ease-in-out .8s infinite; }
.asst-hero [data-asst-hello] { animation: asst-rise .55s ease-out .25s both; }
.asst-hero [data-asst-day] { animation: asst-rise .55s ease-out .4s both; }
[data-asst-examples] { animation: asst-rise .55s ease-out .55s both; }
.asst-name { color: rgb(var(--hivis-ink)); }
.asst-hero [data-asst-status] { position: relative; }
.asst-hero .asst-orb[data-state="listening"] { animation: asst-listen .9s ease-in-out infinite; }
.asst-hero .asst-orb[data-state="thinking"] { animation: none; }
@media (min-width: 768px) { .asst-hero .asst-orb { width: 112px; height: 112px; } .asst-hero { padding-top: 44px; } .asst-hero::before { top: 100px; height: 200px; width: 340px; } }
/* Halo: círculo propio (pseudo-elemento) centrado en el orbe, no un degradado pegado a la caja: así no se corta con un borde recto. */
/* El cuerpo de la hoja recorta lo que sale por arriba: el halo (elipse centrada en el orbe) y los anillos caben DENTRO del héroe (36 px arriba = radio del anillo al escuchar). */
.asst-hero { position: relative; isolation: isolate; border-radius: 24px; padding: 36px 8px 4px; }
.asst-hero::before { content: ''; position: absolute; left: 50%; top: 84px; width: 280px; height: 168px; transform: translate(-50%, -50%); pointer-events: none; z-index: -1;
  background: radial-gradient(ellipse closest-side, rgb(255 107 26 / .20), rgb(255 107 26 / .07) 55%, transparent 100%); }
html.dark body:not(.public-view) .asst-hero::before { background: radial-gradient(ellipse closest-side, rgb(255 107 26 / .34), rgb(255 107 26 / .10) 55%, transparent 100%); }
html.dark body:not(.public-view) .asst-orb { box-shadow: 0 0 0 1px rgb(255 140 70 / .4), 0 0 40px 6px rgb(255 107 26 / .45); }
[data-asst-panel][data-compact] .asst-hero { flex-direction: row; justify-content: center; text-align: left; gap: 12px; padding: 0; }
[data-asst-panel][data-compact] .asst-hero::before { display: none; }
[data-asst-panel][data-compact] .asst-hero .asst-orb { width: 40px; height: 40px; }
[data-asst-panel][data-compact] [data-asst-status] { display: none; }
html body .jd [data-asst-mic].asst-stop { color: rgb(var(--paper)) !important; background: rgb(var(--ink)); box-shadow: inset 0 0 0 3px rgb(var(--hivis)); } /* Stop lleno: mientras graba es LA acción */
html body [data-asst-panel][data-pending] [data-asst-mic]:not(.asst-stop) { color: rgb(var(--ink)) !important; background: transparent; box-shadow: inset 0 0 0 2px rgb(var(--hivis)); }
.asst-undo-bar { height: 5px; }
/* Micrófono bloqueado: el orbe sigue centrado (columna) sobre el aviso, un poco más chico que el saludo. */
[data-asst-panel][data-compact="mic"] .asst-hero { flex-direction: column; text-align: center; gap: 0; padding: 28px 8px 0; }
[data-asst-panel][data-compact="mic"] .asst-hero::before { display: block; top: 64px; width: 240px; height: 128px; }
[data-asst-panel][data-compact="mic"] .asst-hero .asst-orb { width: 72px; height: 72px; }
[data-asst-panel][data-compact="mic"] [data-asst-hello] { font-size: 20px; margin-top: 10px; }
/* Dentro del área con scroll el último botón no queda pegado al borde: >= 16 px de aire. */
[data-asst-out]:not(:empty) { padding-bottom: 16px; padding-top: 14px; -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 14px); mask-image: linear-gradient(to bottom, transparent 0, #000 14px); } /* lo que sube bajo el borde se desvanece, no se corta */
[data-asst-panel][data-pending] .asst-hero { display: none; } /* con una tarjeta pendiente el saludo no ocupa lugar: la tarjeta se ve entera */
[data-asst-panel][data-pending] [data-asst-out] { max-height: 68vh; }

/* Páginas legales: ritmo del documento. Antes space-y-3 pisaba el mt-8 de los títulos (13 px arriba y 13 px abajo: el título no agrupaba con su sección).
   Ahora: título 2:1 (2rem arriba, 1rem abajo), párrafos y listas a .75rem. */
.legal-doc > * + * { margin-top: .75rem; }
.legal-doc > h2 { margin-top: 2rem; line-height: 1.25; }
.legal-doc > h2 + * { margin-top: 1rem; }
.legal-doc > h1 + * { margin-top: .5rem; }
/* Entradilla sin numero («Two roles»): NO es una seccion de la serie. Se pinta como una nota enmarcada (etiqueta en versalitas + lista dentro del mismo recuadro), no como un titulo. */
.legal-doc > h2.legal-lead { margin: 1.5rem 0 0; padding: .875rem 1rem 0; font-size: .8125rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: rgb(var(--muted)); background: rgb(var(--card)); border: 1px solid rgb(var(--line)); border-bottom: 0; border-radius: .75rem .75rem 0 0; }
.legal-doc > h2.legal-lead + ul { margin: 0; padding: .5rem 1rem .875rem 2.25rem; background: rgb(var(--card)); border: 1px solid rgb(var(--line)); border-top: 0; border-radius: 0 0 .75rem .75rem; }
.legal-doc > h2.legal-lead + ul > li + li { margin-top: .5rem; }
.legal-doc > h2.legal-sub { margin-top: 1.5rem; } /* Contact: h2 sin numero = titulos normales (sin recuadro) */
.legal-doc [data-legal-draft] { margin-top: .25rem; }
.legal-doc > h2 { scroll-margin-top: 1rem; } /* el salto desde el indice deja el titulo a la vista (la barra de la pagina no es fija) */
.legal-doc > h2:focus { outline: none; }
.legal-doc > .legal-toc { margin-top: 1.5rem; }
.legal-toc > summary { list-style: none; }
.legal-toc > summary::-webkit-details-marker { display: none; }
.legal-toc > summary::after { content: ''; margin-left: auto; width: .5rem; height: .5rem; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: translateY(-2px) rotate(45deg); } /* flecha: dice que se abre */
.legal-toc[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.legal-toc[open] > summary { border-bottom: 1px solid rgb(var(--line)); margin-bottom: .25rem; }
/* Enlace dentro de una frase con zona tocable >= 44 px SIN inflar la linea (un inline-block con py-2 llevaba la linea de 24 a 33 px). */
.tap-inline { position: relative; }
.tap-inline::after { content: ''; position: absolute; inset: -12px -4px; }
