/* ============================================================================
   _cuerpo-puntos-spark.css — motor.css + componente.css (v2, 19-ago-2026).
   Primero el componente genérico (.cuerpo-stage/.cuerpo-marcador/.cuerpo-item),
   después el layout de las dos ubicaciones reales (.cuerpo-bascula-fb,
   .cuerpo-origen-px). Va como ÚLTIMA hoja del <head> de cada página.
   ============================================================================ */
/* ============================================================================
   CUERPO DE PUNTOS SPARK — motor.css (universal)
   Namespace: .cuerpo-stage + hijos .cuerpo-*, .cm-*, .ci-*  (E4 del workflow «cuerpo»)
   OJO al editar este comentario: nunca escribir la secuencia asterisco-barra
   dentro de un bloque de comentario CSS — el parser la lee como cierre aunque
   sea texto descriptivo, y corrompe el parseo de todo lo que viene después
   (bug real detectado en la v1 de este archivo: .cuerpo-stage completo no
   se aplicaba porque este comentario se cerraba solo, en la línea de arriba).

   Qué vive aquí (lo que es IGUAL en fatburner.html y pelvix.html):
     · el escenario del canvas 2D (.cuerpo-stage/.cuerpo-lienzo)
     · los marcadores squircle sobre el cuerpo (.cuerpo-marcador)
     · el panel-acordeón <details> (.cuerpo-panel/.cuerpo-item)
     · la degradación sin-JS y prefers-reduced-motion

   Lo que NO vive aquí (lo escribe la tarea de componente.css):
     · el grid/layout que ubica el escenario y el panel uno junto al otro
     · nombres de página, copy, data específica de fatburner/pelvix

   Markup mínimo esperado (contrato §1/§7 en …/scratchpad/wfe/cuerpo/contrato.md —
   OJO: .cuerpo-lienzo va DIRECTO en el <canvas>, no en un div envoltorio):
     <div class="cuerpo-stage" data-cuerpo="fatburner" style="--cuerpo-acento:#bd0e31">
       <canvas class="cuerpo-lienzo" aria-hidden="true"></canvas>
       <img class="cuerpo-fallback" src="assets/cuerpo-fatburner-720.png" alt="…" width="720" height="960">
       <button class="cuerpo-marcador" data-region="visceral" style="left:50%;top:40%">
         <span class="cm-caja"><i></i></span><span class="cm-lbl">Grasa visceral</span>
       </button>
       <script type="application/json" class="cuerpo-escena">{ … }</script>
     </div>
     <div class="cuerpo-panel">
       <details class="cuerpo-item" data-item="it-visceral" data-region="visceral">
         <summary><span>Grasa visceral</span><span class="ci-signo"></span></summary>
         <div class="ci-cuerpo"><p>…</p></div>
       </details>
     </div>

   Tokens usados (definidos en _sistema-spark.css, NO se redeclaran aquí):
     --fondo --quieto --panel --tinta --suave --linea --carmin --carmin-activo
     --r-xxs…--r-3xl --r-full --ease --voz --serif
   ========================================================================= */


/* ===== §A ESCENARIO — .cuerpo-stage / .cuerpo-lienzo ===================== */
/* el contenedor del canvas: variables locales que la página puede
   sobreescribir inline (--cuerpo-acento por campaña, etc.) sin tocar los
   tokens globales. container-type habilita futuras cqw en componente.css
   sin que este archivo tenga que declarar el grid. Sin radio/overflow
   propios a propósito: el marco visual (esquinas, recorte) es layout de
   página y le toca a componente.css, no al motor. */
.cuerpo-stage{
  position:relative;
  container-type:inline-size;
  --cuerpo-fondo:var(--fondo);
  --cuerpo-acento:var(--carmin);
  --cuerpo-alto:560px;
  background:var(--cuerpo-fondo);
  min-height:var(--cuerpo-alto);
}

/* el <canvas class="cuerpo-lienzo"> (contrato §1: la clase va DIRECTO en el
   canvas, no en un div envoltorio) ocupa todo el escenario, no captura
   clicks (los clicks reales están en los <button> .cuerpo-marcador) y no
   se selecciona. El aria-hidden="true" lo pone el HTML/motor.js siempre:
   el contenido accesible real vive en el acordeón, nunca en el dibujo. */
.cuerpo-lienzo{
  display:block;
  position:absolute;
  inset:0;
  pointer-events:none;
  -webkit-user-select:none;user-select:none;-webkit-user-drag:none;
}


/* ===== §B FALLBACK — .cuerpo-fallback ===================================== */
/* PNG exportado del propio canvas (assets/cuerpo-<escena>-*.png), superpuesta
   al mismo cuadro que el canvas (contrato §7). Se ve por defecto SIEMPRE; el
   motor la oculta al montar añadiendo .cuerpo-vivo al escenario. html:not(.js)
   la deja visible pase lo que pase: es la única garantía real de
   degradación cuando no hay JS. */
.cuerpo-fallback{
  display:block;
  position:absolute;
  inset:0;
  width:100%;height:100%;
  object-fit:contain; /* el fotograma entero, sin recortar la cabeza en escenarios más anchos que altos */
  object-position:center;
}
.cuerpo-stage.cuerpo-vivo .cuerpo-fallback{display:none}
html:not(.js) .cuerpo-fallback{display:block!important}


/* ===== §C MARCADOR — .cuerpo-marcador (hermano de .globo-pin, §6 playbook) */
/* <button> transparente posicionado por left/top inline (motor.js calcula
   la proyección 3D→2D); transform centra la caja en su ancla. Tres estados,
   todos el MISMO carmín graduado (principio §0.4): oculto → .on (la región
   está "en escena": caja de contorno fino + punto sólido, como la referencia)
   → .activo (región encendida: caja llena + punto hueco, igual que el pin
   del globo). .atras = el ancla cayó en la cara oculta del cuerpo: se atenúa
   pero no desaparece. La caja es la ÚNICA superficie clicable grande; el
   botón entero mide ≥44px de alto por el padding vertical. */
.cuerpo-marcador{
  --cm-size:26px;
  position:absolute;
  left:0;top:0;
  display:flex;
  align-items:center;
  gap:.5rem;
  background:transparent;
  border:0;padding:7px 0;margin:0;
  cursor:pointer;
  font-family:var(--voz);
  transform:translate(calc(-1 * var(--cm-size) / 2),-50%) scale(.6);
  transform-origin:calc(var(--cm-size) / 2) 50%;
  opacity:0;
  transition:opacity .5s cubic-bezier(.16,1,.3,1),transform .5s cubic-bezier(.16,1,.3,1);
  will-change:transform;
  pointer-events:none;
}
.cuerpo-marcador.on{opacity:1;transform:translate(calc(-1 * var(--cm-size) / 2),-50%) scale(1);pointer-events:auto}
.cuerpo-marcador.atras{opacity:.28;pointer-events:none}
.cuerpo-marcador:hover .cm-caja,
.cuerpo-marcador:focus-visible .cm-caja{transform:scale(1.08)}
/* foco de teclado: anillo de 1px a 4px de separación, nunca outline:none a secas */
.cuerpo-marcador:focus-visible{outline:1px solid var(--cuerpo-acento);outline-offset:4px;border-radius:var(--r-full)}

.cm-caja{
  width:var(--cm-size);height:var(--cm-size);
  flex:none;
  display:grid;place-items:center;
  background:transparent;
  border:1.25px solid var(--cuerpo-acento);
  border-radius:8px;
  box-sizing:border-box;
  transition:transform .2s var(--ease),background-color .35s var(--ease),box-shadow .35s var(--ease);
}
@supports (corner-shape:squircle){
  /* compensación de la escala Neko (playbook §1.2): 9 → 15 para caja de 30px */
  .cm-caja{border-radius:13px;corner-shape:squircle}
}
/* punto central: sólido carmín en reposo; hueco (color de fondo) cuando la
   caja se llena — el mismo gesto que .gp-caja i del globo */
.cm-caja i{
  width:7px;height:7px;
  border-radius:50%;
  background:var(--cuerpo-acento);
  display:block;
  transition:background-color .35s var(--ease);
}
.cuerpo-marcador.activo .cm-caja{background:var(--cuerpo-acento);box-shadow:0 8px 24px rgba(34,23,19,.16)}
.cuerpo-marcador.activo .cm-caja i{background:var(--cuerpo-fondo)}
.cuerpo-marcador.atras .cm-caja{box-shadow:none}
@media(max-width:767px){
  .cuerpo-marcador{--cm-size:24px}
  .cm-caja{border-radius:7px}
  .cm-caja i{width:7px;height:7px}
}

.cm-lbl{
  font-size:14px;font-weight:400;letter-spacing:0;line-height:1.2;
  color:var(--suave);
  white-space:nowrap;
  transition:color .35s var(--ease);
}
.cuerpo-marcador.activo .cm-lbl{color:var(--tinta);font-weight:500}
/* la etiqueta es solo para lectores de pantalla salvo que el escenario pida
   .cm-etiquetas: el nombre de la zona ya lo dice el panel abierto al lado, y
   sobre el cuerpo de puntos el texto compite (la referencia tampoco rotula) */
.cuerpo-stage:not(.cm-etiquetas) .cm-lbl{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);margin:-1px}
@media(max-width:719px){
  .cm-lbl{display:none}
}
/* variante con la etiqueta a la IZQUIERDA de la caja (calcada de .globo-pin):
   la caja sigue centrada en el ancla, el texto cuelga hacia el lado del titular */
.cuerpo-stage.cm-izq .cuerpo-marcador{
  flex-direction:row-reverse;
  transform:translate(calc(-100% + var(--cm-size) / 2),-50%) scale(.6);
  transform-origin:calc(100% - var(--cm-size) / 2) 50%;
}
.cuerpo-stage.cm-izq .cuerpo-marcador.on{transform:translate(calc(-100% + var(--cm-size) / 2),-50%) scale(1)}


/* ===== §D ACORDEÓN — .cuerpo-panel / .cuerpo-item ========================= */
/* el panel en sí: ancho y tipografía nada más — la ubicación junto al
   escenario (grid/flex de la sección) la decide componente.css. */
.cuerpo-panel{
  display:flex;
  flex-direction:column;
  gap:.9rem;
  width:100%;
}
@media(min-width:980px){
  .cuerpo-panel{max-width:460px}
}

/* tarjeta squircle sobre --panel; borde --linea; línea de acento a la
   izquierda solo cuando está abierta (nunca oculta el item por CSS: sin JS
   y sin abrir, el <details> sigue siendo 100% legible y operable) */
.cuerpo-item{
  background:var(--panel);
  border:1px solid var(--linea);
  border-left:3px solid transparent;
  border-radius:var(--r-l);
  overflow:hidden;
}
@supports (corner-shape:squircle){
  /* compensación de la escala Neko para radio 24 → 46 (playbook §1.2) */
  .cuerpo-item{border-radius:46px;corner-shape:squircle}
}
.cuerpo-item[open]{
  background:var(--panel);
  border-left-color:var(--carmin);
  box-shadow:0 10px 30px rgba(34,23,19,.08);
}

/* píldora-título: sin marcador nativo (ni ::marker ni el triángulo webkit),
   altura de toque ≥44px */
.cuerpo-item > summary{
  list-style:none;
  cursor:pointer;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1rem;
  min-height:44px;
  padding:.85rem 1.3rem;
  font-family:var(--voz);
  font-size:16px;font-weight:500;letter-spacing:-.1px;
  color:var(--tinta);
}
.cuerpo-item > summary::-webkit-details-marker{display:none}
.cuerpo-item > summary::marker{content:""}
.cuerpo-item > summary:focus-visible{outline:1px solid var(--carmin);outline-offset:-3px;border-radius:var(--r-xs)}

/* signo +/× construido con dos barras en pseudo-elementos: rotar ambas 45°
   convierte el + en × sin tocar contenido (mismo par de líneas, otro ángulo) */
.ci-signo{
  flex:none;
  width:22px;height:22px;
  position:relative;
}
.ci-signo::before,.ci-signo::after{
  content:"";
  position:absolute;inset:0;margin:auto;
  background:var(--carmin);
  border-radius:1px;
  transition:transform .3s var(--ease);
}
.ci-signo::before{width:14px;height:2px}
.ci-signo::after{width:2px;height:14px}
.cuerpo-item[open] .ci-signo::before,
.cuerpo-item[open] .ci-signo::after{transform:rotate(45deg)}

/* cuerpo del item: texto secundario + viñetas con cuadradito de acento */
.cuerpo-item .ci-cuerpo{
  padding:0 1.3rem 1.2rem;
  color:var(--suave);
  font-size:15px;line-height:1.55;
}
.cuerpo-item .ci-cuerpo ul{list-style:none;display:flex;flex-direction:column;gap:.5rem;margin-top:.6rem}
.cuerpo-item .ci-cuerpo li{position:relative;padding-left:1.3rem}
.cuerpo-item .ci-cuerpo li::before{
  content:"";
  position:absolute;left:0;top:.45em;
  width:7px;height:7px;
  background:var(--carmin);
  border-radius:1px;
}

/* media del ítem (como la tarjeta-foto del panel de la referencia): foto real
   de la clínica arriba del texto, squircle, recorte 16:9 — ancla lo abstracto
   del cuerpo de puntos a la sesión real. Sin JS también se ve. */
.cuerpo-item .ci-media{
  margin:.1rem 0 .95rem;
  aspect-ratio:4/3; /* fase B: las tarjetas-foto traen fotos verticales; 16/9 tiraba el 58 % */
  overflow:hidden;
  border-radius:var(--r-m);
  background:var(--quieto);
}
@supports (corner-shape:squircle){
  .cuerpo-item .ci-media{border-radius:29px;corner-shape:squircle}
}
.cuerpo-item .ci-media img{width:100%;height:100%;object-fit:cover;display:block}
/* enlace que conversa con el resto de la página (una sola línea, al pie) */
.cuerpo-item .ci-link{
  display:inline-block;margin-top:.9rem;
  font-family:var(--voz);font-size:14px;font-weight:500;letter-spacing:0;
  color:var(--carmin);text-decoration:none;
  border-bottom:1px solid transparent;
  transition:border-color .3s var(--ease),color .3s var(--ease);
}
.cuerpo-item .ci-link:hover{border-bottom-color:currentColor}
.cuerpo-item .ci-link:focus-visible{outline:1px solid var(--carmin);outline-offset:3px;border-radius:2px}

/* apertura suave del <details>: se anima solo si el navegador soporta
   interpolate-size (Chrome 129+ vía ::details-content); en el resto el
   <details> nativo simplemente salta abierto/cerrado — sigue funcionando */
@supports (interpolate-size:allow-keywords){
  .cuerpo-item{interpolate-size:allow-keywords}
  .cuerpo-item::details-content{
    height:0;
    overflow:hidden;
    transition:height .4s var(--ease),content-visibility .4s allow-discrete;
    transition-behavior:allow-discrete;
  }
  .cuerpo-item[open]::details-content{height:calc-size(auto,size)}
}


/* ===== §E RESPONSIVE — solo anchos y tipografía del panel ================= */
/* nunca fija display/flex-direction/grid del bloque escenario+panel: eso es
   layout de página y le corresponde a componente.css */
@media(min-width:980px){
  .cuerpo-item > summary{font-size:17px}
}
@media(max-width:767px){
  .cuerpo-item > summary{font-size:15px;padding:.75rem 1.1rem}
  .cuerpo-item .ci-cuerpo{font-size:14px;padding:0 1.1rem 1rem}
}


/* ===== §F DEGRADACIÓN (playbook §8, no negociable) ========================= */
/* reduced-motion: fuera transiciones/animaciones del componente; los
   marcadores quedan en su estado final visible (opacity 1) sin depender de
   que el JS alcance a añadir .on antes del primer paint; .atras se respeta
   porque sigue siendo un estado final legítimo, no una animación */
@media(prefers-reduced-motion:reduce){
  .cuerpo-marcador,
  .cm-caja,
  .ci-signo::before,
  .ci-signo::after,
  .cuerpo-item,
  .cuerpo-item::details-content{
    transition:none!important;
    animation:none!important;
  }
  .cuerpo-marcador.on{transform:translate(calc(-1 * var(--cm-size) / 2),-50%) scale(1)}
  .cuerpo-stage.cm-izq .cuerpo-marcador.on{transform:translate(calc(-100% + var(--cm-size) / 2),-50%) scale(1)}
  .cuerpo-marcador.atras{opacity:.28}
}

/* ============ fin motor.css · inicio componente.css (layout) ============ */

/* ============================================================================
   componente.css — layout de las DOS ubicaciones reales del componente
   «cuerpo de puntos» Spark (v2, 19-ago-2026). SOLO grid/posición/tamaños de
   esta ubicación: el componente en sí (marcador, acordeón, fallback,
   degradación) vive en motor.css y no se redeclara aquí.

   Namespace: SOLO ".cuerpo-bascula-fb" (sección #bascula de fatburner.html) y
   ".cuerpo-origen-px" (sección #origen de pelvix.html) y selectores calificados
   por uno de esos dos ancestros. El hero de cada landing NO se toca (decisión
   de Arturo, 19-ago): el cuerpo va en una sección posterior con poca animación. Cero !important: donde hay que ganarle a una
   regla del sistema se usa mayor especificidad (selector con ancestro).

   Orden de carga: ÚLTIMA hoja del <head> (después de la hoja propia de cada
   página y de _header-spark.css).
   ========================================================================= */


/* ============================================================================
   BLOQUE C · sección #origen de pelvix.html — .cuerpo-origen-px
   Reemplaza a la <figure class="origen-figura"> + el bloque .aristas: el
   .origen-head original (grid 1.05fr/.95fr desde 860px, ya en pelvix.html)
   queda como está; adentro, la columna de texto lleva el titular + el
   acordeón de las 3 aristas, y la segunda columna el escenario.
   ============================================================================ */
.cuerpo-origen-px .origen-texto{max-width:none;display:flex;flex-direction:column;gap:clamp(1.5rem,3vw,2.25rem)}
.cuerpo-origen-px .origen-texto > .rv{max-width:62ch}
.cuerpo-origen-px .cuerpo-panel{max-width:560px}
/* pelvix.html tiene ".origen-head p{margin-top:1rem}": dentro del acordeón no
   aplica ese margen de párrafo de intro */
.cuerpo-origen-px .cuerpo-item p{margin-top:0}
.cuerpo-origen-px .cuerpo-item p + p{margin-top:.6rem}
/* la ficha "Lo medimos con" que traían las aristas (mismo estilo que .arista .mide) */
.cuerpo-origen-px .ci-mide{margin-top:.9rem;font-size:.9rem;color:var(--tinta)}
.cuerpo-origen-px .ci-mide b{display:block;font-weight:400;color:var(--carmin);font-family:var(--dato);font-size:.78rem;letter-spacing:.08em;margin-bottom:.25rem}
/* summary en dos niveles (eyebrow de la arista + título), como el h3 original */
.cuerpo-origen-px .cuerpo-item > summary > span:first-child{display:flex;flex-direction:column;gap:.2rem}
.cuerpo-origen-px .cuerpo-item > summary small{font-family:var(--dato);font-size:12px;letter-spacing:.13em;text-transform:uppercase;color:var(--carmin);font-weight:400}

/* escenario: el fondo es el de la sección (--tinte, "quieto"), sin marco */
.cuerpo-origen-px .cuerpo-stage{
  --cuerpo-fondo:var(--tinte);
  --cuerpo-alto:clamp(420px,110vw,540px);
  height:var(--cuerpo-alto);
  width:100%;
  max-width:440px;
  margin-inline:auto;
}
@media(min-width:861px){
  /* el escenario acompaña al acordeón: arranca un poco más abajo que el
     titular (a la altura del texto de intro) y se queda pegado bajo el header
     mientras se recorren las aristas — al abrir una caja, el cuerpo que
     reacciona está siempre a la vista (pedido de Arturo, 19-ago). El grid
     padre (.origen-head) centra verticalmente; aquí se alinea arriba para
     que el sticky tenga recorrido. Alto acotado a la ventana para que quepa
     entero bajo el header. */
  .origen-head.cuerpo-origen-px{align-items:start}
  .cuerpo-origen-px .cuerpo-stage{
    --cuerpo-alto:clamp(460px,calc(100svh - var(--header-h,104px) - 3rem),620px);
    max-width:none;
    align-self:start;
    position:sticky;
    top:calc(var(--header-h,104px) + 1.25rem);
    margin-top:clamp(2rem,9vh,5.5rem);
  }
}
@media(max-width:860px){
  /* apilado: texto, escenario, acordeón (el grid padre ya es 1 columna) */
  .cuerpo-origen-px .origen-texto{display:contents}
  .cuerpo-origen-px .origen-texto > .rv{order:1}
  .cuerpo-origen-px .cuerpo-stage{order:2;margin-top:.5rem}
  .cuerpo-origen-px .cuerpo-panel{order:3}
}


/* ============================================================================
   BLOQUE D · sección #bascula de fatburner.html — .cuerpo-bascula-fb
   «La báscula miente. El InBody lo mide.» Va entre el titular y la comparación
   báscula/InBody ya existente (.balanza): el cuerpo a la izquierda, el
   acordeón de lo que el InBody separa a la derecha. Sección oscura: el fondo
   del escenario es el de la sección y los puntos apagados van en el neutro
   claro del tema oscuro; el carmín queda para lo encendido (un solo acento).
   ============================================================================ */
.cuerpo-bascula-fb{
  width:100%;
  max-width:1080px;
  margin-inline:auto;
  display:grid;
  grid-template-columns:minmax(0,1fr);
  grid-template-areas:"escena" "panel";
  row-gap:clamp(1.5rem,4vw,2.5rem);
  text-align:left;
}
.cuerpo-bascula-fb .cuerpo-stage{grid-area:escena}
.cuerpo-bascula-fb .cuerpo-panel{grid-area:panel;max-width:none}
@media(min-width:900px){
  .cuerpo-bascula-fb{
    grid-template-columns:minmax(300px,.9fr) minmax(320px,1.1fr);
    grid-template-areas:"escena panel";
    column-gap:clamp(2rem,5vw,4.5rem);
    align-items:center;
  }
  .cuerpo-bascula-fb .cuerpo-panel{max-width:520px}
}
.cuerpo-bascula-fb .cuerpo-stage{
  --cuerpo-fondo:var(--oscuro-fondo);
  --cuerpo-puntos:var(--oscuro-suave);
  --cuerpo-alto:clamp(420px,120vw,560px);
  height:var(--cuerpo-alto);
  width:100%;
  max-width:440px;
  margin-inline:auto;
}
@media(min-width:900px){
  .cuerpo-bascula-fb .cuerpo-stage{
    --cuerpo-alto:clamp(480px,44vw,600px);
    max-width:none;
    margin-inline:0;
  }
}
/* tokens del componente en tema oscuro: tarjetas sobre el fondo oscuro, texto
   del tema, línea tenue. Mismo acordeón, otro fondo. */
.cuerpo-bascula-fb .cb-lead{font-family:var(--dato);font-size:13px;font-weight:500;letter-spacing:.07em;text-transform:uppercase;color:var(--oscuro-suave);margin:0 0 .2rem}
.cuerpo-bascula-fb .cuerpo-item{background:rgba(255,250,244,.05);border-color:rgba(242,237,232,.14)}
.cuerpo-bascula-fb .cuerpo-item[open]{background:rgba(255,250,244,.07);box-shadow:none}
.cuerpo-bascula-fb .cuerpo-item > summary{color:var(--oscuro-tinta)}
.cuerpo-bascula-fb .cuerpo-item .ci-cuerpo{color:var(--oscuro-suave)}
.cuerpo-bascula-fb .cuerpo-item .ci-link{color:#f2d4db}
.cuerpo-bascula-fb .cuerpo-item .ci-media{background:rgba(255,250,244,.06)}
.cuerpo-bascula-fb .cuerpo-marcador.activo .cm-caja i{background:var(--oscuro-fondo)}
/* la .balanza de abajo se mantiene centrada como estaba; este bloque no la toca */
