/*
 * Hoja única, escrita de móvil hacia arriba: lo que se ve sin ninguna media
 * query es la versión de teléfono, que es donde se revisa de verdad. Las
 * pantallas grandes sólo añaden columnas.
 */

:root {
  --bg: #0f1216;
  --surface: #171b21;
  --surface-2: #1e242c;
  --line: #2a323d;
  --text: #e6e9ee;
  --muted: #97a1b0;
  /*
   * La paleta se divide en dos papeles, y conviene no mezclarlos:
   *
   *   --x        relleno. Va detrás de algo, y encima lleva --on-fill.
   *   --x-ink    tinta. Es texto, y va sobre --surface o --surface-2.
   *
   * Un color de marca casi nunca sirve para las dos cosas: el verde que se lee
   * bien como texto sobre un panel oscuro es demasiado claro para llevar texto
   * blanco encima. Todos los pares están medidos contra AA (4,5:1) en los dos
   * esquemas; `tests/ux_smoke.php` los recalcula en cada ejecución, así que
   * cambiar un valor a ojo aquí hace fallar la batería.
   */
  --accent: #4f8cff;
  --ok: #2f9e6b;
  --ok-strong: #35b47a;
  --warn: #c98a1b;
  --danger: #d25645;
  --violet: #8b5cf6;

  /* Tintas del esquema oscuro: sobre panel las de marca ya se leen, y sólo
     rojo y violeta necesitaban aclararse para llegar a 4,5:1. */
  --accent-ink: #4f8cff;
  --ok-ink:     #2f9e6b;
  --warn-ink:   #c98a1b;
  --danger-ink: #d86c5e;
  --violet-ink: #9c74f7;

  /* En oscuro los rellenos son vivos y la tinta que llevan encima es casi
     negra: al revés —blanco sobre azul vivo— sólo se llega a 3,2:1, y para
     alcanzar 4,5 habría que apagar tanto el azul que el botón se confundiría
     con el fondo. */
  --on-fill:  #0f1216;
  --pill-ink: #0f1216;
  --radius: 12px;
  --radius-sm: 8px;
  --tap: 44px;                 /* objetivo mínimo de toque en iOS */

  /*
   * Escala tipográfica. Cuatro peldaños y un suelo: por debajo de --t-xs (12px)
   * no baja nada de la interfaz. Antes había diecisiete tamaños sueltos
   * repartidos por la hoja, seis de ellos por debajo del suelo —hasta 9,9px en
   * el calendario—, que es donde la letra deja de leerse a pulso y con el
   * teléfono en la mano.
   */
  --t-xs: .75rem;   /* 12px — metadatos, distintivos, cabeceras de tabla */
  --t-sm: .82rem;   /* 13px — texto secundario */
  --t-md: .92rem;   /* 15px — texto de apoyo dentro de una tarjeta */
  --t-lg: 1.05rem;  /* 17px — títulos de tarjeta y de pantalla */

  /* Única excepción al suelo, y por eso va con nombre propio: la etiqueta que
     va bajo el icono en la barra de secciones. Es la convención de iOS y
     Android, y ahí lo que se reconoce es el icono; el texto sólo confirma. */
  --t-nav: .625rem;
  --shadow: 0 1px 2px rgba(0, 0, 0, .28), 0 8px 24px rgba(0, 0, 0, .18);
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --topbar-h: 52px;            /* una sola fila en el móvil */
  --botnav-h: 56px;            /* barra de secciones al alcance del pulgar */
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f5f7fa;
    --surface: #ffffff;
    --surface-2: #eef1f6;
    --line: #d8dee7;
    --text: #1b2029;
    --muted: #5c6675;
    --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 8px 24px rgba(16, 24, 40, .06);

    /* Sobre blanco los papeles se invierten: los rellenos se apagan para poder
       llevar texto blanco, y las tintas se oscurecen para leerse sobre panel.
       El contador de pendientes es la excepción: el ámbar se queda igual y su
       tinta sigue siendo casi negra en los dos esquemas. */
    --accent: #1969ff;
    --ok:     #27845a;
    --danger: #cd4735;

    --accent-ink: #085dff;
    --ok-ink:     #247952;
    --warn-ink:   #916313;
    --danger-ink: #bf402f;
    --violet-ink: #7a44f5;

    --on-fill: #ffffff;
  }
}

* { box-sizing: border-box; }
img, video { max-width: 100%; }

/* Al saltar a un ancla, dejar hueco para la barra fija: nada queda debajo. */
html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--topbar-h) + var(--safe-t) + .5rem);
  scroll-padding-bottom: calc(var(--botnav-h) + var(--safe-b) + .5rem);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.55 -apple-system, BlinkMacSystemFont, system-ui, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: anywhere;
}

a { color: var(--accent-ink); text-decoration: none; }
a:hover { text-decoration: underline; }
/* El halo del color del fondo separa el anillo de foco del control: sobre un
   botón azul, un contorno azul a secas desaparecía justo donde más hace falta. */
:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px;
  box-shadow: 0 0 0 2px var(--bg);
}

/* Ancho útil: fijo hasta donde 1180px ya llenaba la pantalla, y a partir de ahí
   crece con el monitor en vez de dejar dos franjas vacías a los lados. El tope
   de 1600px es deliberado: sin él, en un monitor grande las filas se estiran
   tanto que el ojo pierde el renglón al ir del título a la fecha. La usan la
   barra superior y el contenido, así que las dos siguen alineadas. */
:root { --wrap-max: clamp(1180px, 88vw, 1600px); }
.wrap {
  max-width: var(--wrap-max); margin: 0 auto;
  padding: 1rem calc(1rem + var(--safe-r)) calc(1rem + var(--safe-b)) calc(1rem + var(--safe-l));
}
/* Con barra inferior, el final de la página tiene que poder verse entera. */
.app main.wrap { padding-bottom: calc(var(--botnav-h) + var(--safe-b) + 1.25rem); }
.muted { color: var(--muted); }
.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 60;
  padding: .6rem 1rem; background: var(--accent); color: var(--on-fill); border-radius: 0 0 var(--radius-sm) 0;
}
.skip:focus { left: 0; }

/* --- Barra superior ---
 * Una sola fila en el móvil: título de la pantalla y salir. Las secciones
 * viven abajo (.botnav); desde tableta vuelven aquí, en la segunda fila.
 */
.topbar {
  background: var(--surface); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
  padding-top: var(--safe-t);
  backdrop-filter: saturate(180%) blur(8px);
}
.topbar-inner {
  display: flex; align-items: center; gap: .75rem; justify-content: space-between;
  min-height: var(--topbar-h); padding-block: .35rem;
}
.brand { font-weight: 700; color: var(--text); letter-spacing: -.01em; }
.topbar-title {
  margin: 0; min-width: 0; flex: 1;
  font-size: var(--t-lg); font-weight: 700; line-height: 1.25; letter-spacing: -.015em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.session { display: flex; align-items: center; gap: .5rem; margin: 0; flex: none; }
/* En el móvil el nombre y el rol sobran: se recuperan desde tableta. */
.session .who { display: none; flex-direction: column; line-height: 1.15; text-align: right; }
.who-name { font-size: .85rem; }
.who-role { font-size: var(--t-xs); color: var(--muted); }

/* Navegación de cabecera: sólo desde tableta. */
.nav { display: none; gap: .25rem; padding-block: 0 .5rem; flex-wrap: wrap; }
.nav a {
  display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap;
  padding: .45rem .8rem; border-radius: 999px;
  color: var(--muted); font-size: var(--t-md);
}
.nav a:hover { background: var(--surface-2); text-decoration: none; }
.nav a.on { background: var(--surface-2); color: var(--text); font-weight: 600; }
.pill {
  display: inline-block; min-width: 1.25rem; padding: 0 .3rem; border-radius: 999px;
  background: var(--warn); color: var(--pill-ink); font-size: var(--t-xs); font-weight: 700;
  text-align: center; line-height: 1.25rem;
}

/* --- Barra inferior de secciones (móvil) --- */
.botnav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: var(--surface); border-top: 1px solid var(--line);
  padding-left: var(--safe-l); padding-right: var(--safe-r);
  padding-bottom: var(--safe-b);
  backdrop-filter: saturate(180%) blur(8px);
}

/* --- CRM personal --- */
.contact-hero { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:.65rem; margin:0 0 1rem; }
.contact-hero>div { grid-column:1/-1; }
.contact-hero .btn { width:100%; min-width:0; text-align:center; overflow-wrap:normal; word-break:normal; }
.contact-hero .btn.primary { grid-column:1/-1; }
.contact-hero h2,.contact-hero p { margin:.15rem 0; }
.contact-metrics { grid-template-columns:repeat(3,1fr); margin-bottom:1rem; }
.contact-filters { display:grid; grid-template-columns:1fr; gap:.6rem; margin-bottom:1rem; }
.contact-form { display:grid; grid-template-columns:1fr; gap:0 .8rem; }
.contact-list { display:flex; flex-direction:column; }
.contact-row { display:grid; grid-template-columns:2.5rem 1fr; gap:.75rem; padding:.85rem 0; border-bottom:1px solid var(--line); color:var(--text); }
.contact-row:last-child { border-bottom:0; }
.contact-row:hover { text-decoration:none; }
.contact-row.is-due { border-left:3px solid var(--warn); padding-left:.65rem; }
.contact-avatar { width:2.5rem; height:2.5rem; border-radius:50%; display:grid; place-items:center; background:var(--surface-2); color:var(--accent-ink); font-weight:700; }
.contact-main,.contact-side { display:flex; flex-direction:column; gap:.15rem; }
.contact-main span,.contact-main small,.contact-side small { color:var(--muted); }
.contact-main small { margin-top:.2rem; }
.contact-side { grid-column:2; align-items:flex-start; }
.interaction-form { display:grid; gap:.6rem; }
.contact-history { list-style:none; padding:0; }
.contact-history li { border-left:2px solid var(--line); padding:0 0 1rem 1rem; }
.contact-history li span { color:var(--muted); margin-left:.5rem; }
.contact-history li p { margin:.25rem 0; }
.progressive { border:1px solid var(--line); border-radius:var(--radius-sm); padding:.7rem; margin-bottom:.9rem; }
.progressive summary { cursor:pointer; font-weight:600; }
.contact-form.nested { margin-top:1rem; }
.relationship-form,.task-form { display:grid; gap:.6rem; }
.compact { display:flex; align-items:center; gap:.45rem; color:var(--muted); }
.compact input[type="number"] { width:4.5rem; }
.compact input[type="checkbox"] { width:auto; }
.relation-list { display:grid; gap:.5rem; margin-top:1rem; }
.relation-list a { display:flex; flex-direction:column; padding:.65rem; border:1px solid var(--line); border-radius:var(--radius-sm); color:var(--text); }
.relation-list a:hover { text-decoration:none; border-color:var(--accent); }
.relation-list span { color:var(--muted); font-size:var(--t-sm); }
.task-list { list-style:none; padding:0; }
.task-list li { display:flex; justify-content:space-between; align-items:center; gap:.75rem; padding:.65rem 0; border-bottom:1px solid var(--line); }
.task-list span { display:flex; flex-direction:column; }
.task-list small { color:var(--muted); }
.crm-inbox h3 { margin-top:1.25rem; }
.graph-head { display:grid; grid-template-columns:minmax(0,1fr) auto; align-items:start; gap:.75rem; }
.graph-head h2,.graph-head p { margin:.15rem 0; }
.graph-actions { display:flex; gap:.55rem; flex-wrap:wrap; justify-content:flex-end; }
.graph-actions .btn { overflow-wrap:normal; word-break:normal; white-space:nowrap; }
.graph-filters { display:grid; gap:.6rem; margin:1rem 0; }
.graph-shell { position:relative; padding:0; overflow:hidden; }
.graph-toolbar { position:absolute; z-index:5; top:.75rem; left:.75rem; right:.75rem; display:flex; align-items:center; gap:.55rem; pointer-events:none; }
.graph-toolbar>* { pointer-events:auto; }
.graph-search { width:min(420px,calc(100% - 3.5rem)); }
.graph-search input { width:100%; min-height:2.6rem; background:color-mix(in srgb,var(--surface) 94%,transparent); box-shadow:var(--shadow); }
.graph-fullscreen { margin-left:auto; width:2.75rem; height:2.75rem; min-width:2.75rem; padding:.65rem; display:grid; place-items:center; }
.graph-fullscreen svg { width:1.3rem; height:1.3rem; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
.graph-search-status { position:absolute; z-index:4; top:3.7rem; left:.9rem; margin:0; padding:.2rem .45rem; border-radius:var(--radius-sm); background:color-mix(in srgb,var(--surface) 90%,transparent); font-size:var(--t-sm); }
.graph-search-status:empty { display:none; }
#contact-graph { height:min(68vh,720px); min-height:480px; background:radial-gradient(circle at center,var(--surface-2),var(--surface)); }
.graph-shell:fullscreen,.graph-shell.is-fullscreen { width:100vw; height:100vh; border:0; border-radius:0; background:var(--surface); }
.graph-shell.is-fullscreen { position:fixed; z-index:10000; inset:0; margin:0; max-width:none; }
.graph-shell:fullscreen #contact-graph,.graph-shell.is-fullscreen #contact-graph { width:100vw; height:100vh; min-height:100vh; }
.graph-shell:fullscreen .graph-detail,.graph-shell.is-fullscreen .graph-detail { z-index:3; }
body.graph-fullscreen-open { overflow:hidden; }
.graph-detail { position:absolute; left:.75rem; right:.75rem; bottom:.75rem; padding:.75rem; background:color-mix(in srgb,var(--surface) 92%,transparent); border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow); }
.graph-detail--hint { top:.75rem; right:12rem; bottom:auto; min-height:2.9rem; display:flex; align-items:center; }
.graph-detail--hint p { margin:0; }
.graph-detail h3,.graph-detail p { margin:.2rem 0 .5rem; }
.graph-detail__role { color:var(--muted); }
.graph-detail__scores { display:grid; grid-template-columns:repeat(2,1fr); gap:.4rem; margin:.7rem 0; }
.graph-detail__scores span { display:flex; justify-content:space-between; gap:.4rem; padding:.4rem .5rem; background:var(--surface-2); border-radius:var(--radius-sm); }
.graph-detail__scores small { color:var(--muted); }
.graph-detail__facts { display:grid; gap:.55rem; margin:.75rem 0; }
.graph-detail__facts div { display:grid; gap:.1rem; }
.graph-detail__facts dt { color:var(--muted); font-size:var(--t-sm); }
.graph-detail__facts dd { margin:0; line-height:1.35; overflow-wrap:anywhere; }
.graph-notice { margin:.65rem .15rem 1rem; font-size:var(--t-sm); }
.route-tool>div { display:grid; gap:.6rem; }
@media (max-width: 520px) {
  .graph-head { grid-template-columns:1fr; }
  .graph-actions { justify-content:stretch; }
  .graph-actions .btn { width:100%; text-align:center; }
  .graph-shell { display:flex; flex-direction:column; }
  .graph-toolbar { position:relative; inset:auto; display:grid; grid-template-columns:minmax(0,1fr) 2.75rem; align-items:center; padding:.65rem; gap:.5rem; background:var(--surface); }
  .graph-search { width:auto; min-width:0; }
  .graph-search input { font-size:16px; }
  .graph-fullscreen { width:2.75rem; min-width:2.75rem; margin:0; color:var(--text); }
  .graph-search-status { position:static; order:2; margin:0 .75rem .5rem; align-self:flex-start; }
  #contact-graph { order:3; min-height:500px; height:62vh; }
  .graph-detail { position:static; order:4; margin:.75rem; width:auto; max-height:none; }
  .graph-detail--hint { display:none; }
  .graph-detail:not(.graph-detail--hint) { position:absolute; z-index:6; left:.75rem; right:.75rem; bottom:.75rem; margin:0; width:auto; max-height:min(48vh,420px); overflow:auto; background:color-mix(in srgb,var(--surface) 97%,transparent); }
  .graph-shell.is-fullscreen { display:block; }
  .graph-shell.is-fullscreen .graph-toolbar { position:absolute; inset:.75rem .75rem auto; display:grid; }
  .graph-shell.is-fullscreen .graph-search-status { position:absolute; top:4rem; left:.75rem; z-index:5; margin:0; }
  .graph-shell.is-fullscreen #contact-graph { min-height:100vh; height:100vh; }
  .graph-shell.is-fullscreen .graph-detail { position:absolute; left:.75rem; right:.75rem; bottom:.75rem; margin:0; max-height:42vh; overflow:auto; }
}
@media (min-width: 760px) {
  .contact-hero { display:flex; align-items:center; justify-content:space-between; gap:1rem; }
  .contact-hero>div { grid-column:auto; }
  .contact-hero .btn,.contact-hero .btn.primary { width:auto; grid-column:auto; }
  .contact-filters { grid-template-columns:2fr 1fr auto; }
  .contact-form { grid-template-columns:repeat(2,1fr); }
  .contact-form .span2 { grid-column:span 2; }
  .contact-row { grid-template-columns:2.5rem 1fr auto; align-items:center; }
  .contact-side { grid-column:auto; align-items:flex-end; }
  .interaction-form { grid-template-columns:1.1fr .8fr .8fr 2fr auto; align-items:end; }
  .relationship-form { grid-template-columns:1.4fr 1fr auto auto 1fr auto; align-items:end; }
  .task-form { grid-template-columns:2fr 1fr .7fr auto; align-items:end; }
  .graph-filters { grid-template-columns:2fr .7fr auto; }
  .graph-detail { left:auto; width:min(380px,calc(100% - 1.5rem)); max-height:calc(100% - 5rem); overflow:auto; top:4.25rem; bottom:auto; }
  .route-tool>div { grid-template-columns:1fr 1fr auto; }
}
.botnav a {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .15rem;
  min-height: var(--botnav-h); padding: .3rem .2rem;
  color: var(--muted); line-height: 1.1; text-align: center;
  border-top: 2px solid transparent;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.botnav a:hover { text-decoration: none; }
.botnav a.on { color: var(--text); font-weight: 600; border-top-color: var(--accent); }
/* El icono es lo que se reconoce de un vistazo; la etiqueta lo confirma. Por
   eso la etiqueta puede bajar del suelo de 12px que rige en el resto de la
   interfaz: es la excepción declarada en --t-nav, y sólo aquí. */
.botnav .bn-label {
  display: block; font-size: var(--t-nav);
  /* El cuerpo del documento rompe por donde sea para que ningún texto largo
     desborde el teléfono. Aquí eso partiría «Compromisos» en dos líneas por la
     mitad de la palabra: en una columna de un quinto de pantalla, la etiqueta
     se recorta con puntos suspensivos y el icono sigue diciendo qué es. */
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.botnav a, .nav a { overflow-wrap: normal; }
.botnav .bn-icon { display: block; flex: none; }
/* El icono del destino activo se tiñe del acento, igual que su filo superior:
   el color no es el único indicador —hay filo, peso de texto y aria-current—
   pero refuerza dónde está uno sin añadir nada a la pantalla. */
.botnav a.on .bn-icon { color: var(--accent-ink); }
/* El contador cabalga sobre el icono de Revisión y tiene que caber ahí sin
   taparlo: es la segunda excepción declarada al suelo de 12px, y la última. */
.botnav .pill {
  position: absolute; top: .2rem; left: 50%; margin-left: .55rem;
  font-size: .625rem; min-width: 1.05rem; line-height: 1.05rem;
}

/* --- Acceso --- */
.gate {
  max-width: 380px; margin: 8vh auto; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 2rem;
  box-shadow: var(--shadow);
}
.gate h1 { margin: 0 0 .25rem; font-size: 1.5rem; }
.gate-form { display: flex; flex-direction: column; gap: .35rem; margin-top: 1.5rem; }
.gate-form label { font-size: .85rem; color: var(--muted); }
.gate-form input { margin-bottom: .8rem; }
.gate-form .btn { margin-top: .4rem; }

/* --- Formularios --- */
input, select, textarea, button { font: inherit; }
input, select, textarea {
  width: 100%; padding: .6rem .7rem; color: var(--text);
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-size: 16px;    /* menos de 16px hace que Safari haga zoom al enfocar */
}
input[type="file"] { padding: .5rem; background: var(--surface-2); }
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
}
input:disabled, select:disabled, textarea:disabled { opacity: .65; cursor: not-allowed; }
textarea { resize: vertical; min-height: 3.5rem; }
.form .f { margin-bottom: .9rem; }
.form label, .filters label { display: block; font-size: var(--t-sm); color: var(--muted); margin-bottom: .25rem; }
.hint { display: block; font-size: .78rem; margin-top: .3rem; }
.row3 { display: grid; grid-template-columns: 1fr; gap: .8rem; }
.form-actions { display: flex; gap: .6rem; flex-wrap: wrap; }
.err { display: block; margin-top: .25rem; color: var(--danger-ink); font-size: var(--t-sm); }
.req { color: var(--danger-ink); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  min-height: var(--tap); padding: .55rem 1rem;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text); cursor: pointer;
  text-decoration: none; font-weight: 500;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: transform .06s ease, border-color .12s ease, background .12s ease;
}
.btn:hover { border-color: var(--accent); text-decoration: none; }
.btn:active { transform: scale(.98); }
.btn[disabled] { opacity: .6; cursor: progress; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-fill); }
.btn.ghost { background: transparent; }
.btn.danger { background: transparent; border-color: var(--danger); color: var(--danger-ink); }
.btn.danger.solid { background: var(--danger); color: var(--on-fill); }
/* «Pequeño» es cuestión de aspecto, no de superficie que se puede tocar: en el
   móvil un botón secundario sigue necesitando los 44px de alto, aunque su texto
   y su relleno sean menores. Desde tableta, donde se apunta con un ratón, vuelve
   a su altura compacta. */
.btn.sm { min-height: var(--tap); padding: .3rem .6rem; font-size: .85rem; }
.btn.lg { min-height: 52px; padding: .8rem 1.6rem; font-size: var(--t-lg); width: 100%; }

.alert {
  padding: .75rem .9rem; border-radius: var(--radius-sm); border: 1px solid var(--line);
  background: var(--surface); margin: 0 0 .8rem;
}
.alert.error { border-color: var(--danger); color: var(--danger-ink); }
.alert.ok { border-left: 4px solid var(--ok); }

/* --- Paneles y tarjetas --- */
.module-purpose {
  margin: .85rem 0 1rem;
  max-width: 78ch;
  line-height: 1.45;
}
.module-guide { margin-bottom: 1rem; }
.page-cta { margin: 1rem 0; }
.panel {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1rem; margin-bottom: 1rem; min-width: 0;
}
/* El encabezado de sección manda: iba en 13px, versalitas y gris —más pequeño
   que el propio cuerpo— y las pantallas se leían como un bloque uniforme.
   Con el peldaño grande de la escala, el ojo encuentra las secciones solo. */
.panel h2, .section-title {
  font-size: var(--t-lg); font-weight: 650; margin: 0 0 .8rem; color: var(--text);
}
.cols { display: grid; grid-template-columns: 1fr; gap: 1rem; align-items: start; }
.piece-review-workspace { display: flex; flex-direction: column; }
.piece-review-decision { order: 1; }
.piece-review-material { order: 2; }
.piece-review-flow { order: 3; }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
         gap: .6rem; margin-bottom: 1rem; }
.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .8rem; display: flex; flex-direction: column; color: var(--text);
}
.card:hover { border-color: var(--accent); text-decoration: none; }
.card .n { font-size: 1.6rem; font-weight: 700; line-height: 1.1; letter-spacing: -.02em; }
.card .l { font-size: .78rem; color: var(--muted); }
.card.stat { border-left: 4px solid var(--line); }

/* Llamada a la acción del panel: lo pendiente, imposible de pasar por alto. */
.hero {
  background: var(--surface); border: 1px solid var(--line); border-left: 4px solid var(--warn);
  border-radius: var(--radius); padding: 1.1rem; margin-bottom: 1rem; box-shadow: var(--shadow);
}
.hero-n { margin: 0; font-size: 2.6rem; font-weight: 800; line-height: 1; letter-spacing: -.03em; }
.hero-l { margin: .2rem 0 .9rem; color: var(--muted); }

.list { list-style: none; margin: 0; padding: 0; }
.list li { padding: .6rem 0; border-bottom: 1px solid var(--line); }
.list li:last-child { border-bottom: 0; }
.list .meta { display: block; font-size: .8rem; color: var(--muted); }
.list blockquote {
  margin: .4rem 0 0; padding: .45rem .65rem; background: var(--surface-2);
  border-radius: var(--radius-sm); font-size: .88rem; color: var(--muted);
}
.empty { padding: 2rem 1rem; text-align: center; color: var(--muted);
         border: 1px dashed var(--line); border-radius: var(--radius); }
.empty.done { color: var(--ok-ink); border-color: var(--ok); }
.empty .big { display: block; font-size: 2.4rem; line-height: 1; margin-bottom: .4rem; }

/* --- Tarjeta de revisión --- */
.queue { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; min-width: 0; }
.queue-count { margin: 0 0 .8rem; }
.queue-filter { margin-bottom: 1rem; display: flex; gap: .5rem; }

/* Paso a paso del móvil: una pieza a la vista, con su posición en la cola. */
.stepper {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  margin: 0 0 .8rem;
}
/* `display` de autor gana al del navegador: [hidden] hay que declararlo. */
.stepper[hidden], .rcard[hidden] { display: none; }
.stepper .btn { min-width: 6.5rem; }
.stepper .btn[disabled] { opacity: .4; cursor: default; }
.stepper-pos { font-size: .85rem; color: var(--muted); font-variant-numeric: tabular-nums; }

.rcard {
  background: var(--surface); border: 1px solid var(--line);
  border-left: 4px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); scroll-margin-top: calc(var(--topbar-h) + var(--safe-t) + .5rem);
}
.rcard.s-en_revision { border-left-color: var(--warn); }
.rcard.s-aprobado    { border-left-color: var(--ok); }
.rcard.s-rechazado   { border-left-color: var(--danger); }
.rcard.s-programado  { border-left-color: var(--accent); }
.rcard.s-publicado   { border-left-color: var(--violet); }

/* La urgencia manda sobre el estado en el filo de la tarjeta: en una cola donde
   todo está «en revisión», el color del estado no distingue nada, y lo que hay
   que ver de un vistazo es qué se publica ya. Van después de las reglas de
   estado a propósito: misma especificidad, gana la última. */
.rcard.u-vencida { border-left-color: var(--danger); }
.rcard.u-hoy     { border-left-color: var(--danger); }
.rcard.u-manana  { border-left-color: var(--warn); }

.rcard-waiting { margin: 0 0 .4rem; font-size: .78rem; color: var(--muted); }
.artifact-id {
  margin: 0 0 .55rem; padding: .5rem .65rem; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--surface-2); font-size: .82rem;
}
.artifact-id span { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Consolas, monospace; }

.rcard-media { background: var(--surface-2); border-radius: var(--radius) var(--radius) 0 0; overflow: hidden; }
.rcard-media.empty-media {
  display: flex; align-items: center; justify-content: center;
  min-height: 72px; color: var(--muted); font-size: var(--t-sm);
}
.rcard-body { padding: .8rem .9rem; }
.rcard-state { margin: 0 0 .35rem; display: flex; gap: .4rem; flex-wrap: wrap; }
.rcard-title { margin: 0 0 .3rem; font-size: var(--t-lg); line-height: 1.3; letter-spacing: -.01em; }
.rcard-title a { color: var(--text); }
.rcard-caption { margin: 0 0 .5rem; color: var(--muted); font-size: var(--t-md); }
/* Sólo se recorta cuando app.js ha puesto el botón para desplegarlo. */
.rcard-caption.clamped {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
  line-clamp: 3; overflow: hidden;
}
.cap-toggle {
  display: inline-flex; align-items: center; min-height: var(--tap);
  margin: -.4rem 0 .35rem; padding: 0; border: 0; background: none;
  color: var(--accent-ink); font-size: .85rem; font-weight: 600; cursor: pointer;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}

/* Metadatos en una línea de fichas: marca, canal y tipo ocupan lo justo, y la
   fecha prevista va aparte porque es el dato que se busca de un vistazo. */
.rcard-facts { list-style: none; margin: 0; padding: 0;
               display: flex; flex-wrap: wrap; gap: .3rem .35rem; align-items: center; }
.rcard-facts .f-chip {
  padding: .12rem .5rem; border-radius: 999px; background: var(--surface-2);
  border: 1px solid var(--line); font-size: .76rem; color: var(--muted);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rcard-facts .f-when {
  flex-basis: 100%; margin-top: .15rem; font-size: .88rem; color: var(--text); font-weight: 600;
}

/* Acciones: dos objetivos grandes, pegados al borde inferior de la tarjeta, de
   modo que se alcanzan sin recorrer la pieza entera. */
.rcard-actions {
  /* Se queda a la vista mientras se recorre la pieza, justo encima de la
     barra de secciones, sin taparla ni ser tapada por ella. */
  position: sticky; bottom: calc(var(--botnav-h) + var(--safe-b)); z-index: 5;
  display: grid; grid-template-columns: 1fr 1fr; gap: .5rem;
  padding: .7rem .9rem;
  border-top: 1px solid var(--line); background: var(--surface-2);
  border-radius: 0 0 var(--radius) var(--radius);
}
.rcard-actions form { margin: 0; }
.btn.approve, .btn.reject, .rcard-actions .btn { width: 100%; min-height: 48px; font-weight: 600; }
.btn.approve { background: var(--ok); border-color: var(--ok); color: var(--on-fill); }
.btn.approve::-webkit-details-marker { display: none; }
.btn.reject {
  list-style: none; background: transparent; border-color: var(--danger); color: var(--danger-ink);
}
.btn.reject::-webkit-details-marker { display: none; }
.act-approve { grid-column: 1; }
.act-approve[open] { grid-column: 1 / -1; }
.act-approve[open] > .btn.approve { margin-bottom: .6rem; }
.approve-form {
  padding: .75rem; border: 1px solid var(--ok); border-radius: var(--radius-sm);
  background: var(--surface);
}
.approve-form p { margin: 0 0 .7rem; color: var(--text); }
.act-reject { grid-column: 2; }
.act-reject[open] { grid-column: 1 / -1; }
.act-discard { grid-column: 1 / -1; }
.btn.discard { width: 100%; min-height: 44px; border-color: var(--danger); color: var(--danger); }
.act-discard[open] .btn.discard { background: var(--danger); color: var(--on-fill); margin-bottom: .6rem; }
.act-reject[open] .btn.reject { background: var(--danger); color: var(--on-fill); margin-bottom: .6rem; }
.reject-form label { display: block; font-size: var(--t-sm); color: var(--muted); margin-bottom: .3rem; }
.reject-form textarea { margin-bottom: .6rem; }

/* En el panel las tarjetas son un resumen, no la pantalla de trabajo: el
   material va más bajo y las acciones no se pegan al borde. */
.compact-queue .ga-frame { aspect-ratio: 16 / 9; max-height: 30vh; }
.compact-queue .rcard-actions { position: static; }
.queue-row { margin-top: .7rem; }
.queue-row:first-of-type { margin-top: 0; }
.queue-row .rcard-actions { position: static; }

/* Lo pendiente del panel: apilado en el teléfono, en columnas en escritorio
   (ver la consulta de 700px). La separación la pone la rejilla, así que el
   margen entre filas sobra aquí. */
.queue-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: .7rem; min-width: 0; }
.queue-grid > .queue-row { margin-top: 0; }

/* Bandeja del panel: dos bloques —piezas y compromisos— bajo un solo título,
   porque para quien decide son la misma pregunta. Los subtítulos sólo aparecen
   cuando hay de los dos; con uno solo, el título de la sección ya basta. */
.inbox-sub {
  margin: 1rem 0 .5rem; font-size: var(--t-xs); text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted);
}
.queue-grid + .inbox-head .inbox-sub, .queue-grid + .inbox-sub { margin-top: 1.2rem; }
.inbox-head { display: flex; align-items: baseline; justify-content: space-between; gap: .8rem; }
.inbox-head .inbox-sub { margin-bottom: .5rem; }
.list.attention li { display: grid; gap: .15rem; }
.list.attention .meta { overflow-wrap: anywhere; }
.attention-tags { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .25rem; }

/* Rechazos recientes: contexto útil, pero plegado para no alargar la cola. */
.recent-decisions > summary {
  list-style: none; cursor: pointer; min-height: var(--tap);
  display: flex; align-items: center; gap: .4rem;
}
.recent-decisions > summary::-webkit-details-marker { display: none; }
.recent-decisions > summary h2 { margin: 0; }
.recent-decisions > summary::after { content: '▾'; color: var(--muted); }
.recent-decisions[open] > summary::after { content: '▴'; }

/* --- Galería ---
 * Marco de proporción fija y `contain`: la tarjeta mide siempre lo mismo y no
 * se recorta ningún arte, sea vertical, cuadrado o apaisado.
 */
.gallery { display: grid; grid-template-columns: 1fr; gap: .4rem; }
.gallery .ga { margin: 0; min-width: 0; }
.ga-version-label {
  margin: 0; padding: .45rem .6rem; background: var(--surface); border-bottom: 1px solid var(--line);
  color: var(--text); font-size: .78rem; font-weight: 650;
}
.ga-frame {
  display: block; width: 100%; aspect-ratio: 4 / 5; max-height: 44vh;
  background: #000; overflow: hidden;
}
.ga-frame-video { aspect-ratio: 16 / 9; }
.gallery img, .gallery video {
  display: block; width: 100%; height: 100%; object-fit: contain; background: #000;
}
.gallery figcaption { padding: .4rem .6rem; font-size: .8rem; color: var(--muted); }

/* Blindaje móvil: ningún nivel de la galería puede crecer por el ancho
   intrínseco del archivo. Es importante en Safari, que puede conservar las
   dimensiones width/height del arte al recalcular una tarjeta. */
@media (max-width: 699px) {
  /* Safari puede usar el ancho intrínseco del arte como mínimo del ítem de
     grid. El límite debe empezar en el viewport y atravesar todos los
     contenedores, no solamente aplicarse a la etiqueta img. */
  html, body { width: 100%; max-width: 100%; overflow-x: clip; }
  .app main.wrap, .panel, .queue, .queue-grid, .compact-queue,
  .rcard, .rcard-media, .gallery, .gallery .ga, .ga-frame {
    width: 100%; max-width: 100%; min-width: 0;
  }
  .app main.wrap { overflow-x: hidden; }
  .rcard { contain: inline-size; }
  .rcard-media { contain: inline-size; overflow: hidden; }
  .gallery img, .gallery video {
    width: 100% !important; max-width: 100% !important; min-width: 0;
    height: 100%; object-fit: contain;
  }

  /* Panel tiene tarjetas compactas propias. Se blinda de forma explícita para
     que ninguna dimensión nativa del arte pueda ensanchar la página en Safari. */
  .panel .compact-queue .rcard,
  .panel .compact-queue .rcard-media,
  .panel .compact-queue .gallery,
  .panel .compact-queue .ga,
  .panel .compact-queue .ga-frame,
  .panel .compact-queue img,
  .panel .compact-queue video {
    inline-size: 100% !important; max-inline-size: 100% !important; min-inline-size: 0 !important;
  }
  .panel .compact-queue .ga { flex: 0 1 100%; overflow: hidden; }
}

/* Con varias piezas de material, tira horizontal con ajuste por elemento. */
.gallery.many {
  display: flex; gap: .4rem; overflow-x: auto; scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch; scrollbar-width: thin;
}
.gallery.many .ga { flex: 0 0 88%; scroll-snap-align: center; }
.gallery-hint { margin: .4rem .9rem 0; font-size: .76rem; }

/* Visor de revisión: una sola lámina original ocupa la pantalla. En móvil el
   copy queda fuera para dedicar el viewport al arte; desde 700 px vuelve la
   ficha dividida entre creatividad y decisión. */
body.review-focus-open { overflow: hidden; }
.rcard.review-focus {
  position: fixed; inset: 0; z-index: 100; width: 100%; height: 100%; margin: 0;
  overflow: hidden; border: 0; border-radius: 0; background: #08090b;
  box-shadow: 0 0 0 100vmax rgba(0,0,0,.86);
}
.rcard.review-focus .rcard-media { width: 100%; height: 100%; border-radius: 0; background: #08090b; }
.rcard.review-focus .gallery { width: 100%; height: 100%; overflow: hidden; }
.rcard.review-focus .gallery .ga { display: none; flex: 0 0 100%; width: 100%; height: 100%; margin: 0; }
.rcard.review-focus .gallery .ga.review-focus-current { display: block; }
.rcard.review-focus .ga-frame { width: 100%; height: 100%; max-height: none; aspect-ratio: auto; pointer-events: none; }
.rcard.review-focus .gallery img,
.rcard.review-focus .gallery video { width: 100%; height: 100%; object-fit: contain; }
.rcard.review-focus .gallery figcaption,
.rcard.review-focus .gallery-hint,
.rcard.review-focus .rcard-body,
.rcard.review-focus .rcard-actions { display: none; }
.review-focus-close,
.review-focus-nav {
  width: 44px; height: 44px; padding: 0; border: 1px solid rgba(255,255,255,.35);
  border-radius: 999px; background: rgba(10,12,16,.86); color: #fff;
  font-size: 1.45rem; line-height: 1; cursor: pointer;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.review-focus-close { position: absolute; top: max(.75rem, env(safe-area-inset-top)); right: .75rem; z-index: 4; }
.review-focus-controls {
  position: absolute; z-index: 4; left: 50%; bottom: max(.75rem, env(safe-area-inset-bottom));
  transform: translateX(-50%); display: flex; align-items: center; gap: .7rem;
  padding: .35rem; border-radius: 999px; background: rgba(10,12,16,.72);
}
.review-focus-counter { min-width: 3.5rem; text-align: center; color: #fff; font-size: .9rem; font-variant-numeric: tabular-nums; }
.review-focus-nav[disabled] { opacity: .3; cursor: default; }
/* En la ficha de la pieza la galería cuelga directamente del panel y el marco
   puede respirar; dentro de una tarjeta de revisión manda la regla de arriba. */
.panel > .gallery .ga-frame { aspect-ratio: 3 / 2; max-height: 60vh; }

.ga-doc {
  display: flex; align-items: center; gap: .6rem; padding: 1rem;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  color: var(--text); min-height: var(--tap);
}
.ga-doc-icon {
  flex: none; font-size: var(--t-xs); font-weight: 700; letter-spacing: .05em;
  padding: .3rem .45rem; border-radius: 4px; background: var(--danger); color: var(--on-fill);
}
.ga-doc-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ga-doc-size { flex: none; font-size: .78rem; color: var(--muted); }

.media-admin { list-style: none; margin: 1rem 0 0; padding: 0; }
.media-admin li {
  display: grid; gap: .5rem; padding: .7rem 0; border-top: 1px solid var(--line);
}
.media-admin .m-kind { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.media-admin .m-name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; }
.media-admin .m-size { font-size: .78rem; }
.media-admin .m-caption { display: flex; gap: .4rem; }
.media-admin .m-ops { display: flex; gap: .4rem; flex-wrap: wrap; align-items: center; }
.media-admin form { margin: 0; }

/* --- Filtros --- */
.filters {
  display: grid; grid-template-columns: 1fr; gap: .7rem; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 1rem; margin-bottom: 1rem;
}
.filters .actions { display: flex; gap: .5rem; align-items: flex-end; }
.result-count { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }

/* --- Tabla --- */
.table-wrap { overflow-x: auto; background: var(--surface);
              border: 1px solid var(--line); border-radius: var(--radius); }
.table { width: 100%; border-collapse: collapse; }
.table th, .table td { padding: .6rem .8rem; text-align: left; border-bottom: 1px solid var(--line); }
.table th { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.table tbody tr:hover { background: var(--surface-2); }
.row-caption { display: block; font-size: .8rem; }
.th-thumb, .td-thumb { width: 64px; }
.thumb {
  position: relative; display: block; width: 56px; height: 56px; border-radius: var(--radius-sm);
  overflow: hidden; background: var(--surface-2); border: 1px solid var(--line);
}
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb-none {
  display: flex; width: 100%; height: 100%; align-items: center; justify-content: center;
  font-size: var(--t-xs); color: var(--muted);
  /* «Newsletter» no cabe en 56px: se recorta con puntos en vez de desbordar. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 .2rem;
}
.thumb-n {
  position: absolute; right: 2px; bottom: 2px; padding: 0 .3rem; border-radius: 999px;
  background: rgba(0, 0, 0, .68); color: #fff; font-size: var(--t-xs); line-height: 1.1rem;
}
.pager { display: flex; gap: .8rem; align-items: center; justify-content: center; margin: 1rem 0; }

/* --- Estados --- */
.badge {
  display: inline-block; padding: .18rem .55rem; border-radius: 999px;
  font-size: var(--t-xs); border: 1px solid var(--line); background: var(--surface-2); white-space: nowrap;
}
.badge.origin { color: var(--muted); }
.s-borrador    { border-color: #6b7280; }
.s-en_revision { border-color: var(--warn); color: var(--warn-ink); }
.s-aprobado    { border-color: var(--ok); color: var(--ok-ink); }
.s-rechazado   { border-color: var(--danger); color: var(--danger-ink); }
.s-programado  { border-color: var(--accent); color: var(--accent-ink); }
.s-publicado   { border-color: var(--violet); color: var(--violet-ink); }
.s-archivado   { border-color: var(--line); color: var(--muted); }

/* Urgencia. Sólo tres niveles llevan color: lo vencido, lo de hoy y lo de
   mañana. Si todo grita, no grita nada. */
/* Seguimiento de la publicación: acompaña al estado y dice qué falta.
   `sch-tentativo` va discontinuo como en el calendario —plan, no compromiso—;
   `sch-manual` avisa en color de alerta de que hay que subirla a mano; y
   `sch-verificado` es un enlace real a la publicación, la única prueba. */
.badge.sch-tentativo { border-style: dashed; color: var(--muted); }
.badge.sch-vencido   { border-color: var(--danger); color: var(--danger-ink); font-weight: 600; }
.badge.sch-nativa    { border-color: var(--accent); color: var(--accent-ink); }
.badge.sch-manual    { border-color: var(--warn); color: var(--warn-ink); }
.badge.sch-publicado { border-color: var(--violet); color: var(--violet-ink); }
.badge.sch-verificado {
  border-color: var(--ok); color: var(--ok-ink); text-decoration: none;
}
.badge.sch-verificado:hover { background: color-mix(in srgb, var(--ok) 12%, transparent); }

.badge.u-vencida {
  border-color: var(--danger); background: var(--danger); color: var(--on-fill); font-weight: 600;
}
.badge.u-hoy    { border-color: var(--danger); color: var(--danger-ink); font-weight: 600; }
.badge.u-manana { border-color: var(--warn); color: var(--warn-ink); }
.badge.u-pronto { color: var(--muted); }
.card.stat.s-en_revision { border-left-color: var(--warn); }
.card.stat.s-aprobado    { border-left-color: var(--ok); }
.card.stat.s-rechazado   { border-left-color: var(--danger); }
.card.stat.s-programado  { border-left-color: var(--accent); }
.card.stat.s-publicado   { border-left-color: var(--violet); }

.piece-meta { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.panel.decide { border-left: 4px solid var(--warn); }
/* En la ficha el par aprobar/rechazar ya está arriba del todo: no necesita
   quedarse pegado al borde, y así no tapa el resto de la pieza. */
.panel.decide .rcard-actions {
  position: static; border-top: 0; background: transparent; padding: .4rem 0 0;
}
.danger-zone { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--line); }

/* --- Historial --- */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { padding: .7rem 0 .7rem 1rem; border-left: 2px solid var(--line); }
.timeline li.ev-aprobado  { border-left-color: var(--ok); }
.timeline li.ev-rechazado { border-left-color: var(--danger); }
.timeline .when { font-size: .78rem; color: var(--muted); margin-right: .5rem; }
.timeline .who { font-weight: 600; }
.timeline .ack {
  margin-left: .4rem; padding: 0 .4rem; border-radius: 999px; font-size: var(--t-xs);
  border: 1px solid var(--line); color: var(--muted);
}
.timeline blockquote {
  margin: .4rem 0 0; padding: .5rem .7rem; background: var(--surface-2);
  border-radius: var(--radius-sm); font-size: var(--t-md);
}

/* --- Calendario ---
 * En el móvil no es una rejilla encogida: es una agenda. Los días sin nada no
 * se pintan, cada día es un bloque con su fecha en palabras y cada entrada
 * envuelve el texto en vez de recortarlo, así que nada se sale de la pantalla.
 */
.cal-head { display: flex; flex-direction: column; gap: .7rem; margin-bottom: 1rem; }
.cal-nav { display: flex; align-items: center; justify-content: space-between; gap: .6rem; }
.cal-month { font-size: var(--t-lg); letter-spacing: -.01em; }
.btn.icon { min-width: var(--tap); min-height: var(--tap); padding: .4rem; font-size: 1.1rem; }

/* Selector de proyecto: fichas grandes, deslizables, sin desbordar la página. */
.chips {
  display: flex; gap: .4rem; overflow-x: auto; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  margin-inline: calc(-1rem - var(--safe-l)) calc(-1rem - var(--safe-r));
  padding-inline: calc(1rem + var(--safe-l)) calc(1rem + var(--safe-r));
}
.chips::-webkit-scrollbar { display: none; }
.chip {
  display: inline-flex; align-items: center; white-space: nowrap; flex: none;
  min-height: var(--tap); padding: .3rem .9rem; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--muted);
  font-size: .9rem; -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.chip:hover { text-decoration: none; border-color: var(--accent); }
.chip.on { background: var(--accent); border-color: var(--accent); color: var(--on-fill); font-weight: 600; }

/* Segunda fila de ámbito en el listado: el estado. Cada ficha lleva el punto
   de color de su estado —el mismo del distintivo y del filo de las tarjetas—
   para que la fila se lea de un vistazo sin depender del texto. El color va en
   un punto y no en el texto porque el contraste de la ficha ya está medido, y
   teñir la etiqueta lo rompería en la mitad de los estados. */
.chips-estado { margin-top: .4rem; }
.chips-estado .chip:not(.chip-todas)::before {
  content: ""; flex: none; width: .5rem; height: .5rem; border-radius: 50%;
  margin-right: .45rem; background: var(--line);
}
.chips-estado .chip.s-en_revision::before { background: var(--warn); }
.chips-estado .chip.s-aprobado::before    { background: var(--ok); }
.chips-estado .chip.s-rechazado::before   { background: var(--danger); }
.chips-estado .chip.s-programado::before  { background: var(--accent); }
.chips-estado .chip.s-publicado::before   { background: var(--violet); }
.chips-estado .chip.on::before            { background: var(--on-fill); }

.cal-filters > summary {
  list-style: none; display: inline-flex; align-items: center; gap: .35rem;
  min-height: var(--tap); width: fit-content;
}
.cal-filters > summary::-webkit-details-marker { display: none; }
.cal-filters > summary::after { content: '▾'; }
.cal-filters[open] > summary::after { content: '▴'; }
.cal-filters .filters { margin-top: .6rem; }
.filters.inline { margin-bottom: 0; }
.cal-note {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0 .6rem;
  margin: 0 0 1rem; font-size: .86rem;
}
.cal-note a { display: inline-flex; align-items: center; min-height: var(--tap); }

.cal { display: grid; grid-template-columns: 1fr; gap: .5rem; }
.cal-dow { display: none; }
.cal-cell {
  min-width: 0; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: .5rem .6rem;
}
.cal-cell.empty { display: none; }
.cal-cell.quiet { display: none; }
.cal-cell.today { border-color: var(--accent); }
.cal-day {
  display: flex; align-items: baseline; gap: .4rem;
  font-size: .8rem; color: var(--muted); font-variant-numeric: tabular-nums;
}
.cal-num { display: none; }
.cal-long { font-weight: 600; color: var(--text); text-transform: capitalize; }
.cal-hoy {
  padding: 0 .4rem; border-radius: 999px; font-size: var(--t-xs); font-weight: 700;
  background: var(--accent); color: var(--on-fill); text-transform: uppercase; letter-spacing: .04em;
}
.cal-n { margin-left: auto; font-size: var(--t-xs); }

/* Flex y no rejilla: la miniatura sólo existe cuando la pieza tiene portada,
   y con columnas fijas el texto de las que no la tienen caía en la columna de
   la miniatura y se partía letra a letra a 320px. Con flex, el texto ocupa la
   fila entera cuando va solo y cede sitio cuando hay arte. */
.cal-item {
  display: flex; gap: .65rem; align-items: center;
  margin-top: .4rem; padding: .5rem .6rem; border-radius: 6px;
  background: var(--surface-2); border-left: 3px solid var(--line);
  font-size: .9rem; color: var(--text); min-height: var(--tap);
  min-width: 0; overflow-wrap: anywhere;
}
.cal-art {
  flex: none; width: 72px; aspect-ratio: 4 / 5; object-fit: cover;
  border-radius: 6px; background: var(--surface);
}
.cal-copy { min-width: 0; flex: 1; display: block; }
.cal-item:hover { text-decoration: none; border-color: var(--accent); }
.cal-item .h { color: var(--muted); font-variant-numeric: tabular-nums; font-size: var(--t-sm); }
.cal-item .t { min-width: 0; }
.cal-tags {
  grid-column: 2; display: flex; flex-wrap: wrap; gap: .3rem; align-items: center;
  margin-top: .15rem; font-size: var(--t-xs); color: var(--muted);
}
.cal-brand, .cal-status {
  padding: 0 .4rem; border-radius: 999px; border: 1px solid var(--line); background: var(--surface);
}
.cal-media { color: var(--muted); font-size: var(--t-xs); }
.cal-item.s-en_revision { border-left-color: var(--warn); }
.cal-item.s-aprobado    { border-left-color: var(--ok); }
.cal-item.s-rechazado   { border-left-color: var(--danger); }
.cal-item.s-programado  { border-left-color: var(--accent); }
.cal-item.s-publicado   { border-left-color: var(--violet); }

/* Aprobado con fecha probable: está en el plan, pero no hay nada cargado en
   ninguna red. Se distingue por el trazo discontinuo y el fondo rebajado, no
   sólo por el color: en la rejilla mensual el color solo no basta para separar
   una intención de un compromiso, y confundirlos es justo lo que hay que
   evitar. La etiqueta «probable» lo dice además con palabras. */
.cal-item.tentativo {
  border-left-style: dashed;
  background: color-mix(in srgb, var(--surface-2) 55%, transparent);
}
.cal-item.tentativo .t { opacity: .82; }
.cal-tentativo, .cal-manual {
  padding: 0 .4rem; border-radius: 999px; font-size: var(--t-xs);
  border: 1px dashed var(--line); color: var(--muted); background: var(--surface);
}
/* Programada, pero la red no publica sola: aviso de que alguien tiene que
   subirla a esa hora. Trazo continuo —es un compromiso— y color de alerta. */
.cal-manual {
  border-style: solid; border-color: var(--warn); color: var(--warn-ink);
}
.cal-verificado { color: var(--ok-ink); font-size: var(--t-xs); font-weight: 700; }

.legend { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: 1rem; align-items: center; }
/* La leyenda explica, no sólo colorea: cada distintivo lleva al lado lo que
   significa, porque «aprobado» y «programado» se leen como sinónimos si no. */
.legend-note {
  font-size: var(--t-xs); color: var(--muted); margin-right: .5rem;
}
@media (max-width: 480px) {
  .legend { display: grid; grid-template-columns: auto 1fr; gap: .3rem .5rem; }
  .legend-note { margin-right: 0; }
}

/* Compromisos: comparte la lectura mensual del calendario editorial, pero
   cada entrada es una promesa operativa con meta, siguiente acción y evidencia. */
.commit-summary { display:grid; grid-template-columns:repeat(2,1fr); gap:.55rem; margin-bottom:1rem; }
/* Cifra arriba y etiqueta debajo: en dos columnas de teléfono, «2 Bloqueado»
   en línea se partía en anchos distintos según la palabra. Apilado, cada
   tarjeta mide lo mismo y el número es lo primero que se ve. */
.commit-stat { display:flex; flex-direction:column; gap:.1rem; padding:.75rem; border:1px solid var(--line); border-left:4px solid var(--line); border-radius:var(--radius-sm); background:var(--surface); }
.commit-stat strong { font-size:1.45rem; }
.commit-stat span { color:var(--muted); font-size:var(--t-sm); }
/* Cada compromiso se abre y se consulta con el pulgar: cuenta como objetivo
   táctil, igual que las entradas del calendario editorial. */
.commit-item { margin-top:.45rem; padding:.65rem; border-radius:7px; background:var(--surface-2); border-left:4px solid var(--line); overflow-wrap:anywhere; min-height: var(--tap); }
.commit-item h3 { margin:.15rem 0 .35rem; font-size:var(--t-md); line-height:1.25; }
.commit-item p { margin:.4rem 0 0; font-size:.78rem; color:var(--muted); }
.commit-time { font-size:var(--t-xs); color:var(--muted); font-variant-numeric:tabular-nums; }
.commit-tags { display:flex; flex-wrap:wrap; gap:.3rem; align-items:center; }
.commit-tags > span:not(.badge) { padding:0 .4rem; border:1px solid var(--line); border-radius:999px; font-size:var(--t-xs); color:var(--muted); }
.commit-item details { margin-top:.4rem; font-size:.75rem; }
.c-in_progress { border-left-color:var(--accent); }
.c-inbox { border-left-color:var(--muted); }
.c-pending { border-left-color:var(--warn); }
.c-waiting { border-left-color:var(--violet); }
.c-blocked { border-left-color:var(--danger); }
.c-review { border-left-color:var(--violet-ink); }
.c-done { border-left-color:var(--ok); }
.c-cancelled { border-left-color:var(--muted); }
.badge.c-in_progress { background:color-mix(in srgb,var(--accent) 16%,transparent); }
.badge.c-inbox { background:color-mix(in srgb,var(--muted) 16%,transparent); }
.badge.c-pending { background:color-mix(in srgb,var(--warn) 16%,transparent); }
.badge.c-waiting { background:color-mix(in srgb,var(--violet) 16%,transparent); }
.badge.c-blocked { background:color-mix(in srgb,var(--danger) 16%,transparent); }
.badge.c-review { background:color-mix(in srgb,var(--violet) 20%,transparent); }
.badge.c-done { background:color-mix(in srgb,var(--ok) 16%,transparent); }
.badge.p-critical { border-color:var(--danger); color:var(--danger-ink); font-weight:700; }
.badge.p-high { border-color:var(--warn); color:var(--warn-ink); }
.badge.p-normal,.badge.p-low { color:var(--muted); }
.dashboard-shortcut { margin:.25rem 0 1rem; }

/* Biblioteca privada de análisis. El PDF es el artefacto descargable; la
   tarjeta mantiene visible la lectura ejecutiva y la fecha vigente. */
.analysis-list { display:grid; gap:1rem; }
.analysis-card { padding:1rem; border:1px solid var(--line); border-radius:var(--radius); background:var(--surface); box-shadow:var(--shadow); }
.analysis-card h2 { margin:.2rem 0 .45rem; font-size:1.2rem; }
.analysis-card.is-reviewed { opacity:.82; }
.analysis-review-state-form { margin:0; }
.analysis-meta { display:flex; flex-wrap:wrap; gap:.4rem .8rem; color:var(--muted); font-size:var(--t-sm); }
.analysis-summary { max-width:72ch; }
.analysis-actions { display:flex; flex-wrap:wrap; gap:.6rem; margin-top:1rem; }
.analysis-empty { color:var(--muted); }
.analysis-reader-head { margin-bottom:1rem; }
/* Versión narrada. Siete archivos, un solo reproductor: la barra representa el
   informe entero y las marcas verticales enseñan dónde cambia de parte, así que
   lo que antes ocupaba siete reproductores nativos apilados —media pantalla de
   móvil antes de llegar al texto— cabe ahora en la altura de una tarjeta. */
.analysis-audio { max-width:780px; margin:0 auto 1rem; padding:1rem; border:1px solid var(--line); border-radius:var(--radius); background:var(--surface); box-shadow:var(--shadow); }
.analysis-audio h2 { margin:.15rem 0 .2rem; font-size:1.3rem; }
.ap-note { margin:0 0 .9rem; font-size:var(--t-sm); }

.audio-player[hidden] { display:none; }

/* La barra: el control real es el input, invisible y por encima; lo que se ve
   es el carril, que es lo único que se puede pintar a gusto en los tres
   navegadores. El foco del teclado se traslada al carril con el hermano. */
.ap-seek-wrap { position:relative; display:flex; align-items:center; height:32px; }
.ap-seek { position:absolute; inset:0; width:100%; height:100%; margin:0; padding:0; opacity:0; cursor:pointer; -webkit-appearance:none; appearance:none; background:transparent; }
.ap-seek::-webkit-slider-thumb { -webkit-appearance:none; width:32px; height:32px; }
.ap-seek::-moz-range-thumb { width:32px; height:32px; border:0; }
.ap-rail { position:relative; width:100%; height:6px; border-radius:999px; background:var(--surface-2); border:1px solid var(--line); }
.ap-buffer, .ap-fill { position:absolute; top:0; bottom:0; left:0; width:0; border-radius:999px; }
.ap-buffer { background:color-mix(in srgb, var(--accent) 20%, transparent); }
.ap-fill { background:linear-gradient(90deg, color-mix(in srgb, var(--accent) 65%, var(--violet)), var(--accent)); }
.ap-tick { position:absolute; top:-3px; width:2px; height:10px; margin-left:-1px; border-radius:1px; background:var(--surface); opacity:.9; }
.ap-knob { position:absolute; top:50%; left:0; width:15px; height:15px; margin:-8px 0 0 -7px; border-radius:50%;
           background:var(--accent); border:2px solid var(--surface); box-shadow:0 1px 4px rgba(0,0,0,.35); }
.ap-seek:focus-visible + .ap-rail { outline:2px solid var(--accent); outline-offset:4px; border-radius:999px; }
.ap-seek:active + .ap-rail .ap-knob { transform:scale(1.25); }

.ap-meta { display:flex; align-items:center; justify-content:space-between; gap:.5rem; margin:.15rem 0 0; font-size:var(--t-xs); color:var(--muted); }
.ap-time { font-variant-numeric:tabular-nums; flex:none; }
.ap-part { color:var(--text); font-weight:600; text-align:center; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* Transporte. Botones redondos sin caja: el toque mide los 44px aunque el
   icono ocupe la mitad. */
.ap-controls { display:flex; align-items:center; justify-content:center; gap:.1rem; margin-top:.25rem; }
.ap-btn { display:inline-flex; align-items:center; justify-content:center; position:relative; flex:none;
          min-width:var(--tap); min-height:var(--tap); padding:0; border:0; border-radius:50%;
          background:transparent; color:var(--text); cursor:pointer; -webkit-tap-highlight-color:transparent;
          touch-action:manipulation; transition:background .12s ease, transform .06s ease; }
.ap-btn svg { width:24px; height:24px; fill:currentColor; }
.ap-btn:hover { background:var(--surface-2); }
.ap-btn:active { transform:scale(.94); }
.ap-btn[disabled] { opacity:.32; cursor:default; }
.ap-btn[disabled]:hover { background:transparent; }
/* El número va dentro del círculo del icono, como en cualquier reproductor de
   pódcast: dice cuánto salta el botón sin necesidad de tocarlo. */
.ap-btn-num { position:absolute; font-size:var(--t-xs); font-weight:600; letter-spacing:-.02em; transform:translateY(1px); pointer-events:none; }
.ap-rate { font-size:var(--t-xs); font-weight:700; color:var(--muted); border-radius:999px; }
.ap-rate[data-fast] { color:var(--accent-ink); background:color-mix(in srgb, var(--accent) 14%, transparent); }

.ap-play { display:inline-flex; align-items:center; justify-content:center; flex:none; width:56px; height:56px;
           margin:0 .3rem; padding:0; border:0; border-radius:50%; background:var(--accent); color:var(--on-fill);
           cursor:pointer; -webkit-tap-highlight-color:transparent; touch-action:manipulation;
           box-shadow:0 4px 14px color-mix(in srgb, var(--accent) 38%, transparent); transition:transform .07s ease; }
.ap-play:active { transform:scale(.95); }
.ap-play svg { width:26px; height:26px; fill:currentColor; }
.ap-play .ap-icon-pause, .is-playing .ap-play .ap-icon-play { display:none; }
.is-playing .ap-play .ap-icon-pause { display:block; }
.is-loading .ap-play { animation:ap-pulse 1.1s ease-in-out infinite; }
@keyframes ap-pulse { 50% { opacity:.55; } }

/* Sin JavaScript se sirve la lista de siempre. */
.audio-playlist { list-style:none; padding:0; margin:1rem 0 0; display:grid; gap:.75rem; }
.audio-playlist li { padding:.7rem; border-radius:12px; background:var(--surface-2); }
.audio-playlist span { display:block; margin-bottom:.4rem; color:var(--muted); font-size:var(--t-sm); }
.audio-playlist audio { display:block; width:100%; height:42px; }
.analysis-reader-head .back-link { display:inline-block; margin-bottom:1rem; color:var(--muted); }
.analysis-reader { max-width:780px; margin:0 auto; padding:clamp(1rem,4vw,2.2rem); border:1px solid var(--line); border-radius:var(--radius); background:var(--surface); box-shadow:var(--shadow); font-size:1rem; line-height:1.72; overflow-wrap:anywhere; }
.analysis-reader h2 { margin:1.8rem 0 .7rem; font-size:clamp(1.35rem,5vw,1.75rem); line-height:1.2; }
.analysis-reader h3 { margin:1.45rem 0 .55rem; font-size:clamp(1.1rem,4vw,1.3rem); line-height:1.3; }
.analysis-reader h2:first-child { margin-top:0; font-size:clamp(1.65rem,7vw,2.3rem); }
.analysis-reader p { margin:.75rem 0; }
.analysis-reader ul, .analysis-reader ol { margin:.7rem 0 1rem; padding-left:1.35rem; }
.analysis-reader li { margin:.55rem 0; padding-left:.15rem; }
.analysis-reader strong { color:var(--text); }
.analysis-review { max-width:780px; margin:1rem auto 0; padding:clamp(1rem,4vw,1.6rem); border:1px solid var(--line); border-radius:var(--radius); background:var(--surface); box-shadow:var(--shadow); }
.analysis-review h2 { margin:.15rem 0 .35rem; }
.analysis-review-form { display:grid; gap:.8rem; margin-top:1rem; }
.analysis-review-form textarea { width:100%; min-height:8rem; }
.review-type-options { display:flex; flex-wrap:wrap; gap:.65rem 1rem; margin:0; padding:.8rem; border:1px solid var(--line); border-radius:.75rem; }
.review-type-options legend { padding:0 .35rem; font-weight:700; }
.review-type-options label { display:flex; align-items:center; gap:.4rem; cursor:pointer; }
.analysis-review-history { margin-top:1.5rem; padding-top:1rem; border-top:1px solid var(--line); }
.analysis-feedback-item { padding:.9rem 0; border-bottom:1px solid var(--line); }
.analysis-feedback-item:last-child { border-bottom:0; padding-bottom:0; }
.analysis-feedback-item p { margin:.45rem 0; }
.analysis-feedback-meta { display:flex; justify-content:space-between; align-items:center; gap:.7rem; }
.analysis-resolution { padding:.75rem; border-radius:.65rem; background:var(--surface-2); }

@media (max-width: 520px) {
  .analysis-audio { margin-inline:-.25rem; padding:.85rem; }
  .analysis-reader { margin-inline:-.25rem; padding:1rem; border-radius:14px; line-height:1.65; }
  .analysis-reader-head .analysis-actions .btn { width:100%; }
}

/* ------------------------------------------------------------------ */
/* A partir de tableta: más columnas, nada nuevo que aprender.          */
/* ------------------------------------------------------------------ */
@media (min-width: 700px) {
  :root { --topbar-h: 56px; --botnav-h: 0px; }

  /* La navegación vuelve arriba y la barra inferior desaparece del todo. */
  .nav { display: flex; }
  .botnav { display: none; }
  .app main.wrap { padding-bottom: calc(1rem + var(--safe-b)); }
  .session .who { display: flex; }
  .topbar-title { font-size: 1.25rem; }

  .row3 { grid-template-columns: repeat(3, 1fr); }
  .filters { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
  .queue { grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }

  /* Lo que espera decisión en el panel: tarjetas compactas en rejilla, tres o
     cuatro por fila según el ancho, en lugar de una fila por pieza cruzando la
     pantalla entera. `auto-fill` y no `auto-fit` a propósito: con una sola
     pieza pendiente la tarjeta conserva su ancho de columna en vez de
     estirarse de lado a lado, que es justo lo que se quería evitar. */
  .queue-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: .8rem; }
  /* Misma altura en toda la fila, con las dos decisiones alineadas abajo aunque
     un título ocupe dos líneas y el de al lado sólo una. */
  .queue-grid > .queue-row { display: flex; flex-direction: column; }
  .queue-grid > .queue-row .rcard-body { flex: 1 1 auto; padding: .7rem .75rem; }
  .queue-grid > .queue-row .rcard-actions { margin-top: auto; padding: .6rem .75rem; }
  /* En una columna estrecha un título largo desequilibraría la fila entera. */
  .queue-grid .rcard-title {
    font-size: .98rem;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    line-clamp: 2; overflow: hidden;
  }
  .queue-grid .rcard-title a { display: block; }
  .queue-grid .btn.approve, .queue-grid .btn.reject { min-height: 42px; font-size: .88rem; }
  .btn.sm { min-height: 2rem; }
  .btn.lg { width: auto; }
  .hero { display: flex; align-items: center; gap: 1rem; }
  .hero-n { font-size: 2.2rem; }
  .hero-l { margin: 0; flex: 1; }
  .media-admin li { grid-template-columns: 5rem 1fr auto; align-items: center; }
  .media-admin .m-caption { grid-column: 1 / -1; }
  .gallery.many .ga { flex-basis: 44%; }

  /* Con varias tarjetas en paralelo la barra fija estorba: vuelve al flujo. */
  .rcard-actions { position: static; }
  .ga-frame { aspect-ratio: 4 / 3; max-height: none; }

  /* Visor de revisión en escritorio: la creatividad permanece dentro del
     sistema y comparte pantalla con el copy y las decisiones. */
  .rcard.review-focus {
    position: fixed; inset: clamp(1rem, 3vw, 2.5rem); z-index: 100;
    display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(300px, .7fr);
    grid-template-rows: minmax(0, 1fr) auto;
    width: auto; max-width: 1500px; height: auto; margin: auto;
    overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--surface); box-shadow: 0 0 0 100vmax rgba(0,0,0,.78), var(--shadow);
  }
  .rcard.review-focus .rcard-media {
    grid-row: 1 / -1; min-width: 0; min-height: 0; border-radius: var(--radius) 0 0 var(--radius);
    display: flex; align-items: center; background: #08090b;
  }
  .rcard.review-focus .gallery,
  .rcard.review-focus .gallery .ga,
  .rcard.review-focus .ga-frame { width: 100%; height: 100%; min-height: 0; }
  .rcard.review-focus .gallery img,
  .rcard.review-focus .gallery video { width: 100%; height: 100%; object-fit: contain; }
  .rcard.review-focus .rcard-body {
    display: block; grid-column: 2; min-height: 0; padding: 1.25rem; overflow-y: auto;
  }
  .rcard.review-focus .rcard-caption { white-space: pre-wrap; }
  .rcard.review-focus .rcard-actions {
    display: grid; grid-column: 2; position: static; padding: 1rem 1.25rem;
    border-radius: 0 0 var(--radius) 0; box-shadow: 0 -8px 24px rgba(0,0,0,.12);
  }
  .rcard.review-focus .act-reject[open] { max-height: 45vh; overflow-y: auto; }
  .review-focus-controls { left: calc((100% - max(300px, 29.17%)) / 2); }

  .cal { grid-template-columns: repeat(7, 1fr); gap: 4px; }
  .cal-dow { display: block; font-size: var(--t-xs); color: var(--muted); text-align: center; padding: .3rem 0; }
  .cal-cell { min-height: 96px; padding: .45rem .55rem; }
  .cal-cell.empty { display: block; background: transparent; border-color: transparent; }
  .cal-cell.quiet { display: block; }
  .cal-cell.weekend { background: var(--surface-2); }
  .cal-day { display: block; }
  .cal-num { display: inline; }
  .cal-long, .cal-n { display: none; }
  .cal-hoy { font-size: var(--t-xs); }
  .cal-item {
    display: grid; grid-template-columns: 36px minmax(0, 1fr); gap: .35rem;
    font-size: var(--t-xs); min-height: 0; padding: .25rem; margin-top: .25rem;
    overflow: hidden; white-space: nowrap;
  }
  .cal-art { width: 36px; border-radius: 3px; }
  .cal-copy { overflow: hidden; text-overflow: ellipsis; }
  .cal-item .h { margin-right: .25rem; font-size: inherit; }
  .cal-item .t { display: inline; }
  .cal-tags { display: inline; margin: 0; }
  .cal-brand, .cal-status { display: none; }
  .cal-head { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: .8rem; }
  .commit-summary { grid-template-columns:repeat(4,1fr); }
  .analysis-list { grid-template-columns:repeat(auto-fit,minmax(320px,1fr)); }
  .commitment-cal .cal-cell { min-height:120px; }
  .commitment-cal .commit-item h3 { font-size:.76rem; }
  .commitment-cal .commit-item p, .commitment-cal .commit-item details { display:none; }
  .chips { margin-inline: 0; padding-inline: 0; }
}

@media (min-width: 900px) {
  /* Ficha de revisión: en escritorio el arte y la decisión comparten el
     primer viewport. Móvil conserva intacto el flujo vertical anterior. */
  /* La ficha de revisión ya era más ancha que el resto; ahora sigue al
     contenedor cuando éste la supera, y nunca baja de los 1560px de antes. */
  body:has(.piece-review-workspace) main.wrap { max-width: max(1560px, var(--wrap-max)); }
  .piece-review-workspace {
    display: grid;
    grid-template-columns: minmax(0, 1.9fr) minmax(340px, .72fr);
    grid-template-rows: auto auto;
    gap: 1rem;
    align-items: start;
  }
  .piece-review-workspace > .panel { margin-bottom: 0; }
  .piece-review-material { grid-column: 1; grid-row: 1 / span 2; }
  .piece-review-decision { grid-column: 2; grid-row: 1; }
  .piece-review-flow { grid-column: 2; grid-row: 2; position: sticky; top: calc(var(--topbar-h) + 4.5rem); }
  .piece-review-decision .rcard-actions { position: static; padding: 0; border: 0; background: transparent; }
  .piece-review-material > .gallery .ga-frame { max-height: calc(100vh - 11rem); aspect-ratio: auto; min-height: 520px; }
  .piece-review-material > .gallery img,
  .piece-review-material > .gallery video { max-height: calc(100vh - 11rem); }
  .piece-review-workspace + .cols { margin-top: 1rem; }
  .cols { grid-template-columns: 2fr 1fr; }
  .panel { padding: 1.2rem; }
  .topbar-inner { padding-block: .6rem; }
  .gallery.many .ga { flex-basis: 30%; }
}

/* Cuatro columnas y se acabó: el panel muestra cuatro piezas, así que dejar que
   `auto-fill` abriera una quinta y una sexta pista en un monitor grande sólo
   habría devuelto el hueco lateral dentro de la propia rejilla. */
@media (min-width: 1140px) {
  .queue-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* En pantallas estrechas la tabla se convierte en tarjetas apiladas. */
@media (max-width: 699px) {
  .table thead { display: none; }
  .table, .table tbody, .table tr, .table td { display: block; width: 100%; }
  .table tr { border-bottom: 1px solid var(--line); padding: .5rem 0; }
  .table td { border: 0; display: flex; justify-content: space-between; gap: 1rem;
              align-items: center; padding: .3rem .8rem; }
  .table td::before { content: attr(data-l); color: var(--muted); font-size: var(--t-xs); flex: none; }
  .table .td-thumb { width: auto; }
  .row-caption { text-align: right; }
}

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

/* Evidencia editorial: sólo se renderiza cuando el hash del arte coincide con
   una revisión real registrada por Claude. */
.claude-review {
  margin: 1rem 0;
  padding: .85rem 1rem;
  border-left: 3px solid #8b5cf6;
  border-radius: 0 .75rem .75rem 0;
  background: color-mix(in srgb, #8b5cf6 8%, var(--surface, #fff));
}
.claude-review p { margin: 0; line-height: 1.5; }
.claude-review-label {
  margin-top: .45rem !important;
  font-size: .82rem;
  font-weight: 700;
  color: var(--muted, #667085);
}
.analysis-archive-form{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap;margin:0}
.analysis-archive-form input[type="text"]{min-width:12rem;max-width:22rem}
.analysis-archive-head{margin-top:2.5rem}

/* === Tablero, clientes y asistente ======================================= */

/* El tablero: columnas que en el teléfono se recorren de lado con el pulgar
   (scroll con ajuste por columna) y en pantallas anchas se ven las cuatro a la
   vez. La tarjeta es la unidad; la columna es sólo el estado que la contiene. */
.board {
  display: grid; grid-auto-flow: column; grid-auto-columns: min(82vw, 300px);
  align-items: start;
  gap: .75rem; overflow-x: auto; scroll-snap-type: x proximity;
  padding-bottom: .75rem; margin-top: 1rem;
  -webkit-overflow-scrolling: touch;
}
.board-col {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  scroll-snap-align: start; display: flex; flex-direction: column; align-self:start;
  border-top: 3px solid var(--line);
}
.board-col.c-pending     { border-top-color: var(--warn); }
.board-col.c-inbox       { border-top-color: var(--muted); }
.board-col.c-in_progress { border-top-color: var(--accent); }
.board-col.c-waiting     { border-top-color: var(--violet); }
.board-col.c-blocked     { border-top-color: var(--danger); }
.board-col.c-review      { border-top-color: var(--violet-ink); }
.board-col.c-done        { border-top-color: var(--ok); }
.board-col-head { padding: .7rem .8rem .4rem; }
.board-col-head h2 { margin: 0; font-size: var(--t-md); display: flex; align-items: center; gap: .45rem; }
.board-col-head p { margin: .15rem 0 0; font-size: var(--t-xs); }
.board-n {
  font-size: var(--t-xs); font-weight: 600; color: var(--muted);
  background: var(--surface-2); border-radius: 999px; padding: .05rem .5rem;
}
.board-cards { display: flex; flex-direction: column; gap: .55rem; padding: .55rem .55rem .7rem; min-height: 4rem; }
.board-empty { margin: .5rem .3rem; font-size: var(--t-sm); }
.board-card {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: .6rem .7rem;
}
.board-card h3 { margin: 0 0 .25rem; font-size: var(--t-md); line-height: 1.3; }
.board-card h3 a { color: var(--text); }
.board-card.dragging { opacity: .5; }
.board-col.drop-ok { outline: 2px dashed var(--accent); outline-offset: -4px; }
.board-meta {
  margin: 0; display: flex; flex-wrap: wrap; gap: .25rem .6rem; align-items: center;
  font-size: var(--t-xs); color: var(--muted);
}
.board-client { font-weight: 600; color: var(--accent-ink); }
.board-next { margin: .3rem 0 0; font-size: var(--t-sm); color: var(--muted); }
.board-detail { margin-top:.4rem; font-size:var(--t-xs); color:var(--muted); }
.board-detail summary { color:var(--accent-ink); cursor:pointer; }
.board-detail p { margin:.35rem 0 0; }
.board-move { margin-top: .35rem; }
.board-move summary { font-size: var(--t-xs); color: var(--accent-ink); cursor: pointer; padding: .2rem 0; }
.board-move-opts { display: flex; flex-wrap: wrap; gap: .35rem; padding-top: .3rem; }
.board-move-opts form { margin: 0; }
.board-head { margin-bottom: .25rem; }
.board-context { margin: .35rem 0 0; font-size: var(--t-sm); }
.board-add { margin: .75rem 0; }
@media (min-width: 900px) {
  .board { grid-auto-columns:minmax(250px,1fr); }
}

/* Clientes: fichas con sus cifras. Lo que reclama atención va en tinta de
   aviso; el resto informa sin gritar. */
.client-grid { display: grid; gap: .75rem; margin-top: 1rem; }
@media (min-width: 700px) { .client-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); } }
.client-card {
  display: flex; flex-direction: column; gap: .4rem;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .8rem .9rem; color: var(--text);
}
.client-card:hover { text-decoration: none; border-color: var(--accent); }
.client-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.client-head strong { font-size: var(--t-lg); }
.client-summary { font-size: var(--t-sm); color: var(--muted); }
.client-stats { display: flex; flex-wrap: wrap; gap: .3rem .9rem; font-size: var(--t-xs); color: var(--muted); }
.client-stats b { color: var(--text); }
.client-warn b, .client-warn { color: var(--danger-ink); }
.badge.k-cliente   { border-color: var(--accent); color: var(--accent-ink); }
.badge.k-prospecto { border-color: var(--warn); color: var(--warn-ink); }
.badge.k-interno   { color: var(--muted); }
.client-top { margin: .25rem 0 1rem; }
.client-kind { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: 0 0 .35rem; }
.client-lede { margin: 0; color: var(--muted); }
.topic-add { margin-top: .75rem; }
.prewrap { white-space: pre-wrap; }
.inline-form { display: inline; margin: 0; }

/* Sugerencias del asistente: cada una con sus dos salidas a la vista. */
.suggestion { display: flex; flex-wrap: wrap; gap: .5rem .9rem; align-items: center; }
.suggestion-body { flex: 1 1 16rem; display: flex; flex-direction: column; gap: .2rem; }
.suggestion-title { font-weight: 600; }
.suggestion-actions { display: flex; gap: .4rem; }
.suggestion-actions form { margin: 0; }
.badge.sug-accent { border-color: var(--accent); color: var(--accent-ink); }
.badge.sug-danger { border-color: var(--danger); color: var(--danger-ink); }
.badge.sug-ok     { border-color: var(--ok); color: var(--ok-ink); }
.badge.sug-warn   { border-color: var(--warn); color: var(--warn-ink); }

/* «Más»: la página del quinto icono. Tarjetas grandes, una por sección, con
   el icono heredando el color del texto igual que en la barra. */
.more-grid { display: grid; gap: .75rem; margin-top: 1rem; }
@media (min-width: 700px) { .more-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); } }
.more-card {
  display: grid; grid-template-columns: auto 1fr; gap: .2rem .7rem; align-items: center;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: .85rem 1rem; color: var(--text); min-height: var(--tap);
}
.more-card:hover { text-decoration: none; border-color: var(--accent); }
.more-card .bn-icon { grid-row: span 2; width: 26px; height: 26px; color: var(--accent-ink); }
.more-label { font-weight: 600; display: flex; align-items: center; gap: .45rem; }
.more-desc { font-size: var(--t-sm); color: var(--muted); grid-column: 2; }

/* Sistema operativo personal: lectura ejecutiva, sin controles que sugieran
   permisos inexistentes. El riesgo se distingue por borde, no sólo por color. */
.life-risk { border-left-color: var(--danger); }
.life-layout { display:grid; gap:1rem; align-items:start; }
.life-objectives,.life-competencies { display:grid; gap:.75rem; }
.life-objective,.life-competency { border:1px solid var(--line); border-left:4px solid var(--accent); border-radius:var(--radius-sm); padding:.8rem; background:var(--surface-2); }
.life-objective.is-at_risk { border-left-color:var(--danger); }
.life-objective.is-paused,.life-objective.is-archived { border-left-color:var(--muted); }
.life-objective-head { display:flex; justify-content:space-between; gap:.75rem; align-items:flex-start; }
.life-objective h3 { margin:.12rem 0 .35rem; font-size:var(--t-md); }
.life-objective p,.life-competency p { margin:.35rem 0; font-size:var(--t-sm); }
.life-outcomes { list-style:none; margin:.6rem 0; padding:0; display:grid; gap:.35rem; }
.life-outcomes li { display:flex; justify-content:space-between; gap:.75rem; font-size:var(--t-sm); border-top:1px solid var(--line); padding-top:.35rem; }
.life-outcomes span { color:var(--muted); font-variant-numeric:tabular-nums; }
.life-signal { border-left:2px solid var(--violet); padding-left:.55rem; }
.life-signal span { display:block; color:var(--muted); font-size:var(--t-xs); }
.life-competency { border-left-color:var(--violet); }
.life-competency p { color:var(--muted); }
.life-add > summary { font-size:var(--t-md); }
.life-forms { display:grid; gap:1rem; margin-top:1rem; }
.life-forms form { border:1px solid var(--line); border-radius:var(--radius-sm); padding:.8rem; background:var(--surface-2); }
.life-forms h3 { margin:.1rem 0 .7rem; font-size:var(--t-md); }
.life-forms label { display:block; margin:.55rem 0; color:var(--muted); font-size:var(--t-sm); }
.life-forms input,.life-forms select,.life-forms textarea { width:100%; margin-top:.2rem; }
.life-forms textarea { min-height:5rem; }
@media (min-width:900px) {
  .life-layout { grid-template-columns:minmax(0,1.7fr) minmax(300px,.8fr); }
  .life-side { position:sticky; top:calc(var(--topbar-h) + 1rem); }
  .life-competencies { grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); }
  .life-forms { grid-template-columns:repeat(2,minmax(0,1fr)); }
}

/* Pulido del móvil: más aire entre lo apilado. En una pantalla estrecha todo
   va en una columna y el borde de cada tarjeta se convierte en ruido; un poco
   más de separación y de padding interior hace el mismo trabajo con menos
   líneas a la vista. */
@media (max-width: 699px) {
  .panel { padding: 1rem .95rem; margin-bottom: 1.15rem; }
  .list li { padding: .75rem 0; }
  .inbox-head, .panel-head { row-gap: .25rem; }
}

/* La ficha se abre para consultar: el formulario largo va plegado y el borde
   del pliegue hace de título de sección. */
.edit-fold > summary { cursor: pointer; list-style: none; }
.edit-fold > summary::-webkit-details-marker { display: none; }
.edit-fold > summary h2 { display: inline-block; margin: 0; }
.edit-fold > summary::after { content: ' ▸'; color: var(--muted); }
.edit-fold[open] > summary::after { content: ' ▾'; }
.edit-fold[open] > summary { margin-bottom: .8rem; }
details.danger-zone { border-color: var(--danger); margin-top: 1rem; }
details.danger-zone > summary { cursor: pointer; color: var(--danger-ink); font-weight: 600; }

.review-trace { margin:.55rem 0; padding:.55rem .7rem; border-left:3px solid var(--accent); background:var(--surface-2); border-radius:var(--radius-sm); }
.review-trace p { margin:.15rem 0; font-size:var(--t-sm); }
.review-trace blockquote { margin:.4rem 0 0; white-space:normal; }
.review-trace.is-empty { border-left-color:var(--muted); color:var(--muted); }
.version-list { display:grid; gap:.5rem; padding-left:1.35rem; }
.badge.sch-revision-vigente { border-color:var(--ok); color:var(--ok-ink); }
