/* ── Reset & base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font-ui);
  background-color: var(--surface-page);
  color: var(--text-body);
  line-height: 1.5;
  min-height: 100dvh;
  overflow-x: hidden;
}
a { color: var(--blue-500); text-decoration: none; }
button { cursor: pointer; border: none; background: none; font-family: inherit; }
input, select, textarea { font-family: inherit; font-size: 0.875rem; }
img { max-width: 100%; display: block; }
h1,h2,h3,h4,h5 { font-family: var(--font-display); color: var(--text-strong); line-height: 1.25; }

/* ── Login page ── */
.login-page {
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--gradient-brand);
  padding: 1.5rem;
}
.login-card {
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  padding: 2.5rem 2rem;
  width: 100%;
  max-width: 380px;
  box-shadow: var(--shadow-modal);
}
.login-logo { width: 160px; margin: 0 auto 1.5rem; display: block; }
.login-logo-dark { display: none; }
html[data-theme="dark"] .login-logo-light { display: none; }
html[data-theme="dark"] .login-logo-dark { display: block; }

.mount-step1-split {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.mount-form-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0 1.25rem;
}
.mount-form-grid .col-span-all { grid-column: 1 / -1; }
@media (max-width: 1100px) { .mount-form-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 720px)  { .mount-form-grid { grid-template-columns: 1fr; } }
.mount-step1-top, .mount-step1-bottom {
  flex: 1 1 50%;
  min-height: 0;
}
.mount-step1-bottom .table-wrap { max-height: 420px; overflow-y: auto; }

/* Ícono del selector de fecha invisible en modo oscuro */
html[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator,
html[data-theme="dark"] input[type="datetime-local"]::-webkit-calendar-picker-indicator,
html[data-theme="dark"] input[type="time"]::-webkit-calendar-picker-indicator {
  filter: invert(1);
}
.login-title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-strong);
  text-align: center;
  margin-bottom: 0.25rem;
}
.login-sub {
  color: var(--text-muted);
  font-size: 0.813rem;
  text-align: center;
  margin-bottom: 1.75rem;
}
.login-error {
  background: var(--error-bg);
  color: var(--error);
  font-size: 0.813rem;
  padding: 0.625rem 0.875rem;
  border-radius: var(--radius-sm);
  margin-bottom: 1rem;
  display: none;
}
.login-error.show { display: block; }

/* ── Form controls ── */
.form-group { margin-bottom: 1rem; }
.form-label {
  display: block;
  font-size: 0.813rem;
  font-weight: 600;
  color: var(--text-strong);
  margin-bottom: 0.375rem;
}
.form-control {
  display: block;
  width: 100%;
  padding: 0.625rem 0.875rem;
  border: 1.5px solid var(--border-normal);
  border-radius: var(--radius-md);
  background-color: var(--surface-card);
  color: var(--text-body);
  font-size: 0.875rem;
  transition: border-color var(--transition), box-shadow var(--transition);
  outline: none;
  appearance: auto;
}
.form-control:focus {
  border-color: var(--blue-500);
  box-shadow: 0 0 0 3px rgba(48,108,180,.18);
}
.form-control.error { border-color: var(--error); }
.form-control.input-error {
  border-color: var(--error) !important;
  background: #fff5f5 !important;
  animation: shake .3s ease;
}
@keyframes shake {
  0%,100% { transform: translateX(0); }
  25%      { transform: translateX(-4px); }
  75%      { transform: translateX(4px); }
}
.req-star { color: var(--error); font-weight: 700; margin-left: .1rem; }
.form-hint { font-size: 0.75rem; color: var(--text-muted); margin-top: 0.25rem; }

/* ── Buttons ── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.625rem 1.25rem;
  border-radius: var(--radius-pill);
  font-family: var(--font-ui);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1;
  transition: background var(--transition), box-shadow var(--transition), transform var(--transition);
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn-primary {
  background: var(--blue-500);
  color: #fff;
  box-shadow: var(--shadow-button);
}
.btn-primary:hover { background: var(--blue-600); }
/* Acción secundaria que acompaña a un btn-primary: mismo peso visual, azul un tono más claro */
.btn-primary-soft {
  background: var(--blue-400);
  color: #fff;
  box-shadow: var(--shadow-button);
}
.btn-primary-soft:hover { background: var(--blue-500); }
.btn-secondary {
  background: var(--blue-50);
  color: var(--blue-600);
}
.btn-secondary:hover { background: var(--blue-100); }
.btn-ghost {
  background: transparent;
  color: var(--text-muted);
}
.btn-ghost:hover { background: var(--surface-sunken); color: var(--text-body); }
.btn-danger {
  background: var(--error);
  color: #fff;
}
.btn-danger:hover { background: #b91c1c; color: #fff; }
.btn-sm { padding: 0.375rem 0.875rem; font-size: 0.813rem; }
.btn-icon { padding: 0.5rem; border-radius: var(--radius-md); }
.btn-block { width: 100%; justify-content: center; padding: 0.75rem; }
.btn:disabled { opacity: .5; pointer-events: none; }

/* ── App layout ── */
.app-layout {
  display: flex;
  min-height: 100dvh;
}
.hidden { display: none !important; }

/* ── Sidebar ── */
.sidebar {
  width: var(--sidebar-width);
  background: var(--gradient-ink);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: var(--topbar-height); left: 0;
  height: calc(100dvh - var(--topbar-height));
  z-index: 200;
  transition: transform var(--transition), width var(--transition), box-shadow var(--transition);
  overflow-y: auto;
  overflow-x: hidden;
}
.sidebar-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.5);
  z-index: 199;
}
.sidebar-overlay.show { display: block; }

/* Logos: ahora viven en la barra superior (.topbar-logo), no en el sidebar */
.topbar-logo {
  padding: 0 .5rem 0 0;
  display: flex;
  align-items: center;
  gap: .75rem;
  flex-shrink: 0;
  height: 100%;
}
#sidebar-logo-la-top, #sidebar-logo-la-top-dark { width: 66px; flex-shrink: 0; transition: width .2s; }
.topbar-logo.has-client #sidebar-logo-la-top, .topbar-logo.has-client #sidebar-logo-la-top-dark { width: 56px; }
#sidebar-logo-la-top-dark { display: none; }
html[data-theme="dark"] #sidebar-logo-la-top { display: none; }
html[data-theme="dark"] #sidebar-logo-la-top-dark { display: block; }
.sidebar-logo-faena { max-height: 32px; max-width: 84px; object-fit: contain; flex-shrink: 0; opacity: .95; border-radius: 5px; padding: 3px 6px; }
.sidebar-logo-sep {
  width: 1px;
  height: 28px;
  background: var(--border-normal);
  flex-shrink: 0;
}
.sidebar-logo-client {
  max-height: 28px;
  max-width: 76px;
  object-fit: contain;
  flex-shrink: 0;
  opacity: .95;
  border-radius: 5px;
  padding: 3px 6px;
}

/* Logo upload en modal */
.logo-upload-area {
  border: 1.5px dashed var(--border);
  border-radius: var(--radius-sm);
  padding: .75rem 1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 72px;
  background: var(--surface-2);
  transition: border-color .15s, background .15s;
}
.logo-upload-area:hover { border-color: var(--primary); background: var(--primary-50, #eff6ff); }
#logo-upload-placeholder { display: flex; align-items: center; gap: .5rem; color: var(--text-muted); font-size: .825rem; }

/* Selector de faena, ahora en la barra superior (a la derecha del botón de tema) */
.topbar-faena { flex-shrink: 0; }
.topbar-faena select {
  background: var(--surface-sunken);
  border: 1px solid var(--border-normal);
  color: var(--text-body);
  border-radius: var(--radius-sm);
  padding: 0.4rem 0.6rem;
  font-size: 0.813rem;
  font-weight: 600;
  outline: none;
  cursor: pointer;
  appearance: auto;
  max-width: 12rem;
}
.topbar-faena select:hover { background: var(--blue-50); border-color: var(--blue-300); }
html[data-theme="dark"] .topbar-faena select:hover { background: var(--surface-card); border-color: var(--blue-500); }
.topbar-faena select option { background: var(--surface-card); color: var(--text-body); }

/* Botón para expandir/plegar el menú manualmente (dispositivos táctiles, sin hover) */
.sidebar-toggle-btn {
  display: none;
  align-items: center;
  justify-content: center;
  margin: .625rem auto 0;
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  color: rgba(255,255,255,.6);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.sidebar-toggle-btn:hover { background: rgba(255,255,255,.08); color: #fff; }

/* Bloque de usuario, ahora arriba del sidebar (antes era el selector de faena) */
.sidebar-user-top {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid rgba(255,255,255,.08);
  color: rgba(255,255,255,.7);
  font-size: 0.813rem;
}
.sidebar-nav { flex: 1; padding: 0.75rem 0; }
.nav-section-label {
  padding: 0.75rem 1.25rem 0.25rem;
  font-size: 0.688rem;
  font-weight: 600;
  color: rgba(255,255,255,.3);
  text-transform: uppercase;
  letter-spacing: .08em;
  white-space: nowrap;
}
.nav-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 1.25rem;
  color: rgba(255,255,255,.65);
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
  border-radius: 0;
  width: 100%;
  text-align: left;
  white-space: nowrap;
}
.nav-item:hover { background: rgba(255,255,255,.07); color: #fff; }
.nav-item.active { background: rgba(48,108,180,.35); color: #fff; }
.nav-item .nav-icon { width: 16px; height: 16px; flex-shrink: 0; }
.nav-icon-wrap { position: relative; display: inline-flex; flex-shrink: 0; }
.nav-pulse-dot {
  position: absolute;
  top: -3px; right: -3px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--error);
  animation: navPulseDot 1.6s infinite;
}
@keyframes navPulseDot {
  0%   { box-shadow: 0 0 0 0 rgba(224,65,61,.6); }
  70%  { box-shadow: 0 0 0 6px rgba(224,65,61,0); }
  100% { box-shadow: 0 0 0 0 rgba(224,65,61,0); }
}
.nav-label { overflow: hidden; text-overflow: ellipsis; }
.sidebar-footer {
  padding: .75rem 1.25rem 1rem;
  border-top: 1px solid rgba(255,255,255,.08);
}
.sidebar-footer-logo {
  display: flex;
  justify-content: center;
}
.sidebar-footer-logo img { width: 84px; opacity: 1; }
.sidebar-footer-logo-dark { display: none; }
html[data-theme="dark"] .sidebar-footer-logo-light { display: none; }
html[data-theme="dark"] .sidebar-footer-logo-dark { display: block; }
.sidebar-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--blue-500);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
}
.sidebar-username { flex: 1; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.btn-logout { color: rgba(255,255,255,.5); padding: 0.25rem; border-radius: var(--radius-sm); flex-shrink: 0; }
.btn-logout:hover { color: var(--error); background: rgba(224,65,61,.15); }

/* ── Scrollbar del sidebar, acorde al tema (antes quedaba con el scrollbar claro del navegador) ── */
.sidebar { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.18) transparent; }
.sidebar::-webkit-scrollbar { width: 6px; }
.sidebar::-webkit-scrollbar-track { background: transparent; }
.sidebar::-webkit-scrollbar-thumb { background: rgba(255,255,255,.18); border-radius: var(--radius-pill); }
.sidebar::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.32); }
html:not([data-theme="dark"]) .sidebar { scrollbar-color: rgba(12,23,38,.18) transparent; }
html:not([data-theme="dark"]) .sidebar::-webkit-scrollbar-thumb { background: rgba(12,23,38,.15); }
html:not([data-theme="dark"]) .sidebar::-webkit-scrollbar-thumb:hover { background: rgba(12,23,38,.28); }

/* ── Sidebar colapsable (solo iconos), pantallas de escritorio ──
   `and (hover: hover)` es CRÍTICO: un teléfono en horizontal mide ~915px de ancho
   y entraba aquí, quedando con layout de escritorio. Al volver a vertical, Chrome
   conservaba ese ancho de layout y la app se veía "alejada" y descuadrada.
   La regla ahora es: escritorio = tiene mouse, no = es ancho. */
@media (min-width: 900px) and (hover: hover) {
  .sidebar { width: var(--sidebar-collapsed-width); }
  .sidebar.expanded { width: var(--sidebar-width); box-shadow: var(--shadow-modal); }
  .sidebar:not(.expanded) .nav-label,
  .sidebar:not(.expanded) .sidebar-username,
  .sidebar:not(.expanded) .btn-logout,
  .sidebar:not(.expanded) .sidebar-footer-logo { display: none; }
  .sidebar:not(.expanded) .nav-item { justify-content: center; padding-left: 0; padding-right: 0; gap: 0; }
  .sidebar:not(.expanded) .sidebar-user-top { justify-content: center; padding-left: 0; padding-right: 0; gap: 0; }
  /* Plegado: el título de cada sección se reemplaza por una línea divisoria delgada */
  .sidebar:not(.expanded) .nav-section-label {
    height: 0;
    padding: 0;
    margin: .75rem 1.25rem;
    border-top: 1px solid rgba(255,255,255,.12);
    overflow: hidden;
    font-size: 0;
    line-height: 0;
  }
  .sidebar:not(.expanded) .nav-section-label:first-child { margin-top: .5rem; }
  /* En dispositivos con mouse el hover ya expande — el botón manual solo estorba */
  .sidebar-toggle-btn { display: none !important; }
}
/* Notebook con pantalla táctil (tiene mouse Y dedo): ahí sí sirve el botón manual.
   Un teléfono/tablet puro ya no entra aquí — usa el drawer con hamburguesa. */
@media (min-width: 900px) and (hover: hover) and (any-pointer: coarse) {
  .sidebar-toggle-btn { display: flex; }
}

/* ── Sidebar modo día ── */
html:not([data-theme="dark"]) .sidebar {
  background: #ffffff;
  border-right: 1px solid var(--border-subtle);
}
html:not([data-theme="dark"]) .sidebar-logo-sep {
  background: var(--border-normal);
}
html:not([data-theme="dark"]) .sidebar-user-top {
  border-bottom-color: var(--border-subtle);
  color: var(--text-body);
}
html:not([data-theme="dark"]) .sidebar-toggle-btn {
  color: var(--text-muted);
}
html:not([data-theme="dark"]) .sidebar-toggle-btn:hover {
  background: var(--surface-sunken);
  color: var(--text-strong);
}
html:not([data-theme="dark"]) .nav-section-label {
  color: var(--text-muted);
}
@media (min-width: 900px) and (hover: hover) {
  html:not([data-theme="dark"]) .sidebar:not(.expanded) .nav-section-label {
    border-top-color: var(--border-subtle);
  }
}
html:not([data-theme="dark"]) .nav-item {
  color: var(--text-body);
}
html:not([data-theme="dark"]) .nav-item:hover {
  background: var(--blue-50);
  color: var(--blue-600);
}
html:not([data-theme="dark"]) .nav-item.active {
  background: var(--blue-100);
  color: var(--blue-700);
}
html:not([data-theme="dark"]) .sidebar-footer {
  border-top-color: var(--border-subtle);
}
html:not([data-theme="dark"]) .btn-logout {
  color: var(--text-muted);
}

/* ── Topbar ── */
.topbar {
  height: var(--topbar-height);
  background: var(--surface-card);
  border-bottom: 1px solid var(--border-subtle);
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0 1.5rem;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  box-shadow: var(--shadow-card);
}
.btn-hamburger {
  display: none;
  padding: 0.375rem;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
}
.btn-hamburger:hover { background: var(--surface-sunken); }
.topbar-title {
  flex: 1;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-strong);
}
.sync-status {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.75rem;
  color: var(--text-muted);
  padding: 0.25rem 0.625rem;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
}
.sync-status .sync-icon { font-size: 0.875rem; }
.sync-status.sync--ok    { color: var(--success); background: var(--success-bg); }
.sync-status.sync--error { color: var(--error);   background: var(--error-bg); }
.sync-status.sync--saving{ color: var(--warning); background: var(--warning-bg); }
.sync-status.sync--pending{ color: var(--warning); background: var(--warning-bg); }
.sync-text { display: inline; }
#btn-theme {
  padding: 0.375rem;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: 1rem;
}
#btn-theme:hover { background: var(--surface-sunken); }

/* ── Main content ── */
.main-content {
  margin-left: var(--sidebar-collapsed-width);
  margin-top: var(--topbar-height);
  padding: 1.75rem 1.5rem;
  min-height: calc(100dvh - var(--topbar-height));
  flex: 1;
}

/* ── Views ── */
.view { display: none; }
.view.view--active { display: block; }

/* ── Page header ── */
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.page-header-text h2 { font-size: 1.375rem; font-weight: 800; margin-bottom: 0.125rem; }
.page-header-text p  { color: var(--text-muted); font-size: 0.875rem; }

/* ── Cards ── */
.card {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
}
.card-body { padding: 1.25rem; }
.card-header {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border-subtle);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.card-title { font-size: 0.938rem; font-weight: 700; color: var(--text-strong); }

/* ── Stat cards (dashboard) ── */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.stat-card {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  padding: 1.25rem;
  box-shadow: var(--shadow-card);
  cursor: pointer;
  transition: box-shadow var(--transition), border-color var(--transition), transform var(--transition);
  position: relative;
  overflow: hidden;
}
.stat-card:hover { box-shadow: 0 6px 24px rgba(48,108,180,.14); border-color: var(--blue-300); transform: translateY(-2px); }
.stat-card-accent {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
}
.stat-card-icon {
  width: 36px; height: 36px;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.875rem;
}
.stat-card-value {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 800;
  color: var(--text-strong);
  line-height: 1;
  margin-bottom: 0.25rem;
}
.stat-card-label { font-size: 0.813rem; color: var(--text-muted); font-weight: 500; }
.stat-card-sub { display: flex; gap: .875rem; margin-top: .5rem; flex-wrap: wrap; }
.stat-card-sub-item { display: flex; align-items: center; gap: .3rem; font-size: .75rem; color: var(--text-muted); }
.stat-card-sub-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
/* Variante compacta: las tarjetas KPI del dashboard eran del mismo tamaño que las de páginas
   donde tiene sentido que dominen la vista — Jairo las pidió más chicas para dejar más espacio
   a los gráficos que siguen inmediatamente debajo. */
.stat-card-compact { padding: .7rem .875rem; }
.stat-card-compact .stat-card-icon { width: 26px; height: 26px; margin-bottom: .45rem; }
.stat-card-compact .stat-card-value { font-size: 1.2rem; margin-bottom: .15rem; }
.stat-card-compact .stat-card-label { font-size: .7rem; }

/* ── Dash rows ── */
.dash-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin-bottom: 1rem;
}

/* ── Tables ── */
.table-wrap { overflow-x: auto; border-radius: var(--radius-xl); }
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}
.data-table th {
  text-align: left;
  padding: 0.625rem 1rem;
  background: var(--surface-sunken);
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  white-space: nowrap;
}
.data-table th:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.data-table th:last-child  { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.sortable-th { display: flex; flex-direction: column; gap: .25rem; }
.sort-btn { cursor: pointer; user-select: none; white-space: nowrap; display: flex; align-items: center; gap: .25rem; }
.sort-btn:hover { color: var(--primary); }
.sort-arrow { font-size: .65rem; opacity: .6; }
.col-filter { width: 100%; font-size: .72rem; padding: .2rem .4rem; background: var(--surface-base); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); color: var(--text-body); outline: none; font-weight: 400; text-transform: none; letter-spacing: 0; }
.col-filter:focus { border-color: var(--primary); }
.data-table td {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: middle;
  color: var(--text-body);
}
.data-table tr:last-child td { border-bottom: none; }

/* ── Celda de acciones ──────────────────────────────────────────────────────
   Los botones variaban de ancho según el texto ("Editar" vs "Desarmar") y las
   filas quedaban desalineadas entre sí. Ahora la celda es una grilla de ancho
   fijo por botón: aunque una fila tenga 2 botones y otra 4, todos caen en la
   misma columna visual. Aplica a todas las tablas. */
/* Alineada a la IZQUIERDA a propósito: con text-align:right el primer botón se corría
   según cuántos botones tuviera la fila y "Editar" no quedaba en la misma vertical.
   Además, en el HTML los botones que SIEMPRE aparecen van primero y los condicionales
   al final, así las columnas de botones fijos coinciden entre filas. */
.data-table td.td-actions {
  white-space: nowrap; text-align: left; width: 1%;
}
.data-table td.td-actions .btn {
  min-width: 72px; padding: .25rem .5rem; font-size: .7rem;
  justify-content: center; border-radius: var(--radius-sm);
  margin-right: .25rem; vertical-align: middle;
}
.data-table td.td-actions .btn:last-child { margin-right: 0; }
@media (max-width: 767px) {
  .data-table td.td-actions .btn { min-width: 0; padding: .25rem .4rem; font-size: .65rem; }
}
.data-table tr:hover td { background: var(--surface-sunken); }
.data-table tr { cursor: pointer; }

/* ── Badges ── */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.2rem 0.625rem;
  border-radius: var(--radius-pill);
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}
.badge-blue    { background: var(--info-bg);    color: var(--blue-600); }
.badge-green   { background: var(--success-bg); color: var(--success); }
.badge-yellow  { background: var(--warning-bg); color: #c87d00; }
.badge-red     { background: var(--error-bg);   color: var(--error); }
.badge-gray    { background: var(--surface-sunken); color: var(--text-muted); }
.folio-badge   { font-family: var(--font-mono); font-size: .75rem; font-weight: 700;
                 color: #1d4ed8; background: #eff6ff;
                 padding: .15rem .45rem; border-radius: .3rem; white-space: nowrap; letter-spacing: .02em; }

/* Status badges for tires — tokenizados en tokens.css (2026-08-14), con
   variante oscura: antes eran hex crudo y no reaccionaban al tema. */
.status-mounted          { background: var(--info-bg); color: var(--blue-600); }  /* Azul pálido — montado */
.status-stock            { background: var(--status-stock-bg);           color: var(--status-stock-fg); }
.status-stock-armado     { background: var(--status-stock-bg);           color: var(--status-stock-fg); }
.status-stock-desarmado  { background: var(--status-desarmado-bg);       color: var(--status-desarmado-fg); }
.status-evaluation       { background: var(--status-evaluation-bg);      color: var(--status-evaluation-fg); }
.status-pending_repair   { background: var(--status-pending-repair-bg);  color: var(--status-pending-repair-fg); }
.status-repair           { background: var(--status-repair-bg);          color: var(--status-repair-fg); }
.status-pending_retread  { background: var(--status-pending-retread-bg); color: var(--status-pending-retread-fg); }
.status-retread          { background: var(--status-retread-bg);         color: var(--status-retread-fg); }
.status-scrapped         { background: var(--status-scrapped-bg);        color: var(--status-scrapped-fg); }
.status-recycling        { background: var(--status-recycling-bg);       color: var(--status-recycling-fg); } /* distinto de Baja, que es rojo */
.status-transferred      { background: var(--surface-sunken); color: var(--text-muted); } /* Gris — trasladado a faena externa */
.status-pending_reception{ background: var(--status-pending-repair-bg);  color: var(--status-pending-repair-fg); }

/* ── Modals ── */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(12,23,38,.5);
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition);
}
.modal-backdrop.is-open { opacity: 1; pointer-events: all; }
.modal {
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-modal);
  width: 100%;
  max-width: 520px;
  max-height: calc(100dvh - 2rem);
  overflow-y: auto;
  transform: translateY(12px);
  transition: transform var(--transition);
}
.modal-backdrop.is-open .modal { transform: translateY(0); }
.modal-lg { max-width: 720px; }
.modal-xl { max-width: 900px; }
.modal-header {
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--border-subtle);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.modal-title { font-size: 1rem; font-weight: 700; color: var(--text-strong); }
.modal-body { padding: 1.5rem; }
.modal-footer {
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--border-subtle);
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
}
/* ── Selector de componentes de los despachos ─────────────────────────────────
   Reparación, recauchaje, traslado, baja y reciclaje comparten este bloque
   "Agregar componente". Antes el botón "+ Añadir" iba al costado y le robaba
   ~120px de ancho a la lista, que es justo donde hay que leer N° interno, serie
   y medida. Ahora el botón va debajo, a lo ancho: la lista se extiende completa
   y el botón queda con un blanco de toque cómodo. */
.cmp-picker { display: flex; flex-direction: column; gap: .5rem; }
.cmp-picker > div { width: 100%; min-width: 0; }
.cmp-picker select { width: 100%; min-height: 132px; }
.cmp-picker-add { width: 100%; justify-content: center; white-space: nowrap; }

.btn-close { color: var(--text-muted); padding: 0.25rem; border-radius: var(--radius-sm); }
.btn-close:hover { background: var(--surface-sunken); }

/* ── Toasts ── */
.toast-container {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: 600;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.toast {
  padding: 0.75rem 1.125rem;
  border-radius: var(--radius-lg);
  font-size: 0.875rem;
  font-weight: 500;
  box-shadow: var(--shadow-modal);
  display: flex;
  align-items: center;
  gap: 0.625rem;
  animation: slideUp .25s var(--ease);
  max-width: 320px;
  color: #fff;
}
.toast-success { background: var(--success); }
.toast-error   { background: var(--error); }
.toast-info    { background: var(--blue-500); }
@keyframes slideUp { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }

/* ── Filters / search bar ── */
.filter-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}
.search-input {
  position: relative;
  flex: 1;
  min-width: 180px;
}
.search-input input {
  width: 100%;
  padding: 0.5rem 0.875rem 0.5rem 2.25rem;
  border: 1.5px solid var(--border-normal);
  border-radius: var(--radius-pill);
  background-color: var(--surface-card);
  color: var(--text-body);
  font-size: 0.875rem;
  outline: none;
  transition: border-color var(--transition);
}
.search-input input:focus { border-color: var(--blue-500); }
.search-icon {
  position: absolute;
  left: 0.75rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
}

/* ── Combobox con búsqueda (selector de equipo en Cambios) ──────────────────────
   Antes era un <select> plano con todos los equipos de la faena: había que
   desplazarse por la lista entera. Este es un input de texto + lista filtrada,
   con un input oculto que guarda el id real (mismo id que tenía el <select> viejo,
   para no tocar el resto del código que lee su .value). */
.combo-select { position: relative; }
.combo-select-list {
  display: none;
  position: absolute; z-index: 40; top: calc(100% + 4px); left: 0; right: 0;
  max-height: 260px; overflow-y: auto;
  background: var(--surface-card); border: 1.5px solid var(--border-normal);
  border-radius: var(--radius-md); box-shadow: 0 8px 24px rgba(0,0,0,.12);
}
.combo-select-list.is-open { display: block; }
.combo-select-item {
  padding: .5rem .75rem; font-size: .85rem; cursor: pointer;
  border-bottom: 1px solid var(--border-subtle);
}
.combo-select-item:last-child { border-bottom: none; }
.combo-select-item:hover, .combo-select-item.is-active { background: var(--blue-50); }
.combo-select-empty { padding: .625rem .75rem; font-size: .8rem; color: var(--text-muted); }

/* ── Grid de 2 columnas para formularios ── */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }
.form-grid .col-span-2 { grid-column: 1 / -1; }
.form-row { display: flex; gap: 1rem; align-items: flex-start; }
.form-row .form-group { margin-bottom: 1rem; }
.form-section-title {
  font-size: 0.813rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .06em;
  margin: 1.25rem 0 0.75rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border-subtle);
  grid-column: 1 / -1;
}

/* ── Cambio de neumáticos (drag & drop) ── */
/* ── Cambio de neumáticos ────────────────────────────────────────────────── */
.mount-equip-bar {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}
.mount-layout {
  display: flex;
  align-items: stretch;
  height: calc(100dvh - 260px);
  min-height: 480px;
}
.mount-left {
  display: flex;
  flex-direction: column;
  flex: 0 0 58%;
  min-width: 360px;
  min-height: 0;
}
.mount-left-bottom {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .75rem;
  flex: 1 1 auto;
  min-height: 140px;
}
.mount-stock-right {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 280px;
  min-height: 0;
}
#mount-armed-panel {
  flex: 0 0 220px;
  min-height: 140px;
}
.mount-right-lower {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  flex: 1 1 auto;
  min-height: 140px;
}
.mount-stock-bottom {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .75rem;
}
.stock-panel-sm {
  overflow: hidden;
  flex: 0 0 150px;
}
.equipment-diagram {
  padding: 1.5rem;
  flex: 0 0 420px;
  min-height: 220px;
  overflow: auto;
}
/* Manijas de redimensionamiento */
.mount-resize-handle {
  position: relative;
  flex-shrink: 0;
  z-index: 5;
}
.mount-resize-col {
  width: 16px;
  margin: 0 .1rem;
  cursor: col-resize;
}
.mount-resize-col::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%,-50%);
  width: 4px; height: 44px;
  border-radius: 3px;
  background: var(--border-normal);
  transition: background .12s;
}
.mount-resize-col:hover::after, .mount-resize-col.is-resizing::after { background: var(--primary); }
.mount-resize-row {
  height: 16px;
  margin: .1rem 0;
  cursor: row-resize;
}
.mount-resize-row::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%,-50%);
  height: 4px; width: 44px;
  border-radius: 3px;
  background: var(--border-normal);
  transition: background .12s;
}
.mount-resize-row:hover::after, .mount-resize-row.is-resizing::after { background: var(--primary); }
/* Historial de movimientos */
.mount-history-panel {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.mount-history-list {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  padding: .5rem .75rem;
  display: flex;
  flex-direction: column;
  gap: .4rem;
}
.mount-history-item {
  display: flex;
  align-items: flex-start;
  gap: .5rem;
  padding: .4rem .5rem;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-size: .75rem;
  line-height: 1.3;
}
.mount-history-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .7rem;
  font-weight: 700;
  color: #fff;
}
.mount-history-icon.mh-mount      { background: var(--success); }
.mount-history-icon.mh-dismount   { background: var(--error); }
.mount-history-icon.mh-assemble   { background: var(--blue-500); }
.mount-history-icon.mh-disassemble{ background: #e07b2b; }
.mount-history-icon.mh-chain      { background: #6b7280; }
.mount-history-text strong { font-family: var(--font-mono); }
.mount-history-sub { color: var(--text-muted); font-size: .68rem; }
/* Diagrama del equipo */
.equip-diagram-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: 1rem;
  padding-bottom: .75rem;
  border-bottom: 1px solid var(--border-subtle);
}
.equip-diagram-badge {
  font-size: .75rem;
  font-weight: 700;
  padding: .2rem .625rem;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  display: inline-block;
}
.diag-progress {
  height: 4px; border-radius: 2px;
  background: var(--border-normal);
  margin-top: .25rem; overflow: hidden;
}
.diag-progress-bar { height: 100%; border-radius: 2px; transition: width .4s; }
.diag-hint {
  font-size: .72rem; color: var(--text-muted); text-align: center;
  margin-bottom: .875rem; opacity: .8;
}
.wheel-front-label, .wheel-back-label {
  font-size: .65rem; font-weight: 700; letter-spacing: .08em;
  color: var(--text-muted); text-align: center; opacity: .7; padding: .125rem 0;
}
.slot-empty { font-size: .7rem; opacity: .35; margin-top: .25rem; }
.wheel-grid {
  display: grid;
  gap: 1rem;
  margin: 0 auto;
  width: fit-content;
}
.wheel-axle {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.wheel-axle-label {
  font-size: .7rem;
  font-weight: 700;
  color: var(--text-muted);
  width: 28px;
  text-align: center;
}
.wheel-axle-line {
  flex: 1;
  height: 3px;
  background: var(--border-normal);
  border-radius: 2px;
}
.wheel-axle-slots {
  display: flex;
  gap: .625rem;
}
.wheel-slot {
  width: 88px;
  min-height: 130px;
  border: 2px dashed var(--border-normal);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .15rem;
  padding: .25rem .25rem .3rem;
  cursor: pointer;
  transition: border-color .15s, background .15s, transform .1s;
  position: relative;
  user-select: none;
  text-align: center;
  overflow: hidden;
}
.wheel-slot:hover { border-color: var(--blue-400); background: var(--blue-50); }
.wheel-slot.has-tire {
  border: 2px solid var(--blue-400);
  background: var(--surface-sunken);
}
.wheel-slot.drag-over {
  border-color: var(--success);
  background: var(--success-bg);
  transform: scale(1.04);
}
.wheel-slot .pos-label {
  font-weight: 700;
  font-size: .75rem;
  color: var(--text-secondary, rgba(255,255,255,.75));
  letter-spacing: .03em;
}
/* Position badge overlaid on filled slot */
.slot-pos-badge {
  position: absolute;
  top: 5px;
  left: 6px;
  background: rgba(0,0,0,.6);
  color: #fff;
  font-size: .65rem;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: 4px;
  line-height: 1.5;
  letter-spacing: .02em;
  pointer-events: none;
}
/* Info overlay at bottom of filled slot */
.slot-tire-overlay {
  width: calc(100% + .5rem);
  margin: 0 -.25rem -.3rem;
  background: rgba(0,0,0,.52);
  backdrop-filter: blur(2px);
  padding: .3rem .35rem .25rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .12rem;
}
.wheel-slot .tire-code {
  font-weight: 700;
  font-size: .72rem;
  color: #fff;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.wheel-slot .tire-size {
  font-size: .58rem;
  color: rgba(255,255,255,.65);
  white-space: nowrap;
}
.slot-rim-tag {
  font-size: .58rem;
  color: #e07b2b;
  white-space: nowrap;
}
/* Remanente + horas del neumático montado. Antes era solo "12mm" sobre una
   píldora de color; ahora lleva las horas al lado, igual que las tarjetas del
   stock, así que se lee mejor como texto suelto que dentro de la píldora. */
.wheel-slot .tire-tread {
  font-size: .6rem;
  font-weight: 700;
  line-height: 1.25;
  padding: .08rem .2rem;
  /* En un slot de 88px (64 en teléfono) "95,0mm · 429 h" puede no caber en una
     línea: que parta antes que se recorte. */
  white-space: normal;
}
.wheel-slot .btn-dismount {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--error);
  color: #fff;
  font-size: .65rem;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity .15s;
  z-index: 2;
}
.wheel-slot.has-tire:hover .btn-dismount { opacity: 1; }
/* Stock panel */
.stock-panel {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.stock-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  padding: .875rem 1rem;
  border-bottom: 1px solid var(--border-subtle);
  flex-wrap: wrap;
  flex: 0 0 auto;
}
.stock-panel-list {
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: .35rem;
  padding: .4rem;
}
.stock-tire-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: .1rem;
  padding: .3rem .25rem .25rem;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  cursor: grab;
  transition: background .12s, border-color .12s;
  user-select: none;
  flex: 0 0 auto;
  width: auto;
  min-width: 60px;
  max-width: 92px;
  background: var(--surface-2);
  box-sizing: border-box;
  position: relative;
}
.stock-tire-item:hover { background: var(--blue-50); border-color: var(--primary); }
.stock-tire-item.drag-over { background: var(--blue-50); border-color: var(--primary); outline: 2px solid var(--primary); }
.stock-tire-item.dragging { opacity: .35; }
/* Selección por toque (alternativa al drag&drop en celular): toca el neumático,
   toca la posición destino. */
.stock-tire-item.is-selected {
  background: var(--blue-50); border-color: var(--primary);
  outline: 2px solid var(--primary); outline-offset: -1px;
}
.stock-tire-shape { flex-shrink: 0; display: block; }
.stock-tire-info { width: 100%; min-width: 0; }
.stock-tire-num { font-weight: 700; font-size: .68rem; font-family: var(--font-mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stock-tire-meta { font-size: .58rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stock-tire-tread { font-size: .58rem; font-weight: 700; }
.btn-disassemble-stock {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: none;
  background: rgba(224,65,61,.85);
  color: #fff;
  font-size: .6rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s;
  z-index: 2;
}
.stock-tire-item:hover .btn-disassemble-stock { opacity: 1; }
.stock-drag-hint {
  position: absolute;
  top: .25rem;
  right: .35rem;
  font-size: .65rem;
  color: var(--text-muted);
  opacity: .5;
  line-height: 1;
}
/* Modal desmontaje */
.dismount-tire-card {
  background: var(--blue-50);
  border: 1px solid var(--blue-200);
  border-radius: var(--radius-md);
  padding: .75rem 1rem;
  display: flex;
  gap: .75rem;
  align-items: center;
}
.dismount-status-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .5rem;
}
.dismount-status-opt {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .25rem;
  padding: .75rem .5rem;
  border: 2px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color .15s, background .15s;
  text-align: center;
}
.dismount-status-opt input[type=radio] { display: none; }
.dismount-status-opt:has(input:checked) {
  border-color: var(--primary);
  background: var(--blue-50);
}
.dso-icon {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .875rem;
}
.dso-label { font-weight: 700; font-size: .8rem; }
.dso-desc { font-size: .7rem; color: var(--text-muted); }
.tire-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--blue-400);
  flex-shrink: 0;
}

/* ── Inspección ── */
.insp-summary-title {
  font-size: .75rem; font-weight: 700; color: var(--text-strong);
  text-transform: uppercase; letter-spacing: .03em;
  margin: .75rem 0 .35rem;
}
.insp-summary-row {
  padding: .35rem 0;
  border-bottom: 1px solid var(--border-subtle);
  font-size: .8rem;
}
.insp-delta-badge {
  display: inline-block;
  font-size: .75rem; font-weight: 600;
  color: var(--blue-700, #1d4ed8);
  background: var(--info-bg, #eff6ff);
  padding: .15rem .5rem; border-radius: 999px;
}
.rev-tag {
  display: inline-block; font-size: .65rem; font-weight: 700;
  padding: .05rem .4rem; border-radius: 999px; margin-left: .25rem;
  vertical-align: middle;
}
.rev-tag--modified { color: var(--blue-700, #1d4ed8); background: var(--info-bg, #eff6ff); }
.rev-tag--removed  { color: var(--error, #dc2626); background: var(--error-bg, #fef2f2); }
.insp-tabs {
  display: flex;
  gap: .25rem;
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: 1rem;
}
.insp-tab-btn {
  padding: .5rem 1rem;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--text-muted);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  margin-bottom: -1px;
}
.insp-tab-btn:hover { color: var(--text-strong); }
.insp-tab-btn.active { color: var(--blue-600); border-bottom-color: var(--blue-500); }
.config-subtabs {
  display: flex;
  gap: .25rem;
  padding: .75rem 1rem 0;
  border-bottom: 1px solid var(--border-subtle);
}
.config-subtab-btn {
  padding: .45rem .9rem;
  font-size: .78rem;
  font-weight: 600;
  color: var(--text-muted);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  margin-bottom: -1px;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.config-subtab-btn:hover { color: var(--text-strong); background: var(--surface-2); }
.config-subtab-btn.active { color: var(--blue-600); border-bottom-color: var(--blue-500); }
.component-badge {
  display: inline-block;
  font-size: .68rem;
  font-weight: 700;
  padding: .1rem .5rem;
  border-radius: 999px;
}
.component-badge.tire  { background: var(--blue-100); color: var(--blue-700); }
.component-badge.rim   { background: #ffedd5; color: #c2410c; }
.component-badge.chain { background: #ede9fe; color: #6d28d9; }
/* --insp-card-w la calcula _setInspModalWidth() en app.js a partir del ancho
   real disponible y del eje más lleno del equipo. El valor de aquí es solo el
   piso de arranque, antes del primer render. */
:root { --insp-card-w: 240px; }

.insp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--insp-card-w), 1fr));
  gap: 0.75rem;
  margin-top: 1rem;
}
.insp-tire-card {
  border: 1.5px solid var(--border-normal);
  border-radius: var(--radius-lg);
  padding: 0.875rem;
  background: var(--surface-card);
}
/* Neumáticos por posición: agrupados en filas por eje, igual que en el equipo */
#insp-items-grid {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  margin-top: 1rem;
}
.insp-axle-row {
  display: flex;
  gap: .75rem;
  flex-wrap: nowrap;
  /* Sin esto las posiciones que no caben quedaban simplemente cortadas y era
     imposible llegar a ellas (reportado 2026-08-14 en teléfono). */
  overflow-x: auto;
  /* Nada de `scroll-behavior: smooth` aquí: convierte en animación CUALQUIER
     ajuste programático de scrollLeft, incluido el que hace el navegador al
     restaurar posición. La animación la pide _carouselInit() en su scrollTo. */
}
.insp-axle-row .insp-tire-card {
  flex: 0 0 var(--insp-card-w);
  width: var(--insp-card-w);
}

/* ── Carrusel de posiciones (inspección) ──────────────────────────────────────
   La barra de control (◀ · Eje 1 — 2 de 5 · ▶ · puntos) la inyecta
   _carouselInit() en app.js, y solo cuando la pista realmente desborda. */
.carousel { position: relative; }
.carousel-nav {
  display: none;
  align-items: center; gap: .5rem;
  margin-top: .5rem;
}
.carousel.is-scrollable > .carousel-nav { display: flex; }
.carousel-nav-btn {
  flex: 0 0 auto;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-normal);
  border-radius: var(--radius-pill);
  background: var(--surface-card);
  color: var(--text-normal);
  transition: opacity var(--transition), background var(--transition);
}
.carousel-nav-btn svg { width: 16px; height: 16px; }
.carousel-nav-btn:disabled { opacity: .35; }
.carousel-nav-btn:active:not(:disabled) { background: var(--surface-sunken); }
.carousel-nav-label {
  flex: 1 1 auto; min-width: 0;
  text-align: center;
  font-size: .75rem; font-weight: 700;
  color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.carousel-dots {
  display: flex; align-items: center; justify-content: center;
  gap: .3rem; flex-wrap: wrap;
  margin-top: .4rem;
}
.carousel-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--border-normal);
  transition: background var(--transition), width var(--transition);
}
.carousel-dot.active { background: var(--blue-500); width: 18px; border-radius: var(--radius-pill); }
.insp-tire-pos {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.875rem;
  color: var(--blue-600);
  margin-bottom: 0.5rem;
}
.insp-field { margin-bottom: 0.375rem; }
.insp-field label { font-size: 0.688rem; font-weight: 600; color: var(--text-muted); display: block; }
.insp-field input, .insp-field select {
  width: 100%;
  padding: 0.25rem 0.4rem;
  border: 1.5px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background-color: var(--surface-card);
  color: var(--text-body);
  font-size: 0.813rem;
  outline: none;
  box-sizing: border-box;
}
.insp-field input::placeholder { font-size: 0.7rem; color: var(--text-muted); opacity: .85; }
.insp-field input:focus, .insp-field select:focus { border-color: var(--blue-500); }
.insp-fields-row { display: grid; grid-template-columns: 1fr 1fr; gap: .375rem; }

/* ── Inspección — sección daños múltiples ── */
.insp-damages-section { margin-top: .75rem; border-top: 1px solid var(--border-subtle); padding-top: .625rem; }
.insp-last-damages {
  margin-top: .625rem;
  padding: .5rem .6rem;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px dashed var(--border-normal);
}
.insp-last-damages-title {
  font-size: .68rem; font-weight: 700; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .03em; margin-bottom: .35rem;
}
.insp-damages-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: .5rem; }
.insp-damages-title { font-size: .75rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.btn-add-damage {
  font-size: .75rem; font-weight: 600; color: var(--primary);
  background: none; border: 1.5px solid var(--primary); border-radius: var(--radius-sm);
  padding: .15rem .5rem; cursor: pointer;
}
.btn-add-damage:hover { background: var(--blue-50); }

/* Toggle Nuevo / Usado */
.toggle-pill-group { display: flex; gap: .375rem; }
.toggle-pill {
  padding: .35rem 1rem; border-radius: var(--radius-full);
  font-size: .8125rem; font-weight: 600;
  border: 1.5px solid var(--border-base); color: var(--text-muted);
  background: var(--surface-base); transition: all .15s;
}
.toggle-pill.active {
  background: var(--primary); border-color: var(--primary); color: #fff;
}
/* Punto que marca en qué pestaña quedó guardada la ubicación del daño (modal-damage-location),
   independiente de cuál pestaña se esté mirando en este momento. */
.dmg-loc-face-dot { color: var(--success); font-size: .6rem; }
.toggle-pill.active .dmg-loc-face-dot { color: #bbf7d0; }

/* Título de sección dentro de modal */
.form-section-title {
  font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); margin: .75rem 0 .375rem;
  padding-bottom: .25rem; border-bottom: 1px solid var(--border-base);
}
.form-label-hint { font-size: .7rem; font-weight: 400; color: var(--text-muted); margin-left: .25rem; }

/* ── Toggle de despacho (Pendiente / Enviado) ── */
.dispatch-toggle-wrap { padding: 0 0 .75rem; }
.dispatch-toggle {
  display: inline-flex; border: 1px solid var(--border);
  border-radius: var(--radius-sm); overflow: hidden; background: var(--surface-2);
}
.dt-btn {
  display: flex; align-items: center; gap: .45rem;
  padding: .45rem 1rem; font-size: .8125rem; font-weight: 500;
  color: var(--text-muted); background: transparent; border: none; cursor: pointer;
  transition: background .15s, color .15s;
}
.dt-btn:hover { color: var(--text); }
.dt-btn--active { background: var(--surface); color: var(--text); }
.dt-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.dt-dot--pending { background: #a78bfa; }
.dt-dot--sent    { background: #10b981; }
/* Colores específicos por sección */
.dt-dot--repair-pending  { background: #92400e; }   /* amber — pending_repair */
.dt-dot--repair-sent     { background: #c2410c; }   /* naranjo — repair/en planta */
.dt-dot--retread-pending { background: #6d28d9; }   /* morado — pending_retread */
.dt-dot--retread-sent    { background: #3b0764; }   /* morado oscuro — retread/en planta */
.dt-dot--transfer-sent    { background: var(--text-muted); } /* gris — trasladado */
.dt-dot--transfer-pending { background: #92400e; }   /* amber — pendiente de recepción */
.dt-count {
  background: #a78bfa; color: #fff; border-radius: 99px;
  font-size: .7rem; font-weight: 700; padding: 0 .4rem; min-width: 1.2rem;
  text-align: center; line-height: 1.4rem;
}
.dt-breakdown { font-size: .75rem; font-weight: 400; color: var(--text-muted); }

/* Tarjeta de info de neumático en modal despacho */
.dispatch-tire-card {
  background: var(--surface-2); border-radius: var(--radius-sm);
  padding: .625rem .875rem; font-size: .875rem;
  border-left: 3px solid #a78bfa;
}

/* Sub-grupos de opciones condicionales en modales de retorno */
.outcome-sub-group {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: .875rem 1rem;
  margin-bottom: .75rem;
}
.radio-group { display: flex; flex-direction: column; gap: .4rem; }
.radio-label { display: flex; align-items: center; gap: .5rem; font-size: .875rem; cursor: pointer; }
.radio-label input[type="radio"] { accent-color: var(--primary); width: 1rem; height: 1rem; }

/* Banner de info de causa de baja en modal reciclaje */
.scrap-info-banner {
  background: #fff1f2; border: 1px solid #fecdd3;
  border-radius: var(--radius-sm); padding: .5rem .75rem;
  font-size: .8125rem; margin-bottom: .25rem;
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
}

/* Time input 24h (two number fields) */
.time-input-24h { display: flex; align-items: center; gap: .375rem; }
.time-colon { font-weight: 700; font-size: 1.125rem; color: var(--text-strong); line-height: 1; }
.time-input-24h input[type="number"] { padding: .375rem .25rem; }
/* Hide number spinners */
.time-input-24h input[type="number"]::-webkit-inner-spin-button,
.time-input-24h input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.time-input-24h input[type="number"] { -moz-appearance: textfield; }

/* Toggle switch (iOS-style) */
.toggle-switch { position: relative; display: inline-block; width: 2.75rem; height: 1.5rem; flex-shrink: 0; }
.toggle-switch input { opacity: 0; width: 0; height: 0; }
.toggle-slider {
  position: absolute; inset: 0; background: #4a7fb5;
  border-radius: 1.5rem; cursor: pointer; transition: .2s;
}
[data-theme="light"] .toggle-slider { background: #a8b8c8; }
.toggle-slider::before {
  content: ''; position: absolute;
  width: 1.125rem; height: 1.125rem; left: .1875rem; top: .1875rem;
  background: #fff; border-radius: 50%; transition: .2s;
  box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
.toggle-switch input:checked + .toggle-slider { background: #e07b2b; }
.toggle-switch input:checked + .toggle-slider::before { transform: translateX(1.25rem); }

/* Fila de opción de configuración con toggle */
.config-toggle-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
  padding: .875rem 1rem; border: 1px solid var(--border-base);
  border-radius: var(--radius-md); background: var(--surface-base);
  margin-bottom: .625rem;
}

/* Fila trabajos de reparación */
.repair-work-row {
  display: flex; flex-direction: column; gap: .375rem; margin-bottom: .375rem;
}
.repair-work-fields {
  display: grid; grid-template-columns: 1fr 4.5rem 1fr auto;
  gap: .375rem; align-items: center;
}
.repair-work-photos { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }

/* ── Modal de validación de secuencia temporal ── */
.seq-section { margin-bottom: .75rem; }
.seq-section:last-child { margin-bottom: 0; }
.seq-section-label {
  font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  margin-bottom: .375rem; padding: .2rem .5rem; border-radius: var(--radius-sm);
}
.seq-section-label--error { background: #fee2e2; color: #991b1b; }
.seq-section-label--warn  { background: #fef9c3; color: #713f12; }
.seq-list { list-style: none; display: flex; flex-direction: column; gap: .375rem; }
.seq-item {
  display: flex; gap: .5rem; align-items: flex-start;
  font-size: .8125rem; line-height: 1.45;
  padding: .5rem .625rem; border-radius: var(--radius-sm);
}
.seq-item.seq-error { background: #fef2f2; color: #7f1d1d; border: 1px solid #fca5a5; }
.seq-item.seq-warn  { background: #fffbeb; color: #78350f; border: 1px solid #fcd34d; }
.seq-icon { flex-shrink: 0; font-weight: 700; margin-top: .05rem; }
.btn-warning {
  background: var(--btn-warning-bg); color: #fff; border: none; font-weight: 600;
}
.btn-warning:hover { background: var(--btn-warning-bg-hover); }

/* Fila de un daño */
.dmg-row {
  display: flex;
  flex-direction: column;
  gap: .4rem;
  background: var(--bg-secondary);
  border: 1.5px solid var(--border-subtle);
  border-radius: var(--radius);
  padding: .5rem .6rem;
  margin-bottom: .5rem;
}
.dmg-row-line3, .dmg-row-line4 {
  display: flex;
  align-items: center;
  gap: .5rem;
}
/* Selector de tipo de daño en su propia fila a ancho completo: cuando compartía fila
   con los botones de grado + eliminar en una tarjeta de 240px, el <select> quedaba con
   tan poco ancho que su texto se veía cortado a 2-3 caracteres. */
.dmg-row-line1 { display: flex; }
.dmg-row-line1 .dmg-type-sel { width: 100%; }
/* Grado + ubicación + eliminar: se deja envolver (flex-wrap) en vez de forzar una sola
   línea — así nunca se aprietan al punto de recortarse, en el peor caso pasan a una
   segunda línea dentro de la tarjeta. */
.dmg-row-line2 {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .4rem;
}
.dmg-row-line2 .dmg-del-btn { margin-left: auto; }
.dmg-history-badge {
  display: inline-block;
  font-size: .65rem; font-weight: 700;
  color: var(--blue-600); background: var(--blue-50);
  padding: .1rem .45rem; border-radius: 999px;
  margin-bottom: .3rem;
}
.dmg-row-line3 { align-items: stretch; }
.dmg-row-line3 .dmg-notes-inp { flex: 1; min-width: 0; }
.dmg-type-sel  { font-size: .775rem; width: 100%; }
.dmg-notes-inp {
  font-size: .775rem;
  resize: none;
  overflow: hidden;
  min-height: 2.1rem;
  line-height: 1.35;
  font-family: inherit;
}
.dmg-row-line4 { flex-wrap: wrap; align-items: flex-start; }

/* Botones de grado G1/G2/G3 */
.dmg-grade-group { display: flex; gap: .2rem; }
.dmg-grade-btn {
  font-size: .7rem; font-weight: 800; padding: .15rem .35rem;
  border-radius: var(--radius-sm); border: 2px solid transparent;
  cursor: pointer; background: var(--bg-tertiary); color: var(--text-muted);
  transition: all .15s;
}
.dmg-grade-btn.G1.active, .dmg-grade-btn.G1:hover { background: var(--grade-1-bg); color: var(--grade-1-fg); border-color: var(--grade-1-border); }
.dmg-grade-btn.G2.active, .dmg-grade-btn.G2:hover { background: var(--grade-2-bg); color: var(--grade-2-fg); border-color: var(--grade-2-border); }
.dmg-grade-btn.G3.active, .dmg-grade-btn.G3:hover { background: var(--grade-3-bg); color: var(--grade-3-fg); border-color: var(--grade-3-border); }

/* Botón "Ubicación del daño" — abre el diagrama de reloj (modal-damage-location) */
.btn-dmg-location {
  font-size: .68rem; font-weight: 600; color: var(--primary);
  background: none; border: 1.5px solid var(--primary); border-radius: var(--radius-sm);
  padding: .15rem .4rem; cursor: pointer; white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.btn-dmg-location:hover { background: var(--blue-50); }
.btn-dmg-location.has-location { color: var(--success); border-color: var(--success); }

/* Foto */
.dmg-photo-label {
  display: flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border-radius: var(--radius-sm);
  background: var(--bg-tertiary); border: 1.5px dashed var(--border-normal);
  cursor: pointer; font-size: 1rem; position: relative;
}
.dmg-photo-label:hover { border-color: var(--primary); background: var(--blue-50); }
.dmg-photo-inp { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; }
.dmg-photo-preview { width: 2rem; height: 2rem; }
.dmg-photo-thumb { width: 2rem; height: 2rem; object-fit: cover; border-radius: var(--radius-sm); border: 1.5px solid var(--border-normal); }
.dmg-uploading { font-size: .65rem; color: var(--text-muted); }
.dmg-upload-err { font-size: .65rem; color: var(--error); }
.dmg-photos-gallery { display: flex; flex-wrap: wrap; gap: .3rem; }
.dmg-photo-thumb-wrap { position: relative; width: 2rem; height: 2rem; flex-shrink: 0; }
.dmg-photo-thumb-wrap .dmg-photo-thumb { width: 100%; height: 100%; }
.dmg-photo-thumb-pending .dmg-photo-thumb { opacity: .6; }
.dmg-photo-pending-badge {
  position: absolute; bottom: -3px; left: -3px;
  font-size: .6rem; line-height: 1;
  background: var(--warning-bg); border-radius: 50%;
  padding: 1px;
}
.dmg-photo-remove {
  position: absolute; top: -5px; right: -5px;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--error); color: #fff; border: none;
  font-size: .55rem; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.dmg-photo-thumb { cursor: pointer; }
.dmg-photo-lock {
  position: absolute; top: -5px; right: -5px;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--surface-2, #e5e7eb); border: 1px solid var(--border-normal);
  font-size: .55rem; line-height: 1; cursor: default;
  display: flex; align-items: center; justify-content: center;
}
.dmg-photo-status { font-size: .65rem; color: var(--text-muted); }

/* Visor de fotos (lightbox) */
.photo-lightbox {
  display: none;
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(0,0,0,.82);
  align-items: center; justify-content: center;
  padding: 1.5rem;
}
.photo-lightbox-inner {
  position: relative; max-width: 92vw; max-height: 92vh;
  display: flex; flex-direction: column; align-items: center; gap: .6rem;
}
.photo-lightbox-img {
  max-width: 92vw; max-height: 82vh; object-fit: contain;
  border-radius: var(--radius-md); box-shadow: 0 8px 40px rgba(0,0,0,.5);
}
.photo-lightbox-meta {
  color: #fff; font-size: .85rem; background: rgba(0,0,0,.4);
  padding: .4rem .9rem; border-radius: 999px;
}
.photo-lightbox-close {
  position: absolute; top: -14px; right: -14px;
  width: 34px; height: 34px; border-radius: 50%;
  background: #fff; color: #111; border: none; cursor: pointer;
  font-size: 1rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 10px rgba(0,0,0,.4);
}
.dmg-del-btn {
  width: 1.5rem; height: 1.5rem; border-radius: 50%; background: var(--error-bg);
  color: var(--error); border: none; cursor: pointer; font-size: .7rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.dmg-del-btn:hover { background: var(--error); color: white; }

/* ── Badges de grado en tarjeta de vida ── */
.dmg-grade-badge {
  display: inline-block; font-size: .65rem; font-weight: 800;
  padding: .05rem .3rem; border-radius: .25rem; margin-right: .25rem;
}
.dmg-grade-badge.G1 { background: var(--grade-1-bg); color: var(--grade-1-fg); }
.dmg-grade-badge.G2 { background: var(--grade-2-bg); color: var(--grade-2-fg); }
.dmg-grade-badge.G3 { background: var(--grade-3-bg); color: var(--grade-3-fg); }
.dmg-chip { flex-wrap: wrap; align-items: center; padding: .25rem .5rem; }
.dmg-chip-g1 { background: var(--grade-1-bg) !important; color: var(--grade-1-fg) !important; }
.dmg-chip-g2 { background: var(--grade-2-bg) !important; color: var(--grade-2-fg) !important; }
.dmg-chip-g3 { background: var(--grade-3-bg) !important; color: var(--grade-3-fg) !important; }
.dmg-photo-link { margin-left: .25rem; text-decoration: none; font-size: .85rem; }
/* Código+nombre del daño destacados; las notas van en su propia línea dentro del chip
   en vez de quedar todo mezclado en un solo bloque de texto monoespaciado. */
.dmg-chip-text { font-weight: 700; }
.dmg-chip em { flex-basis: 100%; font-style: italic; opacity: .85; }

/* ── Empty state ── */
.empty-state {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--text-muted);
}
.empty-state-icon { font-size: 2.5rem; margin-bottom: 0.75rem; opacity: .4; }
.empty-state h3 { font-size: 1rem; color: var(--text-strong); margin-bottom: 0.375rem; }
.empty-state p  { font-size: 0.875rem; }

/* ── KPI progress ring ── */
.kpi-ring-wrap { display: flex; align-items: center; gap: 1rem; }
.kpi-ring { position: relative; width: 72px; height: 72px; }
.kpi-ring svg { transform: rotate(-90deg); }
.kpi-ring-val {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 0.938rem;
  font-weight: 800;
  color: var(--text-strong);
}

/* ── Tabs ── */
.tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 2px solid var(--border-subtle);
  margin-bottom: 1.25rem;
}
.tab-btn {
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-muted);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: color var(--transition), border-color var(--transition);
}
.tab-btn.active { color: var(--blue-600); border-color: var(--blue-500); }
.tab-btn:hover  { color: var(--text-body); }

/* ── Pill filter chips ── */
.filter-chips { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.chip {
  padding: 0.3rem 0.875rem;
  border-radius: var(--radius-pill);
  font-size: 0.813rem;
  font-weight: 600;
  border: 1.5px solid var(--border-normal);
  color: var(--text-muted);
  cursor: pointer;
  transition: all var(--transition);
}
.chip.active { background: var(--blue-500); border-color: var(--blue-500); color: #fff; }
.chip:hover:not(.active) { border-color: var(--blue-400); color: var(--blue-600); }

/* ── History timeline ── */
.timeline { list-style: none; position: relative; padding-left: 1.5rem; }
.timeline::before {
  content: '';
  position: absolute;
  left: 0.375rem;
  top: 0; bottom: 0;
  width: 2px;
  background: var(--border-subtle);
}
.timeline-item {
  position: relative;
  padding: 0 0 1.25rem 1rem;
}
.timeline-dot {
  position: absolute;
  left: -1.125rem;
  top: 0.25rem;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--blue-400);
  border: 2px solid var(--surface-card);
}
.timeline-date { font-size: 0.75rem; color: var(--text-muted); margin-bottom: 0.125rem; }
.timeline-desc { font-size: 0.875rem; color: var(--text-body); }

/* ── Loading spinner ── */
.spinner {
  width: 24px; height: 24px;
  border: 3px solid var(--border-subtle);
  border-top-color: var(--blue-500);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading-overlay {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 3rem;
  color: var(--text-muted);
  font-size: 0.875rem;
}

/* ── Confirm dialog ── */
.modal-confirm { max-width: 360px !important; }
.confirm-icon  { font-size: 2rem; text-align: center; margin-bottom: .5rem; }
.confirm-msg   { color: var(--text-body); font-size: .938rem; text-align: center; line-height: 1.6; }

/* ── Alerts bell ── */
.topbar-alerts { position: relative; }
.alert-bell { padding: .375rem; border-radius: var(--radius-sm); color: var(--text-muted); position: relative; }
.alert-bell:hover { background: var(--surface-sunken); }
.alert-badge {
  position: absolute; top: 2px; right: 2px;
  background: var(--error); color: #fff;
  font-size: .625rem; font-weight: 700;
  min-width: 16px; height: 16px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 3px; pointer-events: none;
}
.alerts-panel {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: 340px; max-height: 420px; overflow-y: auto;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-modal);
  z-index: 300;
}
.alerts-panel-header {
  padding: .75rem 1rem;
  border-bottom: 1px solid var(--border-subtle);
  font-size: .813rem; font-weight: 700; color: var(--text-strong);
  display: flex; align-items: center; justify-content: space-between;
}
.alert-item {
  display: flex; gap: .75rem; align-items: flex-start;
  padding: .75rem 1rem;
  border-bottom: 1px solid var(--border-subtle);
  cursor: pointer; transition: background var(--transition);
}
.alert-item:last-child { border-bottom: none; }
.alert-item:hover { background: var(--surface-sunken); }
.alert-dot {
  width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; margin-top: 5px;
}
.alert-dot-error   { background: var(--error); }
.alert-dot-warning { background: var(--warning); }
.alert-dot-info    { background: var(--blue-400); }
.alert-text { font-size: .813rem; color: var(--text-body); line-height: 1.4; }
.alerts-empty { padding: 2rem; text-align: center; color: var(--text-muted); font-size: .875rem; }

/* ── Skeleton loaders ── */
.skeleton {
  background: linear-gradient(90deg, var(--surface-sunken) 25%, var(--border-subtle) 50%, var(--surface-sunken) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s infinite;
  border-radius: var(--radius-sm);
}
@keyframes shimmer { to { background-position: -200% 0; } }
.skeleton-row { height: 48px; margin-bottom: 1px; }
.skeleton-card { height: 100px; border-radius: var(--radius-xl); margin-bottom: 1rem; }
.skeleton-stat { height: 110px; border-radius: var(--radius-xl); }

/* Versión de los archivos cargados, al pie del menú lateral. */
.sidebar-version {
  margin-top: .5rem;
  text-align: center;
  font-size: .65rem;
  font-family: var(--font-mono, monospace);
  color: var(--text-muted);
  opacity: .7;
}

/* ── Aviso flotante de instalación de la PWA ──────────────────────────────────
   Reemplaza a la antigua barra inferior de navegación (retirada el 2026-08-14:
   la navegación vive solo en el drawer lateral). Es una tarjeta flotante sobre
   el contenido, no un elemento del chasis, así que no reserva espacio. */
.install-banner {
  position: fixed;
  left: max(.75rem, env(safe-area-inset-left, 0px));
  right: max(.75rem, env(safe-area-inset-right, 0px));
  bottom: calc(.75rem + env(safe-area-inset-bottom, 0px));
  z-index: 300;
  display: flex; align-items: center; gap: .75rem;
  padding: .875rem 2.25rem .875rem .875rem;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  box-shadow: 0 12px 32px rgba(12,23,38,.28);
  animation: install-banner-in .28s ease-out;
}
.install-banner[hidden] { display: none; }
@keyframes install-banner-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
.install-banner-icon img {
  width: 40px; height: 40px; border-radius: var(--radius-md); display: block;
}
/* flex-basis 0 y min-width 0: con `auto` el texto imponía su ancho natural, no
   cabía junto al ícono y se iba a una línea propia — el aviso quedaba de 190px
   de alto tapando media pantalla. */
.install-banner-body { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: .15rem; }
.install-banner-body strong { font-size: .9375rem; color: var(--text-strong); }
.install-banner-body span { font-size: .75rem; line-height: 1.35; color: var(--text-muted); }
.install-banner-actions { display: flex; gap: .5rem; flex-shrink: 0; }
.install-banner-close {
  position: absolute; top: .35rem; right: .35rem;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted); border-radius: var(--radius-sm);
}
.install-banner-close svg { width: 15px; height: 15px; }
/* En teléfono el texto y los botones no caben en una línea: se apila. */
@media (max-width: 639px) {
  .install-banner { flex-wrap: wrap; }
  .install-banner-actions { width: 100%; }
  .install-banner-actions .btn { flex: 1 1 0; justify-content: center; }
}

/* ── Profile view ── */
.profile-grid {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 1.25rem;
  align-items: start;
}
.profile-avatar-card {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  padding: 2rem 1.5rem;
  text-align: center;
  box-shadow: var(--shadow-card);
}
.profile-avatar-big {
  width: 80px; height: 80px; border-radius: 50%;
  background: var(--gradient-brand);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 2rem; font-weight: 800;
  color: #fff; margin: 0 auto 1rem;
}
.profile-name  { font-family: var(--font-display); font-size: 1.125rem; font-weight: 700; color: var(--text-strong); }
.profile-role  { font-size: .813rem; color: var(--text-muted); margin-top: .25rem; }
.profile-badge { margin-top: .75rem; }

/* ── Profile layout ── */
.profile-layout { display: grid; grid-template-columns: 260px 1fr; gap: 1.25rem; align-items: start; }
.profile-left-col { display: flex; flex-direction: column; gap: 1.25rem; }
.profile-right-col { display: flex; flex-direction: column; gap: 1.25rem; }
.profile-id-card { }

/* Avatar con foto */
.profile-avatar-zone { display: flex; flex-direction: column; align-items: center; padding: 1.5rem 1.25rem 1rem; border-bottom: 1px solid var(--border-subtle); }
.profile-avatar-wrap-photo {
  position: relative; width: 80px; height: 80px; border-radius: 50%; cursor: pointer;
  overflow: hidden; flex-shrink: 0;
}
.profile-avatar-wrap-photo .profile-avatar-big {
  width: 80px; height: 80px; font-size: 1.75rem; border-radius: 50%;
}
.profile-avatar-wrap-photo img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 50%;
}
.profile-avatar-overlay {
  position: absolute; inset: 0; border-radius: 50%;
  background: rgba(0,0,0,.45); display: flex; align-items: center; justify-content: center;
  font-size: 1.25rem; opacity: 0; transition: opacity .15s;
}
.profile-avatar-wrap-photo:hover .profile-avatar-overlay { opacity: 1; }

.profile-avatar-big {
  width: 80px; height: 80px; border-radius: 50%; flex-shrink: 0;
  background: var(--gradient-brand);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 1.75rem; font-weight: 800; color: #fff;
}
.profile-name { font-family: var(--font-display); font-size: 1.125rem; font-weight: 700; color: var(--text-strong); line-height: 1.2; }
.profile-info-list { padding: 1rem 1.25rem; display: flex; flex-direction: column; gap: .75rem; }
.profile-info-row { display: flex; flex-direction: column; gap: .125rem; }
.profile-info-label { font-size: .688rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); font-weight: 600; }
.profile-info-val { font-size: .875rem; color: var(--text-strong); font-weight: 500; }
.profile-session-row {
  display: flex; align-items: center; gap: .75rem;
  padding: .625rem .75rem; border-radius: var(--radius-md);
  background: var(--surface-subtle); margin-bottom: .5rem;
}
.profile-session-icon { font-size: 1.25rem; flex-shrink: 0; }
.profile-session-info { flex: 1; min-width: 0; }
.profile-session-device { font-size: .813rem; font-weight: 600; color: var(--text-strong); }
.profile-session-date { font-size: .75rem; color: var(--text-muted); }
.profile-session-current { border: 1px solid var(--blue-300); background: var(--blue-50); }

/* ── Equipment detail ── */
.eq-detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; }
.eq-detail-item { }
.eq-detail-label { font-size: .75rem; color: var(--text-muted); font-weight: 600; margin-bottom: .125rem; }
.eq-detail-value { font-size: .938rem; color: var(--text-strong); font-weight: 600; }
.tire-position-badge {
  display: inline-flex; align-items: center; gap: .375rem;
  padding: .375rem .75rem;
  background: var(--blue-50); border: 1px solid var(--blue-200);
  border-radius: var(--radius-md);
  font-size: .813rem; font-weight: 600; color: var(--blue-700);
  margin: .25rem;
}

/* ── Reports avanzados ── */
.report-filter-bar {
  display: flex; gap: .75rem; flex-wrap: wrap;
  align-items: flex-end; margin-bottom: 1.25rem;
  padding: 1rem 1.25rem;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
}
.report-filter-bar .form-group { margin: 0; min-width: 140px; }
.report-summary-grid {
  display: grid; grid-template-columns: repeat(4,1fr); gap: 1rem; margin-bottom: 1.25rem;
}
.report-kpi {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  padding: 1rem 1.25rem;
  box-shadow: var(--shadow-card);
}
.report-kpi-val { font-family: var(--font-display); font-size: 1.5rem; font-weight: 800; color: var(--text-strong); }
.report-kpi-label { font-size: .75rem; color: var(--text-muted); margin-top: .125rem; }

/* ── Onboarding banner ── */
.onboarding-banner {
  background: var(--gradient-brand);
  border-radius: var(--radius-xl);
  padding: 1.5rem;
  color: #fff;
  margin-bottom: 1.5rem;
  display: flex; align-items: center; gap: 1.25rem;
}
.onboarding-icon { font-size: 2.5rem; flex-shrink: 0; }
.onboarding-title { font-family: var(--font-display); font-size: 1rem; font-weight: 700; margin-bottom: .25rem; }
.onboarding-text  { font-size: .875rem; opacity: .85; }
.onboarding-steps {
  display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .75rem;
}
.onboarding-step {
  background: rgba(255,255,255,.18); border-radius: var(--radius-pill);
  padding: .25rem .75rem; font-size: .75rem; font-weight: 600;
  display: flex; align-items: center; gap: .375rem;
}
.onboarding-step.done { background: rgba(22,163,90,.4); }

/* ── Tooltip ── */
[data-tip] { position: relative; cursor: help; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute; bottom: calc(100% + 6px); left: 50%;
  transform: translateX(-50%);
  background: var(--text-strong); color: #fff;
  font-size: .688rem; font-weight: 500; white-space: nowrap;
  padding: .25rem .5rem; border-radius: var(--radius-sm);
  pointer-events: none; opacity: 0; transition: opacity .15s;
  z-index: 500;
}
[data-tip]:hover::after { opacity: 1; }

/* ── Modal XL ── */
.modal-xl { max-width: 900px; width: 96vw; }

/* ── Tarjeta de vida del neumático ── */
.tire-life-header {
  background: var(--gradient-ink);
  color: #fff;
  padding: 1.5rem 1.75rem;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1rem;
  align-items: start;
}
.tire-life-id {
  font-family: var(--font-mono);
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: .02em;
  line-height: 1;
}
.tire-life-meta {
  margin-top: .375rem;
  font-size: .813rem;
  opacity: .75;
  display: flex; gap: 1rem; flex-wrap: wrap;
}
.tire-life-stats {
  display: grid;
  grid-template-columns: repeat(4,1fr);
  gap: 0;
  border-bottom: 1px solid var(--border-normal);
}
.tire-life-stat {
  padding: 1rem 1.25rem;
  border-right: 1px solid var(--border-normal);
  text-align: center;
}
.tire-life-stat:last-child { border-right: none; }
.tire-life-stat-val {
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 800;
  color: var(--blue-500);
  line-height: 1;
}
.tire-life-stat-lbl {
  font-size: .688rem;
  color: var(--text-muted);
  margin-top: .25rem;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.tire-life-body { padding: 1.5rem 1.75rem; }
.tire-life-section-title {
  font-family: var(--font-display);
  font-size: .875rem;
  font-weight: 700;
  color: var(--text-strong);
  text-transform: uppercase;
  letter-spacing: .06em;
  margin: 1.5rem 0 .75rem;
}
.tire-life-section-title:first-child { margin-top: 0; }

/* ── Timeline vertical ── */
.tl { position: relative; padding-left: 2rem; }
.tl::before {
  content: '';
  position: absolute; left: .6875rem; top: 0; bottom: 0;
  width: 2px;
  background: var(--border-normal);
}
.tl-item {
  position: relative;
  padding: 0 0 1.25rem 1rem;
}
.tl-item:last-child { padding-bottom: 0; }
.tl-dot {
  position: absolute; left: -1.4375rem; top: .25rem;
  width: 14px; height: 14px;
  border-radius: 50%;
  border: 2px solid var(--surface-card);
  background: var(--blue-400);
  z-index: 1;
}
.tl-dot.tl-mount    { background: var(--success); }
.tl-dot.tl-dismount { background: var(--text-muted); }
.tl-dot.tl-repair   { background: var(--warning); }
.tl-dot.tl-retread  { background: #6b3fa0; }
.tl-dot.tl-recycling { background: var(--error); }
.tl-dot.tl-scrap    { background: var(--error); }
.tl-dot.tl-create   { background: var(--blue-500); }
.tl-dot.tl-inspect  { background: #0891b2; }
.tl-date {
  font-size: .75rem;
  color: var(--text-muted);
  font-family: var(--font-mono);
  margin-bottom: .125rem;
}
.tl-label {
  font-size: .875rem;
  font-weight: 600;
  color: var(--text-strong);
}
.tl-detail {
  font-size: .813rem;
  color: var(--text-body);
  margin-top: .125rem;
}
.tl-insp-row {
  display: flex; gap: 1rem; flex-wrap: wrap;
  margin-top: .375rem;
}
.tl-insp-chip {
  background: var(--surface-subtle);
  border-radius: var(--radius-sm);
  padding: .125rem .5rem;
  font-size: .75rem;
  font-family: var(--font-mono);
  display: flex; align-items: center; gap: .25rem;
}
.tl-insp-chip.warn  { background: var(--warning-bg); color: #a16207; }
.tl-insp-chip.crit  { background: var(--error-bg); color: var(--error); }

/* ── Corrección ── */
.correction-info-box {
  background: var(--surface-subtle);
  border-radius: var(--radius-md);
  padding: .75rem 1rem;
  font-size: .813rem;
}
.correction-info-box strong { display: block; font-size: .875rem; margin-bottom: .25rem; }
.correction-badge {
  display: inline-flex; align-items: center; gap: .25rem;
  background: var(--warning-bg); color: #a16207;
  border-radius: var(--radius-pill);
  padding: .125rem .5rem;
  font-size: .688rem; font-weight: 600;
  cursor: pointer;
}
.corr-tab-panel { display: block; }
.corr-tab-panel[style*="display:none"] { display: none !important; }
.correction-row-old { color: var(--error); text-decoration: line-through; font-size: .813rem; }
.correction-row-new { color: var(--success); font-weight: 600; font-size: .813rem; }

/* ── Editor de posiciones (canvas drag) ── */
.pos-presets { display: flex; flex-wrap: wrap; gap: .3rem; margin-bottom: .75rem; }
.btn-preset {
  font-size: .75rem; padding: .25rem .625rem; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--bg-secondary);
  color: var(--text-primary); cursor: pointer; transition: background .15s;
}
.btn-preset:hover { background: var(--bg-hover); }
.pos-canvas {
  position: relative;
  background-color: var(--bg-secondary);
  background-image: radial-gradient(circle, rgba(74,157,224,.35) 1.5px, transparent 1.5px);
  background-size: 88px 72px;
  background-position: 60px 52px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  user-select: none;
  touch-action: none;
  overflow: visible;
}
.pos-tire {
  position: absolute;
  cursor: grab;
  transition: transform .1s;
}
.pos-tire:active { cursor: grabbing; }
.pos-tire-edit, .pos-tire-del {
  position: absolute; border: none; border-radius: 50%;
  cursor: pointer; width: 18px; height: 18px;
  font-size: .65rem; line-height: 18px; text-align: center; padding: 0;
  opacity: 0; transition: opacity .15s; z-index: 10;
  box-shadow: 0 1px 3px rgba(0,0,0,.4);
}
.pos-tire:hover .pos-tire-edit,
.pos-tire:hover .pos-tire-del { opacity: 1; }
.pos-tire-edit { top: -7px; right: -7px; background: #2e82cc; color: white; }
.pos-tire-del  { top: -7px; left: -7px;  background: var(--error); color: white; }
.btn-add-tire {
  margin-top: .75rem; font-size: .8rem; padding: .375rem .875rem;
  border: 1.5px dashed var(--border); background: transparent;
  border-radius: var(--radius); cursor: pointer; color: var(--text-muted);
  transition: border-color .15s, color .15s; display: inline-block;
}
.btn-add-tire:hover { border-color: #2e82cc; color: #2e82cc; }

/* ── Compatibilidad tipo equipo ↔ tipo neumático ── */
.compat-tire-list {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  max-height: 200px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.5rem;
  background: var(--bg-secondary);
}
.compat-tire-opt {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.375rem 0.5rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background .15s;
  font-size: 0.875rem;
}
.compat-tire-opt:hover { background: var(--bg-hover); }
.compat-tire-opt input[type="checkbox"] { accent-color: var(--primary); width: 15px; height: 15px; flex-shrink: 0; }

/* ── Responsive: tablet ──
   La segunda condición hace que TODO dispositivo táctil (sin mouse) use este
   layout sin importar su ancho: así el teléfono en horizontal sigue con drawer
   y hamburguesa en vez de saltar al layout de escritorio. */
@media (max-width: 899px), (hover: none) and (pointer: coarse) {
  .sidebar { transform: translateX(-100%); }
  .sidebar.open { transform: none; }
  .main-content { margin-left: 0; }
  .btn-hamburger { display: flex; }
  .sidebar-toggle-btn { display: none !important; }
  .dash-grid { grid-template-columns: 1fr 1fr; }
  .mount-layout { flex-direction: column; height: auto; }
  .mount-left { flex: 0 0 auto; min-width: 0; }
  .mount-stock-right { flex: 0 0 auto; min-width: 0; }
  #mount-armed-panel { flex: 0 0 220px; }
  .mount-left-bottom { grid-template-columns: 1fr; }
  .mount-resize-col { display: none; }
  .form-grid { grid-template-columns: 1fr; }
  .sync-text { display: none; }
  .profile-grid { grid-template-columns: 1fr; }
  .profile-layout { grid-template-columns: 1fr; }
  .profile-id-card { grid-row: auto; }
  .report-summary-grid { grid-template-columns: 1fr 1fr; }
  .eq-detail-grid { grid-template-columns: 1fr; }
  .alerts-panel { width: 300px; }
}
/* ── Responsive: teléfono ──
   "Teléfono" = pantalla angosta O dispositivo táctil de poca altura (teléfono
   en horizontal, ~412px de alto). Una tablet en horizontal (768px de alto) NO
   entra aquí y conserva el layout más amplio. */
@media (max-width: 639px), (hover: none) and (pointer: coarse) and (max-height: 559px) {
  .main-content { padding: 1rem; padding-bottom: 72px; }
  .dash-grid { grid-template-columns: 1fr 1fr; }
  .dash-row { grid-template-columns: 1fr; }
  .modal-backdrop { align-items: flex-end; padding: 0; }
  .modal { border-radius: var(--radius-xl) var(--radius-xl) 0 0; max-height: 90dvh; }
  .page-header { flex-direction: column; align-items: flex-start; }
  .report-summary-grid { grid-template-columns: 1fr 1fr; }
  .alerts-panel { width: calc(100vw - 2rem); right: -1rem; }
}
/* ── Mount mode bar ─ (duplicate toggle block removed, kept definition above) ── */

/* ── Mount mode bar ─────────────────────────────────────────────────────────── */
.mount-mode-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  background: var(--surface-raised); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: .6rem 1rem; margin-bottom: .6rem;
}

/* ── Slot indicators ────────────────────────────────────────────────────────── */
.slot-rim-badge {
  font-size: .65rem; color: var(--primary); background: var(--primary)15;
  border-radius: 3px; padding: .1rem .3rem; margin-top: .1rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.slot-rim-only {
  font-size: .72rem; color: #b45309; background: #fff3cd;
  border-radius: 3px; padding: .15rem .4rem; text-align: center;
}
.wheel-slot.has-free-rim {
  border-color: #e07b2b;
  border-style: dashed;
  background: var(--surface-sunken);
}

/* ── Assemble tire list ─────────────────────────────────────────────────────── */
.assemble-tire-opt {
  display: flex; align-items: center; gap: .75rem;
  padding: .5rem .75rem; cursor: pointer; border-bottom: 1px solid var(--border-subtle);
  transition: background .1s;
}
.assemble-tire-opt:last-child { border-bottom: none; }
.assemble-tire-opt:hover { background: var(--surface-hover); }
.assemble-tire-opt.selected { background: var(--primary)15; border-left: 3px solid var(--primary); }

/* ── Multi-tire dispatch chips ──────────────────────────────────────────────── */
.dispatch-chips {
  margin-top: .5rem;
  padding: .5rem .6rem;
  background: var(--surface-2);
  border-radius: var(--radius);
  border: 1px solid var(--border);
}
.dispatch-chips-label {
  font-size: .75rem;
  color: var(--text-muted);
  margin-bottom: .35rem;
  font-weight: 500;
}
.dispatch-chip {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  /* antes: var(--primary), variable inexistente → chip invisible (blanco sobre blanco) */
  background: var(--blue-500);
  color: #fff;
  font-size: .75rem;
  font-weight: 500;
  padding: .2rem .55rem;
  border-radius: 999px;
  margin: .15rem .2rem .15rem 0;
}
.dispatch-chip button {
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  font-size: .85rem;
  opacity: .75;
}
.dispatch-chip button:hover { opacity: 1; }

/* ── Lista de componentes con daño por ítem (Reparación / pendiente de envío) ── */
.dispatch-item-list { display: flex; flex-direction: column; gap: .5rem; }
.dispatch-item-row {
  display: grid;
  grid-template-columns: minmax(150px,1fr) minmax(150px,190px) minmax(180px,1fr);
  gap: .5rem;
  align-items: start;
  padding: .4rem 0;
  border-bottom: 1px solid var(--border-subtle);
}
.dispatch-item-row:last-child { border-bottom: none; }
.dir-head { display: flex; align-items: center; gap: .4rem; font-size: .8rem; padding-top: .5rem; }
.dir-remove {
  background: none; border: none; color: var(--text-muted); cursor: pointer;
  font-size: .85rem; line-height: 1; padding: .15rem; flex-shrink: 0;
}
.dir-remove:hover { color: var(--error); }
.dir-type { font-size: .7rem; opacity: .75; flex-shrink: 0; }
.dir-label { font-family: var(--font-mono); font-weight: 600; }

/* ── Mount Step 2 header ────────────────────────────────────────────────────── */
.mount-step2-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: .75rem 1rem;
  margin-bottom: .75rem;
}
.mount-pending-bar {
  background: var(--warning-bg);
  color: var(--warning);
  border: 1px solid var(--warning-border, #fcd34d);
  border-radius: var(--radius-md);
  padding: .4rem .75rem;
  font-size: .8rem;
  font-weight: 600;
  margin-bottom: .75rem;
}
/* Slot con neumático recién montado en sesión */
.wheel-slot.slot-new {
  border-color: var(--primary);
  box-shadow: 0 0 0 2px var(--primary)33;
}
/* El montaje ya no espera a que se ingrese el torque para completarse (ver
   _placeStockTireAt) — este badge recuerda que falta antes de poder guardar. */
.wheel-slot.slot-torque-pending { border-color: var(--warning); }
.slot-torque-badge {
  position: absolute; top: 5px; right: 6px;
  background: var(--warning-bg); color: var(--warning);
  font-size: .7rem; line-height: 1; padding: 2px 4px; border-radius: 999px;
  border: 1px solid var(--warning);
}
/* Botón de desmontar bloqueado */
.btn-dismount-blocked {
  background: var(--surface-raised) !important;
  color: var(--text-muted) !important;
  cursor: not-allowed !important;
  opacity: .6;
}
/* ── Cadena: overlay sobre slot de neumático ─────────────────────────────────── */
.wheel-slot.has-chain {
  position: relative;
}
.chain-slot-overlay {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-start;
}
.chain-slot-overlay .chain-slot-remove {
  pointer-events: all;
  position: absolute;
  top: 4px;
  right: 4px;
  background: rgba(0,0,0,.6);
  color: #fff;
  border: 1.5px solid rgba(255,255,255,.5);
  border-radius: 50%;
  width: 24px;
  height: 24px;
  font-size: .85rem;
  line-height: 21px;
  text-align: center;
  cursor: pointer;
  padding: 0;
  z-index: 4;
  transition: background .15s, transform .15s;
}
.chain-slot-overlay .chain-slot-remove:hover { background: var(--error); transform: scale(1.1); }
/* Toda la cadena se resalta al pasar el mouse por cualquier parte de ella, no solo el botón —
   así el botón de retirar es más fácil de descubrir. */
.wheel-slot.has-chain:hover .chain-overlay-svg { filter: brightness(1.3); }
.chain-overlay-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  z-index: 2;
}
.chain-slot-label {
  position: absolute;
  bottom: 4px;
  left: 0;
  right: 0;
  text-align: center;
  font-size: .6rem;
  font-weight: 700;
  color: #e8e8e8;
  text-shadow: 0 1px 3px rgba(0,0,0,.8);
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 0 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chain-slot-label svg { flex-shrink: 0; color: #ddd; }
/* Hint cuando se arrastra cadena sobre un slot con neumático */
.chain-drop-hint {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  font-size: .65rem;
  font-weight: 600;
  color: var(--warning);
  background: rgba(0,0,0,.25);
  border-radius: inherit;
  z-index: 1;
  pointer-events: none;
}
.wheel-slot.drag-over .chain-drop-hint {
  display: flex;
}
/* Toggle naranja para cadenas */
/* .toggle-slider-orange is now identical to .toggle-slider */

/* ── Assembly item popup ───────────────────────────────────── */
.asm-popup {
  position: fixed;
  z-index: 9000;
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0,0,0,.35);
  padding: .75rem 1rem;
  min-width: 200px;
  max-width: 280px;
  font-size: .8125rem;
}
.asm-popup-title {
  font-weight: 700;
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
  margin-bottom: .375rem;
}
.asm-popup-row {
  display: flex;
  justify-content: space-between;
  gap: .5rem;
  padding: .15rem 0;
  border-bottom: 1px solid var(--border);
}
.asm-popup-row:last-child { border-bottom: none; }
.asm-popup-label {
  color: var(--text-muted);
  white-space: nowrap;
}
.asm-popup-close {
  position: absolute;
  top: .35rem;
  right: .5rem;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: .75rem;
  padding: 0;
  line-height: 1;
}
.asm-popup-close:hover { color: var(--text-strong); }

/* ── Photo upload zone ──────────────────────────────────────── */
.photo-upload-zone {
  border: 1.5px dashed var(--border);
  border-radius: var(--radius);
  padding: .75rem;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.photo-preview-list {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}
.photo-thumb-item {
  position: relative;
  width: 72px;
  height: 72px;
  border-radius: calc(var(--radius) - 2px);
  overflow: hidden;
  border: 1px solid var(--border);
}
.photo-thumb-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.photo-thumb-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(0,0,0,.65);
  color: #fff;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .6rem;
  line-height: 1;
  padding: 0;
}
.photo-thumb-remove:hover { background: var(--danger); }
.photo-existing-grid {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-bottom: .5rem;
}
.photo-existing-item {
  position: relative;
  width: 72px;
  height: 72px;
  border-radius: calc(var(--radius) - 2px);
  overflow: hidden;
  border: 1px solid var(--border);
}
.photo-existing-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  cursor: pointer;
}
.photo-existing-del {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(0,0,0,.65);
  color: #fff;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .6rem;
  padding: 0;
}
.photo-existing-del:hover { background: var(--danger); }
.photo-upload-btn {
  align-self: flex-start;
  font-size: .8rem;
  padding: .3rem .75rem;
  height: auto;
}

/* ── Grupo plegable de inspecciones en la tarjeta de vida ──────────────────── */
.tl-group .tl-grp-head {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  width: 100%; background: var(--surface-sunken); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md); padding: .4rem .625rem; cursor: pointer;
  font-family: inherit; text-align: left; color: var(--text-body);
}
.tl-group .tl-grp-head:hover { border-color: var(--border-normal); }
.tl-grp-caret { font-size: .7rem; color: var(--text-muted); }
.tl-grp-title { font-size: .8125rem; font-weight: 700; color: var(--text-strong); }
.tl-grp-range { font-size: .7rem; color: var(--text-muted); }
.tl-grp-metric {
  font-size: .7rem; font-family: var(--font-mono);
  background: var(--info-bg); color: var(--blue-600); padding: .1rem .35rem; border-radius: .25rem;
}
.tl-grp-dmg {
  font-size: .7rem; background: var(--warning-bg); color: #92400e;
  padding: .1rem .35rem; border-radius: .25rem;
}
.tl-grp-body { margin-top: .5rem; padding-left: .5rem; border-left: 2px dashed var(--border-subtle); }

/* ── Paneles del dashboard ─────────────────────────────────────────────────── */
/* Ranking con barra horizontal — para pocos elementos se lee mejor que un gráfico
   y no consume memoria de canvas. */
.bar-list { display: flex; flex-direction: column; gap: .5rem; }
.bar-row { display: grid; grid-template-columns: minmax(0,1fr) 2.2fr auto; gap: .625rem; align-items: center; }
.bar-label {
  font-size: .75rem; color: var(--text-body);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bar-track { height: 10px; background: var(--surface-sunken); border-radius: 999px; overflow: hidden; }
.bar-fill { height: 100%; border-radius: 999px; transition: width .3s; }
.bar-value { font-size: .75rem; font-family: var(--font-mono); color: var(--text-strong); white-space: nowrap; }

/* ── Centro de filtros del dashboard ───────────────────────────────────────────
   Barra única arriba de la vista: filtra todas las tarjetas y gráficos a la vez. */
.dash-filters {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  padding: .625rem .875rem; margin-bottom: 1rem;
  background: var(--surface-card); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md); position: sticky; top: 0; z-index: 20;
}
.dash-filters-title {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); margin-right: .25rem;
}
.dash-filters-summary { font-size: .72rem; color: var(--blue-500); font-weight: 600; margin-left: auto; }

/* Lista de neumáticos críticos */
.crit-list { display: flex; flex-direction: column; }
.crit-pct {
  font-size: .625rem; font-weight: 700; padding: .05rem .3rem; border-radius: .25rem;
  white-space: nowrap; margin-left: .35rem;
}
.crit-row {
  display: flex; align-items: center; gap: .75rem; padding: .45rem .25rem;
  border-bottom: 1px solid var(--border-subtle); cursor: pointer; border-radius: var(--radius-sm);
}
.crit-row:last-child { border-bottom: none; }
.crit-row:hover { background: var(--surface-sunken); }
.crit-rem {
  font-family: var(--font-mono); font-size: 1.05rem; font-weight: 800;
  min-width: 68px; text-align: right;
}
.crit-rem span { font-size: .625rem; font-weight: 600; margin-left: .1rem; opacity: .75; }
.crit-main { flex: 1; min-width: 0; }
.crit-num { font-family: var(--font-mono); font-size: .8125rem; font-weight: 700; color: var(--text-strong); }
.crit-meta { font-size: .7rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crit-hours { font-family: var(--font-mono); font-size: .75rem; color: var(--text-muted); white-space: nowrap; }

/* Distribución por grado de daño */
.grade-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem; }
.grade-box {
  border: 1.5px solid; border-radius: var(--radius-md); padding: .5rem;
  text-align: center; background: var(--surface-sunken);
}
.grade-val { font-size: 1.4rem; font-weight: 800; line-height: 1.1; }
.grade-lbl { font-size: .68rem; color: var(--text-muted); margin-top: .1rem; }

/* ── KPIs del tablero de inspecciones ──────────────────────────────────────── */
.insp-kpi-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: .5rem; margin-bottom: .5rem;
}
.insp-kpi {
  background: var(--surface-sunken); border-radius: var(--radius-md);
  padding: .5rem .75rem; text-align: center;
}
.insp-kpi-val { font-size: 1.25rem; font-weight: 800; color: var(--text-strong); line-height: 1.2; }
.insp-kpi-lbl { font-size: .7rem; color: var(--text-muted); margin-top: .1rem; }
.insp-cover-bar { height: 8px; border-radius: 999px; background: var(--surface-sunken); overflow: hidden; }
.insp-cover-fill { height: 100%; background: var(--success); border-radius: 999px; transition: width .3s; }

/* Fila de inspección dentro del modal del tablero: lleva al detalle al pulsarla */
.insp-detail-row {
  border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
  padding: .625rem .75rem; cursor: pointer; transition: border-color .15s, background .15s;
}
.insp-detail-row:hover { border-color: var(--blue-500); background: var(--surface-sunken); }

/* ── Paginación de tablas ──────────────────────────────────────────────────── */
.data-table tfoot.tbl-pager td {
  padding: .5rem 1rem; border-top: 1px solid var(--border-subtle); border-bottom: none;
  background: var(--surface-sunken);
}
.pager { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; justify-content: flex-end; }
.pager-info { font-size: .75rem; color: var(--text-muted); margin-right: auto; }
.pager-controls { display: flex; align-items: center; gap: .2rem; }
.pager-controls button {
  border: 1px solid var(--border-subtle); background: var(--surface-card);
  color: var(--text-body); cursor: pointer; border-radius: var(--radius-sm);
  min-width: 26px; height: 26px; font-size: .8rem; line-height: 1;
}
.pager-controls button:hover:not(:disabled) { border-color: var(--blue-500); color: var(--blue-500); }
.pager-controls button:disabled { opacity: .35; cursor: default; }
.pager-page { font-size: .75rem; color: var(--text-body); padding: 0 .5rem; font-family: var(--font-mono); }
.pager-size {
  font-size: .72rem; padding: .2rem .4rem; border-radius: var(--radius-sm);
  border: 1px solid var(--border-subtle); background: var(--surface-card); color: var(--text-body);
}
@media (max-width: 639px) { .pager-info { margin-right: 0; width: 100%; } }

/* ── Encabezado con orden + filtro por columna (tipo Excel) ────────────────── */
.th-sortable { white-space: nowrap; user-select: none; }
.th-inner { display: flex; align-items: center; gap: .25rem; }
.th-label { cursor: pointer; display: inline-flex; align-items: center; gap: .25rem; }
.th-label:hover { color: var(--blue-500); }
.th-arrow { opacity: .45; font-size: .65rem; }
.th-filter-btn {
  border: none; background: none; cursor: pointer; padding: 0 .15rem;
  color: var(--text-muted); font-size: .7rem; line-height: 1; border-radius: 3px;
}
.th-filter-btn:hover { background: var(--border-subtle); color: var(--text-strong); }
.th-filter-btn.is-active { color: var(--blue-500); background: var(--info-bg); font-weight: 700; }

.col-filter-panel {
  position: absolute; z-index: 3000; width: 250px;
  background: var(--surface-card); border: 1px solid var(--border-normal);
  border-radius: var(--radius-md); box-shadow: var(--shadow-modal);
  font-size: .8125rem; overflow: hidden;
}
.col-filter-head { padding: .5rem; border-bottom: 1px solid var(--border-subtle); }
.col-filter-search { font-size: .75rem; padding: .3rem .5rem; }
.col-filter-actions {
  display: flex; gap: .5rem; padding: .35rem .625rem;
  border-bottom: 1px solid var(--border-subtle);
}
.col-filter-actions button {
  background: none; border: none; cursor: pointer; padding: 0;
  color: var(--blue-500); font-size: .7rem; font-weight: 600; font-family: inherit;
}
.col-filter-actions button:hover { text-decoration: underline; }
.col-filter-list { max-height: 230px; overflow-y: auto; padding: .25rem 0; }
.col-filter-opt {
  display: flex; align-items: center; gap: .45rem;
  padding: .25rem .625rem; cursor: pointer; font-size: .75rem;
}
.col-filter-opt:hover { background: var(--surface-sunken); }
.col-filter-opt-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.col-filter-opt-n { color: var(--text-muted); font-size: .65rem; font-family: var(--font-mono); }
.col-filter-empty { padding: .75rem; color: var(--text-muted); font-size: .75rem; text-align: center; }
.col-filter-foot {
  display: flex; gap: .5rem; justify-content: space-between;
  padding: .5rem; border-top: 1px solid var(--border-subtle);
}

/* ── Stock por nivel de uso (dashboard) ────────────────────────────────────── */
.stock-usage-bar {
  display: flex; height: 14px; border-radius: 999px; overflow: hidden;
  background: var(--surface-sunken);
}
.stock-usage-seg { height: 100%; transition: width .3s; }
.stock-usage-seg:first-child { border-radius: 999px 0 0 999px; }
.stock-usage-seg:last-child  { border-radius: 0 999px 999px 0; }

/* ── Daños plegables en inspección ─────────────────────────────────────────── */
/* "desde" y la ubicación van en su propia línea (dmg-summary-meta), no compitiendo por
   ancho con el nombre en la misma fila — en una tarjeta de 240px eso dejaba al nombre
   con tan poco espacio que el texto se cortaba letra por letra. */
.dmg-summary {
  display: flex; flex-direction: column; gap: .15rem; width: 100%;
  background: none; border: none; cursor: pointer;
  padding: .3rem .1rem; text-align: left; font-family: inherit;
  color: var(--text-strong);
}
.dmg-summary-main { display: flex; align-items: flex-start; gap: .4rem; width: 100%; }
.dmg-summary-caret {
  font-size: .7rem; color: var(--text-muted); flex-shrink: 0; margin-top: .1rem;
  transition: transform .15s; transform: rotate(90deg);
}
.dmg-row.is-collapsed .dmg-summary-caret { transform: rotate(0deg); }
.dmg-row.is-collapsed .dmg-body { display: none; }
/* El nombre del daño se muestra COMPLETO (varias líneas si hace falta): el inspector en
   terreno necesita leerlo entero, antes se cortaba con puntos suspensivos. */
.dmg-summary-name {
  font-size: .75rem; font-weight: 600; flex: 1; min-width: 0;
  white-space: normal; overflow-wrap: anywhere; line-height: 1.35;
}
.dmg-summary-meta { font-size: .65rem; color: var(--text-muted); padding-left: 1.1rem; }
.dmg-summary .dmg-grade-pill { margin-top: .1rem; }
.dmg-grade-pill {
  font-size: .625rem; font-weight: 700; padding: .1rem .3rem;
  border-radius: .25rem; flex-shrink: 0; line-height: 1.3;
}
/* Severidad: G1 = grave (rojo), G2 = medio (naranjo), G3 = leve (amarillo) */
.dmg-grade-G1 { background: var(--grade-1-bg); color: var(--grade-1-fg); }
.dmg-grade-G2 { background: var(--grade-2-bg); color: var(--grade-2-fg); }
.dmg-grade-G3 { background: var(--grade-3-bg); color: var(--grade-3-fg); }

/* ── Reinicio de daños al retornar de planta ───────────────────────────────── */
.reset-dmg-master {
  display: flex; gap: .5rem; align-items: flex-start;
  font-size: .8125rem; padding: .5rem .625rem; cursor: pointer;
  background: var(--surface-sunken); border-radius: var(--radius-md);
}
.reset-dmg-master input { margin-top: .15rem; flex-shrink: 0; }
.reset-dmg-list { margin-top: .375rem; display: flex; flex-direction: column; gap: .125rem; }
.reset-dmg-item {
  display: flex; align-items: center; gap: .4rem;
  font-size: .75rem; padding: .3rem .625rem; cursor: pointer; border-radius: .3rem;
}
.reset-dmg-item:hover { background: var(--surface-sunken); }
.reset-dmg-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.reset-dmg-date { font-size: .65rem; color: var(--text-muted); flex-shrink: 0; }

/* ── Importación masiva ────────────────────────────────────────────────────── */
.import-steps { display: flex; gap: .5rem; margin-bottom: 1.25rem; flex-wrap: wrap; }
.import-step {
  display: flex; align-items: center; gap: .5rem;
  padding: .5rem .875rem; border-radius: var(--radius-md);
  background: var(--surface-sunken); color: var(--text-muted);
  font-size: .813rem; font-weight: 600;
}
.import-step span {
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--border-normal); color: var(--surface-card);
  display: flex; align-items: center; justify-content: center; font-size: .7rem;
}
.import-step.is-active { background: var(--info-bg); color: var(--blue-600); }
.import-step.is-active span { background: var(--blue-500); color: #fff; }
.import-step.is-done { background: var(--success-bg); color: var(--success); }
.import-step.is-done span { background: var(--success); color: #fff; }
.import-dropzone {
  border: 2px dashed var(--border-normal); border-radius: var(--radius-lg);
  padding: 2rem 1rem; text-align: center; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.import-dropzone:hover, .import-dropzone.is-drag { border-color: var(--blue-500); background: var(--info-bg); }
.import-file-row {
  display: flex; align-items: center; gap: .625rem;
  padding: .5rem .75rem; border-bottom: 1px solid var(--border-subtle); font-size: .813rem;
}
.import-file-row:last-child { border-bottom: none; }
.import-progress-track { height: 10px; border-radius: 999px; background: var(--surface-sunken); overflow: hidden; }
.import-progress-bar { height: 100%; width: 0%; background: var(--blue-500); border-radius: 999px; transition: width .25s; }
.import-log {
  margin-top: .875rem; max-height: 260px; overflow-y: auto;
  font-family: var(--font-mono); font-size: .7rem; line-height: 1.6;
  background: var(--surface-sunken); border-radius: var(--radius-md); padding: .625rem .75rem;
  color: var(--text-muted);
}
.import-map-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .625rem 1rem; align-items: center; }
.import-section-title {
  font-size: .875rem; font-weight: 700; color: var(--text-strong);
  margin: 1.25rem 0 .625rem; padding-bottom: .375rem; border-bottom: 1px solid var(--border-subtle);
}
.import-section-title:first-child { margin-top: 0; }
.import-chip {
  display: inline-block; padding: .2rem .5rem; margin: .15rem;
  background: var(--surface-sunken); border-radius: .3rem;
  font-size: .7rem; font-family: var(--font-mono); color: var(--text-body);
}
.import-stat-row {
  display: flex; justify-content: space-between; padding: .4rem 0;
  border-bottom: 1px solid var(--border-subtle); font-size: .875rem;
}
.import-stat-row:last-child { border-bottom: none; }
@media (max-width: 767px) { .import-map-grid { grid-template-columns: 1fr; } }

/* Teléfono en horizontal: pantalla ancha pero muy baja. */
@media (hover: none) and (pointer: coarse) and (max-height: 559px) and (orientation: landscape) {
  .main-content { padding-bottom: 64px; }
}


/* ── Gráfico no disponible ──────────────────────────────────────────────────
   Mensaje que reemplaza al <canvas> cuando Chart.js no cargó o no hay datos.
   Lo inserta chartUnavailable() en js/app.js. */
.chart-fallback {
  display: flex; align-items: center; justify-content: center;
  width: 100%; min-height: 160px; padding: 1.5rem 1rem;
  text-align: center; text-wrap: balance;
  font-size: .875rem; line-height: 1.45; color: var(--text-muted);
}


/* ── Leyenda de gráfico fuera del canvas ────────────────────────────────────
   La leyenda nativa de Chart.js se dibuja DENTRO del canvas: con el modo zoom
   (scroll horizontal) quedaba al medio del área desplazable y había que centrar
   el gráfico para alcanzarla, perdiendo la referencia. Esta versión vive en el
   DOM, fuera del contenedor con overflow, y sigue funcionando como filtro
   (click = mostrar/ocultar esa serie). La pinta _renderChartLegendOutside(). */
.chart-legend-out {
  display: flex; flex-wrap: wrap; gap: .35rem .75rem;
  margin: 0 0 .4rem; padding: 0;
}
.chart-legend-out .cl-item {
  display: inline-flex; align-items: center; gap: .35rem;
  background: none; border: 0; padding: .15rem .1rem; margin: 0;
  font-family: inherit; font-size: .72rem; font-weight: 600;
  color: var(--text-strong); cursor: pointer; line-height: 1.2;
}
.chart-legend-out .cl-swatch {
  width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0;
}
.chart-legend-out .cl-item.is-off { color: var(--text-muted); text-decoration: line-through; }
.chart-legend-out .cl-item.is-off .cl-swatch { opacity: .3; }

/* Marcador de reparación/recauche sobre la curva de remanente (tarjeta de vida):
   tooltip propio, porque los marcadores los dibuja un plugin y no son puntos de
   ningún dataset (ver _tireLifeEventMarks en js/app.js). */
.chart-mark-tip {
  position: absolute; z-index: 5; pointer-events: none;
  display: none; max-width: 230px;
  padding: .45rem .6rem; border-radius: var(--radius-md);
  background: var(--surface-inverse, #1f2937); color: #fff;
  font-size: .7rem; line-height: 1.35;
  box-shadow: var(--shadow-md, 0 4px 12px rgba(0,0,0,.25));
}
.chart-mark-tip strong { font-size: .72rem; }


/* ═══════════════════════════════════════════════════════════════════════════
   ORIGEN DE LA FOTO — hoja de acción estilo iOS · 2026-08-14

   Pregunta "cámara o galería" antes de abrir el selector de archivos. La monta
   y la destruye initPhotoSourcePicker() en js/app.js, así que —al revés que los
   ~40 .modal-backdrop del index.html— este elemento SOLO existe mientras está
   abierto: por eso aquí sí se puede usar backdrop-filter sin multiplicar capas
   de composición (ver la regla de oro del bloque de teléfono, más abajo).
   ═══════════════════════════════════════════════════════════════════════════ */
.photo-src-backdrop {
  --ps-fill:  rgba(252,252,254,.86);
  --ps-sep:   rgba(60,60,67,.20);
  --ps-tint:  var(--blue-500);
  --ps-press: rgba(120,120,128,.18);
  --ps-sub:   var(--text-muted);

  position: fixed;
  inset: 0;
  z-index: 900;                       /* los modales viven en 400 */
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(8,13,22,.42);
  opacity: 0;
  transition: opacity .3s cubic-bezier(.32,.72,0,1);
  -webkit-tap-highlight-color: transparent;
}
.photo-src-backdrop.is-open { opacity: 1; }

[data-theme="dark"] .photo-src-backdrop {
  --ps-fill:  rgba(42,49,64,.88);
  --ps-sep:   rgba(255,255,255,.13);
  --ps-tint:  #64a9ee;
  --ps-press: rgba(255,255,255,.10);
  background: rgba(0,0,0,.55);
}

.photo-src-sheet {
  width: 100%;
  max-width: 460px;
  display: flex;
  flex-direction: column;
  gap: .5rem;
  padding: 0 .5rem calc(.5rem + env(safe-area-inset-bottom, 0px));
  font-family: var(--font-ui);
  /* La curva es la de iOS: sale rápido y frena largo. */
  transform: translateY(112%);
  transition: transform .36s cubic-bezier(.32,.72,0,1);
  outline: none;
}
.photo-src-backdrop.is-open .photo-src-sheet { transform: translateY(0); }

.photo-src-group {
  border-radius: 14px;
  overflow: hidden;
  background: var(--ps-fill);
  -webkit-backdrop-filter: saturate(180%) blur(22px);
  backdrop-filter: saturate(180%) blur(22px);
  box-shadow: 0 8px 30px rgba(8,13,22,.16);
}

.photo-src-head {
  padding: .8rem 1rem .7rem;
  text-align: center;
  box-shadow: inset 0 -.5px 0 var(--ps-sep);   /* hairline de medio píxel */
}
.photo-src-head strong {
  display: block;
  font-size: .82rem;
  font-weight: 700;
  color: var(--text-strong);
}
.photo-src-head span {
  display: block;
  margin-top: .15rem;
  font-size: .74rem;
  line-height: 1.3;
  color: var(--ps-sub);
}

.photo-src-btn {
  width: 100%;
  min-height: 56px;
  padding: .5rem 1rem;
  border: 0;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  font-family: inherit;
  font-size: 1.0625rem;      /* 17px, el cuerpo de los menús de iOS */
  font-weight: 500;
  line-height: 1.2;
  color: var(--ps-tint);
  cursor: pointer;
  transition: background 120ms linear;
}
.photo-src-btn + .photo-src-btn { box-shadow: inset 0 .5px 0 var(--ps-sep); }
.photo-src-btn:active { background: var(--ps-press); }
.photo-src-btn svg { width: 21px; height: 21px; flex: 0 0 auto; }
.photo-src-cancel { font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
  .photo-src-backdrop,
  .photo-src-sheet { transition-duration: 1ms; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   LENGUAJE iOS — controles de sistema · 2026-08-14
   Extiende a toda la app el lenguaje del action sheet .photo-src-* (arriba):
   segmented control, switch, listas agrupadas, banner, sheet. Solo táctil —
   el escritorio hereda paleta/tipografía (tokens.css) pero conserva su layout.
   Va aquí, antes de CHASIS MÓVIL, por el mismo motivo que .photo-src-*: todo
   lo nuevo tiene que quedar antes de ese bloque para no perderse en la cascada.
   No es un archivo aparte (css/ios.css): el service worker ya es red-primero
   para CSS, así que separarlo solo sumaría una petición sin ganar cacheo. */
@media (hover: none) and (pointer: coarse) {

  /* ── Segmented control ── reemplaza el subrayado tipo Material de .tabs,
     .insp-tabs y .config-subtabs por una pista con relleno, sin tocar markup
     (las tres ya son una fila de botones). */
  .tabs, .insp-tabs, .config-subtabs {
    border-bottom: 0;
    background: var(--fill-3);
    border-radius: var(--radius-ios-md);
    padding: .1875rem;
    gap: 0;
    margin-bottom: 1rem;
  }
  .tab-btn, .insp-tab-btn, .config-subtab-btn {
    flex: 1 1 0;
    justify-content: center;
    border-bottom: 0 !important;
    border-radius: var(--radius-ios-sm);
    margin-bottom: 0;
    min-height: 34px;
    transition: background var(--transition-ios), color var(--transition-ios);
  }
  .tab-btn.active, .insp-tab-btn.active, .config-subtab-btn.active {
    background: var(--surface-card);
    color: var(--text-strong);
    box-shadow: 0 1px 3px rgba(12,23,38,.16);
  }

  /* ── Switch de sistema ── mismo markup (input+span), solo color y proporción. */
  .toggle-switch { width: 51px; height: 31px; }
  .toggle-slider { background: var(--fill-1) !important; }
  .toggle-slider::before {
    width: 27px; height: 27px; left: 2px; top: 2px;
    box-shadow: 0 1px 4px rgba(0,0,0,.25);
  }
  .toggle-switch input:checked + .toggle-slider { background: #34c759 !important; } /* verde de sistema */
  .toggle-switch input:checked + .toggle-slider::before { transform: translateX(20px); }

  /* ── Tarjetas ── radio y sombra más suaves; el hover de mouse no aplica en dedo. */
  .card, .stat-card { border-radius: var(--radius-ios-lg); box-shadow: 0 1px 3px rgba(12,23,38,.08); }
  .stat-card:hover { transform: none; }

  /* ── Botones ── ya son pill; feedback de opacidad además del scale de la sección 2. */
  .btn:active { opacity: .6; }

  /* ── Listas agrupadas (formularios) ── cada .form-group pasa a ser una fila
     suelta con radio y fondo propio en vez de una etiqueta+input a secas. No
     se fusionan en un solo grupo con hairlines internas (eso exigiría envolver
     cada modal a mano en index.html); esta es la variante segura que no toca
     markup y cubre los ~39 modales de una sola vez. */
  .form-group {
    background: var(--surface-sunken);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-ios-md);
    padding: .75rem .875rem;
  }
  .form-label { font-size: .8125rem; }

  /* ── Empty state ── un poco menos "web", más espaciado de app. */
  .empty-state { padding: 3.5rem 1.25rem; }
  .empty-state-icon { opacity: .3; }

  /* ── Toasts ── banner superior con blur, como una notificación del sistema,
     en vez de la esquina inferior derecha (patrón de escritorio). */
  .toast-container {
    top: calc(env(safe-area-inset-top, 0px) + .5rem);
    bottom: auto; left: .625rem; right: .625rem;
    align-items: stretch;
  }
  .toast {
    max-width: none;
    -webkit-backdrop-filter: var(--blur-chrome);
    backdrop-filter: var(--blur-chrome);
    animation: slideDownIos .3s var(--ease-ios);
  }
  @keyframes slideDownIos { from { opacity:0; transform:translateY(-12px); } to { opacity:1; transform:none; } }

  /* ── Panel de alertas → hoja inferior ── no hay .modal-backdrop propio que
     envolverlo (no es uno de los 40 modales), así que se fija al piso de la
     pantalla en vez de flotar bajo la campana. El blur cuelga de .show, misma
     regla que los modales: una sola instancia, no cuesta caro. */
  .alerts-panel {
    position: fixed;
    top: auto; right: 0; left: 0; bottom: 0;
    width: auto; max-height: 70dvh;
    border-radius: var(--radius-ios-lg) var(--radius-ios-lg) 0 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    transform: translateY(100%);
    transition: transform var(--transition-ios);
  }
  .alerts-panel:not(.hidden) {
    transform: none;
    -webkit-backdrop-filter: var(--blur-chrome);
    backdrop-filter: var(--blur-chrome);
    background: var(--surface-chrome);
  }
  .alerts-panel-header { border-radius: var(--radius-ios-lg) var(--radius-ios-lg) 0 0; }

  /* ── Drawer (Fase 5) ── mismo open/show que ya usa app.js: solo cambia la
     capa visual, filas agrupadas con radio en vez del bloque plano de siempre. */
  .sidebar.open {
    -webkit-backdrop-filter: var(--blur-chrome);
    backdrop-filter: var(--blur-chrome);
  }
  .nav-section-label {
    padding: 1rem 1.25rem .375rem;
    letter-spacing: .07em;
  }
  .nav-item {
    margin: .1rem .75rem;
    padding-left: .875rem; padding-right: .875rem;
    min-height: var(--row-h);
    border-radius: var(--radius-ios-md);
  }
  .nav-item:active { background: rgba(255,255,255,.10); }
  .nav-item.active { background: rgba(255,255,255,.14); }
}


/* ═══════════════════════════════════════════════════════════════════════════
   CHASIS MÓVIL — Fase 1 · 2026-07-25
   Ver docs/mobile-ui-guidelines.md

   Este bloque va SIEMPRE AL FINAL del archivo: corrige por orden de cascada en
   vez de reescribir las ~2900 líneas de arriba. Si agregas CSS nuevo, ponlo
   ANTES de esta línea (o de la sección "LENGUAJE iOS" de arriba) o dejará de
   aplicar.

   Condiciones usadas (idénticas a las de los bloques responsive de arriba):
     TÁCTIL   → (hover: none) and (pointer: coarse)
     TELÉFONO → (max-width: 639px) o táctil de poca altura (móvil horizontal)
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. Anti-desborde horizontal (todas las pantallas) ──────────────────────
   Un hijo de grid/flex tiene min-width:auto, así que una tabla ancha infla su
   contenedor y con él la página entera. min-width:0 es lo que obliga a respetar
   el ancho de la pantalla; sin esto, el scroll horizontal reaparece solo. */
html { overflow-x: hidden; }
.view, .card, .card-body, .table-wrap, .main-content, .dash-row > * { min-width: 0; }
.table-wrap { max-width: 100%; }

/* ── 2. Chasis táctil ─────────────────────────────────────────────────────── */
@media (hover: none) and (pointer: coarse) {

  /* Zonas seguras: con viewport-fit=cover el contenido pasa POR DEBAJO del
     notch y de la barra de gestos. En pantallas sin notch env() vale 0. */
  .topbar {
    height: calc(var(--topbar-height) + env(safe-area-inset-top, 0px));
    padding-top: env(safe-area-inset-top, 0px);
    padding-left:  max(.5rem, env(safe-area-inset-left, 0px));
    padding-right: max(.5rem, env(safe-area-inset-right, 0px));
  }
  .sidebar {
    top: calc(var(--topbar-height) + env(safe-area-inset-top, 0px));
    height: calc(100dvh - var(--topbar-height) - env(safe-area-inset-top, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .main-content { margin-top: calc(var(--topbar-height) + env(safe-area-inset-top, 0px)); }

  /* Blancos de toque de 44px (mínimo de Apple HIG / 48 de Material).
     Los íconos siguen viéndose iguales: crece el área, no el dibujo. */
  .btn { min-height: 44px; }
  .btn-sm { min-height: 38px; }
  .btn-icon, .btn-hamburger, #btn-theme, .alert-bell { min-width: 44px; min-height: 44px; }
  .nav-item { min-height: 46px; }

  /* Sin zoom automático al enfocar: iOS hace zoom en cualquier control <16px. */
  .form-control, input, select, textarea { font-size: 16px; }
  .col-filter { font-size: 16px; }

  /* Feedback táctil: el :hover se queda "pegado" tras el tap en pantallas
     táctiles, así que se neutraliza y se reemplaza por :active. */
  * { -webkit-tap-highlight-color: transparent; }
  .data-table tr:hover td { background: transparent; }
  .data-table tbody tr:active td { background: var(--surface-sunken); }
  .stat-card:hover { transform: none; box-shadow: var(--shadow-card); border-color: var(--border-subtle); }
  .stat-card:active { transform: scale(.985); }
  .btn:active { transform: scale(.97); }

  /* El scroll dentro de paneles no arrastra la página completa. */
  .modal, .sidebar, .table-wrap { overscroll-behavior: contain; }
}

/* ── 3. Teléfono ──────────────────────────────────────────────────────────── */
@media (max-width: 639px), (hover: none) and (pointer: coarse) and (max-height: 559px) {

  /* 3.1 Barra superior ────────────────────────────────────────────────────
     Antes cabían 7 elementos en 60px y el selector de faena quedaba fuera de
     pantalla. Ahora: ☰ · faena · sync · alertas · tema.
     Se reordena por CSS (order), NO por DOM: app.js sigue encontrando los
     mismos id en el mismo sitio. */
  .topbar { gap: .3rem; }
  .topbar-logo   { display: none; }   /* los logos viven en el drawer */
  .topbar-title  { display: none; }   /* cada vista ya tiene su propio <h2> */
  .btn-hamburger { order: -1; display: flex; }
  .topbar-faena  { order: 0; flex: 1 1 auto; min-width: 0; }
  .topbar-faena select {
    width: 100%; max-width: 100%;
    font-size: 16px; font-weight: 700;
    padding: .45rem .4rem;
    text-overflow: ellipsis;
  }
  .sync-status   { order: 1; flex-shrink: 0; padding: 0; }
  .topbar-alerts { order: 2; flex-shrink: 0; }
  #btn-theme     { order: 3; flex-shrink: 0; }

  /* 3.2 Fin del contenido ──────────────────────────────────────────────────
     La barra inferior de navegación se retiró (2026-08-14): la navegación es
     solo el drawer lateral. Ya no hay que reservar sus 56px, únicamente el
     respiro final y la zona de gestos del sistema. */
  .main-content { padding-bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px)); }

  /* 3.3 Dashboard ──────────────────────────────────────────────────────────
     app.js escribe `grid-template-columns:repeat(5,1fr)` como estilo INLINE
     (js/app.js ~9516 y ~9560) y un estilo inline le gana a cualquier media
     query. !important es aquí la única herramienta que funciona sin tocar el JS. */
  .dash-grid { grid-template-columns: 1fr 1fr !important; gap: .625rem; margin-bottom: 1rem !important; }
  .dash-row  { grid-template-columns: 1fr !important; }
  .stat-card { padding: .875rem .75rem; }
  .stat-card-icon  { width: 30px; height: 30px; margin-bottom: .5rem; }
  .stat-card-value { font-size: 1.5rem; }
  .stat-card-label { font-size: .75rem; line-height: 1.25; }

  /* Los filtros ocupaban ~200px antes del primer dato. Compactos y sin sticky
     (en un teléfono el sticky se come la pantalla útil). */
  .dash-filters { position: static; padding: .5rem; gap: .4rem; }
  .dash-filters-title { display: none; }
  .dash-filters .form-control { width: 100% !important; min-width: 0 !important; }

  /* 3.4 Tablas → tarjetas ──────────────────────────────────────────────────
     Una tabla de 8 columnas no se lee en un teléfono: se scrollea de lado y se
     pierde la referencia. Cada fila pasa a ser una tarjeta con etiqueta a la
     izquierda y valor a la derecha.
     El texto de la etiqueta lo pone el helper tagTableCells() de app.js, que
     copia el <th> correspondiente al atributo data-label de cada <td>. */
  .table-wrap { overflow-x: visible; background: transparent; border: 0; }
  .data-table { display: block; font-size: .875rem; }
  .data-table thead { display: none; }
  .data-table tbody, .data-table tbody tr, .data-table tbody td { display: block; width: 100%; }

  .data-table tbody tr {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: .75rem .875rem;
    margin-bottom: .625rem;
  }
  .data-table tbody td {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: .75rem;
    padding: .3rem 0;
    border: 0;
    text-align: right;
    white-space: normal;
  }
  .data-table tbody td::before {
    content: attr(data-label);
    flex: 0 0 auto; max-width: 45%;
    text-align: left;
    font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
    color: var(--text-muted);
  }
  .data-table tbody td:not([data-label])::before { content: none; }

  /* Primera celda = titular de la tarjeta (el identificador del activo). */
  .data-table tbody td:first-child {
    font-family: var(--font-display);
    font-size: 1.0625rem; font-weight: 800; color: var(--text-strong);
    padding-bottom: .5rem; margin-bottom: .35rem;
    border-bottom: 1px solid var(--border-subtle);
  }
  .data-table tbody td:first-child::before { content: none; }

  /* Acciones: al pie de la tarjeta, repartidas y con altura real de dedo. */
  .data-table tbody td.td-actions {
    width: auto; display: flex; gap: .5rem;
    margin-top: .5rem; padding-top: .625rem;
    border-top: 1px solid var(--border-subtle);
    text-align: center;
  }
  .data-table tbody td.td-actions::before { content: none; }
  .data-table tbody td.td-actions .btn {
    flex: 1 1 0; min-width: 0; min-height: 40px;
    margin-right: 0;
    font-size: .75rem; padding: .5rem .35rem;
  }

  /* Filas de "cargando" / "sin resultados": ocupan la tarjeta completa. */
  .data-table tbody td[colspan] {
    display: block; text-align: center;
    border-bottom: 0; margin-bottom: 0; padding: .75rem 0;
    font-family: var(--font-ui); font-size: .875rem; font-weight: 400; color: var(--text-muted);
  }
  .data-table tbody tr:has(td[colspan]) {
    background: transparent; border-style: dashed; box-shadow: none;
  }

  /* 3.5 Modales como hoja inferior (patrón bottom-sheet) ───────────────────
     El tirador no es decorativo: initSheetDrag() en app.js lo hace funcionar —
     se arrastra la cabecera hacia abajo y la hoja se cierra, igual que en iOS.

     REGLA DE ORO DE ESTE BLOQUE: los ~40 modales del index.html tienen su
     `.modal-backdrop` siempre presente en el DOM (cerrados quedan en opacity:0,
     no en display:none) y son `position: fixed`, o sea que ocupan coordenadas de
     pantalla aunque no se vean. Cualquier propiedad que cree capas de
     composición o regiones de gesto —`backdrop-filter`, `filter`, `will-change`,
     `touch-action`— va SIEMPRE colgada de `.is-open`, nunca del selector suelto.
     Puesta suelta se multiplica por 40 y rompe la app entera: primero dejó la
     pantalla en negro (blur) y después bloqueó el scroll de todas las vistas
     (touch-action). Las de layout y pintura sí pueden ir sueltas: dentro de un
     contenedor con opacity 0 no cuestan nada. */
  /* El fondo arranca DEBAJO de la barra superior: así la barra queda nítida y
     legible (Jairo la quiso fuera del difuminado) y la hoja puede subir hasta
     tocarla, que es el espacio que se gana. El desenfoque del resto es el toque
     de iOS — se degrada solo en navegadores sin backdrop-filter, donde queda el
     velo oscuro de siempre. */
  .modal-backdrop {
    align-items: flex-end;
    padding: 0;
    top: calc(var(--topbar-height) + env(safe-area-inset-top, 0px));
    background: rgba(12, 23, 38, .42);
  }
  /* El desenfoque va SOLO en la hoja abierta, nunca en `.modal-backdrop` a secas.
     El index.html tiene ~40 modales y todos sus fondos existen siempre en el DOM
     (quedan en opacity:0, no en display:none). Con el blur en la regla general
     eran 40 capas fijas a pantalla completa que el teléfono tenía que muestrear
     y desenfocar en cada frame: el compositor se caía y la app quedaba en negro
     (2026-08-14). En escritorio ni se notaba, porque este bloque es solo de
     teléfono. Abierta hay una sola a la vez, que es lo que cuesta barato. */
  .modal-backdrop.is-open {
    -webkit-backdrop-filter: blur(7px);
    backdrop-filter: blur(7px);
  }
  .modal {
    width: 100%; max-width: 100%;
    border-radius: 20px 20px 0 0;
    /* % del fondo, que ya excluye la barra superior: deja ver una franja de
       fondo difuminado arriba de la hoja. */
    max-height: 94%;
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  /* Durante el arrastre manda el dedo, no la transición: si no, la hoja
     persigue al dedo con retraso y se siente pegajosa. */
  .modal.is-sheet-dragging { transition: none; }

  /* NO PONER AQUÍ `overscroll-behavior-y: contain` sobre html/body.
     Se probó el 2026-08-14 para matar el "recargar página" de Chrome Android y
     dejó la app entera sin scroll en el teléfono. El motivo: `body` tiene
     `overflow-x: hidden` (línea ~10), y por especificación eso computa el otro
     eje como `auto` — o sea que body ES un contenedor de scroll, pero mide
     exactamente lo que su contenido, así que no puede desplazarse él mismo y el
     gesto tiene que ENCADENAR hacia el viewport. `contain` es precisamente lo
     que prohíbe ese encadenamiento: el gesto moría en el body y la página no se
     movía. Se notaba solo al tocar: el scroll por código y la rueda del mouse
     seguían funcionando, y con el menú lateral abierto también, porque su
     overlay es `position: fixed` y el gesto empieza en otra cadena de scroll.
     El pull-to-refresh ya está cubierto donde importa, sin efectos globales:
     `touch-action: none` en la cabecera de la hoja ABIERTA (más abajo) impide
     que el navegador inicie cualquier gesto de desplazamiento sobre ella. */

  /* "Handle" de arrastre. El área agarrable es toda la cabecera, así que se le
     agrega espacio arriba para que el tirador no se pise con el título. */
  .modal-header {
    position: relative;
    padding-top: 1.5rem;
    cursor: grab;
    -webkit-user-select: none; user-select: none;
  }

  /* touch-action SOLO dentro de la hoja abierta — misma trampa que el
     backdrop-filter (ver arriba). Puesto en `.modal-header` a secas eran 40
     franjas de 390x89px con `touch-action: none` flotando en coordenadas de
     pantalla (los fondos son `position: fixed`), y el navegador dejaba de
     desplazar la página justo sobre ellas: entrar a Inspección y no poder bajar
     (2026-08-14). `pointer-events: none` no basta para sacarlas de las regiones
     de touch-action que evalúa el compositor.
     Abierta la hoja, `none` en la cabecera es la otra mitad del arreglo del
     pull-to-refresh: con `pan-y` el navegador se quedaba con el gesto vertical
     y nunca llegaba a initSheetDrag(). Bloquea arrastres, no toques — el ✕ se
     sigue pudiendo tocar. */
  .modal-backdrop.is-open > .modal { touch-action: pan-y; }
  .modal-backdrop.is-open .modal-header { touch-action: none; }
  .modal-backdrop.is-open .modal-header .btn,
  .modal-backdrop.is-open .modal-header button { touch-action: manipulation; }
  .modal-header::before {
    content: ''; position: absolute; top: .55rem; left: 50%; transform: translateX(-50%);
    width: 40px; height: 5px; border-radius: var(--radius-pill);
    background: var(--border-normal);
    transition: background var(--transition), width var(--transition);
  }
  .modal.is-sheet-dragging .modal-header::before { background: var(--text-muted); width: 52px; }

  /* 3.6 Formularios y encabezados a una columna ────────────────────────────*/
  .form-grid, .mount-form-grid, .profile-grid, .profile-layout,
  .report-summary-grid, .eq-detail-grid, .import-map-grid { grid-template-columns: 1fr !important; }
  .page-header { flex-direction: column; align-items: stretch; gap: .75rem; }
  .page-header .btn { width: 100%; justify-content: center; }
  .filters-bar, .toolbar { flex-wrap: wrap; }

  /* 3.7 Inspección: una posición por pantalla ──────────────────────────────
     En el teléfono la tarjeta de 240px dejaba media tarjeta cortada al borde y
     no había forma de llegar a las posiciones de la derecha. Cada eje (y las
     listas de aros y cadenas) pasa a ser una pista con enganche: se desliza con
     el dedo y cada posición queda centrada. */
  /* Nada de `>` desde #insp-items-grid: _carouselInit() envuelve cada eje en un
     .carousel para colgarle la barra de control, así que la fila deja de ser
     hija directa de la grilla. */
  #insp-items-grid .insp-axle-row,
  .insp-grid {
    display: flex !important;
    flex-direction: row; flex-wrap: nowrap;
    gap: .625rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    padding-bottom: .25rem;
    scrollbar-width: none;
  }
  #insp-items-grid .insp-axle-row::-webkit-scrollbar,
  .insp-grid::-webkit-scrollbar { display: none; }

  #insp-items-grid .insp-axle-row > .insp-tire-card,
  .insp-grid > .insp-tire-card {
    flex: 0 0 min(86%, 320px) !important;
    width: auto !important;
    scroll-snap-align: center;
  }
  /* El "no hay nada que inspeccionar" no es una tarjeta: ocupa la pista entera. */
  #insp-items-grid .insp-axle-row > .empty-state,
  .insp-grid > .empty-state { flex: 1 1 100%; }

  /* 3.8 Cambio de neumáticos (paso 2) ──────────────────────────────────────
     Tres problemas en teléfono: la cabecera de acciones se salía de pantalla,
     la barra de toggles gastaba media pantalla en texto de ayuda, y el diagrama
     del equipo vivía en una caja de 420px con scroll propio — había que deslizar
     una barra interna para ver las posiciones y era imposible soltar ahí un
     componente. */

  /* Cabecera: título arriba, acciones abajo repartidas en toda la fila. */
  .mount-step2-header {
    flex-direction: column; align-items: stretch; gap: .625rem;
    padding: .75rem;
  }
  .mount-step2-header > div:last-child { width: 100%; }
  .mount-step2-header > div:last-child .btn { flex: 1 1 0; justify-content: center; min-width: 0; }

  /* Toggles: uno por línea, sin la columna de ayuda de la derecha (el mismo
     texto ya sale bajo el diagrama, en el aviso de modo). */
  .mount-mode-bar { flex-direction: column; align-items: stretch; gap: .625rem; padding: .625rem .75rem; }
  .mount-mode-bar > div:first-child { flex-direction: column; align-items: stretch; gap: .625rem; }
  #mount-mode-stock-hint { display: none; }

  /* El diagrama se muestra entero: sin alto fijo ni scroll interno. Si aun así
     el equipo es demasiado ancho, _fitMountDiagram() en app.js lo reduce con un
     scale para que quepa completo. */
  .equipment-diagram {
    flex: 0 0 auto !important;
    height: auto !important;
    max-height: none;
    min-height: 0;
    overflow: visible;
    padding: .75rem .5rem;
  }
  #wheel-diagram { transform-origin: top center; }
  .wheel-axle-slots { gap: .375rem; justify-content: center; }
  .wheel-slot { width: 64px; min-height: 100px; }

  /* Orden pedido: diagrama → neumáticos armados → desarmados/aros → cadenas e
     historial. "Armados" vive dentro de la columna derecha del layout de
     escritorio, así que se usa display:contents para que sus hijos suban a ser
     items directos de .mount-layout y se puedan reordenar con `order`. */
  .mount-layout { display: flex; flex-direction: column; gap: .75rem; }
  .mount-left, .mount-stock-right { display: contents; }
  #mount-equip-box    { order: 1; }
  #mount-armed-panel  { order: 2; flex: 0 0 auto !important; max-height: 42dvh; }
  .mount-left-bottom  { order: 3; display: flex; flex-direction: column; gap: .75rem; }
  .mount-right-lower  { order: 4; }
  .mount-left-bottom .stock-panel { max-height: 38dvh; }
  /* Las manijas de redimensionar son de escritorio: en táctil estorban. */
  .mount-resize-handle { display: none; }
}

/* ── 4. Tablet ────────────────────────────────────────────────────────────
   Hueco identificado el 2026-08-14: una tablet táctil en vertical (~768-834px
   de ancho, más de 559px de alto) no cumplía ni "(max-width:639px)" ni
   "max-height:559px" de la sección 3, así que se quedaba con tablas anchas y
   modales centrados de escritorio pese a ya tener targets de 44px (sección 2)
   y los controles de la sección "LENGUAJE iOS" de arriba (esos sí son
   táctil-ancho, sin tope). Este bloque es el complemento exacto de "teléfono"
   dentro del universo táctil: NO toca el selector de la sección 3 (afinado a
   propósito para excluir el teléfono en horizontal, ~915×412px — tocarlo
   arriesga un caso que costó encontrar) y en su lugar DUPLICA solo lo que hace
   falta. Las hojas inferiores no llevan tope de ancho (se ven bien en
   cualquier tablet); la tarjetización de tablas sí, para no tarjetizar una
   tabla que en una tablet grande apaisada ya cabe entera. */
@media (hover: none) and (pointer: coarse) and (min-width: 640px) and (min-height: 560px) {

  /* Modales como hoja inferior — mismas reglas que 3.5, sin tope de ancho. */
  .modal-backdrop {
    align-items: flex-end;
    padding: 0;
    top: calc(var(--topbar-height) + env(safe-area-inset-top, 0px));
    background: rgba(12, 23, 38, .42);
  }
  .modal-backdrop.is-open {
    -webkit-backdrop-filter: blur(7px);
    backdrop-filter: blur(7px);
  }
  .modal {
    width: 100%; max-width: 560px;
    border-radius: 20px 20px 0 0;
    max-height: 94%;
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .modal.is-sheet-dragging { transition: none; }
  .modal-header {
    position: relative;
    padding-top: 1.5rem;
    cursor: grab;
    -webkit-user-select: none; user-select: none;
  }
  .modal-backdrop.is-open > .modal { touch-action: pan-y; }
  .modal-backdrop.is-open .modal-header { touch-action: none; }
  .modal-backdrop.is-open .modal-header .btn,
  .modal-backdrop.is-open .modal-header button { touch-action: manipulation; }
  .modal-header::before {
    content: ''; position: absolute; top: .55rem; left: 50%; transform: translateX(-50%);
    width: 40px; height: 5px; border-radius: var(--radius-pill);
    background: var(--border-normal);
    transition: background var(--transition), width var(--transition);
  }
  .modal.is-sheet-dragging .modal-header::before { background: var(--text-muted); width: 52px; }
}

/* Tarjetización de tablas — mismas reglas que 3.4, con tope de ancho: una
   tablet grande en horizontal ya tiene espacio para la tabla real. */
@media (hover: none) and (pointer: coarse) and (min-width: 640px) and (min-height: 560px) and (max-width: 1023px) {
  .table-wrap { overflow-x: visible; background: transparent; border: 0; }
  .data-table { display: block; font-size: .875rem; }
  .data-table thead { display: none; }
  .data-table tbody, .data-table tbody tr, .data-table tbody td { display: block; width: 100%; }
  .data-table tbody tr {
    background: var(--surface-card);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: .75rem .875rem;
    margin-bottom: .625rem;
  }
  .data-table tbody td {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: .75rem;
    padding: .3rem 0;
    border: 0;
    text-align: right;
    white-space: normal;
  }
  .data-table tbody td::before {
    content: attr(data-label);
    flex: 0 0 auto; max-width: 45%;
    text-align: left;
    font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
    color: var(--text-muted);
  }
  .data-table tbody td:not([data-label])::before { content: none; }
  .data-table tbody td:first-child {
    font-family: var(--font-display);
    font-size: 1.0625rem; font-weight: 800; color: var(--text-strong);
    padding-bottom: .5rem; margin-bottom: .35rem;
    border-bottom: 1px solid var(--border-subtle);
  }
  .data-table tbody td:first-child::before { content: none; }
  .data-table tbody td.td-actions {
    width: auto; display: flex; gap: .5rem;
    margin-top: .5rem; padding-top: .625rem;
    border-top: 1px solid var(--border-subtle);
    text-align: center;
  }
  .data-table tbody td.td-actions::before { content: none; }
  .data-table tbody td.td-actions .btn {
    flex: 1 1 0; min-width: 0; min-height: 40px;
    margin-right: 0;
    font-size: .75rem; padding: .5rem .35rem;
  }
  .data-table tbody td[colspan] {
    display: block; text-align: center;
    border-bottom: 0; margin-bottom: 0; padding: .75rem 0;
    font-family: var(--font-ui); font-size: .875rem; font-weight: 400; color: var(--text-muted);
  }
  .data-table tbody tr:has(td[colspan]) {
    background: transparent; border-style: dashed; box-shadow: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   FIRMA DEL RESPONSABLE  (js/signature.js)
   ---------------------------------------------------------------------------
   Bloque "Responsable y firma" que cierra todos los formularios de registro.
   Va siempre al final del modal y visualmente separado, porque es el gesto de
   cierre: primero se completan los datos, después se firma.

   El alto del canvas está en px y no en % porque el contenedor del modal no
   tiene alto definido (crece con el contenido) y un % ahí colapsa a 0.
   ═══════════════════════════════════════════════════════════════════════════ */

.sig-block {
  margin-top: 1.25rem;
  padding: .875rem 1rem 1rem;
  border: 1px solid var(--border-base);
  border-radius: var(--radius-md);
  background: var(--surface-subtle);
}

.sig-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; margin-bottom: .75rem;
}
.sig-head-title {
  font-family: var(--font-display);
  font-size: .8125rem; font-weight: 800;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-strong);
}
.sig-head-note {
  font-size: .6875rem; font-weight: 700;
  letter-spacing: .03em; text-transform: uppercase;
  color: var(--danger);
  background: var(--danger-bg);
  padding: .15rem .45rem; border-radius: var(--radius-pill);
}

.sig-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
  gap: .75rem 1rem;
  align-items: end;
}
.sig-block .form-group { margin-bottom: 0; }

.sig-pad-group > .form-label {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
}

.sig-clear-btn {
  border: 1px solid var(--border-base);
  background: var(--surface);
  color: var(--text-muted);
  font: inherit; font-size: .6875rem; font-weight: 700;
  padding: .15rem .5rem;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: var(--transition);
}
.sig-clear-btn:active { transform: scale(.96); }

.sig-canvas-wrap {
  position: relative;
  height: 130px;
  background: var(--surface-card);
  border: 1px solid var(--border-base);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
/* Línea de firma: guía visual, igual que en un formulario de papel. */
.sig-canvas-wrap::after {
  content: '';
  position: absolute; left: 8%; right: 8%; bottom: 26px;
  border-bottom: 1px dashed var(--border-base);
  pointer-events: none;
}
.sig-canvas {
  position: relative; z-index: 1;
  display: block; width: 100%; height: 100%;
  /* Sin esto el dedo hace scroll del modal en vez de firmar. */
  touch-action: none;
  cursor: crosshair;
}
.sig-hint {
  position: absolute; left: 0; right: 0; bottom: 6px;
  text-align: center;
  font-size: .75rem; color: var(--text-muted);
  pointer-events: none;
  transition: opacity var(--transition);
}
.sig-canvas-wrap.sig-has-ink::after,
.sig-canvas-wrap.sig-has-ink .sig-hint { opacity: 0; }

.sig-canvas-wrap.sig-invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-bg);
}

@media (max-width: 640px) {
  .sig-grid { grid-template-columns: 1fr; }
  .sig-canvas-wrap { height: 150px; }
}
