/* ═══════════════════════════════════════════════════════════════════
   desk-components.css — Desk by Prana · Design System · Fase 1
   ───────────────────────────────────────────────────────────────────
   PRIMITIVOS. Cada bloque anota de qué archivo aprobado salió y con
   qué id de opción. Todo lee var(--desk-*): acá tampoco hay hexes.

   Requiere desk-theme.css cargado antes.
   Requiere assets/lucide.js (íconos <i class="lu" data-i="nombre">).
   Set único: Lucide. Ver ICONOS.md — un concepto = UN icono, para siempre.

   Convención: .desk-bloque__elemento--variante
   ═══════════════════════════════════════════════════════════════════ */

/* ═══ 1 · BOTONES ═════════════════════════════════════════════════
   Origen: v8 11a/11b, v11 14d, v13 pie de modal (CLAUDE.md §4.11).
   Base: píldora de 44 px, radio 999, 14/600, gap 9, ícono adelante.
   Verbo explícito. Nunca "OK" ni "Aceptar". */
.desk-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  height:var(--desk-touch); padding:0 var(--desk-pad-pill-44);
  border:0; border-radius:var(--desk-r-pill);
  font-family:var(--desk-font); font-size:var(--desk-fs-sm); font-weight:600;
  letter-spacing:-.005em; white-space:nowrap; cursor:pointer;
  transition:background var(--desk-t-fast) var(--desk-ease),
             color var(--desk-t-fast) var(--desk-ease),
             box-shadow var(--desk-t-fast) var(--desk-ease);
}
/* Ícono de botón: 17px contra texto de 14 · v21 26b */
.desk-btn > i{ font-size:var(--desk-ico-14); line-height:1; }
.desk-btn:disabled{ opacity:.45; cursor:not-allowed; }
.desk-btn:focus-visible{ outline:0; box-shadow:0 0 0 3px var(--desk-soft), 0 0 0 5px var(--desk-line); }

/* Primaria · relleno sólido de acento · CLAUDE.md §3.7 */
.desk-btn--primary{ background:var(--desk-accent); color:var(--desk-onAccent); }
.desk-btn--primary:hover:not(:disabled){ filter:brightness(.94); }

/* Secundaria · la que va al lado de Cancelar */
.desk-btn--ghost{ background:var(--desk-inset); color:var(--desk-text2); }
.desk-btn--ghost:hover:not(:disabled){ background:var(--desk-hair); color:var(--desk-text); }

/* Carbón · jerarquía máxima, fuera del acento · CLAUDE.md §3.5 */
.desk-btn--carbon{ background:var(--desk-carbon); color:var(--desk-onCarbon); }
.desk-btn--carbon:hover:not(:disabled){ filter:brightness(1.25); }

/* Destructiva · va separada, nunca al lado de la primaria · §4.11 */
.desk-btn--danger{ background:var(--desk-danger); color:var(--desk-onDanger); }
.desk-btn--danger:hover:not(:disabled){ filter:brightness(.92); }
.desk-btn--danger-quiet{ background:transparent; color:var(--desk-danger); padding:0 14px; }
.desk-btn--danger-quiet:hover:not(:disabled){ background:var(--desk-danger-soft); }

/* Sólo texto */
.desk-btn--plain{ background:transparent; color:var(--desk-text2); padding:0 14px; }
.desk-btn--plain:hover:not(:disabled){ background:var(--desk-inset); color:var(--desk-text); }

/* Ícono redondo · superficie flotante, sin border · CLAUDE.md §2 */
.desk-btn--icon{
  width:var(--desk-touch); height:var(--desk-touch); padding:0;
  background:var(--desk-surface); color:var(--desk-text2);
  box-shadow:0 1px 2px rgba(16,18,20,.05);
}
.desk-btn--icon:hover:not(:disabled){ color:var(--desk-text); }
.desk-btn--icon-quiet{ background:var(--desk-inset); box-shadow:none; }

/* Agregar · "Agregar tarea" / "Agregar persona" · §4.1 y §4.11
   Píldora de 44 px en --inset con el más en accentText. No es texto suelto. */
.desk-btn--add{
  width:100%; background:var(--desk-inset); color:var(--desk-text2); justify-content:flex-start;
  padding:0 var(--desk-pad-pill-44);
}
.desk-btn--add > i{ color:var(--desk-accentText); font-size:var(--desk-ico-15); }
.desk-btn--add:hover:not(:disabled){ background:var(--desk-hair); }

/* Tamaños */
.desk-btn--sm{ height:36px; padding:0 var(--desk-pad-pill-36); font-size:var(--desk-fs-xs); gap:9px; }
.desk-btn--sm > i{ font-size:var(--desk-ico-13); }
.desk-btn--sm.desk-btn--icon{ width:36px; padding:0; }
.desk-btn--xs{ height:32px; padding:0 12px; font-size:var(--desk-fs-xs); border-radius:var(--desk-r-tooltip); }
.desk-btn--block{ width:100%; }
/* Móvil: la primaria a lo ancho, 50 px · CLAUDE.md §4.11 */
.desk-btn--mobile{ width:100%; height:var(--desk-h-btn-mobile); font-size:var(--desk-fs-body); }

/* Cargando · el rótulo no cambia de ancho */
.desk-btn[aria-busy="true"]{ pointer-events:none; }
.desk-btn[aria-busy="true"] > i{ animation:desk-spin 1s linear infinite; }


/* ═══ 2 · CAMPOS ══════════════════════════════════════════════════
   Origen: v8 11b (buscador), v16 21a/21b (login), v13 (formularios).
   48 px, radio 16, superficie con canto de 1.5 px por box-shadow inset:
   nunca border · CLAUDE.md §2. */
.desk-field{ display:flex; flex-direction:column; gap:7px; }
.desk-field__label{
  font-size:var(--desk-fs-micro); font-weight:600; color:var(--desk-text2);
  letter-spacing:-.005em;
}
.desk-field__box{
  display:flex; align-items:center; gap:10px;
  height:var(--desk-h-field); padding:0 16px;
  border-radius:var(--desk-r-field);
  background:var(--desk-surface);
  box-shadow:inset 0 0 0 1.5px var(--desk-hair);
  transition:box-shadow var(--desk-t-fast) var(--desk-ease);
}
.desk-field__box > i{ font-size:16px; color:var(--desk-text3); flex:none; }
.desk-field__box:hover{ box-shadow:inset 0 0 0 1.5px var(--desk-text3); }
.desk-field__box:focus-within{ box-shadow:inset 0 0 0 2px var(--desk-line); }
.desk-field__input{
  flex:1; min-width:0; border:0; outline:0; background:transparent;
  font-family:var(--desk-font); font-size:var(--desk-fs-sm); color:var(--desk-text);
}
.desk-field__input::placeholder{ color:var(--desk-text3); }
.desk-field__hint{ font-size:var(--desk-fs-micro); color:var(--desk-text3); }
.desk-field__error{ font-size:var(--desk-fs-micro); color:var(--desk-danger); font-weight:500; }
.desk-field--error .desk-field__box{ box-shadow:inset 0 0 0 2px var(--desk-danger); }
.desk-field--error .desk-field__box:focus-within{ box-shadow:inset 0 0 0 2px var(--desk-danger); }
.desk-field--disabled .desk-field__box{ background:var(--desk-inset); box-shadow:none; opacity:.7; }
/* Número, importe, fecha, hora: mono · CLAUDE.md §2 */
.desk-field--num .desk-field__input{ font-family:var(--desk-font-mono); }
/* Multilínea */
.desk-field__box--area{ height:auto; min-height:110px; padding:14px 16px; align-items:flex-start; }
.desk-field__box--area .desk-field__input{ resize:vertical; min-height:82px; line-height:var(--desk-lh-dense); }

/* Select · misma caja, cheurón a la derecha */
.desk-select{ position:relative; }
.desk-select select{
  appearance:none; width:100%; height:var(--desk-h-field);
  padding:0 44px 0 16px; border:0; outline:0;
  border-radius:var(--desk-r-field); background:var(--desk-surface);
  box-shadow:inset 0 0 0 1.5px var(--desk-hair);
  font-family:var(--desk-font); font-size:var(--desk-fs-sm); color:var(--desk-text);
  cursor:pointer; transition:box-shadow var(--desk-t-fast) var(--desk-ease);
}
.desk-select select:hover{ box-shadow:inset 0 0 0 1.5px var(--desk-text3); }
.desk-select select:focus{ box-shadow:inset 0 0 0 2px var(--desk-line); }
.desk-select__chevron{
  position:absolute; right:16px; top:50%; transform:translateY(-50%);
  pointer-events:none; color:var(--desk-text3); font-size:14px;
}

/* Checkbox · 20 px, radio 6, canto inset de 1.5 px · v10/v11 */
.desk-check{
  appearance:none; margin:0; flex:none;
  width:20px; height:20px; border-radius:var(--desk-r-check);
  background:transparent; box-shadow:inset 0 0 0 1.5px var(--desk-hair);
  cursor:pointer; position:relative;
  transition:background var(--desk-t-fast) var(--desk-ease),
             box-shadow var(--desk-t-fast) var(--desk-ease);
}
.desk-check:hover{ box-shadow:inset 0 0 0 1.5px var(--desk-text3); }
.desk-check:checked{ background:var(--desk-accent); box-shadow:none; }
.desk-check:checked::after{
  content:''; position:absolute; left:6px; top:3px;
  width:5px; height:9px; border:2px solid var(--desk-onAccent);
  border-top:0; border-left:0; transform:rotate(42deg);
}
.desk-check:indeterminate{ background:var(--desk-accent); box-shadow:none; }
.desk-check:indeterminate::after{
  content:''; position:absolute; left:4px; top:8.5px; width:12px; height:2px;
  background:var(--desk-onAccent); border:0; transform:none;
}
.desk-check:focus-visible{ outline:0; box-shadow:0 0 0 3px var(--desk-soft); }
/* El área de toque real son 44 px aunque el cuadro mida 20 */
.desk-check-hit{
  display:inline-flex; align-items:center; justify-content:center;
  width:var(--desk-touch); height:var(--desk-touch); margin:-12px;
}

/* Radio. Ojo: hereda el ::after del tilde del checkbox, que trae
   width:5px;height:9px. Hay que resetear los dos o el punto sale como
   un óvalo vertical — inset no gana contra un width explícito. */
.desk-radio{ border-radius:var(--desk-r-pill); }
.desk-radio:checked::after{
  content:''; position:absolute;
  left:5px; top:5px; width:10px; height:10px;
  border:0; border-radius:var(--desk-r-pill);
  background:var(--desk-onAccent); transform:none;
}

/* Interruptor */
.desk-switch{
  appearance:none; margin:0; flex:none; position:relative; cursor:pointer;
  width:44px; height:26px; border-radius:var(--desk-r-pill);
  background:var(--desk-hair);
  transition:background var(--desk-t-fast) var(--desk-ease);
}
.desk-switch::after{
  content:''; position:absolute; top:3px; left:3px; width:20px; height:20px;
  border-radius:var(--desk-r-pill); background:var(--desk-surface);
  box-shadow:0 1px 3px rgba(16,18,20,.2);
  transition:transform var(--desk-t-fast) var(--desk-ease);
}
.desk-switch:checked{ background:var(--desk-accent); }
.desk-switch:checked::after{ transform:translateX(18px); }


/* ═══ 2.9 · ALINEACIÓN DE ÍCONOS · v21 26a ═══════════════════════
   KeenIcons era una FUENTE: el glifo se apoyaba solo en la línea de
   base. Un SVG no sabe que existe una línea de base.

   En flujo inline lo resuelve el cargador (assets/lucide.js) con
   vertical-align:-.14em — la caja de 1em baja hasta que su centro
   coincide con el centro óptico del texto (~.36em sobre la base, con
   altura de mayúscula .72em en Figtree).

   En una FILA el vertical-align no aplica. La regla es centrar el ícono
   sobre la PRIMERA LÍNEA de texto, nunca sobre el bloque entero: con
   align-items:flex-start el ícono se pega al padding de arriba y cada
   fila lo muestra a distinta altura según cuántas líneas tenga.

   Y la caja del ícono mide LO QUE EL ÍCONO. Una columna de 30px para un
   ícono de 16 mete 14px que se leen como gap, y después el gap real
   parece excesivo. */
.desk-ico{
  display:flex; align-items:center; justify-content:center;
  flex:none; width:20px; height:21px;      /* 21px = alto de línea de 15px */
}
.desk-ico > i{ font-size:var(--desk-ico-15); }
.desk-ico--sm{ width:17px; height:20px; }
.desk-ico--sm > i{ font-size:var(--desk-ico-14); }
.desk-ico--lg{ width:24px; height:24px; }
.desk-ico--lg > i{ font-size:var(--desk-ico-17); }
/* Caja con relleno (avatar de notificación, badge de módulo): ahí sí
   la caja es más grande que el ícono, porque la caja ES la pieza. */
.desk-ico--caja{
  width:30px; height:30px; border-radius:10px;
  background:var(--desk-inset); color:var(--desk-text2);
}
.desk-ico--caja > i{ font-size:var(--desk-ico-13); }


/* ═══ 3 · SELECCIÓN ═══════════════════════════════════════════════
   Regla dura · CLAUDE.md §3.7. Tres pesos, no más:
     .is-elegido → relleno sólido de acento (elegido / abierto ahora)
     .is-marcado → --soft (checkbox en tabla, resaltado informativo)
     sin clase   → todo lo demás
   Nunca relleno tenue con filete. Nunca sólo un tilde al costado. */
.desk-pick{
  display:flex; align-items:center; gap:12px;
  min-height:var(--desk-touch); padding:0 16px;
  border-radius:var(--desk-r-field); background:transparent;
  color:var(--desk-text); font-size:var(--desk-fs-sm); cursor:pointer;
  transition:background var(--desk-t-fast) var(--desk-ease),
             color var(--desk-t-fast) var(--desk-ease);
}
.desk-pick:hover{ background:var(--desk-inset); }
.desk-pick.is-elegido{ background:var(--desk-accent); color:var(--desk-onAccent); font-weight:600; }
.desk-pick.is-elegido i{ color:var(--desk-onAccent); }
/* Sobre relleno, el secundario sube a --text2: el gris tenue no llega
   a 4.5:1 · CLAUDE.md §4.1. Sobre acento usa el mismo sólido, sin alpha. */
.desk-pick.is-elegido .desk-pick__sub{ color:var(--desk-onAccent); opacity:1; }
.desk-pick__sub{ color:var(--desk-text3); font-size:var(--desk-fs-micro); }
.desk-pick.is-marcado{ background:var(--desk-soft); }
.desk-pick.is-marcado .desk-pick__sub{ color:var(--desk-text2); }

/* Tarjeta de opción · tipo de tablero, modo de privacidad · v13 */
.desk-optcard{
  display:flex; flex-direction:column; gap:6px;
  padding:18px; border-radius:var(--desk-r-field-lg);
  background:var(--desk-inset); cursor:pointer;
  transition:background var(--desk-t-fast) var(--desk-ease);
}
.desk-optcard:hover{ background:var(--desk-hair); }
.desk-optcard.is-elegido{ background:var(--desk-accent); }
.desk-optcard__t{ font-size:var(--desk-fs-body); font-weight:600; letter-spacing:-.01em; color:var(--desk-text); }
.desk-optcard__d{ font-size:var(--desk-fs-xs); line-height:var(--desk-lh-dense); color:var(--desk-text3); }
.desk-optcard.is-elegido .desk-optcard__t,
.desk-optcard.is-elegido .desk-optcard__d{ color:var(--desk-onAccent); }

/* Chip de filtro · el activo muestra el valor y su cruz · v12 */
.desk-chip{
  display:inline-flex; align-items:center; gap:8px;
  height:36px; padding:0 14px; border:0;
  border-radius:var(--desk-r-pill); background:var(--desk-inset);
  color:var(--desk-text2); font-family:var(--desk-font);
  font-size:var(--desk-fs-xs); font-weight:600; white-space:nowrap; cursor:pointer;
  transition:background var(--desk-t-fast) var(--desk-ease);
}
.desk-chip:hover{ background:var(--desk-hair); }
.desk-chip.is-elegido{ background:var(--desk-chip); color:var(--desk-onChip); }
.desk-chip__val{ font-family:var(--desk-font-mono); font-weight:500; }
.desk-chip__x{ display:inline-flex; font-size:11px; opacity:.75; }
.desk-chip__x:hover{ opacity:1; }

/* Pestañas · el subrayado usa --line, nunca el acento crudo · §4.9 */
.desk-tabs{ display:flex; gap:2px; align-items:flex-end; }
.desk-tab{
  display:inline-flex; align-items:center; gap:8px;
  height:46px; padding:0 16px; border:0; background:transparent;
  font-family:var(--desk-font); font-size:var(--desk-fs-sm); font-weight:600;
  color:var(--desk-text3); cursor:pointer; position:relative;
  transition:color var(--desk-t-fast) var(--desk-ease);
}
.desk-tab:hover{ color:var(--desk-text2); }
.desk-tab.is-elegido{ color:var(--desk-text); }
.desk-tab.is-elegido::after{
  content:''; position:absolute; left:12px; right:12px; bottom:0;
  height:2px; border-radius:2px; background:var(--desk-line);
}
.desk-tab__n{
  font-family:var(--desk-font-mono); font-size:var(--desk-fs-micro);
  color:var(--desk-text3);
}


/* ═══ 4 · BADGES, PÍLDORAS, AVATARES ══════════════════════════════
   Origen: v10 (estados), v14 17b (stack), v7 10a.
   El badge de estado lleva el color de la base de datos: el acento no
   lo toca · CLAUDE.md §3.5. Los emojis van verbatim · §4.5. */
.desk-badge{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:38px; height:26px; padding:0 10px;
  border-radius:var(--desk-r-pill);
  font-size:var(--desk-fs-micro); font-weight:600;
  white-space:nowrap;               /* label + emoji nunca se parten · §4.5 */
}
.desk-badge--cliente{ background:var(--desk-carbon); color:var(--desk-onCarbon); }
.desk-badge--soft{ background:var(--desk-inset); color:var(--desk-text2); }
.desk-badge--accent{ background:var(--desk-accent); color:var(--desk-onAccent); }
.desk-badge--danger{ background:var(--desk-danger); color:var(--desk-onDanger); }
.desk-badge--outline{ background:transparent; box-shadow:inset 0 0 0 1px var(--desk-hair); color:var(--desk-text2); }
.desk-badge--num{ font-family:var(--desk-font-mono); font-weight:500; }

/* Estados del ítem. El slug es el de desk-theme.css §12. */
.desk-st{ display:inline-flex; align-items:center; justify-content:center;
  min-width:38px; height:26px; padding:0 10px; border-radius:var(--desk-r-pill);
  font-size:var(--desk-fs-micro); font-weight:600; white-space:nowrap; }
.desk-st--a-ingresar{ background:var(--desk-st-a-ingresar-bg); color:var(--desk-st-a-ingresar-fg); }
.desk-st--en-proceso{ background:var(--desk-st-en-proceso-bg); color:var(--desk-st-en-proceso-fg); }
.desk-st--a-asignar{ background:var(--desk-st-a-asignar-bg); color:var(--desk-st-a-asignar-fg); }
.desk-st--aprobacion-interna{ background:var(--desk-st-aprobacion-interna-bg); color:var(--desk-st-aprobacion-interna-fg); }
.desk-st--en-cliente{ background:var(--desk-st-en-cliente-bg); color:var(--desk-st-en-cliente-fg); }
.desk-st--aprobado{ background:var(--desk-st-aprobado-bg); color:var(--desk-st-aprobado-fg); }
.desk-st--finalizado{ background:var(--desk-st-finalizado-bg); color:var(--desk-st-finalizado-fg); }
.desk-st--en-pausa{ background:var(--desk-st-en-pausa-bg); color:var(--desk-st-en-pausa-fg); }
.desk-st--cancelado{ background:var(--desk-st-cancelado-bg); color:var(--desk-st-cancelado-fg); }
.desk-st--seguimiento{ background:var(--desk-st-seguimiento-bg); color:var(--desk-st-seguimiento-fg); }
.desk-st--programado{ background:var(--desk-st-programado-bg); color:var(--desk-st-programado-fg); }
.desk-st--carga-manual{ background:var(--desk-st-carga-manual-bg); color:var(--desk-st-carga-manual-fg); }
/* Punto de color · alternativa aprobada para tablas y listados densos · §4.5 */
.desk-st-dot{ width:9px; height:9px; border-radius:var(--desk-r-pill); flex:none; display:inline-block; }

/* Avatar. Se dibuja con background-image, NUNCA con <img src>: el hole
   en src dispara GET fallidos en cada carga · CLAUDE.md §4.1. */
.desk-avatar{
  flex:none; width:32px; height:32px; border-radius:var(--desk-r-pill);
  background-color:var(--desk-ph); background-size:cover; background-position:center;
}
.desk-avatar--sm{ width:26px; height:26px; }
.desk-avatar--md{ width:34px; height:34px; }
.desk-avatar--lg{ width:44px; height:44px; }
.desk-avatar--xl{ width:56px; height:56px; }
/* Iniciales cuando no hay foto. No es un placeholder de relleno: es el
   estado real de una persona sin foto cargada, así que tiene que verse
   deliberado. El tamaño va a escala del avatar — 0.38 veces el lado —
   porque un 12 px fijo se pierde en un avatar de 56. */
.desk-avatar__ini{
  display:flex; align-items:center; justify-content:center; width:100%; height:100%;
  border-radius:inherit;
  background:var(--desk-inset); color:var(--desk-text2);
  box-shadow:inset 0 0 0 1px var(--desk-hair);
  font-size:12px; font-weight:700; letter-spacing:.02em;
  text-transform:uppercase;
}
.desk-avatar--sm .desk-avatar__ini{ font-size:10px; }
.desk-avatar--md .desk-avatar__ini{ font-size:13px; }
.desk-avatar--lg .desk-avatar__ini{ font-size:16px; }
.desk-avatar--xl .desk-avatar__ini{ font-size:21px; }

/* Stack de caras · un solo stack con el conteo · v14 17b */
.desk-stack{ display:flex; align-items:center; }
.desk-stack > .desk-avatar{ margin-left:-8px; box-shadow:0 0 0 2px var(--desk-surface); }
.desk-stack > .desk-avatar:first-child{ margin-left:0; }
.desk-stack__mas{
  display:inline-flex; align-items:center; justify-content:center;
  height:32px; min-width:32px; padding:0 10px; margin-left:-8px;
  border-radius:var(--desk-r-pill); background:var(--desk-inset);
  box-shadow:0 0 0 2px var(--desk-surface);
  font-family:var(--desk-font-mono); font-size:var(--desk-fs-micro);
  font-weight:500; color:var(--desk-text2);
}
/* Píldora tocable con el conteo total: "14 personas" */
.desk-stack-count{
  display:inline-flex; align-items:center; gap:9px; height:var(--desk-touch);
  padding:0 16px 0 8px; border:0; border-radius:var(--desk-r-pill);
  background:var(--desk-inset); color:var(--desk-text2);
  font-family:var(--desk-font); font-size:var(--desk-fs-xs); font-weight:600; cursor:pointer;
}
.desk-stack-count:hover{ background:var(--desk-hair); }


/* ═══ 5 · TOOLTIP ═════════════════════════════════════════════════
   Fuente de verdad: v11 14e · CLAUDE.md §4.12.
   Carbón, radio 12, 13 px. Demora 400 ms, separación 8 px, ancho máximo
   240. En móvil no existe: la explicación va en la hoja de acciones.

   FLECHA · con dos límites. Sólo en las posiciones vertical (arriba y
   abajo), que es donde la flecha nace de un lado plano. En izquierda y
   derecha se suprime: el ancho del tooltip es chico y la flecha choca
   con el radio de 12 de la esquina, así que en vez de apuntar deforma
   la caja. Y se suprime cuando el tooltip se recoloca y su centro deja
   de estar sobre el disparador — una flecha que apunta al vacío es peor
   que ninguna.

   MOVIMIENTO · entrada 240 ms con la curva de entrada, salida 120 ms
   con la de salida: 4 px de desplazamiento desde el lado del
   disparador, para que se lea que sale de ahí y no que aparece suelto. */
.desk-tip{ position:relative; display:inline-flex; }
.desk-tip__body{
  position:absolute; z-index:70; left:50%; bottom:calc(100% + 8px);
  max-width:var(--desk-tooltip-max); width:max-content;
  padding:9px 12px; border-radius:var(--desk-r-tooltip);
  background:var(--desk-carbon); color:var(--desk-onCarbon);
  font-size:var(--desk-fs-xs); line-height:1.45;
  opacity:0; pointer-events:none;
  transform:translateX(-50%) translateY(4px);
  transition:opacity var(--desk-t-fast) var(--desk-ease-out),
             transform var(--desk-t-fast) var(--desk-ease-out);
  transition-delay:0ms;
}
/* La flecha es un cuadrado rotado con el fondo heredado, así la variante
   destructiva no necesita su propia regla. */
.desk-tip__body::after{
  content:''; position:absolute; width:10px; height:10px;
  background:inherit; border-radius:2px;
  left:50%; margin-left:-5px; bottom:-3px;
  transform:rotate(45deg); clip-path:polygon(100% 0,100% 100%,0 100%);
}
.desk-tip:hover > .desk-tip__body,
.desk-tip:focus-within > .desk-tip__body{
  opacity:1; transform:translateX(-50%) translateY(0);
  transition:opacity var(--desk-t-base) var(--desk-ease),
             transform var(--desk-t-base) var(--desk-ease);
  transition-delay:var(--desk-tooltip-delay);
}
/* 0 ms entre elementos vecinos: el grupo mantiene el tooltip caliente */
.desk-tip-group:hover .desk-tip:hover > .desk-tip__body{ transition-delay:0ms; }

.desk-tip__body--bottom{
  bottom:auto; top:calc(100% + 8px);
  transform:translateX(-50%) translateY(-4px);
}
.desk-tip__body--bottom::after{ bottom:auto; top:-3px; clip-path:polygon(0 0,100% 0,0 100%); }
.desk-tip:hover > .desk-tip__body--bottom,
.desk-tip:focus-within > .desk-tip__body--bottom{ transform:translateX(-50%) translateY(0); }

/* Izquierda y derecha: sin flecha. El radio de 12 se la come. */
.desk-tip__body--left{
  left:auto; right:calc(100% + 8px); bottom:auto; top:50%;
  transform:translateY(-50%) translateX(4px);
}
.desk-tip__body--right{
  left:calc(100% + 8px); bottom:auto; top:50%;
  transform:translateY(-50%) translateX(-4px);
}
.desk-tip__body--left::after,
.desk-tip__body--right::after,
.desk-tip__body--sin-flecha::after{ display:none; }
.desk-tip:hover > .desk-tip__body--left,
.desk-tip:hover > .desk-tip__body--right,
.desk-tip:focus-within > .desk-tip__body--left,
.desk-tip:focus-within > .desk-tip__body--right{ transform:translateY(-50%) translateX(0); }

.desk-tip__body--danger{ background:var(--desk-danger); color:var(--desk-onDanger); }
.desk-tip__d{ display:block; margin-top:3px; color:var(--desk-onCarbon2); }
.desk-tip__key{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:20px; height:20px; padding:0 5px; margin-left:8px;
  border-radius:6px; background:rgba(255,255,255,.14);
  font-family:var(--desk-font-mono); font-size:11px;
}
@media (pointer:coarse){ .desk-tip__body{ display:none; } }


/* ═══ 6 · SUPERFICIES ═════════════════════════════════════════════
   Superficie flotante = fondo + box-shadow con canto de 1 px.
   NUNCA border · CLAUDE.md §2. */
.desk-card{ background:var(--desk-surface); border-radius:var(--desk-r-card); box-shadow:var(--desk-shadow); }
.desk-panel{ background:var(--desk-surface); border-radius:var(--desk-r-panel); box-shadow:var(--desk-shadow-lg); }
.desk-inset{ background:var(--desk-inset); border-radius:var(--desk-r-field-lg); }
.desk-hair{ height:1px; background:var(--desk-hair); border:0; margin:0; }
.desk-eyebrow{
  font-size:var(--desk-fs-eyebrow); letter-spacing:var(--desk-fs-eyebrow-ls);
  text-transform:uppercase; font-weight:700; color:var(--desk-text3);
}

/* Modal · v13, pie según CLAUDE.md §4.11 */
.desk-modal__scrim{
  position:fixed; inset:0; z-index:80; background:rgba(16,18,20,.45);
  backdrop-filter:blur(3px); animation:desk-fade-in var(--desk-t-base) var(--desk-ease);
}
.desk-modal{
  position:relative; z-index:81; display:flex; flex-direction:column;
  max-height:86vh; overflow:hidden;
  background:var(--desk-surface); border-radius:var(--desk-r-panel);
  box-shadow:var(--desk-shadow-lg);
  animation:desk-pop-in var(--desk-t-slow) var(--desk-ease);
}
.desk-modal__head{
  display:flex; align-items:center; gap:14px;
  padding:24px 26px 18px; flex:none;
}
.desk-modal__title{ font-size:var(--desk-fs-h3); font-weight:700; letter-spacing:var(--desk-fs-h3-ls); color:var(--desk-text); }
.desk-modal__body{ padding:0 26px 24px; overflow:auto; flex:1; }
.desk-modal__body.desk-scroll{ scrollbar-width:none; }
/* Pie: fijo, no scrollea. Contexto a la izquierda sin rótulo ni ícono;
   Cancelar y primaria a la derecha, gap 14 · CLAUDE.md §4.11 */
.desk-modal__foot{
  flex:none; display:flex; align-items:center; gap:14px;
  padding:18px 26px; background:var(--desk-panel);
  box-shadow:inset 0 1px 0 var(--desk-hair);
}
.desk-modal__ctx{ font-size:var(--desk-fs-xs); color:var(--desk-text3); flex:1; min-width:0; }
.desk-modal__acts{ display:flex; align-items:center; gap:14px; flex:none; }
@media (max-width:640px){
  .desk-modal{ border-radius:0; max-height:100vh; height:100vh; }
  .desk-modal__foot{
    flex-direction:column-reverse; align-items:stretch; gap:10px;
    padding:14px 18px calc(14px + var(--desk-safe-bottom));
  }
  .desk-modal__acts{ flex-direction:column-reverse; align-items:stretch; gap:10px; }
  .desk-modal__acts .desk-btn{ width:100%; height:var(--desk-h-btn-mobile); }
  .desk-modal__ctx{ text-align:center; }
}

/* Fila de lista del modal · 60 px, radio 18, --inset, foto 34 · §4.11 */
.desk-listrow{
  display:flex; align-items:flex-start; gap:var(--desk-gap-icono);
  min-height:var(--desk-h-listrow); padding:11px 14px;
  border-radius:var(--desk-r-field-lg); background:var(--desk-inset);
}
.desk-listrow__txt{ flex:1; min-width:0; display:flex; flex-direction:column; gap:1px; }
.desk-listrow__n{ font-size:var(--desk-fs-sm); font-weight:600; color:var(--desk-text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.desk-listrow__d{ font-size:var(--desk-fs-micro); color:var(--desk-text3);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.desk-listrow__x{
  flex:none; display:inline-flex; align-items:center; justify-content:center;
  width:32px; height:32px; border:0; border-radius:var(--desk-r-pill);
  background:transparent; color:var(--desk-text3); cursor:pointer;
}
.desk-listrow__x:hover{ background:var(--desk-hair); color:var(--desk-danger); }

/* Popover · reusa la lista del modal · v14 17b */
.desk-pop{
  position:absolute; z-index:75; min-width:320px;
  background:var(--desk-surface); border-radius:var(--desk-r-card-lg);
  box-shadow:var(--desk-shadow-lg); overflow:hidden;
  animation:desk-pop-in var(--desk-t-base) var(--desk-ease);
}
.desk-pop__body{ padding:14px; display:flex; flex-direction:column; gap:6px; max-height:340px; overflow:auto; }
.desk-pop__foot{ padding:12px 14px; background:var(--desk-panel); box-shadow:inset 0 1px 0 var(--desk-hair); }

/* Menú · agrupado por consecuencia: editar · configurar · destruir · §4.9 */
  .desk-menu-legacy{ display:none }
.desk-menu{
  min-width:250px; padding:10px; background:var(--desk-surface);
  border-radius:var(--desk-r-field-lg); box-shadow:var(--desk-shadow-lg);
  display:flex; flex-direction:column; gap:var(--desk-gap-items);
  animation:desk-pop-in var(--desk-t-base) var(--desk-ease) forwards;
}
/* Salida: el elemento se queda montado el tiempo de la animación y
   recién después se desmonta · v20 */
.desk-menu.is-saliendo,
.desk-pop.is-saliendo,
.desk-modal.is-saliendo{ animation:desk-pop-out var(--desk-t-base-out) var(--desk-ease-out) forwards; }
.desk-sheet.is-saliendo{ animation:desk-sheet-out var(--desk-t-slow-out) var(--desk-ease-out) forwards; }
.desk-drawer.is-saliendo{ animation:desk-drawer-out var(--desk-t-slow-out) var(--desk-ease-out) forwards; }
.desk-modal__scrim.is-saliendo,
.desk-drawer__scrim.is-saliendo{ animation:desk-scrim-out var(--desk-t-slow-out) linear forwards; }
/* Densidad CÓMODA por defecto · v21 26e. La densa queda sólo para la
   tabla y los listados donde se comparan filas. */
.desk-menu__item{
  display:flex; align-items:flex-start; gap:var(--desk-gap-icono); width:100%;
  min-height:52px; padding:var(--desk-pad-fila); border:0;
  border-radius:var(--desk-r-row); background:transparent;
  font-family:var(--desk-font); font-size:var(--desk-fs-sm); color:var(--desk-text);
  text-align:left; cursor:pointer;
}
.desk-menu__item > i{ font-size:var(--desk-ico-15); color:var(--desk-text3); flex:none; }
.desk-menu__item:hover{ background:var(--desk-inset); }
.desk-menu__item--danger{ color:var(--desk-danger); }
.desk-menu__item--danger > i{ color:var(--desk-danger); }
.desk-menu__item--danger:hover{ background:var(--desk-danger-soft); }
.desk-menu__sep{ height:1px; margin:10px 8px; background:var(--desk-hair); }
/* La tecla del atajo. OJO: la del tooltip usa rgba(255,255,255,.14),
   que funciona sobre carbón y es invisible sobre la superficie blanca
   del menú. Son dos piezas distintas y cada una lleva su fondo. */
.desk-menu__key{
  margin-left:auto; flex:none;
  display:inline-flex; align-items:center; justify-content:center;
  min-width:22px; height:22px; padding:0 6px;
  border-radius:6px; background:var(--desk-inset);
  box-shadow:inset 0 0 0 1px var(--desk-hair);
  font-family:var(--desk-font-mono); font-size:11.5px;
  color:var(--desk-text2);
}

/* Toast · confirma en carbón · v12 §4.9 */
.desk-toast{
  display:inline-flex; align-items:center; gap:12px;
  min-height:var(--desk-touch); padding:0 18px;
  border-radius:var(--desk-r-field-lg);
  background:var(--desk-carbon); color:var(--desk-onCarbon);
  font-size:var(--desk-fs-sm); font-weight:500;
  box-shadow:var(--desk-shadow-lg);
  animation:desk-pop-in var(--desk-t-base) var(--desk-ease);
}


/* ═══ 7 · SHELL DE ESCRITORIO ═════════════════════════════════════
   Sidebar 246 px, píldoras de 46 px · v3 · CLAUDE.md §4.2 */
/* Sidebar · v22. El padding horizontal es 12 para que el centro del
   ícono caiga a 39 y el riel comprimido mida exactamente 78. */
.desk-sidebar{
  width:var(--desk-sidebar-w); flex:none; height:100%;
  display:flex; flex-direction:column; gap:var(--desk-gap-grupos);
  padding:16px var(--desk-sidebar-pad); background:var(--desk-surface);
  box-shadow:1px 0 0 var(--desk-hair); overflow:hidden;
  transition:width var(--desk-t-sidebar) var(--desk-ease);
}
.desk-sidebar[data-comprimido="1"]{ width:var(--desk-sidebar-riel); }
.desk-sidebar__group{ display:flex; flex-direction:column; gap:2px; flex:none; }
/* El bloque del rótulo mide 26px en LOS DOS estados: texto expandido,
   filete de 20px comprimido. Colapsarlo a cero sube todo lo que tiene
   debajo — 26px por grupo — y comprimir deja de ser un cambio de ancho
   para volverse un salto vertical · v22 27d. */
.desk-sidebar__label{
  height:var(--desk-sidebar-rotulo); display:flex; align-items:center;
  padding:0 var(--desk-pad-pill-44); position:relative; flex:none;
  font-size:var(--desk-fs-eyebrow); letter-spacing:.18em; text-transform:uppercase;
  font-weight:700; color:var(--desk-text3); white-space:nowrap;
}
.desk-sidebar__label > span{ transition:opacity var(--desk-t-label) linear; }
.desk-sidebar__label::after{
  content:''; position:absolute; left:20px; width:20px; height:1px;
  background:var(--desk-hair); opacity:0;
  transition:opacity var(--desk-t-label) linear;
}
.desk-sidebar[data-comprimido="1"] .desk-sidebar__label > span{ opacity:0; }
.desk-sidebar[data-comprimido="1"] .desk-sidebar__label::after{ opacity:1; }
/* Las etiquetas se apagan ANTES de que el ancho termine de cerrar, así
   no se ve el texto cortándose contra el borde. */
.desk-sidebar[data-comprimido="1"] .desk-nav__t,
.desk-sidebar[data-comprimido="1"] .desk-nav__n{ opacity:0; }
.desk-nav__t, .desk-nav__n{ transition:opacity var(--desk-t-label) linear; }

/* Hover: abre en OVERLAY, nunca empujando el contenido. Empujar
   reacomoda la pantalla entera cada vez que el mouse roza el borde, y
   con 28 columnas el reflow se ve. Los handlers van en el PANEL, que es
   el que crece: en la zona de 78px el mouse sale al llegar a los ítems
   y el panel se cierra solo · v22 27b. */
.desk-sidebar-zona{ width:var(--desk-sidebar-riel); flex:none; position:relative; }
.desk-sidebar-zona > .desk-sidebar{
  position:absolute; top:0; bottom:0; left:0;
  width:var(--desk-sidebar-riel); z-index:4;
}
.desk-sidebar-zona > .desk-sidebar:hover{
  width:var(--desk-sidebar-w);
  box-shadow:1px 0 0 var(--desk-hair), 26px 0 60px -20px rgba(16,18,20,.35);
  transition-delay:var(--desk-hover-in);
}
.desk-sidebar-zona > .desk-sidebar{ transition-delay:var(--desk-hover-out); }
/* Fila de 46px, UNA línea, truncada. Una fila de dos líneas rompe la
   altura uniforme que hace que nada se mueva al comprimir, y con radio
   999 el texto entra en la curva de los dos lados. A 246px quedan 187
   para la etiqueta: los nombres largos del Desk entran completos · v22 27d. */
.desk-nav{
  display:flex; align-items:center; gap:var(--desk-gap-icono);
  height:var(--desk-h-nav); padding:0 var(--desk-pad-pill-44);
  overflow:hidden;
  border-radius:var(--desk-r-pill); background:transparent;
  color:var(--desk-text2); font-size:var(--desk-fs-body); cursor:pointer;
  transition:background var(--desk-t-fast) var(--desk-ease), color var(--desk-t-fast) var(--desk-ease);
}
.desk-nav > i{ font-size:var(--desk-ico-15); flex:none; }
.desk-nav__t{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Cuando trunca, la fila lleva tooltip · CLAUDE.md §4.12 */
.desk-nav__n{
  flex:none; font-family:var(--desk-font-mono); font-size:var(--desk-fs-micro);
  color:var(--desk-text3);
}
.desk-nav:hover{ background:var(--desk-inset); color:var(--desk-text); }
/* Activo en acento (expresivo) · §3.4 */
.desk-nav.is-elegido{ background:var(--desk-chip); color:var(--desk-onChip); font-weight:600; }
/* El contador sobre la píldora activa SE INVIERTE: acento sobre acento
   no se lee · CLAUDE.md §3.4 */
.desk-nav.is-elegido .desk-nav__n{
  background:var(--desk-surface); color:var(--desk-accentText);
  padding:1px 7px; border-radius:var(--desk-r-pill); font-weight:600;
}
/* Sin permiso · text3 atenuado · §4.2 */
.desk-nav.is-bloqueado{ color:var(--desk-text3); opacity:.55; cursor:not-allowed; }

/* Lockup del logo · aprobado, se usa siempre así · CLAUDE.md §2.1
   Isotipo por background-image, "Desk" en Figtree 800 como TEXTO. */
.desk-logo{ display:flex; align-items:center; gap:10px; }
.desk-logo__iso{
  flex:none; width:30px; height:30px;
  background-image:url('/assets/desk-iso.png');
  background-size:contain; background-repeat:no-repeat; background-position:center;
}
.desk-logo__wm{
  font-family:var(--desk-font); font-weight:800; font-size:22px;
  letter-spacing:-.03em; color:var(--desk-text); line-height:1;
}
.desk-logo__by{
  font-family:var(--desk-font); font-weight:700; font-size:9px;
  text-transform:uppercase; letter-spacing:.2em; color:var(--desk-text3);
  margin-top:7px; line-height:1;
}
.desk-logo__v{
  font-family:var(--desk-font-mono); font-size:10px; color:var(--desk-text3);
  margin-top:7px;
}
/* Sobre foto o carbón: las tres piezas en blanco, nunca teñidas de acento */
.desk-logo--onDark .desk-logo__wm{ color:#FFFFFF; }
.desk-logo--onDark .desk-logo__by,
.desk-logo--onDark .desk-logo__v{ color:rgba(255,255,255,.5); }

/* ═══ SHELL EN DOS CAPAS · v20 25a ════════════════════════════════
   Dos barras con dueños distintos, y no se mezclan.

   La prueba para saber dónde va algo: si cambia cuando navegás, es de
   la página; si te sigue a todas las pantallas, es de la app. El reloj
   del time tracking es el caso más claro — hay uno solo por persona en
   toda la app, así que si viviera en el header de página desaparecería
   al navegar.

   Capa 1 · .desk-appbar   → ROOT, reloj, notificaciones, chats, tema,
                             usuario. 56px. NO colapsa, NO cambia.
   Capa 2 · .desk-pagehead → breadcrumb, título, badges, acciones de la
                             pantalla. 96px, colapsa a 56.

   Las dos llevan blur progresivo (.desk-blur) porque el contenido pasa
   por debajo. Un solo umbral de scroll, a 48px: o reposo o pegado. Dos
   umbrales se sienten como un temblor al scrollear despacio. */
/* ═══ ANCHO DEL CONTENIDO · v25 32a ═══════════════════════════════
   Dos anchos, y el modo va en el shell como data-attribute:

     data-desk-ancho="maximo"  (por defecto) → el contenido se centra
       y no pasa de --desk-lienzo-max. Para lo que se lee y se decide:
       Inicio, configuración, formularios, listados, detalle de ítem.
     data-desk-ancho="fluido"  → ocupa todo el espacio disponible.
       Para lo que se compara a lo ancho: el tablero con sus 28
       columnas, la semana y el día del calendario, email y chats.

   La misma pareja de clases envuelve las DOS barras y el contenido. Si
   sólo la envuelve el contenido, en máximo el título del header queda
   contra el borde y las cards centradas, y se lee como un error de
   alineación en vez de como una decisión.

   El rail lleva el padding; el inner lleva el máximo. Poner las dos
   cosas en un solo elemento hace que el padding se reste del máximo, y
   entonces el ancho real de la grilla cambia con el viewport.

     <div class="desk-shell" data-desk-ancho="maximo">
       <header class="desk-lienzo"><div class="desk-lienzo__in desk-appbar">…</div></header>
       <main class="desk-lienzo"><div class="desk-lienzo__in">…</div></main>
     </div>                                                        */
.desk-lienzo{ width:100%; padding-inline:var(--desk-lienzo-pad); }
.desk-lienzo__in{ width:100%; max-width:var(--desk-lienzo-max); margin-inline:auto; }
[data-desk-ancho="fluido"] .desk-lienzo__in{ max-width:none; }
/* Una pantalla puede pedir su propio modo sin tocar el shell: el
   atributo más cercano gana por proximidad en el árbol. */
[data-desk-ancho] [data-desk-ancho="maximo"] .desk-lienzo__in{ max-width:var(--desk-lienzo-max); }
.desk-lienzo__in > .desk-appbar,
.desk-lienzo__in.desk-appbar{ padding-left:0; padding-right:0; }
.desk-lienzo__in > .desk-pagehead,
.desk-lienzo__in.desk-pagehead{ padding-inline:0; }
@media (max-width:640px){
  .desk-lienzo{ padding-inline:var(--desk-lienzo-pad-movil); }
}

/* La zona de barras despega del borde del navegador. Sin esto los círculos
   de la barra de aplicación quedan a 8 px del filo de la ventana y se leen
   como pegados al cromo del browser · producción v28. */
.desk-barras{ padding-top:var(--desk-barras-top,10px); }

/* El offset sale de una custom property propia, así un contexto no
   scrolleable (una tarjeta de la galería, un mockup) lo puede poner en
   0 sin pelear con la especificidad. Sobreescribir sólo `position` no
   alcanza: en position:relative el `top` sigue corriendo el elemento
   sin liberar su espacio de layout. */
.desk-appbar{
  position:sticky; top:var(--desk-appbar-top,0px); z-index:50;
  display:flex; align-items:center; gap:10px;
  height:var(--desk-appbar-h); padding:0 20px 0 10px;
}
.desk-appbar__sep{ margin-left:auto; display:flex; align-items:center; gap:10px; flex:none; }
/* El botón NO es fantasma: va sobre disco de superficie. Sobre el fondo gris
   del lienzo un círculo transparente no se lee como botón hasta que lo tocás,
   y estos cinco son la navegación permanente de la app · producción v28. */
.desk-appbar__btn{
  position:relative; display:inline-flex; align-items:center; justify-content:center;
  width:40px; height:40px; border:0; border-radius:var(--desk-r-pill);
  background:var(--desk-surface); box-shadow:0 1px 2px rgba(16,18,20,.06);
  color:var(--desk-text2); cursor:pointer;
  transition:background var(--desk-t-fast) linear;
}
.desk-appbar__btn:hover, .desk-appbar__btn[aria-expanded="true"]{ background:var(--desk-inset); }
.desk-appbar__btn > i{ font-size:var(--desk-ico-17); }
/* El usuario es su foto y nada más: sin disco debajo, sin sombra y sin
   chevron. Una foto de 32 adentro del botón de 40 dibujaba un aro de 4 px
   que se leía como un anillo de estado; ahora la foto ES el botón. */
.desk-appbar__btn--foto{
  background:var(--desk-ph); box-shadow:none;
  background-size:cover; background-position:center;
}
.desk-appbar__btn--foto:hover{ background-color:var(--desk-ph); }
/* Contador: número, no punto, cuando el dato importa */
.desk-appbar__n{
  position:absolute; top:2px; right:0;
  display:inline-flex; align-items:center; justify-content:center;
  min-width:20px; height:19px; padding:0 5px; border-radius:var(--desk-r-pill);
  background:var(--desk-danger); color:#fff;
  font-family:var(--desk-font-mono); font-size:10px; font-weight:500;
}
.desk-appbar__dot{
  position:absolute; top:7px; right:8px; width:7px; height:7px;
  border-radius:var(--desk-r-pill); background:var(--desk-accent);
}
/* Reloj corriendo. La fila NO lleva canto ni borde de color: el
   movimiento del anillo es la señal · CLAUDE.md §4.8 */
.desk-appbar__timer{
  display:inline-flex; align-items:center; gap:11px;
  height:36px; padding:0 14px 0 7px; border:0;
  border-radius:var(--desk-r-pill); background:var(--desk-soft);
  color:var(--desk-text); font-family:var(--desk-font);
  font-size:var(--desk-fs-xs); font-weight:600; white-space:nowrap; cursor:pointer;
  max-width:360px; overflow:hidden;
  transition:max-width var(--desk-t-sidebar) var(--desk-ease), opacity var(--desk-t-label) linear;
}
/* Colapsa por clase, no por [hidden]: el atributo ahora es display:none
   !important (theme §15) y no deja animar el ancho · v28 */
.desk-appbar__timer.is-oculto{ max-width:0; opacity:0; }
/* Identidad: la foto se ancla ARRIBA, no al centro. El bloque puede
   tener nombre + rol + cargo, y con un cargo largo la cabecera crece:
   la foto encabeza el conjunto, no acompaña al nombre · v21 */
.desk-ident{ display:flex; align-items:flex-start; gap:14px; padding:20px 22px 18px; }
.desk-ident__foto{ width:44px; height:44px; border-radius:14px; flex:none;
  background-size:cover; background-position:center; background-color:var(--desk-ph); }
.desk-ident__col{ flex:1; min-width:0; display:flex; flex-direction:column; gap:6px; }
.desk-ident__n{ font-size:var(--desk-fs-body); font-weight:700; letter-spacing:-.015em;
  color:var(--desk-text); line-height:21px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.desk-ident__cargo{ font-size:var(--desk-fs-micro); color:var(--desk-text3);
  line-height:1.45; text-wrap:pretty; }

.desk-pagehead{
  position:sticky; top:var(--desk-pagehead-top,var(--desk-appbar-h)); z-index:45;
  display:flex; align-items:center; gap:16px;
  height:var(--desk-pagehead-h); padding-inline:var(--desk-lienzo-pad); overflow:hidden;
  transition:height var(--desk-t-header) var(--desk-ease);
}
.desk-pagehead[data-pegado="1"]{
  height:var(--desk-appbar-h);
  box-shadow:0 1px 0 var(--desk-hair);
}
.desk-pagehead__col{ flex:1; min-width:0; display:flex; flex-direction:column; justify-content:center; }
.desk-pagehead__t{
  font-size:28px; font-weight:700; letter-spacing:-.03em; color:var(--desk-text);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:font-size var(--desk-t-header) var(--desk-ease);
}
.desk-pagehead[data-pegado="1"] .desk-pagehead__t{ font-size:var(--desk-fs-body); }
/* Breadcrumb · v19 24f, corregido en v25 32d.
   El último nivel va en --text con peso 600: no es link y no tiene
   hover, ya estás ahí. Cuando no entra se trunca el del MEDIO, nunca el
   último. Con más de tres niveles los intermedios se pliegan en un
   botón de puntos. En móvil no hay ruta: hay un nivel, el padre, en el
   volver.

   DOS COSAS QUE NO HACE, y las dos aparecieron en la implementación:

   1 · NO EXISTE EN UN SOLO NIVEL. Una ruta de un elemento no es una
       ruta. En Inicio, Buscador o Reportes el pagehead va sin migas:
       marcá el contenedor con data-nivel="1" y no las renderices. Con
       migas de un nivel más el título debajo, la palabra "Inicio"
       aparece dos veces seguidas y la segunda no agrega nada.

   2 · NO SE PEGA. Vive en el pagehead en reposo y se va cuando el
       pagehead se pega. Lo que queda a los 48 px de scroll es el
       título y las acciones; la ruta ya la leíste al llegar y pegada
       ocupa la única línea que le queda al título.

   Y no repite el título: si el último nivel dice lo mismo que el h1, se
   muestran sólo los ancestros. Si no hay ancestros, no hay migas. */
.desk-migas{
  display:flex; align-items:center; gap:7px; height:20px;
  font-size:var(--desk-fs-xs); color:var(--desk-text3);
  transition:height var(--desk-t-header) var(--desk-ease), opacity var(--desk-t-label) linear;
}
.desk-pagehead[data-pegado="1"] .desk-migas{ height:0; opacity:0; pointer-events:none; }
.desk-pagehead[data-nivel="1"] .desk-migas{ display:none; }
.desk-migas a{ color:inherit; white-space:nowrap; }
.desk-migas a:hover{ color:var(--desk-text2); text-decoration:underline; }
.desk-migas__sep{ opacity:.6; font-size:var(--desk-fs-xs); }
.desk-migas__actual{ color:var(--desk-text); font-weight:600; white-space:nowrap; }
.desk-migas__medio{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  max-width:150px; flex:0 1 auto; }

/* Barra sticky de 56 px al scrollear · v12 §4.9 */
.desk-topbar{
  position:sticky; top:0; z-index:40;
  display:flex; align-items:center; gap:14px;
  height:var(--desk-h-topbar); padding:0 20px;
  background:var(--desk-surface); box-shadow:0 1px 0 var(--desk-hair), var(--desk-shadow);
}
.desk-topbar__t{
  font-size:var(--desk-fs-sm); font-weight:700; letter-spacing:-.015em;
  color:var(--desk-text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.desk-topbar__n{ font-family:var(--desk-font-mono); font-size:var(--desk-fs-micro); color:var(--desk-text3); }

/* Barra de progreso · v12 15a: 260 × 6 px, porcentaje en mono de 26 px */
.desk-progress{ width:260px; height:6px; border-radius:var(--desk-r-pill); background:var(--desk-inset); overflow:hidden; }
.desk-progress__fill{ height:100%; border-radius:inherit; background:var(--desk-accent); }
.desk-progress__pct{ font-family:var(--desk-font-mono); font-size:26px; font-weight:500; letter-spacing:-.02em; color:var(--desk-text); }


/* ═══ 8 · MÓVIL Y EMPAQUETADO NATIVO ═════════════════════════════
   CLAUDE.md §4.6 y §4.7. El contenido nunca arranca en el borde.
   Lienzos de referencia: iPhone 375×812, Android 360×800. */
.desk-safe-t{ padding-top:var(--desk-safe-top); }
.desk-safe-b{ padding-bottom:var(--desk-safe-bottom); }
.desk-safe-x{ padding-left:var(--desk-safe-left); padding-right:var(--desk-safe-right); }

/* Header nativo: va DEBAJO de la barra de estado del sistema */
.desk-mhead{
  position:sticky; top:0; z-index:40;
  padding-top:var(--desk-safe-top);
  background:var(--desk-surface); box-shadow:0 1px 0 var(--desk-hair);
}
.desk-mhead__row{
  display:flex; align-items:center; gap:10px;
  height:52px; padding:0 8px;
}
.desk-mhead__t{
  flex:1; min-width:0; font-size:17px; font-weight:700; letter-spacing:-.02em;
  color:var(--desk-text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* Tab bar · pegada al safe area, no al borde. Cinco destinos; el quinto
   abre el drawer. El activo se marca con color y peso, NO con píldora
   rellena · CLAUDE.md §4.7. Con el teclado abierto se oculta. */
.desk-tabbar{
  position:sticky; bottom:0; z-index:45;
  display:grid; grid-auto-flow:column; grid-auto-columns:1fr;
  padding-bottom:var(--desk-safe-bottom);
  background:var(--desk-surface); box-shadow:0 -1px 0 var(--desk-hair);
}
.desk-tabbar[data-teclado="1"]{ display:none; }
.desk-tabbar__i{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
  min-height:var(--desk-touch); padding:8px 0 6px; border:0; background:transparent;
  color:var(--desk-text3); font-family:var(--desk-font); font-size:10px; font-weight:600;
  cursor:pointer;
}
.desk-tabbar__i > i{ font-size:20px; }
.desk-tabbar__i.is-elegido{ color:var(--desk-accentText); font-weight:700; }

/* Drawer · 300 de 375 px. Entra por el header y por "Más",
   NUNCA por swipe de borde: pelea con el volver de iOS · §4.7 */
.desk-drawer{
  position:fixed; z-index:85; top:0; bottom:0; left:0;
  width:var(--desk-drawer-w); max-width:80vw;
  padding-top:var(--desk-safe-top); padding-bottom:var(--desk-safe-bottom);
  background:var(--desk-panel); box-shadow:var(--desk-shadow-lg);
  overflow:auto; animation:desk-drawer-in var(--desk-t-slow) var(--desk-ease);
}
/* Blur progresivo debajo del drawer · aprobado en §2.1 */
.desk-drawer__scrim{
  position:fixed; inset:0; z-index:84;
  background:rgba(16,18,20,.35); backdrop-filter:blur(4px);
  animation:desk-fade-in var(--desk-t-slow) var(--desk-ease);
}

/* Hoja de acciones. En móvil reemplaza al tooltip: la explicación va
   acá · CLAUDE.md §4.12 */
.desk-sheet{
  position:fixed; z-index:86; left:0; right:0; bottom:0;
  padding-bottom:var(--desk-safe-bottom);
  background:var(--desk-surface);
  border-radius:var(--desk-r-panel) var(--desk-r-panel) 0 0;
  box-shadow:var(--desk-shadow-lg);
  animation:desk-sheet-up var(--desk-t-slow) var(--desk-ease);
}
.desk-sheet__grab{ width:38px; height:4px; border-radius:2px; background:var(--desk-hair); margin:10px auto 4px; }
.desk-sheet__body{ padding:8px 16px 16px; display:flex; flex-direction:column; gap:4px; }
/* Pie fijo por encima del teclado: la primaria nunca al final de un
   scroll largo · CLAUDE.md §4.6 */
.desk-mfoot{
  position:sticky; bottom:0; z-index:44;
  padding:12px 16px calc(12px + var(--desk-safe-bottom));
  background:var(--desk-panel); box-shadow:inset 0 1px 0 var(--desk-hair);
}
/* Nada crítico en los 20 px del borde izquierdo (swipe de volver iOS) */
.desk-no-edge{ margin-left:20px; }


/* ═══ 9 · TABLA DE PENDIENTES ═════════════════════════════════════
   ⚠ NO SE REDISEÑA · CLAUDE.md §4.1 y §7.
   Los anchos de acá son los aprobados, verbatim. El markup de
   referencia está en «Fase 1 v10 - Tablero y Tabla.dc.html» y las
   interacciones en v11: copiarlo de ahí, no rearmarlo. Rearmarla
   introduce paddings distintos entre encabezado y filas, que es lo
   que desalinea las columnas. */
:root{
  --desk-col-tarea: 400px;        /* divisor: 220–760 px, un solo estado global */
  /* 18 columnas · las dos primeras son tirador y checkbox */
  --desk-cols: 22px 22px minmax(var(--desk-col-tarea),1.4fr) 104px 52px 48px 72px 68px 68px 68px 120px 70px 92px 52px 52px 168px 62px 62px;
  /* Las diez de sistema, agrupadas y en gris, al final */
  --desk-cols-sistema: 72px 56px 132px 88px 132px 56px 76px 68px 48px 62px;
  --desk-table-min: 1726px;
}
.desk-table{ background:var(--desk-surface); border-radius:var(--desk-r-card); box-shadow:var(--desk-shadow); overflow:hidden; }
/* El riel vive ADENTRO de cada card y está sincronizado entre grupos.
   La card, el encabezado del grupo y "Agregar tarea" no se mueven:
   sólo viajan las columnas · §4.1 */
.desk-table__rail{ overflow-x:auto; scrollbar-width:none; }
.desk-table__rail::-webkit-scrollbar{ display:none; }
.desk-table__grid{ min-width:var(--desk-table-min); }
.desk-table__head{
  display:grid; grid-template-columns:var(--desk-cols); align-items:center;
  height:52px; padding:0 18px; box-shadow:inset 0 -1px 0 var(--desk-hair);
  font-size:var(--desk-fs-eyebrow); letter-spacing:var(--desk-fs-eyebrow-ls);
  text-transform:uppercase; font-weight:700; color:var(--desk-text3);
}
.desk-table__row{
  display:grid; grid-template-columns:var(--desk-cols); align-items:center;
  height:var(--desk-h-row); padding:0 18px;
  font-size:var(--desk-fs-body); color:var(--desk-text);
}
.desk-table__row:hover{ background:var(--desk-inset); }
/* Tres pesos de fila · v11 14h · §4.1. Pueden convivir en la misma fila. */
.desk-table__row.is-marcado{ background:var(--desk-soft); }         /* checkbox */
.desk-table__row.is-marcado .desk-table__sec{ color:var(--desk-text2); }
.desk-table__row.is-abierto .desk-table__tarea{                      /* drawer abierto */
  background:var(--desk-accent); color:var(--desk-onAccent);
  border-radius:var(--desk-r-tooltip);
}
.desk-table__sec{ color:var(--desk-text3); }
.desk-table__num{ font-family:var(--desk-font-mono); font-size:var(--desk-fs-xs); color:var(--desk-text2); }
/* Fila vencida: fechas con line-through · §4.1 */
.desk-table__row.is-vencida .desk-table__num{ text-decoration:line-through; }
/* Jerarquía: tarea simple SIN ícono · carpeta folder · subtarea
   sangrada 18 px con corner-down-right · §4.1 */
.desk-table__tarea{ display:flex; align-items:center; gap:9px; min-width:0; padding:0 12px; }
.desk-table__tarea--sub{ padding-left:30px; }
.desk-table__tarea span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Oclusión del bloque fijo: sombra lateral SÓLO cuando el riel está
   desplazado · v11 §4.8 */
.desk-table__fix{ position:relative; z-index:2; background:var(--desk-surface); }
.desk-table__rail[data-scrolled="1"] .desk-table__fix{ box-shadow:var(--desk-oclusion), 1px 0 0 var(--desk-hair); }
/* Divisor: filete de 1 px en reposo; 3 px en acento al hover · §4.8 */
.desk-table__div{ width:1px; height:36px; background:var(--desk-hair); cursor:col-resize; }
.desk-table__div:hover, .desk-table__div.is-drag{ width:3px; height:100%; background:var(--desk-line); }
/* Tirador: TRES líneas horizontales, no nueve puntos · §4.8 */
.desk-grip{ display:inline-flex; flex-direction:column; gap:3px; align-items:center; cursor:grab; }
.desk-grip > span{ width:14px; height:2px; border-radius:999px; background:var(--desk-hair); }
.desk-grip:hover > span{ background:var(--desk-text2); }
.desk-grip:active{ cursor:grabbing; }
/* Línea de inserción de 2 px en acento · §4.8 */
.desk-drop-line{ height:2px; border-radius:2px; background:var(--desk-accent); margin:0 10px; }
.desk-drop-line--dentro{ margin-left:42px; }

/* Time tracking · v11 §4.8. Play = triángulo sólido en --line, hecho con
   spans (el triángulo no existe como ícono de línea). Corriendo =
   anillo que gira; la fila NO lleva canto ni borde de color. */
.desk-play{
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; border:0; border-radius:var(--desk-r-pill);
  background:transparent; cursor:pointer;
}
.desk-play__tri{
  width:0; height:0; border-style:solid; border-width:6px 0 6px 10px;
  border-color:transparent transparent transparent var(--desk-line);
  margin-left:2px;
}
.desk-play:hover{ background:var(--desk-inset); }
.desk-timer{ position:relative; display:inline-flex; align-items:center; justify-content:center; width:26px; height:26px; }
.desk-timer__ring{
  position:absolute; inset:0; border-radius:var(--desk-r-pill);
  border:2px solid var(--desk-danger-soft); border-top-color:var(--desk-danger);
  animation:desk-spin 1s linear infinite;
}
.desk-timer__pause{ display:flex; gap:2px; }
.desk-timer__pause > span{ width:2px; height:8px; border-radius:1px; background:var(--desk-danger); }

/* Móvil: la tabla es LA MISMA tabla. Al deslizar, la columna Tarea se
   comprime de 351 a 158 px y queda fija con su sombra de oclusión.
   La card no se mueve · CLAUDE.md §4.6 */
@media (max-width:640px){
  :root{ --desk-col-tarea: 351px; }
  .desk-table__rail[data-comprimido="1"]{ --desk-col-tarea: 158px; }
  .desk-table__row{ font-size:var(--desk-fs-sm); }
}


/* ═══ PIE FIJO DE PANTALLA · v28 producción ═══════════════════════
   El pie de un formulario de pantalla completa NO es el pie de un modal:
   corre de borde a borde del área de contenido (del filete del sidebar al
   borde de la ventana) y se pega abajo, pero su CONTENIDO va adentro del
   mismo rail que las cards. Si la barra se recorta al ancho del contenido,
   flota; si el contenido no entra al rail, los botones caen debajo de otra
   columna y no alinean con nada.

     <footer class="desk-pie-fijo">
       <div class="desk-lienzo"><div class="desk-lienzo__in desk-pie-fijo__in">
         <span class="desk-pie-fijo__ctx">Los cambios se aplican a todo el tablero</span>
         <button class="desk-btn desk-btn--fantasma">Cancelar</button>
         <button class="desk-btn desk-btn--primario"><i class="lu" data-i="check"></i>Guardar cambios</button>
       </div></div>
     </footer>

   El fondo es --panel y no --surface por una razón funcional: Cancelar es
   una píldora --inset, y --inset sobre blanco es invisible. */
.desk-pie-fijo{
  position:sticky; bottom:0; z-index:40;
  background:var(--desk-panel); box-shadow:inset 0 1px 0 var(--desk-hair);
}
.desk-pie-fijo__in{
  display:flex; align-items:center; gap:14px;
  padding-block:18px; min-height:80px;
}
/* Contexto: qué alcance tiene lo que estás por guardar. A la IZQUIERDA,
   una línea, sin rótulo y sin ícono — nunca una advertencia · §4.11.
   Con elipsis: un texto que parte en dos renglones al lado de un botón
   se lee como error. */
.desk-pie-fijo__ctx{
  flex:1; min-width:0; font-size:var(--desk-fs-xs); color:var(--desk-text3);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* La destructiva va a la izquierda, separada de la primaria, y no lleva
   relleno: el peso lo da el color, no una caja roja. */
.desk-pie-fijo__destruir{ flex:none; margin-right:2px; }
@media (max-width:640px){
  /* Apilado, la primaria a lo ancho y sobre el safe area · §4.11 */
  .desk-pie-fijo__in{ flex-wrap:wrap; padding-bottom:calc(18px + env(safe-area-inset-bottom)); }
  .desk-pie-fijo__in > .desk-btn{ width:100%; height:50px; }
  .desk-pie-fijo__ctx{ flex-basis:100%; white-space:normal; }
}


/* ═══ 10 · UTILIDADES ═════════════════════════════════════════════ */
.desk-row{ display:flex; align-items:center; gap:var(--desk-s4); }
.desk-col{ display:flex; flex-direction:column; gap:var(--desk-s4); }
.desk-grow{ flex:1; min-width:0; }
.desk-trunc{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.desk-skel{
  background:var(--desk-inset); border-radius:var(--desk-r-tooltip);
  animation:desk-skeleton 1.4s var(--desk-ease) infinite;
}


/* ═══ CUMPLEAÑOS · v27 ═════════════════════════════════════════════
   La card del cumpleaños NO pesa lo mismo que la del perfil. La foto a
   sangre es el peso más alto del Inicio y está reservada a la card de
   estado del usuario; un cumpleaños es un dato, no un estado.

   Tres pesos, todos sobre la grilla de v24 (columna 108, gap 14,
   fila 160):
     .desk-cumple            → 2 columnas · foto de 44 como avatar
     .desk-cumple--partida   → 3 columnas · foto al costado (el default)
     .desk-cumple-lista      → 4 columnas · el mes entero

   El 🎉 va en el rótulo y es la ÚNICA excepción a "sin emojis" (§4.5).
   Guirnaldas y banderines dibujados con spans: probados y descartados,
   se leen como un glifo roto.                                        */
.desk-cumple{
  border-radius:var(--desk-r-card); background:var(--desk-surface);
  box-shadow:0 0 0 1px var(--desk-hair);
  padding:var(--desk-pad-card);           /* = radio · v27 36 */
  display:flex; flex-direction:column; justify-content:space-between;
}
.desk-cumple__rotulo{
  display:flex; align-items:center; gap:8px;
  font-size:11px; font-weight:700; letter-spacing:.12em; color:var(--desk-text3);
}
.desk-cumple__emoji{ font-size:16px; line-height:1; }
.desk-cumple__foto{
  width:44px; height:44px; border-radius:var(--desk-r-pill); flex:none;
  background-size:cover; background-position:center;
}
.desk-cumple__nombre{ font-size:15px; font-weight:600; letter-spacing:-.01em; line-height:1.25; color:var(--desk-text); }
.desk-cumple__pie{ display:flex; align-items:center; justify-content:space-between; font-size:13px; color:var(--desk-text2); }

/* Partida: la foto ocupa un tercio y la fecha va en una píldora de
   acento PINCHADA sobre el canto, mitad afuera de la foto. */
.desk-cumple--partida{ flex-direction:row; padding:0; overflow:hidden; }
.desk-cumple--partida .desk-cumple__lado{
  width:130px; flex:none; position:relative;
  background-size:cover; background-position:center;
}
.desk-cumple--partida .desk-cumple__col{
  flex:1; min-width:0;
  padding:var(--desk-pad-card) var(--desk-pad-card) var(--desk-pad-card) 30px;
  display:flex; flex-direction:column; justify-content:space-between;
}
.desk-cumple__fecha{
  position:absolute; right:-16px; bottom:16px; z-index:2;
  display:inline-flex; align-items:center; justify-content:center;
  padding:7px 11px; border-radius:14px;
  background:var(--desk-accent); color:var(--desk-onAccent);
  font-family:var(--desk-font-mono); font-size:15px; font-weight:600; line-height:1.1;
  box-shadow:0 10px 24px -10px rgba(16,18,20,.4);
}

/* Lista del mes: blanca, NO carbón. El carbón es la superficie de lo
   que resume, y un cumpleaños no se anuncia de luto. Todas las filas
   llevan las MISMAS cuatro celdas —foto, nombre, área, fecha— con la
   celda de la derecha de ancho fijo; si a la de hoy le falta el área,
   el nombre en flex:1 se estira y las columnas dejan de alinear. */
.desk-cumple-lista{
  border-radius:var(--desk-r-card); background:var(--desk-surface);
  box-shadow:0 0 0 1px var(--desk-hair);
  padding:var(--desk-pad-card); display:flex; flex-direction:column; gap:12px;
}
.desk-cumple-lista__fila{
  display:flex; align-items:center; gap:11px; height:38px;
  padding:0 var(--desk-pad-card-filas); border-radius:12px;
}
.desk-cumple-lista__fila.is-hoy{ background:var(--desk-accent); color:var(--desk-onAccent); }
.desk-cumple-lista__foto{ width:28px; height:28px; border-radius:var(--desk-r-pill); flex:none; background-size:cover; background-position:center; }
.desk-cumple-lista__nombre{ flex:1; min-width:0; font-size:14px; font-weight:500; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.desk-cumple-lista__fila.is-hoy .desk-cumple-lista__nombre{ font-weight:600; }
.desk-cumple-lista__area{ font-size:12.5px; color:var(--desk-text3); flex:none; }
.desk-cumple-lista__fila.is-hoy .desk-cumple-lista__area{ color:var(--desk-onAccent); }
.desk-cumple-lista__cuando{
  flex:none; width:44px; text-align:right;
  font-family:var(--desk-font-mono); font-size:12px; color:var(--desk-text3);
}
.desk-cumple-lista__fila.is-hoy .desk-cumple-lista__cuando{
  font-family:var(--desk-font); font-size:12px; font-weight:700; letter-spacing:.1em; color:var(--desk-onAccent);
}

/* ═══ POPUP DE CUMPLEAÑOS · v27 37 ════════════════════════════════
   Son DOS pantallas, no una. Cuando el cumpleaños es tuyo no hay nada
   que hacer y la única salida honesta es cerrar; cuando es de otro la
   acción es saludar. Poner "Saludar" en el tuyo sería pedirte que te
   saludes.

   Padding: el modal tiene radio 30, así que TODO lo que toca el borde
   —banda, cuerpo y pie— va con 30 horizontal. §4.11 fija los 18
   verticales del pie, no los horizontales.                          */
.desk-cumple-modal{
  width:460px; border-radius:var(--desk-r-panel);
  background:var(--desk-surface); overflow:hidden;
  box-shadow:0 30px 70px -30px rgba(16,18,20,.5);
}
.desk-cumple-modal__banda{
  height:132px; background:var(--desk-accent);
  display:flex; align-items:flex-start; justify-content:space-between;
  padding:22px var(--desk-pad-panel);
}
.desk-cumple-modal__banda .desk-cumple__emoji{ font-size:44px; }
/* El cuerpo monta sobre la banda con margen negativo. Necesita
   position:relative: sin eso la banda (que sí está posicionada) pinta
   encima y le come la mitad de arriba a la foto. */
.desk-cumple-modal__cuerpo{
  margin-top:-52px; position:relative;
  padding:0 var(--desk-pad-panel) var(--desk-pad-panel);
  display:flex; flex-direction:column; align-items:center; gap:4px;
}
.desk-cumple-modal__foto{
  width:104px; height:104px; border-radius:var(--desk-r-pill);
  background-size:cover; background-position:center;
  box-shadow:0 0 0 5px var(--desk-surface); margin-bottom:16px;
}
.desk-cumple-modal__pie{
  background:var(--desk-panel); box-shadow:0 -1px 0 var(--desk-hair);
  padding:18px var(--desk-pad-panel);
  display:flex; align-items:center; justify-content:space-between; gap:14px;
}
/* Emojis para sumar al saludo. 36 en escritorio, 44 en móvil (toque). */
.desk-emojis{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.desk-emojis > button{
  display:inline-flex; align-items:center; justify-content:center;
  width:36px; height:36px; border:0; border-radius:var(--desk-r-pill);
  background:var(--desk-inset); font-size:19px; line-height:1; cursor:pointer;
}
@media (max-width:640px){
  .desk-emojis > button{ width:44px; height:44px; font-size:22px; }
}

/* ═══ PAPELITOS · v27 ══════════════════════════════════════════════
   La capa va POR DELANTE de todo con pointer-events:none. Atrás del
   popup el tiro queda tapado y en móvil la hoja cubre justo la mitad
   por donde pasa. El JS está en desk-papelitos.js.                  */
.desk-papelitos{ position:fixed; inset:0; pointer-events:none; z-index:1200; }
