/* ==========================================================================
   Befocusy App — hoja de estilos de la webapp de cliente (raíz del dominio).
   Tokens del design system de Befocusy + layout responsive (escritorio: sidebar;
   móvil: cabecera + barra inferior + FAB) + estados de los componentes.
   El cuerpo de la app usa estilos inline con var(--*) (igual que el diseño);
   aquí viven los tokens, el reset, las animaciones, la conmutación de "chrome"
   por viewport y las clases :hover/:active.
   ========================================================================== */

:root {
  /* Teal (marca) */
  --teal-50:#F0FDFA; --teal-100:#CCFBF1; --teal-200:#99F6E4; --teal-300:#5EEAD4;
  --teal-400:#2DD4BF; --teal-500:#14B8A6; --teal-600:#0D9488; --teal-700:#0F766E;
  --teal-800:#115E59; --teal-900:#0B3F3A; --teal-950:#06251F;

  /* Neutros (slate) */
  --slate-50:#F8FAFC; --slate-100:#F1F5F9; --slate-200:#E2E8F0; --slate-300:#CBD5E1;
  --slate-400:#94A3B8; --slate-500:#64748B; --slate-600:#475569; --slate-700:#334155;
  --slate-800:#1E293B; --slate-900:#0F172A;
  --ink:#0C1A19; --white:#FFFFFF;

  /* Semánticos */
  --fg1:var(--ink); --fg2:var(--slate-600); --fg3:var(--slate-400); --fg-brand:var(--teal-700);
  --brand:var(--teal-700); --brand-deep:var(--teal-900);
  --bg1:#FFFFFF; --bg2:var(--slate-50); --bg3:var(--slate-100);
  --border:var(--slate-200); --border-strong:var(--slate-300); --border-brand:var(--teal-200);

  /* Estado */
  --success:#059669; --success-bg:#ECFDF5;
  --warning:#D97706; --warning-bg:#FFFBEB;
  --danger:#DC2626;  --danger-bg:#FEF2F2;

  /* Destacados (callout) de Notion — un tinte por color real de Notion, usado
     IDÉNTICO en lectura (app.js:inboxBlock) y edición (_bootstrap.php:
     bfNotaEditableHtml) para que ambas vistas se vean exactamente igual.
     Verde/amarillo/rojo reusan los tokens de estado ya existentes (mismo
     matiz que el resto de la app); gris/azul son nuevos. */
  --callout-default:var(--bg3);
  --callout-gray:var(--slate-100);
  --callout-blue:#E7F3FA;
  --callout-green:var(--success-bg);
  --callout-yellow:var(--warning-bg);
  --callout-red:var(--danger-bg);

  /* Radios */
  --radius-md:12px; --radius-lg:16px; --radius-xl:24px; --radius-2xl:32px; --radius-pill:999px;

  /* Sombras */
  --shadow-xs:0 1px 2px rgba(12,26,25,0.06);
  --shadow-sm:0 1px 3px rgba(12,26,25,0.08), 0 1px 2px rgba(12,26,25,0.04);
  --shadow-md:0 4px 12px rgba(12,26,25,0.08), 0 2px 4px rgba(12,26,25,0.04);
  --shadow-lg:0 12px 32px rgba(12,26,25,0.10), 0 4px 8px rgba(12,26,25,0.04);
  --shadow-brand:0 10px 28px rgba(15,118,110,0.30);
  --shadow-brand-sm:0 4px 14px rgba(15,118,110,0.25);

  /* Tipografía */
  --font-sans:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;
  --font-display:'Poppins','Inter',system-ui,sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,Menlo,monospace;
}

* { box-sizing:border-box; }
html, body { margin:0; height:100%; }
body { font-family:var(--font-sans); color:var(--fg1); background:var(--bg2); -webkit-font-smoothing:antialiased; touch-action:manipulation; }
button { font-family:inherit; }
::-webkit-scrollbar { width:9px; height:9px; }
::-webkit-scrollbar-thumb { background:#cfd8de; border-radius:999px; }
::-webkit-scrollbar-track { background:transparent; }

/* ---- Animaciones ---- */
@keyframes bf-pulse { 0% { transform:scale(1); opacity:.30; } 100% { transform:scale(1.9); opacity:0; } }
@keyframes bf-blink { 0%,100% { opacity:1; } 50% { opacity:.25; } }
@keyframes bf-pop   { 0% { transform:scale(.6); opacity:0; } 60% { transform:scale(1.08); } 100% { transform:scale(1); opacity:1; } }
@keyframes bf-toast { 0% { transform:translate(-50%,14px); opacity:0; } 100% { transform:translate(-50%,0); opacity:1; } }
@keyframes bf-spin  { to { transform:rotate(360deg); } }
@keyframes wos-pop  { 0% { transform:translateY(6px) scale(.985); opacity:.4; } 100% { transform:none; opacity:1; } }
@keyframes bf-shimmer { 0% { background-position:-300px 0; } 100% { background-position:300px 0; } }

/* Placeholder "skeleton" (barra/círculo con brillo animado) mientras se resuelven
   datos que tardan más de un instante — p. ej. la cabecera de un mensaje del Inbox,
   que espera al nombre del contacto del CRM antes de mostrarse, para no parpadear
   entre un valor provisional y el definitivo. */
.bf-skel {
  display:block;
  border-radius:6px;
  background:linear-gradient(90deg, var(--bg2) 25%, var(--border) 37%, var(--bg2) 63%);
  background-size:400px 100%;
  animation:bf-shimmer 1.4s ease-in-out infinite;
}
.bf-skel-circle { border-radius:999px; flex:none; }

/* ==========================================================================
   Conmutación de "chrome" por viewport. < 900px = móvil.
   Los elementos solo-escritorio / solo-móvil se marcan con data-chrome.
   ========================================================================== */
[data-chrome="mobile"], [data-chrome="mobile-nav"] { display:none; }
[data-chrome="desktop"] { display:flex; }
@media (max-width:899px) {
  [data-chrome="desktop"] { display:none !important; }
  [data-chrome="mobile"], [data-chrome="mobile-nav"] { display:flex; }
  /* Botones de acción de la cabecera del Inbox («Enviar mensaje», «Nuevo WhatsApp»):
     en móvil ocupan demasiado con texto → se colapsan a icono cuadrado 40×40, igual
     que los otros botones de la cabecera (reglas/spam/actualizar). El title mantiene
     la etiqueta accesible. !important porque el padding/gap van en estilo inline. */
  .bf-newbtn { width:40px !important; height:40px !important; padding:0 !important; gap:0 !important; justify-content:center; }
  .bf-newbtn-label { display:none; }
}

/* La barra inferior y el FAB (móvil) se ocultan en la sección grabar y en el
   detalle: lo gestiona el JS con la clase .bf-hide-mobilenav en #bfApp. */
#bfApp.bf-hide-mobilenav [data-chrome="mobile-nav"] { display:none !important; }

/* Barra inferior móvil con >5 iconos: scroll horizontal SIN barra de scroll
   visible (el ancho fijo por botón va inline, ver app/index.php). Sin ningún
   indicio visual, un icono que cae fuera del viewport inicial (p. ej.
   «Clientes» cuando el módulo CRM añade una 2ª sección) parece simplemente
   no existir — bug real reportado 2026-08-05. `.bf-navb-more` (activada por
   JS en app.js según scrollLeft/scrollWidth) difumina el borde derecho SOLO
   mientras queda contenido sin ver, como pista de que hay más iconos. */
nav.bf-navb-scroll { scrollbar-width:none; -ms-overflow-style:none; scroll-snap-type:x proximity; }
nav.bf-navb-scroll::-webkit-scrollbar { display:none; height:0; }
nav.bf-navb-scroll > .bf-nav-bottom { scroll-snap-align:start; }
nav.bf-navb-scroll.bf-navb-more {
  -webkit-mask-image:linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
  mask-image:linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
}

/* Filas de pestañas con scroll horizontal (p. ej. las 5 de la ficha de un
   proyecto): mismo ocultado de la barra de scroll que .bf-navb-scroll, pero
   genérica (no cualificada por `nav`) — clase APARTE a propósito, para no
   arriesgar ese fix ya verificado de la barra inferior móvil. */
.bf-tabrow-scroll { scrollbar-width:none; -ms-overflow-style:none; }
.bf-tabrow-scroll::-webkit-scrollbar { display:none; height:0; }

/* ==========================================================================
   Bloqueo de orientación (solo móvil): la app está pensada para vertical. En
   landscape se oculta TODO (login, "sin configurar" o la app) y se muestra un
   aviso para girar el móvil. `pointer:coarse` + `max-height` evitan que dispare
   en escritorio (una ventana normal ya es "landscape") o en tablets grandes.
   Puro CSS: se reevalúa solo al rotar, sin JS. Ver overlay #bfRotateBlock al
   final de app/index.php.
   ========================================================================== */
#bfRotateBlock { display:none; }
@media (orientation:landscape) and (max-height:520px) and (pointer:coarse) {
  body > *:not(#bfRotateBlock) { display:none !important; }
  #bfRotateBlock {
    display:flex !important; position:fixed; inset:0; z-index:9999;
    flex-direction:column; align-items:center; justify-content:center; gap:16px;
    background:var(--bg2); color:var(--fg1); text-align:center; padding:32px;
  }
  #bfRotateBlock svg { color:var(--teal-600); animation:bf-rotate-hint 1.8s ease-in-out infinite; }
  #bfRotateBlock p { margin:0; font-family:var(--font-display); font-size:17px; font-weight:600; line-height:1.4; max-width:280px; color:var(--fg1); }
}
@keyframes bf-rotate-hint { 0%,50%,100% { transform:rotate(0deg); } 25% { transform:rotate(-90deg); } }

/* ---- Spinner de carga ---- */
.bf-spinner { display:inline-block; width:18px; height:18px; border-radius:999px; border:3px solid var(--slate-200); border-top-color:var(--teal-600); animation:bf-spin .8s linear infinite; flex:none; }

/* ---- Layout de página de sección ---- */
/* Sin tope de ancho: cada sección usa todo el ancho disponible del área principal. */
/* padding-bottom:104px (no 40px) en escritorio — el botón flotante de Kairos
   (#deskRec, fixed, right/bottom:24px, 60px de lado, siempre visible en
   escritorio con o sin Kairos configurado) ocupa hasta bottom:84px; sin este
   margen tapaba el botón "Siguientes" del paginador al final de cualquier
   listado largo (Catálogos, CRM, Reuniones…). En móvil ya se reservaban 96px
   por el mismo motivo (ver la regla de abajo, @media max-width:899px) — este
   ajuste solo llevaba el equivalente en escritorio. */
.bf-page { margin:0 auto; padding:28px 32px 104px; }
/* Detalle de un mensaje del Inbox: en pantallas grandes se ensancha (mejor uso del
   espacio y los botones de acción no se cortan); estrecho y legible en pequeñas. */
.bf-inbox-detail { max-width:760px; margin:0 auto; }
@media (min-width:1100px) { .bf-inbox-detail { max-width:1040px; } }
@media (min-width:1400px) { .bf-inbox-detail { max-width:1200px; } }

/* ---- Inbox: rail de filtros (estados + tipos de correo) + lista ----
   Escritorio (≥900px): rail en COLUMNA a la izquierda como tarjeta fija; lista a la
   derecha. Móvil (base): el rail se colapsa tras un botón (hamburguesa) que despliega
   un panel; sin pestañas horizontales con scroll. */
#inboxLayout { display:block; }
#inboxTabs { position:relative; margin-bottom:12px; }
.bf-inbox-mobileonly { display:none; }

/* Botón disparador del panel de filtros (solo móvil) */
.bf-inbox-filterbtn {
  appearance:none; cursor:pointer; align-items:center; gap:10px; width:100%;
  background:var(--white); border:1px solid var(--border-strong); border-radius:12px;
  padding:11px 14px; font-size:14px; font-weight:600; color:var(--fg1); box-shadow:var(--shadow-xs);
}
.bf-inbox-filterbtn .ic { display:flex; flex:none; color:var(--fg2); }
.bf-inbox-filterbtn .dot { flex:none; width:8px; height:8px; border-radius:999px; }
.bf-inbox-filterbtn .lb { flex:1; min-width:0; text-align:left; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bf-inbox-filterbtn .n { flex:none; font-size:12.5px; font-weight:700; color:var(--fg3); }
.bf-inbox-filterbtn .chev { display:flex; flex:none; color:var(--fg3); transition:transform .18s; }
#inboxTabs.is-open .bf-inbox-filterbtn .chev { transform:rotate(180deg); }

/* Panel con estados + tipos (tarjeta) */
.bf-inbox-railpanel { display:none; }
.bf-inbox-states { display:flex; flex-direction:column; gap:3px; }
.bf-inbox-state {
  appearance:none; cursor:pointer; display:flex; align-items:center; gap:11px; width:100%;
  padding:10px 12px; border:none; border-radius:10px; background:transparent; color:var(--fg1);
  text-align:left; font-size:14px; font-weight:500;
}
.bf-inbox-state:hover { background:var(--slate-50); }
.bf-inbox-state.is-active { background:var(--teal-700); color:#fff; font-weight:700; }
.bf-inbox-state .ic { display:flex; flex:none; color:var(--slate-400); }
.bf-inbox-state.is-active .ic { color:rgba(255,255,255,0.92); }
.bf-inbox-state .lb { flex:1; min-width:0; }
.bf-inbox-state .n { flex:none; font-size:12.5px; font-weight:600; color:var(--fg3); }
.bf-inbox-state.is-active .n {
  background:rgba(255,255,255,0.22); color:#fff; min-width:22px; height:20px; padding:0 7px;
  border-radius:999px; display:inline-flex; align-items:center; justify-content:center; font-weight:700;
}
.bf-inbox-railsep { display:flex; align-items:center; gap:8px; padding:14px 10px 8px; }
.bf-inbox-railsep > span { font-size:10.5px; font-weight:700; letter-spacing:0.09em; text-transform:uppercase; color:var(--fg3); white-space:nowrap; }
.bf-inbox-railsep::after { content:''; flex:1; height:1px; background:var(--slate-100); }
.bf-inbox-cats { display:flex; flex-direction:column; gap:1px; }
.bf-inbox-cat {
  appearance:none; cursor:pointer; display:flex; align-items:center; gap:11px; width:100%;
  padding:8px 12px; border:none; border-radius:9px; background:transparent; text-align:left;
}
.bf-inbox-cat:hover { background:var(--slate-50); }
.bf-inbox-cat.is-active { background:var(--teal-50); }
.bf-inbox-cat.is-zero:not(.is-active) { opacity:.5; }
.bf-inbox-catdot { flex:none; width:8px; height:8px; border-radius:999px; }
.bf-inbox-cat.is-active .bf-inbox-catdot { box-shadow:0 0 0 3px var(--teal-100); }
.bf-inbox-catlb { flex:1; min-width:0; font-size:13.5px; font-weight:500; color:var(--fg1); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bf-inbox-cat.is-active .bf-inbox-catlb { font-weight:700; color:var(--teal-700); }
.bf-inbox-catn { flex:none; font-size:12.5px; font-weight:600; color:var(--fg3); font-variant-numeric:tabular-nums; }
.bf-inbox-cat.is-active .bf-inbox-catn { color:var(--teal-700); font-weight:700; }

/* ---- Inbox: fila de mensaje (rejilla adaptativa) ----
   Escritorio: asunto + remitente a la izquierda; tipo+fecha y cuenta a la derecha.
   Móvil: asunto COMPLETO (varias líneas) y debajo tipo, remitente y cuenta. */
.bf-inbox-open {
  text-align:left; appearance:none; cursor:pointer; flex:1; min-width:0; background:transparent;
  border:none; border-radius:14px; padding:14px 16px 14px 6px;
  display:grid; grid-template-columns:1fr auto; grid-template-areas:"subject meta" "from acct";
  column-gap:14px; row-gap:2px; align-items:center;
}
.bf-inbox-subject { grid-area:subject; font-size:14.5px; font-weight:600; color:var(--fg1); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bf-inbox-from { grid-area:from; font-size:13px; color:var(--fg3); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bf-inbox-meta { grid-area:meta; justify-self:end; display:flex; align-items:center; gap:10px; }
.bf-inbox-time { font-size:12px; color:var(--fg3); white-space:nowrap; }
.bf-inbox-acct { grid-area:acct; justify-self:end; max-width:200px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:11px; color:#475569; background:#EEF2F6; border:1px solid var(--border); border-radius:999px; padding:1px 8px; }

@media (min-width:900px) {
  #inboxLayout { display:flex; align-items:flex-start; gap:18px; }
  #inboxTabs {
    flex:0 0 240px; margin-bottom:0; align-self:flex-start; position:sticky; top:0;
    background:var(--white); border:1px solid var(--border); border-radius:16px;
    box-shadow:var(--shadow-xs); padding:10px;
  }
  .bf-inbox-filterbtn { display:none !important; }
  .bf-inbox-railpanel { display:block; }
  #inboxMain { flex:1; min-width:0; }
}

@media (max-width:899px) {
  /* El rail se colapsa: botón disparador + panel desplegable (absoluto). */
  .bf-inbox-filterbtn { display:flex; }
  .bf-inbox-railpanel {
    position:absolute; left:0; right:0; top:calc(100% + 6px); z-index:20;
    background:var(--white); border:1px solid var(--border); border-radius:14px;
    box-shadow:var(--shadow-lg); padding:10px; max-height:72vh; overflow-y:auto;
  }
  #inboxTabs.is-open .bf-inbox-railpanel { display:block; }
  .bf-inbox-mobileonly.is-on { display:inline-flex; }
  /* Barra de acciones en lote: en móvil, iconos sin texto (mismo patrón que
     .bf-newbtn de la cabecera) — ahorra espacio en una fila que ya compite con el
     checkbox «seleccionar todos» y el contador. El `title` del botón sigue dando
     la etiqueta accesible/tooltip. */
  .bf-bulk-btn { width:36px !important; height:36px !important; padding:0 !important; gap:0 !important; justify-content:center; }
  .bf-bulk-label { display:none; }
  /* Fila: asunto completo (varias líneas) → tipo → remitente → cuenta, apilados. */
  .bf-inbox-open { display:flex; flex-direction:column; align-items:stretch; gap:6px; padding:14px 16px; }
  .bf-inbox-subject { white-space:normal; overflow:visible; }
  .bf-inbox-meta { order:2; justify-self:start; flex-wrap:wrap; }
  .bf-inbox-from { order:3; white-space:normal; overflow:visible; word-break:break-all; }
  .bf-inbox-acct { order:4; justify-self:start; max-width:100%; }
  /* Sin arrastre en móvil; permitir interacción normal con las filas. */
  .bf-inbox-item { -webkit-user-select:none; user-select:none; -webkit-touch-callout:none; }
}
/* ---- Notas (Jardín digital): rail de filtro por Tipo ----
   Réplica DELIBERADAMENTE DUPLICADA (no generalizada) del rail de Inbox de arriba,
   con prefijo propio `bf-notas-*` y IDs propios (#notasLayout/#notasTabs/#notasMain)
   — así una futura mejora de este filtro no puede afectar a Inbox, que está en uso
   diario por todos los clientes. Más simple que el de Inbox: sin estados/canales,
   sin contadores (v1 no hace recuentos en vivo) — solo "Todos los tipos" + una
   pestaña por opción real de Notion. Se oculta entera si el cliente no configuró
   VOZ_NOTAS_PROP_TIPO (el JS deja #notasTabs con display:none). */
#notasLayout { display:block; }
#notasTabs { position:relative; margin-bottom:12px; }

.bf-notas-filterbtn {
  appearance:none; cursor:pointer; align-items:center; gap:10px; width:100%;
  background:var(--white); border:1px solid var(--border-strong); border-radius:12px;
  padding:11px 14px; font-size:14px; font-weight:600; color:var(--fg1); box-shadow:var(--shadow-xs);
}
.bf-notas-filterbtn .ic { display:flex; flex:none; color:var(--fg2); }
.bf-notas-filterbtn .dot { flex:none; width:8px; height:8px; border-radius:999px; }
.bf-notas-filterbtn .lb { flex:1; min-width:0; text-align:left; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bf-notas-filterbtn .chev { display:flex; flex:none; color:var(--fg3); transition:transform .18s; }
#notasTabs.is-open .bf-notas-filterbtn .chev { transform:rotate(180deg); }

.bf-notas-railpanel { display:none; }
.bf-notas-railsep { display:flex; align-items:center; gap:8px; padding:4px 10px 8px; }
.bf-notas-railsep > span { font-size:10.5px; font-weight:700; letter-spacing:0.09em; text-transform:uppercase; color:var(--fg3); white-space:nowrap; }
.bf-notas-railsep::after { content:''; flex:1; height:1px; background:var(--slate-100); }
.bf-notas-cats { display:flex; flex-direction:column; gap:1px; }
.bf-notas-cat {
  appearance:none; cursor:pointer; display:flex; align-items:center; gap:11px; width:100%;
  padding:8px 12px; border:none; border-radius:9px; background:transparent; text-align:left;
}
.bf-notas-cat:hover { background:var(--slate-50); }
.bf-notas-cat.is-active { background:var(--teal-50); }
.bf-notas-catdot { flex:none; width:8px; height:8px; border-radius:999px; }
.bf-notas-cat.is-active .bf-notas-catdot { box-shadow:0 0 0 3px var(--teal-100); }
.bf-notas-catlb { flex:1; min-width:0; font-size:13.5px; font-weight:500; color:var(--fg1); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bf-notas-cat.is-active .bf-notas-catlb { font-weight:700; color:var(--teal-700); }
/* Listado agrupado de Jardín digital (sin Temática elegida en el filtro): una
   sección por Temática, con su grid de hasta 12 tarjetas + "Ver todo" si hay más.
   Ver loadNotasGrouped()/notaGroupBlock() en app.js. */
.bf-nota-group + .bf-nota-group { margin-top:28px; }
.bf-nota-grouptitle {
  margin:0 0 12px; font-family:var(--font-display); font-size:16px; font-weight:700;
  color:var(--brand-deep); letter-spacing:-0.01em;
}
.bf-nota-groupgrid { display:grid; grid-template-columns:repeat(auto-fill, minmax(240px, 1fr)); gap:12px; }
.bf-nota-groupmore {
  appearance:none; cursor:pointer; margin-top:10px; border:1px dashed var(--border-strong);
  background:transparent; color:var(--teal-700); font-size:13px; font-weight:600;
  padding:8px 14px; border-radius:10px;
}
.bf-nota-groupmore:hover { background:var(--teal-50); border-color:var(--teal-200); }
/* Nota Favorita (VOZ_NOTAS_PROP_FAVORITA) — tarjeta con borde/fondo ámbar +
   insignia de estrella en la esquina (mismo tono que --warning/--warning-bg ya
   usado en la app, sin inventar un color nuevo). !important: notaCard() pone
   background/border INLINE en el <button&gt; (como el resto de tarjetas de la
   app) — sin esto la clase nunca gana esa pelea de especificidad. */
.bf-nota-card--fav { border-color:var(--warning) !important; background:var(--warning-bg) !important; }
/* Insignias combinadas de favorito+compartido en la esquina de la tarjeta (notaCardBadges() en
   app.js) — un único contenedor absoluto en vez de posicionar cada insignia por separado, para
   que quepan las dos a la vez sin solaparse. */
.bf-nota-badges { position:absolute; top:13px; right:13px; display:flex; align-items:center; gap:6px; }
.bf-nota-starbadge { display:flex; color:var(--warning); }
.bf-nota-sharebadge { display:flex; color:var(--fg3); }

@media (min-width:900px) {
  #notasLayout { display:flex; align-items:flex-start; gap:18px; }
  #notasTabs {
    flex:0 0 220px; margin-bottom:0; align-self:flex-start; position:sticky; top:0;
    background:var(--white); border:1px solid var(--border); border-radius:16px;
    box-shadow:var(--shadow-xs); padding:10px;
  }
  .bf-notas-filterbtn { display:none !important; }
  .bf-notas-railpanel { display:block; }
  #notasMain { flex:1; min-width:0; }
}

@media (max-width:899px) {
  .bf-notas-filterbtn { display:flex; }
  .bf-notas-railpanel {
    position:absolute; left:0; right:0; top:calc(100% + 6px); z-index:20;
    background:var(--white); border:1px solid var(--border); border-radius:14px;
    box-shadow:var(--shadow-lg); padding:10px; max-height:60vh; overflow-y:auto;
  }
  #notasTabs.is-open .bf-notas-railpanel { display:block; }
}

/* ---- Documentos: rail de filtro por Tipo ----
   Mismo componente que el de Notas (comparte las clases .bf-notas-* — el
   pintado de cada pestaña es genérico, no acoplado a Notas pese al nombre),
   pero el LAYOUT (columna lateral en escritorio, desplegable en móvil) estaba
   anclado a los ids propios de Notas (#notasLayout/#notasTabs/#notasMain), no
   a las clases — por eso hacía falta esta réplica con los ids de Documentos,
   sin ella el rail se veía como una lista plana siempre visible en vez de
   columna/desplegable colapsable. */
#docLayout { display:block; }
#docTabs { position:relative; margin-bottom:12px; }

/* Ficha de un documento: bloque «Datos» (Estado/Propietario/Proyecto/
   Participantes/Moneda/valores económicos) en 2 columnas en escritorio, 1 en
   móvil — separado del bloque «Contenido» que va debajo (ver #docDetail en
   index.php). */
.bf-doc-config-grid { display:grid; grid-template-columns:1fr; gap:0 24px; margin-bottom:16px; }
.bf-doc-config-grid > * { margin-bottom:16px; }
@media (min-width:860px) {
  .bf-doc-config-grid { grid-template-columns:1fr 1fr; }
}

@media (min-width:900px) {
  #docLayout { display:flex; align-items:flex-start; gap:18px; }
  #docTabs {
    flex:0 0 220px; margin-bottom:0; align-self:flex-start; position:sticky; top:0;
    background:var(--white); border:1px solid var(--border); border-radius:16px;
    box-shadow:var(--shadow-xs); padding:10px;
  }
  #docMain { flex:1; min-width:0; }
}

@media (max-width:899px) {
  #docTabs.is-open .bf-notas-railpanel { display:block; }
}

/* ---- Wiki: rail de pestañas ----
   Misma réplica DELIBERADA que el bloque de Documentos justo arriba (comparte
   las clases .bf-notas-* para el pintado de cada pestaña — genérico, no
   acoplado a Notas pese al nombre — pero el LAYOUT está anclado a ids
   concretos), con los ids propios de Wiki (#wikiLayout/#wikiTabs/#wikiMain).
   A diferencia de Notas/Documentos, aquí la pestaña activa SIEMPRE existe
   (viene de WikiIndexReader, no es una propiedad opcional) — el rail no se
   oculta nunca (salvo 0 pestañas visibles, caso de config a medias). */
#wikiLayout { display:block; }
#wikiTabs { position:relative; margin-bottom:12px; }

@media (min-width:900px) {
  #wikiLayout { display:flex; align-items:flex-start; gap:18px; }
  #wikiTabs {
    flex:0 0 220px; margin-bottom:0; align-self:flex-start; position:sticky; top:0;
    background:var(--white); border:1px solid var(--border); border-radius:16px;
    box-shadow:var(--shadow-xs); padding:10px;
  }
  #wikiMain { flex:1; min-width:0; }
}

@media (max-width:899px) {
  #wikiTabs.is-open .bf-notas-railpanel { display:block; }
}

/* Acordeón de temáticas (grupos) de la pestaña activa — ver
   loadWikiGrouped()/wikiGroupBlock() en app.js. Un <details> nativo por
   temática (colapsable, sin JS de apertura/cierre propio); el grid de
   tarjetas reutiliza .bf-nota-groupgrid/.bf-nota-group/.bf-nota-grouptitle
   (genéricas, ya usadas por el listado agrupado de Jardín digital). */
.bf-wiki-group + .bf-wiki-group { margin-top:14px; }
.bf-wiki-group {
  background:var(--white); border:1px solid var(--border); border-radius:14px;
  box-shadow:var(--shadow-xs); padding:4px 16px;
}
.bf-wiki-group[open] { padding-bottom:16px; }
.bf-wiki-summary {
  display:flex; align-items:center; gap:10px; cursor:pointer; list-style:none;
  padding:14px 0; user-select:none;
}
.bf-wiki-summary::-webkit-details-marker { display:none; }
.bf-wiki-summary .chev { display:flex; flex:none; color:var(--fg3); transition:transform .18s; }
.bf-wiki-group[open] .bf-wiki-summary .chev { transform:rotate(90deg); }
.bf-wiki-summary h3 {
  flex:1; min-width:0; margin:0; font-family:var(--font-display); font-size:15.5px;
  font-weight:700; color:var(--brand-deep); letter-spacing:-0.01em;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.bf-wiki-summary .count { flex:none; font-size:12.5px; font-weight:600; color:var(--fg3); }
/* Botón «+» de cada grupo — solo visual por ahora (sin acción real, ver plan
   del plugin Wiki: la creación de artículos se aborda en otra sesión). */
.bf-wiki-plus {
  appearance:none; cursor:pointer; flex:none; display:flex; align-items:center;
  justify-content:center; width:26px; height:26px; border:1px dashed var(--border-strong);
  border-radius:8px; background:transparent; color:var(--teal-700);
}
.bf-wiki-plus:hover { background:var(--teal-50); border-color:var(--teal-200); }
.bf-wiki-groupgrid { display:grid; grid-template-columns:repeat(auto-fill, minmax(240px, 1fr)); gap:12px; }

/* ---- CRM: rail de filtro por Estado ----
   Misma réplica DELIBERADA que el bloque de Documentos justo arriba (comparte
   las clases .bf-notas-*, pero el LAYOUT está anclado a ids concretos) — con
   los ids propios de CRM, para que una mejora futura de un rail no afecte a
   los otros dos. */
#crmLayout { display:block; }
#crmTabs { position:relative; margin-bottom:12px; }

@media (min-width:900px) {
  #crmLayout { display:flex; align-items:flex-start; gap:18px; }
  #crmTabs {
    flex:0 0 220px; margin-bottom:0; align-self:flex-start; position:sticky; top:0;
    background:var(--white); border:1px solid var(--border); border-radius:16px;
    box-shadow:var(--shadow-xs); padding:10px;
  }
  #crmMain { flex:1; min-width:0; }
}

@media (max-width:899px) {
  #crmTabs.is-open .bf-notas-railpanel { display:block; }
}

/* ---- CLIENTES del CRM: rail de filtro por Estado ----
   Cuarta copia de la misma réplica deliberada (ver el comentario de CRM justo
   arriba). Ids `cli*` = sección «clientes» (empresas); `crm*` = «contactos». */
#cliLayout { display:block; }
#cliTabs { position:relative; margin-bottom:12px; }

@media (min-width:900px) {
  #cliLayout { display:flex; align-items:flex-start; gap:18px; }
  #cliTabs {
    flex:0 0 220px; margin-bottom:0; align-self:flex-start; position:sticky; top:0;
    background:var(--white); border:1px solid var(--border); border-radius:16px;
    box-shadow:var(--shadow-xs); padding:10px;
  }
  #cliMain { flex:1; min-width:0; }
}

@media (max-width:899px) {
  #cliTabs.is-open .bf-notas-railpanel { display:block; }
}

.bf-pagehead { display:flex; align-items:flex-end; justify-content:space-between; gap:12px; margin-bottom:18px; flex-wrap:wrap; }
.bf-h1 { font-family:var(--font-display); font-size:26px; font-weight:700; letter-spacing:-0.02em; color:var(--brand-deep); margin:0; }
.bf-sub { margin:4px 0 0; font-size:14px; color:var(--fg2); }
@media (max-width:899px) {
  .bf-page { padding:16px 14px 96px; }
  .bf-h1 { font-size:23px; }
}

/* ---- Estados de componentes (hover/active) ---- */
.bf-navbtn:hover { background:rgba(15,118,110,0.05); }
.bf-primary { transition:background .15s, transform .12s; }
.bf-primary:hover { background:var(--teal-800); }
.bf-primary:active { transform:scale(.985); }
.bf-secondary { transition:all .15s; }
.bf-secondary:hover { background:var(--bg3); }
.bf-card-hover { transition:box-shadow .15s, border-color .15s; }
.bf-card-hover:hover { border-color:var(--border-brand); box-shadow:var(--shadow-md); }
/* Botón "Adjuntar" con un fichero arrastrado encima (ver bfWireFileDrop en app.js). */
.bf-filedrop-over { outline:2px solid var(--teal-500); outline-offset:1px; background-color:var(--teal-50) !important; }
/* Tooltip propio (sustituye al `title` nativo, que se retrasa en escritorio y no
   existe en táctil). Se posiciona por JS; el texto va por textContent (multilínea). */
.bf-tip { position:fixed; z-index:10000; pointer-events:none; max-width:260px; white-space:pre-line;
  background:var(--slate-900); color:var(--white); font-size:12px; line-height:1.35;
  padding:7px 9px; border-radius:8px; box-shadow:var(--shadow-lg);
  opacity:0; transform:translateY(2px); transition:opacity .12s, transform .12s; }
.bf-tip.show { opacity:1; transform:translateY(0); }
/* Desplegable de menciones "@" (buscar Notas/Reuniones desde el editor de una nota o
   la Investigación de una publicación). z-index por ENCIMA del offcanvas (9999) y de
   los diálogos (200/300) — puede abrirse dentro de cualquiera de los dos. */
.bf-mention-pop {
  position:fixed; z-index:10001; max-height:260px; overflow-y:auto;
  background:var(--white); border:1px solid var(--border); border-radius:12px;
  box-shadow:var(--shadow-lg); padding:6px;
}
.bf-mention-grouplb { padding:6px 10px 3px; font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--fg3); }
.bf-mention-row {
  appearance:none; cursor:pointer; width:100%; display:flex; align-items:center; gap:8px;
  border:none; background:transparent; border-radius:8px; padding:7px 8px; text-align:left;
  font-size:13.5px; color:var(--fg1);
}
.bf-mention-row.is-active, .bf-mention-row:hover { background:var(--teal-50); }
/* Resaltado por teclado (↑/↓) en los buscadores con desplegable — bfMakeCombo
   (.bfc-opt) y los modales bfPickContact/bfPickProject/bfPickQontoClient
   (.bf-pick-row) — mismo color que .bf-mention-row.is-active, por consistencia. */
.bf-pick-row.is-active, .bf-pick-row:hover { background:var(--teal-50); }
.bfc-opt.is-active, .bfc-opt:hover { background:var(--teal-50); }
.bf-mention-title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.bf-mention-empty { display:flex; align-items:center; padding:9px 10px; font-size:13px; color:var(--fg3); }
/* Editor por bloques de Notas/Documentos (bfNotaEditableHtml en el backend,
   treeFromEditor/wireNotaBlockDrag en app.js) — cada unidad arrastrable (párrafo,
   encabezado, lista, desplegable, destacado, tabla) se envuelve en un .bf-block con
   asa de arrastre. Antes esto era estilo inline duplicado en 4 sitios (2 en
   _bootstrap.php, 2 en app.js); consolidado aquí para que un solo cambio (p.ej.
   centrar el asa) aplique a los 4 de golpe, y para dejar hueco al botón "+" de
   insertar bloque sin volver a triplicar el markup. `align-items:center` (no
   `flex-start`): el asa queda centrada verticalmente aunque el bloque ocupe varias
   líneas (párrafo largo, lista, tabla), no pegada siempre arriba. */
.bf-block { display:flex; align-items:center; gap:6px; margin:2px 0; }
.bf-block-handles { display:flex; align-items:center; gap:0; flex:none; }
.bf-block-drag { cursor:grab; color:var(--fg3); padding:2px 3px; user-select:none; touch-action:none; font-size:14px; line-height:1.8; }
/* Botón "+" de insertar bloque (antes/después) — oculto hasta pasar el ratón por el
   bloque, o al recibir foco por teclado (:focus-visible, para que sea alcanzable sin
   ratón). Ver insertBlockAsSibling()/wireNotaBlockInsert() en app.js. */
.bf-block-plus { cursor:pointer; color:var(--fg3); opacity:0; transition:opacity .12s; padding:2px 3px; font-size:14px; line-height:1.8; }
.bf-block:hover .bf-block-plus, .bf-block-plus:focus-visible { opacity:1; }
/* Botón "borrar bloque" — mismo criterio de aparición que "+" (oculto hasta pasar el
   ratón o recibir foco por teclado), pero en rojo tenue: sutil hasta que se necesita,
   con la intención destructiva clara en cuanto se ve. Ver deleteBfBlock() en app.js.
   SVG en vez de un emoji (🗑): un emoji se pinta con las métricas de la fuente de
   emoji del sistema, que suelen desbordar bastante más grandes de lo que sugiere
   `font-size` — se veía desproporcionado frente a "+"/"⠿" y, al desbordar su propia
   caja, el clic dejaba de caer sobre el elemento real en algunos casos. El SVG fija
   el tamaño en píxeles reales, sin depender de ninguna fuente. `padding` deja el
   área de clic (22×22px con el icono de 13px) más generosa que el icono visible —
   más fácil de acertar sin que se vea grande. */
.bf-block-del { display:inline-flex; align-items:center; justify-content:center; cursor:pointer; color:var(--fg3); opacity:0; transition:opacity .12s, color .12s; padding:4.5px; }
.bf-block:hover .bf-block-del, .bf-block-del:focus-visible { opacity:1; }
.bf-block-del:hover, .bf-block-del:focus-visible { color:var(--danger); }
.bf-block-content { flex:1; min-width:0; }
/* Tamaños de encabezado DENTRO de cualquier región editable — sin esto, un h1-h4
   editable hereda el tamaño por defecto del navegador (todos casi iguales, apenas
   distinguibles). Mismos valores que inboxBlock() usa en modo LECTURA (app.js) para
   que edición y lectura se vean igual. `[contenteditable] hN` cubre tanto el editor
   por bloques (dentro de .bf-block-content) como el editor plano (Tareas/CRM/
   Proyectos, sin ese envoltorio) con una única regla. */
[contenteditable] h1 { font-family:var(--font-display); font-weight:600; font-size:18px; margin:0; }
[contenteditable] h2 { font-family:var(--font-display); font-weight:600; font-size:16px; margin:0; }
[contenteditable] h3 { font-family:var(--font-display); font-weight:600; font-size:15px; margin:0; }
[contenteditable] h4 { font-family:var(--font-display); font-weight:600; font-size:14px; margin:0; }
/* Código en línea: mismos valores que inboxRun() en modo lectura (app.js), para que
   `<code>` se vea igual al editar que al leer. `.bf-code-block code` (bloque de
   código completo) anula esto más abajo — no debe heredar fondo/padding aquí. */
code { background:var(--bg3); border-radius:4px; padding:1px 4px; font-family:var(--font-mono); font-size:.9em; }
/* Bloque de código completo — mismo patrón que el estilo inline PUB_CODE_BOX ya
   usado en el editor de Publicaciones (app.js), convertido a clase real y
   compartida por lectura (inboxBlock) y edición (bfNotaEditorUnitsHtml/
   bfItemsToEditorHtml, ambos en app/_bootstrap.php). El <code> interior anula la
   regla `code {}` de arriba (no debe llevar su propio fondo/padding, el <pre> ya
   lo aporta). */
.bf-code-block {
  width:100%; box-sizing:border-box; margin:4px 0;
  font-family:var(--font-mono); font-size:13px; line-height:1.55;
  color:var(--fg1); background:var(--bg2);
  border:1px solid var(--border); border-radius:var(--radius-md);
  padding:12px 13px; white-space:pre-wrap; word-break:break-word;
  position:relative;
}
.bf-code-block code { background:none; padding:0; border-radius:0; font-size:inherit; }
.bf-code-lang-select {
  position:absolute; top:6px; right:8px; font-size:10.5px;
  border:1px solid var(--border-strong); border-radius:5px; padding:1px 4px;
  background:var(--white); color:var(--fg3);
}
/* Popover de "insertar bloque" — mismo patrón de posicionamiento/z-index que
   .bf-mention-pop (ver arriba), pero más angosto (es una lista de opciones, no un
   buscador). */
.bf-blockins-pop {
  position:fixed; z-index:10001; width:186px;
  background:var(--white); border:1px solid var(--border); border-radius:12px;
  box-shadow:var(--shadow-lg); padding:6px;
}
.bf-blockins-pos { display:flex; gap:4px; padding:2px 2px 6px; margin-bottom:4px; border-bottom:1px solid var(--border); }
.bf-blockins-posbtn {
  appearance:none; cursor:pointer; flex:1; border:1px solid var(--border-strong); background:var(--white);
  color:var(--fg2); font-size:11.5px; font-weight:600; padding:5px 4px; border-radius:7px;
}
.bf-blockins-posbtn.is-active { background:var(--teal-50); border-color:var(--teal-200); color:var(--teal-700); }
/* Chevron del encabezado desplegable (bfNotaEditableHtml, editor de Notas/
   Documentos): rota al abrir el <details> nativo — sustituye al marcador que
   `list-style:none` le quita al <summary> sin dejar ningún indicador visual. */
details[open] > summary[data-bf-role="summary"] > span[data-bf-ui] { transform: rotate(90deg); }
/* Popover de emoji del destacado (sustituye al prompt() de texto) — mismo patrón
   fixed/z-index que .bf-mention-pop/.bf-blockins-pop. */
.bf-emoji-pop {
  position:fixed; z-index:10001; width:220px;
  background:var(--white); border:1px solid var(--border); border-radius:12px;
  box-shadow:var(--shadow-lg); padding:8px;
}
.bf-emoji-grid { display:grid; grid-template-columns:repeat(6, 1fr); gap:2px; margin-bottom:6px; }
.bf-emoji-cell {
  appearance:none; cursor:pointer; border:none; background:transparent; border-radius:7px;
  font-size:18px; line-height:1; padding:6px 0; text-align:center;
}
.bf-emoji-cell:hover { background:var(--bg3); }
.bf-emoji-custom { border-top:1px solid var(--border); padding-top:6px; }
.bf-emoji-custom input {
  width:100%; box-sizing:border-box; border:1px solid var(--border-strong); border-radius:8px;
  padding:6px 8px; font-size:13.5px; outline:none;
}
/* "Quitar emoji" — solo tiene sentido cuando el popover se abrió para el icono de
   portada de una nota (Jardín digital); en el destacado del editor simplemente
   vacía el icono, sin efecto dañino. */
.bf-emoji-clear {
  appearance:none; cursor:pointer; width:100%; margin-top:6px; border:none; background:transparent;
  color:var(--fg3); font-size:12.5px; font-weight:600; padding:6px 4px; border-radius:7px; text-align:center;
}
.bf-emoji-clear:hover { background:var(--bg3); color:var(--fg1); }
#notaDetailIcon:hover { background:var(--bg3) !important; }
/* Popover de color de texto (botón "A" de la barra de formato, Notas/Documentos)
   — 9 swatches de texto + 9 de resaltado + "Quitar color". Mismo patrón fixed/
   z-index que .bf-emoji-pop/.bf-link-pop. Ver ensureColorPop() en app.js. */
.bf-color-pop {
  position:fixed; z-index:10001; width:216px;
  background:var(--white); border:1px solid var(--border); border-radius:12px;
  box-shadow:var(--shadow-lg); padding:8px;
}
.bf-color-pop-row { display:flex; align-items:center; gap:3px; margin-bottom:6px; }
.bf-color-pop-label { flex:none; width:56px; font-size:11px; color:var(--fg3); }
.bf-color-pop-swatch {
  appearance:none; cursor:pointer; flex:1; height:24px; border:1px solid var(--border);
  border-radius:6px; font-size:12px; font-weight:700; padding:0;
}
.bf-color-pop-swatch:hover { box-shadow:0 0 0 2px var(--teal-200); }
.bf-color-pop-clear {
  appearance:none; cursor:pointer; width:100%; border:1px solid var(--border); background:transparent;
  border-radius:8px; padding:6px 8px; font-size:12.5px; color:var(--fg2); margin-top:2px;
}
.bf-color-pop-clear:hover { background:var(--bg3); }
.bf-blockins-row {
  appearance:none; cursor:pointer; width:100%; display:flex; align-items:center; gap:8px;
  border:none; background:transparent; border-radius:8px; padding:7px 8px; text-align:left;
  font-size:13.5px; color:var(--fg1);
}
.bf-blockins-row:hover { background:var(--teal-50); }
/* Popover de enlace (crear/editar la URL — quitar es el icono de papelera después del
   enlace, ver bfInlineIconBtnHtml en app.js/_bootstrap.php). Mismo patrón fixed/z-index
   que .bf-mention-pop/.bf-emoji-pop. Ver ensureLinkPop() en app.js. */
.bf-link-pop {
  position:fixed; z-index:10001; width:280px;
  background:var(--white); border:1px solid var(--border); border-radius:12px;
  box-shadow:var(--shadow-lg); padding:8px; display:flex; flex-direction:column; gap:8px;
}
.bf-link-pop-input {
  width:100%; box-sizing:border-box; border:1px solid var(--border-strong); border-radius:8px;
  padding:7px 9px; font-size:13.5px; outline:none;
}
.bf-link-pop-input:focus { border-color:var(--teal-500); box-shadow:0 0 0 3px var(--teal-100); }
.bf-link-pop-actions { display:flex; gap:6px; justify-content:flex-end; }
.bf-link-pop-actions button {
  appearance:none; cursor:pointer; border:none; border-radius:8px; font-size:12.5px; font-weight:600; padding:7px 12px;
}
.bf-link-pop-actions [data-act="save"] { background:var(--teal-700); color:#fff; }
/* Iconos de editar/quitar enlace y quitar mención (después del propio enlace, dentro
   de [data-bf-link-unit]) — más oscuros al pasar el ratón/foco para dejar clara la
   intención; el de quitar (papelera), además, en rojo. */
[data-link-edit]:hover, [data-link-edit]:focus-visible,
[data-link-del]:hover, [data-link-del]:focus-visible,
[data-mention-del]:hover, [data-mention-del]:focus-visible { background:var(--bg3); }
[data-link-del]:hover, [data-link-del]:focus-visible,
[data-mention-del]:hover, [data-mention-del]:focus-visible { color:var(--danger); }
/* Círculo de usuario del header + su desplegable (nombre, cliente, cambiar de
   cliente, salir). Duplicado en escritorio/móvil con ids propios (D/M), pero
   estas clases son compartidas — ver wireUserMenu() en app.js. Icono simple de
   usuario (antes iniciales) — ver $IC['user'] en index.php. */
.bf-usermenu-trigger {
  appearance:none; cursor:pointer; border:none; width:34px; height:34px; border-radius:999px;
  background:var(--teal-600); color:#fff;
  display:flex; align-items:center; justify-content:center; transition:background .15s; flex:none;
}
.bf-usermenu-trigger:hover { background:var(--teal-700); }
.bf-usermenu-trigger-sm { width:30px; height:30px; }
/* Saludo "Hola, {nombre}" — solo escritorio (hay sitio en el header; en móvil el
   círculo se queda solo con el icono). Recorta con ellipsis ante nombres largos
   en ventanas estrechas, en vez de forzar overflow del header. */
.bf-usermenu-greeting {
  font-size:13px; font-weight:600; color:var(--fg2); white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis; max-width:160px;
}
.bf-usermenu-panel {
  position:absolute; top:calc(100% + 8px); right:0; z-index:60; min-width:240px; max-width:300px;
  background:var(--white); border:1px solid var(--border); border-radius:14px; box-shadow:var(--shadow-lg);
  padding:14px; display:flex; flex-direction:column;
}
/* [hidden] y la clase (display:flex) empatan en especificidad; sin esto la regla de
   autor .bf-usermenu-panel gana sobre la de user-agent [hidden] y el panel queda
   siempre visible. Con el atributo selector, [hidden] pesa más y sí lo oculta. */
.bf-usermenu-panel[hidden] { display:none; }
.bf-usermenu-name { font-size:14.5px; font-weight:700; color:var(--fg1); }
.bf-usermenu-client { margin-top:2px; font-size:12.5px; color:var(--fg3); }
.bf-usermenu-divider { height:1px; background:var(--border); margin:10px 0; }
.bf-usermenu-hint { margin:0 0 6px; font-size:11px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; color:var(--fg3); }
.bf-usermenu-switch { display:flex; flex-direction:column; gap:6px; max-height:180px; overflow-y:auto; }
.bf-usermenu-switchbtn {
  appearance:none; cursor:pointer; text-align:left; width:100%; border:1px solid var(--border-strong);
  background:var(--white); color:var(--fg1); font-size:13px; font-weight:600; padding:8px 10px;
  border-radius:9px; display:flex; align-items:center; justify-content:space-between; gap:8px;
}
.bf-usermenu-switchbtn:hover { background:var(--bg3); }
.bf-usermenu-switchbtn:disabled { cursor:default; }
.bf-usermenu-role { color:var(--fg3); font-size:11px; font-weight:500; }
.bf-usermenu-switchmsg { margin:8px 0 0; font-size:12.5px; }
.bf-usermenu-item {
  appearance:none; cursor:pointer; border:none; background:transparent; text-align:left; width:100%;
  color:var(--fg1); font-size:13.5px; font-weight:600; padding:9px 10px; border-radius:9px;
}
.bf-usermenu-item:hover { background:var(--bg3); }
/* Offcanvas lateral (detalle de una tarea) */
.bf-oc-backdrop { position:fixed; inset:0; background:rgba(12,26,25,.42); z-index:9998; opacity:0; transition:opacity .2s ease; }
.bf-oc-backdrop.show { opacity:1; }
.bf-oc { position:fixed; top:0; right:0; height:100%; width:min(440px,94vw); background:var(--white); z-index:9999;
  box-shadow:var(--shadow-lg); display:flex; flex-direction:column;
  transform:translateX(100%); transition:transform .24s cubic-bezier(.4,0,.2,1); }
.bf-oc.show { transform:translateX(0); }
.bf-oc-head { display:flex; align-items:center; justify-content:space-between; gap:8px; padding:18px 20px; border-bottom:1px solid var(--border); }
.bf-oc-head h3 { margin:0; font-family:var(--font-display); font-size:17px; font-weight:600; color:var(--brand-deep); }
.bf-oc-x { appearance:none; cursor:pointer; border:none; background:transparent; color:var(--fg3); font-size:20px; line-height:1; padding:4px 7px; border-radius:8px; }
.bf-oc-x:hover { background:var(--bg3); color:var(--fg1); }
.bf-oc-body { flex:1; overflow-y:auto; padding:20px; }
.bf-oc-label { display:block; font-size:12px; font-weight:600; color:var(--fg3); text-transform:uppercase; letter-spacing:.04em; margin-bottom:6px; }
.bf-oc-input { width:100%; box-sizing:border-box; font-size:15px; color:var(--fg1); background:var(--white); border:1px solid var(--border-strong); border-radius:10px; padding:10px 12px; outline:none; transition:border-color .15s, box-shadow .15s; }
.bf-oc-input:focus { border-color:var(--teal-500); box-shadow:0 0 0 3px var(--teal-100); }
/* Foco verde WorkOS en TODOS los campos de la app (sustituye el azul por defecto del
   navegador). Muchos inputs fijan el borde con estilo inline (shorthand `border`), que
   gana al selector de clase → `!important` en el color del borde. Casillas/radios fuera. */
input:not([type=checkbox]):not([type=radio]):focus,
select:focus,
textarea:focus,
.bfc-trigger:focus-visible,
.bfc-search:focus {
  outline:none !important;
  border-color:var(--teal-500) !important;
  box-shadow:0 0 0 3px var(--teal-100);
}
.bf-oc-meta { margin-top:10px; display:flex; flex-direction:column; }
.bf-oc-field { display:flex; align-items:flex-start; gap:12px; padding:11px 0; border-bottom:1px solid var(--slate-100); font-size:14px; color:var(--fg1); }
.bf-oc-field:first-child { border-top:1px solid var(--slate-100); }
.bf-oc-flabel { flex:none; width:96px; font-size:12.5px; color:var(--fg3); padding-top:1px; }
/* Ancho ESTÁNDAR de los offcanvas "grandes" (bf-oc-wide): 620px en vez de los 440px
   por defecto — nació con el de TAREA (bf-oc-task, que además reorganiza sus campos
   en 2 columnas más abajo) y ahora es el ancho de referencia para cualquier offcanvas
   con contenido sustancioso (reunión, evento de agenda, publicación…). `bf-oc-task`
   sigue llevando también esta clase compartida (mismo ancho, sin duplicar el valor).
   Solo desktop; en móvil todos los offcanvas se quedan en min(…,94vw) como siempre. */
@media (min-width:900px) {
  .bf-oc-task, .bf-oc-wide { width:min(620px,94vw); }
  /* Offcanvas de TAREA: además del ancho de arriba, campos en 2 columnas —
     tiene más campos que el resto de offcanvas (estado/tipo/fecha/proyecto/responsable/
     seguimiento) y en una sola columna angosta quedaba muy apretado. La etiqueta pasa a
     ir ENCIMA del campo (en vez de al lado, con ancho fijo) para dejarle más sitio al
     propio control. */
  .bf-oc-task .bf-oc-meta { display:grid; grid-template-columns:1fr 1fr; column-gap:24px; row-gap:2px; }
  .bf-oc-task .bf-oc-field { flex-direction:column; align-items:stretch; gap:4px; border-bottom:none; padding:9px 0; }
  .bf-oc-task .bf-oc-field:first-child { border-top:none; }
  .bf-oc-task .bf-oc-flabel { width:auto; padding-top:0; }
}
.bf-oc-foot { padding:16px 20px; border-top:1px solid var(--border); display:flex; gap:10px; }
/* Offcanvas de TAREA: 4 botones posibles (Descartar/Borrar/Completar/Guardar, algunos
   condicionales vía display:none) — en móvil se apilan a ancho completo (como antes);
   en escritorio pasan a una rejilla de 2 columnas para ocupar menos alto (los botones
   ocultos simplemente no cuentan en el flujo de la rejilla). */
.bf-oc-foot-task { flex-direction:column; align-items:stretch; gap:10px; }
@media (min-width:900px) {
  .bf-oc-foot-task { display:grid; grid-template-columns:1fr 1fr; }
}
.bf-oc-save { flex:1; appearance:none; cursor:pointer; border:none; background:var(--teal-600); color:#fff; font-size:14px; font-weight:600; border-radius:10px; padding:11px 16px; transition:background .15s; }
.bf-oc-save:hover { background:var(--teal-700); }
.bf-oc-save:disabled { opacity:.55; cursor:default; }

/* ==========================================================================
   Kairos — panel deslizante de escritorio (≥900px), reutilizando TAL CUAL el
   nodo &lt;section data-section="grabar"&gt; (mismos ids, mismo motor de app.js —
   nunca se mueve/duplica). SIN backdrop, a propósito (decisión de producto:
   asistente "copiloto", se sigue viendo/usando la sección de fondo). La
   visibilidad (display) la gestiona JS (openKairosPanel/closeKairosPanel en
   app.js + el guard en showSection()) — aquí solo el posicionamiento/anim.
   En móvil (&lt;900px) esta regla no aplica: la sección sigue en flujo normal,
   pantalla completa, exactamente como siempre. ========================== */
#kairosCloseBtn { display:none; }
@media (min-width:900px) {
  #kairosCloseBtn { display:flex; }
  #bfApp.bf-kairos-panel [data-section="grabar"] {
    position:fixed; top:0; right:0; height:100%; width:min(480px,94vw);
    z-index:9999; box-shadow:var(--shadow-lg); background:var(--white);
    transform:translateX(100%);
    transition:transform .24s cubic-bezier(.4,0,.2,1);
  }
  #bfApp.bf-kairos-panel.bf-kairos-show [data-section="grabar"] { transform:translateX(0); }
  /* El wrapper de las pantallas (#kairosScreens) pasa de "tarjeta centrada a
     560px" a "llenar el panel, con scroll propio". Selector por ID a propósito
     (antes era `> div:nth-child(2)` — posicional; añadir la barra de pestañas
     #kairosModeTabs como hermano ANTES de este wrapper lo desplazó a 3er hijo y
     rompió la regla en silencio, dejando el composer/mic fuera del área visible
     del panel). */
  #bfApp.bf-kairos-panel [data-section="grabar"] #kairosScreens {
    max-width:none !important; margin:0 !important; padding:20px !important;
    min-height:0 !important; flex:1 1 auto; overflow-y:auto;
  }
}

/* Pasos de la pantalla "processing" (pending → active → done). */
.bf-procstep { display:flex; align-items:center; gap:12px; font-size:14px; color:var(--fg3); }
.bf-procstep-dot { flex:none; width:9px; height:9px; border-radius:999px; background:var(--slate-300); }
.bf-procstep.is-active { color:var(--brand-deep); font-weight:600; }
.bf-procstep.is-active .bf-procstep-dot { background:var(--teal-600); animation:bf-blink 1.2s ease-in-out infinite; }
.bf-procstep.is-done { color:var(--fg2); }
.bf-procstep.is-done .bf-procstep-dot { background:var(--success); }

/* Tarjeta de resolución (renderJob()/#jobStatus) — mismo `inflight`/`lastResult`
   de siempre, solo restyling. */
.bf-proc-card { display:flex; align-items:flex-start; gap:10px; padding:12px 14px; border-radius:12px; line-height:1.4; }
.bf-proc-card-ok { background:var(--success-bg); color:var(--success); }
.bf-proc-card-err { background:var(--danger-bg); color:var(--danger); }
.bf-proc-card-pending { background:var(--bg3); color:var(--fg2); }

.bf-mic { transition:transform .15s, background .15s; }
.bf-mic:hover { background:var(--teal-800); }
.bf-mic:active { transform:scale(.95); }
.bf-cat { transition:all .18s cubic-bezier(.4,0,.2,1); }
.bf-cat:hover { border-color:var(--border-brand); background:var(--teal-50); }
.bf-link:hover { text-decoration:underline; text-underline-offset:3px; }
.bf-play:hover { background:var(--teal-800); }
.bf-iconbtn { transition:background .15s, color .15s; }
.bf-iconbtn:hover { background:var(--bg3); }
.bf-topbtn:hover { color:var(--teal-700); }
/* Botón «completar tarea» (lista/kanban): outline que se rellena en verde al pasar. */
.tarea-complete { transition:background .15s, border-color .15s, color .15s, transform .1s; }
.tarea-complete:hover { background:var(--success); border-color:var(--success); color:#fff; }
.tarea-complete:active { transform:scale(.92); }
.tarea-complete:disabled { cursor:default; }

/* Botones «Editar»/«Eliminar» de un registro de Seguimiento de tiempo (pestaña
   «Tiempos» del offcanvas): se deshabilitan JUNTOS desde el primer clic en
   «Eliminar» (antes incluso de confirmar) — atenuados mientras tanto, para que
   «deshabilitado» se lea como «trabajando», no como roto. */
.tarea-time-edit:disabled, .tarea-time-delete:disabled { opacity:.45; cursor:default; }

/* Constructor de voz IA paso a paso (modal abierto desde el banner de personalización). */
.aiw-chip {
  appearance:none; cursor:pointer; border:1px solid var(--border-strong); background:var(--white);
  color:var(--fg2); font-size:13px; font-weight:600; padding:7px 13px; border-radius:999px;
  transition:background .15s, border-color .15s, color .15s;
}
.aiw-chip:hover { border-color:var(--border-brand); }
.aiw-chip.on { background:var(--teal-700); border-color:var(--teal-700); color:#fff; }
.aiw-dot {
  appearance:none; cursor:pointer; width:36px; height:36px; border-radius:999px; border:1px solid var(--border-strong);
  background:var(--white); color:var(--fg3); font-size:13px; font-weight:700; display:flex; align-items:center; justify-content:center;
  transition:background .15s, border-color .15s, color .15s;
}
.aiw-dot:hover { border-color:var(--border-brand); }
.aiw-dot.on { background:var(--teal-700); border-color:var(--teal-700); color:#fff; }
.aiw-step { animation:wos-pop .22s ease; }
/* Resaltado sutil («efecto Gmail») de un mensaje del Inbox recién insertado por un
   refresco silencioso del latido (ver pollInboxHeartbeat/loadInbox(quiet) en app.js). */
.bf-inbox-item-new { animation:wos-pop .5s ease; }
.aiw-post-x { appearance:none; cursor:pointer; border:none; background:transparent; color:var(--fg3); font-size:15px; line-height:1; padding:4px 6px; border-radius:8px; }
.aiw-post-x:hover { background:var(--bg3); color:var(--fg1); }
.aiw-add { appearance:none; cursor:pointer; display:inline-flex; align-items:center; gap:6px; border:1px dashed var(--border-strong); background:var(--white); color:var(--teal-700); font-size:13px; font-weight:600; padding:8px 13px; border-radius:10px; }
.aiw-add:hover { background:var(--teal-50); }

/* Kanban (Tareas y Proyectos) en móvil: el arrastre táctil (startItemDrag, pointer
   events con pulsación mantenida) SÍ funciona aquí — a diferencia de otras vistas
   donde el drag se desactiva en móvil. Sin esto, un toque prolongado antes de que
   empiece a moverse el dedo dispara la selección de texto nativa (o el menú de
   copiar/pegar de iOS) en vez de iniciar el arrastre. Solo estas dos pantallas —
   no afecta a Lista/Calendario/Inbox, que no tienen este problema. */
@media (max-width:899px) {
  #tareasKanban, #proyectosKanban {
    -webkit-user-select:none; user-select:none; -webkit-touch-callout:none;
  }
}

/* Ficha de Wiki en móvil: "Editar"/"Abrir en Notion" pasan a ser solo icono
   (el texto queda como title/tooltip) — ahorra espacio en la cabecera, que en
   móvil ya comparte fila con la miga de pan de ancestros. */
@media (max-width:899px) {
  #wikiEdit, #wikiOpen { padding:9px; gap:0; }
  #wikiEdit .bf-btn-label, #wikiOpen .bf-btn-label { display:none; }
}
