/* Elffuss — tema "aurora local": charcoal, brass y un secundario índigo */
:root {
  --bg: #090a11;
  --bg2: #101317;
  --bg3: #161a24;
  --line: #20252c;
  --fg: #eae8f2;
  --muted: #8b929c;
  --accent: #c8a06a;
  --accent2: #6e63c5;
  --ok: #7faa7f;
  --warn: #c9a15a;
  --serif: "Iowan Old Style", Georgia, "Times New Roman", serif;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--fg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ---------- header ---------- */
header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--bg2);
}
.brand { display: flex; align-items: center; gap: 8px; font-size: 1.1rem; font-family: var(--serif); letter-spacing: .2px; }
.logo { width: 30px; height: 30px; }
.beta { color: var(--accent2); font-size: .75rem; }
.claim { color: var(--muted); font-size: .8rem; font-style: italic; }
.controls { display: flex; align-items: center; gap: 10px; }
.model-pick { font-size: .9rem; color: var(--muted); }

/* Cabecera en UNA línea. Se partía en dos y tres (2026-09-13) por tres cosas a
   la vez: el <select> de modelo toma el ancho de su opción más larga —la del 27B
   pasa de 120 caracteres— y sin tope aplastaba al resto; la etiqueta que lo
   envuelve es en línea, así que el icono se iba a una fila y el selector a otra;
   y ni la marca, ni el lema, ni el chip de disco tenían nowrap, de modo que en vez
   de encoger se partían. Regla: NADA en la cabecera parte línea; lo que sobra se
   recorta. Va antes del bloque responsive para que en móvil siga mandando ese. */
.brand { min-width: 0; }
.brand b, .beta { white-space: nowrap; flex: none; }
.claim { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
#build { flex: none; }
#build a { color: inherit; text-decoration: none; }
#build a:hover { text-decoration: underline; }
.controls { flex: none; }
.model-pick { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.model-pick select { max-width: min(30vw, 380px); text-overflow: ellipsis; }
#disk-chip { white-space: nowrap; flex: none; padding: 4px 10px; font-size: .78rem; border-radius: 999px; }
.model-card { color: var(--muted); text-decoration: none; font-size: .9rem; flex: none; }
.model-card:hover { color: var(--fg); }
.model-card[hidden] { display: none; }
#model-select:disabled { opacity: .6; cursor: progress; }
select {
  background: var(--bg3);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px 8px;
  font-size: .85rem;
}
.dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: none; }
.dot.off { background: #4a5062; }
.dot.loading { background: var(--warn); animation: pulse 1.2s ease-in-out infinite; }
.dot.on { background: var(--ok); }
.dot.gpu { background: var(--accent2); box-shadow: 0 0 8px var(--accent2); }
/* Un mensaje del chat al que se acaba de llevar (ui.irAlMensaje). */
.msg.resaltado { outline: 2px solid var(--accent2); outline-offset: 2px; transition: outline-color .3s; }
/* El estado del cerebro en palabras, junto al punto (el color solo no basta).
   El margen negativo lo arrima al punto: el hueco entre controles es mayor. */
.model-st-txt { font-size: .72rem; color: var(--muted); white-space: nowrap; flex: none; margin-left: -5px; }
.model-st-txt.loading { color: var(--warn); }
@keyframes pulse { 50% { opacity: .35; } }

/* ---------- layout ---------- */
main {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(360px, 42%) 1fr;
  min-height: 0;
}

/* botón flotante chat↔vista: solo existe en móvil */
#btn-flip {
  display: none;
  position: fixed; bottom: 86px; right: 14px; z-index: 60;
  padding: 10px 16px; font-size: .9rem; color: #fff; border: none;
  border-radius: 999px; background: linear-gradient(135deg, var(--accent), var(--accent2));
  box-shadow: 0 8px 24px rgba(0, 0, 0, .5); cursor: pointer;
}


/* ---------- chat ---------- */
#chat {
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--line);
  min-height: 0;
  min-width: 0; /* los chips en nowrap no deben ensanchar la columna */
}
#log { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.msg { padding: 10px 14px; border-radius: 14px; max-width: 92%; white-space: pre-wrap; word-break: break-word; line-height: 1.45; font-size: .93rem; }
.msg.sys { background: linear-gradient(135deg, #1c1430, #14202e); border: 1px solid var(--line); white-space: normal; }
.msg.user { background: var(--accent2); color: #fff; align-self: flex-end; border-bottom-right-radius: 4px; }
.msg.assistant { background: var(--bg3); border: 1px solid var(--line); align-self: flex-start; border-bottom-left-radius: 4px; }
.msg.err { border-color: #a03050; }
/* lo que se oye en la llamada del copiloto: no es un mensaje del usuario */
.msg.transcript { align-self: flex-start; background: none; border-left: 3px solid var(--accent2); border-radius: 4px; color: var(--muted); font-size: .86rem; padding: 4px 10px; }
.msg.transcript b { color: var(--fg); font-weight: 600; }
.msg.thinking {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: var(--bg3); border: 1px dashed var(--line);
  align-self: flex-start; color: var(--muted); font-size: .85rem;
}
.msg.thinking .mini { width: 22px; height: 22px; }
.msg.thinking .dots i {
  display: inline-block; width: 6px; height: 6px; margin-left: 4px;
  border-radius: 50%; background: var(--accent);
  animation: bounce 1.2s ease-in-out infinite;
}
.msg.thinking .dots i:nth-child(2) { animation-delay: .2s; }
.msg.thinking .dots i:nth-child(3) { animation-delay: .4s; }
@keyframes bounce { 0%, 80%, 100% { transform: translateY(0); opacity: .4; } 40% { transform: translateY(-5px); opacity: 1; } }
.msg.thinking .gen {
  width: 100%; font-family: ui-monospace, monospace; font-size: .72rem;
  white-space: pre-wrap; word-break: break-word;
  max-height: 168px; overflow-y: auto; color: #5f6880;
  background: rgba(0,0,0,.16); border-radius: 8px; padding: 6px 8px; margin-top: 4px;
}
.msg.thinking .gen:empty { display: none; }
.msg.thinking .gen.tool-preview {
  font-family: inherit; font-size: .8rem; color: #a9b2c8;
  background: none; max-height: none; overflow: visible; padding: 2px 0;
}
.msg.tool { color: var(--accent); font-size: .8rem; background: none; padding: 0 14px; }
.msg.tool-result { font-size: .8rem; color: var(--muted); background: var(--bg2); border: 1px dashed var(--line); border-radius: 10px; padding: 6px 10px; }
.msg.tool-result.err summary { color: var(--warn); }
.msg.tool-result pre { margin: 6px 0 0; white-space: pre-wrap; word-break: break-word; max-height: 200px; overflow: auto; }
.msg.tool-result summary { cursor: pointer; }

#chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 14px; }
#chips[hidden] { display: none; }   /* tras el primer mensaje del usuario (ui.js) */
.chip {
  font: inherit;
  font-size: .78rem;
  color: var(--muted);
  background: none;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 12px;
  cursor: pointer;
  transition: all .15s;
}
.chip:hover, .chip:focus-visible { color: var(--fg); border-color: var(--accent); }
.chip:focus-visible { outline: 2px solid var(--accent2); outline-offset: 1px; }

/* El campo de texto va en SU PROPIA FILA y los botones debajo.
   Antes compartía fila con ellos, y como los botones se inyectan desde el JS la
   fila fue creciendo hasta seis: el sitio donde se escribe acabó siendo una
   píldora estrecha, del mismo tamaño y forma que sus vecinas, distinguible solo
   por un borde de un píxel. O sea el elemento MENOS visible de la barra, que es
   justo al revés de lo que tiene que ser en un chat. */
#composer {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 12px 14px 16px;
}
#prompt {
  /* Fila entera y la primera, pase lo que pase con los botones de al lado. */
  flex: 1 0 100%;
  order: -1;
  background: var(--bg2, var(--bg3));
  border: 1.5px solid var(--line);
  border-radius: 14px;
  color: var(--fg);
  padding: 15px 16px;
  font-size: 1rem;
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
/* El marcador de posición tiene que LEERSE: es lo único que dice para qué
   sirve la caja cuando está vacía. */
#prompt::placeholder { color: var(--fg3, #8b8b9e); opacity: 1; }
#prompt:focus {
  border-color: var(--accent2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent2) 22%, transparent);
}
#send {
  background: linear-gradient(135deg, var(--accent), var(--accent2));
  color: #fff;
  border: none;
  border-radius: 12px;
  padding: 0 18px;
  font-size: 1rem;
  cursor: pointer;
}
.cbtn.hardwork {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--bg3); border: 1px solid var(--line); color: var(--fg-dim, #9aa0ab);
  border-radius: 12px; padding: 0 12px; font-size: .78rem; cursor: pointer; white-space: nowrap;
}
.cbtn.hardwork:hover { border-color: var(--accent2); color: var(--fg); }
.cbtn.hardwork.on { color: #fff; border-color: var(--accent); background: linear-gradient(135deg, #3a2a18, #2a1f40); box-shadow: 0 0 0 1px var(--accent) inset; }
/* En estrecho la palabra no cabe y solo se ve ⛏, pero se sigue LEYENDO: con
   display:none el nombre accesible del botón se quedaba en el pico «⛏». */
@media (max-width: 560px) { .cbtn.hardwork .hw-txt { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; } }

/* ---------- visualizador ---------- */
/* min-width: 0 para que la fila de pestañas se desplace DENTRO y no ensanche la
   columna: en un teléfono, con 7 pestañas, #viz medía 447 px en una pantalla de
   390 y la página entera se desplazaba de lado (y «💬 Chat» quedaba fuera). */
#viz { display: flex; flex-direction: column; min-height: 0; min-width: 0; background: var(--bg2); }
#tabs { display: flex; gap: 2px; padding: 8px 12px 0; border-bottom: 1px solid var(--line); }
#tabs button {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--muted);
  padding: 8px 14px;
  font-size: .88rem;
  cursor: pointer;
}
#tabs button.active { color: var(--fg); border-bottom-color: var(--accent); }
#tabs button:focus-visible { outline: 2px solid var(--accent2); outline-offset: -2px; border-radius: 4px; }
/* lo que señala una ruta (#/tareas/<id>, #/skills/<nombre>…) */
.resaltado { outline: 2px solid var(--accent); outline-offset: 2px; }
/* enlaces en el chat: URL de fuera y rutas de Claw */
.msg a, .msg.tool-result pre a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; word-break: break-all; }
.msg.tool .tool-link { text-decoration: none; margin-left: 2px; }
.panel { display: none; flex: 1; overflow-y: auto; padding: 16px; min-height: 0; }
.panel.active { display: block; }
#panel-vista { padding: 0; position: relative; }
#panel-vista.active { display: flex; }
#appframe { flex: 1; width: 100%; height: 100%; border: none; background: #0d1117; }
#vista-empty[hidden] { display: none; }
#vista-empty {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  color: var(--muted); text-align: center; gap: 8px;
}
#vista-empty .big { width: 120px; opacity: .5; }

/* ---------- escaparate de descarga (mini-UIs mientras baja el modelo) ---------- */
#loading-stage {
  position: absolute; inset: 0; z-index: 4; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(1100px 700px at 50% 32%, #1a1236, #0b0d12 72%);
}
#loading-stage .ls-galaxy { position: absolute; inset: 0; }
#loading-stage .ls-galaxy canvas.gl { position: absolute; inset: 0; width: 100%; height: 100%; }
#loading-stage .ls-content {
  position: relative; z-index: 1; width: 100%; max-width: 520px; padding: 24px;
  display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center;
}
#loading-stage .ls-window {
  width: min(440px, 82vw); aspect-ratio: 4 / 3; display: flex; flex-direction: column;
  background: #0b0d12; border: 1px solid var(--line); border-radius: 14px; overflow: hidden;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .55), 0 0 0 1px rgba(124, 92, 255, .12),
              0 0 60px rgba(124, 92, 255, .18);
}
#loading-stage .ls-bar-top {
  display: flex; align-items: center; gap: 6px; padding: 8px 12px;
  background: rgba(255, 255, 255, .03); border-bottom: 1px solid var(--line);
}
#loading-stage .ls-bar-top .d { width: 9px; height: 9px; border-radius: 50%; opacity: .8; }
#loading-stage .ls-bar-top .d.r { background: #ff6b6b; }
#loading-stage .ls-bar-top .d.y { background: #ffc94a; }
#loading-stage .ls-bar-top .d.g { background: #5fbf6e; }
#loading-stage .ls-badge {
  margin-left: 8px; font-size: .72rem; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#loading-stage .ls-frames { position: relative; flex: 1; }
#loading-stage .ls-frame {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: #090a11;
  opacity: 0; transition: opacity .6s ease; pointer-events: none;
}
#loading-stage .ls-frame.on { opacity: 1; }
#loading-stage .ls-head {
  margin-top: 4px; font-size: 1.18rem; font-weight: 600;
  background: linear-gradient(90deg, var(--accent), var(--accent2));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
#loading-stage .ls-sub { margin: -4px 0 2px; color: var(--muted); font-size: .86rem; line-height: 1.5; max-width: 420px; }
#loading-stage .ls-sub b { color: var(--fg); }
#loading-stage .ls-prog { width: min(320px, 76vw); height: 5px; background: var(--bg); border-radius: 3px; overflow: hidden; }
#loading-stage .ls-bar {
  height: 100%; width: 0; border-radius: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent2)); transition: width .3s ease;
}
#loading-stage .ls-bar.indet { width: 38%; animation: indet 1.1s ease-in-out infinite; }
#loading-stage .ls-progtext { font-size: .74rem; color: var(--muted); font-family: ui-monospace, monospace; min-height: 1.1em; }
@media (prefers-reduced-motion: reduce) {
  #loading-stage .ls-frame { transition: none; }
  #loading-stage .ls-bar.indet { animation: none; }
}
@media (max-width: 820px) {
  #loading-stage .ls-window { width: min(360px, 86vw); }
  #loading-stage .ls-head { font-size: 1.05rem; }
}
.msg.sys .avatar { width: 44px; height: 44px; float: left; margin: 2px 10px 4px 0; }

/* ---------- tarjetas y controles de paneles ---------- */
.card {
  display: flex; align-items: center; gap: 10px;
  background: var(--bg3);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
  font-size: .9rem;
}
.card b { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.card code { background: var(--bg); padding: 2px 8px; border-radius: 6px; max-width: 40%; overflow: hidden; text-overflow: ellipsis; }
.card.col { flex-direction: column; align-items: stretch; gap: 8px; }
/* Solo el título de la tarjeta (hijo directo). Con `.card.col b` también caía
   en el nombre de la fila de cada skill y de cada repo, que ya no podía encoger
   ni partirse: hasta 1280 px, «Explorar» y «Quitar» quedaban fuera del panel. */
.card.col > b { flex: none; }
/* Skills: enlaces a repos y SKILL.md, la lista de un repo dentro de su tarjeta y
   el texto que se le da al modelo. La fila de cada tarjeta (nombre, repo,
   enlace, botones) baja a otra línea lo que no cabe: el nombre va primero, entero
   si cabe, y los nombres largos se parten en vez de empujar los botones fuera. */
.repo-link { color: var(--accent2); font-size: .74rem; text-decoration: none; overflow-wrap: anywhere; min-width: 0; }
.skills-instaladas .row.between, .skills-fuentes .row.between, .repo-skills .card { flex-wrap: wrap; gap: 6px 10px; }
.skills-instaladas .row.between > :not(button), .skills-fuentes .row.between > :not(button), .repo-skills .card > :not(button) { min-width: 0; overflow-wrap: anywhere; }
.skills-instaladas .row.between > button, .skills-fuentes .row.between > button, .repo-skills .card > button { flex: none; }
.skills-instaladas .row.between > b, .skills-fuentes .row.between > b, .repo-skills .card > b { flex: 1 1 auto; }
/* Cada catálogo, igual en todas las tarjetas: nombre y repo uno debajo del
   otro, y su botón a la derecha. Antes el botón bajaba a otra línea solo cuando
   el nombre era largo y cada tarjeta quedaba distinta. */
.skills-fuentes .card > .row.between { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 2px 10px; margin: 0; }
.skills-fuentes .card > .row.between > b { grid-column: 1; grid-row: 1; }
.skills-fuentes .card > .row.between > .repo-link { grid-column: 1; grid-row: 2; }
.skills-fuentes .card > .row.between > button { grid-row: 1 / span 2; }
.sk-h { font-size: .74rem; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; font-weight: 600; margin: 14px 0 8px; }
.sk-h:focus { outline: none; }
.sk-h:focus-visible { outline: 2px solid var(--accent2); outline-offset: 2px; }
.sk-nota { margin: -4px 0 8px; font-size: .78rem; }
.prov-name { font-weight: 700; flex: 1; cursor: pointer; }
.panel .card a { color: var(--accent2); }
.repo-link:hover { text-decoration: underline; }
.repo-skills { display: flex; flex-direction: column; gap: 6px; }
.repo-skills[hidden] { display: none; }
.repo-skills .card { margin-bottom: 0; background: var(--bg2); }
.skill-text { white-space: pre-wrap; word-break: break-word; max-height: 260px; overflow: auto; font-size: .76rem; color: var(--muted); background: var(--bg); border-radius: 8px; padding: 8px 10px; margin: 6px 0 0; }
.card details summary { cursor: pointer; font-size: .8rem; color: var(--muted); }
.row.between { justify-content: space-between; align-items: center; }
.field { display: flex; flex-direction: column; gap: 3px; }
.field .muted { font-size: .74rem; }
.msg.user.queued { opacity: .55; }
.msg.user.queued::after { content: ' ⏳'; }
/* en cola cuando pulsaste ■: no se llegó a procesar ni se procesará */
.msg.user.cancelled { opacity: .45; text-decoration: line-through; }
.muted { color: var(--muted); font-size: .82rem; }
.row { display: flex; gap: 8px; margin: 10px 0; }
.row.right { justify-content: flex-end; }
.panel input {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--fg);
  padding: 9px 12px;
  flex: 1;
}
button.primary {
  background: linear-gradient(135deg, var(--accent), var(--accent2));
  color: #fff; border: none; border-radius: 8px; padding: 9px 16px; cursor: pointer; font-size: .88rem;
}
button.ghost {
  background: none; color: var(--muted);
  border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px; cursor: pointer; font-size: .85rem;
}
button.ghost:hover { color: var(--fg); border-color: var(--accent); }
/* Ocupado o ya hecho (una skill instalada): aria-disabled en vez de disabled,
   para que el botón no pierda el foco (ver btn en ui.js). */
.panel button[aria-disabled="true"], .mobile-gate button[aria-disabled="true"] { opacity: .6; cursor: default; }
.panel button[aria-busy="true"], .mobile-gate button[aria-busy="true"] { cursor: progress; }
h3 { margin: 6px 0 12px; font-size: .95rem; }

/* ---------- modal de permisos ---------- */
dialog {
  background: var(--bg2);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 22px 24px;
  max-width: 420px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .6);
}
dialog::backdrop { background: rgba(5, 6, 10, .7); backdrop-filter: blur(3px); }
dialog h3 { margin: 0 0 8px; }
dialog p { margin: 6px 0; font-size: .9rem; }

/* ---------- toasts y progreso ---------- */
/* Por ENCIMA de la Mente (z-index 300): sus avisos tienen que verse y poder
   pulsarse con ella abierta (modal.js los deja vivos). Con el splash de
   bienvenida delante no se enseñan (siguen inertes detrás, como antes). */
#toasts { position: fixed; bottom: 18px; right: 18px; display: flex; flex-direction: column; gap: 8px; z-index: 310; }
body:has(#splash:not([hidden])) #toasts { visibility: hidden; }
.toast {
  background: var(--bg3);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: .85rem;
  max-width: 340px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, .5);
  animation: slidein .2s ease-out;
  display: flex; align-items: flex-start; gap: 8px;
}
@keyframes slidein { from { transform: translateX(20px); opacity: 0; } }
.toast .toast-txt { flex: 1; min-width: 0; }
.toast .toast-accion {
  flex: none; background: none; border: 1px solid var(--accent); color: var(--fg);
  border-radius: 6px; padding: 2px 8px; font-size: .8rem; cursor: pointer; white-space: nowrap;
}
.toast .toast-accion:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.toast .toast-x {
  flex: none; background: none; border: none; color: var(--muted); cursor: pointer;
  font-size: .8rem; padding: 0 2px; line-height: 1.4;
}
.toast .toast-x:hover { color: var(--fg); }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }
#model-progress {
  position: fixed; bottom: 18px; left: 18px; z-index: 50;
  background: var(--bg3); border: 1px solid var(--line); border-radius: 10px;
  padding: 10px 14px; font-size: .8rem; color: var(--muted); width: 300px;
}
#model-progress .track { height: 4px; background: var(--bg); border-radius: 2px; margin-bottom: 6px; overflow: hidden; }
#model-bar { height: 100%; width: 0; background: linear-gradient(90deg, var(--accent), var(--accent2)); transition: width .2s; }
#model-bar.indet { width: 35%; animation: indet 1.1s ease-in-out infinite; }
@keyframes indet { 0% { margin-left: -35%; } 100% { margin-left: 100%; } }

/* ---------- splash de primera visita ---------- */
#splash {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(1100px 700px at 50% 28%, #16182a, #090a11 72%);
  text-align: center; transition: opacity .6s ease;
}
#splash[hidden] { display: none; }
#splash canvas.gl { position: absolute; inset: 0; width: 100%; height: 100%; }
#splash .s-inner { position: relative; z-index: 1; max-width: 540px; padding: 28px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
#splash svg { width: 190px; height: 190px; animation: sfloat 5s ease-in-out infinite; filter: drop-shadow(0 12px 40px rgba(124, 92, 255, .35)); }
@keyframes sfloat { 50% { transform: translateY(-9px); } }
#splash .spark { animation: spark 2.4s ease-in-out infinite; transform-origin: center; }
#splash .spark.s2 { animation-delay: 1.2s; }
@keyframes spark { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
#splash h1 { margin: 10px 0 2px; font-size: 1.7rem; }
#splash h1 b { background: linear-gradient(90deg, var(--accent), var(--accent2)); -webkit-background-clip: text; background-clip: text; color: transparent; }
#splash .l { margin: 0; color: var(--muted); font-size: 1.02rem; opacity: 0; animation: srise .7s ease-out forwards; }
#splash .l b { color: var(--accent); }
#splash .l1 { animation-delay: .6s; }
#splash .l2 { animation-delay: 1.7s; }
#splash .l3 { animation-delay: 2.8s; }
#splash .l4 { animation-delay: 3.9s; font-size: 1.12rem; color: var(--fg); }
@keyframes srise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
/* el guiño: el ojo derecho se cierra un instante, sincronizado con «entre tú y yo» */
#splash .eye-r { transform-origin: 76px 73px; animation: wink 5s ease-in-out 4.1s infinite; }
@keyframes wink { 0%, 7%, 100% { transform: scaleY(1); } 3.5% { transform: scaleY(.06); } }
#splash button {
  margin-top: 16px; padding: 13px 38px; font-size: 1.05rem; cursor: pointer;
  color: #fff; border: none; border-radius: 999px;
  background: linear-gradient(135deg, var(--accent), var(--accent2));
  box-shadow: 0 8px 30px rgba(255, 77, 141, .35);
  opacity: 0; animation: srise .7s ease-out 4.9s forwards;
}
#splash button:hover { filter: brightness(1.1); }
/* con el teclado, «Entrar» se ve en cuanto tiene el foco (no tras la animación) */
#splash button:focus-visible { opacity: 1; animation: none; outline: 2px solid #fff; outline-offset: 3px; }
/* sin animaciones si el sistema lo pide: todo a la vista desde el principio */
@media (prefers-reduced-motion: reduce) {
  #splash, #splash .l, #splash button, #splash svg, #splash .spark, #splash .eye-r { animation: none !important; transition: none !important; }
  #splash .l, #splash button { opacity: 1; }
}

/* ---------- móvil: una columna, chat ↔ visualizador conmutables ---------- */
@media (max-width: 700px) {
  main { grid-template-columns: minmax(0, 1fr); }
  #btn-flip { display: block; }
  /* por encima de los chips y del compositor (su alto lo mide ui.js en
     --alto-pie): antes tapaba la fila de chips */
  #btn-flip { bottom: calc(var(--alto-pie, 150px) + 8px); }
  body.show-viz #btn-flip { bottom: 14px; }
  #viz { display: none; }
  body.show-viz #viz { display: flex; }
  body.show-viz #chat { display: none; }
  #chat { border-right: none; }

  header { padding: 8px 10px; gap: 6px; }
  .claim { display: none; }
  .beta { display: none; }
  .brand { font-size: .95rem; gap: 6px; }
  .logo { width: 26px; height: 26px; }
  .controls { gap: 6px; }
  /* En móvil la cabecera no cabe entera, así que aquí SÍ se encoge — pero lo
     que encoge es el selector (se queda con el hueco que sobre), no los botones.
     Sin esto, el nowrap de la regla general cambiaba «se parte en líneas» por
     «Permisos se sale de la pantalla», que es peor: medido a 390 px. */
  .controls { flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
  .model-pick { flex: 1 1 auto; min-width: 0; }
  .model-pick select { max-width: none; width: 100%; min-width: 0; font-size: .78rem; }
  #disk-chip { padding: 4px 7px; font-size: .72rem; }
  /* Solo el logo como marca. El nombre y el icono del selector no caben en un
     teléfono, y con el nombre dentro el selector se le montaba ENCIMA: medido a
     390 px, «Elffu» asomaba por detrás de la caja del selector. Al tocarlo se
     abre el selector nativo del sistema, que sí enseña los nombres enteros. */
  .brand { flex: none; }
  .brand b, #model-ico, .model-card { display: none; }
  #btn-clear, #btn-perms { padding: 7px 9px; font-size: .78rem; }
  .model-st-txt { margin-left: -2px; font-size: .68rem; }

  #log { padding: 10px; }
  .msg { max-width: 100%; font-size: .9rem; }
  .msg.sys .avatar { width: 36px; height: 36px; }

  #chips { flex-wrap: nowrap; overflow-x: auto; padding: 6px 10px; scrollbar-width: none; }
  #chips::-webkit-scrollbar { display: none; }
  .chip { flex: 0 0 auto; }

  #composer { padding: 8px 10px 12px; }
  #prompt { font-size: 16px; } /* evita el zoom automático de iOS */
  #send { padding: 0 16px; min-width: 48px; }

  #tabs { overflow-x: auto; scrollbar-width: none; }
  #tabs button { padding: 8px 10px; font-size: .82rem; white-space: nowrap; }
  .panel { padding: 12px; }
  /* el botón flotante «Chat» no tapa lo último del panel (un «Instalar») */
  body.show-viz .panel:not(#panel-vista) { padding-bottom: 72px; }
  .card { flex-wrap: wrap; }

  dialog { max-width: 92vw; margin: auto; }
  /* Los avisos van ENCIMA del compositor y del botón ⇄, como la caja de
     progreso, y encima de ella si está a la vista (--alto-progreso, ui.js).
     Abajo del todo tapaban ■, ⛏ y /, y en un teléfono ■ es la única forma de
     parar: el toque caía en el aviso. */
  #toasts { left: 12px; right: 12px; bottom: calc(var(--alto-pie, 150px) + 56px + var(--alto-progreso, 0px)); }
  body.show-viz #toasts { bottom: calc(60px + var(--alto-progreso, 0px)); }
  .toast { max-width: none; }
  /* Encima del compositor y del botón ⇄, que ya flota sobre --alto-pie: a 390 px
     la caja de progreso tapaba la caja de texto durante toda la descarga (el
     camino normal tras «Descargarlo igualmente»). En la Vista no hay
     compositor: basta con dejar sitio al botón. */
  #model-progress { left: 12px; right: 12px; width: auto; bottom: calc(var(--alto-pie, 150px) + 56px); }
  body.show-viz #model-progress { bottom: 60px; }

  #splash svg { width: 140px; height: 140px; }
  #splash h1 { font-size: 1.35rem; }
  #splash .l { font-size: .92rem; }
  #splash .s-inner { padding: 18px; }
}


/* ---------- markdown en el chat (estilo plugin de agente) ---------- */
.msg.md { white-space: normal; }
.msg.md code {
  background: #0d1117; border: 1px solid var(--line); border-radius: 5px;
  padding: 1px 6px; font-family: ui-monospace, monospace; font-size: .8em; color: #ffb3c9;
}
.msg.md pre.codeblock {
  position: relative; background: #0d1117; border: 1px solid var(--line);
  border-radius: 8px; padding: 10px 12px; margin: 8px 0; overflow-x: auto;
}
.msg.md pre.codeblock code {
  background: none; border: none; padding: 0; color: #c9d1d9;
  font-size: .78rem; line-height: 1.5; white-space: pre;
}
.msg.md pre.codeblock .lang {
  position: absolute; top: 4px; right: 8px; font-size: .64rem;
  color: var(--muted); text-transform: uppercase; letter-spacing: .06em;
}
.msg.md h4 { margin: 10px 0 4px; font-size: .95rem; }
.msg.md ul { margin: 4px 0; padding-left: 18px; }
.msg.md li { margin: 2px 0; }
.msg.md b { color: #fff; }

/* ---------- iconos vectoriales + menú de comandos (/) ---------- */
.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 30px; padding: 0; }
.icon-btn svg, .icon-inline svg { width: 16px; height: 16px; }
.icon-inline { display: inline-flex; vertical-align: middle; color: var(--muted); }
#send { display: inline-flex; align-items: center; justify-content: center; }
#send svg { width: 18px; height: 18px; }
/* mientras trabaja, el mismo botón PARA (como en Elffuss Code) */
#send.is-stop { background: linear-gradient(135deg, #e5484d, #c0353a); }
#send.is-stop svg { width: 14px; height: 14px; }
/* ■ ya pulsado y el turno aún soltando el modelo: «Parando…», sin más clics */
#send.is-stopping { background: #7a2a2d; color: #f3d6d7; cursor: progress; font-size: .78rem; white-space: nowrap; }
.msg.thinking.stopping .dots i { animation: none; opacity: .35; }
/* lo que llegó a escribir antes de parar: se queda, apagado */
.msg.assistant.partial { opacity: .75; }
#btn-clear[aria-busy="true"] { opacity: .5; cursor: progress; }
/* solo para lectores de pantalla */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
#btn-slash { background: var(--bg3); border: 1px solid var(--line); border-radius: 12px; color: var(--muted); }
#btn-slash:hover { color: var(--fg); border-color: var(--accent2); }
#cmd-menu {
  position: absolute; left: 14px; right: 14px; bottom: 72px; z-index: 40;
  background: var(--bg3); border: 1px solid var(--accent2); border-radius: 12px;
  box-shadow: 0 -8px 30px rgba(0,0,0,.5); max-height: 320px; overflow-y: auto; padding: 4px;
}
#cmd-menu[hidden] { display: none; }
.cmd-item { display: flex; justify-content: space-between; gap: 12px; width: 100%; text-align: left; background: none; border: none; color: var(--fg); padding: 8px 12px; border-radius: 8px; cursor: pointer; font-size: .86rem; }
.cmd-item:hover, .cmd-item.activo, .cmd-item:focus-visible { background: #ffffff14; outline: none; }
.cmd-item.activo { box-shadow: inset 2px 0 0 var(--accent2); }
.cmd-vacio { padding: 8px 12px; color: var(--muted); font-size: .82rem; }
/* atajos de teclado («?» o /atajos) */
dl.atajos { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 8px 0 4px; font-size: .88rem; }
dl.atajos dt { text-align: right; }
dl.atajos dd { margin: 0; color: var(--muted); }
kbd { font-family: ui-monospace, monospace; font-size: .8rem; background: var(--bg3); border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 5px; padding: 1px 6px; }
.cmd-item b { font-family: ui-monospace, monospace; font-weight: 600; }
.cmd-item span { color: var(--muted); font-size: .76rem; }
#chat { position: relative; }

/* ── Mente de Elffuss (cerebro CEO · mundo trance) ─────────────────────── */
#mind-overlay { position: fixed; inset: 0; z-index: 300; background: radial-gradient(1200px 800px at 50% 45%, #1a0a2e, #05030c 78%); overflow: hidden; }
#mind-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
#mind-title { position: absolute; top: 16px; left: 50%; transform: translateX(-50%); text-align: center; font-size: 1.1rem; font-weight: 800; letter-spacing: .18em; color: #fff; text-shadow: 0 0 22px #ff4d8d; pointer-events: none; }
#mind-title span { display: block; font-size: .66rem; font-weight: 500; letter-spacing: .06em; color: #b9a7ff; margin: 4px auto 0; text-shadow: none; max-width: min(520px, 44vw); }
/* en estrecho la explicación no cabe sin tapar los botones: se queda solo para
   el lector de pantalla (aria-describedby la sigue leyendo) */
@media (max-width: 900px) { #mind-title span { display: none; } }
#mind-close { position: absolute; top: 14px; right: 16px; z-index: 6; background: rgba(255,77,141,.14); border: 1px solid #ff4d8d; color: #ffd7e6; border-radius: 999px; padding: 7px 14px; font-size: .8rem; cursor: pointer; backdrop-filter: blur(6px); }
#mind-close:hover { background: rgba(255,77,141,.28); }
#mind-history { position: absolute; top: 14px; right: 182px; z-index: 6; background: rgba(73,232,221,.14); border: 1px solid #49e8ff; color: #bfeef6; border-radius: 999px; padding: 7px 12px; font-size: .78rem; cursor: pointer; backdrop-filter: blur(6px); }
#mind-history:hover { background: rgba(73,232,221,.28); }
#mind-playstop { position: absolute; top: 14px; right: 278px; z-index: 6; background: rgba(63,185,112,.16); border: 1px solid #3fb970; color: #b7f2cf; border-radius: 999px; padding: 7px 12px; font-size: .78rem; cursor: pointer; backdrop-filter: blur(6px); }
#mind-playstop:hover { background: rgba(63,185,112,.3); }
#mind-playstop.paused { background: rgba(255,180,70,.16); border-color: #ffb446; color: #ffe0b0; }
#mind-playstop.paused:hover { background: rgba(255,180,70,.3); }
#mind-config { position: absolute; top: 14px; right: 96px; z-index: 6; background: rgba(124,92,255,.16); border: 1px solid #7c5cff; color: #d8ccff; border-radius: 999px; padding: 7px 12px; font-size: .78rem; cursor: pointer; backdrop-filter: blur(6px); }
#mind-config:hover { background: rgba(124,92,255,.3); }
/* leyenda de perfiles: fija, no flota (siempre legible) */
#mind-legend { position: absolute; top: 60px; left: 14px; z-index: 5; display: flex; flex-direction: column; gap: 5px; background: rgba(8,5,18,.5); border: 1px solid rgba(124,92,255,.3); border-radius: 10px; padding: 8px 12px; backdrop-filter: blur(6px); pointer-events: auto; }
.ml-item { font: inherit; font-size: .68rem; color: #cfe8f0; display: flex; align-items: center; gap: 7px; cursor: pointer; padding: 2px 4px; border-radius: 5px; background: none; border: none; text-align: left; }
.ml-item:hover, .ml-item:focus-visible { background: rgba(255,255,255,.08); }
.ml-sw { width: 9px; height: 9px; border-radius: 50%; box-shadow: 0 0 6px currentColor; flex: none; }
/* solo etiquetas de propuestas forjadas flotan ancladas al mundo */
#mind-anchors { position: absolute; inset: 0; pointer-events: none; z-index: 3; }
/* la capa no recibe clics (deja girar el mundo), pero cada etiqueta SÍ: es un
   botón y su clic abre la propuesta. Antes heredaba pointer-events:none y solo
   funcionaba atinar a la malla 3D que hubiera debajo. */
.mind-node-label { position: absolute; font: inherit; font-size: .6rem; color: #ffd7e6; background: rgba(255,77,141,.18); border: 1px solid rgba(255,77,141,.5); border-radius: 6px; padding: 1px 6px; pointer-events: auto; cursor: pointer; white-space: nowrap; text-shadow: 0 0 8px #ff4d8d; }
.mind-node-label:hover, .mind-node-label:focus-visible { background: rgba(255,77,141,.34); outline: 1px solid #ffd7e6; }
#mind-overlay button:focus-visible { outline: 2px solid #ffd7e6; outline-offset: 2px; }
.ml-open { margin-left: 6px; background: none; border: 1px solid rgba(73,232,221,.45); color: #bfeef6; border-radius: 5px; padding: 0 6px; font-size: .62rem; cursor: pointer; }
.cfg-status { font-size: .72rem; color: #bfeef6; min-height: 1em; }
.cfg-status:empty { display: none; }
.mind-music-btn { position: absolute; bottom: 14px; right: 14px; z-index: 6; background: rgba(255,77,141,.14); border: 1px solid rgba(255,77,141,.5); color: #ffd7e6; border-radius: 999px; padding: 6px 12px; font-size: .74rem; cursor: pointer; backdrop-filter: blur(6px); }
.mind-music-btn:hover { background: rgba(255,77,141,.28); }
.mind-music-cap a { color: #ffd7e6; }
/* historial completo: TODO lo que ha llegado, sin recortar */
#mind-log { position: absolute; top: 0; right: -380px; width: 360px; height: 100%; z-index: 8; display: flex; flex-direction: column; background: rgba(6,4,14,.92); border-left: 1px solid rgba(73,232,221,.35); backdrop-filter: blur(10px); transition: right .25s ease; }
#mind-log.show { right: 0; }
.ml-head { display: flex; align-items: center; padding: 12px 14px; font-size: .82rem; font-weight: 700; color: #bfeef6; border-bottom: 1px solid rgba(73,232,221,.25); }
.ml-head button { margin-left: auto; background: none; border: none; color: #7fd9d0; cursor: pointer; font-size: .9rem; }
#mind-log-body { flex: 1; overflow-y: auto; padding: 8px 10px; }
.ml-row { font-size: .68rem; line-height: 1.6; padding: 3px 4px; border-radius: 5px; display: flex; gap: 6px; align-items: baseline; }
.ml-row:hover { background: rgba(255,255,255,.04); }
.ml-row .ml-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.ml-row .ml-t { color: #dfeef2; word-break: break-word; }
/* panel flotante con el .md del pensamiento (clic en un nodo) */
#mind-panel { position: absolute; top: 70px; right: 16px; width: min(420px, 40vw); max-height: 70vh; z-index: 6; display: none; flex-direction: column; background: rgba(8,5,18,.9); border: 1px solid #7c5cff; border-radius: 12px; overflow: hidden; box-shadow: 0 12px 50px rgba(0,0,0,.6); }
#mind-panel.show { display: flex; }
#mind-panel .mp-head { display: flex; align-items: center; gap: 8px; padding: 8px 12px; font-size: .74rem; color: #d8ccff; background: rgba(124,92,255,.14); border-bottom: 1px solid rgba(124,92,255,.3); }
#mind-panel .mp-head button { margin-left: auto; background: none; border: none; color: #b9a7ff; cursor: pointer; font-size: .9rem; }
#mind-panel .mp-body { flex: 1; overflow: auto; margin: 0; padding: 12px; font-size: .78rem; line-height: 1.55; color: #cfe8f0; }
#mind-panel .mp-body h1, #mind-panel .mp-body h2, #mind-panel .mp-body h3 { color: #fff; margin: 12px 0 6px; }
#mind-panel .mp-body code { background: rgba(124,92,255,.18); padding: 1px 5px; border-radius: 4px; font-size: .82em; }
#mind-panel .mp-body pre { background: #0b0716; border: 1px solid rgba(124,92,255,.3); border-radius: 8px; padding: 8px; overflow-x: auto; }
#mind-panel .mp-body ul, #mind-panel .mp-body ol { padding-left: 1.2em; }
.mp-actions { display: flex; gap: 8px; padding: 0 12px 12px; }
.mp-exec { flex: 1; background: linear-gradient(135deg, #ff4d8d, #7c5cff); border: none; color: #fff; border-radius: 8px; padding: 9px; cursor: pointer; font-size: .78rem; font-weight: 600; }
.mp-open { flex: 1; background: rgba(124,92,255,.15); border: 1px solid #7c5cff; color: #d8ccff; border-radius: 8px; padding: 9px; cursor: pointer; font-size: .78rem; }
/* panel de configuración del cerebro */
#mind-cfg { position: absolute; top: 60px; left: 50%; transform: translateX(-50%); width: min(520px, 92vw); z-index: 7; display: none; flex-direction: column; gap: 6px; background: rgba(8,5,18,.94); border: 1px solid #7c5cff; border-radius: 14px; padding: 14px 16px; box-shadow: 0 16px 60px rgba(0,0,0,.6); }
#mind-cfg.show { display: flex; }
.cfg-head { display: flex; align-items: center; font-size: .9rem; font-weight: 700; color: #fff; margin-bottom: 4px; }
.cfg-head button { margin-left: auto; background: none; border: none; color: #b9a7ff; cursor: pointer; }
.cfg-notif { font-size: .68rem; color: #9fb; background: rgba(63,185,112,.1); border: 1px solid rgba(63,185,112,.3); border-radius: 8px; padding: 6px 10px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cfg-notif-btn { background: #3fb970; border: none; color: #06180d; border-radius: 6px; padding: 3px 10px; font-size: .68rem; font-weight: 700; cursor: pointer; }
#mind-cfg label { font-size: .68rem; color: #b9a7ff; margin-top: 4px; }
#mind-cfg textarea, #mind-cfg input:not([type=color]) { background: #0b0716; border: 1px solid rgba(124,92,255,.4); color: #e8ebf4; border-radius: 8px; padding: 8px 10px; font-size: .78rem; font-family: inherit; resize: vertical; }
#cfg-profiles { display: flex; flex-direction: column; gap: 6px; max-height: 200px; overflow-y: auto; }
.cfg-prof { display: grid; grid-template-columns: 30px 1fr 1.4fr 26px; gap: 6px; align-items: center; }
.cfg-prof input[type=color] { width: 30px; height: 30px; padding: 0; border: 1px solid rgba(124,92,255,.4); border-radius: 6px; background: none; cursor: pointer; }
.cfg-prof input[type=text] { background: #0b0716; border: 1px solid rgba(124,92,255,.4); color: #e8ebf4; border-radius: 6px; padding: 6px 8px; font-size: .72rem; }
.cp-del { background: none; border: none; color: #ff8fb0; cursor: pointer; font-size: .8rem; }
.cfg-add { align-self: flex-start; background: rgba(124,92,255,.15); border: 1px dashed rgba(124,92,255,.5); color: #d8ccff; border-radius: 8px; padding: 6px 12px; font-size: .74rem; cursor: pointer; margin-top: 4px; }
.cfg-actions { display: flex; gap: 8px; margin-top: 8px; }
.cfg-ghost { flex: 1; background: rgba(73,232,221,.14); border: 1px solid #49e8ff; color: #bfeef6; border-radius: 8px; padding: 9px; cursor: pointer; font-size: .78rem; }
.cfg-save { flex: 1; margin-top: 0; background: linear-gradient(135deg, #ff4d8d, #7c5cff); border: none; color: #fff; border-radius: 8px; padding: 9px; cursor: pointer; font-size: .8rem; font-weight: 600; }
.cfg-note { font-size: .64rem; color: #8a7bb8; margin-top: 4px; }
.mind-music { position: absolute; bottom: 52px; right: 14px; z-index: 5; width: 300px; border-radius: 12px; overflow: hidden; border: 1px solid rgba(255,77,141,.4); box-shadow: 0 8px 30px rgba(0,0,0,.5); }
.mind-music-cap { font-size: .62rem; color: #ffd7e6; background: rgba(10,6,24,.8); padding: 4px 8px; text-align: center; }
.proposal-exec-btn { display: block; margin-top: 10px; background: linear-gradient(135deg, var(--accent), var(--accent2)); border: none; color: #fff; border-radius: 8px; padding: 8px 14px; font-size: .78rem; font-weight: 600; cursor: pointer; }
.proposal-exec-btn:hover { filter: brightness(1.1); }
.proposal-exec-btn:disabled { opacity: .6; cursor: default; filter: none; }
/* En Básico no hay con qué ejecutar una propuesta: el botón se esconde y en su
   sitio se dice que hace falta un modelo, con un botón para elegirlo. */
.proposal-needs-model { display: none; margin-top: 10px; font-size: .78rem; color: var(--muted); align-items: center; gap: 8px; flex-wrap: wrap; }
.proposal-needs-model button { background: none; border: 1px solid var(--line); color: var(--fg, inherit); border-radius: 8px; padding: 5px 10px; font-size: .78rem; cursor: pointer; }
body.modo-basico .proposal-exec-btn, body.modo-basico #mp-exec { display: none; }
body.modo-basico .proposal-needs-model { display: flex; }

/* modelos externos: sección plegada, al final y visualmente secundaria */
.ext-block{opacity:.72}
.ext-block:hover,.ext-block[open]{opacity:1}
.ext-block>summary{cursor:pointer;font-weight:600;font-size:.9rem;list-style:none;padding:2px 0}
.ext-block>summary::-webkit-details-marker{display:none}
.ext-block>summary::before{content:'▸ ';color:var(--accent)}
.ext-block[open]>summary::before{content:'▾ '}

/* ── Velocímetro ─────────────────────────────────────────────────────────────
   Panel anclado a la derecha de la cabecera. Posición fija y no absoluta
   respecto al header a propósito: el header tiene overflow y recortaba la
   gráfica por abajo. */
#speed-panel {
  position: fixed; top: 52px; right: 12px; z-index: 60;
  width: min(280px, calc(100vw - 24px));
  background: var(--panel, #15161c); color: var(--fg, #e8e8ef);
  border: 1px solid var(--line, #2a2b36); border-radius: 10px;
  padding: 12px 14px; box-shadow: 0 10px 30px rgba(0,0,0,.45);
  font-size: .82rem; line-height: 1.35;
}
#speed-panel[hidden] { display: none; }
.vm-tit { font-weight: 600; margin-bottom: 8px; }
.vm-tit2 { margin-top: 14px; }
.vm-filas { display: grid; gap: 6px; }
.vm-filas > div { display: flex; align-items: baseline; gap: 8px; }
.vm-filas b { font-variant-numeric: tabular-nums; font-size: 1.05rem; min-width: 4.2em; }
.vm-filas span { opacity: .72; }
.vm-graf { margin: 10px 0 2px; }
.vm-graf-top, .vm-graf-pie { display: flex; justify-content: space-between; opacity: .6; font-size: .72rem; }
.vm-graf svg { width: 100%; height: 38px; display: block; margin: 3px 0; }
.vm-vacio { opacity: .55; font-size: .76rem; margin: 6px 0; }
.vm-nota { margin-top: 12px; opacity: .5; font-size: .7rem; line-height: 1.3; }
.vm-modelo { font-weight: 400; opacity: .6; font-size: .78rem; }
/* El aviso de «leer va tan lento como escribir»: es un sintoma, no un dato. */
.vm-alerta { margin: 10px 0 2px; padding: 8px 10px; border-radius: 8px; font-size: .75rem;
  line-height: 1.35; background: rgba(255,176,32,.10); border: 1px solid rgba(255,176,32,.28); }

/* Barra del PREFILL dentro de la burbuja de «pensando». El prefill es la espera
   larga antes de la primera letra y no se veía: con un prompt de arnés en el
   modelo grande son decenas de segundos de burbuja quieta, que se leen como un
   cuelgue. Sin animación propia: el ancho lo mueve el motor por lote terminado
   en la GPU, así que la barra avanza cuando hay trabajo hecho y se para cuando
   de verdad está parada — que es justo la información que hace falta. */
.msg.thinking .prefill { height: 3px; border-radius: 2px; background: #ffffff1a; margin: 6px 0 2px; overflow: hidden; }
.msg.thinking .prefill > i { display: block; height: 100%; width: 0; border-radius: 2px; background: currentColor; opacity: .7; transition: width .18s linear; }

/* ── Dedos, no ratón ────────────────────────────────────────────────────────
   Medido en un iPhone (393 px de ancho): los controles de las barras salían a
   30-36 px de alto. La guía de Apple pide 44 y no es capricho: por debajo de
   eso se falla el toque y se pulsa el de al lado, que en una barra con el botón
   de limpiar al lado del de enviar es caro.
   Va bajo `pointer: coarse` y no bajo un ancho: lo que decide no es el tamaño
   de la pantalla sino con qué se toca. Una tablet grande con dedo lo necesita;
   una ventana estrecha con ratón, no — y encajonar el escritorio a 44 px le
   estropearía la densidad sin motivo. */
@media (pointer: coarse) {
  #composer button, #composer select, #composer input,
  .bar button, .bar select, #tabs button, button.ghost,
  #model-select, #send, #btn-clear, #btn-mind, #btn-perms,
  #btn-slash, #btn-hardwork, #btn-flip {
    min-height: 44px;
  }
  /* Los que además son estrechos: un cuadrado de 44 se falla por los lados. */
  #btn-clear, #btn-mind, #btn-slash, #btn-hardwork { min-width: 44px; }
  /* El alto crece, así que el espacio entre ellos puede bajar sin apelotonarse. */
  #composer { gap: 6px; }
}
