/* ═══════════════════════════════════════════════════════════════════════════
   VIDA · BOTÓN  ·  .c-boton  ·  las 5 épocas
   Contrato: design-system/07-contrato-vida-y-armazon.md §0 (doctrina MATERIA)
             + §A (reglas de la capa de vida)
   Fuente:   rebranding-academia-2026-08/MATERIA-animaciones.html
             (01 brasa que respira · 07 chispa de yunque · 15 lacre)

   Se carga DESPUÉS de base.css y de las cinco hojas de época. No añade
   marcado, no añade JS, no carga nada. Solo toca `.c-boton`.

   ── LA LEY DEL CALOR (doctrina §3) ────────────────────────────────────────
   Nada hace hover: se CALIENTA. Entra a `--e-vel`, sale a `--e-vel * 3.5`.
   Las cinco pieles congeladas transicionan simétrico; esta capa parte la
   simetría en las cinco. Es el cambio que más se nota y el que menos se ve.

   ── UNA IDEA POR ÉPOCA (doctrina §5) ──────────────────────────────────────
   1 · CUEVA   el rescoldo se aviva dentro y se apaga despacio
   2 · PIEDRA  la antorcha se ACERCA (y el bloque solo se asienta)
   3 · PAPEL   el sello ESTAMPA: aplastamiento seco + tinta que muerde
   4 · HIERRO  chispa de yunque: golpe, chispas que se enfrían al volar
   5 · CABINA  la luz SUBE seca (130 ms) y CAE lenta (455 ms)

   ── PSEUDOS: lo que ya usa cada piel, y lo que queda libre ────────────────
   é1 `::after` = salpicaduras de pigmento  → aquí se usa `::before` (libre)
   é2 ninguno                               → aquí se usa `::before`
   é3 `--brasa::before` = la tinta del sello · `--fantasma::after` = el filete
      → NO cabe un tercer pseudo: la estampa se hace con transform + filter
   é4 ninguno                               → aquí se usa `::after` (las chispas)
   é5 ninguno                               → aquí se usa `::before` (la luz)

   ── CONTRASTE ─────────────────────────────────────────────────────────────
   Toda capa de luz que cae DEBAJO del texto (`::before`, z-index:-1) va sobre
   la variante de tinta oscura (brasa) sin tope, y capada en la de tinta clara
   (fantasma). Las capas que van ENCIMA del texto (`::after`, z-index:1) solo
   se usan en é4 y viven en la banda inferior, fuera del renglón.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════════════════════════════
   1 · CUEVA — EL RESCOLDO SE AVIVA
   El botón no cambia de color: tiene un carbón dentro. Al calentarlo el núcleo
   sube y crece desde el suelo de la pieza; al soltarlo se apaga en 2,5 s, que
   es lo que tarda una brasa de verdad. La piel ya hace respirar la brasa en
   hover (`e1c-respira`): eso no se toca ni se duplica.
   ═══════════════════════════════════════════════════════════════════════════ */

/* la ley del calor: se enfría a 2520 ms */
html[data-epoca="1"] .c-boton{
  transition:
    background-color calc(var(--e-vel) * 3.5) var(--e-curva),
    border-color     calc(var(--e-vel) * 3.5) var(--e-curva),
    box-shadow       calc(var(--e-vel) * 3.5) var(--e-curva),
    color            calc(var(--e-vel) * 3.5) var(--e-curva),
    transform        calc(var(--e-vel) * 1.4) var(--e-curva),
    filter           calc(var(--e-vel) * 3.5) var(--e-curva);
}
/* …y se calienta a 720 ms */
html[data-epoca="1"] .c-boton:hover,
html[data-epoca="1"] .c-boton:focus-visible{
  transition-duration: var(--e-vel);
}
/* pulsar es lo único inmediato de la cueva: la mano aprieta, el pigmento no */
html[data-epoca="1"] .c-boton:active:not(:disabled):not([aria-disabled="true"]){
  transition-duration:
    var(--e-vel), var(--e-vel), var(--e-vel), var(--e-vel),
    calc(var(--e-vel) * .34), var(--e-vel);
}

/* EL CARBÓN. Vive en el `::before` (materia, z-index:-1): queda encima del
   pigmento del botón y DEBAJO de la letra, que es donde está un rescoldo.
   `inset` negativo para que la luz pase por debajo del trazo de 3px. */
html[data-epoca="1"] .c-boton::before{
  content: "";
  inset: calc(var(--e-grosor) * -1);
  background:
    radial-gradient(66% 104% at 50% 104%,
      rgba(255, 240, 214, .98)  0%,
      rgba(255, 186, 110, .78) 26%,
      rgba(255, 122,  40, .40) 52%,
      rgba(255, 106,  31,   0) 78%);
  opacity: 0;
  transform: scale(.78);
  transform-origin: 50% 100%;
  transition:
    opacity   calc(var(--e-vel) * 3.5) var(--e-curva),
    transform calc(var(--e-vel) * 3.5) var(--e-curva);
}

/* la brasa: el núcleo entero. Tinta #170902 sobre naranja → aclarar el fondo
   solo puede SUBIR el contraste (peor píxel medido: 5,07:1 en reposo → 5,35:1
   encendido; el pulsado sube a 5,52:1). */
html[data-epoca="1"] .c-boton--brasa:hover:not(:disabled):not([aria-disabled="true"])::before,
html[data-epoca="1"] .c-boton--brasa:focus-visible:not([aria-disabled="true"])::before{
  opacity: .88;
  transform: scale(1);
  transition-duration: var(--e-vel);
}

/* el fantasma no es una brasa untada: es un hueco con un carbón dentro. Mismo
   fenómeno, carbón PEQUEÑO — y por una razón medida, no estética: aquí la tinta
   es cal clara (#F2E3D2) y una luz que subiera hasta el renglón le comería el
   contraste. El rescoldo se queda en los 10px del suelo, donde no hay letra. */
html[data-epoca="1"] .c-boton--fantasma::before{
  background:
    radial-gradient(46% 38% at 50% 108%,
      rgba(255, 226, 182, .92)  0%,
      rgba(255, 150,  66, .52) 38%,
      rgba(255, 106,  31,   0) 74%);
}
html[data-epoca="1"] .c-boton--fantasma:hover:not(:disabled):not([aria-disabled="true"])::before,
html[data-epoca="1"] .c-boton--fantasma:focus-visible:not([aria-disabled="true"])::before{
  opacity: .92;
  transform: scale(1);
  transition-duration: var(--e-vel);
}

/* al pulsar el carbón se aplasta contra el suelo y suelta un golpe de luz */
html[data-epoca="1"] .c-boton:active:not(:disabled):not([aria-disabled="true"])::before{
  transform: scale(1.04);
  transition-duration: calc(var(--e-vel) * .34);
}

/* el pigmento seco no tiene carbón dentro */
html[data-epoca="1"] .c-boton:disabled::before,
html[data-epoca="1"] .c-boton[aria-disabled="true"]::before{ opacity: 0; }


/* ═══════════════════════════════════════════════════════════════════════════
   2 · PIEDRA — LA ANTORCHA SE ACERCA
   La piedra no reacciona: la que se mueve es la luz. En reposo la antorcha
   está lejos y a la izquierda; al calentarse se planta encima del bloque y lo
   baña. Al soltar, se aleja durante 1,96 s. El bloque solo hace una cosa:
   asentarse — y eso ya lo hace la piel. Aquí solo se le pone tiempo.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-epoca="2"] .c-boton{
  transition:
    background-color calc(var(--e-vel) * 3.5) var(--e2-curva),
    border-color     calc(var(--e-vel) * 3.5) var(--e2-curva),
    box-shadow       calc(var(--e-vel) * 3.5) var(--e2-curva),
    color            calc(var(--e-vel) * 3.5) var(--e2-curva),
    /* el sillar vuelve a su sitio despacio, pero no rebota: es piedra */
    transform        var(--e-vel) var(--e2-curva);
}
html[data-epoca="2"] .c-boton:hover,
html[data-epoca="2"] .c-boton:focus-visible{
  transition-duration: var(--e-vel), var(--e-vel), var(--e-vel), var(--e-vel), var(--e-vel);
}
/* asentarse es lo único inmediato de esta época: el bloque cae, no baja */
html[data-epoca="2"] .c-boton:active:not(:disabled):not([aria-disabled="true"]){
  transition-duration: 90ms, 90ms, 90ms, 90ms, 90ms;
}

/* Registradas para que INTERPOLEN: la antorcha viaja por dentro del propio
   `radial-gradient` (`at var(--e2-antorcha-x) var(--e2-antorcha-y)`), nunca
   moviendo la CAJA del pseudo con `transform`. Mismo mecanismo que `--vp-dx`
   en vida-panel.css § 0 — una variable registrada movida en vez de la caja. */
@property --e2-antorcha-x { syntax: "<percentage>"; inherits: false; initial-value: 13%; }
@property --e2-antorcha-y { syntax: "<percentage>"; inherits: false; initial-value: -7%; }

/* LA ANTORCHA. `::before` = materia, debajo de la letra. El foco de luz cae
   fuera de la caja (arriba a la izquierda): dentro solo entra el derrame.

   BUGFIX 2026-08-12 — un `.c-boton--bloque` pegado al margen derecho en é2
   empujaba `document.scrollWidth` (390→427 medido a 390px de viewport). Causa:
   el reposo movía la CAJA entera con `transform: translate3d(16%, -9%, 0)`.
   Invisible (`opacity:0`), pero una caja transformada cuenta para el scroll
   aunque no se vea — y con `.c-boton` sin overflow propio, ese `matrix(1,0,0,1,
   56.16,-2.82)` se colaba en el scroll del documento. Arreglo: la caja del
   pseudo se queda SIEMPRE quieta en `inset: calc(var(--e-grosor) * -1)`; lo
   que viaja es el punto `at X Y` del gradiente. Álgebra que demuestra que el
   barrido se ve IGUAL: mover la caja +16%/-9% con el foco fijo en 13%/-7%
   desplaza el foco, en píxeles absolutos, tanto como fijar la caja y mover el
   foco a (13+16)%=29%, (-7-9)%=-16% — la interpolación es lineal, así que el
   offset constante (13%,-7%) se cancela en cada fotograma y la trayectoria es
   idéntica; solo cambia QUIÉN se mueve, la caja o el punto dentro de ella. */
html[data-epoca="2"] .c-boton::before{
  content: "";
  inset: calc(var(--e-grosor) * -1);
  background:
    radial-gradient(94% 122% at var(--e2-antorcha-x) var(--e2-antorcha-y),
      rgba(255, 236, 206, .62) 0%,
      rgba(255, 190, 128, .30) 30%,
      rgba(255, 150,  74, .09) 56%,
      rgba(255, 138,  61,   0) 80%);
  opacity: 0;
  --e2-antorcha-x: 29%;    /* 13% + 16%: aún está lejos y a un lado */
  --e2-antorcha-y: -16%;   /* -7% + -9% */
  transition:
    opacity         calc(var(--e-vel) * 3.5) var(--e2-curva),
    --e2-antorcha-x calc(var(--e-vel) * 3.5) var(--e2-curva),
    --e2-antorcha-y calc(var(--e-vel) * 3.5) var(--e2-curva);
}
html[data-epoca="2"] .c-boton:hover:not(:disabled):not([aria-disabled="true"])::before,
html[data-epoca="2"] .c-boton:focus-visible:not([aria-disabled="true"])::before{
  opacity: 1;
  --e2-antorcha-x: 13%;    /* ya está encima */
  --e2-antorcha-y: -7%;
  transition-duration: var(--e-vel);
}
/* sobre el bronce la letra es #14100A: la antorcha solo puede subir el
   contraste. Sobre piedra viva la tinta es clara → el derrame se capa. */
html[data-epoca="2"] .c-boton--fantasma:hover:not(:disabled):not([aria-disabled="true"])::before,
html[data-epoca="2"] .c-boton--fantasma:focus-visible:not([aria-disabled="true"])::before{
  opacity: .62;
}
html[data-epoca="2"] .c-boton:disabled::before,
html[data-epoca="2"] .c-boton[aria-disabled="true"]::before{ opacity: 0; }


/* ═══════════════════════════════════════════════════════════════════════════
   3 · PAPEL — EL SELLO ESTAMPA
   «Cae, se aplasta, se estampa y se enfría. Lo lento es secarse» (demo 15).
   Al pulsar, el sello se aplasta contra la hoja desde su canto de apoyo —seco,
   70 ms, sin curva— y la tinta MUERDE: un cerco que sigue la silueta mordida
   (`drop-shadow`, no un rectángulo) y que tarda 1,4 s en secarse.
   La piel ya ocupa los dos pseudos del botón en esta época (la tinta del sello
   en `::before`, el filete del fantasma en `::after`): la estampa se hace
   entera con `transform` + `filter`, sin pedir un tercer pseudo.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-epoca="3"] .c-boton--brasa{
  transform-origin: 50% 100%;           /* el canto que toca el papel */
  transition:
    transform var(--e-vel) cubic-bezier(.2, .72, .28, 1),
    filter    calc(var(--e-vel) * 3.5) linear,   /* la tinta se seca despacio */
    color     var(--e-vel) linear;
}
/* calentarse (la prensa que se acerca) sigue siendo rápido: 400 ms */
html[data-epoca="3"] .c-boton--brasa:hover:not(:disabled):not([aria-disabled="true"]),
html[data-epoca="3"] .c-boton--brasa:focus-visible:not([aria-disabled="true"]){
  transition-duration: var(--e-vel), var(--e-vel), var(--e-vel);
}
/* LA ESTAMPA. Va envuelta en `no-preference` a propósito: con la preferencia de
   movimiento reducido activa esta regla NO EXISTE, y el pulsado del sello vuelve
   a ser exactamente el de la piel congelada (verificado píxel a píxel). */
@media (prefers-reduced-motion: no-preference){
  html[data-epoca="3"] .c-boton--brasa:active:not(:disabled):not([aria-disabled="true"]){
    /* aplastamiento: se hunde 1px y se ensancha lo que pierde de alto */
    transform: translateY(1px) scale(1.022, .952);
    /* la tinta muerde: cerco de rúbrica pegado a la silueta + el que se corre */
    filter:
      drop-shadow(0 0 0 rgba(26, 23, 20, .30))
      drop-shadow(0 0 1.5px rgba(168, 50, 30, .78))
      drop-shadow(0 0 5px   rgba(168, 50, 30, .34));
    transition-duration: 70ms, 70ms, 70ms;
  }
}

/* el fantasma no es un sello: es una palabra. Solo se apoya en la hoja —y se
   levanta despacio, que es lo que hace el papel. */
html[data-epoca="3"] .c-boton--fantasma{
  transition:
    transform   calc(var(--e-vel) * 1.6) cubic-bezier(.2, .72, .28, 1),
    color       calc(var(--e-vel) * 3.5) linear,
    box-shadow  calc(var(--e-vel) * 3.5) linear;
}
html[data-epoca="3"] .c-boton--fantasma:hover:not(:disabled):not([aria-disabled="true"]),
html[data-epoca="3"] .c-boton--fantasma:focus-visible:not([aria-disabled="true"]){
  transition-duration: var(--e-vel), var(--e-vel), var(--e-vel);
}
html[data-epoca="3"] .c-boton--fantasma:active:not(:disabled):not([aria-disabled="true"]){
  transition-duration: 70ms, 70ms, 70ms;
}


/* ═══════════════════════════════════════════════════════════════════════════
   4 · HIERRO — CHISPA DE YUNQUE
   «El botón no se pulsa: recibe un golpe» (demo 07). Squash rápido desde el
   canto de apoyo, rebote amortiguado, y chispas que nacen ceñidas al filo
   inferior y se ENFRÍAN AL VOLAR: al soltar se abren, se desenfocan y se
   apagan en 840 ms. Sin canvas y sin JS: el reposo del pseudo ES el final del
   vuelo, así que la transición de vuelta hace de física.
   El filamento (`--e4-on`) ya lo enciende la piel con sus dos destellos: aquí
   solo se le quita la simetría, para que se apague como una bombilla.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-epoca="4"] .c-boton{
  transition:
    --e4-on      calc(var(--e-vel) * 3.5) linear,   /* el filamento se enfría */
    color        calc(var(--e-vel) * 3.5) ease,
    border-color calc(var(--e-vel) * 3.5) ease,
    box-shadow   calc(var(--e-vel) * 3.5) ease,
    transform    calc(var(--e-vel) * 1.4) cubic-bezier(.18, 1.62, .42, 1);
}
html[data-epoca="4"] .c-boton:hover,
html[data-epoca="4"] .c-boton:focus-visible{
  transition-duration: var(--e-vel), var(--e-vel), var(--e-vel), var(--e-vel), calc(var(--e-vel) * 1.4);
}

/* EL GOLPE: el squash sale del canto de apoyo, no del centro (mismo criterio de
   `no-preference` que el sello de é3: sin movimiento, la regla no existe). */
@media (prefers-reduced-motion: no-preference){
  html[data-epoca="4"] .c-boton:active:not(:disabled):not([aria-disabled="true"]){
    transform-origin: 50% 100%;
    transform: translateY(1px) scale(1.030, .944);
    transition-duration: var(--e-vel), var(--e-vel), var(--e-vel), var(--e-vel), 60ms;
  }
}

/* LAS CHISPAS. `::after` = luz (z-index:1). El grupo se ancla al filo de abajo
   —donde pega el martillo— y ninguna sube más de 13px: se quedan por debajo
   del renglón, así que no tapan la etiqueta. Las que vuelan lejos salen de la
   caja, y un `box-shadow` nunca empuja el layout. */
html[data-epoca="4"] .c-boton::after{
  content: "";
  inset: auto;
  left: 50%;
  bottom: -2px;
  width: 2px;
  height: 2px;
  margin: 0 0 -1px -1px;
  border-radius: 50%;
  background: none;
  opacity: 0;                 /* reposo = el vuelo ya terminó */
  /* se abren MUCHO a lo ancho y poco a lo alto: una chispa de yunque patina por
     la cara del hierro, no sube en vertical — y así ninguna cruza el renglón */
  transform: scale(2.9, 1.35);
  filter: blur(2px);          /* …y se enfriaron */
  box-shadow:
    -103px  10px 0 -.8px #C25A18,
     -84px   1px 0 -.4px #FF6A1F,
     -63px  11px 0  .1px #FFA24A,
     -46px  -1px 0 -.5px #FFE0A8,
     -30px   9px 0  .3px #FFE0A8,
     -16px  -3px 0 -.6px #FFA24A,
      -3px  12px 0 -.2px #FFE0A8,
      12px  -2px 0  .2px #FF6A1F,
      27px  10px 0 -.5px #FFE0A8,
      43px  -3px 0  .1px #FFA24A,
      62px   8px 0 -.3px #FFE0A8,
      84px  -1px 0 -.6px #FF6A1F,
     104px   9px 0 -.8px #C25A18,
    /* el fogonazo del golpe, hundido bajo el filo. Medido: un fogonazo
       centrado subía al renglón y dejaba la etiqueta del primario en 3,53:1;
       y una chispa que asome 10px por encima del filo, en 2,22:1 en pleno
       vuelo. Por eso TODO el enjambre vive por debajo de la línea de contacto:
       ahí es donde pega el martillo, y ahí no hay letra. */
       0px  10px 12px 0 rgba(255, 196, 122, .30);
  transition:
    opacity   calc(var(--e-vel) * 3.5) linear,
    transform calc(var(--e-vel) * 3.5) cubic-bezier(.08, .82, .3, 1),
    filter    calc(var(--e-vel) * 3.5) linear;
}
/* el instante del golpe: ceñidas, nítidas y a plena luz, en 40 ms */
html[data-epoca="4"] .c-boton:active:not(:disabled):not([aria-disabled="true"])::after{
  opacity: 1;
  transform: scale(1);
  filter: blur(0);
  transition-duration: 40ms;
}
html[data-epoca="4"] .c-boton:disabled::after,
html[data-epoca="4"] .c-boton[aria-disabled="true"]::after{
  opacity: 0;                 /* el hierro frío no chispea */
  transition: none;
}


/* ═══════════════════════════════════════════════════════════════════════════
   5 · CABINA — LA LUZ SUBE SECA Y CAE LENTA
   Aquí no hay materia: hay nivel de luz. Sube por dentro de la pieza en 130 ms
   —seco, sin curva blanda— y tarda 455 ms en bajar. Nada más se mueve.
   El nivel es un `scaleY` desde el suelo: se recorta solo, sin `overflow`.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-epoca="5"] .c-boton{
  transition:
    transform        calc(var(--e-vel) * 3.5) var(--e5-curva),
    box-shadow       calc(var(--e-vel) * 3.5) linear,
    border-color     calc(var(--e-vel) * 3.5) linear,
    background-color calc(var(--e-vel) * 3.5) linear,
    filter           calc(var(--e-vel) * 3.5) linear,
    color            calc(var(--e-vel) * 3.5) linear;
}
html[data-epoca="5"] .c-boton:hover,
html[data-epoca="5"] .c-boton:focus-visible,
html[data-epoca="5"] .c-boton:active{
  transition-duration: var(--e-vel);
}

/* EL NIVEL. `::before` = materia: la luz se queda debajo del dato, nunca
   encima. El borde superior del degradado es la superficie del nivel. */
html[data-epoca="5"] .c-boton::before{
  content: "";
  inset: 0;
  background: linear-gradient(to top,
    rgba(255, 255, 255, .020)  0%,
    rgba(255, 255, 255, .055) 58%,
    rgba(255, 255, 255, .120) 93%,
    rgba(255, 255, 255, .030) 100%);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform calc(var(--e-vel) * 3.5) var(--e5-curva);
}
html[data-epoca="5"] .c-boton:hover:not(:disabled):not([aria-disabled="true"])::before,
html[data-epoca="5"] .c-boton:focus-visible:not([aria-disabled="true"])::before{
  transform: scaleY(1);
  transition-duration: var(--e-vel);
}
/* pulsar es confirmar: el nivel se queda arriba y no parpadea */
html[data-epoca="5"] .c-boton:active:not(:disabled):not([aria-disabled="true"])::before{
  transform: scaleY(1);
}
html[data-epoca="5"] .c-boton:disabled::before,
html[data-epoca="5"] .c-boton[aria-disabled="true"]::before{
  transform: scaleY(0);       /* lo que no informa, no se enciende */
  transition: none;
}


/* ═══════════════════════════════════════════════════════════════════════════
   MOVIMIENTO REDUCIDO — la capa de vida se retira entera.
   base.css §12 ya deja las transiciones en .001ms y anula los `transform` de
   hover/active del botón. Aquí se remata: las capas nuevas no existen, así que
   no hay ni un destello. Ningún estado pierde información: lo que decían era
   «esto responde», y el foco y el color de la piel siguen diciéndolo.
   Los dos aplastamientos (é3 y é4) no se deshacen desde aquí sino que viven
   dentro de `no-preference`: deshacerlos con `transform:none; filter:none`
   TAMPOCO devolvía la piel original (le comía su propio `drop-shadow`).
   VERIFICADO: con la preferencia activa, las cinco épocas renderizan
   BYTE A BYTE igual que con la piel congelada sola.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce){
  html[data-epoca="1"] .c-boton::before,
  html[data-epoca="2"] .c-boton::before,
  html[data-epoca="4"] .c-boton::after,
  html[data-epoca="5"] .c-boton::before{
    content: none;
  }
  html[data-epoca="1"] .c-boton,
  html[data-epoca="2"] .c-boton,
  html[data-epoca="3"] .c-boton--brasa,
  html[data-epoca="3"] .c-boton--fantasma,
  html[data-epoca="4"] .c-boton,
  html[data-epoca="5"] .c-boton{
    transition: none;
  }
}
