/* =========================================================
   Tasks — hoja de estilos única
   Referencia visual: Microsoft To Do. Móvil primero.
   ========================================================= */

:root {
  --accent: #2564cf;
  --accent-soft: #2564cf1a;

  --bg: #f3f5f9;
  --surface: #ffffff;
  --surface-2: #f7f8fb;
  --sidebar-bg: #ffffff;
  --text: #1b1d21;
  --text-dim: #61656e;
  --text-faint: #8b909a;
  --border: #e4e7ee;
  --border-strong: #d2d7e2;
  --danger: #d13438;
  --warning: #c8811a;
  --success: #107c41;

  --radius: 12px;
  --radius-sm: 8px;
  --shadow-1: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .1);
  --shadow-2: 0 8px 24px rgba(16, 24, 40, .12);
  --shadow-3: 0 20px 48px rgba(16, 24, 40, .22);

  --sidebar-w: 288px;
  --detail-w: 380px;
  /* Huecos que el aparato pide respetar: el reloj arriba, el indicador de
     inicio abajo. Los declara él (62 y 34 en un iPhone con isla dinámica, 0 y 0
     en uno sin nada), así que esto vale para cualquier pantalla sin conocerla.

     Abajo se reserva con `max(fijo, esto)`, nunca sumando: el margen de diseño
     solo actúa cuando no hay nada que esquivar. Arriba sí se suma, porque el
     lienzo empieza pegado al borde de la pantalla y hay que bajar el contenido
     entero. */
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);

  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

:root[data-theme="dark"] {
  --bg: #101216;
  --surface: #191c22;
  --surface-2: #1f232b;
  --sidebar-bg: #14171c;
  --text: #e9ecf2;
  --text-dim: #a2a9b6;
  --text-faint: #767d8b;
  --border: #262b34;
  --border-strong: #333a46;
  --danger: #ff6b6f;
  --warning: #e0a34a;
  --success: #4ec27f;
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-2: 0 8px 24px rgba(0, 0, 0, .5);
  --shadow-3: 0 20px 48px rgba(0, 0, 0, .6);
}

* { box-sizing: border-box; }

/* Hace que los controles nativos (calendario, desplegables, barras de scroll)
   se pinten en el mismo tono que el tema elegido. */
:root { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

html, body {
  height: 100%;
  margin: 0;
  /* Quita el retardo del doble toque para acercar la vista: los toques
     responden al instante y de paso desaparece el zoom accidental. */
  touch-action: manipulation;
  /* La página en sí nunca se desplaza: se comporta como una app, no como un
     documento. Solo tienen scroll las zonas marcadas. */
  overflow: hidden;
  overscroll-behavior: none;
  position: relative;
}

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
  -webkit-tap-highlight-color: transparent;  /* sin destello azul al tocar */
}

/* Los controles no se seleccionan al mantener pulsado; el texto de las tareas sí. */
.sidebar, .list-header, .add-task, .group-title, .list-group-head, .nav-item,
.task-actions, .check, .detail-head, .detail-foot, .tabs, .seg, .swipe-bg {
  user-select: none;
  -webkit-user-select: none;
}

.hidden { display: none !important; }

/* El navegador oculta lo marcado con `hidden` mediante `[hidden]{display:none}`,
   pero cualquier regla propia que fije `display` la gana: `.icon-btn` es
   `display: grid`, así que sus botones no se ocultaban nunca por mucho que el
   código lo pidiera. Se ve fácil cuando pasa —el reloj de sugerencias seguía
   ahí en listas que no sugieren— y es imposible de sospechar leyendo el JS. */
[hidden] { display: none !important; }

button, input, select, textarea { font: inherit; color: inherit; }

/* Aspecto por defecto de cualquier control, para que ninguno se quede blanco
   en modo oscuro. Los que van "desnudos" (búsqueda, título, añadir tarea)
   lo sobrescriben con su propia clase. */
input, select, textarea {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  outline: none;
  max-width: 100%;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
input::placeholder, textarea::placeholder { color: var(--text-faint); }
select { cursor: pointer; }
input[disabled], select[disabled], textarea[disabled] { opacity: .6; cursor: not-allowed; }

::selection { background: var(--accent-soft); }

/* --------------------------- controles base --------------------------- */

.btn {
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 9px 16px;
  cursor: pointer;
  font-weight: 600;
  transition: background .15s, border-color .15s, transform .06s;
  /* Algunos botones son enlaces por dentro (descargar un archivo lo pide). Sin
     esto salen subrayados y dejan de parecer un botón para parecer texto. */
  text-decoration: none;
  /* Y un <a> es texto en línea: sin esto el relleno no cuadra con el de un
     <button> de al lado y quedan a distinta altura. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.btn:hover { background: var(--surface-2); }
.btn:active { transform: scale(.985); }
.btn.primary { background: var(--accent); border-color: transparent; color: #fff; }
.btn.primary:hover { filter: brightness(1.07); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--text-dim); }
.btn.ghost:hover { background: var(--surface-2); color: var(--text); }
.btn.danger { color: var(--danger); border-color: transparent; background: transparent; }
.btn.danger:hover { background: color-mix(in srgb, var(--danger) 12%, transparent); }
.btn.block { width: 100%; }
.btn.sm { padding: 6px 12px; font-size: 14px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }

.icon-btn {
  border: none;
  background: transparent;
  cursor: pointer;
  border-radius: 8px;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  font-size: 16px;
  color: var(--text-dim);
  flex: 0 0 auto;
  transition: background .15s, color .15s;
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); }

.field { display: block; margin-bottom: 14px; }
.field > span {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-dim);
  margin-bottom: 5px;
  letter-spacing: .01em;
}
.field input, .field select, .field textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.field textarea { resize: vertical; min-height: 84px; }
.row { display: flex; gap: 12px; }
.row > * { flex: 1; min-width: 0; }

/* ------------------------------- login -------------------------------- */

.login-screen {
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 24px;
  background:
    radial-gradient(1000px 500px at 12% -10%, color-mix(in srgb, var(--accent) 22%, transparent), transparent 60%),
    radial-gradient(800px 500px at 100% 110%, color-mix(in srgb, #7b61c9 20%, transparent), transparent 60%),
    var(--bg);
}
.login-card {
  width: min(380px, 100%);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 30px 26px 26px;
  box-shadow: var(--shadow-2);
}
.login-logo {
  width: 52px; height: 52px;
  border-radius: 15px;
  background: var(--accent);
  color: #fff;
  display: grid; place-items: center;
  font-size: 26px; font-weight: 700;
  margin-bottom: 16px;
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 40%, transparent);
}
.login-card h1 { margin: 0; font-size: 24px; letter-spacing: -.02em; }
.login-sub { margin: 4px 0 22px; color: var(--text-dim); font-size: 14px; }
.login-workos { display: grid; gap: 8px; }
.login-error {
  margin: 0 0 12px;
  color: var(--danger);
  font-size: 13.5px;
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  padding: 9px 12px;
  border-radius: var(--radius-sm);
}

/* ------------------------------- layout ------------------------------- */

/* Armazón anclado al viewport: no depende de que el navegador soporte dvh ni
   de la barra de direcciones del móvil. */
.app {
  position: fixed;
  inset: 0;
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  overflow: hidden;
  /* La app ocupa TODA la pantalla, áreas seguras incluidas: así no asoma el
     fondo del documento formando franjas de otro color. El hueco del reloj y
     del indicador de inicio lo respeta cada barra con su propio relleno, de
     modo que es su fondo el que cubre esas zonas.

     Sin `height`: con `inset: 0` la altura ya sale de estirar de arriba abajo.
     Poniendo además `height: 100%` la declaración quedaba sobrerrestringida, el
     navegador descartaba el `bottom`… y ese 100% no medía lo mismo: en el
     iPhone instalado daba 812 sobre un lienzo de 874, dejando 62px del fondo
     del documento a la vista justo debajo de la barra de añadir. */
}

.scrim {
  position: fixed;
  inset: 0;
  background: rgba(8, 10, 14, .45);
  z-index: 40;
  backdrop-filter: blur(2px);
  animation: fade-in .18s ease;
}

/* ------------------------------ sidebar ------------------------------- */

.sidebar {
  background: var(--sidebar-bg);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  min-height: 0;
  z-index: 50;
}

.sidebar-head {
  display: flex;
  align-items: center;
  gap: 6px;
  /* El relleno superior incluye la barra de estado: el cajón es fijo respecto a
     la pantalla, así que su cabecera es la que tiene que dejar ese hueco. */
  padding: calc(14px + var(--safe-t)) 12px 8px;
}
.profile {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 6px;
  border-radius: 10px;
  text-align: left;
  min-width: 0;
}
.profile:hover { background: var(--surface-2); }
.profile-meta { min-width: 0; display: block; }
.profile-meta strong {
  display: block;
  font-size: 14.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.profile-meta small { color: var(--text-faint); font-size: 11.5px; }

.avatar {
  width: 34px; height: 34px;
  border-radius: 50%;
  display: grid; place-items: center;
  color: #fff;
  font-weight: 700;
  font-size: 13px;
  flex: 0 0 auto;
  text-transform: uppercase;
}
.avatar.xs { width: 20px; height: 20px; font-size: 9.5px; }
.avatar.sm { width: 26px; height: 26px; font-size: 11px; }

.search-wrap { position: relative; padding: 4px 12px 10px; }
.search-icon {
  position: absolute;
  left: 24px; top: 50%;
  transform: translateY(-60%);
  font-size: 12.5px;
  opacity: .6;
  pointer-events: none;
}
.search-input {
  width: 100%;
  padding: 9px 12px 9px 32px;
  border-radius: 9px;
  border: 1px solid transparent;
  background: var(--surface-2);
  outline: none;
}
.search-input:focus { border-color: var(--accent); background: var(--surface); }

.smart-views { padding: 0 8px 6px; }
.sidebar-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 4px 8px 12px;
  scrollbar-width: thin;
  /* Igual que la zona de tareas: aquí empieza el gesto que cierra el menú. */
  touch-action: pan-y;
}
.sidebar-scroll::-webkit-scrollbar { width: 8px; }
.sidebar-scroll::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 8px; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  background: transparent;
  border-radius: 9px;
  cursor: pointer;
  text-align: left;
  color: var(--text);
  position: relative;
  margin-bottom: 1px;
}
.nav-item:hover { background: var(--surface-2); }

/* Lista abierta. A propósito SIN barra lateral de color: esa marca es de las
   cabeceras de grupo, y si la usaran las dos, una lista seleccionada parecería
   un grupo más. Aquí la señal es el relleno y la negrita. */
.nav-item.active {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  font-weight: 600;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent);
}

/* Las listas van sangradas bajo su grupo, para que se vea la jerarquía. */
.list-group-lists .nav-item { width: calc(100% - 10px); margin-left: 10px; }
.nav-item .nav-icon { font-size: 16px; width: 22px; text-align: center; flex: 0 0 auto; }
.nav-item .nav-label {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nav-item .nav-count {
  font-size: 12px;
  color: var(--text-faint);
  background: var(--surface-2);
  border-radius: 999px;
  padding: 1px 8px;
  font-variant-numeric: tabular-nums;
}
.nav-item.active .nav-count { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.nav-item.drop-target { outline: 2px dashed var(--accent); outline-offset: -2px; }

.list-group { margin-top: 12px; }

/* Cabecera de grupo: con el color propio del grupo, para separar visualmente
   los bloques de la barra lateral. */
.list-group-head {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 10px;
  margin-bottom: 3px;
  border-radius: 9px;
  border-left: 3px solid var(--group-color, var(--border-strong));
  background: color-mix(in srgb, var(--group-color, var(--text-faint)) 13%, transparent);
  color: color-mix(in srgb, var(--group-color, var(--text-faint)) 55%, var(--text));
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .01em;
  text-transform: none;
}
:root[data-theme="dark"] .list-group-head {
  background: color-mix(in srgb, var(--group-color, var(--text-faint)) 18%, transparent);
  color: color-mix(in srgb, var(--group-color, var(--text-faint)) 45%, #ffffff);
}
.list-group-empty {
  padding: 4px 12px 6px;
  font-size: 12px;
  color: var(--text-faint);
}
.list-group-head .list-group-name {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
.list-group-toggle {
  display: flex;
  align-items: center;
  gap: 5px;
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 2px 2px 2px 0;
  color: inherit;
  font: inherit;
  border-radius: 6px;
}
.list-group-toggle:hover { color: var(--text-dim); }
/* El triángulo de plegar era de 9 px: se veía pero no se acertaba. */
.list-group-caret { font-size: 13px; width: 13px; display: inline-block; text-align: center; }

/* Asideros para reordenar la barra lateral */
.list-group-grip, .nav-grip {
  cursor: grab;
  color: var(--text-faint);
  font-size: 13px;
  line-height: 1;
  padding: 2px 1px;
  opacity: 0;
  touch-action: none;          /* el gesto es nuestro, no del scroll */
  transition: opacity .15s;
  flex: 0 0 auto;
}
.nav-grip { margin-left: -4px; }
/* Solo en ratón. En táctil, un :hover que revela un hijo obliga a tocar dos
   veces: el primer toque aplica el hover y no se llega a disparar el clic. */
@media (hover: hover) and (pointer: fine) {
  .list-group:hover .list-group-grip,
  .nav-item:hover .nav-grip { opacity: .7; }
}
.list-group-grip:active, .nav-grip:active { cursor: grabbing; opacity: 1; }

.sb-dragging { opacity: .45; }
.sb-dragging-active { cursor: grabbing; }
/* Al arrastrar una lista se resalta el grupo de destino. */
.sb-dragging-active [data-lists-of] { min-height: 12px; }
.sb-dragging-active .list-group-lists:hover {
  background: var(--accent-soft);
  border-radius: 8px;
}

@media (max-width: 860px) {
  .list-group-grip, .nav-grip { opacity: .55; font-size: 15px; padding: 4px 3px; }
}
.list-group-head .icon-btn { width: 24px; height: 24px; font-size: 13px; opacity: 0; }
@media (hover: hover) and (pointer: fine) {
  .list-group:hover .list-group-head .icon-btn { opacity: 1; }
}

.sidebar-foot {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 8px 12px max(10px, var(--safe-b));
  border-top: 1px solid var(--border);
}
.foot-btn {
  flex: 1;
  text-align: left;
  border: none;
  background: transparent;
  padding: 9px 10px;
  border-radius: 9px;
  cursor: pointer;
  color: var(--accent);
  font-weight: 600;
}
.foot-btn:hover { background: var(--surface-2); }

/* ------------------------------ contenido ----------------------------- */

.content {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;          /* nada de aquí dentro puede ensanchar la pantalla */
  position: relative;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--accent) 9%, transparent), transparent 220px),
    var(--bg);
}

.list-header {
  /* Deja libre la barra de estado con su propio fondo, sin franjas. */
  padding: calc(20px + var(--safe-t)) 26px 12px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  flex: 0 0 auto;            /* fija: nunca se va con el scroll */
  min-width: 0;
}
.header-main { flex: 1; min-width: 0; }
.header-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -.02em;
  margin: 0;
  min-width: 0;
}
.header-title .h-icon { font-size: 24px; }
.header-title .h-name {
  flex: 1 1 auto;
  min-width: 0;              /* deja que se encoja en pantallas estrechas */
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border: 1px solid transparent;
  background: transparent;
  padding: 2px 4px;
  border-radius: 6px;
  font: inherit;
  color: inherit;
  box-shadow: none;
}
.header-title .h-name:focus { outline: 2px solid var(--accent); background: var(--surface); }
.header-sub {
  color: var(--text-dim);
  font-size: 13px;
  margin-top: 3px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 9px;
  font-size: 12px;
  color: var(--text-dim);
}
.menu-btn { font-size: 18px; }
.hamburger { display: none; }

.task-area {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;        /* la única zona que se desplaza, y solo en vertical */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  /* Solo se desplaza en vertical, así que hay que decirlo: sin esto hereda
     `manipulation` de `body`, que deja al navegador quedarse también con los
     gestos horizontales. Y el gesto que abre el menú empieza justo aquí, en el
     borde izquierdo — el sistema se lo llevaba a los 40 o 50 píxeles y el panel
     se volvía a meter. Las filas ya tenían su `pan-y`; el hueco entre ellas, no,
     y de ahí que fallara unas veces y otras no. */
  touch-action: pan-y;
  padding: 0 26px 12px;
  scrollbar-width: thin;
}
.task-area::-webkit-scrollbar { width: 10px; }
.task-area::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 8px; }

/* Oferta de avisos. Va fuera de la zona que se desplaza, entre la cabecera y
   las tareas, y desaparece en cuanto se decide una cosa o la otra. */
.push-banner {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 26px 12px;
  padding: 12px 14px;
  border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--border));
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}
.push-banner-icon { font-size: 20px; line-height: 1; }
/* Base 0, no auto: con `auto` el texto reclama su ancho natural y en el móvil
   se marcha a su propia línea, dejando el icono solo arriba. */
.push-banner-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 0; }
.push-banner-text strong { font-size: 14px; }
.push-banner-text small { color: var(--text-dim); font-size: 12.5px; }
.push-banner-actions { display: flex; gap: 8px; flex: 0 0 auto; }

@media (max-width: 860px) {
  .push-banner {
    margin: 0 12px 10px;
    flex-wrap: wrap;
  }
  /* En pantalla estrecha los botones bajan a su propia línea, a lo ancho, en
     vez de estrujar el texto hasta partirlo letra a letra. */
  .push-banner-actions { width: 100%; }
  .push-banner-actions .btn { flex: 1 1 0; }
}

.group-title {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-faint);
  margin: 18px 2px 8px;
}

/* Secciones de una lista (panadería, limpieza, Home Assistant…).
   Cada una con el color de su categoría, para ver de un vistazo dónde
   empieza y dónde acaba. */
.section-group {
  margin: 22px 0 6px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--section) 6%, transparent);
  padding: 0 0 8px;
  border: 1px solid color-mix(in srgb, var(--section) 22%, transparent);
  overflow: hidden;
}
.section-group:first-child { margin-top: 6px; }

.section-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  background: color-mix(in srgb, var(--section) 16%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--section) 20%, transparent);
  margin-bottom: 8px;
  /* Es un <button>: hay que quitarle lo de botón y devolverle el ancho, que si
     no la cabecera se encoge al tamaño de su texto. */
  width: 100%;
  border-top: none;
  border-left: none;
  border-right: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
/* Plegada, la banda no necesita el hueco de abajo. */
.section-head[aria-expanded="false"] { margin-bottom: 0; }
.section-head .caret {
  font-size: 13px;
  width: 13px;
  text-align: center;
  flex: 0 0 auto;
  color: color-mix(in srgb, var(--section) 55%, var(--text));
}
.section-name {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .01em;
  color: color-mix(in srgb, var(--section) 55%, var(--text));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.section-count {
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: #fff;
  background: var(--section);
  border-radius: 999px;
  padding: 1px 9px;
  opacity: .9;
}
.section-group .task-list { padding: 0 8px; }

/* En oscuro, el color de la sección tiene que aclararse para leerse bien. */
:root[data-theme="dark"] .section-name {
  color: color-mix(in srgb, var(--section) 55%, #ffffff);
}
:root[data-theme="dark"] .section-group {
  background: color-mix(in srgb, var(--section) 10%, transparent);
}

/* --------------------------------- tareas ------------------------------ */

.task-list { display: flex; flex-direction: column; gap: 6px; }

.task-row {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  overflow: hidden;
  touch-action: pan-y;
  animation: pop-in .18s ease;
}
.task-row.dragging { opacity: .45; }
.task-row.drag-over { box-shadow: 0 -2px 0 var(--accent) inset, var(--shadow-1); }
.task-row.leaving { animation: fade-out .18s ease forwards; }

.task-inner {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 11px 14px;
  background: var(--surface);
  position: relative;
  z-index: 1;
  transition: transform .18s cubic-bezier(.2, .8, .3, 1);
}
.task-row.swiping .task-inner { transition: none; }

/* Fondo que asoma al deslizar: izquierda destaca, derecha elimina. */
.swipe-bg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 18px;
  font-size: 17px;
  color: #fff;
  background: var(--surface-2);
  transition: background .18s;
}
.swipe-action {
  display: flex;
  align-items: center;
  gap: 8px;
  opacity: .35;
  transition: opacity .15s, transform .15s;
}
.swipe-label { font-size: 13px; font-weight: 600; letter-spacing: .01em; }
/* Los iconos del deslizamiento miden 1em: sin tamaño propio heredarían el del
   texto de la fila y saldrían más pequeños que antes. */
.swipe-icon { display: grid; place-items: center; font-size: 20px; line-height: 1; }
.swipe-action.armed { opacity: 1; transform: scale(1.06); }

.task-row.sw-star .swipe-bg { background: #e8a33d; }
.task-row.sw-sun .swipe-bg { background: #2f9bd8; }
.task-row.sw-delete .swipe-bg { background: var(--danger); }

.check {
  width: 21px; height: 21px;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  background: transparent;
  cursor: pointer;
  flex: 0 0 auto;
  margin-top: 2px;
  display: grid;
  place-items: center;
  transition: border-color .15s, background .15s, transform .12s;
  position: relative;
}
.check:hover { border-color: var(--accent); }
.check::after {
  content: "";
  width: 10px; height: 6px;
  border-left: 2.2px solid #fff;
  border-bottom: 2.2px solid #fff;
  transform: rotate(-45deg) scale(.2);
  opacity: 0;
  transition: transform .18s cubic-bezier(.2, .9, .3, 1.4), opacity .12s;
  margin-top: -2px;
}
.check.done { background: var(--accent); border-color: var(--accent); }
.check.done::after { opacity: 1; transform: rotate(-45deg) scale(1); }
.check.pulse { animation: check-pop .32s ease; }

.task-body { flex: 1; min-width: 0; cursor: pointer; }
.task-title {
  word-break: break-word;
  transition: color .2s;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
/* El texto tiene que poder encogerse para partirse él solo en varias líneas.
   Sin esto conserva su ancho natural, no cabe al lado del número y `flex-wrap`
   lo baja entero: el número se quedaba solo arriba y el texto debajo. Con
   `align-items: baseline`, el número se alinea con la primera línea. */
.task-title .task-text { flex: 1; min-width: 0; }

/* Cantidad de la entrada: "3 ud", "200 g". Vive con el sol y la estrella, a la
   derecha de la fila, y se toca para ajustarla. */
.qty {
  flex: 0 0 auto;
  font-size: 12.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  background: var(--accent-soft);
  border: none;
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
  cursor: pointer;
  min-height: 26px;
}
.qty:active { transform: scale(.94); }
.qty:disabled { cursor: default; }
/* Sin cantidad todavía: una invitación discreta, no un elemento más que leer. */
.qty.vacio {
  color: var(--text-faint);
  background: transparent;
  border: 1px dashed var(--border-strong);
  font-weight: 600;
  padding: 3px 8px;
}
.task-row.done .qty { color: var(--text-faint); background: var(--surface-2); }

/* Editor de cantidad anclado al globo. */
.qty-pop {
  position: fixed;
  z-index: 120;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-3);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  animation: fade-in .12s ease;
}
.qty-pop-row { display: flex; align-items: center; gap: 6px; }
.qty-step {
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  border: 1px solid var(--border);
  background: var(--surface-2);
  border-radius: 10px;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  color: var(--text);
}
.qty-step:active { transform: scale(.94); }
.qty-pop .qty-amount {
  width: 72px;
  text-align: center;
  font-size: 17px;          /* por debajo de 16 el iPhone acerca la vista */
  font-variant-numeric: tabular-nums;
  padding: 8px 4px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}
.qty-pop select {
  padding: 8px 6px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  max-width: 92px;
}
.qty-clear { align-self: stretch; }

/* Fila de cantidad: el número manda y la unidad ocupa lo justo.
   Con más especificidad que ".detail-section select { width: 100% }", que si no
   se llevaba todo el ancho y empujaba el número (y el panel) fuera de la vista. */
.detail-section .qty-row { display: flex; gap: 10px; align-items: center; }
.detail-section .qty-row input[type="number"] {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;
  font-size: 17px;              /* cómodo para teclear en el móvil */
  font-variant-numeric: tabular-nums;
  padding: 10px 12px;
}
.detail-section .qty-row select {
  flex: 0 0 auto;
  width: auto;
  min-width: 96px;
  max-width: 42%;
  padding: 10px 10px;
}
.detail-section .qty-row .btn { flex: 0 0 auto; }

/* Editor de unidades de la configuración de la lista */
.units-editor {
  margin: 10px 0 4px;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.units-label { display: block; font-size: 12px; color: var(--text-faint); margin-bottom: 8px; }
.unit-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.unit-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  padding: 3px 6px 3px 11px;
  font-size: 13px;
  font-weight: 600;
}
.unit-chip .unit-x {
  border: none;
  background: transparent;
  cursor: pointer;
  color: var(--text-faint);
  font-size: 11px;
  line-height: 1;
  padding: 3px 4px;
  border-radius: 50%;
}
.unit-chip .unit-x:hover { color: var(--danger); background: var(--surface-2); }
.unit-new { flex: 1 1 auto; min-width: 0; }
.task-row.done .task-title { color: var(--text-faint); text-decoration: line-through; }
.task-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-dim);
  align-items: center;
}
.task-meta .due.overdue { color: var(--danger); font-weight: 600; }
.task-meta .due.today { color: var(--accent); font-weight: 600; }
/* Mismo azul que el sol encendido: es la misma marca, para otro día. */
.task-meta .manana { color: #2f9bd8; font-weight: 600; }
.prio {
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.prio.high { color: var(--danger); }
.prio.medium { color: var(--warning); }
.prio.low { color: var(--text-dim); }

.task-actions { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }

/* Estrella de "importante" */
/* Estrella (importante) y sol (Mi día).
   Glifos de texto, no emoji: así se les puede dar color y tamaño. El estado
   activo se distingue por color y fondo, no por un icono distinto. */
/* Iconos dibujados: miden 1em, así que el tamaño se sigue mandando con
   `font-size`, pero a diferencia de los caracteres ★ y ☀︎ ocupan exactamente lo
   mismo en cualquier sistema. */
.ico {
  width: 1em;
  height: 1em;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
}
/* Marcados, se rellenan. El sol solo por dentro: los rayos siguen siendo trazo. */
.star.on .ico { fill: currentColor; }
.sun.on .ico circle { fill: currentColor; }

.star, .sun {
  border: none;
  background: transparent;
  cursor: pointer;
  display: grid;
  place-items: center;
  font-size: 19px;
  line-height: 1;
  padding: 5px 7px;
  border-radius: 8px;
  color: var(--text-faint);
  transition: color .15s, background .15s, transform .12s;
}
.star:hover, .sun:hover { background: var(--surface-2); color: var(--text-dim); }
.star:active, .sun:active { transform: scale(1.2); }
.star:disabled, .sun:disabled { cursor: default; opacity: .3; }

.star.on {
  color: #e8a33d;
  background: color-mix(in srgb, #e8a33d 15%, transparent);
}
.sun.on {
  color: #2f9bd8;
  background: color-mix(in srgb, #2f9bd8 15%, transparent);
}
.star.on:hover { color: #e8a33d; }
.sun.on:hover { color: #2f9bd8; }

.star.big, .sun.big { font-size: 23px; padding: 7px 9px; }

/* En pantallas pequeñas, algo más grandes todavía. */
@media (max-width: 860px) {
  .star, .sun { font-size: 22px; padding: 6px 8px; }
  .star.big, .sun.big { font-size: 25px; }
}

/* Grupo plegable (completadas) */
.group-title.toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: transparent;
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-faint);
  padding: 4px 2px;
}
.group-title.toggle:hover { color: var(--text-dim); }
.group-title .caret { font-size: 13px; width: 13px; display: inline-block; text-align: center; }

.toggle-chip { cursor: pointer; font-family: inherit; }
.toggle-chip:hover { border-color: var(--accent); color: var(--accent); }
.toggle-chip.on { border-color: var(--border-strong); }

/* Confeti al completar */
.confetti-layer {
  position: fixed;
  z-index: 300;
  pointer-events: none;
  width: 0;
  height: 0;
}
.confetti-layer i {
  position: absolute;
  width: 7px;
  height: 9px;
  border-radius: 2px;
  opacity: 0;
  animation: confetti-fly .85s cubic-bezier(.15, .8, .35, 1) var(--delay, 0ms) forwards;
}
@keyframes confetti-fly {
  0% { transform: translate(0, 0) rotate(0deg) scale(.4); opacity: 1; }
  70% { opacity: 1; }
  100% {
    transform: translate(var(--dx), calc(var(--dy) + 26px)) rotate(var(--rot)) scale(1);
    opacity: 0;
  }
}
.drag-handle {
  cursor: grab;
  color: var(--text-faint);
  opacity: 0;
  transition: opacity .15s;
  font-size: 14px;
  padding: 2px 4px;
  touch-action: none;
}
@media (hover: hover) and (pointer: fine) {
  .task-row:hover .drag-handle { opacity: 1; }
}
.drag-handle:active { cursor: grabbing; }

.empty {
  text-align: center;
  padding: 56px 20px;
  color: var(--text-faint);
}
.empty .emoji { font-size: 40px; display: block; margin-bottom: 10px; }

/* Sugerencias del campo de añadir */
.add-wrap { position: relative; }

.suggestions {
  position: absolute;
  left: 26px;
  right: 26px;
  bottom: calc(100% - 4px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-3);
  max-height: min(46dvh, 340px);
  overflow-y: auto;
  z-index: 30;
  padding: 4px;
  animation: pop-in .14s ease;
}
.suggestions-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 8px 4px;
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-faint);
}
.suggestion {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: none;
  background: transparent;
  padding: 9px 10px;
  border-radius: 9px;
  cursor: pointer;
  text-align: left;
  font-size: 14.5px;
}
.suggestion:hover, .suggestion.on { background: var(--accent-soft); }
.sug-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sug-cat { font-size: 12px; flex: 0 0 auto; }
.sug-uses {
  font-size: 11.5px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}
.sug-forget { opacity: 0; font-size: 13px; flex: 0 0 auto; padding: 0 2px; }
.suggestion:hover .sug-forget, .suggestion.on .sug-forget { opacity: .6; }
.sug-forget:hover { opacity: 1; }

.add-task {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;            /* fija abajo, siempre visible */
  margin: 0 26px max(16px, var(--safe-b));
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-2);
}
.add-plus { color: var(--accent); font-size: 18px; font-weight: 700; }
.add-task-input {
  flex: 1;
  border: none;
  background: transparent;
  outline: none;
  padding: 4px 0;
  min-width: 0;
}

/* ---------------------------- panel de detalle ------------------------- */

.detail {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: var(--detail-w);
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-3);
  transform: translateX(102%);
  transition: transform .24s cubic-bezier(.2, .8, .3, 1);
  z-index: 60;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.detail.open { transform: translateX(0); }
.detail-scroll {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;        /* nada de aquí dentro puede desplazar el panel */
  padding: 18px 20px;
  overscroll-behavior: contain;
}
.detail-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 12px 12px 18px;
  border-bottom: 1px solid var(--border);
}
.detail-head strong { flex: 1; font-size: 14px; color: var(--text-dim); font-weight: 600; }
.detail-foot {
  border-top: 1px solid var(--border);
  padding: 10px 16px max(12px, var(--safe-b));
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: space-between;
  color: var(--text-faint);
  font-size: 12px;
}
.detail-stamps {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  line-height: 1.4;
}
.detail-stamps span { overflow: hidden; text-overflow: ellipsis; }
.detail-title-row { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 6px; }
.detail-title {
  flex: 1;
  font-size: 17px;
  font-weight: 600;
  border: 1px solid transparent;
  background: transparent;
  border-radius: 8px;
  padding: 6px 8px;
  resize: none;
  overflow: hidden;
  outline: none;
  min-height: 38px;
}
.detail-title:focus { border-color: var(--accent); background: var(--surface-2); }

.sub-list { display: flex; flex-direction: column; gap: 2px; margin: 8px 0 4px; }
/* Cabecera de los pasos ya hechos. El margen de arriba de `.group-title` está
   pensado para separar bloques en la lista central; aquí, dentro del panel,
   deja un hueco raro. */
.sub-hechas { margin: 2px 2px 4px; }

/* Miniatura de un archivo en la papelera: hay que poder ver qué es antes de
   decidir si se borra del todo. */
/* Con una categoría fijada, el botón lo enseña: estado invisible es meter
   cuatro cosas en Panadería sin querer. */
#pin-cat-btn.fijada {
  background: var(--surface-2);
  box-shadow: 0 0 0 1.5px currentColor inset;
}

.papelera-mini {
  width: 38px;
  height: 38px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--border);
  cursor: zoom-in;
  flex: 0 0 auto;
}

/* Número para poder citar una tarea o una subtarea ("arregla la #7").
   Cifras de ancho fijo y alineado a la derecha para que, bajando la lista,
   todos caigan en la misma columna y se lean de un barrido — pero sin reservar
   sitio de más: el texto es lo que se viene a leer. */
.num {
  flex: 0 0 auto;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--text-faint);
  white-space: nowrap;
}
.task-title .num { padding-top: 1px; }
.sub-row .num { padding-top: 4px; }
/* `align-items: flex-start` y no `center`: con el texto en dos o tres líneas,
   centrar dejaba la casilla flotando a media altura del párrafo. */
.sub-row { display: flex; align-items: flex-start; gap: 8px; padding: 5px 4px; border-radius: 8px; }
.sub-row:hover { background: var(--surface-2); }
.sub-row .check { width: 17px; height: 17px; margin-top: 3px; flex: 0 0 auto; }
.sub-row .check::after { width: 8px; height: 5px; }
/* El texto del paso es un campo, pero no lo parece hasta que se toca: si no,
   la lista de subtareas se vería como un formulario. */
.sub-row .sub-title {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  border: none;
  background: transparent;
  padding: 2px 4px;
  border-radius: 6px;
  /* Es un textarea que no debe parecerlo: crece con el texto, sin asa de
     redimensionar y sin la altura mínima que llevan los de las notas. */
  min-height: 0;
  height: auto;
  resize: none;
  overflow: hidden;
  line-height: 1.35;
  font-family: inherit;
  word-break: break-word;
}
.sub-row .sub-title:focus {
  background: var(--surface);
  border: 1px solid var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.sub-row.done .sub-title { color: var(--text-faint); text-decoration: line-through; }
.sub-add {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 4px;
}
.sub-add input {
  flex: 1;
  border: none;
  border-bottom: 1px solid var(--border);
  background: transparent;
  outline: none;
  padding: 4px 0;
  font-size: 14px;
}
.sub-add input:focus { border-color: var(--accent); }

/* --------------------------- fotos y archivos ---------------------------- */

/* Rejilla que se rellena sola: en el móvil caben dos por fila y en el
   ordenador las que quepan, sin puntos de corte a mano. */
.adjuntos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 8px;
  margin: 8px 0 10px;
}
.adjunto { position: relative; }
.adjunto.foto img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;              /* recortada, no deformada */
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  cursor: zoom-in;
  display: block;
}
/* Un PDF no tiene miniatura que enseñar, así que ocupa la fila entera con lo
   único que lo distingue: su nombre. */
.adjunto.doc { grid-column: 1 / -1; }
.adjunto.doc .doc-link {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  text-decoration: none;
  color: inherit;
}
.adjunto.doc .doc-nombre {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.adjunto.doc .doc-peso { font-size: 12px; color: var(--text-faint); flex: 0 0 auto; }
.adjunto-x {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.adjunto-x:hover { background: rgba(0, 0, 0, .78); }
/* En táctil no hay hover, así que el aspa va siempre visible. */
@media (hover: hover) and (pointer: fine) {
  .adjunto-x { opacity: 0; transition: opacity .15s; }
  .adjunto:hover .adjunto-x { opacity: 1; }
}

/* Visor: la foto manda, y no debe salirse de la pantalla ni a lo alto. */
.modal-body.visor { display: flex; flex-direction: column; gap: 8px; align-items: center; }

/* El marco recorta la foto ampliada. Sin él, al hacer zoom se saldría del
   diálogo y taparía media pantalla. */
.visor-marco {
  width: 100%;
  /* Sin el nombre del archivo debajo sobra sitio, y aquí el sitio es la foto. */
  height: min(76vh, 820px);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: 8px;
  background: var(--surface-2);
  /* El gesto es nuestro: sin esto el navegador se queda el pellizco y el
     arrastre para desplazar la página, y el zoom de la foto no llega a
     enterarse de que pasa algo. */
  touch-action: none;
  cursor: zoom-in;
}
.visor-marco.con-zoom { cursor: grab; }
.visor-marco.con-zoom:active { cursor: grabbing; }
.visor-foto {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  /* El punto de origen en el centro es lo que hacen las cuentas del zoom. */
  transform-origin: center center;
  will-change: transform;
  user-select: none;
  -webkit-user-drag: none;
}
/* Alto fijo: el aumento aparece y desaparece al ampliar, y si la barra creciera
   con él la foto daría un salto justo mientras la estás mirando. */
.visor-barra { display: flex; align-items: center; gap: 10px; min-height: 26px; }
.visor-pie { font-size: 13px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.visor-aumento {
  font-size: 12px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  min-width: 34px;
}
.visor-ayuda { color: var(--text-faint); text-align: center; }
/* Con ratón no se pellizca: se dice lo que sí sirve. */
@media (hover: hover) and (pointer: fine) {
  .visor-ayuda::after { content: ' O usa la rueda del ratón.'; }
}

.detail-section { margin-top: 18px; }
.detail-section textarea,
.detail-section select,
.detail-section input { width: 100%; }
.detail-section textarea { min-height: 92px; resize: vertical; line-height: 1.5; }

/* Notas: vista con enlaces / cuadro de texto, con el mismo aspecto para que
   al pasar de una a otra no dé un salto. */
.notes-field { position: relative; }
.notes-view {
  width: 100%;
  min-height: 92px;
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  white-space: pre-wrap;
  word-break: break-word;
  line-height: 1.5;
  cursor: text;
  transition: border-color .15s;
}
.notes-view:hover { border-color: var(--accent); }
.notes-view:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.notes-view.empty { color: var(--text-faint); }
.notes-view a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  word-break: break-all;
}
.notes-view a:hover { text-decoration-thickness: 2px; }
.detail-section > h4 {
  margin: 0 0 8px;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-faint);
}
.seg { display: flex; gap: 6px; flex-wrap: wrap; }
.seg button {
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: 999px;
  padding: 5px 12px;
  cursor: pointer;
  font-size: 13px;
}
.seg button.on { background: var(--accent); border-color: transparent; color: #fff; font-weight: 600; }
.quick-dates { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }

/* -------------------------------- modales ------------------------------ */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(8, 10, 14, .5);
  /* Centrado con flex, no con rejilla: con `display: grid` el navegador acababa
     dimensionando el cuadro por su contenido (las pestañas suman más que la
     pantalla de un móvil) y se salía por la derecha. En flex el `width: 100%`
     del hijo se resuelve contra el contenedor y no hay sorpresas. */
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 16px;
  /* Deja libre la zona del indicador de inicio del móvil. */
  padding-bottom: max(16px, var(--safe-b));
  animation: fade-in .16s ease;
  backdrop-filter: blur(3px);
}
.modal {
  background: var(--surface);
  border-radius: 16px;
  box-shadow: var(--shadow-3);
  /* Ancho: 100% de su hueco (que la rejilla limita a la pantalla) y un tope en
     escritorio. Antes era `min(520px, 100%)`, pero al ser un elemento de rejilla
     el navegador acababa dimensionándolo por su contenido —las pestañas suman
     más que un móvil— y el cuadro se salía por la derecha. Con `width: 100%` y
     `min-width: 0` no hay ambigüedad posible. */
  width: 100%;
  max-width: 520px;
  min-width: 0;
  flex: 0 1 auto;      /* puede encogerse; nunca estirarse más que max-width */
  /* svh = viewport "pequeño", el que queda con las barras del navegador a la
     vista. Con dvh el cuadro se salía de la pantalla en Safari del iPhone
     cuando la barra inferior estaba desplegada. */
  max-height: 86vh;
  max-height: min(86svh, 760px);
  display: flex;
  flex-direction: column;
  animation: modal-in .2s cubic-bezier(.2, .8, .3, 1);
  overflow: hidden;
}
.modal-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--border);
}
.modal-head h3 { margin: 0; font-size: 17px; flex: 1; }
.modal-head, .modal-foot, .tabs { flex: 0 0 auto; }
.modal-body {
  padding: 18px;
  overflow-y: auto;
  overflow-x: hidden;     /* nada de aquí dentro puede ensanchar el cuadro */
  flex: 1 1 auto;
  min-height: 0;          /* sin esto el contenido desborda y no hay scroll */
  min-width: 0;
  overscroll-behavior: contain;
  overflow-wrap: anywhere;
}
/* Contenedor de pestañas + cuerpo dentro del modal. */
.modal-stack {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;      /* que las pestañas no impongan el ancho del cuadro */
}
.modal-foot {
  padding: 12px 18px max(14px, var(--safe-b));
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* Las pestañas no caben en un móvil estrecho: se desplazan en horizontal en
   lugar de estirar el cuadro. */
/* Las pestañas se reparten en las líneas que hagan falta.
   Antes se desplazaban a lo ancho, y una pestaña escondida a la derecha no se
   ve ni se intuye: nadie descubre que hay que arrastrar ahí. Envolviéndolas
   están todas a la vista, y de paso siguen sin poder ensanchar el diálogo, que
   era el motivo original de aquel scroll. */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 4px;
  padding: 0 12px;
  border-bottom: 1px solid var(--border);
  min-width: 0;
}
.tabs button {
  border: none;
  background: transparent;
  padding: 11px 12px;
  cursor: pointer;
  color: var(--text-dim);
  font-weight: 600;
  border-bottom: 2px solid transparent;
  font-size: 14px;
  flex: 0 1 auto;
  white-space: nowrap;
  min-width: 0;
}
.tabs button.on { color: var(--accent); border-color: var(--accent); }

/* En pantalla estrecha, algo más apretadas para que quepan en dos líneas. */
@media (max-width: 860px) {
  .tabs { padding: 0 8px; }
  .tabs button { padding: 9px 9px; font-size: 13.5px; }
}

.swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.swatch {
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
  transition: transform .12s;
}
.swatch:hover { transform: scale(1.12); }
.swatch.on { border-color: var(--text); box-shadow: 0 0 0 2px var(--surface) inset; }

.emoji-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(38px, 1fr));
  gap: 4px;
  max-height: 148px;
  overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.emoji-grid button {
  border: none;
  background: transparent;
  font-size: 19px;
  padding: 5px;
  border-radius: 7px;
  cursor: pointer;
}
.emoji-grid button:hover { background: var(--surface); }
.emoji-grid button.on { background: var(--accent); }

.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}
.toggle-row:last-child { border-bottom: none; }
.toggle-row small { display: block; color: var(--text-faint); font-size: 12px; }
.switch {
  position: relative;
  width: 42px; height: 24px;
  border-radius: 999px;
  background: var(--border-strong);
  border: none;
  cursor: pointer;
  flex: 0 0 auto;
  transition: background .18s;
}
.switch::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: #fff;
  transition: transform .18s cubic-bezier(.2, .8, .3, 1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
}
.switch.on { background: var(--accent); }
.switch.on::after { transform: translateX(18px); }

.share-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}
.share-row .grow { flex: 1; min-width: 0; }
.share-row .grow strong { display: block; font-size: 14px; }
.share-row .grow small { color: var(--text-faint); font-size: 12px; }

.token-box {
  display: flex;
  gap: 8px;
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  word-break: break-all;
}
.token-box code { flex: 1; min-width: 0; }
.hint { color: var(--text-faint); font-size: 12.5px; margin: 6px 0 0; }

.menu-sheet {
  position: fixed;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-3);
  padding: 6px;
  z-index: 110;
  min-width: 208px;
  animation: pop-in .12s ease;
}
.menu-sheet button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: none;
  background: transparent;
  padding: 9px 11px;
  border-radius: 8px;
  cursor: pointer;
  text-align: left;
  font-size: 14px;
}
.menu-sheet button:hover { background: var(--surface-2); }
.menu-sheet button.danger { color: var(--danger); }
.menu-sheet hr { border: none; border-top: 1px solid var(--border); margin: 5px 2px; }

/* -------------------------------- toasts ------------------------------- */

.toast-root {
  position: fixed;
  left: 50%;
  bottom: max(22px, var(--safe-b));
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 200;
  pointer-events: none;
  width: min(420px, calc(100vw - 32px));
}
.toast {
  background: #23262d;
  color: #fff;
  border-radius: 10px;
  padding: 11px 15px;
  box-shadow: var(--shadow-2);
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  animation: toast-in .2s cubic-bezier(.2, .8, .3, 1);
  pointer-events: auto;
}
.toast.error { background: var(--danger); }
.toast button {
  border: none;
  background: transparent;
  color: inherit;
  text-decoration: underline;
  cursor: pointer;
  font-weight: 600;
  padding: 0;
}
:root[data-theme="dark"] .toast { background: #32363f; }

/* ----------------------------- animaciones ----------------------------- */

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes fade-out { to { opacity: 0; transform: translateY(-4px); } }
@keyframes pop-in { from { opacity: 0; transform: translateY(4px) scale(.995); } to { opacity: 1; transform: none; } }
@keyframes modal-in { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes toast-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes check-pop { 0% { transform: scale(1); } 45% { transform: scale(1.28); } 100% { transform: scale(1); } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/* -------------------------------- móvil -------------------------------- */

@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }

  .sidebar {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    width: min(84vw, 320px);
    transform: translateX(-102%);
    transition: transform .24s cubic-bezier(.2, .8, .3, 1);
    box-shadow: var(--shadow-3);
  }
  .sidebar.open { transform: translateX(0); }

  /* Mientras el dedo arrastra el panel, manda el JavaScript: sin transición
     ni animación de entrada, o el movimiento va a tirones. */
  body.edge-dragging #sidebar { transition: none; }
  body.edge-dragging #scrim { animation: none; }

  /* Zonas de toque cómodas: mínimo recomendado en móvil. */
  .icon-btn { width: 42px; height: 42px; font-size: 19px; }
  .hamburger {
    display: grid;
    width: 46px;
    height: 46px;
    font-size: 26px;
    margin-left: -8px;       /* alinea el icono con el borde óptico */
  }
  .menu-btn { font-size: 24px; }
  .list-header { padding: calc(10px + var(--safe-t)) 12px 8px; align-items: center; gap: 6px; }

  /* La barra de añadir se pega al borde inferior y su propio fondo cubre la
     zona del indicador de inicio: nada de aire muerto ni franjas de otro color.

     El hueco de abajo es `max`, no una suma. Sumando, en el navegador quedaban
     12px (no hay área segura porque la ocupa la barra de Safari) y en la app
     instalada 12+34 = 46, casi cuatro veces más: de ahí el vacío que solo se
     veía con la app en la pantalla de inicio. Con `max` son 34, los que el
     sistema reserva para el indicador y ni uno más. */
  .add-task {
    margin: 0;
    border-radius: var(--radius) var(--radius) 0 0;
    border-bottom: none;
    padding: 12px 14px max(12px, var(--safe-b));
    box-shadow: 0 -6px 18px rgba(16, 24, 40, .07);
  }
  .header-title { font-size: 20px; }
  .header-title .h-icon, .header-title .icon-btn { font-size: 21px; }
  .task-area { padding: 0 14px 8px; }
  .suggestions { left: 14px; right: 14px; }

  .detail {
    width: 100%;
    top: auto;
    height: 85vh;
    height: 85svh;          /* con las barras del navegador a la vista */
    border-radius: 20px 20px 0 0;
    border-left: none;
    border-top: 1px solid var(--border);
    transform: translateY(102%);
  }
  .detail.open { transform: translateY(0); }

  /* En una pantalla táctil no hay "hover": estos controles van siempre visibles
     (si no, hay que tocar una vez para revelarlos y otra para usarlos). */
  .drag-handle,
  .list-group-grip,
  .nav-grip,
  .list-group-head .icon-btn { opacity: 1; }

  .modal { width: 100%; }
}

@media (min-width: 861px) {
  .detail-open .content { padding-right: 0; }
}




/* ------------------- iOS: cuando el lienzo sale recortado -------------------
   Con la barra de estado opaca, iOS solo dibuja hasta donde llega el área
   segura —medido en un iPhone con isla: 812 de una pantalla de 874, anclados
   arriba— y rellena lo que sobra con el fondo del documento. Se comprobó
   estirando la app a 874 con `lvh`: el contenido se colocaba ahí, pero los
   píxeles por debajo de 812 no se pintaban nunca y el botón de añadir salía
   cortado por la mitad.

   La app pide ahora la barra de estado translúcida, que sí entrega la pantalla
   entera, y entonces nada de esto llega a aplicarse. Pero iOS congela esa
   opción al añadir la app a la pantalla de inicio, así que quien la instaló
   antes sigue con el lienzo corto hasta que la reinstale. Para esos:

   · La franja muerta ya deja libre el indicador de inicio (62 > 34), así que
     reservarle hueco dentro de la app sería contarlo dos veces y subir la
     barra de añadir sin motivo.
   · Y se le da el color de la barra, para que se lea como su continuación
     hasta el borde: el fondo del documento se propaga al lienzo entero aunque
     el elemento sea más pequeño.

   main.js lo comprueba en marcha (¿sobra pantalla, y sobra justo el hueco del
   reloj?) en vez de darlo por hecho: en Android se dibuja hasta el borde y ahí
   el hueco de abajo hace falta de verdad. */
:root[data-lienzo="recortado"] { --safe-b: 0px; }
:root[data-lienzo="recortado"] body { background: var(--surface); }

/* Aviso de que se trabaja sobre una copia guardada. Va donde el de los avisos:
   entre la cabecera y las tareas, fuera de la zona que se desplaza. */
.offline-banner {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 26px 10px;
  padding: 9px 12px;
  border-radius: var(--radius);
  font-size: 13px;
  color: var(--text-dim);
  background: color-mix(in srgb, var(--warning, #e8a33d) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--warning, #e8a33d) 32%, var(--border));
}
.offline-icon { font-size: 16px; line-height: 1; }

@media (max-width: 860px) {
  .offline-banner { margin: 0 12px 8px; }
}

/* Invitación a una lista compartida, arriba de la barra lateral. */
.invitacion {
  margin: 0 8px 10px;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 9%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.invitacion-quien {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-dim);
}
.invitacion-lista { font-size: 14.5px; overflow-wrap: anywhere; }
.invitacion-botones { display: flex; gap: 6px; }
.invitacion-botones .btn { flex: 1 1 0; }
