/* ============================================================
   TaskPlan · Look Vectorizer
   Mobile-first, tap targets ≥44px, paleta azul-noche, accent cyan.
   ============================================================ */

/* El atributo nativo [hidden] (display:none de la hoja de estilos del navegador)
   tiene especificidad mínima, así que CUALQUIER regla de autor con `display:`
   (flex/grid/inline-flex…) lo anula y el elemento sigue visible aunque el JS
   haga `el.hidden = true`. Esto causaba menús/pills/líneas que aparecían
   desplegados o pegados por defecto. Esta regla global restaura el contrato de
   [hidden] para todos los toggles del proyecto. */
[hidden] { display: none !important; }

/* ─── Shell ──────────────────────────────────────────────────── */

.tp-app {
  display: grid;
  grid-template-columns: 260px 1fr;
  min-height: 100vh;
  min-height: 100dvh;
  position: relative;
  background: var(--bg-0);
}

.tp-sidebar {
  background: var(--bg-1);
  border-right: 1px solid var(--border);
  padding: var(--s-4);
  overflow-y: auto;
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
}

.tp-sidebar h1 {
  font-size: var(--fs-xl);
  margin: 0 0 var(--s-5);
  padding: 0 var(--s-2);
  color: var(--accent);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.tp-sidebar nav { display: flex; flex-direction: column; gap: 2px; }

.tp-sidebar nav a {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 12px 14px;
  min-height: var(--tap);
  border-radius: var(--r-md);
  color: var(--fg-1);
  font-size: var(--fs-md);
  font-weight: 500;
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}
.tp-sidebar nav a:hover {
  background: var(--bg-2);
  color: var(--fg-0);
  text-decoration: none;
}
.tp-sidebar nav a.active,
.tp-sidebar nav a[aria-current="page"] {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.tp-sidebar .section-title {
  font-size: var(--fs-xs);
  color: var(--fg-2);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: var(--s-5) 0 var(--s-2);
  padding: 0 14px;
  font-weight: 600;
}

#tp-logout-btn {
  margin-top: var(--s-3);
  color: var(--fg-2) !important;
}
#tp-logout-btn:hover { color: var(--red) !important; background: var(--red-soft) !important; }

.tp-sidebar-backdrop { display: none; }
.tp-hamburger { display: none; }
.tp-bottom-nav { display: none; }
.tp-sidebar-close { display: none; } /* solo visible en el overlay móvil */

.tp-main {
  /* Sin FAB ya no necesitamos espacio extra al final; el contenido llega al
     borde de la ventana. Cada vista puede añadir margen local si lo necesita.
     Mantenemos un pelín de aire (s-2) para que la última fila no quede pegada
     al chrome del navegador en mobile (gesture area, etc.). */
  padding: var(--s-5) var(--s-5) var(--s-2);
  overflow-y: auto;
  /* Red de seguridad: el contenedor principal NUNCA debe scrollear en
     horizontal. Cualquier vista que accidentalmente genere contenido más ancho
     que el viewport (tablas, grids, palabras largas) se recorta aquí en vez de
     desbordar la página en iOS/PWA. Los scrollers internos legítimos (calendario,
     wrappers de tabla) tienen su propio overflow-x:auto y siguen funcionando. */
  overflow-x: hidden;
  max-width: 100%;
}

/* ─── Topbar ─────────────────────────────────────────────────── */

.tp-topbar {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-bottom: var(--s-5);
  flex-wrap: wrap;
}
.tp-topbar h2 {
  font-size: var(--fs-2xl);
  margin: 0;
  flex: 1;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--fg-0);
  min-width: 0;
}
.tp-topbar .pill {
  font-size: var(--fs-xs);
  padding: 4px 10px;
  background: var(--bg-3);
  border-radius: var(--r-pill);
  color: var(--fg-1);
  font-weight: 500;
}
.tp-topbar .pill.offline {
  background: var(--red-soft);
  color: var(--red);
  border: 1px solid var(--red);
}

/* ─── Cards ──────────────────────────────────────────────────── */

.tp-card {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.tp-card > header {
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
  background: transparent;
}
.tp-card > header h3 {
  margin: 0;
  font-size: var(--fs-xs);
  color: var(--fg-2);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.tp-card-hint {
  margin: 6px 0 0;
  color: var(--fg-2);
  font-size: var(--fs-sm);
  line-height: 1.55;
}
.tp-card-body { padding: var(--s-5); }

/* Cuando el body lleva forms o filas, el primer/último gap se ve mejor sin doble padding */
.tp-card-body > .tp-form:only-child,
.tp-card-body > .tp-row:first-child { margin-top: 0; }

/* ─── Settings (contenedor de cards) ─────────────────────────── */

.tp-settings {
  max-width: 880px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding-bottom: var(--s-6);
}

/* ─── Formularios ────────────────────────────────────────────── */

.tp-form { display: flex; flex-direction: column; gap: var(--s-2); }

.tp-form-label {
  display: block;
  margin-top: var(--s-4);
  font-size: var(--fs-sm);
  color: var(--fg-1);
  font-weight: 500;
}
.tp-form-label:first-child { margin-top: 0; }

.tp-input {
  width: 100%;
  /* box-sizing: border-box es imprescindible aquí. Sin él (content-box por
     defecto, no hay reset global), width:100% + padding 28px + borde 2px suma
     ~30px MÁS que el contenedor y el input se sale por la derecha en iOS/PWA
     (visible sobre todo en los campos de fecha, cuyo valor va alineado). El
     overflow-x:hidden de .tp-main lo tapa en muchas vistas pero no en tarjetas
     y modales con su propio scroll. DECISION: se corrige localmente en .tp-input
     en vez de con un reset universal para no alterar el resto del layout maduro. */
  box-sizing: border-box;
  padding: 12px 14px;
  margin-top: 6px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-0);
  border-radius: var(--r-md);
  font-size: var(--fs-md);
  font-family: inherit;
  min-height: var(--tap);
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
  /* iOS Safari hace zoom automático al hacer focus en inputs con font-size
     menor a 16px. Forzamos 16px en mobile (≤768px) abajo para evitarlo. */
}
.tp-input::placeholder { color: var(--fg-3); }
.tp-input:hover { border-color: var(--border-strong); }
.tp-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
  background: var(--bg-2);
}
textarea.tp-input { min-height: 96px; resize: vertical; line-height: 1.5; }

select.tp-input {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%237585a0' stroke-width='2'%3e%3cpolyline points='6 9 12 15 18 9'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 38px;
}

input[type="checkbox"], input[type="radio"] {
  width: 18px; height: 18px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Tema oscuro para los inputs de date/time/datetime: hace que los iconos
   del picker nativo (calendario, reloj) sean blancos y que el texto
   placeholder/legible mantenga contraste. */
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"],
input[type="week"] {
  color-scheme: dark;
}
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  filter: invert(1) brightness(1.2);
  cursor: pointer;
  opacity: 0.8;
}
input[type="date"]::-webkit-calendar-picker-indicator:hover,
input[type="time"]::-webkit-calendar-picker-indicator:hover,
input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
}
/* Anti-desbordamiento de los inputs de fecha/hora en móvil (iOS/WebKit les da
   un ancho intrínseco que ignora width:100% y los saca por la derecha, visible
   en "Fecha límite" y "Empezar / diferir hasta"). appearance:none elimina ese
   ancho mínimo nativo; min-width:0 permite encoger; el picker sigue funcionando. */
input[type="date"].tp-input,
input[type="time"].tp-input,
input[type="datetime-local"].tp-input {
  -webkit-appearance: none;
  appearance: none;
  min-width: 0;
  max-width: 100%;
}
input[type="date"].tp-input::-webkit-date-and-time-value {
  text-align: left;
  margin: 0;
}

/* ─── Botones ─────────────────────────────────────────────────── */

.tp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: 10px 18px;
  min-height: var(--tap);
  background: var(--bg-3);
  color: var(--fg-0);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  cursor: pointer;
  font-size: var(--fs-md);
  font-weight: 600;
  text-decoration: none;
  font-family: inherit;
  line-height: 1;
  transition: background 0.15s, border-color 0.15s, transform 0.05s;
  white-space: nowrap;
}
.tp-btn:hover:not(:disabled) {
  background: var(--bg-2);
  border-color: var(--accent);
  text-decoration: none;
}
.tp-btn:active:not(:disabled) { transform: translateY(1px); }
.tp-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.tp-btn.primary {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}
.tp-btn.primary:hover:not(:disabled) {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: var(--accent-fg);
}

.tp-btn.danger {
  color: var(--red);
  border-color: var(--red);
  background: transparent;
}
.tp-btn.danger:hover:not(:disabled) {
  background: var(--red-soft);
  border-color: var(--red);
  color: var(--red);
}

.tp-btn.ghost {
  background: transparent;
  border-color: var(--border);
  color: var(--fg-1);
}

.tp-btn.success {
  color: var(--green);
  border-color: var(--green);
  background: transparent;
}
.tp-btn.success:hover:not(:disabled) {
  background: var(--green-soft);
  border-color: var(--green);
  color: var(--green);
}

.tp-btn + .tp-btn { margin-left: var(--s-2); }
.tp-form .tp-btn { margin-top: var(--s-4); align-self: flex-start; }

/* ─── Tiles (grid de acceso rápido) ──────────────────────────── */

.tp-tile-grid {
  display: grid;
  gap: var(--s-3);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.tp-tile {
  display: block;
  padding: var(--s-4) var(--s-5);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  text-decoration: none;
  color: var(--fg-0);
  min-height: 80px;
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
}
.tp-tile:hover {
  border-color: var(--accent);
  background: var(--bg-3);
  transform: translateY(-2px);
  text-decoration: none;
}
.tp-tile h4 {
  margin: 0 0 6px;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg-0);
}
.tp-tile p {
  margin: 0;
  color: var(--fg-2);
  font-size: var(--fs-sm);
  line-height: 1.5;
}

/* ─── Filas key/value ────────────────────────────────────────── */

.tp-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--fs-md);
  min-height: var(--tap);
}
.tp-row:last-child { border-bottom: none; }
.tp-row .label { color: var(--fg-2); font-size: var(--fs-sm); }

/* ─── Tablas ─────────────────────────────────────────────────── */

.tp-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-md);
}
.tp-table th,
.tp-table td {
  text-align: left;
  padding: var(--s-3) var(--s-3);
  border-bottom: 1px solid var(--border-soft);
  vertical-align: middle;
}
.tp-table th {
  color: var(--fg-2);
  font-weight: 600;
  font-size: var(--fs-sm);
  background: transparent;
  text-transform: none;
  letter-spacing: 0;
  border-bottom: 1px solid var(--border);
}
.tp-table tbody tr { transition: background 0.1s; }
.tp-table tbody tr:hover td { background: var(--bg-2); }
.tp-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.tp-table td.dim { color: var(--fg-2); }

/* Scroll horizontal wrapper opcional */
.tp-table-wrap { overflow-x: auto; }

/* ─── Pills / chips ──────────────────────────────────────────── */

.tp-pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: 600;
  background: var(--bg-3);
  color: var(--fg-1);
  border: 1px solid var(--border-strong);
  white-space: nowrap;
  line-height: 1.4;
}
.tp-pill.ok {
  background: var(--green-soft);
  color: var(--green);
  border-color: var(--green);
}
.tp-pill.err {
  background: var(--red-soft);
  color: var(--red);
  border-color: var(--red);
}
.tp-pill.warn {
  background: var(--yellow-soft);
  color: var(--yellow);
  border-color: var(--yellow);
}
.tp-pill.info {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}

/* Tag chips (task detail, filtros) */
.tp-tag-chip {
  display: inline-flex;
  align-items: center;
  background: var(--bg-3);
  color: var(--fg-1);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  padding: 8px 14px;
  min-height: 36px;
  font-size: var(--fs-sm);
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.tp-tag-chip:hover { background: var(--bg-2); color: var(--fg-0); }
/* El chip activo lleva `:hover` incluido para que pasar el ratón por encima no
   revierta a los colores de hover (background/texto) y lo deje ilegible. */
.tp-tag-chip.active,
.tp-tag-chip.active:hover {
  background: var(--accent);
  /* Texto oscuro EXPLÍCITO (literal, sin var): garantiza contraste aunque un
     tokens.css cacheado/antiguo no traiga o traiga mal --accent-fg. Era el bug
     del "texto del mismo color que el fondo" en el tag activo. */
  color: #04121c;
  border-color: var(--accent);
  font-weight: 600;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
.tp-tag-chip.active::before {
  content: "\2713"; /* ✓ — afordancia clara de selección */
  margin-right: 6px;
  font-weight: 700;
}

/* ─── TaskRow ────────────────────────────────────────────────── */

.tp-task-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  min-height: 56px;
  border-bottom: 1px solid var(--border-soft);
  background: var(--bg-1);
  transition: background 0.1s;
}
.tp-task-row:first-child { border-top-left-radius: var(--r-md); border-top-right-radius: var(--r-md); }
.tp-task-row:last-child { border-bottom-left-radius: var(--r-md); border-bottom-right-radius: var(--r-md); border-bottom: none; }
.tp-task-row:hover { background: var(--bg-2); }

.tp-task-row .tp-checkbox {
  width: 22px;
  height: 22px;
  border: 2px solid var(--fg-3);
  border-radius: 6px;
  cursor: pointer;
  flex-shrink: 0;
  background: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, border-color 0.15s;
}
.tp-task-row .tp-checkbox:hover { border-color: var(--accent); }
.tp-task-row .tp-checkbox.done {
  background: var(--green);
  border-color: var(--green);
}
.tp-task-row .tp-checkbox.done::after {
  content: '✓';
  color: white;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
}
.tp-task-row .title {
  flex: 1 1 0;
  min-width: 0;
  color: var(--fg-0);
  font-size: var(--fs-md);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* Button reset: el título es <button> para accesibilidad, pero visualmente
     debe verse como texto plano clicable. */
  background: transparent;
  border: none;
  text-align: left;
  cursor: pointer;
  padding: 0;
  font: inherit;
  /* Asegura que el texto no se rompa palabra-por-palabra en columnas estrechas
     cuando el wrap todavía no se ha disparado (defensa contra layout shift). */
  word-break: normal;
  overflow-wrap: anywhere;
}
.tp-task-row.done .title { text-decoration: line-through; color: var(--fg-2); }
.tp-task-row .prio {
  font-size: var(--fs-xs);
  padding: 3px 8px;
  border-radius: var(--r-sm);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.tp-task-row .prio.p3 { background: var(--red); color: white; }
.tp-task-row .prio.p2 { background: var(--yellow); color: #1a1206; }
.tp-task-row .prio.p1 { background: var(--blue); color: white; }
.tp-task-row .due { color: var(--fg-2); font-size: var(--fs-sm); white-space: nowrap; }
.tp-task-row .tp-task-estim {
  color: var(--fg-1);
  background: var(--bg-3);
  font-size: var(--fs-xs);
  padding: 2px 8px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.tp-task-row .tag {
  font-size: var(--fs-xs);
  padding: 3px 10px;
  border-radius: var(--r-pill);
  background: var(--bg-3);
  color: var(--fg-1);
  border: 1px solid var(--border-strong);
  white-space: nowrap;
}
.tp-task-row .actions { display: flex; gap: 4px; flex-shrink: 0; }
.tp-task-row .actions button {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--fg-1);
  padding: 6px 10px;
  min-height: 36px;
  border-radius: var(--r-sm);
  cursor: pointer;
  font-size: var(--fs-xs);
  font-weight: 500;
}
.tp-task-row .actions button:hover {
  background: var(--bg-3);
  border-color: var(--accent);
  color: var(--accent);
}
/* #10 — Botón de prioridad inline: color según nivel para lectura de un vistazo. */
.tp-task-row .actions button.tp-row-prio-btn.p3 { color: var(--red); border-color: color-mix(in srgb, var(--red) 45%, var(--border)); }
.tp-task-row .actions button.tp-row-prio-btn.p2 { color: var(--yellow); border-color: color-mix(in srgb, var(--yellow) 45%, var(--border)); }
.tp-task-row .actions button.tp-row-prio-btn.p1 { color: var(--blue); border-color: color-mix(in srgb, var(--blue) 45%, var(--border)); }

/* ─── #18 Pestañas accesibles (WAI-ARIA Tabs) ────────────────────── */
.tp-tabs { display: flex; flex-direction: column; gap: var(--s-4); }
.tp-tabs-list {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  gap: 2px;
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--border);
  background: var(--bg-0);
  -webkit-overflow-scrolling: touch;
}
.tp-tabs-list::-webkit-scrollbar { display: none; }
.tp-tab {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  min-height: var(--tap);
  border: none;
  background: transparent;
  color: var(--fg-2);
  font-size: var(--fs-sm);
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  border-radius: var(--r-md) var(--r-md) 0 0;
  transition: color 0.15s, background 0.15s;
}
.tp-tab-ico {
  display: inline-flex;
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  opacity: 0.75;
  transition: opacity 0.15s, transform 0.15s;
}
.tp-tab-ico svg { width: 100%; height: 100%; display: block; }
.tp-tab:hover { color: var(--fg-0); background: var(--bg-1); }
.tp-tab:hover .tp-tab-ico { opacity: 1; }
.tp-tab.is-active { color: var(--accent); }
.tp-tab.is-active .tp-tab-ico { opacity: 1; transform: scale(1.06); }
.tp-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--r-sm); }
/* Indicador deslizante: subrayado que anima de una tab a otra. Se coloca a
   bottom:0 (dentro del padding-box) para no ser recortado por overflow-x. */
.tp-tabs-indicator {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2.5px;
  width: 0;
  background: var(--accent);
  border-radius: 3px 3px 0 0;
  transform: translateX(0);
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1), width 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .tp-tabs-indicator { transition: none; }
  .tp-tab.is-active .tp-tab-ico { transform: none; }
}
.tp-tabs-panels { display: block; }
.tp-tabpanel { display: flex; flex-direction: column; gap: var(--s-4); }
.tp-tabpanel[hidden] { display: none; }

/* ─── #10 Popover / bottom-sheet de edición rápida ───────────────── */
.tp-popover-overlay {
  position: fixed;
  inset: 0;
  z-index: 9500;
}
.tp-popover-overlay.is-sheet {
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: flex-end;
}
.tp-popover {
  background: var(--bg-1);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md, 10px);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
  padding: 6px;
  min-width: 200px;
  max-width: 320px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tp-popover.is-sheet {
  width: 100%;
  max-width: none;
  border-radius: var(--r-lg, 16px) var(--r-lg, 16px) 0 0;
  padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0));
  animation: tp-sheet-up 0.2s ease-out;
}
@keyframes tp-sheet-up {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}
.tp-popover-title {
  font-size: var(--fs-xs);
  color: var(--fg-2);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 8px 12px 6px;
  font-weight: 600;
}
.tp-popover-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  min-height: var(--tap);
  background: transparent;
  border: none;
  border-radius: var(--r-sm);
  color: var(--fg-0);
  font-size: var(--fs-sm);
  text-align: left;
  cursor: pointer;
}
.tp-popover-item:hover, .tp-popover-item:focus-visible { background: var(--bg-3); outline: none; }
.tp-popover-item.is-active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.tp-popover-item.is-danger { color: var(--red); }
.tp-popover-item-icon { width: 20px; text-align: center; flex-shrink: 0; }
.tp-popover-item-label { flex: 1; }
.tp-popover-item-hint { color: var(--fg-2); font-size: var(--fs-xs); }
.tp-popover.is-sheet .tp-popover-item { min-height: 52px; font-size: var(--fs-md); }

/* ─── Login ──────────────────────────────────────────────────── */

.tp-login {
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--s-4);
  padding-top: calc(var(--s-4) + env(safe-area-inset-top, 0));
  padding-bottom: calc(var(--s-4) + env(safe-area-inset-bottom, 0));
  background: var(--bg-0);
}
.tp-login form {
  background: var(--bg-1);
  border: 1px solid var(--border);
  padding: var(--s-6);
  border-radius: var(--r-xl);
  width: 100%;
  max-width: 400px;
  box-shadow: var(--shadow-lg);
}
.tp-login h2 {
  margin: 0 0 var(--s-5);
  font-size: var(--fs-xl);
  text-align: center;
  font-weight: 700;
  color: var(--fg-0);
  letter-spacing: -0.01em;
}
.tp-login h2 .accent { color: var(--accent); }
.tp-login label {
  display: block;
  margin-top: var(--s-4);
  font-size: var(--fs-sm);
  color: var(--fg-1);
  font-weight: 500;
}
.tp-login input {
  width: 100%;
  padding: 12px 14px;
  margin-top: 6px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-0);
  border-radius: var(--r-md);
  font-size: var(--fs-md);
  min-height: var(--tap);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.tp-login input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}
.tp-login button {
  margin-top: var(--s-5);
  width: 100%;
  padding: 14px;
  min-height: var(--tap);
  background: var(--accent);
  color: var(--accent-fg);
  border: none;
  border-radius: var(--r-md);
  cursor: pointer;
  font-weight: 700;
  font-size: var(--fs-md);
  transition: background 0.15s, transform 0.05s;
}
.tp-login button:hover:not(:disabled) { background: var(--accent-strong); }
.tp-login button:active:not(:disabled) { transform: translateY(1px); }
.tp-login button:disabled { opacity: 0.5; cursor: not-allowed; }
.tp-login .error {
  color: var(--red);
  margin-top: var(--s-3);
  font-size: var(--fs-sm);
  text-align: center;
  min-height: 1.2em;
}

.tp-login .tp-remember,
.tp-remember {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--fg-1);
  cursor: pointer;
  user-select: none;
}
.tp-login .tp-remember input,
.tp-remember input { width: 18px; height: 18px; margin: 0; cursor: pointer; }

/* ─── Checklist (task detail) ────────────────────────────────── */

.tp-checklist { display: flex; flex-direction: column; }
.tp-checklist-item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--fs-md);
  min-height: var(--tap);
}
.tp-checklist-item:last-child { border-bottom: none; }
.tp-checklist-item input[type=checkbox] { cursor: pointer; }
.tp-checklist-item.done > span { text-decoration: line-through; color: var(--fg-2); }

/* Opciones de recurrencia (task detail) */
.tp-rec-option {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3);
  min-height: var(--tap);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
  font-size: var(--fs-md);
  margin-bottom: var(--s-2);
  transition: border-color 0.15s, background 0.15s;
}
.tp-rec-option:hover { border-color: var(--accent); background: var(--bg-3); }
.tp-rec-option.active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }

.tp-rec-banner {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  color: var(--accent);
}

/* ─── Done view ──────────────────────────────────────────────── */

.tp-done-filters {
  display: flex;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
  flex-wrap: wrap;
  align-items: center;
}
.tp-done-filters .tp-input { flex: 1 1 200px; margin-top: 0; }
.tp-done-filters .tp-done-range { flex: 0 0 200px; max-width: 100%; }
.tp-done-filters .tp-done-search { flex: 1 1 240px; }

.tp-done-list { display: flex; flex-direction: column; gap: var(--s-5); }

.tp-done-section { margin-bottom: var(--s-4); }
.tp-done-section h3 {
  margin: 0 0 var(--s-2);
  font-size: var(--fs-xs);
  color: var(--fg-2);
  border-bottom: 1px solid var(--border);
  padding-bottom: var(--s-2);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.tp-done-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3);
  border-radius: var(--r-sm);
  min-height: var(--tap);
  transition: background 0.1s;
}
.tp-done-row:hover { background: var(--bg-2); }
.tp-done-title {
  flex: 1;
  color: var(--fg-1);
  text-decoration: line-through;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tp-done-row:hover .tp-done-title { color: var(--fg-0); }
.tp-done-time {
  color: var(--fg-2);
  font-size: var(--fs-sm);
  white-space: nowrap;
}

/* ─── New task bar (NewTaskBar.js) ─────────────────────────────
   Layout en 2 filas:
   - row-main: + icon, input, ⚙ toggle, botón "Añadir" primario.
   - row-opts: chips fecha, pills prioridad, est, tag, proyecto, plantilla.
   Mobile: la fila opts está oculta por defecto y se despliega con ⚙. */

.tp-ntb {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-4);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.tp-ntb:focus-within {
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}

.tp-ntb-row {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}
.tp-ntb-row-main { gap: var(--s-3); }
.tp-ntb-row-opts {
  padding-top: var(--s-2);
  border-top: 1px dashed var(--border-soft);
  row-gap: var(--s-2);
}

.tp-ntb-plus {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: var(--accent-fg);
  font-size: 22px;
  line-height: 1;
  font-weight: 700;
  flex-shrink: 0;
}

.tp-ntb-input {
  flex: 1 1 200px;
  min-width: 0;
  border: none;
  background: transparent;
  outline: none;
  color: var(--fg-0);
  font-size: var(--fs-md);
  min-height: 40px;
  padding: 0;
}
.tp-ntb-input::placeholder { color: var(--fg-3); }
.tp-ntb-input:disabled { opacity: 0.6; }

.tp-ntb-submit {
  flex-shrink: 0;
  border-radius: var(--r-md);
  font-family: inherit;
  cursor: pointer;
  min-height: 40px;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  background: var(--accent);
  color: var(--accent-fg);
  border: none;
  padding: 0 var(--s-4);
  font-weight: 700;
  font-size: var(--fs-md);
  min-width: 88px;
}
.tp-ntb-submit:hover:not(:disabled) { background: var(--accent-strong); }
.tp-ntb-submit:active:not(:disabled) { transform: translateY(1px); }
.tp-ntb-submit:disabled { opacity: 0.5; cursor: not-allowed; }

/* Preview chip: aparece debajo del input mostrando los modificadores activos */
.tp-ntb-preview {
  font-size: var(--fs-sm);
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-md);
  padding: 6px 12px;
  font-weight: 500;
  word-break: break-word;
}

/* Chips de fecha rápida */
.tp-ntb-quickdates {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}
.tp-ntb-chip {
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-1);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 500;
  padding: 6px 12px;
  min-height: 34px;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.tp-ntb-chip:hover { border-color: var(--accent); color: var(--accent); }
.tp-ntb-chip.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}
.tp-ntb-chip-custom {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.tp-ntb-datepicker {
  /* Input nativo escondido: solo lo abrimos programáticamente desde el chip. */
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Pills de prioridad */
.tp-ntb-priorities {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--bg-2);
}
.tp-ntb-prio {
  background: transparent;
  border: none;
  color: var(--fg-2);
  font-family: inherit;
  font-weight: 700;
  font-size: var(--fs-sm);
  padding: 6px 14px;
  min-height: 34px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
  border-right: 1px solid var(--border-soft);
}
.tp-ntb-prio:last-child { border-right: none; }
.tp-ntb-prio:hover { background: var(--bg-3); color: var(--fg-0); }
.tp-ntb-prio.is-active {
  background: var(--accent-soft);
  color: var(--accent);
}
.tp-ntb-prio-1.is-active { color: var(--blue); background: var(--blue-soft); }
.tp-ntb-prio-2.is-active { color: var(--yellow); background: var(--yellow-soft); }
.tp-ntb-prio-3.is-active { color: var(--red); background: var(--red-soft); }

/* Estimación */
.tp-ntb-est {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  padding: 0 12px;
  min-height: 34px;
}
.tp-ntb-est-icon { color: var(--fg-2); font-size: 14px; }
.tp-ntb-est-input {
  border: none;
  background: transparent;
  color: var(--fg-0);
  outline: none;
  width: 60px;
  font-family: inherit;
  font-size: var(--fs-sm);
  -moz-appearance: textfield;
}
.tp-ntb-est-input::-webkit-outer-spin-button,
.tp-ntb-est-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
/* #2 — valor pre-rellenado por sugerencia de histórico (se quita al editar). */
.tp-ntb-est-input.is-suggested { color: var(--accent); font-weight: 600; }

/* Selects de tag y proyecto */
.tp-ntb-tag,
.tp-ntb-proj {
  appearance: none;
  -webkit-appearance: none;
  background: var(--bg-2)
    url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%237585a0' stroke-width='2.5'%3e%3cpolyline points='6 9 12 15 18 9'/%3e%3c/svg%3e")
    no-repeat right 10px center;
  border: 1px solid var(--border);
  color: var(--fg-0);
  border-radius: var(--r-md);
  padding: 6px 28px 6px 12px;
  min-height: 34px;
  font-family: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
  flex: 1 1 140px;
  min-width: 0;
}
.tp-ntb-tag { border-color: color-mix(in srgb, var(--accent) 30%, var(--border)); }
.tp-ntb-tag:focus,
.tp-ntb-proj:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}

.tp-ntb-tpl {
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-1);
  font-family: inherit;
  font-size: var(--fs-sm);
  padding: 6px 12px;
  min-height: 34px;
  border-radius: var(--r-md);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: border-color 0.12s, color 0.12s;
}
.tp-ntb-tpl:hover { border-color: var(--accent); color: var(--accent); }

/* NOTA: NO ocultar la barra antigua `.tp-new-task-bar` con display:none.
   Hacerlo creaba una trampa de desincronización de versiones: un cliente con
   JS viejo (que aún pinta `.tp-new-task-bar`) + este CSS nuevo se quedaba SIN
   barra de alta visible. Si un cliente sirve JS antiguo, que al menos vea una
   barra usable (aunque sin estilar) en vez de nada. El SW ahora usa
   network-first para JS/CSS (ver sw.js.php), así que este skew no debería
   reproducirse, pero mantenemos la barra antigua visible por seguridad. */

/* ─── Banner de tareas vencidas (rollover #14) ───────────────── */
.tp-overdue-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-4);
  background: var(--red-soft);
  border: 1px solid var(--red);
  border-radius: var(--r-md);
  color: var(--red);
}
.tp-overdue-banner-text { font-weight: 600; }
.tp-overdue-banner-actions { display: flex; gap: var(--s-2); flex-wrap: wrap; }

/* ─── #12 Triage unificado: segmentador ─────────────────────────── */
.tp-triage-seg {
  display: flex;
  gap: 4px;
  padding: 4px;
  margin-bottom: var(--s-4);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow-x: auto;
}
.tp-triage-seg-btn {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  white-space: nowrap;
  padding: 8px 12px;
  min-height: var(--tap);
  border: none;
  background: transparent;
  color: var(--fg-1);
  font-size: var(--fs-sm);
  font-weight: 500;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.tp-triage-seg-btn:hover { background: var(--bg-3); }
.tp-triage-seg-btn.is-active {
  background: var(--bg-1);
  color: var(--accent);
  box-shadow: var(--shadow-sm);
}
.tp-triage-seg-count {
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  background: var(--bg-3);
  color: var(--fg-2);
  border-radius: var(--r-pill);
  padding: 1px 7px;
}
.tp-triage-seg-btn.is-active .tp-triage-seg-count { background: var(--accent-soft); color: var(--accent); }

/* Badge de estado dentro de una fila de tarea (#12). */
.tp-task-row .tp-row-badge {
  font-size: var(--fs-xs);
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--bg-3);
  color: var(--fg-2);
  border: 1px solid var(--border);
  white-space: nowrap;
  flex-shrink: 0;
}
.tp-task-row .tp-row-badge.warn {
  background: color-mix(in srgb, var(--warning, #d98a00) 12%, var(--bg-1));
  color: var(--warning, #d98a00);
  border-color: color-mix(in srgb, var(--warning, #d98a00) 40%, var(--border));
}
@media (max-width: 768px) {
  .tp-task-row .tp-row-badge { order: 3; }
}

/* #13 — botón de dictado por voz */
.tp-mic-btn.is-listening {
  background: var(--red-soft);
  color: var(--red);
  border-color: var(--red);
  animation: tp-mic-pulse 1.2s ease-in-out infinite;
}
@keyframes tp-mic-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.55; } }

/* #19 — Modo Foco (overlay a pantalla completa) */
.tp-focus-overlay {
  position: fixed;
  inset: 0;
  z-index: 11000;
  background: var(--bg-0);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(env(safe-area-inset-top, 0) + var(--s-6)) var(--s-5) calc(env(safe-area-inset-bottom, 0) + var(--s-5));
}
.tp-focus-inner {
  width: 100%;
  max-width: 560px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-4);
}
.tp-focus-close {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0) + var(--s-3));
  right: calc(env(safe-area-inset-right, 0) + var(--s-3));
  width: var(--tap);
  height: var(--tap);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--fg-0);
  font-size: 22px;
  cursor: pointer;
}
.tp-focus-title { font-size: var(--fs-xl); font-weight: 700; color: var(--fg-0); margin: 0; overflow-wrap: anywhere; }
.tp-focus-time {
  font-size: clamp(48px, 18vw, 96px);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  line-height: 1;
}
.tp-focus-bar { width: 100%; max-width: 360px; height: 6px; background: var(--bg-3); border-radius: var(--r-pill); overflow: hidden; }
.tp-focus-bar-fill { display: block; height: 100%; width: 0; background: var(--accent); transition: width 1s linear; }
.tp-focus-pomo { color: var(--fg-2); font-size: var(--fs-sm); }
.tp-focus-pomo.done { color: var(--green); font-weight: 600; }
.tp-focus-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); justify-content: center; }
/* #8 — Estado del timer Clockify dentro del modo foco */
.tp-focus-clockify {
  margin-top: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--fg-2);
  min-height: 1.4em;
  text-align: center;
}
.tp-focus-clockify.is-on { color: var(--green); }
.tp-focus-clockify.is-off { color: var(--fg-3); }
.tp-focus-btn { min-height: var(--tap); }

/* #28 — informe de procrastinación */
.tp-procrast-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-1); }
.tp-procrast-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  background: var(--bg-2);
  border-radius: var(--r-md);
}
.tp-procrast-title { color: var(--fg-0); text-decoration: none; min-width: 0; overflow-wrap: anywhere; }
.tp-procrast-title:hover { color: var(--accent); }
.tp-procrast-count {
  flex: 0 0 auto;
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--red);
  background: var(--red-soft);
  padding: 2px 10px;
  border-radius: var(--r-pill);
}

/* E1 — roles / gestión de usuarios */
.tp-role-badge {
  display: inline-block;
  margin-left: var(--s-2);
  padding: 2px 8px;
  font-size: var(--fs-xs);
  font-weight: 600;
  border-radius: var(--r-pill);
  background: var(--yellow-soft);
  color: var(--yellow);
  vertical-align: middle;
}
.tp-users-ul { list-style: none; margin: 0 0 var(--s-3); padding: 0; display: flex; flex-direction: column; gap: var(--s-1); }
.tp-users-item {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3); flex-wrap: wrap; padding: var(--s-2) 0;
  border-bottom: 1px solid var(--border-soft);
}
.tp-users-role { font-size: var(--fs-xs); color: var(--fg-2); background: var(--bg-3); padding: 1px 8px; border-radius: var(--r-pill); margin-left: 4px; }
.tp-users-form { display: flex; gap: var(--s-2); flex-wrap: wrap; margin-top: var(--s-2); }
.tp-users-form .tp-input { flex: 1 1 180px; }

/* ─── Toasts ─────────────────────────────────────────────────── */

.tp-toasts {
  position: fixed;
  bottom: var(--s-4);
  right: var(--s-4);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  pointer-events: none;
}
.tp-toast {
  background: var(--bg-2);
  color: var(--fg-0);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  max-width: 420px;
  font-size: var(--fs-sm);
  line-height: 1.4;
  overflow-wrap: anywhere;
  word-break: break-word;
  box-shadow: var(--shadow-md);
  animation: slideIn 0.2s ease-out;
  pointer-events: auto;
  /* Layout flex para que el botón "×" se alinee siempre arriba a la
     derecha del mensaje, sin importar cuántas líneas ocupe el texto. */
  display: flex;
  align-items: flex-start;
  gap: var(--s-2);
  transition: opacity 0.2s;
}
.tp-toast.error { border-left-color: var(--red); }
.tp-toast.success { border-left-color: var(--green); }
.tp-toast.warning { border-left-color: var(--yellow); }
/* Mensaje del toast: 5 líneas máximo con ellipsis. Texto completo en title. */
.tp-toast-msg {
  flex: 1;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  overflow: hidden;
  /* Margen superior 2px para que la primera línea quede ópticamente alineada
     con el centro del botón ×. */
  margin-top: 2px;
}
/* Botón cerrar: cuadrado 24×24 que se posiciona claro y centrado. Sin
   marginLeft inline ni ajustes de fontSize. */
.tp-toast-close {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  color: inherit;
  cursor: pointer;
  font-size: 18px;
  font-weight: 400;
  line-height: 1;
  transition: background 0.12s, border-color 0.12s;
}
.tp-toast-close:hover {
  background: var(--bg-3);
  border-color: var(--border);
}
.tp-toast-close:active { transform: scale(0.92); }
.tp-toast-undo {
  flex-shrink: 0;
  padding: 4px 10px;
  background: rgba(255,255,255,0.15);
  border: 1px solid rgba(255,255,255,0.25);
  color: #fff;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}
.tp-toast-undo:hover { background: rgba(255,255,255,0.25); }
@keyframes slideIn {
  from { transform: translateX(20px); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}

/* ─── Banner de instalación PWA (Android nativo + iOS guía manual) ──── */
.tp-install-banner {
  position: fixed;
  left: var(--s-3);
  right: var(--s-3);
  bottom: calc(var(--s-3) + env(safe-area-inset-bottom, 0));
  z-index: 8500;
  background: linear-gradient(135deg, var(--bg-2) 0%, var(--bg-3) 100%);
  border: 1px solid var(--accent);
  border-radius: var(--r-lg);
  padding: var(--s-3) var(--s-4);
  display: flex;
  align-items: center;
  gap: var(--s-3);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
  animation: tp-install-slide 0.35s ease-out;
  max-width: 600px;
  margin: 0 auto;
}
@keyframes tp-install-slide {
  from { transform: translateY(120%); opacity: 0; }
  to   { transform: translateY(0);     opacity: 1; }
}
.tp-install-banner-icon {
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bg-3);
  display: flex;
  align-items: center;
  justify-content: center;
}
.tp-install-banner-icon img {
  width: 100%;
  height: 100%;
  display: block;
}
.tp-install-banner-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: 1.4;
}
.tp-install-banner-text strong {
  color: var(--fg-0);
  font-size: var(--fs-md);
  font-weight: 700;
}
.tp-install-banner-text span {
  color: var(--fg-1);
  font-size: var(--fs-sm);
}
.tp-install-banner-text em {
  font-style: normal;
  color: var(--accent);
  font-weight: 600;
}
.tp-install-share-icon {
  display: inline-block;
  vertical-align: -3px;
  color: var(--accent);
  margin: 0 2px;
}
.tp-install-banner-actions {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  flex-shrink: 0;
}
.tp-install-banner-primary {
  background: var(--accent);
  color: var(--accent-fg);
  border: none;
  padding: 10px 18px;
  border-radius: var(--r-md);
  cursor: pointer;
  font-weight: 700;
  font-size: var(--fs-sm);
  min-height: 40px;
  font-family: inherit;
  white-space: nowrap;
}
.tp-install-banner-primary:hover { background: var(--accent-strong); }
.tp-install-banner-close {
  background: transparent;
  border: none;
  color: var(--fg-2);
  font-size: 24px;
  line-height: 1;
  width: 32px;
  height: 32px;
  border-radius: var(--r-sm);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  padding: 0;
  flex-shrink: 0;
}
.tp-install-banner-close:hover { background: var(--bg-3); color: var(--fg-0); }
.tp-install-banner-close:active { transform: scale(0.92); }

/* En mobile (donde más se usa): banner se levanta por encima de bottom-nav */
@media (max-width: 768px) {
  .tp-install-banner {
    /* Bottom-nav ocupa ~64px + safe-area. Levantamos un poco más para evitar
       que tape el contenido si las dos UI coexisten. */
    bottom: calc(72px + env(safe-area-inset-bottom, 0));
    flex-wrap: wrap;
    row-gap: var(--s-2);
  }
  .tp-install-banner-ios .tp-install-banner-text {
    flex: 1 1 calc(100% - 90px);
  }
  .tp-install-banner-text strong { font-size: var(--fs-sm); }
  .tp-install-banner-text span { font-size: var(--fs-xs); }
}

/* ─── Banner (upgrade, etc.) ─────────────────────────────────── */

.tp-banner {
  position: fixed;
  top: 0; left: 0; right: 0;
  background: var(--accent);
  color: var(--accent-fg);
  /* Safe-area: en PWA standalone iOS (status-bar black-translucent) el banner
     fijo top:0 quedaría bajo el notch/Dynamic Island y sus botones serían
     intocables. Empujamos su contenido por debajo de la zona segura. */
  padding: calc(var(--s-3) + env(safe-area-inset-top, 0)) max(var(--s-4), env(safe-area-inset-right, 0)) var(--s-3) max(var(--s-4), env(safe-area-inset-left, 0));
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--fs-sm);
  font-weight: 500;
  z-index: 9998;
  min-height: var(--tap);
  flex-wrap: wrap;
}
.tp-banner button {
  background: var(--accent-fg);
  color: var(--accent);
  border: none;
  padding: 8px 16px;
  min-height: 36px;
  border-radius: var(--r-md);
  cursor: pointer;
  font-weight: 700;
  font-size: var(--fs-sm);
}
.tp-banner .close {
  background: transparent;
  color: var(--accent-fg);
  margin-left: auto;
  border: 1px solid currentColor;
}

/* ─── Modal ──────────────────────────────────────────────────── */

.tp-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(5, 12, 24, 0.7);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  display: grid;
  place-items: center;
  z-index: 9500;
  padding: var(--s-4);
  animation: fadeIn 0.15s ease-out;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.tp-modal {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: var(--s-5) var(--s-5);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  /* dvh = viewport dinámico real en móvil (excluye barra URL de iOS/Android).
     Con vh el modal se dimensionaba contra el viewport "grande" y podía
     extenderse por debajo del área visible. */
  max-height: 90dvh;
  overflow-y: auto;
  box-shadow: var(--shadow-lg);
  animation: popIn 0.2s ease-out;
}
@keyframes popIn {
  from { transform: scale(0.96) translateY(8px); opacity: 0; }
  to { transform: scale(1) translateY(0); opacity: 1; }
}
.tp-modal h3 {
  margin: 0 0 var(--s-4);
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--fg-0);
}
.tp-modal label {
  display: block;
  margin-top: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--fg-1);
  font-weight: 500;
}
.tp-modal input,
.tp-modal textarea,
.tp-modal select {
  width: 100%;
  padding: 12px 14px;
  margin-top: 6px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-0);
  border-radius: var(--r-md);
  font-size: var(--fs-md);
  min-height: var(--tap);
  font-family: inherit;
}
.tp-modal input:focus,
.tp-modal textarea:focus,
.tp-modal select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}
.tp-modal textarea { min-height: 96px; resize: vertical; line-height: 1.5; }
.tp-modal .actions {
  display: flex;
  gap: var(--s-2);
  justify-content: flex-end;
  margin-top: var(--s-5);
  flex-wrap: wrap;
}
.tp-modal button {
  padding: 10px 18px;
  min-height: var(--tap);
  border-radius: var(--r-md);
  border: 1px solid var(--border-strong);
  background: var(--bg-3);
  color: var(--fg-0);
  cursor: pointer;
  font-weight: 600;
  font-size: var(--fs-md);
  font-family: inherit;
  transition: background 0.15s, border-color 0.15s;
}
.tp-modal button:hover { background: var(--bg-2); border-color: var(--accent); }
.tp-modal button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}
.tp-modal button.primary:hover { background: var(--accent-strong); border-color: var(--accent-strong); }

/* Modal de tareas no planificadas por IA */
.tp-ai-unscheduled-summary {
  background: var(--bg-3);
  border-left: 3px solid #a855f7;
  padding: var(--s-2) var(--s-3);
  margin: 0 0 var(--s-3);
  border-radius: var(--r-sm);
  color: var(--fg-1);
  font-size: var(--fs-sm);
  line-height: 1.5;
}
.tp-ai-unscheduled-intro {
  margin: 0 0 var(--s-3);
  color: var(--fg-1);
}
.tp-ai-unscheduled-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  max-height: 50vh;
  overflow-y: auto;
}
.tp-ai-unscheduled-list li {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: var(--s-2) var(--s-3);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.tp-ai-unscheduled-title {
  font-weight: 600;
  color: var(--fg-0);
  text-decoration: none;
}
a.tp-ai-unscheduled-title:hover { color: var(--accent); text-decoration: underline; }
.tp-ai-unscheduled-reason {
  font-size: var(--fs-sm);
  color: var(--fg-2);
  line-height: 1.4;
}
.tp-ai-unscheduled-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.tp-ai-unscheduled-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-2);
}
.tp-ai-unscheduled-actions .tp-btn {
  font-size: var(--fs-sm);
  padding: 6px 10px;
  min-height: 0;
}
.tp-ai-unscheduled-date-editor {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  margin-top: var(--s-2);
  padding-top: var(--s-2);
  border-top: 1px dashed var(--border);
}
.tp-ai-unscheduled-date-editor .tp-input { width: 160px; }

/* ─── Calendar ───────────────────────────────────────────────── */

/* Topbar nav */
.tp-cal-topbar { align-items: center; gap: var(--s-3); flex-wrap: wrap; }
/* El título de rango ("31 Mayo – 3 Junio 2026") escala de forma fluida con el
   ancho en vez de quedarse en --fs-2xl (28px) y partirse en varias líneas al
   estrechar la ventana en desktop. `nowrap` evita el salto de línea (y anula el
   `overflow-wrap: anywhere` heredado de .tp-topbar h2); el ellipsis es solo red
   de seguridad en anchos extremos. Los @media móviles de más abajo siguen
   mandando dentro de sus breakpoints. */
.tp-cal-topbar h2 {
  font-size: clamp(var(--fs-md), 2.4vw, var(--fs-xl));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tp-cal-viewswitch {
  display: inline-flex;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 3px;
  gap: 2px;
}
.tp-cal-vbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  padding: 6px 14px;
  border-radius: calc(var(--r-md) - 3px);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--fg-1);
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}
.tp-cal-vbtn:hover { color: var(--fg-0); background: var(--bg-3); text-decoration: none; }
.tp-cal-vbtn.active {
  background: var(--accent);
  color: var(--accent-fg);
}

.tp-cal-nav {
  display: inline-flex;
  gap: var(--s-2);
  align-items: center;
}
.tp-cal-navbtn {
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-0);
  border-radius: var(--r-md);
  min-width: var(--tap);
  height: var(--tap);
  padding: 0 var(--s-3);
  cursor: pointer;
  font-size: var(--fs-md);
  font-weight: 600;
  font-family: inherit;
  transition: background 0.15s, border-color 0.15s;
}
.tp-cal-navbtn:hover {
  background: var(--bg-3);
  border-color: var(--accent);
}
.tp-cal-today { color: var(--accent); }

/* Botón "Planificar con IA" en el topbar del calendario */
.tp-cal-ai-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: var(--r-md);
  height: var(--tap);
  padding: 0 var(--s-3);
  margin-left: var(--s-2);
  cursor: pointer;
  font-size: var(--fs-md);
  font-weight: 600;
  font-family: inherit;
  white-space: nowrap;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(124, 58, 237, 0.1);
  transition: transform 0.15s, box-shadow 0.15s, filter 0.15s;
}
.tp-cal-ai-btn:hover:not(:disabled) {
  filter: brightness(1.08);
  box-shadow: 0 2px 8px rgba(124, 58, 237, 0.35);
}
.tp-cal-ai-btn:active:not(:disabled) {
  transform: translateY(1px);
}
.tp-cal-ai-btn:disabled,
.tp-cal-ai-btn.is-loading {
  cursor: progress;
  opacity: 0.75;
}
.tp-cal-ai-icon {
  font-size: var(--fs-md);
  line-height: 1;
}
.tp-cal-ai-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: tp-cal-ai-spin 0.7s linear infinite;
}
@keyframes tp-cal-ai-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .tp-cal-ai-spinner { animation-duration: 2s; }
}

/* ─── Split-button del Planificador IA ───────────────────────── */
.tp-cal-ai-split {
  position: relative;
  display: inline-flex;
  margin-left: var(--s-2);
}
.tp-cal-ai-split .tp-cal-ai-btn { margin-left: 0; }
.tp-cal-ai-split .tp-cal-ai-main {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: 1px solid rgba(255, 255, 255, 0.25);
}
.tp-cal-ai-split .tp-cal-ai-caret {
  padding: 0 10px;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  font-size: var(--fs-md);
}
.tp-cal-ai-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 260px;
  background: var(--bg-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
  z-index: 50;
  overflow: hidden;
  padding: 4px;
}
.tp-cal-ai-menu[hidden] { display: none; }
.tp-cal-ai-menu-item {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 10px 12px;
  background: transparent;
  border: 0;
  color: var(--fg-0);
  text-align: left;
  cursor: pointer;
  border-radius: calc(var(--r-md) - 2px);
  font-family: inherit;
}
.tp-cal-ai-menu-item:hover,
.tp-cal-ai-menu-item:focus-visible {
  background: color-mix(in srgb, var(--accent) 14%, var(--bg-2));
  outline: none;
}
.tp-cal-ai-menu-label {
  font-weight: 600;
  font-size: var(--fs-md);
}
.tp-cal-ai-menu-desc {
  font-size: var(--fs-sm);
  color: var(--fg-2);
}
/* #4 — Separador y acento del ítem "Replanificar resto de hoy" */
.tp-cal-ai-menu-sep {
  height: 1px;
  margin: 4px 8px;
  background: var(--border);
}
.tp-cal-ai-menu-item--today .tp-cal-ai-menu-label { color: var(--accent); }
.tp-cal-ai-menu-item--today:hover,
.tp-cal-ai-menu-item--today:focus-visible {
  background: color-mix(in srgb, var(--accent) 18%, var(--bg-2));
}

.tp-cal-granswitch {
  display: inline-flex;
  gap: var(--s-1);
  align-items: center;
  margin-left: auto;
}
.tp-cal-granlabel {
  color: var(--fg-2);
  font-size: var(--fs-sm);
  margin-right: var(--s-2);
}
.tp-cal-gbtn {
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-1);
  padding: 6px 12px;
  min-height: 36px;
  border-radius: var(--r-md);
  cursor: pointer;
  font-size: var(--fs-sm);
  font-weight: 600;
  font-family: inherit;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.tp-cal-gbtn:hover { color: var(--fg-0); }
.tp-cal-gbtn.active {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}

/* ─── Vista MES (grid 7×6) ───────────────────────────────────── */
.tp-cal-month {
  display: flex;
  flex-direction: column;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  /* Forzamos altura exacta (no max-height) para que el body con flex:1
     estire las 6 filas hasta ocupar toda la ventana disponible. Sin esto,
     el contenedor se quedaba en el alto mínimo del contenido (~530px) y
     dejaba un hueco enorme bajo la última fila en monitores grandes. */
  height: calc(100vh - 140px);
  height: calc(100dvh - 140px);
}
.tp-cal-month-head {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  background: var(--bg-2);
  border-bottom: 1px solid var(--border);
}
.tp-cal-month-head-cell {
  padding: var(--s-2);
  text-align: center;
  color: var(--fg-2);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.tp-cal-month-body {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  /* Sin un máximo: cada fila ocupa lo que le toque del espacio total del
     contenedor (6 filas → 1/6 cada una). Mantenemos el min de 80px para que
     en pantallas pequeñas no se aplaste. */
  grid-template-rows: repeat(6, minmax(80px, 1fr));
  gap: 1px;
  background: var(--border);
  flex: 1 1 auto;
  min-height: 0;
}
.tp-cal-month-cell {
  position: relative;
  background: var(--bg-1);
  padding: var(--s-2);
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-height: 0;
  overflow: hidden;
  cursor: pointer;
  transition: background 0.1s, box-shadow 0.1s;
}
.tp-cal-month-cell:hover { background: var(--bg-2); }
.tp-cal-month-cell:hover .tp-cal-month-add { opacity: 1; }
.tp-cal-month-cell:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  background: var(--bg-2);
}
.tp-cal-month-add {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: var(--accent-fg);
  border: none;
  border-radius: 50%;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s, transform 0.1s;
  z-index: 2;
  box-shadow: var(--shadow-sm);
}
.tp-cal-month-add:hover { transform: scale(1.1); }
.tp-cal-month-add:focus-visible { opacity: 1; outline: 2px solid var(--fg-0); outline-offset: 2px; }
@media (hover: none) {
  /* En táctil, el botón "+" siempre visible (no hay hover real). */
  .tp-cal-month-add { opacity: 0.85; }
}
.tp-cal-month-cell.off { background: var(--bg-0); }
.tp-cal-month-cell.off .tp-cal-month-date { color: var(--fg-3); }
.tp-cal-month-cell.today .tp-cal-month-date {
  background: var(--accent);
  color: var(--accent-fg);
}
.tp-cal-month-date {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: flex-start;
  min-width: 28px;
  height: 28px;
  padding: 0 8px;
  border-radius: var(--r-pill);
  color: var(--fg-1);
  font-size: var(--fs-sm);
  font-weight: 600;
  margin-bottom: var(--s-1);
}
.tp-cal-month-event {
  background: var(--accent);
  color: var(--accent-fg);
  padding: 3px 8px;
  border-radius: var(--r-sm);
  font-size: var(--fs-xs);
  font-weight: 500;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.4;
}
.tp-cal-month-event.is-block {
  background: var(--bg-3);
  color: var(--fg-0);
  border-left: 3px solid var(--accent);
}
/* Eventos "Todo el día" en la vista mes: ahora que la celda entera está
   tintada del color del all-day primario, el chip dentro funciona como
   etiqueta del evento. Estilo más compacto, con fondo translúcido para
   destacar sobre el background coloreado de la celda. */
.tp-cal-month-event.is-allday {
  display: flex;
  align-items: center;
  gap: 5px;
  width: 100%;
  padding: 3px 6px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--bg-0) 55%, transparent);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  color: var(--fg-0);
  font-weight: 600;
  font-size: var(--fs-xs);
}
.tp-cal-month-event-icon { font-size: 11px; line-height: 1; flex-shrink: 0; }
.tp-cal-month-event-text {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Celda del mes con all-day: la celda entera se tinta con el color del
   evento (lo hace JS vía cell.style.background) + un borde izquierdo
   grueso del mismo color (también JS). El box-shadow ya no es necesario;
   el color se ve directamente en TODA la celda. */
.tp-cal-month-cell.has-allday .tp-cal-month-date {
  /* Sobre fondo tintado, el número del día se ve más legible con un
     pequeño chip semitransparente detrás. */
  background: color-mix(in srgb, var(--bg-1) 70%, transparent);
  padding: 0 6px;
  border-radius: var(--r-sm);
}
.tp-cal-month-cell.has-allday.off {
  /* En la celda "fuera del mes" reducimos saturación para no competir con
     las del mes actual. */
  filter: brightness(0.85) saturate(0.7);
}

.tp-cal-month-event:hover { filter: brightness(1.1); }
.tp-cal-month-more {
  color: var(--fg-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  padding: 0 8px;
}

/* ─── Vista WEEK / DAY (eje temporal) ────────────────────────── */
.tp-cal-time {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  /* Altura = viewport - (topbar del calendario + márgenes del main). Sin FAB
     dejamos un margen pequeño para que el último píxel del grid no quede
     pegado al chrome del navegador. ~140px cubre topbar (h2 + nav + viewswitch +
     granswitch) + padding del main + borde. Usamos dvh para iOS Safari/Chrome
     que ajustan el viewport según la barra de URL dinámica. */
  max-height: calc(100vh - 140px);
  max-height: calc(100dvh - 140px);
  /* IMPORTANTE: block (no flex). El sticky de `.tp-cal-time-fixed` se ancla
     al scroll container más cercano que sea block-formatting. Con flex
     column, en algunos navegadores (y especialmente con una sola columna
     como la vista day) el sticky no se queda pegado correctamente arriba.
     Block evita esa rareza y funciona idéntico en day, week y month. */
  display: block;
  overflow-x: hidden;
  overflow-y: auto;
  /* Iso-padding-trim para que el border-radius no muestre rebordes blancos. */
  overscroll-behavior: contain;
}
.tp-cal-time-header,
.tp-cal-time-allday {
  display: grid;
  grid-template-columns: 64px repeat(var(--tp-days, 7), 1fr);
  background: var(--bg-2);
  border-bottom: 1px solid var(--border);
}
/* Wrapper sticky único para header + allday. Esto evita los problemas que
   tenía un doble sticky apilado en contenedores flex column. Al envolver
   ambos elementos en un solo nodo sticky garantizamos que viajan juntos
   y se quedan PEGADOS arriba sin moverse, sin importar cuánto scroll el
   usuario haga sobre el grid horario. */
.tp-cal-time-fixed {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bg-2);
  /* Sombra sutil al hacer scroll para indicar que el header está flotando
     sobre el contenido. No se ve hasta que hay scroll porque el bg-2 del
     grid coincide hasta que aparece contenido detrás. */
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}
.tp-cal-time-allday {
  /* Filas dinámicas según solapamientos. Cada lane mide 32px de alto
     más el padding del row (~6px). */
  grid-auto-rows: 34px;
  grid-template-rows: repeat(var(--tp-allday-rows, 1), 34px);
  padding: 4px 0;
  gap: 3px 0;
}

.tp-cal-time-axis-spacer {
  padding: var(--s-2);
  color: var(--fg-2);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
  border-right: 1px solid var(--border);
  display: flex;
  align-items: center;
}

.tp-cal-time-headcell {
  padding: var(--s-2);
  text-align: center;
  border-left: 1px solid var(--border);
  background: var(--bg-2);
}
.tp-cal-time-headcell:first-of-type { border-left: none; }
.tp-cal-time-weekday {
  color: var(--fg-2);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.tp-cal-time-daynum {
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--fg-0);
  margin-top: 2px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  border-radius: var(--r-pill);
}
.tp-cal-time-headcell.today .tp-cal-time-daynum {
  background: var(--accent);
  color: var(--accent-fg);
}

/* Ribbon "Todo el día" en vista day/week. Posicionado vía `grid-column:
   span N` por el JS — abarca exactamente las columnas de los días que
   cubre. CRÍTICO: `position: static` para anular el `position: absolute`
   heredado de `.tp-cal-time-event` (regla base para bloques horarios);
   sin esto, los ribbons salen del flujo del grid y se renderizan con
   ancho arbitrario sobre el contenedor entero. Idem `left/right: auto`. */
.tp-cal-time-event.allday {
  position: static;
  left: auto;
  right: auto;
  top: auto;
  height: 100%;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  margin: 0 2px;
  font-size: var(--fs-sm);
  font-weight: 600;
  border-left: 4px solid var(--accent);
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--accent) 20%, var(--bg-1));
  color: var(--fg-0);
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  overflow: hidden;
  min-width: 0;
}
.tp-cal-time-event.allday:hover {
  background: color-mix(in srgb, var(--accent) 30%, var(--bg-1));
}
.tp-cal-time-event-allday-icon {
  font-size: 14px;
  line-height: 1;
  flex-shrink: 0;
}
.tp-cal-time-event-allday-title {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Día reservado por un all-day: visualmente DESTACADO para que se note al
   vuelo que ese día está bloqueado. Capas:
    1) Fondo oscurecido para reducir saturación del resto del grid.
    2) Patrón de rayas diagonales en accent al 22% (antes 5%): claramente
       visible sin tapar las tareas que pueda haber.
    3) Borde lateral derecho/izquierdo más marcado.
   El resultado: el día se ve como "tachado en diagonal" — sin lugar a
   dudas que algo lo ocupa. */
.tp-cal-time-col.has-allday {
  background-color: color-mix(in srgb, var(--bg-1) 65%, #000);
  background-image: repeating-linear-gradient(
    -45deg,
    transparent 0,
    transparent 10px,
    color-mix(in srgb, var(--accent) 22%, transparent) 10px,
    color-mix(in srgb, var(--accent) 22%, transparent) 14px
  );
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent);
}
/* El bloque "ahora" y los slots-guía deben mantenerse visibles encima del
   patrón — z-index implícito ya los pone delante por orden DOM, pero
   reforzamos opacidad para evitar que se diluyan. */
.tp-cal-time-col.has-allday .tp-cal-time-slots { opacity: 0.6; }

.tp-cal-time-grid {
  position: relative;
  display: grid;
  grid-template-columns: 64px repeat(var(--tp-days, 7), 1fr);
  /* Forzamos la altura de la única fila implícita para que columnas y eje
     ocupen los 1440px completos. Sin esto, el row implícito puede medir
     solo lo que ocupan los DIVs absolute (que es 0) y las líneas de slot
     se cortan a partir de cierta hora. */
  grid-auto-rows: var(--tp-cal-total-height, 1440px);
  min-height: var(--tp-cal-total-height, 1440px);
}
.tp-cal-time-axis,
.tp-cal-time-col {
  min-height: var(--tp-cal-total-height, 1440px);
  height: 100%;
}

/* Eje izquierdo de horas */
.tp-cal-time-axis {
  position: relative;
  border-right: 1px solid var(--border);
  background: var(--bg-1);
}
.tp-cal-time-axis-label {
  position: absolute;
  left: 0; right: 0;
  text-align: right;
  padding-right: 8px;
  color: var(--fg-2);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  transform: translateY(-7px); /* alinear con la línea de slot superior */
}

/* Columna de día con eventos absolute */
.tp-cal-time-col {
  position: relative;
  border-left: 1px solid var(--border);
  background: var(--bg-1);
  overflow: hidden;
}
/* #4 — Capa de "horas de más energía". Puramente visual, detrás de eventos. */
.tp-cal-energy-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.tp-cal-energy-band {
  position: absolute;
  left: 0;
  right: 0;
  background: color-mix(in srgb, var(--green) 14%, transparent);
  border-left: 3px solid color-mix(in srgb, var(--green) 60%, transparent);
}
.tp-cal-time-col:first-of-type { border-left: none; }
.tp-cal-time-col.today { background: var(--accent-soft); }

/* Líneas guía con background-gradient sobre un único nodo .tp-cal-time-slots.
   Esto rinde mucho mejor que decenas de DIVs absolute y se ajusta a la
   granularidad sin re-render. La hora completa es línea sólida; la media
   hora (cuando granularity=30) es línea más sutil dashed. */
.tp-cal-time-slots {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent calc(var(--tp-cal-hour-height, 60px) - 1px),
      var(--border-soft) calc(var(--tp-cal-hour-height, 60px) - 1px),
      var(--border-soft) var(--tp-cal-hour-height, 60px)
    );
}
.tp-cal-time-slots[data-granularity="30"] {
  background:
    /* media hora: dashed sutil */
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent calc(var(--tp-cal-hour-height, 60px) / 2 - 1px),
      var(--border-soft) calc(var(--tp-cal-hour-height, 60px) / 2 - 1px),
      transparent var(--tp-cal-hour-height, 60px)
    ),
    /* hora completa: sólida */
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent calc(var(--tp-cal-hour-height, 60px) - 1px),
      var(--border-soft) calc(var(--tp-cal-hour-height, 60px) - 1px),
      var(--border-soft) var(--tp-cal-hour-height, 60px)
    );
}
.tp-cal-time-slots[data-granularity="15"] {
  background:
    /* cuarto de hora */
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent calc(var(--tp-cal-hour-height, 60px) / 4 - 1px),
      color-mix(in srgb, var(--border-soft) 50%, transparent) calc(var(--tp-cal-hour-height, 60px) / 4 - 1px),
      transparent calc(var(--tp-cal-hour-height, 60px) / 4)
    ),
    /* media hora */
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent calc(var(--tp-cal-hour-height, 60px) / 2 - 1px),
      var(--border-soft) calc(var(--tp-cal-hour-height, 60px) / 2 - 1px),
      transparent calc(var(--tp-cal-hour-height, 60px) / 2)
    ),
    /* hora completa */
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent calc(var(--tp-cal-hour-height, 60px) - 1px),
      var(--border-soft) calc(var(--tp-cal-hour-height, 60px) - 1px),
      var(--border-soft) var(--tp-cal-hour-height, 60px)
    );
}

/* Indicador de drop: línea horizontal con label de hora. */
.tp-cal-time-drop-line {
  position: absolute;
  left: 0; right: 0;
  height: 0;
  border-top: 2px dashed var(--accent);
  z-index: 4;
  pointer-events: none;
  display: flex;
  justify-content: flex-start;
  padding-left: 6px;
}
.tp-cal-time-drop-line::before {
  content: '';
  position: absolute;
  left: -6px; top: -6px;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--accent);
}
.tp-cal-time-drop-line {
  color: var(--accent);
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(to right, var(--accent-soft), transparent 40%);
  margin-top: -1px;
}

.tp-cal-time-event {
  position: absolute;
  left: 4px; right: 4px;
  background: var(--accent);
  color: var(--accent-fg);
  border-left: 3px solid var(--accent-strong);
  padding: 6px 8px 4px;
  border-radius: var(--r-sm);
  font-size: var(--fs-xs);
  cursor: grab;
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: filter 0.15s, transform 0.1s, box-shadow 0.15s;
  z-index: 1;
  user-select: none;
}
.tp-cal-time-event:hover {
  filter: brightness(1.1);
  z-index: 2;
  box-shadow: var(--shadow-md);
}
.tp-cal-time-event:active { cursor: grabbing; }
.tp-cal-time-event.is-dragging {
  opacity: 0.4;
  transform: scale(0.98);
  cursor: grabbing;
}
.tp-cal-time-event.is-block {
  background: var(--bg-3);
  color: var(--fg-0);
  border-left-color: var(--accent);
}
.tp-cal-time-event.is-blockout {
  background: repeating-linear-gradient(
    -45deg,
    rgba(120, 113, 108, 0.18),
    rgba(120, 113, 108, 0.18) 4px,
    rgba(120, 113, 108, 0.08) 4px,
    rgba(120, 113, 108, 0.08) 8px
  );
  border-left: 3px solid #a8a29e;
  color: var(--fg-0);
}
.tp-cal-time-event.is-blockout .tp-cal-time-event-title {
  font-style: italic;
  color: var(--fg-0);
}
.tp-cal-month-event.is-blockout {
  background: rgba(120, 113, 108, 0.2);
  border-left: 3px solid #a8a29e;
  color: var(--fg-0);
  font-style: italic;
}

/* Popover de elección al clicar hueco vacío */
.tp-cal-slot-menu {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9200;
  display: flex;
  gap: 2px;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  padding: 4px;
  animation: tp-modal-pop 0.15s ease-out;
}
.tp-cal-slot-menu--fixed {
  position: fixed;
  left: auto;
  /* iOS Safari REAL (no el simulador de Chrome, que usa Blink) compone el
     calendario en capas GPU propias (`.tp-cal-time-now` con will-change y
     `.tp-main` con scroll de momento). Un position:fixed SIN capa propia se
     pinta por debajo de esas capas IGNORANDO el z-index → el popover salía
     "detrás del calendario". translateZ(0) lo promueve a su propia capa, donde
     el z-index sí se respeta y queda por encima. No desplaza en X/Y. */
  transform: translateZ(0);
}
.tp-cal-slot-menu button {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: 8px 14px;
  border: none;
  background: transparent;
  color: var(--fg-0);
  font-size: var(--fs-sm);
  font-weight: 500;
  border-radius: var(--r-sm);
  cursor: pointer;
  white-space: nowrap;
  min-height: var(--tap);
}
.tp-cal-slot-menu button:hover {
  background: var(--bg-2);
}
.tp-cal-slot-menu button span {
  font-size: var(--fs-md);
}
/* Menú de la vista mes: posicionado relative al cell, no absolute a eje temporal. */
.tp-cal-month-slot-menu {
  position: absolute;
  bottom: 4px;
  left: 50%;
  transform: translateX(-50%);
  top: auto;
}
/* Task picker modal */
.tp-task-picker-search {
  width: 100%;
  margin-bottom: var(--s-2);
}
.tp-task-picker-time {
  display: flex;
  gap: var(--s-3);
  margin-bottom: var(--s-2);
}
.tp-task-picker-time label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: var(--fs-sm);
  color: var(--fg-2);
  flex: 1;
}
.tp-task-picker-time input[type="time"] {
  width: 100%;
}
.tp-task-picker-list {
  list-style: none;
  padding: 0;
  margin: 0;
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.tp-task-picker-item {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.1s;
  min-height: var(--tap);
}
.tp-task-picker-item:last-child { border-bottom: none; }
.tp-task-picker-item:hover, .tp-task-picker-item:focus-visible {
  background: var(--bg-2);
  outline: none;
}
.tp-task-picker-item.is-loading {
  opacity: 0.5;
  pointer-events: none;
}
.tp-task-picker-item-title {
  flex: 1;
  font-weight: 500;
  color: var(--fg-0);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tp-task-picker-item-due,
.tp-task-picker-item-est {
  font-size: var(--fs-xs);
  color: var(--fg-2);
  white-space: nowrap;
}
.tp-task-picker-item-prio {
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--danger);
}
/* Bloque generado por IA: degradado lila con borde animable y badge ✨ via texto. */
.tp-cal-time-event.is-block.is-ai {
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.22) 0%, rgba(168, 85, 247, 0.18) 100%);
  border-left: 3px solid #a855f7;
  box-shadow: inset 0 0 0 1px rgba(168, 85, 247, 0.25);
}
.tp-cal-time-event.is-block.is-ai .tp-cal-time-event-title {
  color: var(--fg-0);
}
/* Mes: misma marca, más compacta. */
.tp-cal-month-event.is-block.is-ai {
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.28) 0%, rgba(168, 85, 247, 0.22) 100%);
  border-left: 3px solid #a855f7;
}
/* Cluster de acciones dentro de un bloque del calendario (timer ▶, ✓ done…).
   SIEMPRE visible (no requiere hover) — clave para descubribilidad y para
   tactil. Posicionado en top-right del bloque con un pelín de margen para
   no tocar el borde. Cada botón es 26×26 (tap target cómodo, accesible),
   con buen contraste sobre cualquier fondo de bloque gracias al borde
   coloreado + fondo casi opaco. */
.tp-cal-time-event-actions {
  position: absolute;
  top: 4px;
  right: 4px;
  display: flex;
  gap: 4px;
  z-index: 2;
  /* Opacidad media por defecto para no abrumar visualmente; al hover sobre
     el bloque sube a 1. Sigue siendo perfectamente visible al 0.92, no se
     "esconde". */
  opacity: 0.92;
  transition: opacity 0.15s;
}
.tp-cal-time-event:hover .tp-cal-time-event-actions { opacity: 1; }
@media (hover: none) {
  .tp-cal-time-event-actions { opacity: 1; }
}
.tp-cal-time-event-btn {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--bg-1);
  color: var(--fg-0);
  border: 1.5px solid var(--border-strong);
  cursor: pointer;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: background 0.12s, transform 0.1s, color 0.12s, box-shadow 0.12s;
}
.tp-cal-time-event-btn:hover {
  transform: scale(1.08);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
}
.tp-cal-time-event-btn:active { transform: scale(0.92); }
.tp-cal-time-event-btn.is-loading { opacity: 0.6; cursor: progress; }
/* Variantes por tipo: ▶ timer en accent, ✓ done en verde. Fondo sólido
   pleno para que se vea bien sobre bloques con cualquier color. */
.tp-cal-time-event-btn-timer {
  color: #fff;
  border-color: var(--accent);
  background: var(--accent);
}
.tp-cal-time-event-btn-timer:hover { background: var(--accent-strong, var(--accent)); }
/* Variante "parar": rojo para indicar visualmente que es la acción
   destructiva del estado actual (detener un timer en marcha). */
.tp-cal-time-event-btn-timer-stop {
  color: #fff;
  border-color: var(--red, #ef4444);
  background: var(--red, #ef4444);
}
.tp-cal-time-event-btn-timer-stop:hover { filter: brightness(1.1); }
.tp-cal-time-event-btn-done {
  color: #fff;
  border-color: var(--green, #22c55e);
  background: var(--green, #22c55e);
}
.tp-cal-time-event-btn-done:hover { background: #15803d; }

/* Bloques cortos (<45 min): el cluster de botones tapa casi todo. JS añade
   la clase `is-short` y aquí compactamos para que sigan accesibles. */
.tp-cal-time-event.is-short .tp-cal-time-event-btn {
  width: 22px;
  height: 22px;
  font-size: 11px;
}
.tp-cal-time-event.is-short .tp-cal-time-event-actions { gap: 3px; }

/* Handles de resize en los bordes superior e inferior del bloque. Anchos
   completos del bloque, 6px de alto. Cursor ns-resize al hover. Una linita
   visual sutil en el centro al hover indica al usuario que ahí se puede
   agarrar (como las pestañas de Windows). En touch no muestra cursor pero
   sigue funcionando porque mousedown se intercepta vía pointer events. */
.tp-cal-time-event-resize {
  position: absolute;
  left: 0;
  right: 0;
  height: 6px;
  cursor: ns-resize;
  z-index: 3;
  /* Sin background hasta el hover: no contamina el render del bloque. */
}
.tp-cal-time-event-resize-top { top: 0; }
.tp-cal-time-event-resize-bottom { bottom: 0; }
.tp-cal-time-event:hover .tp-cal-time-event-resize::after {
  content: '';
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: 32px;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.6);
}
.tp-cal-time-event:hover .tp-cal-time-event-resize-top::after { top: 1px; }
.tp-cal-time-event:hover .tp-cal-time-event-resize-bottom::after { bottom: 1px; }
/* Durante el resize: bloqueamos pointer-events del resto de bloques para
   que el cursor no salte si pasa por encima de otro. */
.tp-cal-time-event.is-resizing { z-index: 4; }
.tp-cal-time-grid:has(.tp-cal-time-event.is-resizing) .tp-cal-time-event:not(.is-resizing) {
  pointer-events: none;
}
.tp-cal-time-event-title {
  font-weight: 600;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
  line-height: 1.3;
}
.tp-cal-time-event-time {
  font-size: 11px;
  opacity: 0.85;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

/* Overlay de progreso: oscurece el bloque de ARRIBA hacia ABAJO según el
   tiempo dedicado a la tarea en Clockify (height en %, ver applyBlockProgress
   en calendar.js). El borde inferior marca la línea de avance. Va detrás del
   texto (z-index 0; título/hora suben a z-index 1) y no captura el puntero. */
.tp-cal-time-event-progress {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 0;
  background: rgba(0, 0, 0, 0.42);
  border-bottom: 1.5px solid rgba(0, 0, 0, 0.6);
  z-index: 0;
  pointer-events: none;
  transition: height 0.6s linear;
}
.tp-cal-time-event.has-progress .tp-cal-time-event-title,
.tp-cal-time-event.has-progress .tp-cal-time-event-time {
  position: relative;
  z-index: 1;
}
/* Bloque cuyo tiempo dedicado ya iguala o supera su duración. */
.tp-cal-time-event.is-complete {
  border-left-color: #22c55e;
}

/* ── Widget "Progreso" de tarea (popup quick-actions + vista individual) ──
   Tres tiempos (programado/estimado/dedicado) + barra de avance dedicado→estimado.
   Ver ui/TaskProgress.js. */
.tp-task-progress {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
/* Fila de acciones bajo el widget de progreso en la vista de tarea:
   iniciar/continuar/parar el timer y completar/reabrir sin bajar a Estado. */
.tp-task-progress-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-3);
}
.tp-task-progress-actions .tp-btn {
  flex: 1 1 auto;
  margin: 0;
}
.tp-task-progress-barline {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.tp-task-progress-bar {
  flex: 1;
  height: 10px;
  background: var(--bg-3);
  border-radius: 999px;
  overflow: hidden;
}
.tp-task-progress-fill {
  height: 100%;
  width: 0;
  background: var(--accent);
  border-radius: 999px;
  transition: width 0.6s linear, background 0.2s;
}
.tp-task-progress.is-over .tp-task-progress-fill {
  background: var(--red);
}
.tp-task-progress-pct {
  font-size: var(--fs-sm);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--fg-1);
  min-width: 3.2em;
  text-align: right;
}
.tp-task-progress.is-over .tp-task-progress-pct {
  color: var(--red);
}
.tp-task-progress-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
.tp-task-progress-chip {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 0;
  min-width: 90px;
  padding: var(--s-2);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}
.tp-task-progress-chip-label {
  font-size: var(--fs-xs);
  color: var(--fg-2);
}
.tp-task-progress-chip-val {
  font-size: var(--fs-md);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--fg-0);
}

/* Feedback de drop target en columnas de week/day y en celdas de mes. */
.tp-cal-time-col.drop-target { background: var(--accent-soft); }
.tp-cal-month-cell.drop-target {
  outline: 2px dashed var(--accent);
  outline-offset: -2px;
  background: var(--accent-soft);
}
.tp-cal-month-event {
  cursor: grab;
  user-select: none;
}
.tp-cal-month-event:active { cursor: grabbing; }
.tp-cal-month-event.is-dragging { opacity: 0.4; }

/* Durante un drag activo en el grid temporal: el evento que NO se está
   arrastrando ignora eventos de puntero, así el dragover/drop llega
   limpiamente a la columna. El evento siendo arrastrado conserva sus
   eventos porque sigue siendo el "source" del drag. */
.tp-cal-time-grid.is-dragging-active .tp-cal-time-event:not(.is-dragging) {
  pointer-events: none;
}
/* Idéntica regla para la vista mes. */
.tp-cal-month-body.is-dragging-active .tp-cal-month-event:not(.is-dragging) {
  pointer-events: none;
}

.tp-cal-time-now {
  position: absolute;
  left: 0; right: 0;
  top: 0;
  height: 2px;
  background: var(--red);
  z-index: 3;
  pointer-events: none;
  will-change: transform;
  /* La posición se recalcula en vivo (loop consolidado en calendar.js) con
     translateY; animar transform (no `top`) mantiene el avance fluido sin
     disparar layout/repaint en cada frame. */
  transition: transform 0.6s linear;
}
.tp-cal-time-now::before {
  content: '';
  position: absolute;
  left: -6px; top: -4px;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--red);
}

@media (max-width: 768px) {
  .tp-cal-topbar { gap: var(--s-2); }
  .tp-cal-granswitch { margin-left: 0; width: 100%; justify-content: flex-start; }
  .tp-cal-month-body { grid-template-rows: repeat(6, minmax(60px, 1fr)); }
  .tp-cal-month-head-cell { padding: 6px 2px; font-size: 10px; }
  .tp-cal-month-event { font-size: 10px; padding: 2px 6px; }
  /* Restamos lo que ocupan topbar (~140px), bottom-nav (~64px + safe-area),
     hamburger sticky y márgenes. Sin esto el calendario se quedaba con poca
     altura y el bottom-nav tapaba las últimas horas. */
  .tp-cal-time {
    max-height: calc(100dvh - 220px - env(safe-area-inset-top, 0) - env(safe-area-inset-bottom, 0));
  }
  .tp-cal-time-header,
  .tp-cal-time-allday,
  .tp-cal-time-grid {
    grid-template-columns: 44px repeat(var(--tp-days, 7), minmax(60px, 1fr));
  }
  .tp-cal-time-axis-spacer { padding: 4px; font-size: 10px; }
  .tp-cal-time-daynum { font-size: var(--fs-md); width: 26px; height: 26px; }
  .tp-cal-time-axis-label { padding-right: 4px; font-size: 10px; }
  /* "Planificar con IA" prominente en mobile — antes se ocultaba el texto y
     quedaba un cuadrado morado pequeño irreconocible. Ahora el botón ocupa
     ancho disponible con el texto claro. */
  .tp-cal-ai-split {
    margin-left: 0;
    flex: 1 1 auto;
    min-width: 180px;
  }
  .tp-cal-ai-split .tp-cal-ai-main {
    flex: 1 1 auto;
    justify-content: center;
    padding: 0 var(--s-3);
    height: var(--tap);
    min-height: var(--tap);
    font-size: var(--fs-md);
  }
  .tp-cal-ai-icon { font-size: var(--fs-lg); }
  .tp-cal-viewswitch { order: 10; width: 100%; justify-content: center; }
  .tp-cal-vbtn { padding: 6px 8px; font-size: var(--fs-sm); }
  .tp-cal-capacity-badge { margin-left: 0; }
  /* Solo el popover de la vista MES (absolute, dentro de la celda) se reajusta
     a la izquierda en móvil. El variante --fixed conserva su translateZ(0)
     (capa propia) para no volver a quedar detrás del calendario en iOS. */
  .tp-cal-slot-menu:not(.tp-cal-slot-menu--fixed) { left: 4px; transform: none; }
}
@media (max-width: 540px) {
  /* ── Topbar compacto: 2 filas ──
     Fila 1: título compacto + nav + IA + badges (inline, no wrap)
     Fila 2: view switcher (llena el ancho)
     El selector de franjas se oculta para liberar espacio. */
  .tp-cal-topbar {
    gap: 6px;
    margin-bottom: var(--s-2);
  }
  .tp-cal-topbar h2 {
    font-size: var(--fs-sm);
    flex: 0 0 auto;
    width: auto;
    white-space: nowrap;
  }
  .tp-cal-granswitch { display: none; }
  .tp-cal-nav { gap: 4px; }
  .tp-cal-navbtn {
    min-width: 32px;
    height: 36px;
    padding: 0 6px;
    font-size: var(--fs-sm);
  }
  /* ≤540px: el botón IA mantiene su altura cómoda (44px) y conserva el texto
     completo "Planificar con IA". Es la acción más importante del calendario
     en mobile, debe sentirse como tal. */
  .tp-cal-ai-split {
    flex: 1 1 100%;
    order: 5;
    min-width: 0;
    margin-top: var(--s-1);
  }
  .tp-cal-ai-split .tp-cal-ai-main {
    flex: 1 1 auto;
    height: var(--tap);
    min-height: var(--tap);
    font-size: var(--fs-md);
    padding: 0 var(--s-3);
  }
  .tp-cal-ai-split .tp-cal-ai-caret {
    height: var(--tap);
    min-height: var(--tap);
    padding: 0 var(--s-3);
    font-size: var(--fs-lg);
  }
  .tp-cal-capacity-badge {
    height: 32px;
    padding: 0 8px;
    font-size: var(--fs-xs);
  }
  /* El ocultado del pill de readiness Oura en móvil NO va aquí: la regla base
     .tp-cal-readiness (más abajo en el fichero) fija display:inline-flex y, con
     igual especificidad, ganaría por orden de cascada. El override efectivo
     está justo DESPUÉS de la regla base. */
  .tp-cal-viewswitch {
    order: 10;
    width: 100%;
    justify-content: center;
  }
  .tp-cal-vbtn {
    flex: 1;
    text-align: center;
    padding: 6px 4px;
    font-size: var(--fs-xs);
  }
  .tp-cal-vbtn-compact { display: inline-flex; }
  /* Eje temporal estrecho */
  .tp-cal-time-header,
  .tp-cal-time-allday,
  .tp-cal-time-grid {
    grid-template-columns: 32px repeat(var(--tp-days, 7), minmax(40px, 1fr));
  }
  .tp-cal-time-axis-label { font-size: 9px; padding-right: 2px; }
  .tp-cal-time-axis-spacer { padding: 2px; font-size: 9px; }
  .tp-cal-time-event { font-size: 10px; padding: 2px 3px; }
  .tp-cal-time-event-title { font-size: 10px; }
  .tp-cal-time-event-time { font-size: 9px; }
  .tp-cal-time-event-actions { top: 2px; right: 2px; gap: 2px; }
  .tp-cal-time-event-btn { width: 22px; height: 22px; font-size: 10px; }
  .tp-cal-time-headcell { padding: 4px 2px; }
  .tp-cal-time-weekday { font-size: 9px; }
  .tp-cal-time-daynum { font-size: var(--fs-sm); width: 24px; height: 24px; }
  /* Scroll area ocupa todo el alto disponible (dejando hueco bottom-nav).
     Usamos 100dvh para que Safari/Chrome iOS ajusten al área visible real
     según la barra de URL se muestre/oculte. */
  .tp-cal-time { max-height: calc(100dvh - 210px - env(safe-area-inset-top, 0) - env(safe-area-inset-bottom, 0)); }
  /* Bloques y eventos mes */
  .tp-cal-month-cell { padding: 2px; gap: 2px; }
  .tp-cal-month-date { font-size: var(--fs-xs); min-width: 22px; height: 22px; }
  .tp-cal-month-add { width: 22px; height: 22px; font-size: 12px; }
  .tp-cal-month-event { font-size: 9px; padding: 1px 4px; }
}
@media (max-width: 380px) {
  .tp-cal-topbar h2 { font-size: var(--fs-xs); }
  .tp-cal-capacity-badge > span:first-child { display: none; }
  .tp-cal-navbtn { min-width: 28px; padding: 0 4px; }
}

/* ─── Empty state ────────────────────────────────────────────── */

/* ─── Estadísticas (/app/stats) ──────────────────────────────── */
.tp-stats-range {
  width: 120px;
  margin-left: auto;
}
.tp-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--s-2);
  margin-bottom: var(--s-3);
}
.tp-stats-metric {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-2) var(--s-3);
}
.tp-stats-metric-label {
  color: var(--fg-2);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.tp-stats-metric-value {
  color: var(--fg-0);
  font-size: var(--fs-xl);
  font-weight: 700;
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}
.tp-stats-subtitle {
  margin: var(--s-4) 0 var(--s-2);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg-0);
}
.tp-stats-2cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
  gap: var(--s-3);
}
.tp-stats-bars {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-3);
}
.tp-stats-bars-title {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--fg-1);
  margin-bottom: var(--s-2);
}
.tp-stats-bars-svg .tp-stats-bars-tick {
  fill: var(--fg-2);
  font-size: 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.tp-stats-axis-label {
  fill: var(--fg-2);
  font-size: 11px;
}
.tp-stats-scatter {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-3);
}
.tp-stats-sparkline {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-3);
}
.tp-stats-top-list {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}
.tp-stats-top-row {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) 3fr auto;
  gap: var(--s-3);
  align-items: center;
}
.tp-stats-top-name {
  font-size: var(--fs-sm);
  color: var(--fg-0);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tp-stats-top-bar {
  height: 8px;
  background: var(--bg-3);
  border-radius: 4px;
  overflow: hidden;
}
.tp-stats-top-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #7c3aed, #a855f7);
}
.tp-stats-top-value {
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  color: var(--fg-1);
  min-width: 60px;
  text-align: right;
}
.tp-stats-correlations {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-3);
}
.tp-corr-pill {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-2) var(--s-3);
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 220px;
}
.tp-corr-pill span { color: var(--fg-2); font-size: var(--fs-sm); }
.tp-corr-pill strong { font-size: var(--fs-lg); font-variant-numeric: tabular-nums; }
.tp-corr-pill.pos strong  { color: var(--green); }
.tp-corr-pill.neg strong  { color: var(--red); }
.tp-corr-pill.weak strong { color: var(--yellow); }
.tp-corr-pill.na strong   { color: var(--fg-2); font-style: italic; font-size: var(--fs-sm); }

.tp-stats-ai-output {
  margin-top: var(--s-2);
}
.tp-stats-ai-md {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-3) var(--s-4);
  line-height: 1.6;
  color: var(--fg-0);
}
.tp-stats-ai-md h2, .tp-stats-ai-md h3, .tp-stats-ai-md h4 {
  margin: var(--s-3) 0 var(--s-1);
  font-weight: 600;
  color: var(--fg-0);
}
.tp-stats-ai-md h2:first-child, .tp-stats-ai-md h3:first-child { margin-top: 0; }
.tp-stats-ai-md p { margin: 0 0 var(--s-2); }
.tp-stats-ai-md ul { margin: 0 0 var(--s-2); padding-left: var(--s-5); }
.tp-stats-ai-md li { margin-bottom: 4px; }
.tp-stats-ai-md code {
  background: var(--bg-3);
  padding: 1px 6px;
  border-radius: 3px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
}

/* ─── CRON: log de ejecuciones en /app/settings ───────────────── */
.tp-cron-log-title {
  margin: var(--s-5) 0 var(--s-2);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg-0);
}
.tp-cron-log { overflow-x: auto; }
.tp-cron-table th, .tp-cron-table td { vertical-align: top; }
.tp-cron-tasks {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: var(--fs-sm);
}
.tp-cron-task {
  display: flex;
  justify-content: space-between;
  gap: var(--s-2);
  color: var(--fg-2);
  padding: 2px 0;
  border-radius: 3px;
}
.tp-cron-task.has-work { color: var(--fg-0); }
.tp-cron-task.has-error { color: var(--red); }
.tp-cron-task-label { white-space: nowrap; }
.tp-cron-task-value {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
}

/* ─── Database (vista /app/database) ──────────────────────────── */
.tp-db-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--s-3);
}
.tp-db-metric {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-3);
}
.tp-db-metric-label {
  color: var(--fg-2);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.tp-db-metric-value {
  color: var(--fg-0);
  font-size: var(--fs-xl);
  font-weight: 700;
  margin-top: var(--s-1);
  font-variant-numeric: tabular-nums;
}
.tp-db-metric-value.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-md);
  word-break: break-all;
}
.tp-db-table th, .tp-db-table td { vertical-align: middle; }
.tp-db-table td.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-sm);
}
.tp-db-bar {
  height: 8px;
  width: 100%;
  min-width: 80px;
  background: var(--bg-3);
  border-radius: 4px;
  overflow: hidden;
}
.tp-db-bar-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #7c3aed, #a855f7);
  transition: width 0.3s ease;
}
/* Limpieza del historial de IA */
.tp-db-purge-row {
  display: flex;
  align-items: flex-end;
  gap: var(--s-3);
  flex-wrap: wrap;
}
.tp-db-purge-field { display: flex; flex-direction: column; min-width: 0; }
.tp-db-purge-field .tp-input { width: 160px; max-width: 100%; margin-top: 6px; }

/* ─── Política de seguridad de login ──────────────────────────── */
.tp-security-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--s-3);
}
.tp-security-field { display: flex; flex-direction: column; gap: var(--s-1); }
.tp-security-field .tp-input { max-width: 140px; font-variant-numeric: tabular-nums; }
.tp-security-hint { color: var(--fg-2); font-size: var(--fs-sm); margin: 0; line-height: 1.4; }
.tp-security-actions {
  grid-column: 1 / -1;
  display: flex;
  justify-content: flex-end;
  margin-top: var(--s-2);
}

/* ─── Card "Planificación" en task-detail ────────────────────── */
.tp-plan-list {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
}
.tp-plan-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--r-md);
  padding: var(--s-2) var(--s-3);
}
.tp-plan-row.is-ai { border-left-color: #a855f7; background: color-mix(in srgb, var(--bg-2) 88%, #a855f7); }
.tp-plan-row-main { display: flex; flex-direction: column; gap: 2px; }
.tp-plan-row-line { font-variant-numeric: tabular-nums; }
.tp-plan-row-dur { color: var(--fg-2); font-size: var(--fs-sm); }
.tp-plan-row-meta { display: flex; gap: var(--s-2); align-items: center; font-size: var(--fs-sm); color: var(--fg-2); }
.tp-plan-row-label { font-style: italic; }
.tp-plan-row-actions .tp-btn { padding: 4px 10px; min-height: 0; font-size: var(--fs-sm); }
.tp-plan-add {
  background: var(--bg-3);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-md);
  padding: var(--s-2) var(--s-3);
}
.tp-plan-add summary {
  cursor: pointer;
  color: var(--fg-1);
  font-weight: 600;
  list-style: none;
}
.tp-plan-add summary::-webkit-details-marker { display: none; }
.tp-plan-add[open] summary { margin-bottom: var(--s-2); }
.tp-plan-add-form {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-2) var(--s-3);
  align-items: center;
}
.tp-plan-add-form .tp-btn { grid-column: 1 / -1; justify-self: end; }
@media (max-width: 480px) {
  .tp-plan-row { flex-direction: column; align-items: flex-start; }
}

/* ─── Popup de acciones rápidas (doble click en bloque) ──────── */
.tp-quick-actions { display: flex; flex-direction: column; gap: var(--s-3); }
.tp-quick-actions-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  color: var(--fg-2);
  font-size: var(--fs-sm);
  align-items: center;
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--border);
}
.tp-quick-actions-meta .prio { font-weight: 700; }
.tp-quick-actions-list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-2);
}
.tp-quick-action-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: var(--s-4) var(--s-2);
  border-radius: var(--r-md);
  border: 1.5px solid var(--border-strong);
  background: var(--bg-2);
  color: var(--fg-0);
  cursor: pointer;
  font-family: inherit;
  font-size: var(--fs-sm);
  min-height: 80px;
  transition: background 0.15s, transform 0.1s, border-color 0.15s;
}
.tp-quick-action-btn:hover { background: var(--bg-3); border-color: var(--accent); transform: translateY(-1px); }
.tp-quick-action-btn:active { transform: translateY(0); }
.tp-quick-action-btn:disabled { opacity: 0.55; cursor: progress; }
.tp-quick-action-btn-icon { font-size: 24px; line-height: 1; }
.tp-quick-action-btn-label { font-weight: 600; }

.tp-quick-action-btn-timer { border-color: var(--accent); color: var(--accent); }
.tp-quick-action-btn-timer:hover { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
.tp-quick-action-btn-timer-stop { border-color: var(--red, #ef4444); color: var(--red, #ef4444); }
.tp-quick-action-btn-timer-stop:hover { background: var(--red, #ef4444); color: #fff; border-color: var(--red, #ef4444); }
.tp-quick-action-btn-done  { border-color: var(--green, #22c55e); color: var(--green, #22c55e); }
.tp-quick-action-btn-done:hover  { background: var(--green, #22c55e); color: #fff; border-color: var(--green, #22c55e); }
.tp-quick-action-btn-edit  { /* tono neutro: usa los defaults */ }

/* Panel de Planificación dentro del popup de acciones rápidas. Separado del
   cluster de botones por una línea, reutiliza los estilos .tp-plan-* del
   detalle de tarea. */
.tp-quick-actions-plan {
  border-top: 1px solid var(--border);
  padding-top: var(--s-3);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.tp-quick-actions-plan-title {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-2);
}
.tp-quick-actions-plan-hint {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--fg-2);
}

/* En mobile angosto los tres botones se ponen en columna para tener más
   tap target. El umbral 380px cubre teléfonos pequeños sin obligar a
   los normales (~390-430px) a una columna. */
@media (max-width: 380px) {
  .tp-quick-actions-list { grid-template-columns: 1fr; }
  .tp-quick-action-btn { flex-direction: row; min-height: 56px; padding: var(--s-2) var(--s-3); }
  .tp-quick-action-btn-icon { font-size: 18px; }
}

/* ─── Banner del timer activo de Clockify ────────────────────── */
.tp-clockify-banner {
  position: fixed;
  bottom: 12px;
  left: 12px;
  background: var(--bg-2);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 8px 12px;
  z-index: 9000;
  display: flex;
  align-items: center;
  gap: 10px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  max-width: 360px;
  font-size: 13px;
}
@media (max-width: 768px) {
  /* En móvil hay bottom-nav fija; levantamos el banner por encima. */
  .tp-clockify-banner {
    bottom: calc(64px + env(safe-area-inset-bottom, 0) + 8px);
  }
}

/* ─── #5 Replan reactivo: banner de deriva del plan ──────────────── */
.tp-reactive-replan {
  position: fixed;
  bottom: 12px;
  right: 12px;
  z-index: 9100; /* por encima del banner de Clockify */
  display: flex;
  align-items: flex-start;
  gap: 10px;
  max-width: 380px;
  padding: 12px 14px;
  background: var(--bg-1);
  border: 1px solid var(--accent);
  border-left: 4px solid var(--accent);
  border-radius: var(--r-md, 10px);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
  animation: tp-reactive-in 0.25s ease-out;
}
@keyframes tp-reactive-in {
  from { transform: translateY(10px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}
.tp-reactive-replan-icon { font-size: 18px; line-height: 1.3; }
.tp-reactive-replan-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.tp-reactive-replan-text strong { font-size: var(--fs-sm); color: var(--accent); }
.tp-reactive-replan-text span { font-size: var(--fs-xs); color: var(--fg-1); }
.tp-reactive-replan-actions {
  display: flex;
  gap: 6px;
  margin-top: 8px;
  flex-basis: 100%;
  justify-content: flex-end;
}
.tp-reactive-replan-actions .tp-btn { padding: 6px 12px; font-size: var(--fs-xs); min-height: var(--tap); }
@media (max-width: 768px) {
  .tp-reactive-replan {
    left: 12px;
    right: 12px;
    max-width: none;
    bottom: calc(64px + env(safe-area-inset-bottom, 0) + 8px);
  }
}

/* ─── Editor de presupuesto IA y barra de gasto ───────────────── */
.tp-budget-ctrl {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}
.tp-budget-prefix, .tp-budget-suffix {
  color: var(--fg-2);
  font-size: var(--fs-sm);
}
.tp-budget-input {
  width: 110px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.tp-budget-used {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 220px;
}
.tp-budget-bar {
  height: 8px;
  background: var(--bg-3);
  border-radius: 4px;
  overflow: hidden;
}
.tp-budget-bar-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #22c55e, #a855f7);
  transition: width 0.3s ease;
}
.tp-budget-bar-fill.warn { background: linear-gradient(90deg, #f59e0b, #ef4444); }
.tp-budget-bar-fill.stop { background: var(--red); }

/* ─── Selección múltiple en listados ──────────────────────────── */
.tp-sel-toggle.active {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}

/* Checkbox extra a la izquierda de cada row. Solo visible cuando el contenedor
   está en modo selección (.tp-sel-active). Antes del checkbox de completar
   para diferenciarlos: aquí es CUADRADO (selección) vs el de completar que
   es REDONDO (toggle de estado). Diferencia visual y semántica. */
.tp-sel-checkbox {
  width: 22px;
  height: 22px;
  border-radius: 5px;
  border: 2px solid var(--border-strong);
  background: var(--bg-2);
  display: none;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
  position: relative;
}
.tp-sel-active .tp-sel-checkbox { display: inline-flex; }
.tp-sel-checkbox:hover { border-color: var(--accent); }
.tp-sel-checkbox[aria-checked="true"] {
  background: var(--accent);
  border-color: var(--accent);
}
.tp-sel-checkbox[aria-checked="true"]::after {
  content: '✓';
  color: var(--accent-fg);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
}
.tp-sel-checkbox:active { transform: scale(0.9); }

/* Highlight de la row entera cuando está seleccionada. */
.tp-task-row.is-selected {
  background: color-mix(in srgb, var(--accent) 12%, var(--bg-1));
  border-color: var(--accent);
}
/* Cursor pointer en toda la row cuando el modo selección está activo para
   indicar que toda la fila es clickable. */
.tp-sel-active .tp-task-row { cursor: pointer; user-select: none; }

/* Barra contextual de acciones bulk, sticky abajo. */
.tp-sel-bar {
  position: fixed;
  left: 50%;
  bottom: var(--s-3);
  transform: translateX(-50%);
  max-width: calc(100% - var(--s-4));
  background: var(--bg-2);
  border: 1px solid var(--accent);
  border-radius: var(--r-lg);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(124, 58, 237, 0.2);
  z-index: 9000;
  display: flex;
  gap: var(--s-3);
  align-items: center;
  padding: var(--s-2) var(--s-3);
  animation: tp-sel-bar-in 0.18s ease-out;
}
@keyframes tp-sel-bar-in {
  from { transform: translate(-50%, 100%); opacity: 0; }
  to   { transform: translate(-50%, 0);    opacity: 1; }
}
.tp-sel-bar-left, .tp-sel-bar-right {
  display: flex;
  gap: var(--s-2);
  align-items: center;
}
.tp-sel-bar-left { border-right: 1px solid var(--border); padding-right: var(--s-3); }
.tp-sel-bar-counter {
  font-weight: 600;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.tp-sel-bar-btn-quiet {
  background: transparent !important;
  border-color: transparent !important;
  color: var(--fg-2) !important;
  padding: 6px 10px !important;
  min-height: 0 !important;
  font-size: var(--fs-sm) !important;
}
.tp-sel-bar-btn-quiet:hover { color: var(--fg-0) !important; background: var(--bg-3) !important; }

/* En mobile la barra se vuelve full-width y se apila para no recortar acciones. */
@media (max-width: 768px) {
  .tp-sel-bar {
    left: var(--s-2);
    right: var(--s-2);
    max-width: none;
    transform: none;
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-2);
    padding: var(--s-3);
  }
  @keyframes tp-sel-bar-in {
    from { transform: translateY(100%); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
  }
  .tp-sel-bar-left { border-right: 0; padding-right: 0; justify-content: space-between; }
  .tp-sel-bar-right { flex-wrap: wrap; justify-content: stretch; }
  .tp-sel-bar-right .tp-btn { flex: 1 1 auto; min-width: 90px; }
}

/* Encabezado de sección dentro de una lista (Atrasadas, Hoy, etc.). */
.tp-section-header {
  margin: var(--s-4) 0 var(--s-2);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-2);
  padding-bottom: var(--s-1);
  border-bottom: 1px solid var(--border);
}
.tp-section-header:first-of-type { margin-top: 0; }

.tp-empty {
  text-align: center;
  padding: var(--s-7) var(--s-4);
  color: var(--fg-2);
  font-size: var(--fs-md);
  line-height: 1.6;
}
.tp-empty strong { color: var(--fg-0); display: block; margin-bottom: var(--s-2); font-size: var(--fs-lg); }

/* ─── Skeleton loader ────────────────────────────────────────── */

.tp-skel {
  background: linear-gradient(90deg, var(--bg-2) 25%, var(--bg-3) 50%, var(--bg-2) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  height: 36px;
  border-radius: var(--r-sm);
  margin: var(--s-1) 0;
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ─── Clockify pulse ─────────────────────────────────────────── */
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* (El antiguo bloque .tp-tabs de botones simples se eliminó: no tenía ningún
   consumidor y colisionaba con el componente WAI-ARIA Tabs de arriba.) */

/* ─── Accesibilidad ──────────────────────────────────────────── */

*:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
button:focus-visible,
.tp-btn:focus-visible,
a:focus-visible {
  outline-offset: 2px;
}
.tp-input:focus-visible,
.tp-modal input:focus-visible,
.tp-modal textarea:focus-visible,
.tp-modal select:focus-visible {
  outline: none; /* la propia regla :focus ya pinta box-shadow */
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

/* Enlace "Saltar al contenido": invisible hasta recibir foco por teclado,
   entonces aparece sobre todo. Evita tabular los ~18 enlaces del sidebar en
   cada vista. Animar `top` aquí es un one-off al enfocar, no por frame. */
.tp-skip-link {
  position: fixed;
  left: 50%;
  top: -80px;
  transform: translateX(-50%);
  z-index: 1000;
  padding: 10px 16px;
  background: var(--accent);
  color: var(--accent-fg);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  transition: top 0.15s ease;
}
.tp-skip-link:focus { top: var(--s-3); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─── Tablet (≤1024px) ───────────────────────────────────────── */

@media (max-width: 1024px) {
  .tp-app { grid-template-columns: 220px 1fr; }
  .tp-main {
    padding: calc(var(--s-4) + env(safe-area-inset-top, 0)) var(--s-4) var(--s-4);
  }
  .tp-tile-grid { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
}

/* ─── Mobile (≤768px) ────────────────────────────────────────── */

@media (max-width: 768px) {
  /* iOS Safari fix: inputs con font-size < 16px disparan zoom automático al
     hacer focus, lo cual rompe el layout y desorienta. Forzamos 16px en
     TODOS los inputs/textareas/selects en mobile. El zoom-out manual no
     restaura la posición original, así que es preferible prevenirlo. */
  input.tp-input,
  textarea.tp-input,
  select.tp-input,
  .tp-new-task-bar-input,
  .tp-new-task-bar-select,
  input[type="text"],
  input[type="email"],
  input[type="password"],
  input[type="search"],
  input[type="number"],
  input[type="tel"],
  input[type="url"],
  input[type="date"],
  input[type="datetime-local"],
  input[type="time"],
  textarea,
  select {
    font-size: 16px;
  }

  .tp-app { grid-template-columns: 1fr; }

  /* Menú "Más" en móvil: OVERLAY A PANTALLA COMPLETA (opción B). Cubre toda la
     pantalla (incl. la bottom-nav), con ítems grandes y espaciados. Se cierra
     con el botón ✕, deslizando hacia abajo o tocando un enlace. Entra con un
     fade + leve subida. Respeta el safe-area en los 4 lados. */
  .tp-sidebar {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    z-index: 10001;
    background: var(--bg-0);
    box-shadow: none;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding:
      calc(env(safe-area-inset-top, 0) + var(--s-6))
      max(var(--s-5), env(safe-area-inset-right, 0))
      calc(env(safe-area-inset-bottom, 0) + var(--s-5))
      max(var(--s-5), env(safe-area-inset-left, 0));
    /* Cerrado: invisible y no interactuable. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(14px);
    transition: opacity 0.22s ease-out, transform 0.22s ease-out, visibility 0.22s;
  }
  .tp-app.tp-sidebar-open .tp-sidebar {
    opacity: 1;
    visibility: visible;
    transform: none;
  }
  .tp-sidebar h1 {
    font-size: var(--fs-2xl);
    margin: 0 0 var(--s-5);
  }
  /* Botón cerrar: fijo arriba-derecha (cuando el overlay está abierto, el
     contenedor no tiene transform → fixed ancla al viewport). */
  .tp-sidebar-close {
    display: inline-flex;
    position: fixed;
    top: calc(env(safe-area-inset-top, 0) + var(--s-3));
    right: calc(env(safe-area-inset-right, 0) + var(--s-3));
    width: var(--tap);
    height: var(--tap);
    align-items: center;
    justify-content: center;
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: 50%;
    color: var(--fg-0);
    font-size: 22px;
    line-height: 1;
    z-index: 10002;
    cursor: pointer;
  }
  /* Ítems grandes y cómodos para el pulgar. */
  .tp-sidebar nav { display: flex; flex-direction: column; gap: 2px; }
  .tp-sidebar nav a {
    font-size: var(--fs-lg);
    min-height: var(--tap);
    display: flex;
    align-items: center;
    padding: var(--s-3);
    border-radius: var(--r-md);
  }
  .tp-sidebar .section-title {
    margin-top: var(--s-4);
    font-size: var(--fs-xs);
  }
  /* El overlay es opaco a pantalla completa → no necesitamos backdrop. */
  .tp-sidebar-backdrop { display: none; }

  /* Hamburger en mobile está oculto: el bottom-nav ya incluye un "Más" para
     abrir el sidebar completo, así que mantenerlo arriba duplicaba el acceso
     y robaba espacio vertical (cada vista quedaba con un cuadrado vacío
     encima del título). Mantenemos el elemento DOM por compat pero invisible. */
  .tp-hamburger {
    display: none;
  }
  .tp-hamburger span {
    display: block;
    width: 20px;
    height: 2px;
    background: var(--fg-0);
    border-radius: 2px;
    transition: transform 0.2s;
  }

  /* Bottom navigation bar — solo móvil. Fixed bottom con safe-area-inset
     para iOS notch / home indicator. 4 ítems iguales (Cal, Entrada, Planif., Más). */
  .tp-bottom-nav {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 200;
    background: var(--bg-2);
    border-top: 1px solid var(--border);
    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.35);
    padding-bottom: env(safe-area-inset-bottom, 0);
    padding-left: env(safe-area-inset-left, 0);
    padding-right: env(safe-area-inset-right, 0);
  }
  .tp-bottom-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 10px 6px 8px;
    color: var(--fg-2);
    text-decoration: none;
    font-size: 11px;
    font-weight: 500;
    cursor: pointer;
    background: transparent;
    border: none;
    font-family: inherit;
    transition: color 0.15s, background 0.15s;
    /* Tap target mínimo 44px alto + indicador superior para el activo. */
    min-height: 56px;
    position: relative;
  }
  .tp-bottom-nav-item:active { background: var(--bg-3); }
  .tp-bottom-nav-item .tp-bottom-nav-icon {
    font-size: 18px;
    line-height: 1;
  }
  .tp-bottom-nav-item .tp-bottom-nav-label {
    font-variant: small-caps;
    letter-spacing: 0.02em;
  }
  .tp-bottom-nav-item.active {
    color: var(--accent);
  }
  .tp-bottom-nav-item.active::before {
    content: '';
    position: absolute;
    top: 0;
    left: 25%;
    right: 25%;
    height: 3px;
    background: var(--accent);
    border-radius: 0 0 3px 3px;
  }

  /* La bottom nav fija ocupa ~58px + safe-area; dejamos padding generoso en
     el main para que el contenido no quede oculto bajo ella ni por banners
     flotantes (Clockify timer, Plan IA). Subimos a 96px para amortiguar.
     Top: incluye safe-area-inset-top para iPhones con notch en PWA standalone
     (apple-mobile-web-app-status-bar-style=black-translucent deja el contenido
     extenderse bajo la barra de estado). */
  .tp-main {
    padding-top: calc(var(--s-2) + env(safe-area-inset-top, 0));
    padding-bottom: calc(96px + env(safe-area-inset-bottom, 0));
    padding-left: max(var(--s-3), env(safe-area-inset-left, 0));
    padding-right: max(var(--s-3), env(safe-area-inset-right, 0));
  }

  .tp-topbar {
    gap: var(--s-2);
    margin-bottom: var(--s-3);
    row-gap: var(--s-2);
    align-items: center;
  }
  .tp-topbar h2 {
    font-size: var(--fs-xl);
    flex: 1 1 auto;
    min-width: 0;
    /* No forzar width:100% para que botones como "Seleccionar" quepan al lado
       cuando hay espacio. Si no caben, flex-wrap los manda a nueva fila. */
  }

  .tp-tile-grid { grid-template-columns: 1fr; }

  .tp-settings { max-width: 100%; gap: var(--s-3); }
  .tp-card-body { padding: var(--s-4); }
  .tp-card > header { padding: var(--s-3) var(--s-4); }

  /* Tabla: scroll horizontal o card-mode */
  .tp-table { font-size: var(--fs-sm); }
  .tp-table th, .tp-table td { padding: var(--s-2); }

  .tp-modal {
    max-height: 88vh;
    border-radius: var(--r-lg);
    padding: var(--s-4);
  }

  .tp-done-filters { flex-direction: column; align-items: stretch; gap: var(--s-2); }
  .tp-done-filters .tp-input,
  .tp-done-filters .tp-done-range,
  .tp-done-filters .tp-done-search { width: 100%; flex: 0 0 auto; max-width: 100%; }

  .tp-rec-banner { flex-direction: column; align-items: flex-start; }

  /* Task row en móvil: 3 zonas claras
     - Línea 1: checkbox + título (wrap a varias líneas si es largo)
     - Línea 2: chips (prioridad, estimación, tags, due)
     - Línea 3: acciones (play, posponer, borrar) alineadas a la derecha
     Esto evita que el título quede comprimido a una columna estrecha. */
  .tp-task-row {
    flex-wrap: wrap;
    padding: var(--s-3);
    min-height: 60px;
    align-items: flex-start;
    row-gap: var(--s-2);
  }
  .tp-task-row .title {
    white-space: normal;
    flex: 1 1 calc(100% - 34px);
    min-width: 0;
    order: 2;
    word-break: normal;
    overflow-wrap: anywhere;
    overflow: hidden;
    text-overflow: clip;
    line-height: 1.35;
    padding-top: 2px;
  }
  .tp-task-row .tp-checkbox { order: 1; margin-top: 2px; }
  .tp-task-row .prio,
  .tp-task-row .due,
  .tp-task-row .tag,
  .tp-task-row .tp-task-estim {
    order: 3;
    flex: 0 0 auto;
  }
  /* Las acciones se mandan a una nueva línea completa y se alinean al final */
  .tp-task-row .actions {
    order: 4;
    flex: 1 1 100%;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: var(--s-2);
  }
  .tp-task-row .actions button {
    min-height: 40px;
    padding: 8px 14px;
    font-size: var(--fs-sm);
  }

  .tp-row {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-1);
    padding: var(--s-3) 0;
  }

  /* Botones llenan ancho dentro de formularios en mobile */
  .tp-form .tp-btn { width: 100%; }

  /* Banner stack */
  .tp-banner { flex-wrap: wrap; }
  .tp-banner .close { margin-left: 0; }

  /* Toasts ocupando ancho */
  .tp-toasts {
    left: var(--s-3);
    right: var(--s-3);
    /* Subir el contenedor de toasts por encima de la bottom nav fija
       (~64px + safe-area). Sin esto los toasts quedan ocultos detrás. */
    bottom: calc(64px + env(safe-area-inset-bottom, 0) + var(--s-3));
  }
  .tp-toast { max-width: 100%; }

  /* Calendario más compacto */
  .tp-cal-day { min-height: 80px; padding: var(--s-1) var(--s-2); }
}

/* ─── Mobile pequeño (≤480px) ────────────────────────────────── */

@media (max-width: 480px) {
  :root {
    --fs-md: 14px;
    --fs-lg: 17px;
    --fs-xl: 20px;
    --fs-2xl: 24px;
  }
  .tp-card-body { padding: var(--s-3); }
  .tp-card > header { padding: var(--s-3); }
  .tp-modal { padding: var(--s-3); }
  .tp-tile { padding: var(--s-3) var(--s-4); }
}

/* ─── Integraciones (listado) ────────────────────────────────── */

.tp-integrations-grid {
  display: grid;
  gap: var(--s-3);
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}

.tp-integration-tile {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-4) var(--s-5);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  text-decoration: none;
  color: var(--fg-0);
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
}
.tp-integration-tile:hover {
  border-color: var(--accent);
  background: var(--bg-3);
  transform: translateY(-2px);
  text-decoration: none;
}

.tp-integration-tile-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
}
.tp-integration-tile-title {
  margin: 0;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg-0);
}
.tp-integration-tile-desc {
  margin: 0;
  color: var(--fg-2);
  font-size: var(--fs-sm);
  line-height: 1.55;
}
.tp-integration-tile-extra {
  margin: 0;
  color: var(--fg-2);
  font-size: var(--fs-xs);
  font-style: italic;
}
.tp-integration-tile-cta {
  margin-top: var(--s-2);
  color: var(--accent);
  font-size: var(--fs-sm);
  font-weight: 600;
}

/* ─── Task detail ────────────────────────────────────────────── */

/* Barra de guardado: acción primaria a la derecha, "Duplicar" como botón
   secundario a su izquierda. Misma línea visual, jerarquía clara. */
.tp-task-save-bar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-5);
  padding-top: var(--s-4);
  border-top: 1px solid var(--border);
}
.tp-task-save-btn {
  min-width: 200px;
}
.tp-task-dup-btn { flex: 0 0 auto; }
@media (max-width: 600px) {
  .tp-task-save-bar { flex-direction: column; align-items: stretch; }
  .tp-task-save-btn { width: 100%; min-width: 0; }
  .tp-task-dup-btn { width: 100%; order: 2; }
  .tp-task-save-btn { order: 1; }
}

/* Grid de chips de transición de estado.
   En desktop: 1 fila ancha "completar" + fila de 3 columnas con secundarias.
   En mobile: una columna.                                              */
.tp-state-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-3);
}
.tp-state-chip.is-full { grid-column: 1 / -1; }
@media (max-width: 720px) {
  .tp-state-grid { grid-template-columns: 1fr; }
}

.tp-state-chip {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  text-align: left;
  padding: var(--s-3) var(--s-4);
  min-height: 64px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
  font-family: inherit;
  color: var(--fg-0);
  transition: background 0.15s, border-color 0.15s, transform 0.05s;
}
.tp-state-chip:hover {
  background: var(--bg-3);
  border-color: var(--accent);
}
.tp-state-chip:active { transform: translateY(1px); }

.tp-state-chip-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--r-md);
  font-size: 20px;
  font-weight: 700;
  background: var(--bg-3);
  flex-shrink: 0;
  line-height: 1;
}
.tp-state-chip-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.tp-state-chip-label {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg-0);
  line-height: 1.3;
}
.tp-state-chip-hint {
  font-size: var(--fs-sm);
  color: var(--fg-2);
  line-height: 1.4;
}

/* Tonos: aplican color al icono y a la línea del hover. */
.tp-state-chip.tone-success .tp-state-chip-icon { background: var(--green-soft); color: var(--green); }
.tp-state-chip.tone-success:hover { border-color: var(--green); }
.tp-state-chip.tone-info    .tp-state-chip-icon { background: var(--blue-soft); color: var(--blue); }
.tp-state-chip.tone-info:hover    { border-color: var(--blue); }
.tp-state-chip.tone-warn    .tp-state-chip-icon { background: var(--yellow-soft); color: var(--yellow); }
.tp-state-chip.tone-warn:hover    { border-color: var(--yellow); }
.tp-state-chip.tone-neutral .tp-state-chip-icon { background: var(--bg-3); color: var(--fg-1); }
.tp-state-chip.tone-neutral:hover { border-color: var(--fg-2); }
.tp-state-chip.tone-primary .tp-state-chip-icon { background: var(--accent-soft); color: var(--accent); }
.tp-state-chip.tone-primary:hover { border-color: var(--accent); }

/* "Zona peligrosa": tono rojo discreto, no rojo gigante. */
.tp-card.tp-card-danger { border-color: rgba(239,68,68,0.35); }
.tp-card.tp-card-danger > header h3 { color: var(--red); }
.tp-danger-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
}
.tp-danger-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 220px;
}
.tp-danger-text strong { font-size: var(--fs-md); color: var(--fg-0); }
.tp-danger-text span   { font-size: var(--fs-sm); color: var(--fg-2); line-height: 1.5; }
@media (max-width: 600px) {
  .tp-danger-row { flex-direction: column; align-items: stretch; }
  .tp-danger-row .tp-btn { width: 100%; }
}

.tp-task-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-3);
  margin-top: var(--s-3);
}
.tp-task-grid-full {
  grid-column: 1 / -1;
  min-width: 0;
}

/* ── Anti-desbordamiento horizontal en la vista/edición de tarea ──
   En móvil el contenido se salía por la derecha. Causas: celdas de grid e
   ítems flex sin `min-width:0` (no pueden encoger bajo su contenido) y
   palabras/strings largos (URLs, nombres de tag, texto de checklist, notas)
   que empujan en vez de envolver. Esto lo neutraliza de forma segura. */
.tp-task-grid > * { min-width: 0; }
.tp-task-status-line { flex-wrap: wrap; }
.tp-task-status-line > * { min-width: 0; }
.tp-checklist-item { overflow-wrap: anywhere; }
.tp-checklist-item > span { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.tp-tag-chip { max-width: 100%; overflow-wrap: anywhere; }
.tp-wysiwyg-editor { overflow-wrap: anywhere; }
.tp-wysiwyg-editor pre { white-space: pre-wrap; word-break: break-word; }
.tp-wysiwyg-editor img { max-width: 100%; height: auto; }
/* Un título de tarea muy largo (sin espacios) tampoco debe empujar la topbar. */
.tp-topbar h2 { overflow-wrap: anywhere; }

/* #33 — Historial de cambios de tarea */
.tp-task-history { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.tp-task-history-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2) var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--border-soft);
  font-size: var(--fs-sm);
}
.tp-task-history-item:last-child { border-bottom: none; }
.tp-task-history-action { color: var(--fg-0); }
.tp-task-history-when { color: var(--fg-2); }
.tp-estim-hint {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--accent);
  background: var(--accent-soft);
  padding: 4px 10px;
  border-radius: var(--r-sm);
}
@media (max-width: 600px) {
  .tp-task-grid { grid-template-columns: 1fr; }
}

/* Prioridad con dot de color al lado del select */
.tp-prio-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-top: 6px;
}
.tp-prio-row .tp-input { flex: 1; margin-top: 0; }
.tp-prio-dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  flex-shrink: 0;
  box-sizing: border-box;
  background: transparent;
  border: 2px solid var(--border-strong);
  transition: background 0.15s, border-color 0.15s;
}

/* ── "Color en calendario": input nativo + swatches redondos ── */
.tp-color-field {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: 6px;
}
.tp-color-input {
  width: 44px;
  height: 34px;
  flex: 0 0 auto;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-2);
  cursor: pointer;
}
.tp-color-input::-webkit-color-swatch-wrapper { padding: 0; }
.tp-color-input::-webkit-color-swatch { border: none; border-radius: 5px; }
.tp-color-input::-moz-color-swatch { border: none; border-radius: 5px; }
.tp-color-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
/* flex: 0 0 26px + width==height fija el círculo: sin `flex-shrink` los botones
   se comprimían horizontalmente al no caber la fila y salían ovalados. */
.tp-color-swatch {
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid transparent;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.tp-color-swatch:hover { transform: scale(1.12); }
.tp-color-swatch.is-selected {
  border-color: var(--fg-0);
  box-shadow: 0 0 0 2px var(--bg-1), inset 0 0 0 1px rgba(255, 255, 255, 0.25);
}
.tp-color-swatch:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Tags Clockify (single-select chips) */
.tp-clockify-tags {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3);
  margin-top: 6px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  min-height: 56px;
}
.tp-clockify-tags.is-invalid {
  border-color: var(--red);
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.18);
}
.tp-clockify-tags-head {
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-2);
  margin-top: var(--s-1);
}
.tp-clockify-tags-head:first-child { margin-top: 0; }
.tp-clockify-tags-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
.tp-clockify-tags-empty {
  color: var(--fg-2);
  font-size: var(--fs-sm);
  padding: var(--s-2);
  line-height: 1.55;
}
.tp-clockify-tags-empty a { color: var(--accent); font-weight: 600; }

.tp-clockify-tags-search {
  margin-top: 0 !important;
  margin-bottom: var(--s-2);
}

/* Mapeo Tag → Proyecto en ajustes de Clockify */
.tp-clockify-map-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--border);
}
.tp-clockify-map-row .tp-input { margin-top: 0; min-width: 0; }
.tp-clockify-map-arrow {
  font-size: var(--fs-lg);
  color: var(--accent);
  font-weight: 700;
}
@media (max-width: 720px) {
  .tp-clockify-map-row {
    grid-template-columns: 1fr;
  }
  .tp-clockify-map-arrow { text-align: center; }
}

/* "Estado actual" debajo de Proyecto sin doble padding/margin. */
.tp-task-status-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  margin-top: var(--s-3);
  font-size: var(--fs-sm);
}
.tp-task-status-line .label { color: var(--fg-2); }

/* Bloques de URL y comando del CRON */
.tp-cron-url {
  margin-top: 6px;
  padding: var(--s-3);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--fg-0);
  word-break: break-all;
  user-select: all;
}
.tp-cron-cmd {
  margin: 6px 0 0;
  padding: var(--s-3);
  background: #050d1a;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--green);
  white-space: pre-wrap;
  word-break: break-all;
  user-select: all;
  overflow-x: auto;
}

/* ─── Conexiones MCP (Ajustes) ─────────────────────────────────── */
/* Banda de estado: punto vivo + texto + rejilla de métricas. */
.tp-mcp-status {
  margin: 0 0 var(--s-4);
  padding: var(--s-4);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}
.tp-mcp-status-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
}
.tp-mcp-status-text { font-weight: 600; color: var(--fg-0); }
.tp-mcp-dot {
  width: 10px; height: 10px;
  border-radius: var(--r-pill);
  flex-shrink: 0;
  position: relative;
}
.tp-mcp-dot.ok { background: var(--green); box-shadow: 0 0 0 0 var(--green-soft); animation: tp-mcp-pulse 2s ease-out infinite; }
.tp-mcp-dot.warn { background: var(--yellow); }
@keyframes tp-mcp-pulse {
  0%   { box-shadow: 0 0 0 0 var(--green-soft); }
  70%  { box-shadow: 0 0 0 7px rgba(34, 197, 94, 0); }
  100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); }
}
.tp-mcp-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-2);
}
.tp-mcp-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--s-3);
  background: var(--bg-1);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
}
.tp-mcp-stat-value {
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--fg-0);
  line-height: 1.1;
}
.tp-mcp-stat.ok .tp-mcp-stat-value { color: var(--green); }
.tp-mcp-stat.warn .tp-mcp-stat-value { color: var(--yellow); }
.tp-mcp-stat-label {
  font-size: var(--fs-xs);
  color: var(--fg-2);
}

/* Campo monoespaciado con botón de copia acoplado a la derecha. */
.tp-mcp-field {
  display: flex;
  align-items: stretch;
  margin-top: 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-2);
  overflow: hidden;
}
.tp-mcp-field-text {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--fg-0);
  word-break: break-all;
  user-select: all;
  align-self: center;
}
.tp-mcp-copy-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  border: none;
  border-left: 1px solid var(--border);
  background: var(--bg-3);
  color: var(--fg-1);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.tp-mcp-copy-btn:hover { background: var(--accent-soft); color: var(--accent); }
.tp-mcp-copy-btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

/* Bloque de código (comando / JSON) con botón de copia flotante. */
.tp-mcp-code { position: relative; }
.tp-mcp-code .tp-cron-cmd { padding-right: 52px; }
.tp-mcp-copy-btn.floating {
  position: absolute;
  top: var(--s-2);
  right: var(--s-2);
  width: 34px;
  height: 34px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: rgba(10, 19, 34, 0.7);
  backdrop-filter: blur(2px);
}

.tp-mcp-connect { margin-top: var(--s-2); }

/* Cabecera de sección con subtítulo y acción opcional a la derecha. */
.tp-mcp-section {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  flex-wrap: wrap;
}
.tp-mcp-section-sub {
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--fg-2);
}
.tp-mcp-section .tp-mcp-mini-btn { margin-left: auto; align-self: center; }
.tp-mcp-mini-btn {
  padding: 6px 12px;
  font-size: var(--fs-sm);
  min-height: 0;
}

/* Filas de keys revocadas / expiradas atenuadas. */
.tp-mcp-row-muted td { opacity: 0.55; }
.tp-mcp-row-muted:hover td { opacity: 0.8; }

/* Contador de scopes en el modal de creación. */
.tp-mcp-scope-count {
  margin-left: auto;
  align-self: center;
  font-size: var(--fs-xs);
  color: var(--fg-2);
}

/* Estado vacío de la lista de keys. */
.tp-mcp-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s-2);
  padding: var(--s-6) var(--s-4);
  background: var(--bg-2);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-lg);
}
.tp-mcp-empty-ic {
  font-size: 32px;
  line-height: 1;
  opacity: 0.85;
}
.tp-mcp-empty strong { color: var(--fg-0); font-size: var(--fs-md); }
.tp-mcp-empty span { color: var(--fg-2); font-size: var(--fs-sm); max-width: 42ch; }

@media (max-width: 560px) {
  .tp-mcp-stats { grid-template-columns: repeat(2, 1fr); }
}

/* Asterisco rojo en campos obligatorios */
.tp-required {
  color: var(--red);
  font-weight: 700;
  margin-left: 2px;
}

/* Selectores compactos en NewTaskBar */
.tp-new-task-bar-select {
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-0);
  border-radius: var(--r-sm);
  font-family: inherit;
  font-size: var(--fs-sm);
  padding: 6px 10px;
  min-height: 40px;
  max-width: 200px;
  flex-shrink: 0;
}
.tp-new-task-bar-select:hover { border-color: var(--border-strong); }
.tp-new-task-bar-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}
.tp-new-task-bar-tpl {
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-0);
  border-radius: var(--r-sm);
  font-size: var(--fs-lg);
  padding: 4px 10px;
  min-height: 40px;
  cursor: pointer;
  flex-shrink: 0;
  line-height: 1;
}
.tp-new-task-bar-tpl:hover { border-color: var(--accent); background: var(--accent-soft); }
.tp-tpl-picker { display: flex; flex-direction: column; gap: 2px; }
.tp-tpl-picker-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: transparent;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  cursor: pointer;
  text-align: left;
  color: var(--fg-0);
  font-family: inherit;
  font-size: var(--fs-md);
  transition: background 0.1s, border-color 0.1s;
}
.tp-tpl-picker-row:hover { background: var(--bg-2); border-color: var(--accent); }
.tp-tpl-picker-icon { font-size: 22px; flex-shrink: 0; }
.tp-tpl-picker-info { flex: 1; min-width: 0; }
.tp-tpl-picker-name { font-weight: 600; }
.tp-tpl-picker-meta { font-size: var(--fs-sm); color: var(--fg-2); margin-top: 1px; }
@media (max-width: 720px) {
  /* NewTaskBar móvil: el botón "Añadir" salta a una línea propia debajo del
     input cuando no cabe. Los inputs y selects fuerzan min-height 44px para
     tap-target táctil. Las opciones avanzadas (chips, prio, est, tag, proy)
     ocupan 100% en filas separadas, con el tag claramente destacado por ser
     obligatorio. */
  .tp-ntb { padding: var(--s-3); gap: var(--s-2); }
  .tp-ntb-row-main {
    gap: var(--s-2);
    row-gap: var(--s-2);
  }
  .tp-ntb-input {
    flex: 1 1 calc(100% - 100px);
    min-height: 44px;
  }
  .tp-ntb-submit { min-height: 44px; padding: 0 var(--s-3); }
  .tp-ntb-row-opts {
    padding-top: var(--s-3);
    row-gap: var(--s-3);
  }
  .tp-ntb-quickdates {
    flex: 1 1 100%;
    gap: 6px;
  }
  .tp-ntb-priorities { flex: 0 0 auto; }
  .tp-ntb-est { flex: 1 1 110px; }
  .tp-ntb-tag,
  .tp-ntb-proj {
    flex: 1 1 calc(50% - var(--s-1));
    min-height: 40px;
    font-size: 16px; /* evita zoom iOS */
  }
  .tp-ntb-tpl {
    flex: 0 0 auto;
    min-height: 40px;
  }
}

@media (max-width: 540px) {
  /* En pantallas muy estrechas: tag y proyecto ocupan fila completa cada uno
     para que el texto del select sea siempre legible. */
  .tp-ntb-tag,
  .tp-ntb-proj { flex: 1 1 100%; }
  .tp-ntb-input { font-size: 16px; }
  .tp-ntb-est-input { font-size: 16px; }
}

/* WYSIWYG editor */
.tp-wysiwyg {
  display: flex;
  flex-direction: column;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  margin-top: 6px;
  overflow: hidden;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.tp-wysiwyg:focus-within {
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}
.tp-wysiwyg-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: var(--s-2);
  background: var(--bg-3);
  border-bottom: 1px solid var(--border);
}
.tp-wysiwyg-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  padding: 0 10px;
  background: transparent;
  color: var(--fg-1);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  cursor: pointer;
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.tp-wysiwyg-btn:hover {
  background: var(--bg-2);
  color: var(--fg-0);
  border-color: var(--border-strong);
}
.tp-wysiwyg-btn:active { background: var(--accent-soft); color: var(--accent); }

.tp-wysiwyg-editor {
  min-height: 160px;
  max-height: 480px;
  overflow-y: auto;
  padding: var(--s-3) var(--s-4);
  color: var(--fg-0);
  font-size: var(--fs-md);
  line-height: 1.6;
  outline: none;
}
.tp-wysiwyg-editor:empty::before {
  content: 'Escribe aquí…';
  color: var(--fg-3);
  pointer-events: none;
}
.tp-wysiwyg-editor p,
.tp-wysiwyg-editor div { margin: 0 0 var(--s-2); }
.tp-wysiwyg-editor ul,
.tp-wysiwyg-editor ol { margin: 0 0 var(--s-2); padding-left: 24px; }
.tp-wysiwyg-editor li { margin: 2px 0; }
.tp-wysiwyg-editor a { color: var(--accent); text-decoration: underline; }
.tp-wysiwyg-editor code {
  background: var(--bg-3);
  padding: 2px 6px;
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 0.92em;
}
.tp-wysiwyg-editor h2,
.tp-wysiwyg-editor h3 { margin: var(--s-3) 0 var(--s-1); }

@media (max-width: 600px) {
  .tp-wysiwyg-editor { min-height: 140px; padding: var(--s-3); }
  .tp-wysiwyg-btn { min-width: 40px; height: 40px; }
}

/* ─── Event editor (modal) ───────────────────────────────────── */

.tp-event-editor { display: flex; flex-direction: column; gap: var(--s-1); }
.tp-event-editor .tp-form-label { margin-top: var(--s-3); }
.tp-event-editor .tp-form-label:first-child { margin-top: 0; }

/* Toggle "Todo el día" como pill compacto debajo del campo Título.
   El selector `label.tp-event-editor-toggle` gana en especificidad a la
   regla `.tp-modal label { display: block }` que de otro modo apilaba el
   checkbox y el texto en columna. */
label.tp-event-editor-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--fg-0);
  cursor: pointer;
  user-select: none;
  padding: 8px 14px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  white-space: nowrap;
  align-self: flex-start;
  width: fit-content;
}
label.tp-event-editor-toggle:hover { border-color: var(--border-strong); }
label.tp-event-editor-toggle input[type="checkbox"] {
  /* Override completo de las reglas `.tp-modal input { width:100%; min-height:44px;
     padding:12px 14px; ... }` para devolverle al checkbox su tamaño nativo. */
  width: 18px;
  height: 18px;
  min-height: 0;
  padding: 0;
  margin: 0;
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  cursor: pointer;
  flex-shrink: 0;
}
label.tp-event-editor-toggle:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}

.tp-event-editor-range {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-3);
  /* Separación extra arriba para que "Inicio" y "Fin" respiren respecto
     al chip "Todo el día" que está encima. */
  margin-top: var(--s-4);
}
@media (max-width: 600px) {
  .tp-event-editor-range { grid-template-columns: 1fr; }
}

.tp-event-editor-dtblock {
  display: flex;
  flex-direction: column;
}
/* Los labels "Inicio" / "Fin" no necesitan margin-top porque ya lo aporta
   el contenedor `.tp-event-editor-range`. */
.tp-event-editor-dtblock .tp-form-label { margin-top: 0; }

.tp-event-editor-dtrow {
  display: flex;
  gap: var(--s-2);
  margin-top: 6px;
}
.tp-event-editor-dtrow .tp-input { margin-top: 0; flex: 1; min-width: 0; }
.tp-event-editor-dtrow input[type="time"] { flex: 0 0 110px; }

.tp-event-editor-colors {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: 6px;
}
.tp-event-editor-color {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
  transition: transform 0.1s, border-color 0.15s;
  box-shadow: var(--shadow-sm);
}
.tp-event-editor-color:hover { transform: scale(1.1); }
.tp-event-editor-color.active {
  border-color: var(--fg-0);
  transform: scale(1.1);
}

.tp-event-editor-reminders {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: 6px;
}

.tp-event-editor-hint {
  margin-top: var(--s-3);
  padding: var(--s-2) var(--s-3);
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-sm);
  color: var(--accent);
  font-size: var(--fs-sm);
  line-height: 1.5;
}

.tp-event-editor-delete {
  align-self: flex-start;
  margin-top: var(--s-4);
}

/* Fila de acciones extra del editor de evento (Duplicar + Borrar). */
.tp-event-editor-actions {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
  margin-top: var(--s-4);
  padding-top: var(--s-3);
  border-top: 1px solid var(--border);
}
.tp-event-editor-actions .tp-btn { flex: 0 0 auto; }
@media (max-width: 600px) {
  .tp-event-editor-actions .tp-btn { flex: 1 1 calc(50% - var(--s-1)); }
}

/* Cuando el modal contiene el editor de eventos, lo expandimos un poco más
   ancho y quitamos su scroll interno: el contenido cabe en una pantalla
   normal y, si no, el overlay completo hace scroll natural. */
.tp-modal:has(.tp-event-editor) {
  max-width: 640px;
  max-height: none;
  overflow: visible;
}
/* El overlay sí debe poder scrollear en pantallas muy bajas, para que no
   se corte el botón "Crear evento" / "Guardar cambios". */
.tp-modal-overlay:has(.tp-event-editor) {
  align-items: flex-start;
  overflow-y: auto;
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
}

/* ─── Updater ────────────────────────────────────────────────── */

.tp-updater-dropzone {
  border: 2px dashed var(--border-strong);
  border-radius: var(--r-lg);
  padding: var(--s-6) var(--s-4);
  text-align: center;
  background: var(--bg-2);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  transition: border-color 0.15s, background 0.15s;
  margin-top: var(--s-4);
}
.tp-updater-dropzone:hover,
.tp-updater-dropzone:focus-visible {
  border-color: var(--accent);
  background: var(--bg-3);
  outline: none;
}
.tp-updater-dropzone.drag {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.tp-updater-dropzone-icon {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: 700;
  margin-bottom: var(--s-2);
}
.tp-updater-dropzone strong {
  font-size: var(--fs-md);
  color: var(--fg-0);
}
.tp-updater-dropzone-hint {
  color: var(--fg-2);
  font-size: var(--fs-sm);
}

.tp-updater-selected {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  margin-top: var(--s-3);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  color: var(--fg-0);
}
.tp-updater-meta {
  color: var(--fg-2);
  font-size: var(--fs-sm);
}

.tp-updater-phase {
  font-weight: 600;
  font-size: var(--fs-md);
  color: var(--fg-0);
  margin-bottom: var(--s-2);
}
.tp-updater-progress {
  width: 100%;
  height: 10px;
  background: var(--bg-2);
  border-radius: var(--r-pill);
  overflow: hidden;
  margin-bottom: var(--s-2);
  border: 1px solid var(--border);
}
.tp-updater-progress-bar {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-strong));
  transition: width 0.3s ease-out;
  border-radius: var(--r-pill);
}
.tp-updater-pct {
  color: var(--fg-2);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--s-3);
}

.tp-updater-log {
  margin: 0;
  padding: var(--s-3);
  background: #050d1a;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--fg-1);
  max-height: 360px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-word;
}
.tp-updater-log-line { padding: 1px 0; }
.tp-updater-log-line.err { color: var(--red); }
.tp-updater-log-line.warn { color: var(--yellow); }
.tp-updater-log-line.ok { color: var(--fg-0); }

@media (max-width: 768px) {
  .tp-updater-dropzone { padding: var(--s-5) var(--s-3); }
  .tp-updater-log { max-height: 280px; font-size: var(--fs-xs); }
}

/* ─── Hover-capable only ─────────────────────────────────────── */
/* Anula efectos hover en dispositivos sin puntero fino (móvil),
   donde el hover se "queda pegado" tras tap. */
@media (hover: none) {
  .tp-tile:hover { transform: none; }
  .tp-task-row:hover { background: var(--bg-1); }
  .tp-done-row:hover { background: transparent; }
}

/* ─── AI Loading Overlay (planificación en curso) ────────────── */
.tp-ai-loading-overlay {
  /* Por encima del modal base (9500) y de los toasts (9999): mientras la IA
     trabaja, nada debe taparlo. Antes valía 1500 y quedaba por debajo. */
  z-index: 10000;
  animation: tp-fade-in 0.15s ease-out;
}
.tp-ai-loading-overlay.is-closing {
  animation: tp-fade-out 0.15s ease-in forwards;
}
.tp-ai-loading-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
  padding: var(--s-6) var(--s-7);
  width: min(400px, 90vw);
  text-align: center;
  animation: tp-modal-pop 0.22s cubic-bezier(0.2, 0.7, 0.2, 1.05);
}
.tp-ai-loading-icon {
  font-size: 36px;
  line-height: 1;
  animation: tp-ai-loading-pulse 2s ease-in-out infinite;
}
@keyframes tp-ai-loading-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.6; transform: scale(1.12); }
}
.tp-ai-loading-title {
  margin: 0;
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--fg-0);
  background: linear-gradient(135deg, #a855f7, var(--accent));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}
.tp-ai-loading-subtitle {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--fg-2);
}
.tp-ai-loading-bar {
  width: 100%;
  height: 6px;
  background: var(--bg-3);
  border-radius: var(--r-pill);
  overflow: hidden;
  margin-top: var(--s-2);
}
.tp-ai-loading-bar-fill {
  height: 100%;
  width: 40%;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, #7c3aed, #a855f7, var(--accent));
  animation: tp-ai-loading-slide 1.8s ease-in-out infinite;
}
@keyframes tp-ai-loading-slide {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}
@media (prefers-reduced-motion: reduce) {
  .tp-ai-loading-icon { animation: none; }
  .tp-ai-loading-bar-fill { animation: none; width: 100%; opacity: 0.5; }
}
@media (max-width: 880px) {
  .tp-ai-loading-card { padding: var(--s-5) var(--s-5); }
}

/* ─── AI Preview Modal (#5) ───────────────────────────────────── */
.tp-ai-preview-overlay {
  /* Heredada de .tp-modal-overlay pero con z-index propio para asegurar
     que queda sobre Toast/notif (9999) si coinciden temporalmente.
     Antes valía 1500 y quedaba por debajo del modal base (9500). */
  z-index: 10000;
  animation: tp-fade-in 0.15s ease-out;
}
.tp-ai-preview-overlay.is-closing {
  animation: tp-fade-out 0.15s ease-in forwards;
}
.tp-ai-preview {
  display: flex;
  flex-direction: column;
  width: min(720px, 96vw);
  max-height: 88vh;
  max-height: 88dvh;
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
  overflow: hidden;
  animation: tp-modal-pop 0.22s cubic-bezier(0.2, 0.7, 0.2, 1.05);
}
.tp-ai-preview-head {
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
  background: linear-gradient(135deg,
    color-mix(in srgb, #7c3aed 18%, var(--bg-1)),
    var(--bg-1));
}
.tp-ai-preview-head h3 {
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-lg);
  color: var(--fg-0);
}
.tp-ai-icon { color: #c084fc; }
.tp-ai-preview-meta {
  margin-top: var(--s-2);
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.tp-ai-mode-pill {
  background: color-mix(in srgb, #7c3aed 25%, transparent);
  color: #ddd6fe;
  border-color: color-mix(in srgb, #7c3aed 40%, transparent);
}
/* #4 — Pill del alcance "Solo resto de hoy" en el preview IA */
.tp-ai-scope-pill {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
}
.tp-ai-preview-summary {
  margin: 0;
  padding: var(--s-3) var(--s-5);
  background: color-mix(in srgb, #7c3aed 8%, var(--bg-1));
  border-bottom: 1px solid var(--border);
  color: var(--fg-1);
  font-size: var(--fs-sm);
  line-height: 1.5;
  font-style: italic;
}
.tp-ai-preview-body {
  padding: var(--s-3) var(--s-5);
  overflow-y: auto;
  flex: 1 1 auto;
}
.tp-ai-preview-empty {
  text-align: center;
  padding: var(--s-5) var(--s-3);
  color: var(--fg-2);
}
.tp-ai-day-group { margin-bottom: var(--s-4); }
.tp-ai-day-head {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
  color: var(--fg-2);
  margin-bottom: 6px;
  padding-left: 4px;
}
.tp-ai-block-row {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  padding: 10px 12px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  margin-bottom: 6px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, opacity 0.15s, transform 0.15s;
}
.tp-ai-block-row:hover { border-color: var(--border-strong); }
.tp-ai-block-row:has(input:checked) {
  border-color: color-mix(in srgb, #7c3aed 60%, var(--border));
  background: color-mix(in srgb, #7c3aed 6%, var(--bg-2));
}
.tp-ai-block-row.is-off { opacity: 0.5; }
.tp-ai-block-row > input { margin-top: 3px; flex-shrink: 0; }

/* ─── Checkbox/radio custom (consistente cross-browser) ─────────
   Los checkboxes nativos sufren problemas de alineación, tamaño
   inconsistente entre browsers, accent-color limitado en Safari y
   bordes invisibles en dark mode. Reemplazamos el render por uno
   propio dentro de filas tp-ai-block-row / tp-check-row / tp-radio-row.
   El input nativo se mantiene en el DOM (label-for funciona, screen
   readers ven el control), pero se restila con appearance:none. */
.tp-ai-block-row input[type="checkbox"],
.tp-check-row input[type="checkbox"],
.tp-radio-row input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  /* Tamaño FIJO 20×20. Anulamos `min-height: var(--tap)` que `.tp-modal
     input { ... }` aplica genéricamente a TODO input dentro de cualquier
     modal — sin ese override, el navegador estira el checkbox a la
     altura táctil de 44 px (síntoma: checkbox vertical en forma de píldora
     dentro del Preview IA). También fijamos box-sizing y flex para
     blindar contra padres flex/grid que intenten estirarlo. */
  width: 20px !important;
  height: 20px !important;
  min-height: 0 !important;
  min-width: 0;
  max-height: 20px;
  max-width: 20px;
  box-sizing: border-box;
  flex: 0 0 auto;
  align-self: flex-start;
  margin: 2px 0 0;
  padding: 0;
  border: 2px solid var(--border-strong);
  border-radius: 6px;
  background: var(--bg-1);
  cursor: pointer;
  position: relative;
  display: inline-block;
  vertical-align: top;
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
}
.tp-radio-row input[type="radio"] {
  /* Los radios son circulares por convención. */
  border-radius: 50%;
}
.tp-ai-block-row input[type="checkbox"]:hover,
.tp-check-row input[type="checkbox"]:hover,
.tp-radio-row input[type="radio"]:hover {
  border-color: var(--accent);
}
.tp-ai-block-row input[type="checkbox"]:checked,
.tp-check-row input[type="checkbox"]:checked {
  background: var(--accent);
  border-color: var(--accent);
}
.tp-ai-block-row input[type="checkbox"]:checked::after,
.tp-check-row input[type="checkbox"]:checked::after {
  /* Tick blanco dibujado con un span virtual: dos bordes en L girada 45°.
     Posición calibrada para que quede centrado dentro del 20×20. */
  content: '';
  position: absolute;
  left: 5px;
  top: 1px;
  width: 5px;
  height: 10px;
  border: solid #fff;
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg);
}
.tp-radio-row input[type="radio"]:checked {
  border-color: var(--accent);
  background: var(--bg-1);
}
.tp-radio-row input[type="radio"]:checked::after {
  /* Punto interior del radio. */
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  transform: translate(-50%, -50%);
}
.tp-ai-block-row input[type="checkbox"]:active,
.tp-check-row input[type="checkbox"]:active,
.tp-radio-row input[type="radio"]:active {
  transform: scale(0.92);
}
.tp-ai-block-row input[type="checkbox"]:focus-visible,
.tp-check-row input[type="checkbox"]:focus-visible,
.tp-radio-row input[type="radio"]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent);
}
.tp-ai-block-row input[type="checkbox"]:disabled,
.tp-check-row input[type="checkbox"]:disabled,
.tp-radio-row input[type="radio"]:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
@media (prefers-reduced-motion: reduce) {
  .tp-ai-block-row input[type="checkbox"],
  .tp-check-row input[type="checkbox"],
  .tp-radio-row input[type="radio"] { transition: none; }
}
.tp-ai-block-main { flex: 1; min-width: 0; }
.tp-ai-block-top {
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
  flex-wrap: wrap;
}
.tp-ai-block-when {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: #c084fc;
  font-size: var(--fs-sm);
}
.tp-ai-block-label {
  color: var(--fg-0);
  font-weight: 500;
  word-break: break-word;
}
.tp-ai-block-rationale {
  margin: 6px 0 0;
  color: var(--fg-2);
  font-size: var(--fs-xs);
  line-height: 1.5;
  display: flex;
  gap: 6px;
  align-items: flex-start;
}
.tp-ai-block-rationale > span:first-child { color: #fbbf24; }
.tp-ai-preview-section-title {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: var(--s-4) 0 6px;
  font-size: var(--fs-md);
  color: var(--fg-0);
}
.tp-ai-preview-section-title > span:first-child { color: var(--orange); }
.tp-ai-preview-unsched { margin-top: var(--s-3); }
.tp-ai-unsched-row {
  padding: 12px;
  background: color-mix(in srgb, var(--orange) 6%, var(--bg-2));
  border: 1px solid color-mix(in srgb, var(--orange) 35%, var(--border));
  border-radius: var(--r-md);
  margin-bottom: 6px;
  transition: opacity 0.2s;
}
.tp-ai-unsched-row.is-resolved { opacity: 0.55; }
.tp-ai-unsched-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-2);
}
.tp-ai-unsched-title { font-weight: 600; color: var(--fg-0); }
.tp-ai-unsched-open {
  color: var(--accent);
  font-size: var(--fs-sm);
  text-decoration: none;
}
.tp-ai-unsched-open:hover { text-decoration: underline; }
.tp-ai-unsched-reason {
  margin: 6px 0;
  color: var(--fg-1);
  font-size: var(--fs-sm);
  line-height: 1.45;
}
.tp-ai-unsched-alts {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 8px;
}
.tp-ai-alt-btn {
  padding: 6px 12px;
  font-size: var(--fs-sm);
  border-radius: var(--r-md);
}
.tp-ai-alt-btn.is-loading { opacity: 0.7; }
.tp-ai-preview-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s-3) var(--s-5);
  border-top: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg-2) 60%, var(--bg-1));
  gap: var(--s-3);
  flex-wrap: wrap;
}
.tp-ai-preview-counter {
  color: var(--fg-2);
  font-size: var(--fs-sm);
}
.tp-ai-preview-actions { display: flex; gap: var(--s-2); }

/* ─── Bloque IA en calendario: candado + rationale (#6 #7) ─── */
.tp-cal-time-event.is-ai.is-pinned {
  background-image: repeating-linear-gradient(
    -45deg,
    transparent,
    transparent 6px,
    rgba(255, 255, 255, 0.06) 6px,
    rgba(255, 255, 255, 0.06) 8px
  );
  border-left-width: 4px;
}
.tp-cal-time-event-btn-pin-on,
.tp-cal-time-event-btn-pin-off {
  background: rgba(0, 0, 0, 0.25);
  color: #f1f5f9;
}
.tp-cal-time-event-btn-pin-on { background: rgba(124, 58, 237, 0.45); }
.tp-cal-time-event-btn-pin-on:hover,
.tp-cal-time-event-btn-pin-off:hover { transform: scale(1.06); }

.tp-cal-block-rationale {
  position: absolute;
  bottom: 4px;
  right: 6px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.85);
  background: rgba(0, 0, 0, 0.35);
  border-radius: 10px;
  padding: 2px 6px;
  cursor: help;
  max-width: calc(100% - 14px);
  transition: max-width 0.2s ease-out, background 0.15s;
}
.tp-cal-block-rationale-text {
  display: inline-block;
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  opacity: 0;
  transition: max-width 0.25s ease-out, opacity 0.2s;
  font-size: 11px;
}
.tp-cal-block-rationale:hover .tp-cal-block-rationale-text,
.tp-cal-block-rationale.is-open .tp-cal-block-rationale-text {
  max-width: 280px;
  opacity: 1;
  margin-left: 2px;
  white-space: normal;
  word-break: break-word;
}
.tp-cal-block-rationale:hover,
.tp-cal-block-rationale.is-open {
  background: rgba(0, 0, 0, 0.55);
}
@media (hover: none) {
  .tp-cal-block-rationale-text { /* mobile: solo expande con click */
    transition: max-width 0.2s, opacity 0.15s;
  }
}

/* ─── Capacity badge + detail (#11 #14) ─────────────────────── */
.tp-cal-capacity-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  height: var(--tap);
  padding: 0 12px;
  cursor: pointer;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--fg-1);
  margin-left: var(--s-2);
  font-family: inherit;
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
  font-variant-numeric: tabular-nums;
}
.tp-cal-capacity-badge:hover { border-color: var(--border-strong); background: var(--bg-1); }
.tp-cal-capacity-badge:active { transform: translateY(1px); }
.tp-cal-capacity-badge.is-ok    { color: var(--green); border-color: color-mix(in srgb, var(--green) 35%, var(--border)); }
.tp-cal-capacity-badge.is-warn  { color: var(--orange); border-color: color-mix(in srgb, var(--orange) 35%, var(--border)); }
.tp-cal-capacity-badge.is-err   { color: var(--red); border-color: color-mix(in srgb, var(--red) 35%, var(--border)); }
/* Sobrecarga (>100%): tienes planificado MÁS de lo que cabe. Relleno rojo
   para que destaque sobre el simple "ocupación alta". */
.tp-cal-capacity-badge.is-overload {
  color: var(--red);
  background: var(--red-soft);
  border-color: var(--red);
  font-weight: 700;
}
.tp-cal-capacity-badge.is-neutral { color: var(--fg-2); }
.tp-cal-capacity-badge.is-loading { cursor: progress; }

/* #3 — botón "¿Qué hago ahora?" + modal de sugerencia */
.tp-cal-now-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 12px;
  min-height: 34px;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border));
  border-radius: var(--r-pill);
  font-weight: 600;
  font-size: var(--fs-sm);
  cursor: pointer;
  white-space: nowrap;
}
.tp-cal-now-btn:hover { background: var(--accent); color: var(--accent-fg); }
/* E2 — toggle "Solo eventos" (vista mes) */
.tp-cal-eventsonly-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 12px;
  min-height: 34px;
  background: var(--bg-2);
  color: var(--fg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  font-weight: 600;
  font-size: var(--fs-sm);
  cursor: pointer;
  white-space: nowrap;
}
.tp-cal-eventsonly-btn:hover { border-color: var(--accent); color: var(--accent); }
.tp-cal-eventsonly-btn.is-active {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}
.tp-nextaction-card { display: flex; flex-direction: column; gap: var(--s-2); }
.tp-nextaction-title { font-size: var(--fs-lg); font-weight: 700; color: var(--fg-0); }
.tp-nextaction-reason { color: var(--fg-1); }
.tp-nextaction-meta { color: var(--fg-2); font-size: var(--fs-sm); }
.tp-cal-readiness {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 4px 10px;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--bg-2);
  color: var(--fg-1);
  cursor: default;
  font-variant-numeric: tabular-nums;
}
.tp-cal-readiness.ok { color: var(--green); border-color: color-mix(in srgb, var(--green) 30%, var(--border)); }
.tp-cal-readiness.warn { color: var(--yellow); border-color: color-mix(in srgb, var(--yellow) 30%, var(--border)); }
.tp-cal-readiness.err { color: var(--red); border-color: color-mix(in srgb, var(--red) 30%, var(--border)); }
/* Oculto en móvil/PWA estrecha. Va DESPUÉS de la regla base para ganar en
   cascada (misma especificidad → vence el último). La info detallada vive en
   /app/settings/oura. */
@media (max-width: 768px) {
  .tp-cal-readiness { display: none; }
}
.tp-skel-pill {
  display: inline-block;
  width: 90px;
  height: 12px;
  border-radius: 8px;
  background: linear-gradient(90deg,
    var(--bg-2) 0%,
    color-mix(in srgb, var(--fg-3) 10%, var(--bg-2)) 50%,
    var(--bg-2) 100%);
  background-size: 200% 100%;
  animation: tp-skeleton-sweep 1.2s ease-in-out infinite;
}
@keyframes tp-skeleton-sweep {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.tp-capacity-detail { display: flex; flex-direction: column; gap: var(--s-3); }
/* Banner de veredicto de sobrecarga (#1): mensaje humano + días concretos. */
.tp-capacity-verdict {
  border-radius: var(--r-md);
  padding: var(--s-3);
  border: 1px solid var(--border);
  background: var(--bg-2);
}
.tp-capacity-verdict.is-over { border-color: var(--red); background: var(--red-soft); }
.tp-capacity-verdict.is-tight { border-color: var(--amber, #f59e0b); background: rgba(245, 158, 11, 0.12); }
.tp-capacity-verdict.is-ok { border-color: var(--green); background: var(--green-soft); }
.tp-capacity-verdict-msg { margin: 0; color: var(--fg-0); font-size: var(--fs-sm); font-weight: 500; }
.tp-capacity-verdict-days { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s-2); }
.tp-capacity-verdict-day {
  font-size: var(--fs-xs);
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--bg-3);
  color: var(--fg-1);
  white-space: nowrap;
}
.tp-capacity-head h3 {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--fg-0);
}
.tp-capacity-rows { display: flex; flex-direction: column; gap: 8px; }
.tp-capacity-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  animation: tp-row-in 0.25s ease-out backwards;
}
.tp-capacity-rows .tp-capacity-row:nth-child(2) { animation-delay: 30ms; }
.tp-capacity-rows .tp-capacity-row:nth-child(3) { animation-delay: 60ms; }
.tp-capacity-rows .tp-capacity-row:nth-child(4) { animation-delay: 90ms; }
.tp-capacity-rows .tp-capacity-row:nth-child(5) { animation-delay: 120ms; }
.tp-capacity-rows .tp-capacity-row:nth-child(6) { animation-delay: 150ms; }
.tp-capacity-rows .tp-capacity-row:nth-child(7) { animation-delay: 180ms; }
.tp-capacity-rows .tp-capacity-row:nth-child(8) { animation-delay: 210ms; }

.tp-capacity-row-head {
  display: flex;
  justify-content: space-between;
  font-variant-numeric: tabular-nums;
}
.tp-capacity-day {
  text-transform: capitalize;
  font-weight: 600;
  color: var(--fg-0);
}
.tp-capacity-nums {
  color: var(--fg-2);
  font-size: var(--fs-sm);
  display: flex;
  gap: var(--s-2);
  align-items: baseline;
}
.tp-capacity-nums strong {
  color: var(--fg-0);
  font-variant-numeric: tabular-nums;
}
.tp-capacity-label-busy { color: var(--fg-2); }
.tp-capacity-label-free { color: var(--fg-2); }
.tp-capacity-sep { color: var(--fg-3); }
.tp-capacity-legend {
  display: flex;
  gap: var(--s-4);
  margin-top: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--border-soft);
}
.tp-capacity-legend-item {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--fg-2);
}
.tp-capacity-legend-swatch {
  width: 12px;
  height: 12px;
  border-radius: 3px;
}
.tp-capacity-legend-swatch.demand { background: var(--accent); }
.tp-capacity-legend-swatch.free { background: rgba(34, 197, 94, 0.45); }
.tp-capacity-legend-swatch.past {
  background: repeating-linear-gradient(
    -45deg,
    var(--bg-3), var(--bg-3) 3px,
    color-mix(in srgb, var(--fg-2) 18%, var(--bg-3)) 3px,
    color-mix(in srgb, var(--fg-2) 18%, var(--bg-3)) 6px
  );
}

/* ─── Clockify Report ────────────────────────────────────────── */
.tp-ckr-controls {
  padding: 0 0 var(--s-4);
}
.tp-ckr-filters {
  display: flex;
  gap: var(--s-3);
  align-items: flex-end;
  flex-wrap: wrap;
  margin-bottom: var(--s-3);
}
.tp-ckr-filters .tp-input { width: 160px; }
.tp-ckr-filters .tp-form-label { margin: 0; font-size: var(--fs-sm); color: var(--fg-2); }
.tp-ckr-actions {
  display: flex;
  gap: var(--s-3);
  flex-wrap: wrap;
}
.tp-ckr-summary {
  display: flex;
  gap: var(--s-5);
  padding: var(--s-3) var(--s-4);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  margin-bottom: var(--s-4);
  font-size: var(--fs-sm);
  color: var(--fg-1);
}
.tp-ckr-summary strong { color: var(--accent); font-size: var(--fs-lg); }
.tp-ckr-desc { font-weight: 600; color: var(--fg-0); }
.tp-ckr-time { font-variant-numeric: tabular-nums; color: var(--accent); font-weight: 700; }
.tp-ckr-period { color: var(--fg-2); font-size: var(--fs-sm); white-space: nowrap; }
.tp-ckr-expand {
  padding: 4px 12px !important;
  min-height: 32px !important;
  font-size: var(--fs-sm);
  white-space: nowrap;
}
.tp-ckr-sortable {
  cursor: pointer;
  user-select: none;
  position: relative;
  padding-right: 18px !important;
}
.tp-ckr-sortable:hover { color: var(--fg-0); }
.tp-ckr-sortable::after {
  content: '⇅';
  position: absolute;
  right: 4px;
  opacity: 0.3;
  font-size: 11px;
}
.tp-ckr-sortable.asc::after { content: '↑'; opacity: 0.8; }
.tp-ckr-sortable.desc::after { content: '↓'; opacity: 0.8; }
.tp-ckr-mono {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
}
.tp-ckr-audit {
  padding: var(--s-3);
  background: var(--bg-2);
  border-radius: var(--r-md);
  /* La tabla de auditoría es una .tp-table (min-width 500px en móvil): que
     scrollee dentro de su contenedor en vez de desbordar la página. */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.tp-ckr-audit-table { margin: 0; font-size: var(--fs-sm); }
.tp-ckr-audit-table th { font-size: var(--fs-xs); }
.tp-ckr-audit-foot {
  border-top: 2px solid var(--border-strong);
}
.tp-ckr-audit-foot td {
  padding-top: var(--s-3) !important;
}
.tp-ckr-detail-row td { padding: 0 var(--s-3) var(--s-3) !important; }
.tp-ckr-entries {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--s-2) var(--s-3);
  background: var(--bg-2);
  border-radius: var(--r-sm);
}
.tp-ckr-entry {
  display: flex;
  gap: var(--s-4);
  padding: var(--s-2) 0;
  font-size: var(--fs-sm);
  border-bottom: 1px solid var(--border-soft);
}
.tp-ckr-entry:last-child { border-bottom: none; }
.tp-ckr-entry-date { color: var(--fg-1); min-width: 80px; }
.tp-ckr-entry-time { color: var(--fg-2); font-variant-numeric: tabular-nums; min-width: 100px; }
.tp-ckr-entry-dur { color: var(--accent); font-weight: 600; font-variant-numeric: tabular-nums; margin-left: auto; }
.tp-ckr-entry-src {
  align-self: center;
  font-size: var(--fs-xs);
  color: var(--fg-2);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  padding: 0 var(--s-2);
  white-space: nowrap;
}
.tp-ckr-entry.is-suggested { opacity: 0.65; }
.tp-ckr-entry-unlink {
  align-self: center;
  background: none;
  border: none;
  color: var(--fg-3, var(--fg-2));
  cursor: pointer;
  font-size: var(--fs-sm);
  line-height: 1;
  padding: 2px 6px;
  border-radius: var(--radius-sm, 6px);
}
.tp-ckr-entry-unlink:hover { color: var(--danger, #ef4444); background: var(--danger-soft, rgba(239,68,68,0.12)); }
.tp-ckr-entry-unlink:focus-visible { outline: 2px solid var(--danger, #ef4444); outline-offset: 1px; }
.tp-ckr-suggested-head {
  margin-top: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px dashed var(--border-soft);
  font-size: var(--fs-sm);
  color: var(--fg-2);
}

.tp-ckr-task-summary {
  padding: var(--s-3) 0;
  font-size: var(--fs-md);
  color: var(--fg-1);
  border-bottom: 1px solid var(--border-soft);
  margin-bottom: var(--s-3);
}
.tp-ckr-task-summary strong { color: var(--accent); }

@media (max-width: 540px) {
  /* Cada label ocupa fila propia y se pega al input siguiente, evitando que
     "Desde / Hasta / Buscar" queden flotando recortados a la derecha cuando
     el flex-wrap los empuja a posiciones intermedias. */
  .tp-ckr-filters {
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-1);
  }
  .tp-ckr-filters .tp-form-label {
    flex: 0 0 100%;
    margin-top: var(--s-2);
  }
  .tp-ckr-filters .tp-input {
    width: 100%;
    flex: 0 0 100%;
    margin-top: 4px;
  }
  .tp-ckr-actions { flex-direction: column; }
  .tp-ckr-actions .tp-btn { width: 100%; }
  .tp-ckr-summary { flex-direction: column; gap: var(--s-2); }

  /* Entradas individuales (dentro del detalle): que envuelvan en vez de
     desbordar por los min-width fijos de fecha/hora. */
  .tp-ckr-entry { flex-wrap: wrap; gap: var(--s-1) var(--s-3); }
  .tp-ckr-entry-date,
  .tp-ckr-entry-time { min-width: 0; }

  /* Tabla de reporte → cards apilados en mobile. La tabla nativa con scroll
     horizontal obligaba al usuario a deslizar para ver "Período" y "Auditar".
     Convertimos cada fila en una card vertical con labels (data-label). */
  .tp-ckr-table { display: block; }
  .tp-ckr-table thead { display: none; }
  .tp-ckr-table tbody { display: block; }
  .tp-ckr-table tbody tr.tp-ckr-row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: var(--s-1) var(--s-3);
    padding: var(--s-3);
    background: var(--bg-2);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    margin-bottom: var(--s-2);
  }
  .tp-ckr-table tbody tr.tp-ckr-detail-row {
    display: block;
    background: var(--bg-1);
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    margin: calc(-1 * var(--s-1)) 0 var(--s-2);
  }
  .tp-ckr-table tbody tr.tp-ckr-detail-row[hidden] { display: none; }
  .tp-ckr-table tbody tr.tp-ckr-detail-row td {
    display: block;
    padding: var(--s-3) !important;
    border: none;
  }
  .tp-ckr-table tbody td {
    display: block;
    border: none;
    padding: 0;
    font-size: var(--fs-sm);
  }
  .tp-ckr-table tbody td.tp-ckr-desc {
    grid-column: 1 / -1;
    font-size: var(--fs-md);
    font-weight: 600;
    color: var(--fg-0);
    padding-bottom: var(--s-2);
    border-bottom: 1px solid var(--border-soft);
    margin-bottom: var(--s-2);
  }
  .tp-ckr-table tbody td.tp-ckr-desc::before { content: none; }
  .tp-ckr-table tbody td[data-label]:not(.tp-ckr-desc)::before {
    content: attr(data-label) ":";
    display: inline-block;
    min-width: 90px;
    color: var(--fg-2);
    font-weight: 500;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-right: var(--s-2);
  }
  .tp-ckr-table tbody td.num { text-align: left; }
  .tp-ckr-table tbody td.tp-ckr-toggle {
    grid-column: 1 / -1;
    text-align: right;
    margin-top: var(--s-2);
  }
  .tp-ckr-table tbody td.tp-ckr-toggle::before { content: none; }
  .tp-ckr-table tbody .tp-ckr-expand {
    width: 100%;
  }
}

.tp-stats-verdict {
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  font-weight: 600;
  font-size: var(--fs-md);
  margin-top: var(--s-3);
}
.tp-stats-verdict.ok { background: var(--green-soft); color: var(--green); }
.tp-stats-verdict.warn { background: var(--yellow-soft); color: var(--yellow); }
.tp-stats-verdict.err { background: var(--red-soft); color: var(--red); }

.tp-completion-feedback { display: flex; flex-direction: column; gap: var(--s-2); }
.tp-completion-row {
  display: flex;
  justify-content: space-between;
  padding: var(--s-2) var(--s-3);
  background: var(--bg-2);
  border-radius: var(--r-sm);
}
.tp-completion-row span { color: var(--fg-2); }
.tp-completion-row strong { font-variant-numeric: tabular-nums; }
.tp-completion-row.result { border: 1px solid var(--border); }
.tp-completion-row.result.over strong { color: var(--red); }
.tp-completion-row.result.under strong { color: var(--yellow); }
.tp-completion-row.result.ok strong { color: var(--green); }
.tp-completion-advice {
  margin: var(--s-2) 0 0;
  font-size: var(--fs-sm);
  color: var(--fg-1);
  line-height: 1.5;
}
.tp-completion-advice.ok { color: var(--green); }
.tp-completion-advice strong { color: var(--accent); }

/* ─── Search results ─────────────────────────────────────────── */
.tp-search-row {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
  transition: background 0.1s;
}
.tp-search-row:hover { background: var(--bg-2); }
.tp-search-row:last-child { border-bottom: none; }
.tp-search-row .tp-pill { flex-shrink: 0; margin-top: 2px; }
.tp-search-info { flex: 1; min-width: 0; }
.tp-search-title {
  font-weight: 500;
  color: var(--fg-0);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tp-search-meta {
  font-size: var(--fs-sm);
  color: var(--fg-2);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ─── Dependencies ───────────────────────────────────────────── */
.tp-deps-section { margin-bottom: var(--s-4); }
.tp-deps-section:last-child { margin-bottom: 0; }
.tp-deps-title {
  margin: 0 0 var(--s-2);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg-0);
}
.tp-deps-hint {
  font-weight: 400;
  font-size: var(--fs-sm);
  color: var(--fg-3);
}
.tp-deps-list { display: flex; flex-direction: column; gap: 2px; }
.tp-deps-empty {
  color: var(--fg-3);
  font-size: var(--fs-sm);
  margin: 0;
  padding: var(--s-2) 0;
}
.tp-deps-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s-2) var(--s-3);
  background: var(--bg-2);
  border-radius: var(--r-sm);
}
.tp-deps-row:hover { background: var(--bg-3); }
.tp-deps-task-link {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--fg-0);
  text-decoration: none;
  font-size: var(--fs-md);
  min-width: 0;
  overflow: hidden;
}
.tp-deps-task-link:hover { color: var(--accent); }
.tp-deps-task-link span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tp-deps-status {
  flex-shrink: 0;
  width: 18px;
  text-align: center;
  color: var(--fg-3);
  font-size: var(--fs-md);
}
.tp-deps-status.done { color: var(--green); }
.tp-deps-add {
  display: flex;
  gap: var(--s-2);
  margin-top: var(--s-3);
  align-items: center;
}
.tp-deps-select { flex: 1; min-width: 0; }
.tp-deps-add .tp-btn {
  white-space: nowrap;
  padding: 6px 12px;
  font-size: var(--fs-sm);
  min-height: 36px;
}
@media (max-width: 540px) {
  .tp-deps-add { flex-direction: column; }
  .tp-deps-select { width: 100%; }
  .tp-deps-add .tp-btn { width: 100%; }
}

/* ─── Templates ──────────────────────────────────────────────── */
.tp-templates { padding: 0; }
.tp-tpl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--s-4);
}
.tp-tpl-card {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.tp-tpl-card-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.tp-tpl-name {
  font-weight: 700;
  font-size: var(--fs-lg);
  color: var(--fg-0);
}
.tp-tpl-meta {
  color: var(--fg-2);
  font-size: var(--fs-sm);
}
.tp-tpl-stats {
  color: var(--fg-3);
  font-size: var(--fs-xs);
}
.tp-tpl-actions {
  display: flex;
  gap: var(--s-2);
  margin-top: var(--s-2);
  align-items: center;
}
.tp-tpl-actions .tp-btn {
  padding: 4px 12px;
  font-size: var(--fs-sm);
  min-height: 32px;
}
@media (max-width: 540px) {
  .tp-tpl-grid { grid-template-columns: 1fr; }
}

/* ─── Plantillas (rediseño) ──────────────────────────────────── */
.tp-tpl-search {
  margin: 0 0 var(--s-3);
  max-width: 360px;
}
.tp-tpl-search[hidden] { display: none; }

.tp-tpl-card.recurring {
  border-left: 3px solid var(--accent);
}
.tp-tpl-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-2);
}
.tp-tpl-card-top .tp-tpl-name { flex: 1; min-width: 0; }

.tp-tpl-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.tp-tpl-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: 600;
  background: var(--bg-2);
  color: var(--fg-1);
  border: 1px solid var(--border);
  white-space: nowrap;
}
.tp-tpl-status {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-top: 2px;
}
.tp-tpl-next {
  font-size: var(--fs-xs);
  color: var(--fg-2);
}

/* Menú "⋯" de acciones secundarias */
.tp-tpl-menu { position: relative; margin-left: auto; }
.tp-tpl-menu > .tp-btn {
  padding: 4px 10px;
  font-size: var(--fs-md);
  line-height: 1;
}
.tp-tpl-menu-list {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 20;
  min-width: 150px;
  background: var(--bg-1);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  padding: 4px;
  display: flex;
  flex-direction: column;
}
.tp-tpl-menu-item {
  text-align: left;
  background: none;
  border: 0;
  color: var(--fg-1);
  font-size: var(--fs-sm);
  padding: 8px 10px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.tp-tpl-menu-item:hover { background: var(--bg-2); }
.tp-tpl-menu-item.danger { color: var(--red); }

/* Editor: rejilla de 2 columnas + controles de recurrencia */
.tp-form-grid2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-3);
}
.tp-rec-opts {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin-top: var(--s-2);
}
.tp-rec-row {
  display: flex;
  gap: var(--s-2);
  align-items: center;
}
.tp-rec-word {
  font-size: var(--fs-sm);
  color: var(--fg-1);
  white-space: nowrap;
}
.tp-rec-num { width: 72px; flex: 0 0 auto; }
.tp-rec-preview {
  background: var(--accent-soft);
  border-radius: var(--r-md);
  padding: 8px 10px;
}
@media (max-width: 540px) {
  .tp-form-grid2 { grid-template-columns: 1fr; }
}

/* ─── Weekly Review ──────────────────────────────────────────── */
.tp-review { display: flex; flex-direction: column; gap: var(--s-4); }
.tp-review-weeknav {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-left: auto;
}
.tp-review-weeklabel {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg-0);
  min-width: 180px;
  text-align: center;
}
.tp-review-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--s-3);
}
.tp-review-metric {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-4);
  text-align: center;
}
.tp-review-metric.ok { border-left: 3px solid var(--green); }
.tp-review-metric.warn { border-left: 3px solid var(--yellow); }
.tp-review-metric.err { border-left: 3px solid var(--red); }
.tp-review-metric-value {
  font-size: var(--fs-2xl);
  font-weight: 700;
  color: var(--fg-0);
  font-variant-numeric: tabular-nums;
}
.tp-review-metric-trend {
  font-size: var(--fs-sm);
  font-weight: 600;
  margin-left: var(--s-2);
  color: var(--fg-2);
}
.tp-review-metric-label {
  font-size: var(--fs-sm);
  color: var(--fg-2);
  margin-top: 2px;
}
.tp-review-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: var(--s-4);
}
.tp-review-tasksection .tp-card-body { padding: 0; }
/* Layout VERTICAL: el título ocupa su propia línea a ancho completo (antes lo
   aplastaban los botones a su lado, dejándolo en "Pu…"); debajo van los chips
   de info y, por último, la fila de acciones. */
.tp-review-taskrow {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border-soft);
}
.tp-review-taskrow:last-child { border-bottom: none; }
.tp-review-taskinfo { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
/* Título: botón reseteado que parece texto y abre la tarea al click. */
.tp-review-taskname {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  font-weight: 600;
  color: var(--fg-0);
  cursor: pointer;
  overflow-wrap: anywhere;
  line-height: 1.3;
}
.tp-review-taskname:hover { color: var(--accent); }
.tp-review-taskname:focus-visible { outline: none; color: var(--accent); text-decoration: underline; }
.tp-review-taskmeta {
  font-size: var(--fs-sm);
  color: var(--fg-2);
}
/* Chips de información (días parada, prioridad, fecha, estimación). */
.tp-review-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.tp-review-chip {
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-xs);
  line-height: 1;
  padding: 4px 8px;
  border-radius: var(--r-pill);
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--fg-1);
  white-space: nowrap;
}
.tp-review-chip.muted { color: var(--fg-3); }
.tp-review-chip.ok { border-color: var(--green); color: var(--green); }
.tp-review-chip.warn { border-color: var(--yellow); color: var(--yellow); }
.tp-review-chip.err {
  border-color: var(--red, #f87171);
  color: var(--red, #f87171);
  font-weight: 600;
}
.tp-review-taskactions {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
}
.tp-review-taskactions .tp-btn {
  padding: 6px 12px;
  font-size: var(--fs-sm);
  min-height: 34px;
  flex: 0 1 auto;
}
.tp-review-taskactions .tp-input {
  width: 140px;
  padding: 4px 8px;
  font-size: var(--fs-sm);
  min-height: 32px;
}
.tp-review-ai-output {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  margin-top: var(--s-4);
}
.tp-review-ai-card {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-4);
}
.tp-review-ai-card.ok { border-left: 3px solid var(--green); }
.tp-review-ai-card.warn { border-left: 3px solid var(--yellow); }
.tp-review-ai-card.accent { border-left: 3px solid var(--accent); }
.tp-review-ai-card h4 {
  margin: 0 0 var(--s-2);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg-0);
}
.tp-review-ai-card ul {
  margin: 0;
  padding-left: var(--s-5);
  list-style: disc;
  color: var(--fg-1);
  line-height: 1.7;
}
/* #8 — Botones de acciones ejecutables de la revisión semanal. */
.tp-review-ai-actions {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  align-items: flex-start;
}
.tp-review-ai-actions .tp-btn {
  margin: 0;
  width: 100%;
  justify-content: flex-start;
  text-align: left;
  white-space: normal;
}
.tp-review-ai-md {
  white-space: pre-wrap;
  background: var(--bg-2);
  padding: var(--s-4);
  border-radius: var(--r-md);
  color: var(--fg-1);
  line-height: 1.6;
}
@media (max-width: 768px) {
  .tp-review-cols { grid-template-columns: 1fr; }
  .tp-review-metrics { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 540px) {
  .tp-review-metrics { grid-template-columns: repeat(2, 1fr); }
  .tp-review-taskrow { flex-direction: column; align-items: stretch; gap: var(--s-2); }
  .tp-review-taskactions {
    justify-content: stretch;
    flex-wrap: wrap;
  }
  .tp-review-taskactions .tp-btn,
  .tp-review-taskactions .tp-input {
    flex: 1 1 auto;
    min-height: 40px;
    font-size: var(--fs-sm);
    padding: 8px 14px;
  }
  .tp-review-taskactions .tp-input { width: auto; }
  .tp-review-weeknav { margin-left: 0; flex-wrap: wrap; }
  .tp-review-weeklabel { min-width: 0; flex: 1 1 auto; }
}
/* #7 — Botones de acción masiva en las secciones de la review */
.tp-review-bulkrow {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
  margin-top: var(--s-2);
}
.tp-review-bulkbtn { font-size: var(--fs-sm); }

.tp-capacity-bar {
  /* Dos segmentos adyacentes (ocupado + libre). Colores sólidos (sin
     color-mix) para que se rendericen también en Safari/iOS antiguos. */
  height: 12px;
  background: var(--bg-3);
  border-radius: 6px;
  overflow: hidden;
  display: flex;
}
/* "Libre" verde claramente visible (rgba sólido, sin color-mix → compatible
   con Safari/iOS antiguos) y a juego con el swatch de la leyenda. El antiguo
   --green-soft (16% alpha) quedaba casi invisible sobre --bg-3. */
.tp-capacity-bar-avail { height: 100%; background: rgba(34, 197, 94, 0.45); }
.tp-capacity-bar-demand { height: 100%; background: var(--accent); }
/* Parte de la jornada de HOY ya transcurrida (escala fija de jornada
   completa): gris sutil con rayado para diferenciarla de "ocupado". */
.tp-capacity-bar-past {
  height: 100%;
  background: repeating-linear-gradient(
    -45deg,
    var(--bg-3), var(--bg-3) 4px,
    color-mix(in srgb, var(--fg-2) 18%, var(--bg-3)) 4px,
    color-mix(in srgb, var(--fg-2) 18%, var(--bg-3)) 8px
  );
}
/* Fines de semana: día libre, sin barra, etiqueta sutil. */
.tp-capacity-row.is-weekend {
  background: color-mix(in srgb, var(--bg-2) 50%, transparent);
  border-style: dashed;
  opacity: 0.7;
}
.tp-capacity-row.is-weekend .tp-capacity-day { color: var(--fg-2); }
.tp-capacity-weekend-tag {
  font-style: italic;
  color: var(--fg-3);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
/* #11 — Días de viaje en el popup de carga: como weekend pero con acento. */
.tp-capacity-trip-tag {
  font-style: italic;
  color: var(--accent);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ─── Selector de vista: variantes compactas (2d/3d/4d) ───────── */
.tp-cal-vbtn-compact {
  /* Más pequeño que las macro-vistas. En desktop quedan discretos; en
     mobile/tablet (donde son el caso de uso principal) ganan tamaño táctil
     vía la media query de abajo. */
  font-size: var(--fs-sm);
  padding: 0 8px;
  min-width: 32px;
  text-align: center;
}
@media (max-width: 880px) {
  .tp-cal-vbtn-compact {
    font-size: var(--fs-md);
    padding: 0 10px;
    min-width: 38px;
  }
  /* En mobile/tablet la macro-vista "Semana" sigue disponible pero ocupa
     más; los compact 2d/3d/4d son ahora el caso de uso principal. */
}
@media (max-width: 540px) {
  .tp-cal-viewswitch .tp-cal-vbtn[href$="/week"] { display: none; }
}

/* ─── Spinner inline (botones loading) ───────────────────────── */
.tp-spinner {
  display: inline-block;
  width: 12px;
  height: 12px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: tp-cal-ai-spin 0.7s linear infinite;
  vertical-align: -2px;
  margin-right: 6px;
}

/* ─── Animaciones reutilizables ──────────────────────────────── */
@keyframes tp-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes tp-fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes tp-modal-pop {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes tp-row-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes tp-bar-grow {
  from { transform: scaleX(0); transform-origin: left center; }
  to   { transform: scaleX(1); transform-origin: left center; }
}

@media (prefers-reduced-motion: reduce) {
  .tp-ai-preview-overlay,
  .tp-ai-preview,
  .tp-capacity-row,
  .tp-capacity-bar-avail,
  .tp-capacity-bar-demand,
  .tp-skel-pill { animation: none; }
  .tp-cal-block-rationale-text { transition: opacity 0.15s; }
}

/* ─── Responsive: tablet y móvil ─────────────────────────────── */
@media (max-width: 880px) {
  /* BUGFIX móvil: el preview IA era un bottom-sheet (flex-end + margin-top:
     auto) y aparecía pegado al borde inferior. Centrado en el viewport
     dinámico real (dvh), respetando safe-areas. */
  .tp-ai-preview {
    width: 100%;
    max-height: 92vh;
    max-height: calc(100dvh - 2 * var(--s-4));
    border-radius: var(--r-md);
  }
  .tp-ai-preview-overlay {
    align-items: center;
    padding:
      max(var(--s-2), env(safe-area-inset-top, 0))
      max(var(--s-2), env(safe-area-inset-right, 0))
      max(var(--s-2), env(safe-area-inset-bottom, 0))
      max(var(--s-2), env(safe-area-inset-left, 0));
  }
  .tp-ai-preview-head { padding: var(--s-3) var(--s-4); }
  .tp-ai-preview-body { padding: var(--s-3) var(--s-4); }
  .tp-ai-preview-foot {
    padding: var(--s-3) var(--s-4);
    position: sticky;
    bottom: 0;
  }
  .tp-cal-capacity-badge {
    /* En topbar móvil ya saturado, dejamos solo icono + pct. */
    padding: 0 10px;
  }
  .tp-cal-capacity-badge > span:last-child {
    font-size: var(--fs-xs);
  }
}
@media (max-width: 540px) {
  .tp-cal-capacity-badge { margin-left: 0; }
  .tp-ai-preview-actions { width: 100%; }
  .tp-ai-preview-actions .tp-btn { flex: 1; }
}

/* ─── #13 Grafo de dependencias (detalle de tarea) ───────────── */
.tp-deps-graph {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--s-2) 0 var(--s-3);
  margin-bottom: var(--s-3);
  border-bottom: 1px solid var(--border);
}
.tp-deps-graph svg { display: block; }
.tp-deps-edge {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1.5;
}
.tp-deps-edge.warn { stroke: var(--orange); stroke-width: 2; }
.tp-deps-edge-arrow { fill: var(--border-strong); }
.tp-deps-edge-arrow.warn { fill: var(--orange); }
.tp-deps-node rect {
  fill: var(--bg-2);
  stroke: var(--border-strong);
  stroke-width: 1.5;
}
.tp-deps-node text {
  fill: var(--fg-0);
  font-size: 12px;
  font-family: inherit;
}
.tp-deps-node:not(.is-current) { cursor: pointer; }
.tp-deps-node:not(.is-current):hover rect,
.tp-deps-node:not(.is-current):focus-visible rect {
  stroke: var(--accent);
  fill: color-mix(in srgb, var(--accent) 10%, var(--bg-2));
}
.tp-deps-node:focus-visible { outline: none; }
.tp-deps-node.is-current rect {
  fill: color-mix(in srgb, var(--accent) 20%, var(--bg-2));
  stroke: var(--accent);
  stroke-width: 2;
}
.tp-deps-node.is-current text { font-weight: 700; }
.tp-deps-node.is-done rect {
  fill: color-mix(in srgb, var(--green) 8%, var(--bg-2));
  stroke: color-mix(in srgb, var(--green) 45%, var(--border-strong));
}
.tp-deps-node.is-done text { fill: var(--fg-2); }
.tp-deps-node.is-blocking rect { stroke: var(--orange); }

/* ─── #17 Vista "Ahora" (/app/now) ───────────────────────────── */
.tp-now {
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
/* #2 — Tarjeta "Empieza por esto hoy" (cadena crítica). */
.tp-now-cp {
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: var(--r-lg, 14px);
  padding: var(--s-4);
}
.tp-now-cp-title {
  margin: 0 0 var(--s-3);
  font-size: var(--fs-md);
  color: var(--accent);
  display: flex;
  align-items: center;
  gap: 8px;
}
.tp-now-cp-list { display: flex; flex-direction: column; gap: var(--s-2); }
.tp-now-cp-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px;
  min-height: var(--tap);
  border-radius: var(--r-md);
  background: var(--bg-1);
  border: 1px solid var(--border);
  text-decoration: none;
  color: var(--fg-0);
  transition: border-color 0.15s, background 0.15s;
}
.tp-now-cp-item:hover { border-color: var(--accent); background: var(--bg-2); text-decoration: none; }
.tp-now-cp-item-title { font-weight: 600; font-size: var(--fs-sm); }
.tp-now-cp-item-reason { font-size: var(--fs-xs); color: var(--fg-2); }

/* #7 — Reconciliación matinal ("se quedó atrás"). Tono ámbar de aviso, para
   distinguirla de la tarjeta de cadena crítica (acento) y de la agenda. */
.tp-now-reconcile {
  background: color-mix(in srgb, var(--warning, #d98a00) 8%, var(--bg-1));
  border: 1px solid color-mix(in srgb, var(--warning, #d98a00) 45%, var(--border));
  border-radius: var(--r-lg, 14px);
  padding: var(--s-4);
}
.tp-now-reconcile-head { margin-bottom: var(--s-3); }
.tp-now-reconcile-title {
  margin: 0;
  font-size: var(--fs-md);
  color: var(--warning, #d98a00);
  display: flex;
  align-items: center;
  gap: 8px;
}
.tp-now-reconcile-sub { margin: 4px 0 0; font-size: var(--fs-xs); color: var(--fg-2); }
.tp-now-reconcile-list { display: flex; flex-direction: column; gap: var(--s-2); }
.tp-now-reconcile-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  padding: 10px 12px;
  border-radius: var(--r-md);
  background: var(--bg-1);
  border: 1px solid var(--border);
  transition: opacity 0.15s;
}
.tp-now-reconcile-item.is-busy { opacity: 0.5; pointer-events: none; }
.tp-now-reconcile-item-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 60%;
  min-width: 0;
  text-decoration: none;
  color: var(--fg-0);
}
.tp-now-reconcile-item-main:hover { text-decoration: none; }
.tp-now-reconcile-item-main:hover .tp-now-reconcile-item-title { color: var(--accent); }
.tp-now-reconcile-item-title {
  font-weight: 600;
  font-size: var(--fs-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tp-now-reconcile-item-meta { font-size: var(--fs-xs); color: var(--fg-2); }
.tp-now-reconcile-actions {
  display: flex;
  gap: 6px;
  flex: 1 1 auto;
  flex-wrap: wrap;
}
.tp-now-reconcile-btn {
  min-height: var(--tap);
  padding: 6px 12px;
  font-size: var(--fs-xs);
  flex: 1 1 auto;
}
.tp-now-reconcile-foot { margin-top: var(--s-3); }
.tp-now-reconcile-foot .tp-btn { width: 100%; }
@media (min-width: 560px) {
  .tp-now-reconcile-actions { flex: 0 0 auto; }
  .tp-now-reconcile-btn { flex: 0 0 auto; }
  .tp-now-reconcile-foot .tp-btn { width: auto; }
}
.tp-now-clock {
  margin-left: auto;
  color: var(--fg-2);
  font-size: var(--fs-sm);
  text-transform: capitalize;
  font-variant-numeric: tabular-nums;
}
.tp-now-card {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  box-shadow: var(--shadow-sm);
}
.tp-now-card.is-current {
  border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
  border-left-width: 4px;
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--accent) 7%, var(--bg-1)),
    var(--bg-1));
}
.tp-now-card-tag {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--accent);
  margin-bottom: var(--s-2);
}
.tp-now-card.is-upcoming .tp-now-card-tag { color: var(--fg-2); }
.tp-now-live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--green);
  animation: tp-now-pulse 1.6s ease-in-out infinite;
}
@keyframes tp-now-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
@media (prefers-reduced-motion: reduce) {
  .tp-now-live-dot { animation: none; }
}
.tp-now-card-title {
  margin: 0 0 var(--s-1);
  font-size: var(--fs-2xl);
  line-height: 1.25;
  color: var(--fg-0);
  overflow-wrap: anywhere;
}
.tp-now-card-time {
  color: var(--fg-1);
  font-size: var(--fs-md);
  font-variant-numeric: tabular-nums;
}
.tp-now-progress {
  margin-top: var(--s-3);
  height: 8px;
  background: var(--bg-3);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.tp-now-progress-fill {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--accent), #a855f7);
  transition: width 0.4s ease;
}
.tp-now-remaining {
  margin-top: var(--s-1);
  font-size: var(--fs-sm);
  color: var(--fg-2);
  font-variant-numeric: tabular-nums;
}
.tp-now-rationale {
  margin: var(--s-3) 0 0;
  font-size: var(--fs-sm);
  color: var(--fg-2);
  background: color-mix(in srgb, #7c3aed 8%, var(--bg-1));
  border-radius: var(--r-sm);
  padding: var(--s-2) var(--s-3);
}
.tp-now-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-4);
}
.tp-now-actions .tp-btn { min-height: var(--tap); }
.tp-now-next {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-left: 4px solid var(--border-strong);
  border-radius: var(--r-md);
  padding: var(--s-3) var(--s-4);
}
.tp-now-next-tag {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-2);
}
.tp-now-next-title {
  margin-top: 2px;
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--fg-0);
  overflow-wrap: anywhere;
}
.tp-now-next-time {
  font-size: var(--fs-sm);
  color: var(--fg-2);
  font-variant-numeric: tabular-nums;
}
.tp-now-later h4 {
  margin: 0 0 var(--s-2);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--fg-2);
}
.tp-now-later-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border-bottom: 1px solid var(--border);
  min-height: var(--tap);
}
.tp-now-later-row:last-child { border-bottom: 0; }
.tp-now-later-row.is-clickable { cursor: pointer; }
.tp-now-later-row.is-clickable:hover { background: var(--bg-2); border-radius: var(--r-sm); }
.tp-now-later-time {
  font-variant-numeric: tabular-nums;
  color: var(--fg-1);
  font-size: var(--fs-sm);
  min-width: 44px;
}
.tp-now-later-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
}
.tp-now-later-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--fg-0);
}
.tp-now-later-kind {
  font-size: var(--fs-xs);
  color: var(--fg-3);
  white-space: nowrap;
}
.tp-now-empty {
  text-align: center;
  padding: var(--s-7) var(--s-4);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
}
.tp-now-empty-icon { font-size: 44px; }
.tp-now-empty h3 { margin: 0; color: var(--fg-0); }
.tp-now-empty p { margin: 0; color: var(--fg-2); max-width: 40ch; }
/* Móvil: tarjeta principal más compacta, acciones a ancho completo. */
@media (max-width: 540px) {
  .tp-now-card { padding: var(--s-4); }
  .tp-now-card-title { font-size: var(--fs-xl); }
  .tp-now-actions .tp-btn { flex: 1 1 calc(50% - var(--s-1)); }
}

/* ─── #5 Calibración de estimaciones (Ajustes → IA) ──────────── */
.tp-ai-calibration {
  margin-top: var(--s-4);
  padding-top: var(--s-3);
  border-top: 1px solid var(--border);
}
.tp-ai-calibration-title {
  font-weight: 600;
  font-size: var(--fs-md);
  color: var(--fg-0);
  margin-bottom: var(--s-1);
}
/* #3 — Banner de calibración dentro del preview de la IA. */
.tp-ai-calib-banner {
  margin: 0 var(--s-4) var(--s-2);
  padding: 8px 12px;
  border-radius: var(--r-md);
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  color: var(--fg-1);
  font-size: var(--fs-xs);
}
.tp-ai-calibration-rows {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: var(--s-2);
}
.tp-ai-calibration-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 6px 0;
  border-bottom: 1px dashed var(--border);
  font-size: var(--fs-sm);
}
.tp-ai-calibration-row:last-child { border-bottom: 0; }
.tp-ai-calibration-name { flex: 1; color: var(--fg-1); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tp-ai-calibration-factor { font-weight: 600; color: var(--fg-0); white-space: nowrap; }
.tp-ai-calibration-factor.warn { color: var(--orange); }
.tp-ai-calibration-factor.ok { color: var(--green); }
.tp-ai-calibration-n { color: var(--fg-2); font-size: var(--fs-xs); white-space: nowrap; }

/* ─── APCu cache panel ──────────────────────────────────────── */
.tp-apcu-status-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}
.tp-apcu-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}
.tp-apcu-stat {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-3) var(--s-4);
  text-align: center;
}
.tp-apcu-stat-value {
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.tp-apcu-stat-label {
  font-size: var(--fs-sm);
  color: var(--fg-2);
  margin-top: 2px;
}
.tp-apcu-ttl-info {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-4);
  margin-bottom: var(--s-4);
}
.tp-apcu-ttl-info h4 {
  margin: 0 0 var(--s-2);
  font-size: var(--fs-md);
  color: var(--fg-0);
  font-weight: 600;
}
.tp-apcu-ttl-info ul {
  margin: 0;
  padding-left: var(--s-5);
  list-style: disc;
  color: var(--fg-1);
  font-size: var(--fs-sm);
  line-height: 1.7;
}
.tp-apcu-ttl-info li strong {
  color: var(--fg-0);
}
.tp-apcu-actions {
  display: flex;
  gap: var(--s-3);
  flex-wrap: wrap;
}
@media (max-width: 540px) {
  .tp-apcu-grid { grid-template-columns: repeat(2, 1fr); }
  .tp-apcu-actions { flex-direction: column; }
  .tp-apcu-actions .tp-btn { width: 100%; }
}

/* ─── Sessions table ─────────────────────────────────────────── */
.tp-sessions-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.tp-sessions-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.tp-sessions-table th {
  text-align: left;
  padding: var(--s-2) var(--s-3);
  color: var(--fg-2);
  font-weight: 600;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 2px solid var(--border);
  white-space: nowrap;
}
.tp-sessions-table td {
  padding: var(--s-3);
  border-bottom: 1px solid var(--border-soft);
  vertical-align: middle;
}
.tp-sessions-table tbody tr:last-child td {
  border-bottom: none;
}
.tp-sessions-table tbody tr:hover {
  background: var(--bg-2);
}
.tp-sessions-device {
  font-weight: 600;
  color: var(--fg-0);
  white-space: nowrap;
}
.tp-sessions-ip {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--fg-2);
}
.tp-sessions-date {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.tp-sessions-date .dim {
  font-size: var(--fs-xs);
  color: var(--fg-3);
  margin-top: 1px;
}
.tp-sessions-action {
  text-align: right;
  white-space: nowrap;
}
@media (max-width: 768px) {
  .tp-sessions-table th:nth-child(3),
  .tp-sessions-table td:nth-child(3),
  .tp-sessions-table th:nth-child(5),
  .tp-sessions-table td:nth-child(5) {
    display: none;
  }
}
@media (max-width: 540px) {
  .tp-sessions-table th:nth-child(2),
  .tp-sessions-table td:nth-child(2) {
    display: none;
  }
}

/* ─── Planning settings (radio + check rows) ─────────────────── */
.tp-radio-group,
.tp-trigger-list {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin-top: 6px;
}
.tp-radio-row,
.tp-check-row {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  padding: 10px 12px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.tp-radio-row:hover,
.tp-check-row:hover { border-color: var(--border-strong); }
.tp-radio-row:has(input:checked),
.tp-check-row:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--bg-2));
}
.tp-radio-row > input,
.tp-check-row > input {
  margin-top: 2px;
  flex-shrink: 0;
}
.tp-radio-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: 1.4;
}
.tp-radio-text strong { color: var(--fg-0); font-weight: 600; }
.tp-radio-desc { color: var(--fg-2); font-size: var(--fs-sm); }

.tp-card-divider {
  height: 1px;
  background: var(--border);
  margin: var(--s-4) 0 var(--s-3);
}
.tp-form-subtitle {
  margin: 0 0 4px;
  font-size: var(--fs-md);
  color: var(--fg-0);
  font-weight: 600;
}

/* ─── Productivity dashboard ─────────────────────────────────── */
.tp-prod-wrap { display: flex; flex-direction: column; gap: var(--s-4); }
.tp-prod-dual {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-4);
  align-items: start;
}
.tp-prod-card .tp-card-body { padding: var(--s-4); }

.tp-prod-metric {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-3);
  text-align: center;
}
.tp-prod-metric-label { font-size: var(--fs-sm); color: var(--fg-2); margin-bottom: 2px; }
.tp-prod-metric-value { font-size: var(--fs-xl); font-weight: 700; color: var(--fg-0); font-variant-numeric: tabular-nums; }
.tp-prod-metrics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: var(--s-3);
  margin-top: var(--s-3);
}

.tp-prod-trend-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-3);
}
.tp-prod-trend-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
}
.tp-prod-trend-bars {
  display: flex;
  gap: 4px;
  height: 80px;
  align-items: flex-end;
}
.tp-prod-trend-bar-wrap {
  width: 24px;
  height: 100%;
  display: flex;
  align-items: flex-end;
}
.tp-prod-trend-bar {
  width: 100%;
  border-radius: 3px 3px 0 0;
  min-height: 2px;
  transition: height 0.3s ease;
}
.tp-prod-trend-bar--tasks { background: var(--accent); }
.tp-prod-trend-bar--hours { background: var(--green); }
.tp-prod-trend-vals {
  display: flex;
  gap: var(--s-2);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.tp-prod-trend-val--tasks { color: var(--accent); font-weight: 600; }
.tp-prod-trend-val--hours { color: var(--green); font-weight: 600; }
.tp-prod-trend-label { font-size: var(--fs-xs); color: var(--fg-3); }
.tp-prod-trend-legend {
  display: flex;
  gap: var(--s-4);
  margin-top: var(--s-3);
  justify-content: center;
}
.tp-prod-trend-legend-item { display: flex; align-items: center; gap: var(--s-2); font-size: var(--fs-sm); color: var(--fg-2); }
.tp-prod-trend-swatch { width: 12px; height: 12px; border-radius: 3px; }
.tp-prod-trend-swatch--tasks { background: var(--accent); }
.tp-prod-trend-swatch--hours { background: var(--green); }

.tp-prod-ratio {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4);
  border-radius: var(--r-md);
  background: var(--bg-2);
  border: 1px solid var(--border);
}
.tp-prod-ratio--green { border-left: 4px solid var(--green); }
.tp-prod-ratio--yellow { border-left: 4px solid var(--yellow); }
.tp-prod-ratio--red { border-left: 4px solid var(--red); }
.tp-prod-ratio-value { font-size: var(--fs-2xl); font-weight: 700; font-variant-numeric: tabular-nums; }
.tp-prod-ratio--green .tp-prod-ratio-value { color: var(--green); }
.tp-prod-ratio--yellow .tp-prod-ratio-value { color: var(--yellow); }
.tp-prod-ratio--red .tp-prod-ratio-value { color: var(--red); }
.tp-prod-ratio-text { font-size: var(--fs-md); color: var(--fg-1); }

.tp-heatmap-wrap { overflow-x: auto; }
.tp-heatmap-grid { display: flex; flex-direction: column; gap: 2px; min-width: 400px; }
.tp-heatmap-row { display: flex; gap: 2px; }
.tp-heatmap-header { margin-bottom: var(--s-1); }
.tp-heatmap-label {
  width: 50px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 6px;
  font-size: 11px;
  color: var(--fg-3);
  font-variant-numeric: tabular-nums;
}
.tp-heatmap-day-label {
  flex: 1;
  text-align: center;
  font-size: 11px;
  color: var(--fg-2);
  font-weight: 600;
}
.tp-heatmap-cell {
  flex: 1;
  aspect-ratio: 2;
  border-radius: 2px;
  min-height: 14px;
  cursor: default;
}
.tp-heatmap-legend {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: var(--s-3);
  justify-content: flex-end;
}
.tp-heatmap-legend-label { font-size: 11px; color: var(--fg-3); margin: 0 4px; }
.tp-heatmap-legend-swatch { width: 16px; height: 16px; border-radius: 3px; }

.tp-prod-top-wrap { overflow-x: auto; }
.tp-prod-top-bar-cell { width: 120px; }
.tp-prod-top-bar {
  height: 8px;
  background: var(--bg-3);
  border-radius: 4px;
  overflow: hidden;
}
.tp-prod-top-bar-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 4px;
}

.tp-prod-oura-summary { margin-bottom: var(--s-3); }
.tp-prod-oura-readiness { font-size: var(--fs-lg); color: var(--fg-0); margin: 0 0 var(--s-2); }
.tp-prod-oura-readiness strong { color: var(--accent); }
.tp-prod-oura-corr { color: var(--fg-1); margin: 0; line-height: 1.5; }

@media (max-width: 768px) {
  .tp-prod-dual { grid-template-columns: 1fr; }
}
@media (max-width: 540px) {
  .tp-prod-trend-grid { grid-template-columns: repeat(2, 1fr); }
  .tp-prod-metrics-grid { grid-template-columns: repeat(2, 1fr); }
  .tp-prod-ratio { flex-direction: column; text-align: center; }
}

/* ─── Template recurrence badge ──────────────────────────────── */
.tp-tpl-rec {
  font-size: var(--fs-sm);
  color: var(--accent);
  font-weight: 600;
}

/* ════════════════════════════════════════════════════════════════
   RESPONSIVE GLOBAL — reglas que aplican a múltiples componentes
   ════════════════════════════════════════════════════════════════ */

@media (max-width: 768px) {
  /* Safe-area en los 4 lados: este bloque (RESPONSIVE GLOBAL) es posterior al
     bloque de layout y, al usar `padding` shorthand, antes reseteaba el
     padding-top con safe-area que sí ponía aquel → el topbar (flechas de día)
     quedaba bajo el notch en PWA iOS. Lo reincorporamos. */
  .tp-main {
    padding:
      calc(var(--s-3) + env(safe-area-inset-top, 0))
      max(var(--s-3), env(safe-area-inset-right, 0))
      calc(var(--s-3) + 64px + env(safe-area-inset-bottom, 0))
      max(var(--s-3), env(safe-area-inset-left, 0));
  }
  .tp-topbar h2 { font-size: var(--fs-lg); }
  .tp-modal { width: 96vw; max-width: none; }
  .tp-modal-overlay { padding: var(--s-2); }
  .tp-table-wrap, .tp-sessions-table-wrap, .tp-ckr-body { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tp-table { min-width: 500px; }
  .tp-card-body { padding: var(--s-3); }
  .tp-form .tp-input,
  .tp-form select,
  .tp-form textarea { font-size: 16px; }
  .tp-review-weeknav { margin-left: 0; width: 100%; justify-content: space-between; }
}
@media (max-width: 540px) {
  .tp-main {
    padding:
      calc(var(--s-2) + env(safe-area-inset-top, 0))
      max(var(--s-2), env(safe-area-inset-right, 0))
      calc(var(--s-2) + 64px + env(safe-area-inset-bottom, 0))
      max(var(--s-2), env(safe-area-inset-left, 0));
  }
  .tp-topbar { gap: var(--s-2); margin-bottom: var(--s-3); }
  .tp-topbar h2 { font-size: var(--fs-md); }
  .tp-card header { padding: var(--s-3) var(--s-3) 0; }
  .tp-card header h3 { font-size: var(--fs-md); }
  .tp-btn { font-size: var(--fs-sm); padding: 8px 12px; }
  .tp-btn.primary { padding: 10px 16px; }
  /* BUGFIX móvil: antes los modales se anclaban abajo (align-items: flex-end
     + margin-top: auto) como bottom-sheet, y en smartphones aparecían "muy
     abajo" con todo el espacio vacío encima (loading IA, carga semanal, etc.).
     Ahora quedan centrados en el viewport visible real (dvh) respetando las
     safe-areas de iOS. */
  .tp-modal {
    border-radius: var(--r-md);
    max-height: 88vh;
    max-height: calc(100dvh - 2 * var(--s-5));
  }
  .tp-modal-overlay {
    align-items: center;
    padding:
      max(var(--s-2), env(safe-area-inset-top, 0))
      max(var(--s-2), env(safe-area-inset-right, 0))
      max(var(--s-2), env(safe-area-inset-bottom, 0))
      max(var(--s-2), env(safe-area-inset-left, 0));
  }
  .tp-task-row { padding: var(--s-2) var(--s-3); gap: var(--s-2); }
  .tp-task-row .title { font-size: var(--fs-sm); }
  .tp-search-row { padding: var(--s-2) var(--s-3); }
  .tp-tpl-grid { grid-template-columns: 1fr; }
  .tp-tpl-card { padding: var(--s-3); }
}

@media (max-width: 600px) {
  .tp-review-metrics { grid-template-columns: repeat(2, 1fr); }
  .tp-review-metric { padding: var(--s-3); }
  .tp-review-metric-value { font-size: var(--fs-xl); }
  .tp-review-cols { grid-template-columns: 1fr; }
  .tp-review-taskrow { flex-direction: column; align-items: stretch; gap: var(--s-2); }
  .tp-review-taskactions { justify-content: flex-start; flex-wrap: wrap; }
  .tp-ckr-filters { flex-direction: column; }
  .tp-ckr-filters .tp-input { width: 100%; }
  .tp-ckr-actions { flex-direction: column; }
  .tp-ckr-actions .tp-btn { width: 100%; }
  .tp-ckr-summary { flex-direction: column; gap: var(--s-2); }
  .tp-apcu-grid { grid-template-columns: repeat(2, 1fr); }
  .tp-apcu-actions { flex-direction: column; }
  .tp-apcu-actions .tp-btn { width: 100%; }
  .tp-deps-add { flex-direction: column; }
  .tp-deps-select { width: 100%; }
  .tp-deps-add .tp-btn { width: 100%; }
}
@media (max-width: 380px) {
  .tp-review-metrics { grid-template-columns: 1fr; }
}

/* ─── File Upload Component ─────────────────────────────────── */

.tp-file-upload {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.tp-file-upload-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-5) var(--s-4);
  border: 2px dashed var(--border);
  border-radius: var(--r-md);
  background: var(--bg-0);
  color: var(--fg-2);
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
  min-height: 80px;
  text-align: center;
}
.tp-file-upload-drop:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-0));
}
.tp-file-upload-drop.is-over {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, var(--bg-0));
  border-style: solid;
}
.tp-file-upload-drop.is-disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}
.tp-file-upload-drop-icon {
  font-size: 28px;
  line-height: 1;
  opacity: 0.6;
}
.tp-file-upload-drop-text {
  line-height: 1.4;
}
.tp-file-upload-drop-hint {
  font-size: var(--fs-xs);
  color: var(--fg-3);
}
.tp-file-upload-input {
  display: none;
}
.tp-file-upload-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.tp-file-upload-item {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: 8px 10px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: opacity 0.15s, background 0.15s;
}
.tp-file-upload-item:hover {
  background: color-mix(in srgb, var(--bg-2) 80%, var(--bg-1));
}
.tp-file-upload-item.is-uploading {
  opacity: 0.7;
}
.tp-file-upload-item.is-error {
  border-color: var(--red);
  background: color-mix(in srgb, var(--red) 8%, var(--bg-2));
}
.tp-file-upload-item-thumb {
  width: 40px;
  height: 40px;
  border-radius: var(--r-sm);
  overflow: hidden;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-0);
  border: 1px solid var(--border);
  font-size: 18px;
  color: var(--fg-2);
}
.tp-file-upload-item-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tp-file-upload-item-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tp-file-upload-item-name {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--fg-0);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tp-file-upload-item-name a {
  color: inherit;
  text-decoration: none;
}
.tp-file-upload-item-name a:hover {
  color: var(--accent);
  text-decoration: underline;
}
.tp-file-upload-item-size {
  font-size: var(--fs-xs);
  color: var(--fg-3);
}
.tp-file-upload-item-progress {
  height: 3px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
  margin-top: 2px;
}
.tp-file-upload-item-progress-bar {
  height: 100%;
  background: var(--accent);
  border-radius: 2px;
  transition: width 0.2s;
  width: 0%;
}
.tp-file-upload-item-del {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--fg-2);
  cursor: pointer;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  transition: background 0.1s, color 0.1s;
}
.tp-file-upload-item-del:hover {
  background: color-mix(in srgb, var(--red) 18%, transparent);
  color: var(--red);
}
.tp-file-upload-empty {
  color: var(--fg-3);
  font-size: var(--fs-sm);
  text-align: center;
  padding: var(--s-2) 0;
}
@media (max-width: 480px) {
  .tp-file-upload-drop { padding: var(--s-3); min-height: 60px; }
  .tp-file-upload-item-thumb { width: 32px; height: 32px; }
}

/* ════════════════════════════════════════════════════════════════
   Análisis de trabajo (/app/work-analytics) — tp-wa-*
   Reutiliza tp-prod-*, tp-heatmap-* y tp-ckr-* para tablas y KPIs.
   ════════════════════════════════════════════════════════════════ */

.tp-wa-presets {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
  align-items: center;
}
.tp-wa-preset {
  font-size: var(--fs-sm);
  padding: 6px 12px;
}

/* Barras apiladas por día */
.tp-wa-chart {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 220px;
  padding: var(--s-3) 0 var(--s-2);
  overflow-x: auto;
}
.tp-wa-chart-col {
  flex: 1 1 0;
  min-width: 6px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  height: 100%;
}
.tp-wa-chart-bar {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column-reverse;
  justify-content: flex-start;
  border-radius: 2px 2px 0 0;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.02);
}
.tp-wa-chart-seg {
  width: 100%;
  min-height: 1px;
}
.tp-wa-chart-label {
  flex: 0 0 auto;
  font-size: 10px;
  color: var(--fg-2);
  text-align: center;
  white-space: nowrap;
  overflow: visible;
  height: 14px;
  margin-top: 2px;
}

/* Leyenda */
.tp-wa-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  margin-top: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--fg-1);
}
.tp-wa-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.tp-wa-legend-swatch {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  display: inline-block;
}
.tp-wa-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  display: inline-block;
  vertical-align: baseline;
}

/* Tablas de análisis */
.tp-wa-table th,
.tp-wa-table td {
  white-space: nowrap;
}
.tp-wa-table td:first-child {
  white-space: normal;
  max-width: 280px;
  overflow-wrap: anywhere;
}
.tp-wa-examples {
  max-width: 320px;
  white-space: normal !important;
  color: var(--fg-2);
  font-size: var(--fs-sm);
  overflow-wrap: anywhere;
}
.tp-wa-more {
  margin-top: var(--s-3);
}

/* Conclusiones */
.tp-wa-conclusions {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.tp-wa-conclusion {
  padding: var(--s-3) var(--s-4);
  border-left: 3px solid var(--accent);
  background: var(--bg-2);
  border-radius: var(--r-sm);
}
.tp-wa-conclusion-text {
  color: var(--fg-0);
  font-size: var(--fs-md);
}
.tp-wa-conclusion-evidence {
  color: var(--fg-2);
  font-size: var(--fs-sm);
  margin-top: 4px;
  font-family: var(--font-mono);
}

@media (max-width: 640px) {
  .tp-wa-chart { height: 160px; }
  .tp-wa-table td:first-child { max-width: 160px; }
  .tp-wa-examples { max-width: 160px; }
}

/* #8 — Barra de consulta en lenguaje natural (inbox). */
.tp-ask-bar {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  margin: var(--s-2) 0 var(--s-3);
}
.tp-ask-input { flex: 1 1 auto; }
@media (max-width: 640px) {
  .tp-ask-bar { flex-wrap: wrap; }
}

/* #7 — Plantillas de día. */
.tp-daytpl-anchors { display: flex; flex-direction: column; gap: var(--s-1); margin-bottom: var(--s-3); }
.tp-daytpl-anchor { display: flex; align-items: center; gap: var(--s-2); font-size: var(--fs-sm); }
.tp-daytpl-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.tp-daytpl-time { font-family: var(--font-mono); color: var(--fg-2); min-width: 96px; }
.tp-daytpl-label { color: var(--fg-0); }
.tp-daytpl-apply { display: flex; gap: var(--s-2); align-items: center; margin: var(--s-2) 0; }
.tp-daytpl-actions { display: flex; gap: var(--s-2); }
.tp-daytpl-editor-rows { display: flex; flex-direction: column; gap: var(--s-2); }
.tp-daytpl-editor-row { display: flex; gap: var(--s-2); align-items: center; }
.tp-daytpl-editor-row .tp-input { min-width: 0; }
.tp-daytpl-color { width: 44px; flex: 0 0 auto; padding: 2px; }
@media (max-width: 640px) {
  .tp-daytpl-editor-row { flex-wrap: wrap; }
}

/* ─── Sección Long Range (tareas comodín) ───────────────────────── */
.tp-lr-controls {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
}
.tp-lr-sort { width: auto; min-width: 150px; }
.tp-lr-arch-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--fg-2);
  font-size: var(--fs-sm);
  cursor: pointer;
  white-space: nowrap;
}

/* Barra de creación */
.tp-lr-create {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: var(--s-4);
}
.tp-lr-create-title { flex: 1 1 240px; min-width: 0; }
.tp-lr-create-tag { flex: 0 1 220px; min-width: 0; }
.tp-lr-create-btn { flex: 0 0 auto; }
.tp-lr-create-hint {
  flex: 1 0 100%;
  color: var(--fg-3);
  font-size: var(--fs-sm);
  margin-top: var(--s-1);
}

/* Lista de filas compactas */
.tp-lr-list { display: flex; flex-direction: column; gap: 4px; }
.tp-lr-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: background 0.12s ease, border-color 0.12s ease;
}
.tp-lr-row:hover { background: var(--bg-2); }
.tp-lr-row.is-running {
  border-color: var(--green);
  box-shadow: inset 3px 0 0 0 var(--green);
}
.tp-lr-info {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
}
.tp-lr-title {
  font-weight: 600;
  color: var(--fg-0);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tp-lr-info:hover .tp-lr-title { color: var(--accent); }
.tp-lr-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-sm);
  color: var(--fg-2);
}
.tp-lr-time { font-variant-numeric: tabular-nums; }
.tp-lr-row.is-running .tp-lr-time { color: var(--green); font-weight: 600; }
.tp-lr-dot { color: var(--fg-3); }
.tp-lr-when { color: var(--fg-3); }

.tp-lr-actions {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex: 0 0 auto;
}
.tp-lr-timer-btn { min-width: 96px; }
.tp-lr-timer-btn.is-running {
  background: var(--green);
  border-color: var(--green);
  color: #08130b;
}
.tp-lr-del-btn { padding-left: var(--s-2); padding-right: var(--s-2); }

@media (max-width: 640px) {
  .tp-lr-row { flex-wrap: wrap; }
  .tp-lr-actions { width: 100%; justify-content: flex-end; }
  .tp-lr-timer-btn { flex: 1 1 auto; }
  .tp-lr-create-tag { flex: 1 1 160px; }
}

/* ─── Edición en lote (SelectionManager → modal "Editar N tareas") ── */
.tp-bulk-edit { display: flex; flex-direction: column; gap: var(--s-4); }
.tp-bulk-field { display: flex; flex-direction: column; gap: 6px; }

/* #13 — Modal de creación por lotes. */
.tp-batch { display: flex; flex-direction: column; gap: var(--s-3); min-width: min(520px, 82vw); }
.tp-batch-lines { resize: vertical; min-height: 120px; font-family: inherit; }
.tp-batch-counter { margin: 0; }
.tp-batch-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-3);
}
.tp-batch-field { display: flex; flex-direction: column; gap: 4px; }
.tp-batch-prio { display: flex; gap: 6px; }
.tp-batch-prio-btn { flex: 1; margin: 0; padding: 8px 0; min-height: var(--tap); }
.tp-batch-prio-btn.is-active { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
.tp-inbox-batch-btn { margin-left: auto; }
@media (max-width: 560px) {
  .tp-batch-grid { grid-template-columns: 1fr; }
}
.tp-bulk-due-input { margin-top: 2px; }
.tp-bulk-tags { display: flex; flex-wrap: wrap; gap: 6px; max-height: 220px; overflow-y: auto; }
.tp-bulk-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--bg-2);
  color: var(--fg-1);
  font-size: var(--fs-sm);
  cursor: pointer;
  min-height: var(--tap);
}
.tp-bulk-tag input { margin: 0; }

/* Sugerencias de compromisos */
.tp-sugg-badge {
  display: inline-block;
  margin-left: var(--s-2);
  min-width: 20px;
  padding: 1px 6px;
  font-size: var(--fs-xs);
  font-weight: 700;
  text-align: center;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--accent-fg);
}
.tp-sugg-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-2); }
.tp-sugg-item {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding: var(--s-3);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  background: var(--bg-2);
}
.tp-sugg-dot { flex: 0 0 auto; width: 10px; height: 10px; margin-top: 6px; border-radius: 50%; }
.tp-sugg-body { flex: 1 1 240px; min-width: 0; }
.tp-sugg-when { margin-top: 2px; font-size: var(--fs-sm); }
.tp-sugg-meta { margin-top: 2px; font-size: var(--fs-xs); color: var(--fg-2); }
.tp-sugg-msg {
  margin: var(--s-2) 0 0;
  padding: var(--s-2);
  font-size: var(--fs-sm);
  border-left: 2px solid var(--border);
  background: var(--bg-3);
  /* Mensaje de un tercero: que un texto largo no descuadre la fila. */
  overflow-wrap: anywhere;
}
.tp-sugg-actions { display: flex; gap: var(--s-2); flex-wrap: wrap; align-items: flex-start; }
.tp-sugg-edit {
  flex: 1 1 100%;
  margin-top: var(--s-2);
  padding-top: var(--s-2);
  border-top: 1px solid var(--border-soft);
}

/* Popup de revisión de sugerencias al abrir la app */
.tp-sugg-prompt-intro {
  margin: 0 0 var(--s-3);
  color: var(--fg-1);
  font-size: var(--fs-sm);
}
/* Dentro del modal las tarjetas ya van sobre --bg-1: subimos un tono para que
   se distingan del fondo del diálogo. */
.tp-sugg-prompt .tp-sugg-item { background: var(--bg-2); }
.tp-sugg-prompt .tp-sugg-msg { background: var(--bg-1); }

/* Móvil: el modal ya es fluido (width:100%, max-width:560px, max-height:90dvh),
   pero con tres acciones por tarjeta los botones quedan estrechos para el dedo.
   Los pasamos a ancho completo y garantizamos el área táctil mínima. */
@media (max-width: 480px) {
  .tp-sugg-item { gap: var(--s-2); }
  .tp-sugg-body { flex: 1 1 100%; }
  .tp-sugg-actions { width: 100%; }
  .tp-sugg-actions button {
    flex: 1 1 100%;
    min-height: var(--tap);
  }
  /* El panel de edición hereda los inputs a 16px del bloque móvil general
     (evita el zoom automático de iOS al enfocar un datetime-local). */
  .tp-sugg-edit .tp-form-label { margin-top: var(--s-2); }
}
