/* =============================================================
   app.css — Área de miembros · Marca Personal
   Reutiliza tokens de styles.css. Layout: sidebar + main.
   1. Layout shell   2. Sidebar   3. Topbar   4. Views base
   5. Comunidad  6. Calendario  7. Módulos  8. Programación
   9. Perfil  10. Métricas  11. Responsive
   ============================================================= */

/* Tipografía del área de miembros: la serif (Fraunces) se reemplaza por Raleway.
   Solo aquí (app.html carga app.css); el Home no se ve afectado. */
.app-body { --serif: "Raleway", "Helvetica Neue", Arial, sans-serif; --card-pad: 1.3rem; }

/* ---------- App shell ---------- */
/* Mismo guard que ya existe en styles.css (Home): red de seguridad contra cualquier desborde
   horizontal de 1-2px (ej. un elemento fixed mal calculado en móvil) que generaría scroll lateral. */
html:has(body.app-body) { overflow-x: clip; }
body.app-body { background: var(--bg); overflow-x: clip; }
.app { min-height: 100vh; }

.app-icon { width: 20px; height: 20px; flex: 0 0 auto; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.app-icon--sm { width: 16px; height: 16px; }
[hidden] { display: none !important; }

/* =============================================================
   2. SIDEBAR
   ============================================================= */
.sidebar {
  position: fixed; top: 0; left: 0; bottom: 0; width: 264px; z-index: 60;
  background: var(--paper); border-right: 1px solid var(--line-2);
  display: flex; flex-direction: column; padding: 1.4rem 1rem 1rem;
  transition: transform .45s var(--ease-out);
}
.sidebar-brand { display: flex; align-items: center; gap: .7rem; padding: .4rem .6rem 1.3rem; }
.sidebar-brand img { height: 38px; width: auto; }
.sidebar-brand img.brand-mini { display: none; height: 28px; }
.sidebar-brand .badge { margin-left: auto; font-size: .62rem; color: var(--accent-deep); background: var(--accent-soft); padding: .2rem .5rem; border-radius: 100px; font-weight: 600; }

.sidebar-section-label { font-size: .66rem; color: var(--ink-mute); font-weight: 600; padding: .5rem .8rem; margin-top: .4rem; }
.sidebar-nav { display: flex; flex-direction: column; gap: 2px; }
.side-link {
  display: flex; align-items: center; gap: .8rem; padding: .7rem .8rem; border-radius: 12px;
  color: var(--ink-soft); font-size: .92rem; font-weight: 450; position: relative;
  transition: background .25s var(--ease-out), color .25s var(--ease-out);
}
.side-link:hover { background: var(--bg); color: var(--ink); }
.side-link.is-active { background: var(--grad-box); color: var(--bg); }
.side-link.is-active .app-icon { stroke: var(--bg); }
.side-link .count { margin-left: auto; font-size: .72rem; background: var(--accent-soft); color: var(--accent-deep); padding: .1rem .5rem; border-radius: 100px; font-weight: 600; }
.side-link.is-active .count { background: rgba(244,241,234,.18); color: var(--bg); }
.side-link .lock { margin-left: auto; }
.side-link .lock .app-icon { width: 15px; height: 15px; opacity: .6; }

.sidebar-spacer { flex: 1 1 auto; }
.sidebar-foot { border-top: 1px solid var(--line-2); padding-top: .8rem; margin-top: .8rem; }
.side-profile { display: flex; align-items: center; gap: .7rem; padding: .55rem .6rem; border-radius: 12px; transition: background .25s; cursor: pointer; }
.side-profile:hover { background: var(--bg); }
.side-profile.is-active { background: var(--bg); }
.side-avatar { width: 38px; height: 38px; border-radius: 50%; background: var(--accent-soft) center/cover; display: grid; place-items: center; color: var(--accent-deep); font-family: var(--serif); font-style: italic; font-weight: 600; flex: 0 0 auto; }
.side-profile .meta { min-width: 0; }
.side-profile .meta b { font-size: .86rem; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.side-profile .meta span { font-size: .72rem; color: var(--ink-mute); }
.side-home { display: inline-flex; align-items: center; gap: .5rem; font-size: .8rem; color: var(--ink-mute); padding: .6rem .8rem; }
.side-home:hover { color: var(--accent-deep); }

/* =============================================================
   3. TOPBAR + MAIN
   ============================================================= */
.app-main { margin-left: 264px; min-height: 100vh; display: flex; flex-direction: column; }
.topbar {
  /* z-index 70 (> sidebar 60): el topbar es position:sticky y crea un stacking context,
     así sus desplegables (search/notif/user, z80) quedan POR ENCIMA de la sidebar.
     En móvil, el drawer abierto (overlay 75 + sidebar 80) vuelve a cubrir el topbar. */
  position: sticky; top: 0; z-index: 70;
  display: flex; align-items: center; gap: 1rem;
  padding: 1rem clamp(1.2rem, 3vw, 2.4rem);
  background: var(--grad-portada);
  border-bottom: 1px solid rgba(28,26,24,.25);
}
.topbar-burger { display: grid; width: 40px; height: 40px; border-radius: 10px; border: 1px solid rgba(244,241,234,.24); background: rgba(244,241,234,.12); color: var(--bg); place-items: center; transition: border-color .25s, background .25s; }
.topbar-burger:hover { border-color: rgba(244,241,234,.5); background: rgba(244,241,234,.2); }
.topbar-title { min-width: 0; }
.topbar-title h1 { font-family: var(--serif); font-weight: 300; font-size: clamp(1.4rem, 3vw, 1.9rem); letter-spacing: -.02em; line-height: 1; color: var(--bg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar-title p { font-size: .82rem; color: rgba(244,241,234,.72); margin-top: .2rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: .6rem; }
.topbar-search-wrap { position: relative; display: none; flex: 0 1 460px; min-width: 0; }
.topbar-search { display: flex; width: 100%; align-items: center; gap: .55rem; background: rgba(244,241,234,.16); border: 1px solid rgba(244,241,234,.26); border-radius: 100px; padding: .62rem 1.15rem; color: rgba(244,241,234,.85); transition: background .2s, border-color .2s; }
.topbar-search:focus-within { background: rgba(244,241,234,.24); border-color: rgba(244,241,234,.5); }
.topbar-search .app-icon { opacity: .9; flex: 0 0 auto; }
.topbar-search input { border: 0; background: none; outline: none; font-size: .95rem; width: 100%; color: var(--bg); }
.topbar-search input::placeholder { color: rgba(244,241,234,.6); }
.topbar-search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.topbar-search-clear { flex: 0 0 auto; color: rgba(244,241,234,.85); font-size: .9rem; line-height: 1; padding: .1rem .15rem; opacity: .85; transition: opacity .2s; }
.topbar-search-clear:hover { opacity: 1; }
/* Panel de resultados del buscador */
.search-panel { position: absolute; top: calc(100% + 8px); right: 0; left: 0; background: var(--paper); border: 1px solid var(--line); border-radius: 16px; box-shadow: 0 26px 60px -22px rgba(28,26,24,.45); padding: .5rem; z-index: 80; max-height: 64vh; overflow-y: auto; }
.search-panel-label { font-size: .66rem; color: var(--ink-mute); font-weight: 600; padding: .4rem .6rem .2rem; }
.search-panel-hint { font-size: .78rem; color: var(--ink-mute); padding: .55rem .7rem; line-height: 1.4; }
.search-item { display: flex; align-items: center; gap: .7rem; width: 100%; padding: .55rem .6rem; border-radius: 10px; text-align: left; transition: background .2s; }
.search-item:hover { background: var(--bg); }
.search-item b { font-size: .92rem; }
.search-item small { display: block; color: var(--ink-mute); font-size: .76rem; }
.search-av { width: 36px; height: 36px; border-radius: 50%; flex: 0 0 auto; }
.search-hl { background: #FBF1C2; color: inherit; border-radius: 3px; padding: 0 .12em; }
.icon-btn { width: 40px; height: 40px; flex: 0 0 40px; border-radius: 50%; border: 1px solid rgba(244,241,234,.24); background: rgba(244,241,234,.12); display: grid; place-items: center; color: var(--bg); position: relative; transition: border-color .25s, background .25s; }
.icon-btn:hover { border-color: rgba(244,241,234,.5); background: rgba(244,241,234,.2); }
/* Badge de notificaciones estilo iPhone (círculo coral con número y aro claro) */
.icon-btn .dot { position: absolute; top: -5px; right: -5px; min-width: 19px; height: 19px; padding: 0 5px; border-radius: 100px;
  background: var(--accent); color: #fff; border: 2px solid var(--paper);
  font-size: .68rem; font-weight: 700; line-height: 1; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 5px rgba(28,26,24,.35); }
.icon-btn .dot[hidden] { display: none; }
.topbar-avatar { width: 40px; height: 40px; flex: 0 0 40px; aspect-ratio: 1; border-radius: 50%; background: var(--accent-soft) center/cover; display: grid; place-items: center; color: var(--accent-deep); font-family: var(--serif); font-style: italic; font-weight: 600; box-shadow: 0 0 0 1px rgba(244,241,234,.35); overflow: hidden; }

.app-content { padding: clamp(1.3rem, 3vw, 2.4rem); flex: 1 1 auto; }
.view { display: none; animation: viewIn .5s var(--ease-out); }
.view.is-active { display: block; }
@keyframes viewIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.app-card { background: var(--paper); border: 1px solid var(--line-2); border-radius: var(--radius); }
.section-mini-label { font-size: .7rem; color: var(--ink-mute); font-weight: 600; margin-bottom: 1rem; }

/* =============================================================
   5. COMUNIDAD (Skool feed)
   ============================================================= */
.feed-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.4rem; align-items: start; min-width: 0; }
.composer { padding: 1.1rem var(--card-pad); margin-bottom: 1.1rem; display: flex; gap: .9rem; align-items: center; }
.composer .side-avatar { width: 42px; height: 42px; }
.composer button { flex: 1; text-align: left; background: var(--bg); border: 1px solid var(--line-2); border-radius: 100px; padding: .8rem 1.2rem; color: var(--ink-mute); font-size: .92rem; transition: border-color .25s; }
.composer button:hover { border-color: var(--line); }
/* El botón coral "+" se eliminó el 28-jul-2026 (pulsar el cuadro de texto ya abría el mismo editor);
   sus reglas se van con él para no dejar CSS muerto. */

.feed-filters { display: flex; gap: .5rem; flex-wrap: wrap; margin: 0 0 1.1rem; }
.comm-admin { padding: .4rem var(--card-pad) .6rem; margin-bottom: 1.1rem; }
.prog-intro { padding: 1.2rem var(--card-pad); margin-bottom: 1.2rem; }
.filter-pill { padding: .45rem 1rem; border-radius: 100px; border: 1px solid var(--line); font-size: .82rem; color: var(--ink-soft); background: var(--paper); transition: background-color .25s var(--ease-out), border-color .25s var(--ease-out), color .25s var(--ease-out); }
.filter-pill:hover { border-color: var(--ink-mute); }
.filter-pill.is-active { background: var(--ink); color: var(--bg); border-color: var(--ink); }

/* Cambiador de comunidad (feed) */
.comm-switch { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1.1rem; }
/* Selector "Ver publicaciones de" dentro del box de comunidades (admin). */
.comm-view-switch { padding-bottom: .8rem; margin-bottom: .6rem; border-bottom: 1px solid var(--line-2); }
.comm-view-lbl { display: inline-flex; align-items: center; gap: .4rem; font-size: .74rem; font-weight: 700; letter-spacing: .03em; color: var(--ink-mute); margin-bottom: .55rem; }
.comm-view-lbl .app-icon { width: 15px; height: 15px; }
.comm-switch--inbox { margin-bottom: 0; }
.comm-switch-pill { padding: .5rem 1.05rem; border-radius: 100px; border: 1px solid var(--line); font-size: .85rem; font-weight: 500; color: var(--ink-soft); background: var(--paper); transition: background-color .25s var(--ease-out), border-color .25s var(--ease-out), color .25s var(--ease-out); }
.comm-switch-pill:hover { border-color: var(--ink-mute); }
/* Seleccionada en NEGRO, igual que los filtros de tipo de publicación (.filter-pill.is-active):
   el coral queda reservado para las acciones (crear comunidad, publicar), no para marcar el estado
   de un selector — así no compiten dos elementos corales en la misma tarjeta (27-jul-2026). */
.comm-switch-pill.is-active { background: var(--ink); color: var(--bg); border-color: var(--ink); }

/* Selector "Publicar en" del compositor */
.composer-comms { display: flex; flex-direction: column; gap: .55rem; }
.comm-check { display: flex; align-items: center; gap: .6rem; font-size: .92rem; color: var(--ink); cursor: pointer; }
/* Selección múltiple con apariencia de círculo que se rellena (sigue siendo checkbox) */
.comm-check input { appearance: none; -webkit-appearance: none; margin: 0; flex: 0 0 auto;
  width: 19px; height: 19px; border: 2px solid var(--line-2); border-radius: 50%; background: var(--paper);
  display: inline-grid; place-content: center; cursor: pointer; transition: border-color .2s, background .2s; }
.comm-check input::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: #fff;
  transform: scale(0); transition: transform .15s var(--ease-out); }
.comm-check input:hover { border-color: var(--accent); }
.comm-check input:checked { background: var(--accent); border-color: var(--accent); }
.comm-check input:checked::before { transform: scale(1); }
.composer-comms-one { display: flex; align-items: center; gap: .5rem; font-size: .92rem; color: var(--ink-soft); background: var(--bg); border: 1px solid var(--line-2); border-radius: 10px; padding: .6rem .8rem; }
.composer-comms-one .app-icon { width: 16px; height: 16px; color: var(--accent); }

.feed-post { padding: 1.2rem 1.3rem; }
.feed-post + .feed-post { margin-top: 1.1rem; }
/* Medios dentro de una publicación */
.fp-video { position: relative; aspect-ratio: 16 / 9; margin-top: .9rem; border-radius: 12px; overflow: hidden; background: var(--ink); }
.fp-video iframe, .fp-video video { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; object-fit: contain; background: #000; }
.fp-images { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: .5rem; margin-top: .9rem; }
.fp-images img { width: 100%; border-radius: 12px; display: block; }
/* Documentos adjuntos de una publicación (PDF/Word/Excel/…): tarjeta con nombre + descarga. */
.fp-files { display: flex; flex-direction: column; gap: .5rem; margin-top: .9rem; }
.fp-file { display: flex; align-items: center; gap: .6rem; padding: .6rem .8rem; border: 1px solid var(--line); border-radius: 12px; color: var(--ink-soft); text-decoration: none; transition: background .15s, border-color .15s; }
.fp-file:hover { background: var(--accent-soft); border-color: var(--accent); }
.fp-file .app-icon:first-child { color: var(--accent-deep); }
.fp-file .app-icon:last-child { color: var(--ink-mute); }
.fp-file-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .9rem; font-weight: 500; }
.composer-docs { display: flex; flex-wrap: wrap; gap: .5rem; }
/* Adjuntos en el compositor */
.composer-attach { display: flex; flex-wrap: wrap; gap: .5rem; }
.composer-thumbs { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .6rem; }
.composer-thumb { position: relative; width: 76px; height: 76px; flex: 0 0 auto; border-radius: 10px; background: var(--bg) center/cover no-repeat; border: 1px solid var(--line-2); }
.composer-chip { position: relative; display: inline-flex; align-items: center; gap: .4rem; margin-top: .6rem; padding: .45rem .7rem; background: var(--bg); border: 1px solid var(--line-2); border-radius: 8px; font-size: .82rem; }
.composer-chip .app-icon { width: 15px; height: 15px; }
.composer-thumb button, .composer-chip button { position: absolute; top: -7px; right: -7px; width: 20px; height: 20px; border-radius: 50%; border: 0; background: var(--ink); color: #fff; font-size: .68rem; line-height: 1; cursor: pointer; display: grid; place-items: center; }
.composer-chip button { position: static; margin-left: .2rem; width: 18px; height: 18px; }
/* Selector de co-ejecutores del compositor (1.1.4): chips de personas que se activan al tocarlas. */
.composer-people { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .2rem; }
.cperson { display: inline-flex; align-items: center; gap: .4rem; border: 1px solid var(--line); background: #fff; color: var(--ink-soft); border-radius: 100px; padding: .26rem .65rem .26rem .3rem; font: inherit; font-size: .82rem; cursor: pointer; }
.cperson .cperson-av { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; background: var(--grad-box); color: #fff; font-weight: 700; font-size: .64rem; }
.cperson.is-on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-deep); font-weight: 600; }
/* Buscador de co-ejecutores: chips elegidos + input + desplegable de coincidencias. */
.collab-chosen { display: flex; flex-wrap: wrap; gap: .4rem; }
.collab-chosen:not(:empty) { margin-bottom: .5rem; }
.collab-x { border: 0; background: transparent; color: inherit; cursor: pointer; font-size: .72rem; line-height: 1; margin-left: .3rem; padding: 0; }
.collab-search-wrap { position: relative; }
.collab-search { width: 100%; border: 1px solid var(--line); border-radius: 10px; padding: .55rem .75rem; font: inherit; font-size: .9rem; background: #fff; }
.collab-drop { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 30; background: #fff; border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 10px 28px rgba(28, 26, 24, .16); max-height: 240px; overflow-y: auto; padding: .25rem; }
.collab-opt { display: flex; align-items: center; gap: .5rem; width: 100%; text-align: left; border: 0; background: transparent; border-radius: 8px; padding: .4rem .5rem; font: inherit; font-size: .86rem; color: var(--ink-soft); cursor: pointer; }
.collab-opt .cperson-av { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: var(--grad-box); color: #fff; font-weight: 700; font-size: .66rem; }
.collab-opt:hover { background: var(--accent-soft); color: var(--accent-deep); }
.collab-empty { padding: .5rem .6rem; font-size: .82rem; color: var(--ink-mute); }
/* Hilo de comentarios del coach en la tarea (fase2/52 · 1.1.9) — diseño aprobado en preview. */
.tc { margin-top: 1.1rem; padding-top: 1rem; border-top: 1px dashed var(--line); }
.tc-title { display: flex; align-items: center; gap: .45rem; font-size: .82rem; font-weight: 700; color: var(--ink); margin: 0 0 .1rem; }
.tc-title .app-icon { width: 15px; height: 15px; color: var(--accent-deep); }
.tc-sub { font-size: .76rem; color: var(--ink-mute); margin: 0 0 .8rem; }
.tc-list { display: flex; flex-direction: column; gap: .7rem; margin-bottom: .9rem; }
.tc-item { display: flex; gap: .6rem; }
.tc-av { width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto; display: grid; place-items: center; color: #fff; font-weight: 700; font-size: .85rem; }
.tc-av.coach { background: linear-gradient(135deg, #5C322B, #EE8B76); }
.tc-av.ceo { background: linear-gradient(135deg, #1C1A18, #A84A3E); }
.tc-bubble { background: #F4F0E8; border-radius: 12px; padding: .55rem .8rem; min-width: 0; flex: 1; }
.tc-name { font-size: .8rem; font-weight: 700; display: flex; align-items: center; gap: .3rem; }
.tc-name .role { font-weight: 600; color: var(--accent-deep); font-size: .68rem; letter-spacing: .03em; }
.tc-del { border: 0; background: transparent; color: var(--ink-mute); cursor: pointer; font-size: .72rem; margin-left: auto; padding: 0 .1rem; }
.tc-text { font-size: .88rem; color: var(--ink-soft); margin: .1rem 0 0; white-space: pre-wrap; }
.tc-time { font-size: .68rem; color: var(--ink-mute); margin-top: .2rem; }
.tc-form { display: flex; gap: .5rem; align-items: flex-end; }
.tc-form textarea { flex: 1; min-width: 0; border: 1px solid var(--line); border-radius: 12px; padding: .55rem .8rem; font: inherit; font-size: .9rem; resize: vertical; min-height: 42px; background: #fff; }
.tc-send { flex: 0 0 auto; border: 0; background: var(--accent); color: #fff; border-radius: 12px; padding: .55rem .9rem; font-weight: 600; font-size: .85rem; cursor: pointer; }
.tc-readonly { font-size: .8rem; color: var(--ink-mute); background: #F6F2EA; border-radius: 10px; padding: .6rem .8rem; }
.tc-empty { font-size: .84rem; color: var(--ink-mute); font-style: italic; }
/* Banner de límite de sesiones agotadas (2.4). */
.sess-limit { display: flex; gap: .55rem; align-items: flex-start; background: #FBF6EE; border: 1px solid var(--line); border-left: 4px solid var(--accent); border-radius: 12px; padding: .7rem .85rem; margin-bottom: .5rem; }
.sess-limit-ico { color: var(--accent-deep); display: inline-flex; margin-top: 1px; }
.sess-limit-ico .app-icon { width: 18px; height: 18px; }
.sess-limit-t { font-size: .88rem; font-weight: 700; color: var(--ink); }
.sess-limit-s { font-size: .82rem; color: var(--ink-soft); margin: .15rem 0 0; }
.sess-limit-cta { margin-top: .55rem; }
.fp-head { display: flex; align-items: flex-start; gap: .8rem; }
.fp-head .side-avatar { width: 44px; height: 44px; }
.fp-del { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; border: 0; background: transparent; color: var(--ink-mute); display: grid; place-items: center; cursor: pointer; transition: background .2s, color .2s; }
.fp-del:hover { background: rgba(200,60,40,.1); color: #c33; }
/* Editar publicación (solo el autor del equipo). Mismo botón redondo que eliminar, al lado. */
.fp-edit { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; border: 0; background: transparent; color: var(--ink-mute); display: grid; place-items: center; cursor: pointer; transition: background .2s, color .2s; }
.fp-edit:hover { background: var(--accent-soft); color: var(--accent-deep); }
/* Fijar/desfijar (solo equipo). Mismo tamaño que el botón de eliminar, al lado. Apagado = atenuado;
   fijada = a plena opacidad, para que se vea de un vistazo cuál está fijada. */
.fp-pin { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; border: 0; background: transparent;
  display: grid; place-items: center; cursor: pointer; line-height: 1; opacity: .38; transition: opacity .2s, background .2s; }
.fp-pin:hover { opacity: 1; background: var(--accent-soft); }
.fp-pin.is-on { opacity: 1; }
/* Bloque de publicaciones fijadas: va ARRIBA del composer. Mismo espaciado que el feed normal. */
.pinned-feed { display: grid; gap: 1.1rem; margin-bottom: 1.1rem; }
.fp-meta b { font-size: .94rem; }
/* "📌 Fijado" va en su PROPIA fila bajo el nombre y en UNA sola línea (nowrap). El emoji interno debe
   quedar inline: si no, la regla `.fp-meta span { display:block }` lo pondría en su propio renglón y
   partiría "📌" y "Fijado" en dos líneas (el bug que se veía). */
.fp-meta .pin { display: block; white-space: nowrap; color: var(--accent-deep); font-size: .7rem; font-weight: 600; }
/* Icono de "Fijar" = emoji 📌 (decisión del cliente 22-jul-2026). En el botón a 15px; en la etiqueta más chico. */
.fp-meta .pin .pin-emoji { display: inline; font-size: 12px; }
.fp-pin-emoji { font-size: 15px; line-height: 1; }
/* "En colaboración con Ana y Luis": fila propia bajo el nombre, acento coral (1.1.4). */
.fp-meta .fp-collab { display: block; white-space: normal; color: var(--accent-deep); font-size: .74rem; font-weight: 600; margin-top: .1rem; }
.fp-meta .fp-collab .app-icon { display: inline-block; width: 13px; height: 13px; vertical-align: -2px; margin-right: 2px; }
.fp-meta span { font-size: .78rem; color: var(--ink-mute); display: block; }
.fp-cat { margin-left: auto; font-size: .68rem; color: var(--accent-deep); background: var(--accent-soft); padding: .28rem .7rem; border-radius: 100px; font-weight: 600; }
.fp-cat[data-cat="Logro"] { color: #1f7a4d; background: #e2f4ea; }
.fp-cat[data-cat="Evento"] { color: #8a5a00; background: #f7ecd6; }
.fp-title { font-family: var(--serif); font-weight: 400; font-size: 1.2rem; margin: .9rem 0 .4rem; overflow-wrap: anywhere; word-break: break-word; }
.fp-body { color: var(--ink-soft); font-size: .96rem; overflow-wrap: anywhere; word-break: break-word; }
/* Enlaces detectados dentro del texto que ESCRIBE el usuario (publicaciones, comentarios, chat, tareas):
   se diferencian del texto con color coral + subrayado. En la burbuja propia (fondo coral) van en blanco. */
.rich-link { color: var(--accent-deep); text-decoration: underline; text-underline-offset: 2px; overflow-wrap: anywhere; word-break: break-word; }
.rich-link:hover { color: var(--accent); }
.bubble.mine .rich-link { color: #fff; }
/* Al abrir una publicación desde su notificación: un aro coral que aparece y se desvanece para ubicarla. */
.feed-post--flash { animation: feedFlash 1.8s ease; }
@keyframes feedFlash { 0%, 18% { box-shadow: 0 0 0 3px var(--accent); } 100% { box-shadow: 0 0 0 3px rgba(242,107,94,0); } }
.fp-foot { display: flex; gap: 1.6rem; margin-top: 1.1rem; padding-top: .9rem; border-top: 1px solid var(--line-2); color: var(--ink-mute); font-size: .84rem; }
.fp-act { display: inline-flex; align-items: center; gap: .4rem; transition: color .2s; }
.fp-act:hover { color: var(--ink); }
.fp-act.is-liked { color: var(--accent-deep); }
.fp-act.is-liked .app-icon { fill: var(--accent); stroke: var(--accent); }

.rail { display: grid; gap: 1.4rem; }
.rail-card { padding: 1.2rem 1.3rem; }
.rail-card h3 { font-size: 1rem; font-weight: 600; margin-bottom: .9rem; display: flex; align-items: center; gap: .5rem; }
/* Tarjeta "La comunidad": nº real de miembros + descripción editable (lápiz, solo admin) */
.comm-side-stat { font-size: .86rem; margin-bottom: .7rem; }
.comm-side-stat b { font-family: var(--serif); font-style: italic; color: var(--accent-deep); font-size: 1.05rem; margin-right: .3rem; }
.comm-side-desc-row { display: flex; align-items: flex-start; gap: .5rem; }
.comm-side-desc { flex: 1 1 auto; font-size: .86rem; color: var(--ink-mute); margin: 0; }
.comm-side-edit { flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft); display: grid; place-items: center; cursor: pointer; transition: border-color .2s, color .2s; }
.comm-side-edit:hover { border-color: var(--accent); color: var(--accent); }
.comm-side-edit .app-icon { width: 14px; height: 14px; }
.leaderboard li { display: flex; align-items: center; gap: .7rem; padding: .5rem 0; }
.leaderboard li + li { border-top: 1px solid var(--line-2); }
.lb-rank { width: 22px; font-family: var(--serif); font-style: italic; color: var(--ink-mute); }
.lb-rank.top { color: var(--accent-deep); }
.leaderboard .side-avatar { width: 32px; height: 32px; font-size: .8rem; }
.leaderboard b { font-size: .86rem; }
.leaderboard .lb-id { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.leaderboard .lb-id b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.leaderboard .lb-id small { font-size: .7rem; color: var(--ink-mute); }
.leaderboard .pts { margin-left: auto; flex: 0 0 auto; font-size: .8rem; font-weight: 600; color: var(--accent-deep); }
.leaderboard .lb-empty { padding: .3rem 0; }
.rail-event { display: flex; align-items: center; gap: .8rem; padding: .6rem .4rem; width: 100%; text-align: left; background: none; border: 0; border-radius: 10px; cursor: pointer; transition: background .2s; }
.rail-event:hover { background: var(--bg); }
.rail-event:hover .info b { color: var(--accent-deep); }
.rail-event + .rail-event { border-top: 1px solid var(--line-2); }
.rail-date { flex: 0 0 auto; width: 46px; text-align: center; background: var(--bg); border: 1px solid var(--line-2); border-radius: 10px; padding: .3rem 0; }
.rail-date .d { font-size: 1.1rem; font-weight: 600; line-height: 1; }
.rail-date .m { font-size: .64rem; color: var(--accent-deep); }
.rail-event .info b { font-size: .86rem; display: block; }
.rail-event .info span { font-size: .76rem; color: var(--ink-mute); }

/* =============================================================
   6. CALENDARIO
   ============================================================= */
.cal-layout { display: grid; grid-template-columns: 1fr; gap: 1.4rem; align-items: start; min-width: 0; }
/* min-width:0 evita que la tarjeta de "Próximas sesiones" fuerce la columna del grid más ancha que el
   espacio disponible (por defecto un hijo de grid no encoge por debajo de su contenido) y se salga de
   la pantalla — pasaba solo con la barra lateral expandida, porque quedaba menos ancho disponible. */
.cal-wrap { padding: 1.2rem 1.3rem; min-width: 0; }
.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.1rem; }
.cal-head .m { font-family: var(--serif); font-weight: 300; font-size: 1.6rem !important; }
.cal-nav { display: flex; gap: .4rem; }
.cal-nav button { width: 34px; height: 34px; border-radius: 9px; border: 1px solid var(--line); background: var(--paper); display: grid; place-items: center; color: var(--ink-soft); }
.cal-nav button:hover { border-color: var(--ink); color: var(--ink); }
/* ⚠️ `repeat(7, 1fr)` a secas descuadraba el calendario en cuanto un día tenía evento: `1fr` lleva
   implícito min-width:auto, así que la píldora `.cal-evt` (white-space:nowrap, ej. "Sesión en vivo")
   ensanchaba SU columna y empujaba el domingo fuera de la tarjeta, desalineando todos los números.
   Salió a la luz recién el 27-jul-2026 porque hasta entonces ningún evento llegaba a guardarse
   (faltaba correr fase2/43) y la grilla nunca se había pintado con contenido real.
   `minmax(0,1fr)` en la pista + `min-width:0` en la celda dejan que el contenido se RECORTE
   (ya tiene overflow:hidden + ellipsis) en vez de estirar la columna. */
.cal-grid { display: grid; grid-template-columns: repeat(7,minmax(0,1fr)); gap: 4px; }
.cal-dow { text-align: center; font-size: .68rem; color: var(--ink-mute); padding: .4rem 0; font-weight: 600; min-width: 0; }
/* ⚠️ `overflow: hidden` en la celda es lo que impedía que cupieran 3 eventos: la celda es un ítem de
   grilla, y en un ítem de grilla `min-height: auto` (el tamaño mínimo automático = el del contenido)
   queda ANULADO en cuanto se recorta el desbordamiento. Sin ese recorte, `aspect-ratio: 1` pasa a ser
   el alto PREFERIDO —la celda sigue cuadrada mientras el contenido quepa— y la fila crece sola cuando
   un día trae 3 píldoras. El recorte horizontal que motivó el comentario de arriba no se pierde: la
   píldora ya tiene su propio overflow+ellipsis y la celda conserva `min-width: 0`. (28-jul-2026) */
.cal-day { aspect-ratio: 1; border-radius: 10px; border: 1px solid transparent; padding: .4rem; font-size: .82rem; color: var(--ink-soft); position: relative; transition: background .2s, border-color .2s; min-width: 0; cursor: pointer; }
.cal-day:hover { background: var(--bg); }
.cal-day.muted { color: var(--line); cursor: default; }
.cal-day.muted:hover { background: transparent; }
.cal-day.today { border-color: var(--accent); color: var(--ink); font-weight: 600; }
.cal-day.has-event { background: var(--bg); }
/* Hasta 3 píldoras apiladas; de la cuarta en adelante, 3 + "+N" (regla 28-jul-2026). */
.cal-evts { display: flex; flex-direction: column; gap: 2px; margin-top: .22rem; min-width: 0; }
.cal-evt { display: block; font-size: .62rem; line-height: 1.35; background: var(--accent-soft); color: var(--accent-deep); border-radius: 5px; padding: .08rem .3rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; cursor: pointer; }

.events-list h3 { font-size: 1rem; font-weight: 600; margin-bottom: 1rem; }
.evt-item { display: flex; gap: 1rem; padding: 1rem; border-radius: 12px; transition: background .2s; }
.evt-item:hover { background: var(--bg); }
.evt-item + .evt-item { border-top: 1px solid var(--line-2); }
.evt-when { flex: 0 0 auto; width: 54px; text-align: center; }
.evt-when .d { font-family: var(--serif); font-size: 1.5rem; line-height: 1; }
.evt-when .m { font-size: .64rem; color: var(--accent-deep); }
.evt-info { flex: 1; min-width: 0; }
.evt-info .tag { font-size: .66rem; color: var(--accent-deep); font-weight: 600; }
.evt-info b { display: block; font-size: 1rem; margin: .15rem 0; }
.evt-info .det { font-size: .82rem; color: var(--ink-mute); display: flex; gap: 1rem; flex-wrap: wrap; }
.evt-join { flex: 0 0 auto; align-self: center; }

/* =============================================================
   7. MÓDULOS (progreso)
   ============================================================= */
.plan-tabs { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1.6rem; }
.plan-tab { padding: .6rem 1.2rem; border-radius: 100px; border: 1px solid var(--line); background: var(--paper); font-size: .88rem; font-weight: 500; color: var(--ink-soft); transition: background-color .25s, border-color .25s, color .25s; }
.plan-tab:hover { border-color: var(--ink-mute); }
.plan-tab.is-active { background: var(--ink); color: var(--bg); border-color: var(--ink); }
/* Box "+" (miembro sin plan): teaser de los módulos de plan que llegan tras el onboarding */
.plan-tab--plus { font-size: 1.15rem; line-height: 1; font-weight: 600; padding: .5rem 1.5rem; border-style: dashed; color: var(--ink-mute); }
.plan-tab--plus:hover { border-color: var(--accent); color: var(--accent-deep); }

.plan-overview { padding: 1.4rem var(--card-pad); margin-bottom: 1.4rem; display: grid; grid-template-columns: 1fr; gap: 1.2rem; align-items: center; }
.plan-overview h2 { font-family: var(--serif); font-weight: 300; font-size: 1.7rem; }
.plan-overview p { color: var(--ink-mute); font-size: .9rem; margin-top: .3rem; }
.progress-ring { display: flex; align-items: center; gap: 1rem; }
.ring { --p: 0; width: 72px; height: 72px; border-radius: 50%; flex: 0 0 auto;
  background: conic-gradient(var(--accent) calc(var(--p)*1%), var(--bg-3) 0);
  display: grid; place-items: center; position: relative; }
.ring::before { content: ""; position: absolute; inset: 8px; border-radius: 50%; background: var(--paper); }
.ring .pct { position: relative; font-weight: 600; font-size: .95rem; }
.progress-ring .lbl b { font-size: .9rem; } .progress-ring .lbl span { font-size: .78rem; color: var(--ink-mute); display: block; }

.module { margin-bottom: 1rem; overflow: hidden; }
.module-num { width: 38px; height: 38px; border-radius: 11px; background: var(--bg); border: 1px solid var(--line-2); display: grid; place-items: center; font-family: var(--serif); font-style: italic; color: var(--accent-deep); flex: 0 0 auto; }
.module.is-done .module-num { background: var(--accent); color: #fff; border-color: var(--accent); }
.module-bar { width: 90px; height: 6px; border-radius: 100px; background: var(--bg-3); overflow: hidden; flex: 0 0 auto; }
.module-bar i { display: block; height: 100%; background: var(--accent); border-radius: inherit; transition: width .5s var(--ease-out); }
.module-lessons { display: none; padding: 0 1.3rem 1rem 1.3rem; }
.module.is-open .module-lessons { display: block; }

/* ===== Carrusel de portadas de módulos (Skool) ===== */
.mod-carousel { position: relative; margin-bottom: 1.4rem; }
.mod-track { display: flex; align-items: center; gap: 1rem; overflow-x: auto; scroll-snap-type: x proximity; padding: 1rem .6rem 1.2rem; -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
.mod-track::-webkit-scrollbar { height: 8px; }
.mod-track::-webkit-scrollbar-thumb { background: var(--line); border-radius: 100px; }
.mod-track::-webkit-scrollbar-track { background: transparent; }
.mod-cover-card { flex: 0 0 280px; scroll-snap-align: center; background: var(--paper); border: 1px solid var(--line-2); border-radius: 16px; overflow: hidden; cursor: pointer; padding: 0; text-align: left; display: flex; flex-direction: column; transition: transform .22s var(--ease-out), box-shadow .22s; }
.mod-cover-card:hover { transform: translateY(-3px); box-shadow: 0 18px 40px -24px rgba(28,26,24,.45); }
/* Seleccionado: sin borde coral, se agranda un poco (efecto zoom tipo Dock de Mac) */
.mod-cover-card.is-active, .mod-cover-card.is-active:hover { transform: scale(1.08); box-shadow: 0 24px 54px -22px rgba(28,26,24,.5); position: relative; z-index: 2; }
.mod-cover-img { position: relative; aspect-ratio: 1000 / 516; background: var(--ink) center/cover no-repeat; }
/* Módulo sin portada Skool: estado neutral (NO una portada inventada) — fondo liso crema + título. */
.mod-cover-img--empty { background: linear-gradient(135deg, var(--bg-2), var(--paper)); display: grid; place-items: center; padding: 1rem 1.2rem; border-bottom: 1px solid var(--line-2); }
.mod-cover-empty { font: 600 1.02rem/1.25 var(--serif); color: var(--ink-soft); text-align: center; max-width: 90%; }
.mod-cover-num { position: absolute; top: .55rem; left: .6rem; min-width: 26px; height: 26px; padding: 0 .45rem; border-radius: 8px; background: rgba(28,26,24,.55); color: var(--paper); font: 600 .76rem/1 var(--sans); display: grid; place-items: center; backdrop-filter: blur(3px); }
/* Módulo OCULTO: los miembros no lo ven; el equipo sí, con la portada bajo una capa tenue (24-jul-2026). */
.mod-cover-card.is-mod-hidden { opacity: .45; filter: grayscale(.4); }
/* Descripción del módulo: bajo el título, dentro del módulo abierto (respeta saltos y enlaces). */
.mod-desc { font-size: .9rem; color: var(--ink-soft); margin: .1rem 0 .9rem; }
.mod-cover-check { position: absolute; top: .55rem; right: .6rem; width: 26px; height: 26px; border-radius: 50%; background: var(--accent); color: #fff; display: grid; place-items: center; box-shadow: 0 2px 8px -2px rgba(28,26,24,.5); }
.mod-cover-check .app-icon { width: 15px; height: 15px; }
.mod-cover-foot { padding: .7rem .85rem .85rem; display: flex; flex-direction: column; gap: .45rem; }
.mod-cover-foot .module-bar { width: 100%; }
.mod-cover-sub { font-size: .75rem; color: var(--ink-mute); }
/* Lápiz "gestionar grupos de módulos" — junto a la última pestaña de planes (solo coach/admin). */
.plan-tab-edit { display: inline-grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft); cursor: pointer; flex: 0 0 auto; margin-left: .3rem; transition: border-color .18s, color .18s; }
.plan-tab-edit:hover { border-color: var(--accent); color: var(--accent); }
.plan-tab-edit .app-icon { width: 16px; height: 16px; }
/* Papelera de la barra: eliminar el plan/grupo activo por completo. Tono neutro; rojo al pasar encima. */
.plan-tab-del:hover { border-color: #d9534f; color: #d9534f; }
/* Reordenar módulos arrastrando. */
.mod-drag-row { cursor: grab; }
.mod-drag-row.dragging { opacity: .45; cursor: grabbing; }
.mod-drag-grip { display: inline-flex; align-items: center; color: var(--ink-mute); flex: 0 0 auto; }
.mod-drag-grip .app-icon { width: 15px; height: 15px; }
.mod-arrow { position: absolute; top: calc(50% - .5rem); transform: translateY(-50%); width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft); display: grid; place-items: center; cursor: pointer; z-index: 3; box-shadow: 0 8px 22px -12px rgba(28,26,24,.5); }
.mod-arrow:hover { border-color: var(--accent); color: var(--accent); }
.mod-arrow--prev { left: -6px; }
.mod-arrow--next { right: -6px; }
.mod-arrow .app-icon { width: 18px; height: 18px; }
/* Auto-scroll al arrastrar un módulo hacia el borde: la flecha es solo pista visual — "armada" (esperando)
   y "desplazando". En modo Mover no intercepta el arrastre (pointer-events:none), para que el dragover del
   track detecte la zona de borde de forma fiable incluso justo debajo de la flecha. */
.mods-moving .mod-arrow { pointer-events: none; }
.mod-arrow--armed { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.mod-arrow--scrolling { border-color: var(--accent); color: #fff; background: var(--accent); animation: modArrowPulse .7s ease-in-out infinite; }
@keyframes modArrowPulse { 0%,100% { box-shadow: 0 8px 22px -12px rgba(28,26,24,.5); } 50% { box-shadow: 0 0 0 5px var(--accent-soft); } }
@media (prefers-reduced-motion: reduce) { .mod-arrow--scrolling { animation: none; } }
@media (max-width: 640px) { .mod-arrow { display: none; } .mod-cover-card { flex-basis: 78vw; } }
/* Detalle del módulo seleccionado */
.mod-detail-block { background: var(--paper); border: 1px solid var(--line-2); border-radius: var(--radius); overflow: hidden; margin: 0; animation: viewIn .3s var(--ease-out); }
.mod-detail-head { display: flex; align-items: center; gap: 1rem; padding: 1.1rem 1.3rem; border-bottom: 1px solid var(--line-2); }
.mod-detail-head .t { flex: 1; min-width: 0; }
.mod-detail-head .t b { font-size: 1.05rem; display: block; }
.mod-detail-head .t span { font-size: .78rem; color: var(--ink-mute); }
.mod-detail-block .module-lessons { display: block; padding: 1rem 1.3rem 1.1rem; }
.mod-names-note { margin: 0; padding: 1rem 1.3rem 1.1rem; font-size: .85rem; color: var(--ink-mute); }
/* ---- Bloqueo de módulos por alumno (habilitación manual del coach) ---- */
.mod-cover-lock { position: absolute; top: .55rem; right: .6rem; width: 26px; height: 26px; border-radius: 50%; background: rgba(28,26,24,.62); color: var(--paper); display: grid; place-items: center; backdrop-filter: blur(3px); box-shadow: 0 2px 8px -2px rgba(28,26,24,.5); }
.mod-cover-lock .app-icon { width: 15px; height: 15px; }
.mod-cover-card.is-locked .mod-cover-img { filter: grayscale(.55) brightness(.92); }
.mod-cover-card.is-locked .mod-cover-img--empty { filter: none; opacity: .7; }
.mod-cover-card.is-locked .mod-cover-sub { color: var(--ink-soft); font-weight: 600; }
/* Aviso de módulo bloqueado en el detalle (vista del alumno) */
.module-locked { display: grid; place-items: center; text-align: center; gap: .5rem; padding: 2.4rem 1.3rem; }
.module-locked-ico { width: 52px; height: 52px; border-radius: 50%; background: var(--bg-2); color: var(--ink-soft); display: grid; place-items: center; }
.module-locked-ico .app-icon { width: 24px; height: 24px; }
.module-locked b { font: 600 1.05rem var(--serif); }
.module-locked p { margin: 0; max-width: 430px; font-size: .86rem; color: var(--ink-mute); }
/* Toggle de habilitación por módulo (Seguimiento Clientes) */
.mod-lock-toggle { flex: 0 0 auto; display: inline-flex; align-items: center; gap: .4rem; font: 600 .78rem var(--sans); padding: .45rem .8rem; border-radius: 100px; border: 1px solid var(--accent); background: var(--accent); color: #fff; cursor: pointer; transition: filter .18s, background .18s, color .18s, border-color .18s; }
.mod-lock-toggle .app-icon { width: 15px; height: 15px; }
.mod-lock-toggle:hover { filter: brightness(.96); }
.mod-lock-toggle.is-on { background: var(--accent-soft); color: var(--accent-deep); border-color: transparent; }
.mod-lock-toggle.is-on:hover { background: var(--bg-2); filter: none; }
/* "Desbloquear módulo completo": acción fuerte pero secundaria frente al toggle — va en fantasma
   para que el botón principal (habilitar/bloquear) siga siendo el que más llama la atención. */
.mod-unlock-all { flex: 0 0 auto; display: inline-flex; align-items: center; gap: .4rem; font: 600 .78rem var(--sans); padding: .45rem .8rem; border-radius: 100px; border: 1px solid var(--line); background: transparent; color: var(--ink-soft); cursor: pointer; transition: background .18s, color .18s, border-color .18s; }
.mod-unlock-all .app-icon { width: 15px; height: 15px; }
.mod-unlock-all:hover { background: var(--accent-soft); color: var(--accent-deep); border-color: transparent; }
/* Banner de módulo bloqueado para el alumno (Seguimiento Clientes) */
.mod-lock-banner { display: flex; align-items: center; gap: .5rem; background: var(--bg-2); color: var(--ink-soft); border: 1px dashed var(--line); border-radius: 10px; padding: .6rem .8rem; margin-bottom: .8rem; font-size: .82rem; }
.mod-lock-banner .app-icon { width: 16px; height: 16px; flex: 0 0 auto; }
.lesson { display: flex; align-items: center; gap: .9rem; padding: .8rem; border-radius: 10px; transition: background .2s; }
.lesson:hover { background: var(--bg); }
.lesson + .lesson { border-top: 1px solid var(--line-2); }
.lesson-check { width: 24px; height: 24px; border-radius: 50%; border: 1.7px solid var(--line); flex: 0 0 auto; display: grid; place-items: center; color: transparent; transition: background-color .25s, border-color .25s, color .25s; cursor: pointer; }
.lesson.done .lesson-check { background: var(--accent); border-color: var(--accent); color: #fff; }
.lesson-type { width: 30px; height: 30px; border-radius: 8px; background: var(--bg); display: grid; place-items: center; color: var(--ink-soft); flex: 0 0 auto; }
.lesson .t { flex: 1; min-width: 0; }
.lesson .t b { font-size: .9rem; font-weight: 500; display: block; }
.lesson.done .t b { color: var(--ink-mute); }
.lesson .t span { font-size: .74rem; color: var(--ink-mute); }

/* =============================================================
   8. PROGRAMACIÓN (Gantt)
   ============================================================= */
.gantt-legend { display: flex; gap: 1.2rem; flex-wrap: wrap; margin-bottom: 1.2rem; font-size: .8rem; color: var(--ink-mute); }
.gantt-legend span { display: inline-flex; align-items: center; gap: .4rem; }
.gantt-legend i { width: 12px; height: 12px; border-radius: 3px; }
.gantt-wrap { padding: var(--card-pad); overflow-x: auto; }
.gantt { min-width: calc(220px + var(--cols, 12) * 46px); }
.gantt-row { display: grid; grid-template-columns: 220px 1fr; gap: 0; align-items: center; }
.gantt-row.head { border-bottom: 1px solid var(--line); padding-bottom: .6rem; margin-bottom: .6rem; }
.gantt-row.months { margin-bottom: .2rem; }
.gantt-months { display: grid; grid-template-columns: repeat(var(--months, 4), 1fr); }
/* Mismo degradado negro→coral que el topbar (var(--grad-portada)), texto blanco. */
.gantt-months .mo { text-align: center; font-size: .72rem; font-weight: 600; color: #fff; padding: .25rem 0; background: var(--grad-portada); border-radius: 6px; margin: 0 2px; }
.gantt-weeks { display: grid; grid-template-columns: repeat(var(--cols, 12), 1fr); }
.gantt-weeks .wk { font-size: .68rem; color: var(--ink-mute); text-align: center; padding: 0 2px; }
.gantt-task { padding: .7rem .8rem .7rem 0; }
.gantt-task b { font-size: .88rem; display: block; }
.gantt-task span { font-size: .72rem; color: var(--ink-mute); }
.gantt-track { position: relative; height: 30px; display: grid; grid-template-columns: repeat(var(--cols, 12), 1fr); align-items: center; }
.gantt-track::before { content: ""; position: absolute; inset: 0; background-image: repeating-linear-gradient(to right, transparent, transparent calc(100% / var(--cols, 12) - 1px), var(--line-2) calc(100% / var(--cols, 12) - 1px), var(--line-2) calc(100% / var(--cols, 12))); }
/* La barra se posiciona en % sobre el total de DÍAS del cronograma (antes ocupaba columnas enteras de
   semana con grid-column). Así una etapa puede durar 3 o 10 días exactos y el editor de cronograma
   puede fijar el día de inicio, mientras la grilla de fondo sigue marcando semanas. */
.gantt-bar { position: absolute; top: 50%; transform: translateY(-50%); height: 18px; border-radius: 100px;
  display: flex; align-items: center; padding: 0 .5rem; font-size: .66rem; font-weight: 600; color: #fff;
  white-space: nowrap; overflow: hidden; min-width: 8px; }
.gantt-bar.done { background: #1f7a4d; }
.gantt-bar.doing { background: var(--accent); }
.gantt-bar.todo { background: var(--bg-3); color: var(--ink-mute); }
.gantt-row.body { cursor: pointer; border-radius: 8px; transition: background .15s; position: relative; z-index: 1; }
.gantt-row.body:hover { background: var(--bg); }
.gantt-row.body:hover .gantt-task b { color: var(--accent); }
.gantt-body { position: relative; }
/* PAUSA ACTIVA (26-jul-2026): el miembro ve su cronograma ORIGINAL bajo un velo tenue + banner
   negro-coral "en pausa por N días" (reemplazó a la banda coral insertada en el gantt). */
.crono-paused { position: relative; }
.crono-veil { position: absolute; inset: 0; z-index: 40; border-radius: 16px;
  background: rgba(244, 241, 234, .45); backdrop-filter: blur(1.5px); -webkit-backdrop-filter: blur(1.5px); }
.crono-pause-banner { position: absolute; top: 150px; left: 50%; transform: translateX(-50%); z-index: 41;
  display: flex; flex-direction: column; align-items: center; gap: .3rem; text-align: center;
  /* Brillo coral sutil en la esquina superior derecha, con la paleta del --grad-box de la casa. */
  background: radial-gradient(circle at 100% 0%, rgba(199, 92, 79, .5) 0%, rgba(111, 58, 50, .26) 30%, rgba(28, 26, 24, 0) 62%), #1C1A18;
  color: #F4F1EA; border-radius: 16px; padding: 1.15rem 1.6rem;
  width: min(92%, 430px); box-shadow: 0 18px 44px rgba(28, 26, 24, .3); }
.crono-pause-banner b { font-size: 1.02rem; color: #fff; }
.crono-pause-banner > span:last-child { font-size: .85rem; opacity: .85; }
.crono-pause-ico { display: flex; width: 34px; height: 34px; border-radius: 50%; background: var(--accent);
  color: #fff; align-items: center; justify-content: center; margin-bottom: .15rem; }
.crono-pause-ico .app-icon { width: 17px; height: 17px; }
.crono-pause-cancel { margin-top: .55rem; border-color: rgba(244, 241, 234, .45); color: #F4F1EA; background: transparent; }
.crono-pause-cancel:hover { background: rgba(244, 241, 234, .14); border-color: rgba(244, 241, 234, .7); color: #fff; }
.prog-admin-note { display: inline-flex; align-items: center; gap: .35rem; margin-top: .6rem; font-size: .8rem; color: var(--accent); }
.prog-admin-note .app-icon { width: 14px; height: 14px; }
/* Fecha de término del cronograma (con la pausa ya sumada) en el intro del cronograma. */
.prog-dates { margin: .55rem 0 0; font-size: .9rem; color: var(--ink-soft); }
.prog-pause-badge { display: inline-flex; align-items: center; gap: .3rem; margin-left: .35rem; padding: .1rem .5rem;
  border-radius: 100px; background: var(--accent-soft); color: var(--accent-deep); font-size: .74rem; font-weight: 600; white-space: nowrap; }
.prog-pause-badge .app-icon { width: 12px; height: 12px; }
/* Fila "Pausa aplicada" en la proyección de Seguimiento. */
.tm-row--pause span { display: inline-flex; align-items: center; gap: .3rem; color: var(--accent-deep); }
.tm-row--pause b { color: var(--accent-deep); }
.tm-row--pause .app-icon { width: 13px; height: 13px; }
/* El resalte coral del módulo al llegar desde el cronograma (.module--flash / @keyframes modFlash) se
   ELIMINÓ a pedido del cliente (17-jul-2026). La navegación desde el cronograma sigue igual: el módulo
   destino se selecciona y queda a la vista, solo se quitó el parpadeo del borde. */

/* =============================================================
   9. PERFIL
   ============================================================= */
.profile-layout { display: grid; grid-template-columns: 1fr; gap: 1.4rem; align-items: start; }
.profile-hero { padding: 0; overflow: hidden; }
.profile-cover { height: 140px; background: linear-gradient(120deg, var(--accent-soft), var(--bg-3)); position: relative; }
.profile-cover::after { content: ""; position: absolute; inset: 0; background: radial-gradient(60% 100% at 80% 0%, var(--accent-glow), transparent 70%); }
.profile-id { padding: 0 1.5rem 1.5rem; margin-top: -44px; position: relative; }
.profile-avatar { width: 92px; height: 92px; border-radius: 50%; border: 4px solid var(--paper); background: var(--accent-soft); display: grid; place-items: center; color: var(--accent-deep); font-family: var(--serif); font-style: italic; font-size: 2.2rem; font-weight: 600; }
.profile-id h2 { font-family: var(--serif); font-weight: 300; font-size: 1.7rem; margin-top: .8rem; }
.profile-id .role { color: var(--ink-mute); font-size: .9rem; }
.profile-id .bio { color: var(--ink-soft); font-size: .94rem; margin-top: .8rem; max-width: 60ch; }
.profile-meta { display: flex; gap: 1.4rem; flex-wrap: wrap; margin-top: 1rem; font-size: .82rem; color: var(--ink-mute); }
.profile-meta span { display: inline-flex; align-items: center; gap: .4rem; }
/* Editar perfil: lápiz flotante (esquina inferior derecha del box de perfil) → abre modal */
.profile-edit-fab {
  position: absolute; right: 1.4rem; bottom: 1.5rem; width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft); display: grid; place-items: center;
  cursor: pointer; transition: border-color .2s, color .2s;
}
.profile-edit-fab:hover { border-color: var(--accent); color: var(--accent); }

.profile-side { display: grid; gap: 1.4rem; }
.profile-stats { padding: 1.3rem; }
.profile-stats .row { display: flex; justify-content: space-between; align-items: center; padding: .6rem 0; }
.profile-stats .row + .row { border-top: 1px solid var(--line-2); }
.profile-stats .row b { font-family: var(--serif); font-style: italic; font-size: 1.3rem; color: var(--accent-deep); }
.profile-stats .row span { font-size: .86rem; color: var(--ink-soft); }

/* Edit form */
.field { margin-bottom: 1.1rem; }
.field label { display: block; font-size: .78rem; font-weight: 600; color: var(--ink-soft); margin-bottom: .4rem; letter-spacing: .02em; }
.field input, .field textarea, .field select {
  width: 100%; padding: .75rem 1rem; border-radius: 12px; border: 1px solid var(--line);
  background: var(--bg); font: inherit; font-size: .92rem; color: var(--ink); transition: border-color .25s, background .25s;
}
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border-color: var(--accent); background: var(--paper); }
.field textarea { resize: vertical; min-height: 90px; }
/* Desplegables en formato píldora, igual que el filtro "Categoría" de Miembros (.members-select)
   — los input/textarea de al lado conservan su radio de 12px, solo cambian los <select>. */
.field select {
  border-radius: 100px; padding-right: 2.6rem; cursor: pointer;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237a736b' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 1rem center; background-size: 14px;
}
.field .hint { font-size: .72rem; color: var(--ink-mute); margin-top: .35rem; }
.avatar-upload { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.2rem; }
.avatar-upload-actions { display: flex; align-items: center; flex-wrap: wrap; gap: .6rem; }
.avatar-upload-actions .hint { margin: 0 0 0 .3rem; color: var(--ink-mute); }
.avatar-upload .preview { width: 64px; height: 64px; border-radius: 50%; background: var(--accent-soft); display: grid; place-items: center; color: var(--accent-deep); font-family: var(--serif); font-style: italic; font-size: 1.5rem; font-weight: 600; flex: 0 0 auto; }
.edit-actions { display: flex; gap: .7rem; align-items: center; margin-top: 1.4rem; }

/* =============================================================
   10. PANEL DE MÉTRICAS (restringido)
   ============================================================= */
.restricted-banner { display: flex; align-items: center; flex-wrap: wrap; gap: .8rem; padding: .9rem 1.2rem; border-radius: 12px; background: var(--ink); color: var(--bg); margin-bottom: 1.6rem; font-size: .88rem; }
.restricted-banner .app-icon { stroke: var(--accent); flex: 0 0 auto; }
.restricted-banner b { color: var(--accent); }
/* Dos gráficos del panel (Recorrido + Tiempo activo), lado a lado y del tamaño del box "Potencial upsell" (mitad de ancho). */
.metrics-charts { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.2rem; margin-bottom: 1.4rem; align-items: stretch; }
/* Ambas cards igualan altura (stretch) y empujan su gráfico al fondo, de modo que los dos SVG quedan alineados abajo. */
.metrics-chart-card, .metrics-charts .metrics-time-card { display: flex; flex-direction: column; }
.metrics-chart-card .metrics-chart, .metrics-charts .metrics-time-card .metrics-chart { margin-top: auto; }
.metrics-chart-card .metrics-chart-sub, .metrics-charts .metrics-time-card .metrics-chart-sub { min-height: 4.6em; }
.metrics-chart-card { padding: 1.3rem var(--card-pad) 1.4rem; color: var(--paper); border: 0; overflow: hidden; background: var(--grad-portada); }
.metrics-chart-card h3, .metrics-stats-card h3 { font-size: 1.05rem; font-weight: 600; color: var(--paper); }
.metrics-stats-card { padding: 1.1rem var(--card-pad); color: var(--paper); border: 0; overflow: hidden; background: var(--grad-portada); }
.metrics-stats-card .mhero-stats { grid-template-columns: repeat(2, 1fr); height: 100%; }
.metrics-chart-sub { font-size: .82rem; color: rgba(244,241,234,.72); margin: .2rem 0 .9rem; }
.metrics-chart { width: 100%; height: auto; display: block; }
.mhero-stats { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; align-content: center; }
/* Todas las tarjetas del mismo tamaño; si el total es impar, la última queda sola en su fila a tamaño normal. */
.mhero-stat { background: rgba(244,241,234,.08); border: 1px solid rgba(244,241,234,.16); border-radius: 12px; padding: .8rem .9rem; }
.mhero-stat .n { font-size: 1.6rem; font-weight: 600; line-height: 1; }
.mhero-stat .l { font-size: .8rem; color: rgba(244,241,234,.9); margin-top: .35rem; }
.mhero-stat .s { font-size: .68rem; color: rgba(244,241,234,.55); }
@media (min-width: 880px) { .metrics-charts { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
/* Equipo: tabla (Métricas por coach) ARRIBA y gráfico (Tiempo activo) ABAJO, ambos a todo el ancho.
   Se apilan en 1 columna (la tabla va primero en el DOM → queda arriba). Regla posterior → gana sobre el 2-col. */
.metrics-charts--team { grid-template-columns: minmax(0, 1fr); }
.metrics-charts--team .metrics-coach-card { margin-bottom: 0; } /* separación por el gap del grid, no por margen propio */
@media (max-width: 640px) { .metrics-stats-card .mhero-stats { grid-template-columns: 1fr 1fr; } }
.mc-grid { stroke: rgba(244,241,234,.16); stroke-width: 1; }
.mc-legend { display: flex; flex-wrap: wrap; gap: 1.1rem; margin-bottom: .6rem; }
.mc-leg { display: inline-flex; align-items: center; gap: .4rem; font-size: .8rem; color: rgba(244,241,234,.9); }
.mc-leg i { width: 13px; height: 13px; border-radius: 3px; display: inline-block; }
/* Gráfico de recorrido: el SVG se estira a todo el ancho (preserveAspectRatio=none, alto fijo por CSS)
   y TODO el texto de ejes es HTML a tamaño fijo → tipografía constante e igual a la de la página. */
.mc-chart { margin-top: .5rem; }
/* margen izq. = sitio de las etiquetas Y (hasta 3 dígitos con ~300 alumnos); margen der. = medio
   ancho de la última etiqueta X (M12) para que no se corte contra el borde de la tarjeta. */
.mc-plot { position: relative; height: 210px; margin: 0 16px 0 42px; }
.mc-svg { width: 100%; height: 100%; display: block; overflow: visible; }
.mc-yl { position: absolute; right: 100%; margin-right: 8px; transform: translateY(-50%); font-size: .8rem; line-height: 1; color: rgba(244,241,234,.6); font-variant-numeric: tabular-nums; white-space: nowrap; }
.mc-dot { position: absolute; width: 7px; height: 7px; border-radius: 50%; transform: translate(-50%, -50%); }
.mc-xaxis { position: relative; height: 1rem; margin: .5rem 16px 0 42px; }
.mc-xl { position: absolute; transform: translateX(-50%); font-size: .8rem; line-height: 1; color: rgba(244,241,234,.6); white-space: nowrap; }
/* Card de recorrido SUELTA (no en grid): el subtítulo no necesita el min-height que igualaba alturas. */
.bit-chart-full .metrics-chart-sub { min-height: 0; }
.metrics-flags { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.2rem; margin-bottom: 1.4rem; }
.metrics-flag-card { padding: 1.1rem var(--card-pad) .7rem; }
.metrics-flag-card h3 { display: flex; align-items: center; gap: .45rem; font-size: .98rem; font-weight: 600; margin-bottom: .4rem; }
.metrics-flag-card h3 .app-icon { width: 17px; height: 17px; color: var(--accent); }
.flag-count { margin-left: auto; font-size: .78rem; color: var(--ink-mute); font-weight: 600; }
.flag-row { display: flex; align-items: center; gap: .7rem; padding: .6rem .4rem; border-top: 1px solid var(--line-2); cursor: pointer; border-radius: 8px; }
.flag-row:hover { background: var(--bg); }
.flag-id { flex: 1; min-width: 0; }
.flag-id b { display: block; font-size: .9rem; }
.flag-id span { font-size: .76rem; color: var(--ink-mute); }
.flag-tag { font-size: .7rem; font-weight: 600; padding: .2rem .55rem; border-radius: 100px; flex: 0 0 auto; }
.flag-tag.up { background: #e2f4ea; color: #1f7a4d; }
.flag-tag.warn { background: var(--accent-soft); color: var(--accent-deep); }
.flag-av, .coachm-av { width: 38px; height: 38px; flex: 0 0 auto; border-radius: 50%; background: var(--bg-3) center/cover no-repeat; color: var(--ink-soft); display: grid; place-items: center; font-weight: 600; font-size: .8rem; }
.metrics-coach-card { padding: 1.2rem var(--card-pad); margin-bottom: 1.4rem; }
.metrics-coach-card h3 { font-size: 1rem; font-weight: 600; margin-bottom: .8rem; }
.coachm-table { border: 1px solid var(--line-2); border-radius: 12px; overflow: hidden; min-width: 460px; }
.coachm-row { display: grid; grid-template-columns: 1.8fr .8fr 1fr .9fr; gap: .8rem; align-items: center; padding: .7rem var(--card-pad); border-top: 1px solid var(--line-2); }
.coachm-row:first-child { border-top: 0; }
.coachm-head { background: var(--bg); font-size: .72rem; color: var(--ink-mute); font-weight: 600; }
.coachm-name { display: flex; align-items: center; gap: .6rem; min-width: 0; }
.coachm-name b { font-size: .9rem; }
.coachm-stat b { font-size: 1.05rem; display: block; }
.coachm-stat span { font-size: .72rem; color: var(--ink-mute); }
.metrics-empty { color: var(--ink-mute); font-size: .86rem; padding: .6rem 0; }
.metrics-empty.light { color: rgba(244,241,234,.72); }
/* Tiempo activo de coaches — gráfico de barras en card oscura premium */
.metrics-time-card { padding: 1.3rem var(--card-pad) 1.4rem; color: var(--paper); border: 0; overflow: hidden; background: var(--grad-portada); }
.metrics-time-card h3 { font-size: 1.05rem; font-weight: 600; color: var(--paper); }
/* Barras horizontales del tiempo activo del equipo, en HTML (no SVG): nombre · barra · valor.
   Una sola grilla compartida (filas con display:contents) → columnas alineadas entre todas las filas
   y el valor comparte ancho. La tipografía la hereda del área (14px), no se fija acá. */
.tact-chart { display: grid; grid-template-columns: minmax(84px, 168px) 1fr auto; gap: .55rem .75rem; align-items: center; margin-top: .2rem; }
.tact-row { display: contents; }
.tact-name { min-width: 0; font-weight: 600; color: rgba(244,241,234,.96); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tact-track { height: 15px; border-radius: 7px; background: rgba(244,241,234,.14); overflow: hidden; }
.tact-bar { display: block; height: 100%; border-radius: 7px; background: linear-gradient(90deg, #F0A48F 0%, #F26B5E 100%); }
.tact-val { color: var(--paper); font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
/* Encabezados de sección del Panel de métricas (Comunidad / Equipo) */
.metrics-section-head { margin: 0 0 1rem; }
.metrics-section-head h2 { font-size: 1.2rem; font-weight: 600; }
.metrics-section-head p { font-size: .85rem; color: var(--ink-mute); margin-top: .15rem; }
.metrics-section-head.is-team { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--line-2); }
/* Métricas por coach compactas (al tamaño del box de tiempo activo) */
.metrics-coach-card--compact { margin-bottom: 0; padding: 1.1rem var(--card-pad) .9rem; }
.metrics-coach-card--compact h3 { font-size: .98rem; margin-bottom: .55rem; }
.metrics-coach-card--compact .coachm-row { grid-template-columns: 1.6fr .55fr .55fr .5fr; gap: .35rem; padding: .5rem .65rem; }
.metrics-coach-card--compact .coachm-av { width: 27px; height: 27px; font-size: .66rem; }
.metrics-coach-card--compact .coachm-name { gap: .45rem; }
.metrics-coach-card--compact .coachm-name b { font-size: .78rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.metrics-coach-card--compact .coachm-stat b { font-size: .9rem; }
.metrics-coach-card--compact .coachm-stat span { font-size: .6rem; }
.metrics-coach-card--compact .coach-dash-note { margin-top: .5rem; font-size: .68rem; }
.coachm-head-row { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-bottom: .55rem; }
.coachm-head-row h3 { margin-bottom: 0; }
.coachm-range { font-size: .72rem; padding: .26rem 1.5rem .26rem .5rem; border: 1px solid var(--line-2); border-radius: 100px; background: var(--paper); color: var(--ink-soft); cursor: pointer; max-width: 150px; appearance: none; -webkit-appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237a736b' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .45rem center; background-size: 11px; }
@media (min-width: 880px) { .metrics-flags { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.bars { display: flex; align-items: flex-end; gap: .6rem; height: 180px; }

/* =============================================================
   Mobile drawer overlay
   ============================================================= */
.app-overlay { position: fixed; inset: 0; background: rgba(28,26,24,.4); z-index: 75; opacity: 0; visibility: hidden; transition: opacity .35s; }
body.drawer-open .app-overlay { opacity: 1; visibility: visible; }

/* =============================================================
   11. RESPONSIVE
   ============================================================= */
@media (min-width: 600px) {
}
@media (min-width: 980px) {
  .app-main { transition: margin-left .4s var(--ease-out); }
  .sidebar { transition: width .4s var(--ease-out), transform .45s var(--ease-out), padding .4s var(--ease-out); }
  /* ----- Mini-barra colapsada: solo iconos ----- */
  body.sidebar-collapsed .sidebar { width: 76px; padding-left: .5rem; padding-right: .5rem; }
  body.sidebar-collapsed .app-main { margin-left: 76px; }
  body.sidebar-collapsed .sidebar-section-label { opacity: 0; height: 0; padding: 0; margin: 0; overflow: hidden; }
  body.sidebar-collapsed .sidebar-brand { justify-content: center; padding-left: 0; padding-right: 0; }
  body.sidebar-collapsed .sidebar-brand img.brand-full { display: none; }
  body.sidebar-collapsed .sidebar-brand img.brand-mini { display: block; margin: 0 auto; }
  body.sidebar-collapsed .sidebar .side-link,
  body.sidebar-collapsed .side-home,
  body.sidebar-collapsed .side-logout { justify-content: center; gap: 0; font-size: 0 !important; padding-left: 0; padding-right: 0; }
  body.sidebar-collapsed .side-link .count,
  body.sidebar-collapsed .side-link .lock,
  body.sidebar-collapsed .side-link .dot-pend { display: none; }
  body.sidebar-collapsed .side-profile { justify-content: center; padding-left: 0; padding-right: 0; }
  body.sidebar-collapsed .side-profile .meta { display: none; }
}
/* Grillas de 2 columnas del CONTENIDO: el breakpoint de arriba (980px) es del VIEWPORT completo,
   pero la sidebar fija (264px, ver .app-main) le resta ese ancho al contenido real — a 1024px de
   viewport solo quedan ~760px de contenido, más angosto de lo que estas grillas "desktop" esperan
   (caso confirmado en el audit de responsividad, R11.2). Se activan recién cuando el contenido
   efectivo (viewport - 264px de sidebar) alcanza los ~980px que este diseño siempre asumió. */
@media (min-width: 1240px) {
  .feed-layout { grid-template-columns: 1fr 320px; }
  .cal-layout { grid-template-columns: 1.6fr 1fr; }
  .profile-layout { grid-template-columns: 1.7fr 1fr; }
  .plan-overview { grid-template-columns: 1fr auto; }
  .topbar-search-wrap { display: block; }
}
@media (max-width: 979px) {
  .sidebar { transform: translateX(-100%); box-shadow: 0 0 60px rgba(28,26,24,.2); z-index: 80; }
  body.drawer-open .sidebar { transform: none; }
  .app-main { margin-left: 0; }
  .topbar-burger { display: grid; }
}
/* Pulido fino de móvil (≤560px): en pantallas angostas los huecos generosos de escritorio
   ahogan el título de cada tarea/lección (queda en ~73px y rompe en 4 líneas). Se comprimen
   solo los huecos y el padding lateral — sin tocar el tamaño de letra ni el layout de escritorio.
   Además se agrega espacio inferior al contenido para que los botones flotantes (chat + Nubia,
   position:fixed) no tapen la última fila de acciones. */
@media (max-width: 560px) {
  .app-content .task-head, .app-content .lesson { gap: .55rem; padding-left: .5rem; padding-right: .5rem; }
  /* Margen lateral del contenido más ajustado en móvil (pedido cliente 17-jul): de ~21px (el mínimo del
     clamp base) a .85rem (~13.6px). Aplica a TODO el contenido del área de miembros (feed, módulos,
     etc.), así que las publicaciones quedan más cerca de los bordes y con más ancho útil. */
  .app-content { padding-left: .85rem; padding-right: .85rem; padding-bottom: 84px; }

  /* ===== Compactación móvil del área de miembros (auditoría 17-jul-2026) =====
     Medido a 375px. Solo móvil; escritorio queda igual. */
  /* Botones: 27px → 16px de relleno lateral. Era el problema REAL medido: una fila de dos botones en
     un modal ("Cancelar" + "Guardar cambios") pedía 285px y solo había 258px, así que el segundo caía
     a otra línea. Esto libera 44px por fila y pasa a sobrar espacio. La altura no cambia (se toca igual). */
  .app-body .btn { --pad-x: 1rem; }
  /* --card-pad alimenta el relleno lateral de composer, prog-intro, plan-overview, gantt y métricas:
     bajándolo acá se compactan todas de una sola vez. */
  .app-body { --card-pad: 1rem; }                                   /* 21px → 16px */
  .feed-post, .rail-card { padding-left: 1rem; padding-right: 1rem; } /* usan 1.3rem fijo, no la variable */
  /* Ojo: .app-modal-card y .gate-card NO se pueden compactar acá — sus reglas base están MÁS ABAJO en
     este archivo (líneas ~632 y ~832) y con igual especificidad gana la última. Van al final del archivo. */
  /* Fila de evento (Próximas sesiones): en escritorio va [fecha][info][Unirme] en una línea, pero
     en móvil el botón deja el detalle en ~69px y parte la hora. Se hace que el detalle ocupe el
     ancho completo (fecha aparte) y el botón baje a su propia línea, alineado bajo el detalle. */
  .evt-item { flex-wrap: wrap; }
  .evt-item .evt-info { flex-basis: calc(100% - 70px); }
  .evt-item .evt-join { margin-left: 70px; margin-top: .3rem; }
  /* Barra de escribir mensaje (chat): en desktop entran 3 tools + input + "Enviar" en una línea,
     pero en 333px el input (con min-width intrínseco) no encoge y empuja "Enviar" fuera del box.
     Se deja que el input encoja (min-width:0) y se ajustan tools/padding para darle aire. */
  .conv-form input[type="text"], .conv-form textarea { min-width: 0; }
  .msg-conv .conv-form { padding-left: .65rem; padding-right: .65rem; gap: .4rem; }
  .conv-form .conv-tool { width: 36px; height: 36px; }
  .conv-form .btn--coral { padding-left: .95rem; padding-right: .95rem; }
}
@media (prefers-reduced-motion: reduce) {
  .view { animation: none; }
  .bar-col .bar, .module-bar i, .ring, .donut { transition: none; }
}

/* =============================================================
   12. AUTH / PERMISOS — sidebar foot, gates, comunidades,
       miembros, mensajería, modal
   ============================================================= */
.side-role, [data-role-badge] { display: inline; }
.btn-xs { --pad-y: .5rem; --pad-x: .9rem; font-size: .8rem; }
.gate-card { padding: clamp(2rem,5vw,3rem); text-align: center; max-width: 560px; margin: 0 auto; }
.gate-ico { width: 60px; height: 60px; margin: 0 auto 1.2rem; border-radius: 50%; background: var(--bg); border: 1px solid var(--line-2); display: grid; place-items: center; color: var(--ink-mute); }
.gate-ico .app-icon { width: 24px; height: 24px; }
.gate-card h2 { font-family: var(--serif); font-weight: 300; font-size: 1.7rem; }
.gate-card p { color: var(--ink-soft); margin: .8rem auto 0; max-width: 42ch; }
/* Cronograma finalizado / no disponible (regla de fecha de término y toggle del equipo). */
.cron-ended .gate-ico { color: var(--accent-deep); background: var(--accent-soft); border-color: transparent; }
.cron-ended-cta { color: var(--accent-deep) !important; font-weight: 500; }
.gate-meta { display: flex; flex-wrap: wrap; gap: .5rem; justify-content: center; margin: 1.4rem 0; }
.gate-meta li { font-size: .8rem; background: var(--bg); border: 1px solid var(--line-2); border-radius: 100px; padding: .35rem .9rem; color: var(--ink-soft); }
.gate-card .btn { margin-top: .4rem; }
/* Mensaje del box "+" (modal) */
.plus-msg { text-align: center; max-width: 440px; padding: .4rem .6rem .8rem; }
.plus-msg .gate-ico { margin: 0 auto 1rem; }
.plus-msg h2 { font-family: var(--serif); font-weight: 300; font-size: 1.45rem; }
.plus-msg p { color: var(--ink-soft); margin-top: .7rem; }
/* ---- Placeholder ANIMADO de comunidad (miembro sin acceso) · se reemplaza por el video/animación del cliente ---- */
.comm-soon { text-align: center; padding: clamp(2rem,5vw,3.5rem); max-width: 640px; margin: 0 auto; overflow: hidden; }
.comm-soon-stage { position: relative; width: 280px; height: 200px; margin: 0 auto 1.6rem; }
.cs-core { position: absolute; left: 50%; top: 50%; width: 58px; height: 58px; margin: -29px 0 0 -29px; border-radius: 50%; background: var(--grad-portada); animation: csCore 3.2s ease-in-out infinite; }
@keyframes csCore { 0%,100% { transform: scale(1); box-shadow: 0 0 24px 4px rgba(242,107,94,.32); } 50% { transform: scale(1.12); box-shadow: 0 0 42px 12px rgba(242,107,94,.16); } }
.cs-ring { position: absolute; left: 50%; top: 50%; width: 78px; height: 78px; margin: -39px 0 0 -39px; border-radius: 50%; border: 1.5px solid rgba(242,107,94,.5); animation: csRing 3.6s ease-out infinite; }
.cs-ring2 { animation-delay: 1.8s; }
@keyframes csRing { 0% { transform: scale(.55); opacity: .85; } 100% { transform: scale(2.6); opacity: 0; } }
.cs-bubble { position: absolute; border-radius: 50%; display: grid; place-items: center; font-weight: 600; font-size: .82rem; background: var(--accent-soft); color: var(--accent-deep); box-shadow: 0 6px 16px rgba(28,26,24,.12); }
.cs-b1 { width: 44px; height: 44px; left: 11%; top: 13%; animation: csFloat 5s ease-in-out infinite; }
.cs-b1--photo { background-size: cover; background-position: center top; background-color: var(--paper); border: 2px solid var(--paper); }
.cs-b2 { width: 34px; height: 34px; right: 13%; top: 7%; animation: csFloat 6s ease-in-out infinite .5s; }
.cs-b3 { width: 40px; height: 40px; right: 7%; bottom: 15%; animation: csFloat 5.5s ease-in-out infinite 1s; }
.cs-b4 { width: 22px; height: 22px; left: 7%; bottom: 21%; animation: csFloat 4.6s ease-in-out infinite .8s; }
.cs-b5 { width: 15px; height: 15px; left: 41%; top: 3%; animation: csFloat 5.2s ease-in-out infinite .3s; }
.cs-b6 { width: 18px; height: 18px; right: 33%; bottom: 5%; animation: csFloat 4.8s ease-in-out infinite 1.3s; }
@keyframes csFloat { 0%,100% { transform: translate(0,0); } 33% { transform: translate(4px,-10px); } 66% { transform: translate(-5px,6px); } }
.comm-soon h2 { font-family: var(--serif); font-weight: 300; font-size: 1.6rem; }
.comm-soon p { color: var(--ink-soft); margin: .7rem auto 0; max-width: 44ch; }
@media (prefers-reduced-motion: reduce) { .cs-core, .cs-ring, .cs-bubble { animation: none; } }
/* ---- Calendario bloqueado (alumno sin plan): mes real + cursor que hace clic/zoom en 6 fechas ----
   El card lleva además la clase .comm-soon → hereda centro, ancho, padding y estilos h2/p (mismo box que Comunidad). */
/* .cal-layout es un grid de 2 columnas; la card bloqueada ocupa todo el ancho para quedar CENTRADA como en Comunidad. */
.cal-layout > .cal-locked { grid-column: 1 / -1; }
.cal-stage { position: relative; width: min(320px,100%); height: 200px; margin: 0 auto 1.6rem; }
.cal-mini { position: absolute; inset: 0; }
.cm-head { font-size: .82rem; font-weight: 600; color: var(--ink); text-align: center; margin-bottom: .3rem; }
.cm-dows { display: grid; grid-template-columns: repeat(7,minmax(0,1fr)); margin-bottom: .18rem; }
.cm-dow { font-size: .58rem; color: var(--ink-mute); text-align: center; }
.cm-grid { display: grid; grid-template-columns: repeat(7,minmax(0,1fr)); gap: 3px; }
.cm-cell { position: relative; height: 23px; display: grid; place-items: center; font-size: .7rem; color: var(--ink-soft); border-radius: 6px; transition: transform .3s ease, background .3s, color .3s, box-shadow .3s; }
.cm-empty { visibility: hidden; }
.cm-evt { font-weight: 600; color: var(--ink); background: var(--bg); }
.cm-evt::after { content: ""; position: absolute; bottom: 2.5px; left: 50%; transform: translateX(-50%); width: 4px; height: 4px; border-radius: 50%; background: var(--accent); }
.cm-evt.t-vent::after { background: #1f7a4d; }
.cm-evt.t-neuro::after { background: #7c5cff; }
.cm-evt.t-ment::after { background: #F26B5E; }
.cm-evt.t-tech::after { background: #3b82c4; }
.cm-evt.t-work::after { background: #EE8B76; }
.cm-evt.t-pres::after { background: #e0a93b; }
.cm-cell.is-marked { background: var(--ink); color: #fff; }
.cm-cell.is-marked::after { background: #fff; }
.cal-cursor { position: absolute; top: 0; left: 0; margin: -3px 0 0 -4px; z-index: 6; pointer-events: none; transition: transform .6s cubic-bezier(.45,.05,.25,1); filter: drop-shadow(0 2px 3px rgba(0,0,0,.25)); }
.cal-cursor svg { display: block; transition: transform .12s ease; }
.cal-cursor.is-click svg { transform: scale(.78); }
.cal-pop { position: absolute; width: 150px; padding: .42rem .6rem; border-radius: 10px; background: var(--ink); color: var(--bg); box-shadow: 0 10px 24px rgba(28,26,24,.32); opacity: 0; transform: translateY(5px) scale(.96); transition: opacity .25s, transform .25s; z-index: 7; pointer-events: none; text-align: left; }
.cal-pop.is-show { opacity: 1; transform: translateY(0) scale(1); }
.cal-pop-name { display: block; font-size: .76rem; font-weight: 600; line-height: 1.25; }
.cal-pop-date { display: block; font-size: .66rem; opacity: .82; margin-top: 1px; }
@media (prefers-reduced-motion: reduce) { .cal-cursor { transition: none; } }

/* Cronograma bloqueado (alumno sin plan): línea de tiempo animada con el viaje del embudo
   (propuesta → redes → anuncios → leads → cierre). Mismo tratamiento de tarjeta/h2/p que
   .comm-soon (hereda centro, padding, tipografía) — solo el ancho máximo crece para que quepan
   las 5 estaciones con buen espaciado. */
.cron-locked.comm-soon { max-width: 900px; }
.cron-stage { position: relative; width: 100%; padding-top: 50px; margin: 0 auto 2.6rem; }
.cron-timeline { display: flex; justify-content: space-between; align-items: flex-start; position: relative; padding: 0 24px; }
.cron-seg { position: absolute; height: 3px; border-radius: 100px; background: var(--bg-3); overflow: hidden; }
.cron-seg-fill { position: absolute; inset: 0; border-radius: 100px; background: var(--grad-box); transform: scaleX(0); transform-origin: left center; }
.cron-seg-fill.is-animating { transition: transform 1.15s var(--ease-out); }
.cron-seg-fill.is-filled { transform: scaleX(1); }
.cron-node { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; width: 70px; }
.cron-node-dot { width: 24px; height: 24px; border-radius: 50%; background: var(--bg-3); display: grid; place-items: center; transition: transform .55s var(--ease-out), background .5s; }
.cron-node.is-done .cron-node-dot { background: var(--grad-box); }
.cron-node.is-active .cron-node-dot { background: var(--grad-box); transform: scale(1.55); }
/* Icono fijo en el centro del punto: silueta negra sobre fondo blanco, siempre visible (no es
   parte del efecto — lo que aparece y desaparece es solo el texto de abajo). display:flex (en vez
   de dejar el <svg> como inline) evita el hueco de línea base que lo corre del centro. */
.cron-node-dot-icon { width: 18px; height: 18px; border-radius: 50%; background: var(--paper); display: flex; align-items: center; justify-content: center; }
.cron-node-dot-icon svg { display: block; width: 13px; height: 13px; stroke: var(--ink); overflow: visible; }
/* Candado de la última estación: el gancho arranca entreabierto y "se cierra" (gira a su posición
   de reposo) recién cuando termina el zoom del círculo (delay = duración del zoom, .55s) —
   representa el cierre de venta. Vuelve a abrirse solo al reiniciar la vuelta. */
.lock-shackle { transform-origin: 8px 10.5px; transform: rotate(-14deg); transition: transform .5s var(--ease-out) .55s; }
.cron-node.is-active .lock-shackle, .cron-node.is-done .lock-shackle { transform: rotate(0deg); }
/* Efecto al llegar a un punto: solo texto, con chispas que salen disparadas alrededor — nada queda
   pegado como un cartel, todo se desvanece solo. */
.cron-burst { position: absolute; bottom: 100%; left: 50%; width: 0; height: 0; margin-bottom: 14px; pointer-events: none; }
.cron-spark { position: absolute; top: 0; left: 0; width: 6px; height: 6px; margin: -3px 0 0 -3px; border-radius: 50%; background: var(--accent); opacity: 0; }
.cron-label-burst { position: absolute; top: 0; left: 0; transform: translate(-50%, -100%) scale(.7); white-space: nowrap; font-size: .78rem; font-weight: 300; color: var(--ink); opacity: 0; }
.cron-burst.is-firing .cron-spark { animation: cronSparkFly .85s var(--ease-out) forwards; }
.cron-burst.is-firing .cron-label-burst { animation: cronLabelBurst .9s var(--ease-out) forwards; }
@keyframes cronLabelBurst {
  0%   { transform: translate(-50%, -100%) scale(.6); opacity: 0; }
  35%  { transform: translate(-50%, -128%) scale(1); opacity: 1; }
  75%  { transform: translate(-50%, -136%) scale(1); opacity: 1; }
  100% { transform: translate(-50%, -152%) scale(.92); opacity: 0; }
}
@keyframes cronSparkFly {
  0%   { transform: translate(0,0) scale(1); opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) scale(.3); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .cron-seg-fill, .cron-node-dot, .lock-shackle { transition: none !important; }
  .cron-burst.is-firing .cron-spark, .cron-burst.is-firing .cron-label-burst { animation: none !important; }
}

/* Lista de comunidades */
.communities-grid, .comm-list { display: grid; gap: 1rem; }

/* Miembros */
.members-toolbar { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; justify-content: space-between; margin-bottom: 1.4rem; }
.members-search { display: flex; align-items: center; gap: .5rem; background: var(--paper); border: 1px solid var(--line); border-radius: 100px; padding: .6rem 1rem; flex: 1; min-width: 240px; color: var(--ink-mute); }
.members-search input { border: 0; background: none; outline: none; font: inherit; font-size: .9rem; width: 100%; color: var(--ink); }
.members-filters { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
/* Filtros como desplegables (categoría + plan) */
.members-select { display: inline-flex; align-items: center; gap: .5rem; background: var(--paper); border: 1px solid var(--line); border-radius: 100px; padding: .3rem .55rem .3rem .95rem; transition: border-color .2s; }
.members-select:hover { border-color: var(--ink-mute); }
/* Mismo estilo de texto que el buscador de la izquierda (.members-search input): sin mayúsculas
   forzadas, sin negrita ni tracking extra — antes se veían "más pesadas" que el buscador. */
.members-select-lbl { font: inherit; font-size: .9rem; color: var(--ink-mute); font-weight: 400; }
.members-select select { appearance: none; -webkit-appearance: none; border: 0; background: none; outline: none; font: inherit; font-size: .9rem; font-weight: 400; color: var(--ink); cursor: pointer; padding: .15rem 1.3rem .15rem .15rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237a736b' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .25rem center; background-size: 14px; }
.members-banner { display: flex; align-items: center; gap: .6rem; background: var(--accent-soft); color: var(--accent-deep); border-radius: 12px; padding: .8rem var(--card-pad); margin-bottom: 1.2rem; font-size: .9rem; }
.members-banner b { font-weight: 700; }
/* Aviso "viendo la programación de X" (coach/admin entrando desde Seguimiento de alumnos) — mismo
   degradado negro→coral que los elementos activos del sidebar (.side-link.is-active). */
.prog-viewing-banner { display: flex; align-items: center; justify-content: space-between; gap: .8rem; flex-wrap: wrap; background: var(--grad-box); color: var(--paper); border-radius: 12px; padding: .8rem var(--card-pad); margin-bottom: 1.2rem; font-size: .9rem; }
.prog-viewing-banner b { font-weight: 700; }
.prog-viewing-banner .app-icon { stroke: var(--paper); }
.prog-viewing-banner .btn--ghost { border-color: rgba(244,241,234,.4); color: var(--paper); background: transparent; }
.prog-viewing-banner .btn--ghost:hover { background: rgba(244,241,234,.16); border-color: rgba(244,241,234,.65); color: var(--paper); }
/* Tarjeta de "Solicitar/gestionar pausa del programa" en #programacion (R4.7, R7) */
.prog-pause-card { padding: 1.2rem var(--card-pad); margin-bottom: 1.2rem; }
.prog-pause-card h3 { display: flex; align-items: center; gap: .4rem; font-size: .95rem; margin: 0 0 .8rem; }
.prog-pause-card .field { max-width: 220px; margin-bottom: .8rem; }
.prog-pause-card .field:has(textarea) { max-width: 50%; }
.prog-pause-actions { display: flex; gap: .6rem; }
/* Atajo "¿Necesitas una pausa?" al pie del cronograma → abre la pausa en pestaña emergente (modal) */
.prog-pause-cta { display: flex; justify-content: center; margin-top: 1.3rem; }
/* Dentro del modal la tarjeta no lleva su propio padding/margen (el modal ya lo aporta). */
.app-modal-card .prog-pause-card { padding: 0; margin: 0; }
.app-modal-card .prog-pause-card .field:has(textarea) { max-width: 100%; }

.members-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; align-items: stretch; }
/* Grupos dentro de "Todos": Equipo / Miembros, con subtítulo previo a las tarjetas */
.members-group + .members-group { margin-top: 1.9rem; }
.members-group-label { margin: 0 0 .9rem; font: 600 .78rem/1 var(--sans); color: var(--ink-mute); }
.member-card { padding: 1.2rem 1.3rem; display: flex; flex-direction: column; gap: .8rem; cursor: pointer; transition: transform .22s var(--ease-out), box-shadow .22s; }
.member-card:hover { transform: translateY(-3px); box-shadow: 0 18px 40px -24px rgba(28,26,24,.45); }
.member-top { display: flex; align-items: center; gap: .8rem; }
.member-id { flex: 1; min-width: 0; }
.member-id b { display: block; font-size: .95rem; font-family: var(--serif); }
.member-id span { font-size: .78rem; color: var(--ink-mute); }
/* Alto fijo (2 líneas) para que todas las tarjetas midan lo mismo sin importar el largo de la bio;
   el texto completo sigue disponible en un clic (avatar/nombre abren el perfil completo). */
.member-meta { font-size: .82rem; color: var(--ink-mute); word-break: break-all; line-height: 1.35; min-height: 2.7em; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.member-tags { display: flex; flex-wrap: wrap; gap: .4rem; }
/* "Declaró ser miembro activo": sin caja/pill — solo ícono + texto coral en UNA sola línea. El
   font-size lleva !important para ganarle a la regla global de 14px del área de miembros y que entre. */
.member-declared { display: inline-flex; align-items: center; gap: .35rem; color: var(--accent-deep); font-weight: 600; font-size: 13px !important; white-space: nowrap; margin: .15rem 0 .35rem; }
.member-declared .app-icon { width: 15px; height: 15px; }
.m-tag { font-size: .72rem; background: var(--accent-soft); color: var(--accent-deep); border-radius: 100px; padding: .2rem .7rem; font-weight: 600; }
.m-tag.empty { background: var(--bg); color: var(--ink-mute); font-weight: 400; }
.m-status { font-size: .6rem; padding: .18rem .5rem; border-radius: 100px; font-weight: 600; flex: 0 0 auto; }
.m-status.active { background: #e2f4ea; color: #1f7a4d; }
.m-status.admin { background: var(--ink); color: var(--bg); }
.m-status.risk { background: #f7ecd6; color: #8a5a00; }
.member-actions { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.member-actions .app-icon { width: 14px; height: 14px; }
.m-note { font-size: .76rem; color: var(--ink-mute); font-style: italic; }

/* Tarjeta de admin / CEO: fondo degradado negro→coral (Portada) */
.member-card--dark { background: var(--grad-portada); border-color: transparent; color: var(--paper); }
.member-card--dark .member-id b { color: var(--paper); }
.member-card--dark .member-id span,
.member-card--dark .member-meta,
.member-card--dark .member-coach { color: rgba(244,241,234,.78); }
.member-card--dark .member-coach .app-icon { color: rgba(244,241,234,.9); }
.member-card--dark .side-avatar { background: rgba(244,241,234,.2); color: var(--paper); }
.member-card--dark .m-status.admin { background: var(--paper); color: var(--ink); }
.member-card--dark .m-status.team { background: var(--paper); color: #5b46a8; }
.member-card--dark .m-tag { background: rgba(244,241,234,.16); color: var(--paper); }
.member-card--dark .m-tag.empty { background: rgba(244,241,234,.1); color: rgba(244,241,234,.7); }
.member-card--dark .btn--ghost { border-color: rgba(244,241,234,.38); color: var(--paper); background: transparent; }
.member-card--dark .btn--ghost:hover { background: rgba(244,241,234,.14); border-color: rgba(244,241,234,.65); }
.member-card--dark .m-note { color: rgba(244,241,234,.62); }
.member-card--dark .lnk:hover { color: #fff; opacity: 1; }

/* Modal */
.app-modal { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: 1.2rem; }
.app-modal[hidden] { display: none; }
.app-modal-backdrop { position: absolute; inset: 0; background: rgba(28,26,24,.45); backdrop-filter: blur(3px); }
/* Tamaño de las pestañas emergentes (28-jul-2026, pedido del cliente): ancho 440 → 560 (+27%) y alto
   máximo 86 → 90vh. El ancho sube bastante porque es lo que evita el scroll — una descripción larga o
   una lista de miembros caben mucho mejor en 560 que en 440; el alto sube poco a propósito, para no
   pegar la tarjeta a los bordes de la pantalla. */
.app-modal-card { position: relative; background: var(--paper); border-radius: var(--radius-lg); padding: 1.6rem; width: 100%; max-width: 560px; max-height: 90vh; overflow-y: auto; box-shadow: 0 40px 90px -30px rgba(28,26,24,.5); animation: viewIn .35s var(--ease-out); }
/* Excepciones que NO crecen: son piezas cortas donde el ancho extra solo dejaría aire vacío.
   Se detectan por su contenido (`:has`), sin tocar el JS que las abre.
   · .profile-modal → la ficha compacta de miembro, cuyo diseño el cliente aprobó tal cual.
   · .plus-msg / .gate-card → avisos de "sin acceso": un título y dos líneas. */
.app-modal-card:has(> .profile-modal), .app-modal-card:has(> .plus-msg), .app-modal-card:has(> .gate-card) { max-width: 440px; }
.manage-head { display: flex; align-items: center; gap: .9rem; padding-bottom: 1.2rem; border-bottom: 1px solid var(--line-2); margin-bottom: 1rem; }
.manage-head h3 { font-family: var(--serif); font-weight: 400; font-size: 1.3rem; }
.manage-head span { font-size: .78rem; color: var(--ink-mute); }
.manage-section { margin-bottom: 1.2rem; }
.manage-section h4 { font-size: .72rem; color: var(--ink-mute); margin-bottom: .6rem; }
.manage-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .5rem 0; font-size: .9rem; }
.manage-row + .manage-row { border-top: 1px solid var(--line-2); }
/* Select de "Coach asignado": mismos valores que .field select (app.css), pero sin envolverlo en
   .field (que es width:100% — rompería el layout flex de .manage-row, label a la izquierda). */
.manage-row select { padding: .5rem 2.3rem .5rem .95rem; border-radius: 100px; border: 1px solid var(--line); background: var(--bg); font: inherit; font-size: .9rem; color: var(--ink); cursor: pointer; min-width: 200px; transition: border-color .25s, background .25s; appearance: none; -webkit-appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237a736b' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 1rem center; background-size: 13px; }
.manage-row select:focus { outline: none; border-color: var(--accent); background: var(--paper); }

/* ============================================================================
   Desplegable a medida (.mps) y selector de fecha (.mpd) — reemplazan el look
   nativo de <select> / <input type=date>. El control nativo queda oculto (fuente
   de la verdad); el botón + lista los dibuja el componente (ver mpsEnhance/mpdEnhance).
   ============================================================================ */
.mps { position: relative; }
.mps > select { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.mps-btn { width: 100%; display: flex; align-items: center; gap: .6rem; text-align: left; font: inherit; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 100px; padding: .6rem 1rem; cursor: pointer;
  transition: border-color .2s, background .2s, box-shadow .2s; }
.mps-btn:hover { border-color: var(--ink-mute); }
.mps.is-open > .mps-btn { border-color: var(--accent); background: var(--paper); box-shadow: 0 0 0 3px var(--accent-glow); }
.mps.is-disabled > .mps-btn { opacity: .55; cursor: not-allowed; }
.mps-val { flex: 1; min-width: 0; display: flex; align-items: center; gap: .6rem; font-size: .9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mps-val.is-rich .mps-txt { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.mps-val.is-rich .mps-txt b { font-weight: 600; font-size: .88rem; overflow: hidden; text-overflow: ellipsis; }
.mps-val.is-rich .mps-txt small { font-size: .72rem; color: var(--ink-mute); }
.mps-chev { width: 15px; height: 15px; flex: 0 0 auto; color: var(--ink-mute); transition: transform .22s; }
.mps.is-open > .mps-btn .mps-chev { transform: rotate(180deg); }
.mps-list { position: absolute; left: 0; right: auto; top: calc(100% + 6px); z-index: 40; background: var(--paper);
  border: 1px solid var(--line); border-radius: 16px; box-shadow: 0 24px 60px -22px rgba(28,26,24,.5);
  padding: .35rem; max-height: 290px; overflow-y: auto; animation: mpsIn .16s ease-out;
  min-width: 100%; width: max-content; max-width: min(340px, calc(100vw - 24px)); }
.mps.mps-up > .mps-list { top: auto; bottom: calc(100% + 6px); }
.mps.mps-end > .mps-list { left: auto; right: 0; }
@keyframes mpsIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.mps-opt { display: flex; align-items: center; gap: .6rem; padding: .5rem .6rem; border-radius: 11px; cursor: pointer; font-size: .9rem; color: var(--ink-soft); transition: background .13s; white-space: nowrap; }
.mps-opt:hover, .mps-opt.is-hi { background: var(--bg-2); }
.mps-opt.is-sel { background: var(--accent-soft); color: var(--ink); }
.mps-opt.is-disabled { opacity: .5; cursor: not-allowed; }
.mps-opt .mps-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.mps-opt.is-rich .mps-txt b { font-weight: 600; }
.mps-opt.is-rich .mps-txt small { font-size: .74rem; color: var(--ink-mute); }
.mps-opt:not(.is-rich) .mps-txt { flex-direction: row; align-items: center; }
.mps-check { width: 16px; height: 16px; flex: 0 0 auto; color: var(--accent-deep); opacity: 0; transition: opacity .13s; }
.mps-opt.is-sel .mps-check { opacity: 1; }
.mps-av { width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto; background: var(--grad-portada) center/cover no-repeat;
  display: grid; place-items: center; color: #fff; font-weight: 600; font-size: .85rem; }
.mps-val .mps-av { width: 26px; height: 26px; font-size: .74rem; }

/* Filtros ya envueltos en su propia píldora (.members-select) → el botón es transparente, la píldora
   la sigue dando el contenedor; solo cambia la lista abierta. */
.members-select .mps { display: inline-flex; }
.members-select .mps-btn { width: auto; border: 0; background: none; box-shadow: none; padding: .1rem 1.2rem .1rem .1rem; }
.members-select .mps.is-open > .mps-btn { border: 0; background: none; box-shadow: none; }
/* Filtros de métricas (.seg-filter) y "Coach asignado" (.manage-row): la píldora estaba en el propio
   <select>, así que el botón del componente la conserva, dimensionado igual. */
.seg-filter .mps-btn { width: auto; padding: .4rem 1.6rem .4rem .7rem; }
.manage-row .mps { min-width: 200px; }
.manage-row .mps-btn { padding: .5rem 1rem; }
/* Los FILTROS no van en negrita y con font un poco menor (las opciones caben en una línea gracias a
   width:max-content + white-space:nowrap de .mps-list/.mps-opt). No afecta a los selects de persona. */
.members-select .mps-btn, .seg-filter .mps-btn,
.members-select .mps-opt, .seg-filter .mps-opt { font-weight: 400; font-size: .85rem; }

/* Selector de fecha a medida (.mpd) */
.mpd { position: relative; }
.mpd > input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.mpd-btn { width: 100%; display: flex; align-items: center; gap: .6rem; text-align: left; font: inherit; font-size: .9rem; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 100px; padding: .6rem 1rem; cursor: pointer; transition: border-color .2s, background .2s, box-shadow .2s; }
.mpd-btn:hover { border-color: var(--ink-mute); }
.mpd.is-open > .mpd-btn { border-color: var(--accent); background: var(--paper); box-shadow: 0 0 0 3px var(--accent-glow); }
.mpd-btn.is-empty .mpd-lbl { color: var(--ink-mute); }
.mpd-btn svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--ink-mute); margin-left: auto; }
.mpd-cal { position: absolute; left: 0; top: calc(100% + 6px); z-index: 40; width: 290px; max-width: calc(100vw - 32px); background: var(--paper);
  border: 1px solid var(--line); border-radius: 18px; box-shadow: 0 24px 60px -22px rgba(28,26,24,.5); padding: .9rem; animation: mpsIn .16s ease-out; }
.mpd.mpd-up > .mpd-cal { top: auto; bottom: calc(100% + 6px); }
.mpd-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: .7rem; }
.mpd-title { font-weight: 600; font-size: .92rem; }
.mpd-nav { display: flex; gap: .3rem; }
.mpd-nav button { width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft); cursor: pointer; display: grid; place-items: center; transition: border-color .2s, background .2s, color .2s; }
.mpd-nav button:hover { border-color: var(--accent); color: var(--accent-deep); background: var(--accent-soft); }
.mpd-nav svg { width: 15px; height: 15px; }
.mpd-dow, .mpd-grid { display: grid; grid-template-columns: repeat(7, minmax(0,1fr)); gap: 2px; }
.mpd-dow span { text-align: center; font-size: .68rem; font-weight: 600; color: var(--ink-mute); padding: .25rem 0; }
.mpd-day { aspect-ratio: 1; border: 0; background: none; font: inherit; font-size: .82rem; color: var(--ink-soft); border-radius: 9px; cursor: pointer; transition: background .12s, color .12s; }
.mpd-day:hover { background: var(--bg-2); }
.mpd-day.is-out { color: var(--ink-mute); opacity: .5; }
.mpd-day.is-today { box-shadow: inset 0 0 0 1.5px var(--accent); }
.mpd-day.is-sel { background: linear-gradient(90deg, var(--accent), var(--accent-deep)); color: #fff; font-weight: 600; }
.mpd-foot { display: flex; justify-content: space-between; margin-top: .7rem; padding-top: .6rem; border-top: 1px solid var(--line-2); }
.mpd-foot button { border: 0; background: none; font: inherit; font-size: .82rem; font-weight: 600; color: var(--accent-deep); cursor: pointer; padding: .2rem .4rem; border-radius: 8px; }
.mpd-foot button:hover { background: var(--accent-soft); }
/* font-family:inherit — es un <em>, y la regla global "em, .serif-em" (styles.css) le pone Fraunces
   por defecto; el área de miembros usa fuente del sistema en todo, esto no debía ser la excepción. */
.manage-row .req { font-family: inherit; color: var(--accent-deep); font-style: normal; font-size: .76rem; }
/* Fila para agregar un coach pre-aprobado: input en píldora, igual de redondeado que el botón. */
.coach-allow-row { gap: .6rem; }
.coach-allow-input { flex: 1 1 auto; min-width: 0; padding: .6rem 1rem; border-radius: 100px; border: 1px solid var(--line); background: var(--bg); font: inherit; font-size: .88rem; color: var(--ink); transition: border-color .25s, background .25s; }
.coach-allow-input:focus { outline: none; border-color: var(--accent); background: var(--paper); }

/* Mensajería */
.msg-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.2rem; align-items: stretch; }
/* Alto FIJO de los dos boxes (lista + chat abierto): no crecen con el contenido; si el listado no
   cabe, se desplaza con scroll vertical dentro del box (tipo WhatsApp). Ambos comparten el mismo alto. */
.msg-list { padding: .8rem; height: 70vh; overflow-y: auto; }
.msg-list-head { font-size: .72rem; color: var(--ink-mute); padding: .5rem .6rem .7rem; font-weight: 600; }
/* Separador entre la sección "Equipo" y "Conversaciones" en la lista */
.msg-thread + .msg-list-head { margin-top: .5rem; padding-top: .9rem; border-top: 1px solid var(--line-2); }
.msg-thread { display: flex; align-items: center; gap: .7rem; width: 100%; padding: .7rem; border-radius: 12px; transition: background .2s; text-align: left; }
.msg-thread:hover { background: var(--bg); }
.msg-thread.is-active { background: var(--grad-box); }
.msg-thread.is-active b, .msg-thread.is-active .mt-info span { color: var(--bg); }
.mt-info { min-width: 0; }
.mt-info b { display: block; font-size: .88rem; }
.mt-info span { font-size: .76rem; color: var(--ink-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; max-width: 180px; }
.msg-conv { display: flex; flex-direction: column; height: 70vh; }
.conv-head { display: flex; align-items: center; gap: .8rem; padding: 1.1rem 1.3rem; border-bottom: 1px solid var(--line-2); }
/* Solo el span HIJO DIRECTO (el subtítulo) es bloque; con `> span` NO afecta al avatar ni al
   <span class="ceo-badge"> anidado en el <b> del nombre (antes lo volvía una barra a todo el ancho). */
.conv-head-id b { font-size: .95rem; } .conv-head-id > span { font-size: .76rem; color: var(--ink-mute); display: block; }
.conv-body { flex: 1; overflow-y: auto; padding: 1.3rem; display: flex; flex-direction: column; gap: .7rem; }
.bubble { max-width: 75%; padding: .7rem 1rem; border-radius: 16px; background: var(--bg); align-self: flex-start; overflow-wrap: break-word; }
.bubble.mine { background: var(--accent); color: #fff; align-self: flex-end; }
.bubble p { font-size: .9rem; }
.bubble time { font-size: .66rem; opacity: .6; display: block; margin-top: .25rem; }
.conv-form { display: flex; gap: .6rem; padding: 1rem 1.3rem; border-top: 1px solid var(--line-2); }
/* input Y textarea: al pasar el campo a <textarea> estos estilos dejaron de aplicar y el campo
   perdió su forma de píldora. Van juntos para que no vuelva a pasar. */
.conv-form input,
.conv-form textarea { flex: 1; padding: .7rem 1rem; border-radius: 20px; border: 1px solid var(--line); background: var(--bg); font: inherit; font-size: .9rem; outline: none; }
.conv-form input:focus,
.conv-form textarea:focus { border-color: var(--accent); }
.msg-empty { color: var(--ink-mute); font-size: .88rem; text-align: center; padding: 1.4rem; }
/* Indicador "escribiendo…" en vivo (estilo WhatsApp): burbuja a la izquierda con 3 puntos que rebotan. */
.conv-typing { align-self: flex-start; }
.conv-typing-dots { display: inline-flex; align-items: center; gap: 4px; background: var(--bg-2); border-radius: 16px; padding: .6rem .85rem; }
.conv-typing-dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-mute); animation: convDot 1.2s infinite ease-in-out; }
.conv-typing-dots i:nth-child(2) { animation-delay: .18s; }
.conv-typing-dots i:nth-child(3) { animation-delay: .36s; }
@keyframes convDot { 0%, 60%, 100% { opacity: .35; transform: translateY(0); } 30% { opacity: .9; transform: translateY(-3px); } }
/* Estado "Inicia la conversación…" centrado verticalmente en el cuerpo del chat */
.conv-body > .msg-empty { margin: auto 0; }
.msg-placeholder { display: grid; place-items: center; height: 100%; color: var(--ink-mute); gap: .6rem; }
.msg-placeholder .app-icon { width: 30px; height: 30px; }

@media (min-width: 700px) { .members-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 980px) {
  .members-grid { grid-template-columns: repeat(3, 1fr); }
}
/* .msg-layout tiene una columna fija (300px) como .feed-layout: mismo ajuste de breakpoint que
   arriba (R11.2) — recién a los ~980px de contenido REAL (viewport - 264px de sidebar). */
@media (min-width: 1240px) {
  .msg-layout { grid-template-columns: 300px minmax(0, 1fr); }
}

/* =============================================================
   13. ONBOARDING · NOTIFICACIONES · BANNER
   ============================================================= */
/* Sidebar link destacado (onboarding pendiente) */
.side-link--accent { background: var(--accent-soft); color: var(--accent-deep); }
.side-link--accent .app-icon { stroke: var(--accent-deep); }
.side-link--accent:hover { background: var(--accent-soft); color: var(--accent-deep); }
.side-link--accent:hover .app-icon { stroke: var(--accent-deep); }
.dot-pend { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); margin-left: auto; box-shadow: 0 0 0 0 var(--accent-glow); animation: livePulse 2.2s infinite; }

/* Banner onboarding: reusa .restricted-banner (mismo fondo oscuro sólido que Panel de métricas y
   Seguimiento de alumnos, en vez del degradado negro-coral que tenía antes — pedido del cliente,
   13-jul-2026, para unificar el estilo de todos los avisos de "acceso restringido" del sitio). */
.restricted-banner .onb-banner-cta { margin-left: auto; font-weight: 600; white-space: nowrap; }

/* Notificaciones */
.notif { position: relative; }
/* Tope inferior: el panel debe terminar a la MISMA altura que la pestaña de mensajes de la burbuja
   (.msg-mini, anclada con `bottom: 5.35rem`). Sin tope crecía con el número de notificaciones hasta
   salirse de la pantalla y las últimas quedaban fuera de alcance. El valor exacto lo calcula
   sizeNotifPanel() en app.js al abrirlo (el borde superior depende del alto real del topbar, que
   cambia con el ancho porque el título usa font-size con clamp); este max-height es solo el respaldo
   por si el JS no alcanza a correr. `overflow-y: auto` es lo que hace scrolleable el excedente. */
/* Ancho 375px = los 300px originales +25% (pedido 28-jul-2026). Crece SOLO hacia la izquierda porque
   está anclado con `right: 0` a la campana: el borde derecho no se mueve, el izquierdo se corre 75px. */
.notif-panel { position: absolute; top: calc(100% + 10px); right: 0; width: 375px; max-width: 84vw; z-index: 80;
  background: var(--paper); border: 1px solid var(--line-2); border-radius: 16px; box-shadow: 0 24px 60px -24px rgba(28,26,24,.5);
  padding: .6rem; animation: viewIn .25s var(--ease-out);
  max-height: calc(100vh - 10rem); overflow-y: auto; overscroll-behavior: contain; }
.notif-head { font-size: .72rem; color: var(--ink-mute); font-weight: 600; padding: .6rem .7rem .4rem; }
.notif-item { display: flex; gap: .7rem; align-items: flex-start; padding: .8rem .7rem; border-radius: 10px; width: 100%; text-align: left; transition: background .2s; }
.notif-item:hover { background: var(--bg); }
/* Leída (contrato 24-jul-2026): se queda 48h en la barra, atenuada; ya no cuenta en el dot. */
.notif-item.is-read { opacity: .55; }
/* Deep-links de notificaciones (spec 26-jul-2026): aterrizaje con resaltado breve. */
.sol-sub { display: flex; align-items: center; gap: .45rem; margin: 1rem 0 .5rem; font-size: .82rem; font-weight: 700; letter-spacing: .06em; color: var(--ink-mute, #7A746B); }
.sol-sub .app-icon { width: 15px; height: 15px; }
.sol-flash { box-shadow: 0 0 0 2px #F26B5E, 0 8px 24px rgba(242, 107, 94, .18); transition: box-shadow .5s ease; }
.task-flash { outline: 2px solid #F26B5E; outline-offset: 3px; border-radius: 12px; transition: outline-color .5s ease; }
.notif-ico { width: 34px; height: 34px; border-radius: 10px; background: var(--accent-soft); color: var(--accent-deep); display: grid; place-items: center; flex: 0 0 auto; }
.notif-item b { font-size: .88rem; display: block; }
.notif-item span { font-size: .78rem; color: var(--ink-mute); }
.notif-empty { padding: 1.4rem .7rem; text-align: center; color: var(--ink-mute); font-size: .85rem; }

/* Menú de la cuenta (avatar del topbar) */
.topbar-user { position: relative; flex: 0 0 auto; }
button.topbar-avatar { border: none; padding: 0; cursor: pointer; font: inherit; }
.user-menu { position: absolute; top: calc(100% + 10px); right: 0; min-width: 232px; z-index: 80;
  background: var(--paper); border: 1px solid var(--line-2); border-radius: 14px; box-shadow: 0 24px 60px -24px rgba(28,26,24,.5);
  padding: .4rem; animation: viewIn .25s var(--ease-out); }
.user-menu-item { display: flex; align-items: center; gap: .6rem; width: 100%; text-align: left; padding: .65rem .7rem; border-radius: 9px; font-size: .9rem; color: var(--ink); transition: background .15s; cursor: pointer; white-space: nowrap; }
.user-menu-item:hover { background: var(--bg); }
.user-menu-item .app-icon { width: 16px; height: 16px; color: var(--ink-soft); flex: 0 0 auto; }
.user-menu-item + .user-menu-item { border-top: 1px solid var(--line-2); }

/* Onboarding view */
.onb-intro { max-width: 640px; margin-bottom: 1.8rem; }
.onb-intro h2 { font-family: var(--serif); font-weight: 300; font-size: clamp(1.8rem,4vw,2.4rem); }
.onb-intro p { color: var(--ink-soft); margin-top: .6rem; }
.coaches-grid { display: grid; grid-template-columns: 1fr; gap: 1.2rem; }
.coach-card { padding: 1.6rem 1.5rem; text-align: center; display: flex; flex-direction: column; align-items: center; }
.coach-avatar { width: 84px; height: 84px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-deep);
  display: grid; place-items: center; font-family: var(--serif); font-style: italic; font-size: 2rem; font-weight: 600; }
.coach-card h3 { font-family: var(--serif); font-weight: 400; font-size: 1.3rem; margin-top: 1rem; }
.coach-role { font-size: .78rem; color: var(--accent-deep); font-weight: 600; margin-top: .3rem; }
.coach-bio { color: var(--ink-soft); font-size: .9rem; margin: .8rem 0 1.4rem; }
.coach-card .btn { margin-top: auto; width: 100%; }
.onb-done { padding: clamp(2rem,5vw,3rem); text-align: center; max-width: 560px; margin: 0 auto; }
.onb-done .gate-ico { background: #e2f4ea; color: #1f7a4d; }
.onb-done h2 { font-family: var(--serif); font-weight: 300; font-size: 1.8rem; }
.onb-done p { color: var(--ink-soft); margin: .8rem auto 1.4rem; max-width: 42ch; }

/* Welcome popup (reusa modal). Diseño aprobado por el cliente vía Artifact (11-jul-2026):
   foto circular de Nubia + kicker + título editorial, celebrando la decisión de empezar en vez
   de un saludo genérico. Ancho propio (.welcome-modal, ver .app-modal-card más abajo) para que
   la primera oración del texto quepa en una sola línea. Usa Fraunces real (no var(--serif), que
   en el área de miembros es Raleway) para lograr el mismo look editorial de "Sobre Nubia" en la
   portada — única excepción puntual en esta tarjeta; !important necesario para ganarle a las
   reglas globales de tipografía del área de miembros (font-size:14px y font-weight:700 en
   .welcome-card h3, ambas más abajo en este archivo). */
.welcome-card { text-align: center; }
.welcome-kicker { display: block; font-size: .66rem !important; font-weight: 600 !important; letter-spacing: .03em; color: var(--accent-deep); margin-bottom: .85rem; }
.welcome-ico { width: 92px; height: 92px; margin: 0 auto 1rem; border-radius: 50%; overflow: hidden; border: 3px solid var(--accent-soft); }
.welcome-ico img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Tipografía calcada de .auth-brand h1 (styles.css) — el título del panel oscuro de login/registro
   ("Tu marca empieza hoy.") — para que el título de bienvenida se vea con la misma personalidad
   editorial (13-jul-2026, antes calcaba .hero h1; el cliente pidió igualarlo a este otro título en
   su lugar). El font-size se mantiene un valor fijo en rem (no la fórmula clamp(...vw...) del
   original, pensada para su propio panel/ancho) equivalente al tope de su clamp (3rem). */
.welcome-card h3 { font-family: "Fraunces", Georgia, "Times New Roman", serif !important; font-weight: 300 !important; font-size: 3rem !important; line-height: 1.05; letter-spacing: -0.02em; }
/* font-size:inherit !important — sin esto, la regla global del área de miembros
   (font-size:14px !important en todo .app-body *) le gana al <em>, dejando "primer paso." chico
   en vez de heredar el tamaño grande del <h3>. font-family:"Fraunces" explícito — sin esto, la
   regla global del sitio "em{font-family:var(--serif)}" (styles.css) gana por sobre la herencia del
   <h3>, y en el área de miembros --serif es Raleway (no Fraunces), dejando "primer paso." en la
   tipografía equivocada. font-weight:400 (no 300) — igual que el <em> "hoy." de referencia, que por
   esa misma regla global (em{font-weight:400}) renderiza un poco más grueso que el resto del título. */
.welcome-card h3 em { font-family: "Fraunces", Georgia, "Times New Roman", serif !important; font-style: italic; font-weight: 400 !important; font-size: inherit !important; color: var(--accent); }
/* Sin max-width en ch: con el <br> explícito entre las 2 oraciones, el ancho del modal (500px,
   ver .welcome-modal) ya alcanza para que cada una quede en una sola línea; un max-width en ch
   partía la segunda oración (más larga) en dos líneas. */
.welcome-card p { color: var(--ink-soft); margin: .8rem auto 1.4rem; line-height: 1.5; }

@media (min-width: 720px) { .coaches-grid { grid-template-columns: repeat(3, 1fr); } }

/* =============================================================
   14. CALENDARIO (eventos) · MENSAJERÍA (adjuntos) · MODAL
   ============================================================= */
/* Crear evento (solo admin) */
.cal-create { width: 100%; justify-content: center; gap: .55rem; margin-bottom: 1rem; padding: 1rem; border: 0; color: #fff; background: var(--grad-portada); border-radius: var(--radius); box-shadow: 0 14px 34px -20px rgba(28,26,24,.55); }
.cal-create:hover { background: var(--grad-portada); filter: brightness(1.07); box-shadow: 0 18px 40px -18px rgba(28,26,24,.6); }
.cal-create .app-icon { width: 16px; height: 16px; }
.cal-evt:hover { filter: brightness(.96); }
.cal-more { align-self: flex-start; font-size: .6rem; color: var(--ink-mute); font-weight: 600; }

/* ===== Vista de día del calendario (agenda con horario, estilo iOS) =====
   Se abre al pulsar el CUADRO del día. La tarjeta no scrollea: scrollea la franja horaria interna
   (por eso `overflow: hidden` acá y `flex: 1 1 auto; min-height: 0` en .dayv-scroll — sin el
   min-height, un hijo flexible nunca se encoge por debajo de su contenido y el scroll no aparece). */
/* La agenda del día también gana ancho (520 → 620): es donde se reparten en columnas los eventos que
   se pisan, así que cada bloque se lee mejor. El alto se mantiene: es una franja horaria con scroll. */
.app-modal-card.dayv-modal { max-width: 620px; width: min(620px, 94vw); height: min(86vh, 720px); display: flex; flex-direction: column; overflow: hidden; }
.dayv-head { flex: 0 0 auto; }
.dayv-dow { font-size: .74rem; color: var(--ink-mute); }
.dayv-modal .modal-title { margin: .1rem 0 .25rem; }
.dayv-count { display: block; font-size: .78rem; font-weight: 600; color: var(--accent-deep); margin-bottom: .9rem; }
.dayv-nohour { flex: 0 0 auto; display: flex; flex-direction: column; gap: .4rem; border: 1px solid var(--line-2); border-radius: 12px; padding: .6rem .7rem; margin-bottom: .9rem; }
.dayv-nohour .lbl { font-size: .66rem; color: var(--ink-mute); font-weight: 600; }
.dayv-chip { text-align: left; border: none; background: var(--accent-soft); color: var(--accent-deep); border-radius: 9px; padding: .42rem .6rem; cursor: pointer; }
.dayv-chip:hover { filter: brightness(.97); }
.dayv-chip b { display: block; font-size: .84rem; }
.dayv-chip span { font-size: .72rem; opacity: .85; }
.dayv-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; border-top: 1px solid var(--line-2); padding: 14px 0 26px; }
.dayv-grid { position: relative; }
.dayv-line { position: absolute; left: 52px; right: 2px; height: 0; border-top: 1px solid var(--line-2); }
.dayv-line i { position: absolute; left: -52px; top: -7px; width: 44px; text-align: right; font-style: normal; font-size: .64rem; color: var(--ink-mute); font-variant-numeric: tabular-nums; }
.dayv-lane { position: absolute; left: 56px; right: 2px; top: 0; bottom: 0; }
.dayv-ev { position: absolute; overflow: hidden; text-align: left; padding: .3rem .5rem; border: none; border-left: 3px solid var(--accent); border-radius: 8px; background: var(--accent-soft); color: var(--accent-deep); cursor: pointer; }
.dayv-ev:hover { filter: brightness(.97); }
/* Una línea cada uno: en un bloque angosto (eventos que se pisan) el texto se partía en tres renglones
   y quedaba cortado a media palabra. Con nowrap + ellipsis se recorta limpio. */
.dayv-ev b, .dayv-ev span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dayv-ev b { font-size: .8rem; line-height: 1.3; }
.dayv-ev span { font-size: .68rem; opacity: .9; font-variant-numeric: tabular-nums; }
/* Línea de "ahora": solo se pinta si el día abierto es hoy. */
.dayv-now { position: absolute; left: 50px; right: 2px; height: 0; border-top: 2px solid var(--accent); z-index: 2; }
.dayv-now::before { content: ""; position: absolute; left: -4px; top: -5px; width: 9px; height: 9px; border-radius: 50%; background: var(--accent); }

/* Evento en la lista: host + clic para detalle */
.evt-item[data-evt-open] { cursor: pointer; }
.evt-host { display: flex; align-items: center; gap: .5rem; margin-top: .55rem; }
.evt-host-av { width: 26px; height: 26px; font-size: .72rem; flex: 0 0 auto; }
.evt-host-meta { font-size: .8rem; color: var(--ink-soft); line-height: 1.15; }
.evt-host-meta small { display: block; font-size: .7rem; color: var(--ink-mute); }
.muted-pill { align-self: center; font-size: .76rem; color: var(--ink-mute); border: 1px dashed var(--line); border-radius: 100px; padding: .4rem .8rem; white-space: nowrap; }

/* Modal: título, cerrar (×) y formulario de evento */
.modal-title { font-family: var(--serif); font-weight: 300; font-size: 1.6rem; margin: .2rem 0 1.2rem; padding-right: 2rem; }
.app-modal-x { position: absolute; top: 1rem; right: 1rem; width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--line); background: var(--bg); display: grid; place-items: center; color: var(--ink-soft); }
.app-modal-x:hover { border-color: var(--ink); color: var(--ink); }
.app-modal-x .app-icon { width: 16px; height: 16px; transform: rotate(45deg); }
.evt-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }
/* Horario del evento: dos desplegables (inicio a término) en una fila */
.evt-time-row { display: flex; align-items: center; gap: .5rem; }
.evt-time-row select { flex: 1 1 0; min-width: 0; }
.evt-time-sep { flex: 0 0 auto; color: var(--ink-mute); font-size: .82rem; }

/* Dropzone (arrastrar y soltar un archivo/imagen): resalte al arrastrar encima, con `outline` para
   no empujar el layout. Se aplica a todas las subidas por formulario (portadas, entregables,
   publicación, avatar). El .composer-drop-hint solo se muestra en escritorio, donde hay arrastre. */
/* OJO: NO transicionar outline-color. La barra del chat se re-dibuja en cada envío/grabación/adjunto y,
   al añadirse .is-dropzone, el color inicial del outline es `currentcolor` (oscuro): con transición se
   veía animar de oscuro→transparente = un destello punteado intermitente. Sin transición aparece ya en
   transparente (invisible) y el resalte de arrastre entra igual (instantáneo). */
.is-dropzone { transition: background .15s; outline: 2px dashed transparent; outline-offset: 3px; }
.is-dropzone.is-dragover { outline-color: var(--accent); background: var(--accent-soft); }
@media (hover: none) { .composer-drop-hint { display: none; } }

/* Subida de foto de portada (formulario de evento) */
.evt-cover-upload { display: flex; align-items: center; gap: 1rem; }
.evt-cover-preview { width: 132px; height: 80px; flex: 0 0 auto; border-radius: 12px; border: 1px dashed var(--line); background: var(--bg) center/cover no-repeat; display: grid; place-items: center; overflow: hidden; }
.evt-cover-preview.has-img { border-style: solid; border-color: transparent; }
.evt-cover-ph { font-size: .72rem; color: var(--ink-mute); display: inline-flex; align-items: center; gap: .35rem; }
.evt-cover-ph .app-icon { width: 15px; height: 15px; }
.evt-cover-up-actions { display: flex; flex-direction: column; align-items: flex-start; gap: .4rem; }
.evt-cover-up-actions .field-hint { margin-top: 0; }
/* Enlace de reunión + botón de generación automática (Google Meet, checkpoint 12.B) */
.evt-link-row { display: flex; gap: .6rem; align-items: center; }
.evt-link-row input { flex: 1; min-width: 0; }
.evt-link-row button { flex: 0 0 auto; white-space: nowrap; }

/* Detalle de evento */
/* Banner de portada (full-bleed sobre el modal) */
.evt-cover { margin: -1.6rem -1.6rem 1.2rem; height: 200px; background: var(--grad-portada) center/cover no-repeat; border-radius: var(--radius-lg) var(--radius-lg) 0 0; display: flex; align-items: flex-end; padding: 1.3rem 1.5rem; }
.evt-cover.has-img { align-items: stretch; padding: 0; }
.evt-cover-title { font-family: var(--serif); font-weight: 300; font-size: 1.7rem; line-height: 1.05; color: var(--paper); letter-spacing: -.01em; }
.app-modal-x--over { background: rgba(255,255,255,.92); border-color: transparent; color: var(--ink); z-index: 2; box-shadow: 0 4px 14px -6px rgba(28,26,24,.5); }
.app-modal-x--over:hover { background: #fff; color: var(--ink); }
.evt-detail-tag { display: inline-block; font-size: .66rem; color: var(--accent-deep); font-weight: 600; }
.evt-detail-meta { display: flex; flex-wrap: wrap; gap: 1rem; font-size: .85rem; color: var(--ink-mute); margin-bottom: 1.1rem; }
.evt-detail-meta .app-icon { width: 15px; height: 15px; vertical-align: -2px; }
.evt-detail-host { display: flex; align-items: center; gap: .8rem; padding: .9rem 1rem; background: var(--bg); border-radius: 14px; margin-bottom: 1.1rem; }
.evt-detail-av { width: 50px; height: 50px; font-size: 1.1rem; flex: 0 0 auto; }
.evt-detail-host .lbl { display: block; font-size: .66rem; color: var(--ink-mute); }
.evt-detail-host b { font-size: 1rem; }
.evt-detail-host small { display: block; font-size: .78rem; color: var(--ink-mute); }
.evt-detail-intro { margin-bottom: 1.3rem; }
.evt-detail-intro .lbl { display: block; font-size: .66rem; color: var(--ink-mute); margin-bottom: .3rem; }
.evt-detail-intro p { font-size: .92rem; color: var(--ink-soft); }
.evt-detail-actions { display: flex; flex-wrap: wrap; gap: .7rem; }
.btn-danger { color: #b4453a; border-color: #e7c4bf; }
.btn-danger .app-icon { width: 15px; height: 15px; }

/* Badge CEO */
.ceo-badge { display: inline-block; font-size: .58rem; font-weight: 700; letter-spacing: .08em; vertical-align: 1px; background: var(--ink); color: var(--bg); border-radius: 100px; padding: .1rem .42rem; }
.msg-thread.is-active .ceo-badge { background: var(--accent); color: #fff; }

/* Herramientas del chat: imagen + voz */
.conv-tool { flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--line); background: var(--bg); display: grid; place-items: center; color: var(--ink-soft); transition: border-color .2s, color .2s, background .2s; }
.conv-tool:hover { border-color: var(--accent); color: var(--accent-deep); }
.conv-tool .app-icon { width: 18px; height: 18px; }
.conv-tool.is-rec { background: var(--accent); border-color: var(--accent); color: #fff; animation: livePulse 1.4s infinite; }
/* Barra de grabación (timer estilo WhatsApp): reemplaza el input mientras se graba; solo queda el micrófono. */
.conv-rec-bar { display: none; flex: 1 1 auto; align-items: center; gap: .55rem; padding: 0 .3rem; min-width: 0; }
.conv-form.is-recording .conv-rec-bar { display: flex; }
/* Mientras se graba solo quedan el micrófono (dentro de la barra queda la papelera). Se apartan por
   ESTRUCTURA, no por el nombre del campo de cada superficie: antes la regla nombraba
   [data-conv-input]/[data-asst-input] y no conocía [data-msg-mini-input], así que en la burbuja de
   Mensajes el campo se quedaba peleando el ancho con la barra y el cronómetro no se veía. El
   micrófono tampoco entraba en la excepción ([data-mini-rec]) y desaparecía: no había forma de
   detener la grabación. */
.conv-form.is-recording .conv-more-wrap,
.conv-form.is-recording textarea,
.conv-form.is-recording > input[type="text"],
.conv-form.is-recording > button[type="submit"] { display: none; }
.conv-rec-dot { width: 11px; height: 11px; border-radius: 50%; background: #E5484D; flex: 0 0 auto; animation: recPulse 1.2s ease-in-out infinite; }
.conv-rec-time { font-variant-numeric: tabular-nums; font-weight: 600; font-size: .92rem; color: var(--ink); flex: 0 0 auto; min-width: 40px; }
.conv-rec-hint { font-size: .8rem; color: var(--ink-mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@keyframes recPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.82); } }
/* Descartar la grabación sin enviarla. Antes el único botón era el micrófono, que SIEMPRE enviaba:
   una vez empezada la grabación no había salida. */
.conv-rec-cancel { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; border: none; background: transparent; color: var(--ink-mute); display: grid; place-items: center; cursor: pointer; transition: background .15s, color .15s; }
.conv-rec-cancel:hover { background: rgba(229,72,77,.12); color: #E5484D; }
.conv-rec-cancel .app-icon { width: 16px; height: 16px; }
/* Onda animada mientras se graba (decorativa: no representa el volumen real del micrófono). */
.conv-rec-wave { display: inline-flex; align-items: center; gap: 3px; height: 18px; flex: 0 0 auto; }
.conv-rec-wave i { display: block; width: 3px; height: 100%; border-radius: 2px; background: var(--accent); transform: scaleY(.3); animation: recWave 1.05s ease-in-out infinite; }
.conv-rec-wave i:nth-child(2) { animation-delay: .1s; }
.conv-rec-wave i:nth-child(3) { animation-delay: .2s; }
.conv-rec-wave i:nth-child(4) { animation-delay: .3s; }
.conv-rec-wave i:nth-child(5) { animation-delay: .18s; }
.conv-rec-wave i:nth-child(6) { animation-delay: .08s; }
.conv-rec-wave i:nth-child(7) { animation-delay: .26s; }
@keyframes recWave { 0%, 100% { transform: scaleY(.28); } 50% { transform: scaleY(1); } }
/* Barra oscura de la burbuja de Mensajes: el texto por defecto es tinta sobre crema y ahí no se lee. */
.msg-mini-form .conv-rec-time { color: #f4f1ea; }
.msg-mini-form .conv-rec-hint { color: rgba(244,241,234,.55); }
.msg-mini-form .conv-rec-cancel { color: rgba(244,241,234,.7); }
.msg-mini-form .conv-rec-cancel:hover { background: rgba(229,72,77,.24); color: #ff8a8a; }
/* En las burbujas (360px de ancho) el aviso no cabe junto al cronómetro y la onda: se retira ahí. */
.msg-mini-form .conv-rec-hint, .nubia-mini .conv-rec-hint { display: none; }

/* Burbujas con imagen / audio — la descarga de estos 3 vive en el menú "⋮" (.bubble-menu), no superpuesta. */
.bubble-img { display: block; max-width: 100%; width: 240px; border-radius: 12px; margin-bottom: .25rem; cursor: zoom-in; }
/* ===== Nota de voz (reproductor propio, estilo WhatsApp) =====
   Sustituye al <audio controls> nativo, que no ofrece control de velocidad y no se puede vestir.
   Los colores se resuelven con dos variables locales para no repetir cada regla en las cuatro
   combinaciones (recibida/enviada × área grande/burbuja): --vn-on es lo ya reproducido y el botón;
   --vn-off, lo que falta. */
.vnote { --vn-on: var(--accent); --vn-off: rgba(28,26,24,.22);
  display: flex; align-items: center; gap: .5rem; width: 258px; max-width: 100%; margin-bottom: .25rem; }
.vnote-play { flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--vn-on); color: #fff; display: grid; place-items: center; transition: transform .15s var(--ease-out), filter .15s; }
.vnote-play:hover { filter: brightness(1.07); }
.vnote-play:active { transform: scale(.93); }
.vnote-play .app-icon { width: 15px; height: 15px; }
/* La onda es el control de avance: se puede tocar en cualquier punto para saltar ahí. */
.vnote-track { flex: 1 1 auto; min-width: 0; height: 26px; display: flex; align-items: center; gap: 2px; cursor: pointer; }
.vnote-track i { display: block; flex: 1 1 auto; min-width: 2px; border-radius: 2px; background: var(--vn-off); transition: background .12s; }
.vnote-track i.is-on { background: var(--vn-on); }
/* Solo se mueve mientras suena; en pausa la onda queda quieta en su altura real. */
.vnote.is-playing .vnote-track i { animation: vnoteWave 1.1s ease-in-out infinite; }
.vnote.is-playing .vnote-track i:nth-child(3n+1) { animation-delay: .12s; }
.vnote.is-playing .vnote-track i:nth-child(3n+2) { animation-delay: .26s; }
@keyframes vnoteWave { 0%, 100% { transform: scaleY(1); } 50% { transform: scaleY(.55); } }
.vnote-time { flex: 0 0 auto; font-size: .68rem; font-variant-numeric: tabular-nums; color: var(--ink-soft); min-width: 28px; text-align: right; }
.vnote-speed { flex: 0 0 auto; min-width: 30px; padding: .15rem .34rem; border-radius: 100px; border: 1px solid var(--vn-off);
  background: transparent; color: var(--ink-soft); font: 600 .66rem/1.4 var(--sans); cursor: pointer; transition: background .15s, color .15s, border-color .15s; }
.vnote-speed:hover, .vnote-speed.is-fast { background: var(--vn-on); border-color: var(--vn-on); color: #fff; }
/* Burbuja propia (fondo coral en las burbujas flotantes, oscuro en el área grande): la misma paleta
   dejaría el coral sobre coral, así que ahí se invierte a blanco. */
.bubble.mine .vnote { --vn-on: #fff; --vn-off: rgba(255,255,255,.4); }
.bubble.mine .vnote-play { color: var(--accent-deep); }
.bubble.mine .vnote-time { color: rgba(255,255,255,.75); }
.bubble.mine .vnote-speed { color: rgba(255,255,255,.85); }
.bubble.mine .vnote-speed:hover, .bubble.mine .vnote-speed.is-fast { color: var(--accent-deep); }
/* En las burbujas flotantes hay menos ancho disponible. */
.msg-mini-body .vnote, .nubia-mini-body .vnote { width: 216px; }
@media (prefers-reduced-motion: reduce) {
  .vnote.is-playing .vnote-track i { animation: none; }
  .conv-rec-wave i { animation: none; transform: scaleY(.7); }
}
.bubble-video { display: block; width: 260px; max-width: 100%; border-radius: 12px; margin-bottom: .25rem; background: #000; }
.bubble.mine .bubble-img, .bubble.mine .bubble-video { margin-left: auto; }
.bubble-file { display: inline-flex; align-items: center; gap: .5rem; max-width: 260px; padding: .55rem .7rem; border-radius: 12px; background: var(--paper); border: 1px solid var(--line-2); color: var(--ink-soft); margin-bottom: .25rem; text-decoration: none; }
.bubble-file span { flex: 1 1 auto; min-width: 0; font-size: .82rem; font-weight: 500; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bubble-file .app-icon { width: 16px; height: 16px; flex: 0 0 auto; color: var(--accent-deep); }
.bubble.mine .bubble-file { background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.28); color: #fff; }
.bubble.mine .bubble-file span, .bubble.mine .bubble-file .app-icon { color: #fff; }
/* Mientras se firma la URL de Storage del adjunto (ver hydrateAttachments en app.js) */
.bubble-att-loading { display: inline-flex; align-items: center; gap: .5rem; padding: .55rem .7rem; border-radius: 12px; background: var(--paper); border: 1px solid var(--line-2); color: var(--ink-mute); margin-bottom: .25rem; font-size: .82rem; }
.bubble-att-loading .app-icon { width: 16px; height: 16px; flex: 0 0 auto; opacity: .6; }
.bubble.mine .bubble-att-loading { background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.28); color: #fff; }
.bubble a { color: inherit; text-decoration: underline; word-break: break-all; }
.bubble:has(.bubble-img), .bubble:has(.vnote), .bubble:has(.bubble-video), .bubble:has(.bubble-file), .bubble:has(.bubble-att-loading), .bubble:has(.bubble-doc) { padding: .45rem; }

/* Chip de documento estilo Claude — preview sobre el input del chat de Nubia. */
.asst-attach-preview { padding: .7rem 1.3rem 0; }
.doc-chip { display: inline-flex; align-items: center; gap: .6rem; max-width: 100%; padding: .5rem .7rem; border: 1px solid var(--line); border-radius: 12px; background: var(--paper); box-shadow: 0 1px 3px rgba(28,26,24,.06); }
.doc-chip-ico { flex: 0 0 auto; width: 34px; height: 34px; border-radius: 8px; display: grid; place-items: center; background: var(--accent); color: #fff; }
.doc-chip-ico .app-icon { width: 17px; height: 17px; }
.doc-chip-meta { min-width: 0; display: flex; flex-direction: column; }
.doc-chip-meta b { font-size: .82rem; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 220px; }
.doc-chip-meta span { font-size: .7rem; color: var(--ink-mute); }
.doc-chip-x { flex: 0 0 auto; width: 22px; height: 22px; border: 0; background: var(--bg-3); border-radius: 50%; display: grid; place-items: center; cursor: pointer; color: var(--ink-soft); transition: background .2s, color .2s; }
.doc-chip-x .app-icon { width: 13px; height: 13px; transform: rotate(45deg); }
.doc-chip-x:hover { background: var(--accent); color: #fff; }
/* Documento dentro de una burbuja enviada a Nubia. Atenuado/traslúcido, con aire respecto al texto. */
.bubble-doc { display: inline-flex; align-items: center; gap: .55rem; max-width: 260px; padding: .5rem .65rem; border-radius: 12px; background: rgba(28,26,24,.04); border: 1px solid var(--line-2); margin-bottom: .6rem; }
.bubble-doc-ico { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 7px; display: grid; place-items: center; background: rgba(242,107,94,.16); color: var(--accent-deep); }
.bubble-doc-ico .app-icon { width: 15px; height: 15px; }
.bubble-doc-meta { min-width: 0; display: flex; flex-direction: column; }
.bubble-doc-meta b { font-size: .8rem; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px; }
.bubble-doc-meta span { font-size: .68rem; color: var(--ink-mute); }
.bubble.mine .bubble-doc { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.2); }
.bubble.mine .bubble-doc-ico { background: rgba(255,255,255,.2); color: #fff; }
.bubble.mine .bubble-doc-meta b { color: #fff; }
.bubble.mine .bubble-doc-meta span { color: rgba(255,255,255,.72); }

/* "Visto": va FUERA de la burbuja, como hermano suyo, para que quede pegado al borde derecho de la
   columna (el contenedor del chat es flex en columna) y no dentro del globo coral. Solo aparece bajo
   UNA burbuja — la del último mensaje propio que el otro alcanzó a ver.
   El margen superior NEGATIVO contrarresta el `gap` de la columna: sin él, el "Visto" flotaba a la
   misma distancia que separa dos mensajes y parecía suelto en vez de pertenecer a su burbuja.
   ⚠️ El tamaño se declara junto al resto de tamaños del portal (línea ~2222), NO acá: `.app-body *`
   lleva `font-size: 14px !important` y aplasta cualquier font-size de igual especificidad. */
.bubble-seen { align-self: flex-end; color: var(--ink-mute); margin: -.4rem 0 -.1rem; }
/* En la burbuja flotante el globo propio lleva `margin-right: 10px`; el "Visto" lo copia para que
   los dos bordes derechos coincidan. */
.msg-mini-body .bubble-seen { margin: -.3rem 10px -.15rem 0; }
/* Pie de burbuja: hora + menú "⋮" (descargar/editar/eliminar) */
.bubble-foot { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-top: .25rem; }
.bubble-foot time { margin-top: 0; }
.bubble-menu { position: relative; }
.bubble-menu-btn { width: 20px; height: 20px; border: none; background: none; padding: 0; display: grid; place-items: center; color: inherit; opacity: .55; cursor: pointer; border-radius: 6px; transition: opacity .15s, background .15s; }
.bubble-menu-btn:hover { opacity: 1; background: rgba(28,26,24,.08); }
.bubble.mine .bubble-menu-btn:hover { background: rgba(255,255,255,.18); }
.bubble-menu-btn .app-icon { width: 15px; height: 15px; }
.bubble-menu-panel { position: absolute; bottom: calc(100% + 4px); z-index: 5; min-width: 150px; padding: .35rem; border-radius: 12px; background: var(--paper); border: 1px solid var(--line-2); box-shadow: 0 12px 30px -10px rgba(28,26,24,.35); display: flex; flex-direction: column; gap: .1rem; }
.bubble.mine .bubble-menu-panel { right: 0; }
.bubble:not(.mine) .bubble-menu-panel { left: 0; }
.bubble-menu-item { display: flex; align-items: center; gap: .5rem; padding: .45rem .6rem; border-radius: 8px; border: none; background: none; font: inherit; font-size: .82rem; color: var(--ink); text-decoration: none; text-align: left; cursor: pointer; white-space: nowrap; }
.bubble-menu-item:hover { background: var(--bg); }
.bubble-menu-item .app-icon { width: 15px; height: 15px; flex: 0 0 auto; color: var(--ink-mute); }
.bubble-menu-item--danger { color: #b3261e; }
.bubble-menu-item--danger .app-icon { color: #b3261e; }
.bubble-menu-item--danger:hover { background: #fdecea; }

/* Edición inline de un mensaje propio (primer minuto) */
.bubble-edit-form { display: flex; gap: .4rem; align-items: center; margin-top: .3rem; }
.bubble-edit-form input { flex: 1 1 auto; min-width: 0; padding: .4rem .65rem; border-radius: 100px; border: 1px solid var(--line); background: var(--paper); color: var(--ink); font: inherit; font-size: .85rem; }
.bubble.mine .bubble-edit-form input { background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.3); color: #fff; }
.bubble-edit-form input:focus { outline: none; border-color: var(--accent); }

/* ---------- Asistente IA "Nubia" ---------- */
.asst-chat { display: flex; flex-direction: column; min-height: 480px; max-height: 76vh; padding: 0; overflow: hidden; }
.asst-head { display: flex; align-items: center; gap: .85rem; padding: 1rem 1.3rem; border-bottom: 1px solid var(--line-2); }
.asst-avatar { width: 46px; height: 46px; border-radius: 50%; flex: 0 0 auto; background: var(--bg-2) center/cover no-repeat; box-shadow: inset 0 0 0 1px var(--line-2); }
.asst-id { flex: 1; min-width: 0; }
.asst-id b { font-size: 1rem; display: inline-flex; align-items: center; gap: .45rem; }
.asst-status { display: flex; align-items: center; gap: .42rem; font-size: .76rem; color: var(--ink-mute); margin-top: .15rem; }
.asst-status i { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: #1f7a4d; animation: livePulse 2.2s infinite; }
.asst-head .btn-xs { flex: 0 0 auto; }
.asst-body { flex: 1; }
.asst-typing { background: var(--bg); align-self: flex-start; padding: .8rem 1rem; }
.asst-typing .typing { display: inline-flex; gap: 5px; align-items: center; }
.asst-typing .typing i { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-mute); opacity: .45; animation: asstDot 1s infinite; }
.asst-typing .typing i:nth-child(2) { animation-delay: .15s; }
.asst-typing .typing i:nth-child(3) { animation-delay: .3s; }
@keyframes asstDot { 0%, 100% { transform: translateY(0); opacity: .4; } 50% { transform: translateY(-3px); opacity: 1; } }
.asst-note { font-size: .72rem; color: var(--ink-mute); text-align: center; padding: .55rem 1rem .9rem; }

/* ---- Búsqueda en el feed (barra de resultados + comentarios) ---- */
/* Feed vacío: sin caja blanca, texto centrado (misma altura que antes, sin el borde/fondo de tarjeta).
   display:flex además de text-align:center para que quede centrado también si el mensaje ocupa más
   de una línea o el bloque crece de alto (no depender solo del centrado horizontal del texto). */
.feed-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 220px; padding: clamp(2rem, 5vw, 3rem) 1rem; text-align: center; color: var(--ink-mute); }
/* Ícono + título + siguiente paso. Sin tarjeta: el cliente quitó la caja blanca a propósito, así que
   esto vive sobre el fondo. El !important del título es para pasar por encima del 13/14px plano. */
.feed-empty-ico { width: 52px; height: 52px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-deep); display: grid; place-items: center; flex: 0 0 auto; margin-bottom: .9rem; }
.feed-empty-ico .app-icon { width: 22px; height: 22px; }
.feed-empty b { display: block; font-size: 15px !important; color: var(--ink); margin-bottom: .3rem; }
.feed-empty p { margin: 0; max-width: 34ch; line-height: 1.5; }
.feed-searchbar { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; background: var(--accent-soft); color: var(--accent-deep); border-radius: 12px; padding: .7rem 1rem; margin-bottom: 1rem; font-size: .9rem; }
.feed-searchbar b { font-weight: 700; }
.feed-searchbar button { margin-left: auto; font-size: .8rem; font-weight: 600; color: var(--accent-deep); text-decoration: underline; }
/* Comentarios (formato tipo Facebook: avatar + burbuja redondeada + meta con hora/eliminar) */
.fp-comments-section { margin-top: .9rem; padding-top: .9rem; border-top: 1px solid var(--line-2); }
.fp-comments-list { display: flex; flex-direction: column; gap: .55rem; }
.fp-comments-list:empty { display: none; }
.fp-comment { display: flex; gap: .6rem; align-items: flex-start; }
.fp-comment-av { width: 30px; height: 30px; border-radius: 50%; flex: 0 0 auto; }
.fp-comment-body { min-width: 0; }
.fp-comment-bubble { display: inline-block; background: var(--bg); border-radius: 14px; padding: .5rem .85rem; overflow-wrap: anywhere; word-break: break-word; max-width: 100%; }
.fp-comment-bubble b { margin-right: .4rem; }
.fp-comment-bubble span { color: var(--ink-soft); }
.fp-comment-meta { display: flex; gap: .9rem; margin: .25rem 0 0 .85rem; color: var(--ink-mute); font-size: .72rem; }
.fp-comment-meta button { color: var(--ink-mute); font-weight: 600; cursor: pointer; }
.fp-comment-meta button:hover { color: #c33; }
.fp-comment-form { display: flex; align-items: center; gap: .6rem; margin-top: .7rem; }
.fp-comment-form .side-avatar { width: 30px; height: 30px; flex: 0 0 auto; }
.fp-comment-form input { flex: 1 1 auto; min-width: 0; border: 1px solid var(--line-2); background: var(--bg); border-radius: 100px; padding: .55rem .95rem; outline: none; color: var(--ink); font: inherit; }
.fp-comment-form input:focus { border-color: var(--accent); background: var(--paper); }

/* ---- Modal de perfil de un miembro ---- */
.profile-modal { text-align: center; display: flex; flex-direction: column; align-items: center; gap: .35rem; }
.profile-modal-av { width: 76px; height: 76px; border-radius: 50%; font-size: 1.6rem; margin-bottom: .4rem; }
.profile-modal h3 { font-family: var(--serif); font-weight: 400; font-size: 1.5rem; }
.profile-modal-role { font-size: .82rem; color: var(--accent-deep); font-weight: 600; }
.profile-modal-bio { font-size: .92rem; color: var(--ink-soft); margin: .3rem 0 .2rem; overflow-wrap: break-word; }
.profile-modal-loc { font-size: .82rem; color: var(--ink-mute); display: inline-flex; align-items: center; gap: .35rem; }
/* Planes/grupos habilitados de un miembro (solo miembros, nunca equipo — ver openMemberProfile):
   mini-boxes centradas y apiladas, no píldoras en fila como en la tarjeta de Miembros. Diseño
   aprobado por el cliente vía preview (13-jul-2026). */
.profile-modal .section-mini-label { text-align: center; width: 100%; margin: .3rem 0 .3rem; }
.profile-modal-plans { list-style: none; padding: 0; margin: 0 0 .2rem; display: flex; flex-direction: column; align-items: center; gap: .5rem; width: 100%; }
.profile-modal-plans li { font-size: .78rem; color: var(--accent-deep); font-weight: 600; background: var(--accent-soft); border-radius: 100px; padding: .3rem .8rem; width: auto; text-align: center; }
.profile-modal .btn { margin-top: .4rem; }
/* Popup de un miembro del EQUIPO (coach/closer/admin/CEO): mismo degradado negro→coral que su
   tarjeta en el directorio (.member-card--dark), texto claro (pedido del cliente, 13-jul-2026).
   Los miembros regulares mantienen el fondo blanco por defecto. */
.app-modal-card.profile-modal-dark { background: var(--grad-portada); color: var(--paper); }
.app-modal-card.profile-modal-dark .profile-modal h3 { color: var(--paper); }
.app-modal-card.profile-modal-dark .profile-modal-role { color: var(--accent); }
.app-modal-card.profile-modal-dark .profile-modal-bio { color: rgba(244,241,234,.85); }
.app-modal-card.profile-modal-dark .profile-modal-loc { color: rgba(244,241,234,.72); }
.app-modal-card.profile-modal-dark .profile-modal-loc .app-icon { color: rgba(244,241,234,.9); }
.app-modal-card.profile-modal-dark .ceo-badge { background: var(--paper); color: var(--ink); }

/* ---- Filas de Mensajes con hora (WhatsApp) ---- */
.msg-search { display: flex; align-items: center; gap: .5rem; background: var(--bg); border: 1px solid var(--line); border-radius: 100px; padding: .55rem .9rem; margin-bottom: .7rem; color: var(--ink-mute); }
.msg-search input { border: 0; background: none; outline: none; font: inherit; font-size: .88rem; width: 100%; color: var(--ink); }
.mt-top { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; }
.mt-top time { font-size: .68rem; color: var(--ink-mute); flex: 0 0 auto; }
.mt-prev { display: block; font-size: .8rem; color: var(--ink-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: .1rem; }
.msg-thread.is-active .mt-top time, .msg-thread.is-active .mt-prev { color: rgba(244,241,234,.7); }
/* Círculo tipo WhatsApp con el nº de mensajes sin leer (derecha de la fila) */
.mt-unread { margin-left: auto; flex: 0 0 auto; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 100px; background: var(--accent); color: #fff; font: 700 .72rem/1 var(--sans); display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 1px 4px rgba(28,26,24,.28); }
.msg-thread.is-active .mt-unread { background: var(--paper); color: var(--accent); box-shadow: none; }
.mt-unread--mini { min-width: 19px; height: 19px; }

/* ---- Enlaces a perfil (avatar/nombre clicables) ---- */
.lnk { cursor: pointer; }
b.lnk:hover { color: var(--accent-deep); text-decoration: underline; text-underline-offset: 2px; }
span.lnk:hover { opacity: .85; }
.profile-posts-list { display: flex; flex-direction: column; gap: 1rem; margin-top: 1rem; }
.profile-cta { margin-top: 1.1rem; }
.profile-cta .btn { justify-content: center; }

/* ===== Categorías / equipo ===== */
.m-status.team { background: #e8e3f6; color: #5b46a8; }
.member-coach { font-size: .78rem; color: var(--ink-soft); display: flex; align-items: center; gap: .35rem; margin-top: .5rem; }
.member-coach .app-icon { width: 14px; height: 14px; color: var(--accent); }
/* Aviso de solicitudes pendientes en la tarjeta de miembro (admin) */
.member-card.has-req { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.manage-coach { display: inline-flex; align-items: center; gap: .35rem; font-size: .76rem; color: var(--accent); margin-top: .3rem; }
.manage-coach .app-icon { width: 13px; height: 13px; }
.role-switch { display: inline-flex; gap: .4rem; flex-wrap: wrap; }
.welcome-note { font-size: .76rem; color: var(--ink-mute); text-align: center; }
.welcome-note .app-icon { width: 13px; height: 13px; display: inline-block; vertical-align: -2px; }

/* ===== Mensajes: terminar / reabrir conversación ===== */
.conv-head-id { flex: 1; min-width: 0; }
.conv-head-actions { flex: 0 0 auto; }

/* ===== Tareas / submódulos expandibles ===== */
.task { border-radius: 10px; transition: background .2s; }
.task + .task { border-top: 1px solid var(--line-2); }
/* Hover de selección: el tono crema de siempre (var(--bg)), pero SOLO cuando la tarea está
   COLAPSADA — al desplegarse se retira por completo para no restarle contraste a los boxes
   internos (Documentos/Enlaces/Entrega), que usan ese mismo tono (pedido del cliente, 13-jul-2026:
   se probó un degradado oscuro y se descartó; se vuelve al efecto anterior manteniendo el
   :not(.is-expanded)). */
.task:not(.is-expanded):hover { background: var(--bg); }
.task-head { display: flex; align-items: center; gap: .9rem; padding: .8rem; cursor: pointer; }
.task-head .t { flex: 1; min-width: 0; }
.task-head .t b { font-size: .9rem; font-weight: 500; display: block; }
.task-head .t span { font-size: .74rem; color: var(--ink-mute); }
.task.done .t b { color: var(--ink-mute); }
.task.done .lesson-check { background: var(--accent); border-color: var(--accent); color: #fff; }
/* Tarea bloqueada por el avance secuencial (candado, sin contenido). El alumno la ve atenuada. */
.task.is-task-locked { opacity: .72; }
.task.is-task-locked .task-head { cursor: default; }
.task.is-task-locked .lesson-check { border-color: var(--line); color: var(--ink-mute); background: var(--bg-2); cursor: default; }
.task.is-task-locked .lesson-type { color: var(--ink-mute); }
.task.is-task-locked .t b { color: var(--ink-mute); }
.task.is-task-locked .t span { color: var(--accent-deep); font-weight: 600; }
.lesson-check.locked { opacity: .5; cursor: not-allowed; }
.task-chevron { transition: transform .3s var(--ease-out), color .2s; color: var(--ink-mute); flex: 0 0 auto; }
.task.is-expanded .task-chevron { transform: rotate(180deg); }
.task-del, .task-edit { background: none; border: none; color: var(--ink-mute); cursor: pointer; flex: 0 0 auto; padding: .2rem; border-radius: 6px; }
.task-del .app-icon, .task-edit .app-icon { width: 16px; height: 16px; }
.task-del:hover { color: #b3402f; background: #f7ecea; }
.task-edit:hover { color: var(--accent); background: rgba(230,113,90,.12); }
.task-body { display: none; padding: 0 .8rem 1rem 3.4rem; }
.task.is-expanded .task-body { display: block; animation: taskOpen .25s var(--ease-out); }
@keyframes taskOpen { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
/* Al 75% de su ancho anterior (antes ocupaba el 100% del ancho de la tarea); el botón de pantalla
   completa (.task-fs) sigue disponible para verlo grande una vez iniciado. */
.task-video { position: relative; aspect-ratio: 16 / 9; background: var(--ink); border-radius: 12px; overflow: hidden; display: grid; place-items: center; width: 75%; }
.task-video-el { width: 100%; height: 100%; object-fit: contain; background: #000; }
/* Video Loom/YouTube: se incrusta al abrir la tarea (carga diferida). Mientras carga (frame vacío),
   un spinner tenue sobre el fondo oscuro; al aparecer el iframe, el :empty deja de aplicar y se va. */
.task-video--lazy:empty::after { content: ""; width: 30px; height: 30px; border: 3px solid rgba(255,255,255,.22); border-top-color: #fff; border-radius: 50%; animation: taskVideoSpin .8s linear infinite; }
@keyframes taskVideoSpin { to { transform: rotate(360deg); } }
.task-fs { position: absolute; top: .6rem; right: .6rem; width: 32px; height: 32px; border-radius: 8px; border: none; background: rgba(0,0,0,.45); color: #fff; cursor: pointer; display: grid; place-items: center; }
.task-fs .app-icon { width: 16px; height: 16px; }
.task-fs:hover { background: rgba(0,0,0,.7); }
.task-content { margin: .9rem 0; font-size: .85rem; color: var(--ink-soft); line-height: 1.55; }
.task-content p { margin: 0 0 .6rem; }
.task-content p:last-child { margin-bottom: 0; }
.task-content p.task-h { font-weight: 600; color: var(--ink); margin-top: .9rem; }
.task-content strong { color: var(--ink); font-weight: 600; }
.task-content ul { margin: .2rem 0 .7rem; padding-left: 1.1rem; }
.task-content li { margin: .15rem 0; }
/* Entrega del alumno (sube archivo / escribe respuesta; el coach la ve) */
.task-submit { margin: .9rem 0 .2rem; background: var(--accent-soft); border: 1px solid var(--accent); border-radius: 12px; padding: .8rem .9rem; }
.task-submit-h { display: flex; align-items: center; gap: .4rem; font-size: .78rem; font-weight: 600; color: var(--accent-deep); margin-bottom: .55rem; }
.task-submit-h .app-icon { width: 15px; height: 15px; }
.task-submit-empty { font-size: .82rem; color: var(--ink-soft); margin: 0 0 .6rem; }
.task-submit-current { display: flex; flex-direction: column; gap: .45rem; margin-bottom: .65rem; }
.task-submit-text { font-size: .85rem; color: var(--ink); font-style: italic; margin: 0; background: var(--paper); border: 1px solid var(--line-2); border-radius: 8px; padding: .5rem .65rem; }
.task-submit-meta { font-size: .72rem; color: var(--ink-mute); }
.task-submit-form { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.task-submit-file { display: inline-flex; align-items: center; gap: .35rem; font-size: .8rem; font-weight: 500; background: var(--paper); border: 1px dashed var(--accent); color: var(--accent-deep); border-radius: 8px; padding: .45rem .7rem; cursor: pointer; }
.task-submit-file .app-icon { width: 15px; height: 15px; }
.task-submit-area { flex: 1 1 220px; min-width: 180px; font: inherit; font-size: .85rem; border: 1px solid var(--line); border-radius: 8px; padding: .5rem .6rem; resize: vertical; background: var(--paper); color: var(--ink); }
.task-req { margin-top: .6rem; }
.task-req.coach, .task-req.video { background: var(--bg); border: 1px solid var(--line-2); border-radius: 10px; padding: .8rem .9rem; }
.task-req.coach p, .task-req.video p { font-size: .82rem; color: var(--ink-soft); line-height: 1.5; margin: 0 0 .6rem; }
.task-req p .app-icon { width: 15px; height: 15px; color: var(--accent); display: inline-block; vertical-align: -3px; margin-right: .35rem; }
.task-req-actions { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; }
/* 3.3 · Sesión estratégica ya agendada: botón atenuado, no invita a reagendar. */
.btn.is-scheduled { opacity: .7; cursor: default; color: #1f7a4d; border-color: rgba(31,122,77,.4); background: rgba(31,122,77,.08); }
.btn.is-scheduled:hover { background: rgba(31,122,77,.08); }
.task-status { font-size: .76rem; color: var(--ink-mute); }
.task-status.ok { color: #1f7a4d; }
.task-done-date { display: block; width: 100%; font-size: .72rem; color: var(--ink-mute); margin-top: .2rem; }
.task-done-date[hidden] { display: none; }
.task-add { width: 100%; margin-top: .6rem; padding: .6rem; border: 1px dashed var(--line); background: none; border-radius: 10px; color: var(--ink-soft); font-size: .82rem; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: .4rem; }
.task-add .app-icon { width: 15px; height: 15px; }
.task-add:hover { border-color: var(--accent); color: var(--accent); }
.modules-edit-note { display: flex; align-items: center; gap: .45rem; font-size: .82rem; color: var(--accent); background: #fbeee9; border: 1px solid #f3d6cc; border-radius: 10px; padding: .6rem var(--card-pad); margin-bottom: 1.1rem; }
.modules-edit-note .app-icon { width: 15px; height: 15px; flex: 0 0 auto; }
/* El texto va en un <span> (ver app.js): con el nota en flex, los nodos sueltos y los <b> serían flex
   items independientes y en móvil se parten en columnas ilegibles. Con 2+ líneas el ícono va arriba. */
.modules-edit-note { align-items: flex-start; }
.modules-edit-note > span { min-width: 0; }

/* ===== Pestañas emergentes de DOS COLUMNAS (28-jul-2026, aprobado por el cliente) =====
   Para los formularios largos: a la izquierda los datos, a la derecha lo que se consulta en lista
   (miembros, accesos) o la configuración secundaria (portada, audiencia). Así entran sin scroll. */
/* ⚠️ La tarjeta NO scrollea: scrollean sus columnas por dentro (28-jul-2026). Con la lista de miembros
   larga, la tarjeta crecía hasta el tope de 90vh y el botón de guardar quedaba bajo el pliegue, así
   que había que bajar para llegar a «Crear comunidad». Ahora la tarjeta es una columna flex acotada:
   cabecera y pie fijos, y el bloque del medio reparte lo que sobra. */
.app-modal-card.modal-split { max-width: 980px; width: min(980px, 96vw);
  display: flex; flex-direction: column; overflow: hidden; }
.modal-split > .manage-head, .modal-split > .modal-title, .modal-split > .app-modal-x { flex: 0 0 auto; }
/* `align-items: stretch` es lo que hace que la columna derecha llegue SIEMPRE hasta abajo, a ras de
   la línea de los botones, sin importar cuánto mida el formulario de la izquierda. */
.modal-split .msplit { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 370px); gap: 1.5rem;
  align-items: stretch; flex: 1 1 auto; min-height: 0; }
/* La columna izquierda scrollea sola si el formulario es más alto que la ventana (nunca la tarjeta). */
.modal-split .msplit > div:first-child { min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-right: .2rem; }
.msplit-foot { flex: 0 0 auto; display: flex; gap: .5rem; flex-wrap: wrap; margin-top: 1.2rem; padding-top: 1.1rem; border-top: 1px solid var(--line-2); }
/* El formulario de evento envuelve todo: tiene que ser flex igual, o el pie no se queda abajo. */
.modal-split form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* Variante A · con caja de color: cuando la derecha es una LISTA (miembros, accesos). */
.msplit-side { background: var(--bg); border: 1px solid var(--line-2); border-radius: 14px; padding: .9rem;
  display: flex; flex-direction: column; min-height: 0; }
.msplit-side > h4 { font-size: .84rem; font-weight: 600; margin-bottom: .1rem; }
.msplit-side .m-note { font-size: .74rem; }
/* Variante B · sin caja, solo una línea tenue: cuando la derecha son CAMPOS (evento). */
.msplit-line { border-left: 1px solid var(--line-2); padding-left: 1.5rem; display: flex; flex-direction: column; min-height: 0; }
.msplit-line h4 { font-size: .84rem; font-weight: 600; }
.msplit-hr { border: 0; border-top: 1px solid var(--line-2); margin: 1rem 0; }
/* `flex: 1 1 auto` + `min-height: 0` = la lista ocupa lo que sobra y scrollea ella sola. */
.msplit-list { margin-top: .6rem; flex: 1 1 auto; min-height: 90px; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: .3rem; padding-right: .2rem; }
/* Pertenecer o no NO tiñe la fila: lo único que cambia es el botón (pedido del cliente). */
.msplit-list .manage-row { padding: .78rem .85rem; gap: .75rem; border-radius: 13px; background: var(--paper); border: 1px solid var(--line-2); }
/* Lo que SÍ tiñe la fila es la categoría: el EQUIPO (coach/closer/admin/CEO) lleva el mismo degradado
   negro→coral que su tarjeta en el directorio de Miembros (.member-card--dark) y que su ficha
   emergente (.profile-modal-dark). Los alumnos se quedan en blanco (29-jul-2026). */
.msplit-list .manage-row.is-team { background: var(--grad-portada); border-color: transparent; color: var(--paper); }
.msplit-list .manage-row.is-team b { color: var(--paper); }
.msplit-list .manage-row.is-team .m-note { color: rgba(244,241,234,.72); }
/* Si el usuario tiene foto, su `background-image` va en línea y le gana a esta regla: la foto se ve
   igual y este color solo pinta el círculo de la inicial. */
.msplit-list .manage-row.is-team .side-avatar { background: rgba(244,241,234,.2); color: var(--paper); }
/* Los dos botones se adaptan al fondo oscuro conservando su semántica: «Agregar» sigue siendo el
   sólido (ahora en blanco, porque el coral cae justo sobre el tramo coral del degradado y se perdía)
   y «Quitar» sigue siendo el discreto, ahora traslúcido sobre el degradado. */
.msplit-list .manage-row.is-team .btn--coral { background: var(--paper); color: var(--ink); }
.msplit-list .manage-row.is-team .btn--coral:hover { background: #fff; box-shadow: 0 0 0 2px rgba(244,241,234,.35); }
.msplit-list .manage-row.is-team .btn--inbox { background: rgba(244,241,234,.16); color: var(--paper); border-color: rgba(244,241,234,.38); }
.msplit-list .manage-row.is-team .btn--inbox:hover { background: rgba(244,241,234,.26); border-color: rgba(244,241,234,.65); color: var(--paper); }
.msplit-sub { font-size: .72rem; font-weight: 600; color: var(--ink-mute); margin: .7rem 0 -.2rem; }
.msplit-sub:first-child { margin-top: .1rem; }
/* En una columna de 310px el nombre se partía en dos renglones cuando la fila llevaba la píldora de
   upsell. El nombre se queda en UNA línea (con puntos suspensivos si no cabe) y las acciones se
   apilan a la derecha, que es más ordenado que dejarlas envolver. */
.msplit-list .manage-row > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msplit-list .plan-row-actions { flex-direction: column; align-items: flex-end; gap: .3rem; flex: 0 0 auto; }
/* Filas compactas: con el avatar de 38px cada miembro medía ~85px y nueve llenaban la pantalla. */
.msplit-list .side-avatar { width: 38px; height: 38px; font-size: 14px !important; }
/* Nombre y subtítulo con puntos suspensivos: sin esto se cortaban a mitad de palabra ("Carmen Di
   Girolan"), que se lee como un error y no como un recorte. */
.msplit-list .manage-row b, .msplit-list .manage-row .m-note { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ⚠️ El `!important` NO es decorativo: `.app-body * { font-size: 14px !important }` (línea ~2307)
   le gana a cualquier regla sin !important, por específica que sea. Sin esto, el nombre y el
   subtítulo salían los dos a 14px — de ahí que el nombre no cupiera y las dos líneas se vieran
   apretadas una contra otra. Con tamaños propios y algo de aire, cada ficha respira (28-jul-2026). */
/* El nombre va al MISMO tamaño que el resto de los textos de la pestaña (14px, el del portal) y el
   subtexto conserva su proporción respecto al nombre: 11.5/13 ≈ 0,885 → 14 × 0,885 = 12,4px. */
.msplit-list .manage-row b { font-size: 14px !important; line-height: 1.35; }
.msplit-list .manage-row .m-note { font-size: 12.4px !important; line-height: 1.35; margin-top: .14rem; }
.msplit-sub { font-size: 12px !important; }
/* Nada de cursivas dentro de las pestañas emergentes (regla del cliente, 28-jul-2026): el subtexto
   bajo el nombre —y cualquier otra nota de un modal— va en redonda. La cursiva se reserva para las
   piezas de marca (la inicial del avatar, los números de módulo) y para las CITAS textuales
   (el motivo de una pausa, la respuesta de una entrega), que sí son otra voz. */
.app-modal-card .m-note { font-style: normal; }

/* La portada aprovecha el aire que dejó la lista acotada: cuadro más grande y botón debajo, no al
   lado (el cliente lo autorizó expresamente para cuadrar los espacios). */
.modal-split .evt-cover-upload { flex-direction: column; align-items: stretch; gap: .55rem; }
.modal-split .evt-cover-preview { width: 100%; height: 150px; }
.modal-split .evt-cover-up-actions { flex-direction: row; flex-wrap: wrap; align-items: center; }
/* Botón "ya está adentro": del color de la caja, para distinguirlo del coral de "agregar". */
.btn--inbox { background: var(--bg); color: var(--ink-soft); border: 1px solid var(--line); }
.btn--inbox:hover { border-color: var(--ink-mute); color: var(--ink); }
/* En pantallas chicas las dos columnas se apilan: la derecha pasa abajo, sin caja lateral ni línea. */
@media (max-width: 860px) {
  .modal-split .msplit { grid-template-columns: minmax(0, 1fr); }
  .msplit-line { border-left: 0; padding-left: 0; border-top: 1px solid var(--line-2); padding-top: 1.1rem; }
  .msplit-list { max-height: 320px; }
}

/* ===== Modal grande de creación de tarea ===== */
/* Los anchos suben en la misma proporción que el modal base (28-jul-2026): 680 → 820. */
.app-modal-card.modal-wide { max-width: 820px; width: min(820px, 94vw); }
/* Editor de módulo: ya era el más ancho (900); sube a 1000, tope razonable para no partir la lectura. */
.app-modal-card.modal-mod-edit { max-width: 1000px; width: min(1000px, 96vw); }
/* Gestionar miembro: 500 → 640. Es de los que más lo pedían (planes + comunidades + rol + coach). */
.app-modal-card.manage-modal { max-width: 640px; width: min(640px, 94vw); }
/* ---- Bienvenida (ver .welcome-card más arriba): un poco más ancho que el modal por defecto
   (440px) para que la primera oración del mensaje quepa en una sola línea. ---- */
.app-modal-card.welcome-modal { max-width: 580px; width: min(580px, 94vw); }
/* ---- Panel de upsell (miembro Premium · "+") ---- */
.app-modal-card.upsell-modal { max-width: 660px; width: min(660px, 94vw); padding: 0; overflow: hidden; }
.upsell-panel { position: relative; }
.upsell-hero { background: var(--grad-portada); color: var(--paper); padding: 1.9rem 1.9rem 1.6rem; }
.upsell-badge { display: inline-flex; align-items: center; gap: .35rem; font-size: .68rem; font-weight: 600; background: rgba(244,241,234,.18); padding: .3rem .7rem; border-radius: 100px; margin-bottom: .9rem; }
.upsell-badge .app-icon { width: 13px; height: 13px; }
/* Título del upsell con la MISMA tipografía que "Diste el primer paso" (.welcome-card h3): Fraunces
   liviana, pero en blanco y en una sola línea (tamaño reducido para que quepa completo). */
.upsell-hero h2 { font-family: "Fraunces", Georgia, "Times New Roman", serif !important; font-weight: 300 !important; font-size: clamp(1.05rem, 4.6vw, 1.6rem) !important; line-height: 1.1; letter-spacing: -0.02em; color: var(--paper); white-space: nowrap; }
.upsell-lead { font-size: .9rem; color: rgba(244,241,234,.84); margin-top: .65rem; }
.upsell-lead b { color: var(--paper); }
.upsell-body { padding: 1.4rem 1.9rem 0; }
.upsell-intro { font-size: 1rem; font-weight: 600; color: var(--ink); line-height: 1.4; margin-bottom: 1rem; }
.upsell-points { display: grid; gap: .55rem; margin: 1.1rem 0; }
.upsell-points li { display: flex; gap: .5rem; font-size: .88rem; color: var(--ink-soft); line-height: 1.4; }
.upsell-points .app-icon { width: 17px; height: 17px; color: #1f7a4d; flex: 0 0 auto; margin-top: 1px; }
.upsell-tease { font-size: .9rem; color: var(--ink); }
.upsell-cta { margin-top: 1.3rem; padding: 1.2rem 1.9rem 1.9rem; border-top: 1px solid var(--line-2); text-align: center; }
.upsell-cta p { font-size: .88rem; color: var(--ink-soft); margin-bottom: .75rem; }
.upsell-cta .btn { width: 100%; max-width: 300px; }
.upsell-confirm { text-align: center; padding: 2.2rem 1.8rem 2rem; position: relative; }
.upsell-confirm .upsell-ok { background: #e2f4ea; color: #1f7a4d; border-color: #c6e7d4; }
.upsell-confirm h2 { font-family: var(--serif); font-weight: 300; font-size: 1.5rem; margin-top: 1rem; }
.upsell-confirm p { color: var(--ink-soft); margin: .7rem auto 1.3rem; max-width: 40ch; }
.upsell-confirm .btn { min-width: 200px; }
/* el "+" en modo upsell se distingue con el coral de marca */
.plan-tab--upsell { border-style: solid; border-color: var(--accent); color: var(--accent-deep); background: var(--accent-soft); }
.plan-tab--upsell:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
.task-form .field { margin-bottom: 1rem; }
.task-form textarea { width: 100%; resize: vertical; font: inherit; }
.task-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.task-box { background: var(--bg); border: 1px solid var(--line-2); border-radius: 12px; padding: .8rem .9rem; }
.task-box > label { display: flex; align-items: center; gap: .35rem; }
.task-box .app-icon { width: 15px; height: 15px; color: var(--accent); }
.field-hint { display: block; font-size: .72rem; color: var(--ink-mute); margin-top: .4rem; }
.task-form-files { display: flex; flex-direction: column; gap: .4rem; margin-top: .6rem; }
.task-form-file { display: flex; align-items: center; gap: .4rem; font-size: .76rem; background: var(--paper); border: 1px solid var(--line-2); border-radius: 8px; padding: .3rem .5rem; }
.task-form-file .app-icon { width: 14px; height: 14px; }
.task-form-file .tff-img { width: 22px; height: 22px; border-radius: 5px; background-size: cover; background-position: center; flex: 0 0 auto; }
.task-form-file button { margin-left: auto; background: none; border: none; cursor: pointer; transform: rotate(45deg); color: var(--ink-mute); display: grid; place-items: center; }
.task-form-file button .app-icon { width: 14px; height: 14px; }
.task-type-opts { display: flex; flex-direction: column; gap: .5rem; }
/* Solo el borde coral al pasar el cursor; sin animación de fondo/tamaño (pedido del cliente). */
.task-type-opt { display: flex; align-items: flex-start; gap: .6rem; border: 1px solid var(--line-2); border-radius: 10px; padding: .7rem .8rem; cursor: pointer; transition: border-color .15s; }
.task-type-opt:hover { border-color: var(--accent); }
/* El radio debe quedar como CÍRCULO nativo. `.field input` lo estiraba a ancho completo (601px) con
   fondo, borde y transición de "campo de texto" → eso cambiaba tamaños y hacía parpadear el texto al
   cambiar de opción. Se revierte a su tamaño natural, sin animación: el círculo indica la selección. */
.task-type-opt input[type="radio"] { width: auto; flex: 0 0 auto; margin-top: .2rem; padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none; transition: none; }
.task-type-opt input[type="radio"]:focus { outline: none; background: none; }
.task-type-opt b { display: flex; align-items: center; gap: .35rem; font-size: .85rem; font-weight: 500; }
.task-type-opt b .app-icon { width: 15px; height: 15px; color: var(--accent); }
.task-type-opt small { display: block; font-size: .75rem; color: var(--ink-mute); margin-top: .15rem; }

/* ===== Adjuntos en la tarea (vista) ===== */
.task-attach { display: flex; flex-direction: column; gap: .8rem; margin: .9rem 0; }
.task-attach-block { background: var(--bg); border: 1px solid var(--line-2); border-radius: 10px; padding: .7rem .8rem; }
.task-attach-h { display: flex; align-items: center; gap: .35rem; font-size: .74rem; font-weight: 600; color: var(--ink-soft); margin-bottom: .5rem; }
.task-attach-h .app-icon { width: 14px; height: 14px; color: var(--accent); }
.task-link { display: block; font-size: .82rem; color: var(--accent-deep); word-break: break-all; padding: .15rem 0; }
.task-link:hover { text-decoration: underline; }
/* Documentos con vista previa embebida + descarga */
.task-docs { display: flex; flex-direction: column; gap: .55rem; }
.task-doc { background: var(--paper); border: 1px solid var(--line-2); border-radius: 10px; overflow: hidden; }
.task-doc-row { display: flex; align-items: center; gap: .6rem; padding: .55rem .65rem; flex-wrap: wrap; }
.task-doc-ico { width: 30px; height: 30px; flex: 0 0 auto; border-radius: 8px; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent-deep); }
.task-doc-ico .app-icon { width: 16px; height: 16px; }
.task-doc-name { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; flex: 1 1 auto; }
.task-doc-name b { font-size: .84rem; color: var(--ink); font-weight: 600; }
.task-doc-name small { font-size: .7rem; color: var(--ink-mute); }
.task-doc-actions { display: flex; align-items: center; gap: .35rem; flex: 0 0 auto; flex-wrap: wrap; }
.task-doc-btn { display: inline-flex; align-items: center; gap: .3rem; font-size: .76rem; font-weight: 500; border: 1px solid var(--line); border-radius: 8px; padding: .35rem .55rem; background: var(--paper); color: var(--ink-soft); cursor: pointer; white-space: nowrap; transition: background .15s, color .15s, border-color .15s; }
.task-doc-btn .app-icon { width: 14px; height: 14px; }
.task-doc-btn:hover { background: var(--accent-soft); color: var(--accent-deep); border-color: var(--accent); }
.task-doc-btn.is-open { background: var(--accent); color: #fff; border-color: var(--accent); }
.task-doc-btn.ghost { color: var(--ink-mute); }
.task-doc-frame { border-top: 1px solid var(--line-2); background: var(--ink); }
.task-doc-frame iframe { display: block; width: 100%; height: 460px; border: 0; }
.lesson-check.readonly { cursor: default; }
iframe.task-video-el { width: 100%; height: 100%; border: 0; }

/* ===== Seguimiento Clientes (antes "Panel de coach") ===== */
.coach-dash { margin-bottom: 1.6rem; padding: 1.5rem 1.6rem; }
.coach-dash-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.1rem; }
/* Título en la misma tipografía (Inter) que el subtexto, no serif */
.coach-dash-head h2, .coach-dash-h2 { font-family: var(--sans); font-weight: 600; font-size: 1rem; letter-spacing: 0; color: var(--ink); }
.coach-dash-head p { font-size: .82rem; color: var(--ink-mute); margin: .25rem 0 0; }
.seg-filters { display: flex; gap: .6rem; flex-wrap: wrap; }
.seg-filter { display: flex; flex-direction: column; gap: .25rem; font-size: .68rem; color: var(--ink-mute); font-weight: 600; }
.seg-filter select { font: inherit; font-size: .82rem; font-weight: 400; text-transform: none; letter-spacing: 0; padding: .4rem 1.8rem .4rem .7rem; border: 1px solid var(--line); border-radius: 100px; background: var(--paper); color: var(--ink); cursor: pointer; appearance: none; -webkit-appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237a736b' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .6rem center; background-size: 12px; }
/* Scroll horizontal en móvil (mismo patrón que .mstu-scroll/.mstu-table): en vez de comprimir las
   columnas hasta volverlas ilegibles, la tabla mantiene un ancho mínimo y el wrapper scrollea. */
.metric-table-scroll, .track-table-scroll, .coachm-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* Tabla de métricas (bordes contenidos con margen y esquinas redondeadas) */
.metric-table { border: 1px solid var(--line-2); border-radius: 12px; overflow: hidden; min-width: 560px; }
.metric-row { display: grid; grid-template-columns: minmax(150px, 1.6fr) 1fr 46px 18px; align-items: center; gap: 1rem; padding: .72rem var(--card-pad); border-bottom: 1px solid var(--line-2); cursor: pointer; transition: background .15s; }
.metric-row:hover { background: var(--bg); }
.metric-row.is-open { background: var(--bg); }
.metric-name { font-size: .84rem; font-weight: 450; color: var(--ink); line-height: 1.3; }
.metric-bar { height: 8px; border-radius: 100px; background: var(--bg-3); overflow: hidden; }
.metric-bar i { display: block; height: 100%; border-radius: 100px; background: var(--grad-portada); }
/* ===== Bitácora · piezas nuevas ===== */
/* Tarjeta de datos CLARA (Activación, Finalización, Embudo, Mezcla). Distinta de .metrics-chart-card,
   que es OSCURA (--grad-portada) y reservada para el hero y los gráficos SVG diseñados sobre negro.
   Aquí el subtítulo .metrics-chart-sub —pensado en claro para tarjeta oscura— se reescribe a tinta. */
/* Ritmo vertical de la página (1.4rem entre bloques): el hero y la tarjeta de recorrido son cards
   SUELTAS (no van dentro de un grid que ya da el gap), así que necesitan su propio margen inferior. */
.bit-hero { margin-bottom: 1.4rem; }
.bit-chart-full { margin-bottom: 1.4rem; }
/* Listas accionables (estancados, sin arrancar, sin coach, sin plan): con ~300 alumnos pueden tener
   muchas filas. La caja mantiene un alto máximo y hace scroll interno, sin desbordar la página. */
.flag-scroll { max-height: 340px; overflow-y: auto; margin: 0 -.2rem; padding: 0 .2rem; }
.flag-scroll::-webkit-scrollbar { width: 5px; }
.flag-scroll::-webkit-scrollbar-thumb { background: rgba(28,26,24,.16); border-radius: 4px; }
/* Las bit-panel son .app-card, que NO trae padding (cada tarjeta lo pone explícito con --card-pad).
   Sin esto el título y el subtítulo tocaban el borde, mientras el contenido de abajo (número, embudo,
   barras) traía su propio --card-pad y quedaba más adentro. Se le da el mismo padding que las demás
   tarjetas de la página y se quita el margen horizontal DOBLE de los hijos que ya lo traían. */
.bit-panel { display: flex; flex-direction: column; padding: 1.3rem var(--card-pad) 1.4rem; }
.bit-panel .bit-big { padding-left: 0; padding-right: 0; }
.bit-panel .bit-funnel { padding-left: 0; padding-right: 0; }
.bit-panel .metric-table { min-width: 0; }  /* en media tarjeta la tabla no necesita el mínimo de 560px */
.bit-panel h3 { font-size: 1.02rem; font-weight: 600; color: var(--ink); }
/* El subtítulo .metrics-chart-sub está pensado en color CLARO para las tarjetas oscuras; en las
   tarjetas CLARAS (bit-panel y flag-cards) se reescribe a tinta o quedaría ilegible sobre el crema. */
.bit-panel .metrics-chart-sub, .metrics-flag-card .metrics-chart-sub { color: var(--ink-soft); min-height: 0; margin: .2rem 0 .8rem; }
/* Hero de 5 tiles a lo ancho (en la tarjeta oscura de cabecera). */
.bit-hero .mhero-stats { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 880px) { .bit-hero .mhero-stats { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) { .bit-hero .mhero-stats { grid-template-columns: repeat(2, 1fr); } }
/* Fila de barra SIN desplegable (finalización por plan, mezcla): 3 columnas, no 4 — sin cursor. */
.metric-row.is-static { grid-template-columns: minmax(120px, 1.6fr) 1fr 52px; cursor: default; }
.metric-row.is-static:hover { background: none; }
.metric-name .hint { color: var(--ink-mute); font-weight: 400; font-size: .74rem; }
.metric-val { font-variant-numeric: tabular-nums; }
/* Número grande de una métrica destacada (activación). */
.bit-big { display: flex; align-items: baseline; gap: .7rem; padding: 1rem var(--card-pad) 1.2rem; }
.bit-big-n { font-size: 2.6rem; font-weight: 600; line-height: 1; color: var(--accent-deep); }
.bit-big-l { font-size: .86rem; color: var(--ink-soft); }
/* Embudo de 3 pasos (upsell). */
.bit-funnel { display: flex; align-items: stretch; gap: .5rem; padding: 1rem var(--card-pad); }
.bit-funnel-step { flex: 1 1 0; min-width: 0; text-align: center; background: var(--bg); border: 1px solid var(--line-2); border-radius: 12px; padding: .9rem .5rem; }
.bit-funnel-step b { display: block; font-size: 1.7rem; font-weight: 600; line-height: 1; color: var(--ink); }
.bit-funnel-step span { display: block; margin-top: .3rem; font-size: .72rem; color: var(--ink-mute); }
.bit-funnel-step.is-win { background: var(--accent-soft); border-color: rgba(242,107,94,.3); }
.bit-funnel-step.is-win b { color: var(--accent-deep); }
.bit-funnel-arrow { width: 16px; height: 16px; flex: 0 0 auto; align-self: center; color: var(--ink-mute); }
/* Rojo de riesgo en tiles de la cabecera y en la tabla por coach. */
.mhero-stat.is-risk .n { color: #ff9d93; }
.coachm-stat b.is-risk { color: #E5484D; }
@media (max-width: 560px) { .bit-funnel { flex-direction: column; } .bit-funnel-arrow { transform: rotate(90deg); } }
.metric-val { font-size: .82rem; font-weight: 600; color: var(--ink); text-align: right; font-variant-numeric: tabular-nums; }
.metric-chevron { width: 16px; height: 16px; color: var(--ink-mute); transition: transform .25s; justify-self: end; }
.metric-row.is-open .metric-chevron { transform: rotate(180deg); }
/* Desplegable: alumnos que más se demoran en la etapa */
.metric-students { border-bottom: 1px solid var(--line-2); background: var(--bg); padding: .2rem var(--card-pad) 1rem; animation: viewIn .25s var(--ease-out); }
.metric-row:last-child { border-bottom: none; }
.metric-row.is-open:last-child { border-bottom: 1px solid var(--line-2); }
.metric-students:last-child { border-bottom: none; }
.mstu-empty { font-size: .82rem; color: var(--ink-mute); padding: .9rem .2rem .3rem; margin: 0; }
.mstu-scroll { overflow-x: auto; padding-top: .4rem; }
.mstu-table { min-width: 900px; display: flex; flex-direction: column; }
.mstu-row { display: grid; grid-template-columns: 1.7fr .9fr 1.1fr 1.1fr .9fr .9fr .85fr 1.5fr; gap: .7rem; align-items: center; padding: .55rem 0; border-top: 1px solid var(--line-2); font-size: .8rem; color: var(--ink-soft); }
.mstu-head { border-top: none; font-size: .66rem; color: var(--ink-mute); font-weight: 600; }
.mstu-alumno { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.mstu-alumno b { font-weight: 500; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mstu-av { width: 30px; height: 30px; flex: 0 0 auto; font-size: .72rem; }
.mstu-plan { color: var(--ink-mute); }
.mstu-pct { font-weight: 600; color: var(--ink); }
.mstu-row small { color: var(--ink-mute); margin-left: .35rem; }
.mstu-days { color: var(--accent-deep); font-variant-numeric: tabular-nums; }
.mstu-act { font-size: .7rem; font-weight: 600; padding: .2rem .55rem; border-radius: 100px; display: inline-block; line-height: 1.35; }
.mstu-act.warn { background: #fbe4e0; color: #b3402f; }
.mstu-act.up { background: #f7ecd6; color: #8a5a00; }
.mstu-act.ok { background: var(--bg-2); color: var(--ink-soft); }
.coach-dash-note { font-size: .74rem; color: var(--ink-mute); margin: 1rem 0 0; }

/* Tabla de seguimiento de alumnos (mismos márgenes que "Métricas de avance": card con padding + tabla con borde/radio contenidos) */
.track-card { padding: 1.5rem 1.6rem; margin-bottom: 1.6rem; }
.track-title { font-family: var(--serif); font-weight: 400; font-size: 1.15rem; letter-spacing: -.01em; display: flex; align-items: center; gap: .55rem; margin: 0 0 1rem; }
.track-head-row { display: flex; align-items: center; justify-content: space-between; gap: .8rem 1.2rem; flex-wrap: wrap; margin-bottom: 1rem; }
.track-head-row .track-title { margin: 0; }
.track-table { display: flex; flex-direction: column; border: 1px solid var(--line-2); border-radius: 12px; overflow: hidden; min-width: 680px; }
.track-row { display: grid; grid-template-columns: 1.6fr 1fr 1.2fr 1fr .9fr; align-items: center; gap: .8rem; padding: .72rem var(--card-pad); border-top: 1px solid var(--line-2); cursor: pointer; transition: background .15s; }
.track-row:hover:not(.track-head) { background: var(--bg); }
.track-head { cursor: default; border-top: none; font-size: .7rem; color: var(--ink-mute); font-weight: 600; }
.track-head:hover { background: none; }
.track-cell { min-width: 0; font-size: .86rem; }
.track-alumno { display: flex; align-items: center; gap: .6rem; }
.track-alumno b { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.track-av { width: 34px; height: 34px; flex: 0 0 auto; font-size: .8rem; }
.track-plan { color: var(--ink-soft); }
.track-avance { display: flex; align-items: center; gap: .5rem; }
.track-bar { flex: 1; height: 8px; border-radius: 100px; background: var(--bg-3); overflow: hidden; min-width: 50px; }
.track-bar i { display: block; height: 100%; border-radius: 100px; background: var(--grad-coral); }
.track-avance span { font-size: .8rem; font-weight: 600; flex: 0 0 auto; }
.track-conn { color: var(--ink-mute); }
.track-conn .lc-recent { color: #1f7a4d; font-weight: 600; }
.track-conn .lc-stale { color: var(--ink-soft); }
.track-estado { display: flex; align-items: center; justify-content: space-between; gap: .4rem; }
.estado-badge { font-size: .72rem; font-weight: 600; padding: .22rem .6rem; border-radius: 100px; }
.estado-badge.activo { background: #e2f4ea; color: #1f7a4d; }
.estado-badge.riesgo { background: #fbe4e0; color: #b3402f; }
.estado-badge.nuevo { background: #f7ecd6; color: #8a5a00; }
/* Estado v2 por atraso (27-jul-2026): al día / atención / crítico / en pausa / finalizado. */
.estado-badge.aldia { background: #e2f4ea; color: #1f7a4d; }
.estado-badge.atencion { background: #f7ecd6; color: #8a5a00; }
.estado-badge.critico { background: #f3d0c9; color: #7c2417; }
.estado-badge.pausa { background: #ece7dd; color: #6b6357; }
.estado-badge.fin { background: #e6eaf5; color: #33508f; }
.estado-wrap { display: inline-flex; flex-direction: column; gap: 2px; align-items: flex-start; min-width: 0; }
.estado-sub { font-size: .66rem; font-weight: 600; color: #b3402f; white-space: nowrap; }
.track-chevron { width: 16px; height: 16px; color: var(--ink-mute); transition: transform .25s; flex: 0 0 auto; }
.track-row.is-open .track-chevron { transform: rotate(180deg); }
.track-detail { padding: .2rem var(--card-pad) 1rem; border-top: 1px dashed var(--line-2); animation: viewIn .25s var(--ease-out); }
.track-detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; padding-top: 1rem; }
.track-metrics, .track-sessions { min-width: 0; }
.tm-row { display: flex; justify-content: space-between; gap: .8rem; padding: .4rem 0; border-bottom: 1px solid var(--line-2); font-size: .84rem; }
.tm-row span { color: var(--ink-mute); }
.tm-row b { font-weight: 500; text-align: right; }
.verdict.activo { color: #1f7a4d; }
.verdict.riesgo { color: #b3402f; }
.sess-mark-row { display: flex; flex-direction: column; gap: .5rem; padding: .7rem 0; border-bottom: 1px solid var(--line-2); }
.sess-mark-info { display: flex; justify-content: space-between; align-items: baseline; gap: .6rem; }
.sess-mark-row .sess-name { font-size: .84rem; color: var(--ink-soft); }
.sess-mark-tally { font-size: .8rem; color: var(--ink-mute); flex: 0 0 auto; }
.sess-mark-tally b { color: var(--ink); font-size: .92rem; }
/* Círculos numerados: gris con número crema; coral al marcarlos */
.sess-dots { display: flex; flex-wrap: wrap; gap: .42rem; }
.sess-dot { width: 30px; height: 30px; border-radius: 50%; border: none; background: var(--ink-mute); color: var(--paper); font: 600 .78rem/1 var(--sans); cursor: pointer; display: grid; place-items: center; transition: background .15s, transform .1s; }
.sess-dot:hover { transform: scale(1.08); }
.sess-dot.is-on { background: var(--accent); color: #fff; }
/* Marcador de Onboarding: check (realizada) / cruz (no realizada) */
.onb-mark-row { display: flex; align-items: center; justify-content: space-between; gap: .6rem; padding: .55rem 0 .2rem; }
.onb-mark-q { font-size: .84rem; color: var(--ink-soft); }
.onb-mark-btns { display: inline-flex; gap: .35rem; flex: 0 0 auto; }
.onb-mark { width: 36px; height: 30px; border-radius: 9px; border: 1px solid var(--line-2); background: var(--paper); color: var(--ink-mute); font-size: .95rem; font-weight: 700; cursor: pointer; display: grid; place-items: center; transition: background .12s, border-color .12s, color .12s; }
.onb-mark:hover { border-color: var(--ink-soft); }
.onb-mark--yes.is-on { background: #e2f4ea; border-color: #1f7a4d; color: #1f7a4d; }
.onb-mark--no.is-on { background: var(--accent-soft); border-color: var(--accent-deep); color: var(--accent-deep); }
/* Solo lectura: cuando el usuario no es el coach asignado del alumno (no puede editar registros) */
.sess-dot.is-readonly, .onb-mark.is-readonly { cursor: default; }
.sess-dot.is-readonly:hover { transform: none; }
.onb-mark.is-readonly:hover { border-color: var(--line-2); }
.onb-mark.is-readonly:not(.is-on) { opacity: .5; }
.track-readonly-note { margin-top: .7rem; font-size: .72rem; color: var(--ink-mute); font-style: italic; }
.track-detail-actions { margin-top: 1rem; display: flex; gap: .6rem; flex-wrap: wrap; }
.track-detail-actions .app-icon { width: 15px; height: 15px; }

/* Tarjeta de sesiones en el perfil (negro/coral degradado) */
.sessions-card { padding: 0 !important; overflow: hidden; }
.sessions-head { background: var(--grad-portada); color: var(--paper); padding: .9rem 1.1rem; display: flex; justify-content: space-between; align-items: baseline; }
.sessions-head-label { font-size: .82rem; font-weight: 500; letter-spacing: .01em; }
.sessions-head-count { font-family: var(--serif); font-size: 1.5rem; line-height: 1; }
.sessions-head-count small { font-size: .9rem; opacity: .8; }
.sessions-list { padding: .8rem var(--card-pad) 1rem; display: flex; flex-direction: column; gap: .7rem; }
.sess-row { display: grid; grid-template-columns: 1fr auto; gap: .15rem .6rem; align-items: center; }
.sess-row .sess-name { font-size: .82rem; color: var(--ink-soft); }
.sess-row .sess-count { font-size: .8rem; font-weight: 600; color: var(--ink); }
.sess-bar { grid-column: 1 / -1; height: 6px; border-radius: 100px; background: var(--bg-3); overflow: hidden; }
.sess-bar i { display: block; height: 100%; border-radius: 100px; background: var(--grad-coral); }
.seg-count { font-family: var(--sans); font-size: .72rem; font-weight: 600; color: var(--accent-deep); background: var(--bg-2, #efe7e0); border-radius: 100px; padding: .12rem .5rem; }
.seg-back { margin-bottom: 1rem; }
.seg-student-hero { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; padding: var(--card-pad); }
.seg-student-av-lg { width: 58px; height: 58px; flex: 0 0 auto; font-size: 1.1rem; }
.seg-student-hero-id { flex: 1; min-width: 0; }
/* Nombre del alumno en el hero de Seguimiento: misma tipografía que el subtexto ("Alumno · Plan
   Premium"), que hereda var(--sans) — antes usaba var(--serif) (Raleway). En negrita para
   distinguirlo (pedido del cliente, 13-jul-2026). */
.seg-student-hero-id h2 { font-family: var(--sans); font-weight: 700; font-size: 1.45rem; letter-spacing: -.01em; }
.seg-student-hero-id span { font-size: .8rem; color: var(--ink-mute); }
.seg-student-note { display: flex; align-items: center; gap: .4rem; font-size: .82rem; color: var(--ink-soft); background: #fbeee9; border: 1px solid #f3d6cc; border-radius: 10px; padding: .55rem .8rem; margin-bottom: 1.2rem; }
.seg-student-note .app-icon { width: 15px; height: 15px; color: var(--accent); flex: 0 0 auto; }
.seg-plan-block + .seg-plan-block { margin-top: 1.4rem; }

/* ===== Conversación finalizada (subtexto centrado) ===== */
.conv-ended-note { display: flex; align-items: center; justify-content: center; gap: .4rem; text-align: center; font-size: .8rem; color: var(--ink-mute); margin: 1.1rem auto .3rem; padding: .3rem .9rem; }
.conv-ended-note .app-icon { width: 14px; height: 14px; }

/* ===== Nav badge (Mensajes) ===== */
.nav-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 4px; border-radius: 100px; background: var(--accent); color: var(--paper); font-size: .64rem; font-weight: 700; line-height: 1; margin-left: auto; }
.side-link .nav-badge { flex-shrink: 0; }

/* ===== Burbuja de acceso rápido a Mensajes ===== */
.msg-fab { position: fixed; right: 5.4rem; bottom: 1.4rem; width: 52px; height: 52px; border-radius: 50%; border: none; padding: 0; cursor: pointer; z-index: 60;
  background: var(--ink); color: var(--paper); box-shadow: 0 8px 22px rgba(28,26,24,.28); display: grid; place-items: center; transition: transform .18s var(--ease-out), box-shadow .18s; }
.msg-fab:hover { transform: translateY(-2px) scale(1.04); box-shadow: 0 12px 30px rgba(28,26,24,.38); }
.msg-fab.is-open { transform: scale(.92); }
.msg-fab-ico { width: 22px; height: 22px; }
/* Badge de no leídos en la burbuja — idéntico al de la campana (.icon-btn .dot) */
.msg-fab-badge { position: absolute; top: -4px; right: -4px; min-width: 19px; height: 19px; padding: 0 5px; border-radius: 100px;
  background: var(--accent); color: #fff; border: 2px solid var(--paper);
  font-size: .68rem; font-weight: 700; line-height: 1; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 5px rgba(28,26,24,.35); }
.msg-fab-badge[hidden] { display: none; }
/* Panel con gradiente blanco-coral muy suave */
/* top:5.5rem es un piso fijo por debajo del topbar (sticky, ~4.6rem de alto, z-index 70 > 61 del panel):
   evita que el panel crezca por encima del topbar y quede tapado en ventanas no maximizadas, donde
   min(520px, 100vh - 8rem) no dejaba suficiente margen. Con top+bottom fijados, la altura se autoajusta
   al espacio real disponible; max-height conserva el tamaño de tarjeta flotante en pantallas altas. */
/* Anclada ABAJO, no arriba. Antes tenía top + bottom + max-height a la vez: al toparse con el
   máximo, la caja se pegaba al top y dejaba un hueco enorme sobre la burbuja en pantallas altas.
   La protección contra el topbar (sticky, z-index 70) sigue: en vez de `top`, el alto máximo
   descuenta esos 5.5rem, así nunca llega a taparse. NO volver a poner `top` acá. */
/* Alto FIJO, no máximo: con `max-height` la caja se encogía hasta el contenido y con dos
   conversaciones se veía mucho más chica que con diez. El `max(320px, …)` es un suelo para pantallas
   muy bajas, donde el descuento del topbar daría un valor negativo. */
.msg-mini { position: fixed; right: 5.4rem; bottom: 5.35rem; z-index: 61; width: min(360px, calc(100vw - 2rem)); height: min(620px, max(320px, calc(100vh - 10.85rem)));
  background: linear-gradient(180deg, #ffffff 0%, #fff6f5 55%, #fce9e7 100%); border: 1px solid rgba(229,107,94,.22); border-radius: 20px; box-shadow: 0 20px 55px rgba(28,26,24,.22), 0 4px 16px rgba(229,107,94,.1); overflow: hidden; display: flex; flex-direction: column; animation: nubiaPop .22s var(--ease-out); }
/* Encabezado sólido oscuro */
.msg-mini-head { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; padding: .8rem 1rem; gap: .5rem; background: #1C1A18; border-bottom: 1px solid rgba(255,255,255,.1); }
.msg-mini-title { font-size: .9rem; font-weight: 600; color: #f4f1ea; flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msg-mini .nubia-mini-btn { color: rgba(244,241,234,.6); }
.msg-mini .nubia-mini-btn:hover { background: rgba(255,255,255,.12); color: #f4f1ea; }
/* Área de burbujas */
.msg-mini-body { flex: 1 1 auto; overflow-y: auto; min-height: 0; display: flex; flex-direction: column; gap: .55rem; padding: 1rem .9rem; }
.msg-mini-body::-webkit-scrollbar { width: 4px; }
.msg-mini-body::-webkit-scrollbar-thumb { background: rgba(229,107,94,.22); border-radius: 4px; }
/* Burbujas estilo WhatsApp — recibidas (izquierda) */
.msg-mini-body .bubble { position: relative; max-width: 80%; padding: .55rem .85rem .42rem; border-radius: 18px 18px 18px 4px; background: #ede9e8; color: var(--ink); align-self: flex-start; margin-left: 10px; font-size: .875rem; line-height: 1.4; }
.msg-mini-body .bubble::before { content: ''; position: absolute; bottom: 0; left: -7px; border: 7px solid transparent; border-right-color: #ede9e8; border-left: 0; border-top: 0; }
.msg-mini-body .bubble time { font-size: .63rem; opacity: .55; display: block; margin-top: .25rem; color: var(--ink); }
/* Burbujas enviadas (derecha) */
.msg-mini-body .bubble.mine { background: var(--accent); color: #fff; align-self: flex-end; border-radius: 18px 18px 4px 18px; margin-right: 10px; margin-left: 0; }
.msg-mini-body .bubble.mine::before { display: none; }
.msg-mini-body .bubble.mine::after { content: ''; position: absolute; bottom: 0; right: -7px; border: 7px solid transparent; border-left-color: var(--accent); border-right: 0; border-top: 0; }
.msg-mini-body .bubble.mine time { color: rgba(255,255,255,.65); }
.msg-mini-body .bubble p { font-size: .875rem; margin: 0; }
/* Área de escritura sólida oscura */
.msg-mini-form { flex: 0 0 auto; display: flex; gap: .5rem; padding: .7rem .9rem; background: #1C1A18; border-top: 1px solid rgba(255,255,255,.1); }
.msg-mini-form .conv-input { flex: 1 1 auto; min-width: 0; background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.15); border-radius: 22px; padding: .5rem .85rem; font-size: .88rem; color: #f4f1ea; font-family: inherit; outline: none; transition: border-color .15s; }
.msg-mini-form .conv-input::placeholder { color: rgba(244,241,234,.38); }
.msg-mini-form .conv-input:focus { border-color: var(--accent); }
.msg-mini-form .btn--coral { padding: .45rem .65rem; flex: 0 0 auto; border-radius: 50%; width: 36px; height: 36px; display: grid; place-items: center; }
.msg-mini-form .btn--coral .app-icon { width: 16px; height: 16px; }
/* Lista de conversaciones (vista "threads") con tema claro */
.msg-mini-thread { display: flex; align-items: center; gap: .75rem; width: 100%; padding: .8rem 1rem; border: none; background: none; cursor: pointer; text-align: left; border-bottom: 1px solid rgba(28,26,24,.08); transition: background .12s; }
.msg-mini-thread:hover { background: rgba(28,26,24,.05); }
.msg-mini-thread.is-unread { background: rgba(242,107,94,.1); }
.msg-mini-av { width: 36px; height: 36px; border-radius: 50%; background: rgba(229,107,94,.15); color: var(--accent); font-weight: 700; font-size: .85rem; display: grid; place-items: center; flex: 0 0 auto; }
.msg-mini-meta { flex: 1 1 auto; min-width: 0; }
.msg-mini-meta strong { display: block; font-size: .88rem; color: var(--ink); }
.msg-mini-meta span { display: block; font-size: .8rem; color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msg-mini-empty { padding: 2rem 1rem; text-align: center; font-size: .88rem; color: var(--ink-soft); }
/* right:5.5rem deja un margen real de ~12px con .nubia-fab (right:1rem, 60px de ancho) en este
   mismo breakpoint — antes quedaba en 5rem y las dos burbujas se superponían ~2-3px (bug real,
   presente en TODOS los anchos porque ambas burbujas se muestran a cualquier usuario logueado). */
@media (max-width: 560px) { .msg-fab { right: 5.5rem; bottom: 1.4rem; } .msg-mini { right: 1rem; left: 1rem; width: auto; bottom: 5.35rem; } }

/* ===== Upsell panel · tabla en coach ===== */
.upsell-table-wrap { border: 1px solid var(--line-2); border-radius: 12px; overflow-x: auto; overflow-y: hidden; }
/* La tabla tiene 5 columnas (Alumno · Plan · Fecha · Estado · Acción); en móvil no caben en el ancho
   de la tarjeta, así que se desplazan con scroll horizontal en vez de recortarse (columna Acción con
   los botones de aprobar/rechazar el upsell quedaba oculta con overflow:hidden). */
.upsell-table { min-width: 520px; }
.upsell-table { width: 100%; border-collapse: collapse; font-size: .86rem; }
.upsell-table th { text-align: left; padding: .72rem var(--card-pad); font-size: .7rem; color: var(--ink-mute); font-weight: 600; }
.upsell-table td { padding: .72rem var(--card-pad); border-top: 1px solid var(--line-2); color: var(--ink); vertical-align: middle; }
.upsell-table tbody tr:hover td { background: var(--bg); }
.upsell-status { display: inline-block; padding: .22rem .6rem; border-radius: 100px; font-size: .72rem; font-weight: 600; }
.upsell-status--pending { background: #fff3d6; color: #8a6000; }
.upsell-status--contacted { background: #e2f4ea; color: #1f7a4d; }
.upsell-status--won { background: var(--accent); color: #fff; }
.upsell-actions { display: inline-flex; gap: .4rem; flex-wrap: wrap; }
/* Bitácora · fila de upsell concretado (opción A: queda visible con el plan habilitado) */
.upsell-won-row td { background: #fff7f5; }
.upsell-won-sub { display: flex; align-items: center; gap: .25rem; font-size: .72rem; font-weight: 500; color: var(--accent-deep); margin-top: .15rem; }
.upsell-won-sub .app-icon { width: 12px; height: 12px; color: var(--accent-deep); flex: 0 0 auto; }

/* ===== Upsell por plan: etiqueta, píldora, banner al habilitar el 2º plan ===== */
/* Etiqueta UPSELL junto al nombre del plan en Seguimiento (paintModules header) */
.plan-upsell-tag { display: inline-flex; align-items: center; gap: .25rem; vertical-align: middle; margin-left: .6rem; font-family: var(--sans); font-size: .62rem; font-weight: 700; letter-spacing: .06em; color: var(--accent-deep); background: var(--accent-soft); border-radius: 100px; padding: .18rem .55rem; }
.plan-upsell-tag .app-icon { width: 12px; height: 12px; color: var(--accent-deep); }
/* Píldora reversible en «Acceso a planes» (Gestionar miembro) */
.plan-row-actions { display: inline-flex; align-items: center; gap: .45rem; flex-wrap: wrap; justify-content: flex-end; }
.upsell-pill { display: inline-flex; align-items: center; gap: .28rem; font-size: .7rem; font-weight: 600; border-radius: 100px; padding: .3rem .6rem; cursor: pointer; border: 1px solid var(--line); background: transparent; color: var(--ink-mute); }
.upsell-pill .app-icon { width: 12px; height: 12px; }
.upsell-pill:hover { border-color: var(--accent); color: var(--accent-deep); }
.upsell-pill.is-on { background: var(--accent-soft); border-color: transparent; color: var(--accent-deep); }
/* "Desbloquear [Plan] completo" — desplegable en el bloque de cada plan (Seguimiento) */
.seg-unlock { border: 1px solid var(--line-2); border-top: none; border-radius: 0 0 var(--radius) var(--radius); background: var(--bg); overflow: hidden; margin: -1.4rem 0 1.4rem; }
.seg-unlock-head { display: flex; align-items: center; gap: .6rem; width: 100%; padding: .8rem 1.1rem; cursor: pointer; user-select: none; background: none; border: none; text-align: left; font-family: inherit; }
.seg-unlock-head .ic { width: 30px; height: 30px; flex: 0 0 auto; border-radius: 8px; display: grid; place-items: center; background: var(--accent-soft); color: var(--accent-deep); }
.seg-unlock-head .ic .app-icon { width: 16px; height: 16px; }
.seg-unlock-head .tt { flex: 1; min-width: 0; }
.seg-unlock-head .tt b { display: block; font-size: .88rem; font-weight: 600; }
.seg-unlock-head .tt span { font-size: .73rem; color: var(--ink-mute); }
.seg-unlock-chev { transition: transform .3s var(--ease-out); color: var(--ink-mute); flex: 0 0 auto; }
.seg-unlock.open .seg-unlock-chev { transform: rotate(180deg); }
.seg-unlock-body { padding: 0 1.1rem 1.1rem; display: none; }
.seg-unlock.open .seg-unlock-body { display: block; }
.seg-unlock-callout { background: var(--paper); border: 1px solid var(--line-2); border-radius: 10px; padding: .7rem .8rem; margin-bottom: .7rem; }
.seg-unlock-callout p { font-size: .8rem; color: var(--ink-soft); line-height: 1.55; }
.seg-unlock-go { width: 100%; justify-content: center; }
/* Selector de módulo del segundo desplegable ("Desbloquear un módulo completo"). */
.seg-unlock-sel { width: 100%; margin-bottom: .6rem; }
/* Dos desplegables apilados: el margen negativo cancela el inferior del primero para que queden
   pegados como un solo bloque, y el de arriba pierde sus esquinas redondeadas inferiores. */
.seg-unlock + .seg-unlock { margin-top: -1.4rem; }
.seg-unlock:has(+ .seg-unlock) { border-radius: 0; }
/* Banner "¿Es un upsell?" al habilitar el 2º plan núcleo (modal propio) */
.upsell-grant { padding: .2rem 0; }
.ug-head { display: flex; align-items: center; gap: .6rem; margin-bottom: .7rem; }
.ug-ic { width: 38px; height: 38px; flex: 0 0 auto; border-radius: 10px; background: var(--accent); color: #fff; display: grid; place-items: center; position: relative; }
.ug-ic .app-icon { width: 19px; height: 19px; stroke: #fff; color: #fff; }
.ug-ic .ug-dot { position: absolute; top: -3px; right: -3px; width: 12px; height: 12px; border-radius: 50%; background: #e2b400; border: 2px solid var(--paper); }
.ug-head b { font-size: 1rem; font-weight: 700; }
.ug-head .ug-k { display: block; font-size: .66rem; font-weight: 700; letter-spacing: .05em; color: var(--accent-deep); }
.ug-reqline { display: flex; align-items: center; gap: .4rem; font-size: .78rem; color: var(--ink-soft); background: var(--accent-soft); border-radius: 9px; padding: .5rem .7rem; margin-bottom: .7rem; flex-wrap: wrap; }
.ug-reqline .app-icon { width: 14px; height: 14px; color: var(--accent-deep); }
.ug-reqline .ug-st { font-weight: 600; color: #8a6000; background: #fff3d6; border-radius: 100px; padding: .08rem .5rem; font-size: .72rem; }
.ug-body { font-size: .88rem; color: var(--ink-soft); line-height: 1.55; margin-bottom: .5rem; }
.ug-body b, .ug-note b { color: var(--ink); }
.ug-note { font-size: .78rem; color: var(--ink-mute); line-height: 1.5; margin-bottom: 1rem; }
.ug-actions { display: flex; gap: .6rem; flex-wrap: wrap; }
.ug-actions .btn { flex: 1; min-width: 160px; }
.ug-cancel { display: block; width: 100%; margin-top: .7rem; background: none; border: none; color: var(--ink-mute); font-size: .8rem; cursor: pointer; font-family: inherit; padding: .3rem; }
.ug-cancel:hover { color: var(--ink); }

/* ===== Burbuja de acceso rápido a Nubia ===== */
.nubia-fab { position: fixed; right: 1.4rem; bottom: 1.4rem; width: 60px; height: 60px; border-radius: 50%; border: none; padding: 0; cursor: pointer; z-index: 60;
  background: var(--grad-portada, #1C1A18); box-shadow: 0 10px 28px rgba(28,26,24,.32); display: grid; place-items: center; transition: transform .18s var(--ease-out), box-shadow .18s; }
.nubia-fab:hover { transform: translateY(-2px) scale(1.04); box-shadow: 0 14px 34px rgba(28,26,24,.4); }
.nubia-fab.is-open { transform: scale(.92); }
.nubia-fab-av { width: 50px; height: 50px; border-radius: 50%; background-size: cover; background-position: center; border: 2px solid rgba(244,241,234,.85); }
.nubia-fab-dot { position: absolute; top: 4px; right: 4px; width: 13px; height: 13px; border-radius: 50%; background: #1f7a4d; border: 2px solid var(--paper); }
/* Badge de "Nubia sin leer" (1.1.14): respuesta que llegó mientras el alumno no miraba el chat. */
.nubia-fab-badge { position: absolute; top: -4px; right: -4px; min-width: 19px; height: 19px; padding: 0 5px; border-radius: 100px; background: var(--accent); color: #fff; font-size: .68rem; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; border: 2px solid var(--paper); }
/* Mismo criterio que .msg-mini: anclada abajo y con el alto máximo descontando el topbar (sticky,
   z-index 70) en
   ventanas no maximizadas; max-height conserva el tamaño de tarjeta flotante en pantallas altas. */
/* Alto FIJO por el mismo motivo que .msg-mini: con `max-height` la caja se ajustaba al contenido y
   una conversación corta la dejaba mucho más chica. El descuento (11.35rem) y el suelo son los suyos:
   esta burbuja arranca más abajo (bottom 5.85rem) y es más ancha. */
.nubia-mini { position: fixed; right: 1.4rem; bottom: 5.85rem; z-index: 61; width: min(570px, calc(100vw - 2rem)); height: min(640px, max(320px, calc(100vh - 11.35rem)));
  background: var(--paper); border: 1px solid var(--line); border-radius: 18px; box-shadow: 0 18px 50px rgba(28,26,24,.28); overflow: hidden; display: flex; flex-direction: column; animation: nubiaPop .22s var(--ease-out); }
@keyframes nubiaPop { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: none; } }
.nubia-mini-head { flex: 0 0 auto; border-bottom: 1px solid var(--line-2); }
.nubia-mini-btn { width: 30px; height: 30px; border-radius: 8px; border: none; background: transparent; color: var(--ink-soft); cursor: pointer; display: grid; place-items: center; font-size: .9rem; flex: 0 0 auto; }
.nubia-mini-btn:hover { background: var(--bg); color: var(--accent); }
.nubia-mini-btn .app-icon { width: 16px; height: 16px; }
.nubia-mini-body { flex: 1 1 auto; overflow-y: auto; min-height: 0; }
.nubia-mini .conv-form { flex: 0 0 auto; border-top: 1px solid var(--line-2); }
.nubia-mini .conv-form .btn--coral { padding: .5rem .7rem; }
.nubia-mini .conv-form .btn--coral .app-icon { width: 17px; height: 17px; }
@media (max-width: 560px) { .nubia-fab { right: 1rem; } .nubia-mini { right: 1rem; left: 1rem; width: auto; bottom: 5.85rem; } }

/* ===== Animaciones del sistema de chat =====
   Van DESPUÉS de .mt-unread (1399), .msg-fab-badge (1735) y de los .btn--coral de las dos burbujas
   (1775 / 1824) a propósito: ahí ya está todo definido y ninguna regla posterior puede apagarlas en
   silencio. Ninguna de esas reglas toca animation/opacity/transform, así que no se pisan. */

/* Entrada del mensaje que LLEGA (la clase la pone animateNewBubbles solo en el mensaje nuevo, nunca
   al abrir una conversación ya existente). */
@keyframes bubbleIn { from { opacity: 0; transform: translateY(9px) scale(.97); } to { opacity: 1; transform: none; } }
.bubble--in { animation: bubbleIn .24s var(--ease-out) both; }

/* Rebote del contador de mensajes sin leer, en la barra lateral y en la burbuja. */
@keyframes badgePop { 0% { transform: scale(1); } 45% { transform: scale(1.38); } 100% { transform: scale(1); } }
.mt-unread.is-pop, [data-msg-badge].is-pop, .msg-fab-badge.is-pop { animation: badgePop .42s var(--ease-out); }

/* El botón de enviar se apaga sin nada que enviar. La clase la mantiene syncSendState sobre el
   formulario, no sobre el botón, para poder alcanzar también al de Nubia con un documento adjunto. */
.conv-form .btn--coral { transition: opacity .16s, transform .16s var(--ease-out), filter .16s; }
.conv-form:not(.has-text) .btn--coral { opacity: .42; transform: scale(.93); }

@media (prefers-reduced-motion: reduce) {
  .bubble--in, .mt-unread.is-pop, [data-msg-badge].is-pop, .msg-fab-badge.is-pop { animation: none; }
  .conv-form:not(.has-text) .btn--coral { transform: none; }
}

/* ===== Todo el texto en Raleway (antes serif) del área de miembros, en negrita ===== */
.app-body em, .app-body .serif-em,
.side-avatar, .topbar-title h1, .topbar-avatar, .fp-title, .rail-stats .n, .lb-rank,
.cal-head .m, .evt-when .d, .plan-overview h2, .module-num, .profile-avatar, .profile-id h2,
.profile-stats .row b, .avatar-upload .preview, .kpi .num, .donut .c b, .gate-head h2,
.gate-card h2, .manage-head h3, .onb-intro h2, .coach-avatar, .coach-card h3, .onb-done h2,
.welcome-card h3, .modal-title, .evt-cover-title, .profile-modal h3, .track-title,
.sessions-head-count, .coach-section-title, .coach-student-hero-id h2 { font-weight: 700; }

/* ===== Tamaño de tipografía del área de miembros (pedido del cliente, 02-jul-2026) =====
   Se mantiene la fuente de siempre (Raleway/Inter, sin tocar font-family); solo cambia el TAMAÑO:
   14px para el texto en general, 16px en negrita para los títulos de publicación. Los headers de
   las barras superiores (topbar) NO cambian. No afecta la portada ni "crear perfil / acceder"
   (usan styles.css, no este archivo). */
.app-body * { font-size: 14px !important; }
.topbar-title h1 { font-size: clamp(1.4rem, 3vw, 1.9rem) !important; }
.topbar-title p { font-size: .82rem !important; }
/* Tamaños de publicación (recalibrados 21-jul-2026, pedido cliente): el TÍTULO toma el tamaño que tenía
   el cuerpo (16px) pero en negrita, y el CUERPO baja al tamaño genérico de los textos del portal
   (.app-body * = 14px, el mismo de los boxes del rail como Ranking), sin negrita. */
.fp-cat { font-size: 12px !important; }
.fp-title { font-size: 16px !important; font-weight: 700 !important; }
.fp-body { font-size: 14px !important; }
/* "Visto" del chat: subtexto, más chico que el mensaje. Va acá y con DOS clases (0,2,0) porque
   `.app-body *` de arriba lleva !important y le gana a cualquier regla de una sola clase. */
.conv-body .bubble-seen, .msg-mini-body .bubble-seen { font-size: 11px !important; }
/* En móvil el mismo tamaño se siente grande: se baja un poco toda la escala (solo ≤560px). Debe ir
   DESPUÉS de las reglas de arriba y repetir su orden (base .app-body * primero, luego los específicos)
   para que la cascada quede igual que en escritorio pero con tamaños menores. No afecta escritorio. */
@media (max-width: 560px) {
  .app-body * { font-size: 13px !important; }
  .topbar-title h1 { font-size: clamp(1.25rem, 4.5vw, 1.7rem) !important; }
  .topbar-title p { font-size: .76rem !important; }
  .fp-cat { font-size: 11px !important; }
  /* Publicaciones en móvil (recalibrado 21-jul): título al tamaño del cuerpo (13px) en negrita, cuerpo al
     genérico del portal (13px, .app-body *). En móvil ambos quedan en 13px; el título se distingue por la negrita. */
  .fp-title { font-size: 13px !important; font-weight: 700 !important; }
  .fp-body { font-size: 13px !important; }
  /* iOS Safari hace ZOOM a toda la página cuando enfocas un campo con font <16px. Al fijar 16px en todo
     campo de escritura (mayor especificidad que `.app-body *`, así que gana pese al 13px !important),
     enfocar deja de disparar ese zoom. Solo crece el texto del propio campo; el resto sigue a 13px.
     Es el arreglo correcto: NO se toca el viewport (pellizcar-para-ampliar sigue disponible). */
  .app-body input, .app-body textarea, .app-body select, .app-body [contenteditable] { font-size: 16px !important; }
}

/* ===== Filtros de píldoras → desplegable de ancho completo en MÓVIL (pedido cliente) — SOLO ≤560px =====
   En móvil las filas de píldoras (tipo de publicación, grupos/comunidades, y los planes de Módulos y
   Cronograma) se ocultan y aparece el MISMO desplegable .members-select pero a lo ancho, respetando
   márgenes. El texto por defecto del composer pasa a su versión corta (una sola línea). Va al final
   para ganar la cascada sobre las reglas base de cada componente. Escritorio queda intacto. */
.fdrop-mobile { display: none; }
.cmp-short { display: none; }
@media (max-width: 560px) {
  .feed-filters,
  .comm-switch .comm-switch-pill,
  .plan-tabs .plan-tab[data-plan],
  .plan-tabs .plan-tab[data-prog-plan] { display: none; }
  .fdrop-mobile { display: flex; width: 100%; box-sizing: border-box; }
  .feed-filter-drop { margin: 0 0 1.1rem; }
  .comm-switch .fdrop-mobile, .plan-tabs .fdrop-mobile { flex: 1 1 auto; min-width: 0; width: auto; }
  .fdrop-mobile > select { flex: 1 1 auto; min-width: 0; width: 100%; }
  .cmp-long { display: none; }
  .cmp-short { display: inline; }
  /* El texto por defecto del composer, en una sola línea (sin envolver) */
  .composer button { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Contenido de la tarea: el sangrado de 3.4rem (alinea bajo el título en escritorio) se come el 20%
     del ancho en móvil, y el video al 75% (pedido para escritorio) quedaba en ~167px. Juntos dejaban un
     video de ~94px de alto, inusable. En móvil: sin sangrado y video a lo ancho. */
  .task-body { padding-left: .8rem; }
  .task-video { width: 100%; }

  /* ===== Áreas táctiles de 44px (mínimo de la skill mobile-webview-design) =====
     Los controles de icono medían 22-36px. Se agranda el ÁREA TÁCTIL con un pseudo-elemento
     invisible centrado: el icono conserva su tamaño visual y el layout no se mueve.
     Importa especialmente porque estos controles van DENTRO de .task-head, que también es tocable
     (despliega la tarea): un toque impreciso hacía lo contrario de lo buscado. */
  .task-head .lesson-check,
  .task-head .task-edit,
  .task-head .task-del,
  .nubia-mini-btn,
  .conv-form .conv-tool { position: relative; }
  .task-head .lesson-check::after,
  .task-head .task-edit::after,
  .task-head .task-del::after,
  .nubia-mini-btn::after,
  .conv-form .conv-tool::after {
    content: ""; position: absolute; left: 50%; top: 50%;
    width: 44px; height: 44px; transform: translate(-50%, -50%);
  }
  /* Editar y Borrar quedaban a 8.8px: con áreas de 44px se solapaban y borrar es DESTRUCTIVO.
     Se separan para que cada área quede limpia (la skill pide 8px mínimo entre acciones). */
  .task-head .task-edit { margin-right: 1rem; }
  /* Cerrar modal: es absolute, así que agrandarlo no mueve nada. */
  .app-modal-x { width: 44px; height: 44px; }
  /* Campana y burger del topbar. En .icon-btn hay que pisar también el flex-basis (flex:0 0 40px):
     en un contenedor flex el basis manda sobre width. */
  .topbar-burger, .icon-btn { width: 44px; height: 44px; }
  .topbar-actions .icon-btn { flex: 0 0 44px; }

  /* ===== Ventanas emergentes (modales) =====
     Las variantes usan width:min(Xpx, 94vw) = 352px, pero viven dentro de .app-modal que tiene
     padding:1.2rem (caja de 337px): la tarjeta desbordaba ese padding y quedaba PEGADA al borde
     derecho (19px de margen izq. vs 3px der.). width:100% respeta el padding y la deja centrada. */
  .app-modal .app-modal-card { width: 100%; }
  /* Filas [etiqueta][select] de Gestionar miembro: el select tiene min-width:200px, así que a la
     etiqueta le quedaban 85px → rompía en 2 líneas y el nombre del coach salía cortado
     ("Sebastian Alvarez Arena"). En móvil se apilan: etiqueta arriba, select a lo ancho (que además
     es mejor target táctil). */
  .manage-row:has(select), .manage-row:has(.mps) { flex-direction: column; align-items: stretch; gap: .4rem; }
  .manage-row select, .manage-row .mps { min-width: 0; width: 100%; }

  /* Panel de notificaciones: se ancla a la campana (right:0) y su caja de 300px lo empujaba hasta
     6px del borde izquierdo, dejando 69px muertos a la derecha — márgenes rotos respecto al resto
     de la app (que usa 1.2rem). En móvil se ancla al viewport con esos mismos márgenes.
     top: 87px = alto del topbar (77px, medido) + los 10px de separación del diseño original.
     position:fixed funciona aquí: el topbar es sticky y sticky NO crea bloque contenedor para fixed. */
  .notif-panel { position: fixed; top: 87px; left: 1.2rem; right: 1.2rem; width: auto; max-width: none; }
}

/* ===== Compactación móvil · reglas que deben ir AL FINAL para ganar la cascada =====
   `.app-modal-card` (padding 1.6rem, línea ~832) y `.gate-card` (clamp 2rem, línea ~632) se declaran
   más abajo que el bloque de compactación de ≤560px, y con la MISMA especificidad gana la última regla
   del archivo. Por eso su versión móvil vive acá, al final. Escritorio queda intacto. */
@media (max-width: 560px) {
  .app-modal-card { padding: 1.3rem 1.125rem; }                   /* 26px → 18px lateral */
  .gate-card { padding-left: 1.125rem; padding-right: 1.125rem; } /* 32px → 18px (era el mayor del sitio) */
}

/* ===== Nombre de archivo que CONSERVA la extensión al recortarse (chat y adjuntos) =====
   Antes, con solo `text-overflow: ellipsis`, "Guia-de-Marca-Personal-Modulo-3.pdf" se veía
   "Guia-de-Marca-Personal-…" y no se sabía si era un PDF o una planilla. Ahora el cuerpo se corta y la
   extensión queda fija a la derecha: "Guia-de-Marca-Per….pdf". El HTML lo arma fileNameHTML() (app.js).
   Aplica en TODOS los tamaños: los topes de 180/220px también existen en escritorio.
   Especificidad (0,2,0) a propósito, para ganarle a `.bubble-file span` / `.doc-chip-meta b` (0,1,1). */
.fname { display: flex; align-items: baseline; min-width: 0; overflow: hidden; }
.fname .fn-body { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fname .fn-ext { flex: 0 0 auto; white-space: nowrap; }

@media (max-width: 560px) {
  /* Evento del calendario: la celda mide ~40px, así que el título se recortaba a "Sesi…" (ilegible).
     En móvil se muestra un punto coral por evento (hasta 3) y el detalle se lee tocando el día, que
     ahora abre la agenda del día con horario. Los puntos NO son objetivo táctil (7px es imposible de
     acertar): `pointer-events: none` deja que el toque lo reciba la celda completa (28-jul-2026).
     Antes cada `.cal-evt` cubría toda la celda con inset:0 — con varios eventos se apilaban uno sobre
     otro y solo se veía (y se podía tocar) el último. */
  .cal-evts { position: absolute; left: 0; right: 0; bottom: 4px; flex-direction: row;
    align-items: center; justify-content: center; gap: 3px; margin: 0; }
  .cal-evt { width: 6px; height: 6px; padding: 0; border-radius: 50%; background: var(--accent);
    text-indent: -999px; overflow: hidden; flex: 0 0 auto; pointer-events: none; }
  .cal-more { align-self: center; font-size: 9px !important; color: var(--accent-deep); font-weight: 700; }
}

/* ===== Editor de cronograma (admin + coach) =====
   Reutiliza .manage-row + .mod-drag-row + .mod-drag-grip del gestor de planes: un solo patrón de
   "arrastrar para reordenar" en toda la plataforma. Acá solo se agrega lo propio del cronograma. */
.sched-modal { max-width: 900px; }   /* 780 → 900 (ronda de ensanche del 28-jul-2026) */
.sched-total { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin: .9rem 0 .2rem; }
.sched-total label { display: grid; gap: .25rem; font-size: .78rem; font-weight: 600; color: var(--ink-soft); }
.sched-total input { width: 92px; padding: .45rem .6rem; border: 1px solid var(--line); border-radius: 10px;
  background: var(--paper); font: inherit; color: var(--ink); }
.sched-list { display: grid; gap: .4rem; margin-top: .9rem; max-height: 52vh; overflow-y: auto; padding-right: .2rem; }
.sched-row.is-off { opacity: .5; }
.sched-see input { width: 17px; height: 17px; accent-color: var(--accent); cursor: pointer; }
.sched-name { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.sched-nums { display: flex; gap: .45rem; flex: 0 0 auto; }
.sched-nums label { display: grid; gap: .15rem; font-size: .66rem; color: var(--ink-mute); text-align: center; }
.sched-nums input { width: 58px; padding: .3rem .35rem; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg); font: inherit; text-align: center; color: var(--ink); }
@media (max-width: 560px) {
  .sched-row { flex-wrap: wrap; row-gap: .5rem; }
  .sched-name { flex: 1 1 60%; }
  .sched-nums { flex: 1 1 100%; justify-content: flex-start; }
}

/* ============================================================================
   MÓDULOS · menú de 3 puntos, modo Mover y arrastre de tareas (etapa 2C)
   Va al FINAL del archivo a propósito: .mod-cover-card y .task se declaran más
   arriba y con igual especificidad ganaría la última regla. (Ver AUDIT.md,
   "trampa de cascada" — ya costó tres rondas.)
   ============================================================================ */

/* La tarjeta pasa a vivir dentro de un contenedor para poder colgarle el botón
   de 3 puntos por fuera: el botón no puede ir DENTRO de la tarjeta porque la
   tarjeta ya es un <button> y anidar botones es HTML inválido (el clic interno
   se lo comería el externo). El contenedor hereda el ancho fijo del carrusel. */
.mod-cover-wrap { position: relative; flex: 0 0 280px; display: flex; }
.mod-cover-wrap > .mod-cover-card { flex: 1 1 auto; }

.mod-dots { position: absolute; top: .5rem; right: .55rem; z-index: 3; width: 30px; height: 30px;
  border: 0; border-radius: 50%; background: rgba(255,255,255,.92); color: var(--ink);
  display: grid; place-items: center; cursor: pointer; padding: 0;
  box-shadow: 0 2px 8px -1px rgba(28,26,24,.35); opacity: 0; transition: opacity .18s, background .18s; }
.mod-cover-wrap:hover .mod-dots, .mod-dots:focus-visible, .mod-dots.is-open { opacity: 1; }
/* En táctil no hay hover: el botón se ve siempre, si no sería inalcanzable. */
@media (hover: none) { .mod-dots { opacity: 1; } }
.mod-dots:hover { background: #fff; }
.mod-dots .app-icon { width: 16px; height: 16px; }

/* `fixed` y colgado de <body>: dentro de la tarjeta quedaba atrapado en `.mod-track` (overflow-x: auto
   para el carrusel) y un recorte en un eje recorta también el otro, así que el menú se cortaba contra
   el borde de la franja y "Eliminar" desaparecía bajo el cuadro de tareas. Las coordenadas las calcula
   placeModuleMenu() en app.js al abrirlo. z-index alto: tiene que pasar por encima de las tarjetas
   activas (z 2) y del cuadro de tareas. */
.mod-menu { position: fixed; z-index: 200; min-width: 168px; padding: .3rem;
  background: var(--paper); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 18px 44px -18px rgba(28,26,24,.45); }
.mod-menu button { display: flex; align-items: center; gap: .55rem; width: 100%; text-align: left;
  padding: .5rem .6rem; border: 0; background: none; border-radius: 8px; cursor: pointer;
  font: 500 .84rem/1.2 var(--sans); color: var(--ink); }
.mod-menu button:hover { background: var(--bg-2); }
.mod-menu button.is-danger { color: #c0392b; }
.mod-menu .app-icon { width: 15px; height: 15px; opacity: .75; }
.mod-menu hr { border: 0; border-top: 1px solid var(--line-2); margin: .25rem .15rem; }

/* ---- Modo Mover: todo el plan entra en edición ---- */
.mods-move-bar { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  background: var(--ink); color: var(--paper); border-radius: 12px; padding: .6rem .8rem; margin-bottom: .2rem;
  font: 500 .84rem/1.3 var(--sans); }
.mods-move-bar b { font-weight: 700; }
.mods-move-bar .mmb-hint { opacity: .75; }
.mods-move-bar .mmb-sp { flex: 1 1 auto; }
.mods-move-bar .app-icon { width: 16px; height: 16px; }

.mods-moving .mod-dots { display: none; }
/* CRÍTICO para el auto-scroll: sin esto, `scroll-snap-type: x proximity` (del .mod-track) devuelve a 0
   cada micro-incremento de 7px que hace el RAF → el carrusel queda pinneado y el auto-scroll "no mueve"
   aunque el trigger sí dispare. En modo Mover se apaga el snap; al salir se restaura solo. */
.mods-moving .mod-track { scroll-snap-type: none; }
/* Reorden de módulos: la tarjeta arrastrada queda atenuada en su sitio y solo se abre una separación
   animada entre las dos tarjetas donde caería (indicador de hueco, sin reordenar en vivo). */
.mods-moving .mod-cover-wrap { transition: margin .16s ease; }
.mods-moving .mod-cover-wrap.mod-gap-before { margin-left: 2.4rem; }
.mods-moving .mod-cover-wrap.mod-gap-after { margin-right: 2.4rem; }
.mods-moving .mod-cover-card { cursor: grab; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-soft); }
.mods-moving .mod-cover-card:hover { transform: none; }
.mods-moving .mod-cover-card.is-active { transform: none; }
.mods-moving .mod-cover-wrap.dragging { opacity: .4; }
/* (Antes había una grip/hamburguesa en modo Mover; se quitó — la tarjeta queda limpia y el borde coral +
   cursor grab + la barra "Moviendo módulos" ya indican que se arrastra.) */

/* ---- Arrastre de tareas dentro del módulo ---- */
.task-grip { flex: 0 0 auto; width: 26px; height: 26px; display: grid; place-items: center;
  color: var(--ink-mute); cursor: grab; opacity: 0; transition: opacity .18s; }
.task:hover .task-grip, .task-grip:focus-visible { opacity: .8; }
@media (hover: none) { .task-grip { opacity: .55; } }
.task-grip .app-icon { width: 15px; height: 15px; }
.task.dragging { opacity: .4; }
.module-lessons.is-reordering .task { cursor: grab; }

/* ---- Editor de cronograma · una fila por módulo, desplegable ---------------
   Mismo patrón que .task en Módulos: UNA caja redondeada por módulo, con la
   cabecera y el panel adentro. Redondear dos elementos hermanos por separado
   deja siempre alguna esquina en ángulo recto.
   La cabecera es un <button> aparte del asa de arrastre: si toda la fila fuera
   pinchable, arrastrar dispararía también el desplegado. */
.sched-item { border-radius: 12px; overflow: hidden; transition: background .2s; }
.sched-item.is-open { background: var(--bg-2); }
.sched-item:not(.is-open):hover { background: var(--bg); }
.sched-item.dragging { opacity: .4; }

/* Separador entre módulos plegados. Se retira alrededor del abierto: contra su
   fondo beige, la línea se leería como el borde de otra caja. */
.sched-item + .sched-item > .sched-row { border-top: 1px solid var(--line-2); }
.sched-item.is-open > .sched-row,
.sched-item.is-open + .sched-item > .sched-row { border-top-color: transparent; }

.sched-item > .sched-row { padding: .15rem .7rem; border-radius: 0; }
.sched-row .sched-head { flex: 1 1 auto; display: flex; align-items: center; gap: .6rem;
  min-width: 0; padding: .5rem 0; border: 0; background: none; cursor: pointer; text-align: left; font: inherit; color: inherit; }
.sched-row .sched-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.sched-row .sched-when { flex: 0 0 auto; font-size: .78rem; color: var(--ink-mute); }
.sched-caret { flex: 0 0 auto; width: 15px; height: 15px; color: var(--ink-mute); transition: transform .2s var(--ease-out); }
.sched-item.is-open .sched-caret { transform: rotate(180deg); }

.sched-panel { display: flex; gap: .9rem; flex-wrap: wrap; padding: .2rem 1rem 1rem 2.5rem; }
.sched-panel label { display: flex; flex-direction: column; gap: .25rem; font-size: .78rem; color: var(--ink-mute); }
/* Mismos valores que el campo "Semanas" de este mismo modal (.sched-total input): sin declarar
   padding, el número quedaba pegado al borde izquierdo. */
.sched-panel input { width: 7.5rem; padding: .45rem .7rem; border: 1px solid var(--line);
  border-radius: 10px; background: var(--paper); font: inherit; color: var(--ink); }

@media (max-width: 560px) {
  .sched-row .sched-when { display: none; }   /* el rango de días ya se ve al desplegar */
  .sched-panel { padding-left: 1rem; }
  .sched-panel input { width: 100%; }
  .sched-panel label { flex: 1 1 8rem; }
}

/* ---- Campo de redacción que crece con el texto (las 4 superficies) --------
   Era <input>, que no puede tener más de una línea. Ahora es <textarea> con
   alto automático: arranca en una línea y crece hasta cinco (el tope lo aplica
   autoGrow en app.js, que es quien puede medir el contenido real).
   `resize: none` porque el tirador nativo de la esquina pelearía con el alto
   calculado; `field-sizing` no se usa todavía por soporte disparejo. */
.conv-form textarea,
.conv-form .conv-input {
  resize: none; overflow-y: hidden; min-height: 0;
  line-height: 1.35; font-family: inherit;
}
/* El formulario deja de centrar verticalmente: con el campo creciendo, los
   botones deben quedar abajo, a la altura de la última línea. */
.conv-form { align-items: flex-end; }

/* ---- Menú de adjuntos (3 puntos) en las 4 barras de redacción -------------
   Imagen y documento se agrupan acá; el micrófono queda fuera, con clic directo,
   porque es la acción que más se usa. En las burbujas no cabían los tres sueltos. */
.conv-more-wrap { position: relative; flex: 0 0 auto; }
.conv-att-menu { position: absolute; bottom: calc(100% + .45rem); left: 0; z-index: 8; min-width: 172px;
  padding: .3rem; background: var(--paper); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 16px 40px -16px rgba(28,26,24,.45); }
.conv-att-menu button { display: flex; align-items: center; gap: .55rem; width: 100%; text-align: left;
  padding: .5rem .6rem; border: 0; background: none; border-radius: 8px; cursor: pointer;
  font: 500 .85rem/1.2 var(--sans); color: var(--ink); }
.conv-att-menu button:hover { background: var(--bg-2); }
.conv-att-menu .app-icon { width: 15px; height: 15px; opacity: .75; }

/* Dentro de la burbuja de Mensajes la barra es oscura: el menú se aclara para no desaparecer. */
.msg-mini-form .conv-att-menu { background: #262220; border-color: rgba(255,255,255,.14); }
.msg-mini-form .conv-att-menu button { color: #f4f1ea; }
.msg-mini-form .conv-att-menu button:hover { background: rgba(255,255,255,.09); }
.msg-mini-form .conv-tool { color: rgba(244,241,234,.72); }
.msg-mini-form .conv-tool:hover { background: rgba(255,255,255,.1); color: #f4f1ea; }

/* ---- Correcciones de la barra oscura y del menú "⋮" de las burbujas -------

   1) Contraste de los botones. `.conv-tool` trae fondo crema y borde claro,
      pensados para la barra clara del área grande. Sobre la barra negra de la
      burbuja quedaban como dos círculos blancos sin icono visible. */
.msg-mini-form .conv-tool {
  background: rgba(255,255,255,.1);
  border-color: rgba(255,255,255,.18);
  color: rgba(244,241,234,.82);
}
.msg-mini-form .conv-tool:hover {
  background: rgba(255,255,255,.18);
  border-color: rgba(255,255,255,.3);
  color: #f4f1ea;
}
/* Grabando: se mantiene el coral, que sí contrasta contra el negro. */
.msg-mini-form .conv-tool.is-rec { background: var(--accent); border-color: var(--accent); color: #fff; }

/* 2) El menú "⋮" de una burbuja (descargar / eliminar) se posiciona en
      coordenadas de pantalla al abrirse — ver bindBubbleActions—, porque la
      conversación hace scroll y recortaba el panel. */
.bubble-menu-panel.is-floating { position: fixed; bottom: auto; right: auto; z-index: 200; }

/* ---------- Vista previa de adjuntos del chat (popup centrado, 27-jul-2026) ----------
   La imagen y el documento del chat abren acá en grande. La ficha del modal se estira sola
   (att-prev-modal) para aprovechar la pantalla sin llegar a los bordes. */
.att-prev-modal { max-width: min(900px, 94vw); width: 100%; }
.att-prev { display: flex; flex-direction: column; gap: .8rem; min-width: 0; }
.att-prev-head { display: flex; align-items: center; gap: .8rem; justify-content: space-between; padding-right: 2.2rem; }
.att-prev-head .fname { font: 600 .92rem var(--sans); color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-prev-img { display: block; max-width: 100%; max-height: 74vh; margin: 0 auto; border-radius: 12px; object-fit: contain; background: var(--bg-2); }
.att-prev-frame { width: 100%; height: 74vh; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-2); }
.att-prev-none { display: flex; flex-direction: column; align-items: center; gap: .7rem; text-align: center; padding: 2.4rem 1rem; background: var(--bg-2); border-radius: 12px; }
.att-prev-none .app-icon { width: 34px; height: 34px; color: var(--ink-mute); }
.att-prev-none b { font: 600 1rem var(--sans); color: var(--ink); word-break: break-word; }
.att-prev-none p { margin: 0; max-width: 380px; font-size: .86rem; color: var(--ink-mute); }
/* La imagen y el documento de la burbuja ahora se pulsan → se avisa con el cursor. El documento pasó
   de <a> a <button>, así que hay que neutralizar el estilo propio del botón (fuente y alineación). */
.bubble-img { cursor: zoom-in; }
.bubble-file { cursor: pointer; font: inherit; text-align: left; width: auto; }
.bubble-file:hover { border-color: var(--accent); }

/* ---------- Historial de pausas (línea de tiempo tipo seguimiento de envío, 27-jul-2026) ----------
   Solo en la vista del coach sobre el cronograma de un alumno. Lo más reciente arriba: cada entrada
   lleva un punto en la línea vertical y el desenlace real de esa solicitud. */
.pause-hist { list-style: none; margin: .2rem 0 0; padding: 0 0 0 1.35rem; position: relative; }
.pause-hist::before { content: ""; position: absolute; left: .3rem; top: .45rem; bottom: .45rem; width: 2px; background: var(--line-2); border-radius: 2px; }
.ph-item { position: relative; padding: 0 0 1rem; }
.ph-item:last-child { padding-bottom: 0; }
/* El punto: relleno para la entrada más reciente, hueco para las anteriores. */
.ph-item::before { content: ""; position: absolute; left: -1.35rem; top: .3rem; width: 12px; height: 12px; border-radius: 50%; background: var(--paper); border: 2px solid var(--line); box-sizing: border-box; }
.ph-item:first-child::before { border-color: var(--accent); background: var(--accent); }
.ph-head { display: flex; align-items: baseline; gap: .6rem; justify-content: space-between; }
.ph-head b { font: 600 .88rem var(--sans); color: var(--ink); }
.ph-head time { flex: 0 0 auto; font-size: .74rem; color: var(--ink-mute); }
.ph-item p { margin: .15rem 0 0; font-size: .84rem; color: var(--ink-soft); line-height: 1.45; }
.ph-reason { font-style: italic; color: var(--ink-mute) !important; }
.ph-ask { display: block; margin-top: .3rem; font-size: .72rem; color: var(--ink-mute); }
/* Color del estado, sin gritar: solo el título cambia de tono. */
.ph-item.is-live .ph-head b { color: var(--accent-deep); }
.ph-item.is-cut  .ph-head b { color: var(--accent-deep); }
.ph-item.is-done .ph-head b { color: #2E7D5B; }
.ph-item.is-pend .ph-head b { color: var(--ink); }
.ph-item.is-off  .ph-head b { color: var(--ink-mute); }
.ph-item.is-off p, .ph-item.is-off .ph-ask { opacity: .85; }
