/* public/styles.css — ComandAI, por Induxion. Paleta A · Brasa, en base oscura. */
@font-face{font-family:"Satoshi";src:url(fonts/Satoshi-Variable.woff2) format("woff2");font-weight:300 900;font-display:swap}
@font-face{font-family:"JetBrains Mono";src:url(fonts/JetBrainsMono-Variable.woff2) format("woff2");font-weight:100 800;font-display:swap}
@font-face{font-family:"Satoshi Fallback";src:local("Arial");size-adjust:104%;ascent-override:95%;descent-override:22%;line-gap-override:0%}
/* El ticket ya no es hueso: es papel carbón con tinta hueso, sobre un mostrador más oscuro
   todavía. El acento es BRASA y va solo en el 5% que manda el manual. Ascua es SUPERFICIE (la
   pantalla de la app), no acento: es brasa llevada casi al negro, así que puede ocupar más sin
   que el naranja pase del 5% — un aura naranja de verdad "parece promoción de comida rápida".
   Contrastes medidos sobre --papel #1A1A1A: hueso 15.6:1 · tinta #d9d9d9 12.3:1 ·
   medio #9a9a9a 6.2:1 · brasa 4.7:1; carbón sobre brasa 5.0:1 (por eso la tinta de los botones
   es carbón y no blanco: blanco da 3.7:1). Migrado de Paleta B (jade) el 2026-08-26: el manual
   §09 recomienda A y todos los assets de marca ya estaban en brasa. */
:root{
  --fondo:#0E0E0E;--carbon:#131313;--blanco:#FFFFFF;--hueso:#F5F2ED;--papel:#1A1A1A;
  --acento:#E4572E;--ascua:#3A1810;--maiz:#F2C14E;--comal:#FF7A5C;--servicio:#2FA37A;
  --tinta:#d9d9d9;--medio:#9a9a9a;--borde:#2E2E2E;
  /* Ascua #3A1810 es un panel, no un suelo. El suelo de los renglones-pantalla es su versión
     honda: sobre ella --medio da 6.3:1 y hueso 15.9:1 (mejor que el 5.0:1 del suelo que sustituye).
     Funcionales adaptados a base oscura: el manual los midió contra BLANCO, y ahí comal #A83208
     da 2.6:1 y servicio #1F7A5C da 3.3:1 — ilegibles. Se aclaran. Y la alerta se queda AMARILLA
     en vez del #FF9500 del manual: con brasa de acento, un aviso naranja no se distingue. */
  --ascua-honda:#2A1108;--borde-ascua:#4A2A1C;
  --sans:"Satoshi","Satoshi Fallback",system-ui,sans-serif;--mono:"JetBrains Mono",ui-monospace,Menlo,monospace;
  --ease:cubic-bezier(.2,.8,.2,1);--rebote:cubic-bezier(.34,1.56,.64,1);--t1:200ms;--t2:400ms;--t3:900ms;
  /* El ease-out fuerte del sistema de UI: respuestas al toque y lo que entra o sale de pantalla. */
  --ease-out:cubic-bezier(.23,1,.32,1);
  --papel-w:720px;--nav-h:56px;--carril-w:44px;
  --bg:var(--papel);--fg:var(--hueso);
}
/* Sin el destello gris del navegador en cada toque: el feedback es el :active de cada control (§7). */
*{box-sizing:border-box}html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;color-scheme:dark;-webkit-tap-highlight-color:transparent}
[hidden]{display:none!important}
/* Quietud es menos movimiento, no cero aviso: fuera los desplazamientos y las animaciones, pero
   el papelito, los chips y el tachado siguen avisando con un fundido de opacidad o color. Cada
   regla conserva su propia duración. */
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*::before,*::after{animation:none!important;transition-property:opacity,color,background-color,border-color!important}}
body{margin:0;background:var(--fondo);color:var(--fg);font:1.0625rem/1.55 var(--sans);font-feature-settings:"kern";}
/* El aura del mostrador: tres luces difusas sobre el carbón, fijas al viewport, para que el
   negro respire en vez de ser un vacío plano. Van en ASCUA, no en brasa, y no por presupuesto
   sino por definición: ascua es un fondo profundo (brasa casi al negro) y el brasa puro es el acento del
   5% — un campo de 70vw es superficie, no acento, aunque se vea verde. Nunca toca texto (el
   ticket es opaco y va encima), así que ningún contraste cambia. Pseudo del <body> con
   z-index:-1 para quedar detrás de todo, y `fixed` porque la luz es del cuarto, no de la
   página: al hacer scroll el ticket se mueve y el aura se queda. */
body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    /* El núcleo: ascua aclarado con blanco — sigue siendo superficie derivada de ascua, solo
       con más luz. Aclarar el token es lo que sube la intensidad sin tocar el acento. */
    radial-gradient(42vw 38vh at 14% 96%, color-mix(in srgb,var(--ascua) 62%,white), transparent 62%),
    radial-gradient(75vw 68vh at 18% 92%, var(--ascua), transparent 70%),
    radial-gradient(62vw 58vh at 94% 6%, color-mix(in srgb,var(--ascua) 88%,transparent), transparent 72%),
    radial-gradient(50vw 45vh at 96% 80%, color-mix(in srgb,var(--ascua) 55%,transparent), transparent 74%);}
h1,h2,h3{margin:0 0 .5em;line-height:1.05;letter-spacing:-.02em;text-wrap:balance}
/* break-word: una cadena sin espacios (quien pone su página como nombre del negocio, y eso se
   imprime en el resumen) parte en el canto en vez de cortarse ahí. No "anywhere": ese cambia el
   ancho mínimo de grids y flex. */
p{margin:0 0 1em;max-width:62ch;overflow-wrap:break-word}
a{color:inherit}
img{max-width:100%;height:auto;display:block}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
.eyebrow{font:600 .75rem/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--medio);margin-bottom:1rem}
/* A 96px el h1 llenaba el viewport de 800 y dejaba los CTAs bajo el pliegue. El titular parte
   en 5 líneas por encima de 68px y en 4 por debajo: a 4.25rem los CTAs entran en 1280×800
   (cta.bottom 705) y también en el 1366×768 de una laptop; a 4.75rem se salían por 24px. */
.h-display{font-weight:900;font-size:clamp(2.4rem,7vw,4.25rem)}
.h-titulo{font-weight:800;font-size:clamp(1.5rem,4vw,2.5rem)}
.skip{position:absolute;left:-999px;top:8px;background:var(--hueso);color:var(--carbon);padding:.5rem 1rem;border-radius:6px}.skip:focus{left:8px;z-index:99}
:focus-visible{outline:2px dashed currentColor;outline-offset:3px}

/* Nav */
/* -webkit- primero: Safari anterior a la 18 (iOS 17 y antes) solo entiende el prefijo. */
.nav{position:sticky;top:0;z-index:50;height:var(--nav-h);display:flex;align-items:center;gap:1rem;padding:0 1rem;background:color-mix(in srgb,var(--fondo) 88%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);color:#fff}
/* Con "reducir transparencia" la nav se vuelve sólida: sin velo ni desenfoque. */
@media(prefers-reduced-transparency:reduce){.nav{background:var(--fondo);-webkit-backdrop-filter:none;backdrop-filter:none}}
.nav__logo{display:flex;align-items:center;gap:.5rem;height:32px;color:#fff;text-decoration:none}
.nav__logo svg{height:32px;width:auto}
.nav__links{margin-left:auto;display:flex;gap:1.25rem;align-items:center;font-weight:600;font-size:.95rem}
/* La opacidad bajaba también el CTA: el acento al 85% contra el carbón de la nav daba 3.55:1. */
.nav__links a{text-decoration:none}.nav__links a:not(.btn){opacity:.85}.nav__links a:not(.btn):hover{opacity:1}
/* El CTA se comprimía a 141px en un iPhone SE: partía en dos líneas y se salía de la nav de 56. */
.nav__links .btn{flex:none;white-space:nowrap}
.nav__menu{display:none}
@media(max-width:720px){.nav__links a:not(.btn){display:none}.nav__menu{display:block}
  .nav__menu>summary{list-style:none;width:44px;height:44px;display:grid;place-content:center;cursor:pointer;border-radius:8px;font-size:1.25rem}
  .nav__menu>summary::-webkit-details-marker{display:none}
  .nav__menu[open]>nav{position:absolute;top:var(--nav-h);left:0;right:0;display:grid;gap:.75rem;padding:1rem;background:var(--fondo);border-top:1px solid var(--borde);font-weight:600;
    /* Cae de la barra que lo abrió. Keyframes y no @starting-style: el contenido de un <details>
       cerrado vive en content-visibility:hidden y la transición de entrada no es segura. La
       salida es instantánea a propósito, y la regla global de quietud apaga la entrada. */
    animation:menu-cae 180ms var(--ease-out)}
  .nav__menu>nav a{text-decoration:none}}
@keyframes menu-cae{from{opacity:0;transform:translateY(-4px)}}
/* Con el CTA ya sin encoger (flex:none), lo que sobra es ancho: se compacta la nav, no se esconde nada. */
@media(max-width:400px){.nav__links .btn{padding:.55rem .85rem;font-size:.9rem}}
@media(max-width:360px){.nav__logo svg{height:26px}.nav{gap:.5rem;padding:0 .75rem}}

/* Botones */
.btn{display:inline-flex;align-items:center;gap:.5rem;padding:.8rem 1.25rem;border-radius:999px;font-weight:700;text-decoration:none;border:2px solid transparent;transition:transform 160ms var(--ease-out),background var(--t1);cursor:pointer;font-family:inherit;font-size:1rem}
/* El press de los CTA va con el de chips, carril, ☰ y flotante (§7): 160 ms y --ease-out. */
.btn:active{transform:scale(.97)}
/* Blanco sobre brasa da 3.7:1 y .btn es 16px/700 (no cuenta como texto grande): la tinta va en carbón, 5.0:1. */
.btn--acento{background:var(--acento);color:var(--carbon)}
/* El anillo global usa currentColor (= hueso) y se dibuja FUERA del botón: sobre el mostrador
   desaparecía. Aquí va por dentro del relleno brasa, donde el carbón da 5:1 siempre. */
.btn--acento:focus-visible{outline:2px dashed var(--carbon);outline-offset:-5px}
.btn--fantasma{border-color:currentColor;background:transparent;color:inherit}

/* El mostrador y el papel */
.escena{display:grid;grid-template-columns:var(--carril-w) minmax(0,var(--papel-w));justify-content:center;gap:0 12px;padding:24px 8px 96px}
/* Sin carril no hay primera columna: el papel es el único hijo y se centra solo. */
.escena--solo{grid-template-columns:minmax(0,var(--papel-w))}
@media(max-width:600px){.escena{grid-template-columns:minmax(0,1fr);padding:44px 0 96px;gap:0}
  /* Los 44px de arriba son para el carril fijo; en las páginas que no lo tienen, sobran. */
  .escena--solo{padding-top:0}}
/* Sobre el mostrador oscuro una sombra negra no separa nada: el canto del ticket es un filete. */
.papel{background:var(--bg);color:var(--fg);position:relative;border-radius:2px 2px 12px 12px;
  box-shadow:0 0 0 1px #262626,0 30px 60px rgba(0,0,0,.6);overflow:clip}
/* El grano del papel, en oscuro, se SUMA (screen): en normal se lo come el fondo. */
.papel::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:.06;mix-blend-mode:screen;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>")}
@media(max-width:380px),(prefers-reduced-motion:reduce){.papel::before{display:none}}
.papel__perforado{display:block;width:100%;height:10px;color:var(--fondo)}
/* El nav es sticky: sin scroll-margin, ir a #rNN deja el folio y el eyebrow debajo de la barra. */
.renglon{--pad-x:clamp(1.25rem,5vw,3.5rem);padding:clamp(3rem,8vw,6rem) var(--pad-x);border-top:1px dashed var(--borde);contain:layout paint;
  scroll-margin-top:calc(var(--nav-h) + 16px);
  transition:background-color var(--t3) var(--ease),color var(--t3) var(--ease)}
.renglon:nth-child(n+6){content-visibility:auto;contain-intrinsic-size:auto 800px}
/* Pasada la costura la columna ya no es papel: es la pantalla, y su suelo es el ascua honda. */
.renglon[data-tramo="pantalla"]{--bg:var(--ascua-honda);--fg:#fff;--borde:var(--borde-ascua);background:var(--bg);color:var(--fg);border-top-color:var(--borde-ascua)}
/* Sobre el mostrador carbón la columna de papel se pierde: el canto se dibuja por dentro. */
@media(min-width:601px){.renglon[data-tramo="pantalla"]{box-shadow:inset 1px 0 #1C4238,inset -1px 0 #1C4238}}
/* Pasada la costura la columna es una pantalla, y una pantalla EMITE: cada renglón lleva su
   propia luz brasa difusa. El papel no la lleva —el papel no brilla—, y por eso el contraste
   entre los dos tramos se siente físico, no de paleta. La luz va bajo el texto (z-index:0 con
   el contenido en position:relative no hace falta: el pseudo va primero en pintado) y se
   mantiene por debajo del 55% de ascua, donde el blanco sigue dando 8:1 largos. */
.renglon[data-tramo="pantalla"]{position:relative;isolation:isolate}
.renglon[data-tramo="pantalla"]::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(45% 40% at 8% 104%, color-mix(in srgb,var(--ascua) 78%,white), transparent 60%),
    radial-gradient(85% 65% at 12% 100%, var(--ascua), transparent 70%),
    radial-gradient(75% 60% at 100% 0%, color-mix(in srgb,var(--ascua) 80%,transparent), transparent 72%);}
/* La costura hace la migración papel→pantalla una sola vez, y no con un degradado: arriba
   se queda el papel con la pregunta; abajo el teléfono SE ENCIENDE — bloque carbón a sangre,
   esquinas redondeadas arriba y su barra de estado como primer renglón. Filas auto/1fr: sin
   140vh no queda un campo hueso vacío entre los chips y el canto del teléfono. */
.renglon[data-tramo="costura"]{min-height:auto;display:grid;grid-template-rows:auto 1fr;background:var(--papel);color:var(--hueso);padding-bottom:0}
.renglon[data-tramo="costura"]>:first-child{padding-bottom:clamp(2rem,6vh,4rem)}
/* margin negativo = el padding lateral del renglón: el teléfono llega al canto de la columna. */
.costura__abajo{background:var(--ascua-honda);color:#fff;--borde:var(--borde-ascua);
  border-radius:36px 36px 0 0;margin:0 calc(-1 * var(--pad-x,0px));
  padding:clamp(2rem,6vh,4rem) clamp(1.25rem,5vw,3.5rem) clamp(3rem,8vw,6rem)}
/* Del otro lado de la costura ya no hay papel: la app se anuncia con su barra de estado. */
/* Envuelve en vez de desbordar: en un teléfono angosto la barra parte en dos renglones
   antes de dejar "SUCURSAL CENTR" cortado contra el canto del papel. */
.barra-app{display:flex;flex-wrap:wrap;gap:.25rem .75rem;justify-content:space-between;font:600 .7rem/1 var(--mono);color:var(--medio);letter-spacing:.06em;text-transform:uppercase;border-bottom:1px solid var(--borde);padding-bottom:.6rem;margin-bottom:1.5rem}
/* Bajo 360 px la sucursal sobra: la barra de estado dice la hora y que está sincronizada. */
@media(max-width:359px){.solo-ancho{display:none}}
/* El gris de papel no se lee en carbón: el eyebrow sigue al --medio re-anclado del tramo. */
.renglon[data-tramo="pantalla"] .eyebrow,.costura__abajo .eyebrow{color:var(--medio)}
.folio{display:flex;justify-content:space-between;gap:1rem;font:600 .75rem/1 var(--mono);letter-spacing:.06em;color:var(--medio);text-transform:uppercase;margin-bottom:2rem}

/* Carril de la comanda */
.carril{position:sticky;top:calc(var(--nav-h) + 16px);align-self:start;display:flex;flex-direction:column;gap:6px;padding:8px 0}
.carril a{display:flex;align-items:center;gap:6px;min-width:24px;min-height:24px;padding:5px 0;text-decoration:none;color:#fff;font:600 .625rem/1 var(--mono);opacity:.55;transition:opacity var(--t1),transform 160ms var(--ease-out)}
.carril .check{width:14px;height:14px;flex:none;border:1.5px solid currentColor;border-radius:2px;display:grid;place-content:center}
.carril a[data-listo] .check{background:currentColor}
.carril a[data-listo] .check::after{content:"";width:8px;height:4px;border:2px solid var(--fondo);border-top:0;border-right:0;transform:rotate(-45deg) translate(1px,-1px)}
.carril a[aria-current="true"]{opacity:1}
/* La palomita del renglón activo: carbón sobre brasa (5:1). En blanco daría 3.7:1. */
.carril a[aria-current="true"][data-listo] .check{background:var(--acento);border-color:var(--acento)}
.carril a[aria-current="true"][data-listo] .check::after{border-color:var(--carbon)}
/* Pasada la costura la columna ES la app y el carril, su barra lateral: los renglones se
   asientan como filas de sidebar. El JS marca el tramo en <html> desde data-tramo. */
@media(min-width:601px){html[data-tramo="pantalla"] .carril a{background:var(--papel);border-radius:6px;padding:5px 6px}}
/* En el celular el carril es una segunda barra fija bajo la nav. Va OPACO: con el velo al 88 % y
   sin desenfoque el texto de los renglones se veía pasar detrás de las casillas, y un segundo
   backdrop-filter fijo cuesta cuadros en los Android de gama media. */
@media(max-width:600px){.carril{position:fixed;top:var(--nav-h);left:0;right:0;z-index:40;flex-direction:row;justify-content:center;gap:2px;background:var(--fondo);padding:8px}
  .carril a{padding:5px;min-width:24px;min-height:24px}
  .carril a span:not(.check){display:none}.carril a[aria-current="true"] span:not(.check){display:inline}
  /* Aquí el carril también es fijo: la sección tiene que caer bajo las dos barras. */
  .renglon{scroll-margin-top:calc(var(--nav-h) + 56px)}}
/* 12 blancos de 24px + el número no caben en un teléfono angosto: se cierra la fila. */
@media(max-width:359px){.carril{gap:0;padding:8px 4px}}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* Comanda: renglones tipo orden */
.orden{list-style:none;padding:0;margin:0;font-family:var(--mono);font-size:.95rem}
.orden li{display:grid;grid-template-columns:auto 1fr auto;gap:.75rem;align-items:baseline;padding:.6rem 0;border-bottom:1px dotted var(--borde)}
.orden li::before{content:attr(data-n) "×";font-weight:700}
.orden .precio{font-weight:700;white-space:nowrap}
.orden--tachable button{all:unset;cursor:pointer;display:block;width:100%;font:inherit;color:inherit;text-decoration:inherit}
.orden--tachable button:focus-visible{outline:2px dashed currentColor;outline-offset:3px}
/* El tachado se DIBUJA (::after que crece); text-decoration solo queda para el papel impreso. */
.orden--tachable button{position:relative;transform-origin:0 50%;transition:transform 160ms var(--ease-out)}
/* scaleX y no width: es la única animación de layout que quedaba, y es respuesta a un toque, así
   que entra en el presupuesto de 300 ms con ease-out fuerte. La raya sigue dibujándose de
   izquierda a derecha, y una línea sólida de 2 px no se deforma al escalar. */
.orden--tachable button::after{content:"";position:absolute;left:0;right:0;top:.62em;height:2px;background:var(--tinta);
  transform:scaleX(0);transform-origin:0 50%;transition:transform 250ms var(--ease-out);pointer-events:none}
.tachado button::after{transform:scaleX(1)}
.tachado{opacity:.6}
.escrito{font-family:var(--mono);color:var(--tinta);border-bottom:1.5px solid var(--tinta);min-width:6ch;display:inline-block;padding:0 .25rem}
.chips{display:flex;flex-wrap:wrap;gap:.5rem;margin:1rem 0}
.chip{border:1.5px solid currentColor;background:transparent;color:inherit;border-radius:999px;padding:.5rem .9rem;font:600 .9rem var(--sans);cursor:pointer;min-height:44px;transition:transform 160ms var(--ease-out),background 150ms ease,color 150ms ease}
.chip[aria-pressed="true"]{background:var(--fg);color:var(--bg)}
/* El range default se pinta con el azul del navegador, fuera de paleta. */
input[type=range]{width:100%;accent-color:var(--medio);cursor:pointer;margin:.5rem 0}
/* FAQ de /precios: el <details> nativo no trae separación ni área de toque; se alinea con .orden. */
.renglon details{border-bottom:1px dotted var(--borde)}
.renglon summary{cursor:pointer;padding:.6rem 0;font-weight:600}
/* La respuesta se despliega en 200 ms en vez de aparecer de golpe y empujar lo de abajo. Los
   acordeones son la excepción aceptada a "no animar alto". Mejora progresiva: sin
   ::details-content o sin interpolate-size abre como siempre. interpolate-size se hereda, así
   que va en el details y no en :root, para no cambiar en silencio otras transiciones. */
.renglon details{interpolate-size:allow-keywords}
.renglon details::details-content{block-size:0;overflow:clip;opacity:0;
  transition:block-size 200ms var(--ease-out),opacity 200ms ease,content-visibility 200ms allow-discrete}
.renglon details[open]::details-content{block-size:auto;opacity:1}
/* La regla global de quietud no alcanza a ::details-content (no es ::before ni ::after), y
   meterlo en esa lista la invalidaría entera donde no se conoce: va aparte. Solo el fundido. */
@media(prefers-reduced-motion:reduce){.renglon details::details-content{transition-property:opacity}}
/* Formulario de /demo: los campos nativos no heredan tipografía ni caja del sistema. */
#form-demo{display:grid;gap:1rem;max-width:34rem;margin:1.5rem 0}
#form-demo label{display:block;font:600 .75rem/1.4 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--medio);margin-bottom:.4rem}
#form-demo input,#form-demo select{width:100%;min-height:44px;padding:.6rem .75rem;font:1rem var(--sans);color:var(--hueso);background:var(--papel);border:1px solid #3A3A3A;border-radius:8px}
/* El mensaje de error va pegado a su campo, no con el margen de párrafo suelto. */
#form-demo .nota{margin:.4rem 0 0}
/* El anillo de error no puede ser el acento (brasa = "listo") ni el comal, que sobre el ascua
   hondo da 4.1:1. El maíz llega a 7.7:1 ahí y no se confunde con ningún estado bueno. */
#form-demo input[aria-invalid="true"]{outline:2px solid var(--maiz)}

/* Tarjetas y dispositivos */
/* La tarjeta es una superficie levantada, no un papel blanco: sobre #1F1F1F, --medio da 5.9:1. */
.tarjeta{--borde:#333;background:#1F1F1F;color:var(--hueso);border:1px solid var(--borde);border-radius:12px;padding:1.25rem}
/* La pantalla de la app: ascua. Ahí --medio da 5.7:1 (el nixta daba 2.8:1 y no pasaba). */
.tarjeta--app{--medio:#C9D6D1;--tinta:#E8EEEC;--borde:#17715A;background:var(--ascua);color:#fff;border-color:#17715A}
.tarjeta--app .barra{display:flex;justify-content:space-between;font:600 .7rem var(--mono);color:var(--medio);margin-bottom:.75rem}
.grid3{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.telefono{width:min(280px,80vw);aspect-ratio:9/19.5;border-radius:36px;background:#000;padding:10px;box-shadow:0 20px 50px rgba(0,0,0,.5);margin:2rem auto}
.telefono img{width:100%;height:100%;object-fit:cover;border-radius:28px}
.tablet{border-radius:18px;background:#000;padding:10px;box-shadow:0 20px 50px rgba(0,0,0,.5)}
.tablet img{border-radius:10px}
/* En una fila de capturas de distinta proporción, estirar el marco deja el negro colgando. */
.grid3>figure.tablet{align-self:start;margin:0}
/* El estado oculto sólo existe si hay JS: el <head> hace document.documentElement.classList.add('js').
   :where() deja la especificidad en (0,1,0) para que .visto y reduced-motion sigan ganando. */
:where(html.js) .reveal{opacity:0;transform:translateY(12px);transition:opacity var(--t2) var(--ease),transform var(--t2) var(--ease);transition-delay:calc(var(--i,0)*70ms)}
.visto .reveal,.reveal.visto{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none}}
.numero{font:800 clamp(2.5rem,10vw,4rem)/1 var(--mono);letter-spacing:-.03em}
.nota{font-size:.8rem;color:var(--medio)}

/* WhatsApp flotante y pie */
.wa-flotante{position:fixed;right:16px;bottom:16px;z-index:45;width:48px;height:48px;border-radius:50%;background:var(--papel);color:#fff;display:grid;place-content:center;box-shadow:0 8px 24px rgba(0,0,0,.5);border:1px solid #333}
.pie{color:#bbb;font-size:.85rem;padding:2rem 1rem 3rem;text-align:center;display:grid;gap:.5rem}
.pie a{color:#ddd}
/* El chip presionado se pinta con --fg/--bg del papel: en el pie, sobre el mostrador, eso
   era carbón sobre carbón. El toggle de sonido encendido tiene que verse encendido. */
.pie .chip[aria-pressed="true"]{background:#fff;color:var(--carbon)}

/* ═══════════ Movimiento — la comanda se imprime, se sella, cuenta, cose y se corta ═══════════
   Regla de oro: ningún estado que ESCONDA algo vive en una regla base. Lo que esconde vive
   (a) dentro de un @keyframes con fill `backwards` — si el navegador no anima, o si
   prefers-reduced-motion apaga las animaciones, el elemento se queda en su estado natural —
   o (b) detrás de `html.js` + `.visto`, que solo existe si hay JS que lo quite.
   Se animan solo transform, opacity, clip-path y stroke-dashoffset. */

/* Índice de posición para el stagger, sin --i inline en cada nodo del HTML. */
.carril a:nth-child(2),.orden li:nth-child(2),.grid3>:nth-child(2),#r01>:nth-child(2),#r08 pre>:nth-child(2),.app__barras i:nth-child(2),.app__comanda li:nth-child(2){--i:1}
.carril a:nth-child(3),.orden li:nth-child(3),.grid3>:nth-child(3),#r01>:nth-child(3),#r08 pre>:nth-child(3),.app__barras i:nth-child(3),.app__comanda li:nth-child(3){--i:2}
.carril a:nth-child(4),.orden li:nth-child(4),#r01>:nth-child(4),#r08 pre>:nth-child(4),.app__barras i:nth-child(4),.app__comanda li:nth-child(4){--i:3}
.carril a:nth-child(5),.orden li:nth-child(5),#r01>:nth-child(5),.app__barras i:nth-child(5),.app__comanda li:nth-child(5){--i:4}
.carril a:nth-child(6),.orden li:nth-child(6),#r01>:nth-child(6),.app__barras i:nth-child(6),.app__comanda li:nth-child(6){--i:5}
.carril a:nth-child(7),.orden li:nth-child(7),#r01>:nth-child(7),.app__barras i:nth-child(7),.app__comanda li:nth-child(7){--i:6}
.carril a:nth-child(8),.orden li:nth-child(8),#r01>:nth-child(8),.app__barras i:nth-child(8),.app__comanda li:nth-child(8){--i:7}
.carril a:nth-child(9),#r01>:nth-child(9),.app__barras i:nth-child(9),.app__comanda li:nth-child(9){--i:8}
.carril a:nth-child(10){--i:9}.carril a:nth-child(11){--i:10}.carril a:nth-child(12){--i:11}

/* 1 · LA COMANDA SE IMPRIME. Una cortina del color del mostrador se repliega de arriba abajo:
   el papel (con lo impreso encima) sale del rodillo. Es scaleY puro — el compositor lo hace
   solo — y no toca el clip-path del papel entero, que en una página de 20 000 px habría
   revelado el primer pliegue en 40 ms. 105vh = una pantalla de recorrido y algo de colchón.
   La cortina SALE de pantalla, así que va con ease-out (con .4,0,.2,1 a los 200 ms apenas se
   había replegado un 8 %). Y es la primera impresión de la sesión, como la intro: el <head>
   de cada página pone html.ya-impreso desde la segunda página, y ahí ya no se repite encima
   de la transición entre páginas. */
.papel::after{content:"";position:absolute;z-index:3;inset:0 0 auto;height:105vh;background:var(--carbon);
  transform:scaleY(0);transform-origin:50% 100%;pointer-events:none;animation:imprimir 500ms var(--ease-out) backwards}
html.ya-impreso .papel::after{animation:none}
/* Sin cortina, el asomar del hero quedaba a la vista: sus hijos esperaban 300 ms en +16 px y
   subían escalonados hasta ~1 s. Como con la intro, el hero ya está puesto; el teléfono
   conserva su flote. (html.intro, más abajo, gana cuando la portada trae las dos clases.) */
html.ya-impreso #r01>*{animation:none}
@media(min-width:601px){html.ya-impreso #r01 .telefono{animation:flotar 6s ease-in-out 2.4s infinite}}
@keyframes imprimir{from{transform:scaleY(1)}}
/* El hero se acomoda detrás de la cortina: cuando la cortina llega, ya está puesto.
   Aquí NO se anima la opacidad: un elemento en opacity:0 no cuenta como pintado y el LCP se
   iría a donde termine la coreografía (medido: +1.3 s). Solo transform, que sí pinta. */
#r01>*{animation:asomar .45s var(--ease) backwards;animation-delay:calc(300ms + var(--i,0)*80ms)}
@keyframes asomar{from{transform:translateY(16px)}}
@keyframes entrar{from{opacity:0;transform:translateY(14px)}}
/* El titular no necesita su propia entrada: la cortina lo imprime, y su movimiento son las
   dos cifras contando. Las líneas siguen siendo bloques para que el tecleo de la segunda
   pueda reservar su alto. */
.h-display .linea,.h-display .linea>*{display:block}
/* La segunda línea es la del tecleo: mono y más chica, o "Tu carta, tus reglas, tus reportes."
   se come el pliegue en cuatro renglones. */
.h-display .mono{font-weight:800;font-size:.58em;letter-spacing:-.01em;margin-top:.15em}
.cuenta{font-variant-numeric:tabular-nums}
/* El teléfono del hero respira. Solo en escritorio y solo después de entrar. */
@media(min-width:601px){#r01 .telefono{animation:asomar .45s var(--ease) calc(300ms + var(--i,0)*80ms) backwards,flotar 6s ease-in-out 2.4s infinite}}
@keyframes flotar{50%{transform:translateY(-7px)}}
/* El logo: el símbolo aparece y su tercer renglón (brasa) se dibuja, como el trazo del bolígrafo. */
.nav__logo svg{animation:aparecer .45s var(--ease) 80ms backwards}
.logo__acento{stroke-dasharray:1;animation:trazar .6s var(--ease) .5s backwards}
@keyframes aparecer{from{opacity:0}}
@keyframes trazar{from{stroke-dashoffset:1}}
/* El carril se imprime casilla por casilla. `backwards` y no `both`: al terminar manda otra vez
   la opacidad base del carril (.55, o 1 en el renglón activo). */
.carril a{animation:entrar .4s var(--ease) backwards;animation-delay:calc(460ms + var(--i,0)*42ms)}

/* 2 · SELLOS. Palomear es un golpe de sello, no un cambio de color. */
@keyframes sello{0%{transform:scale(.55);opacity:.35}60%{transform:scale(1.25)}100%{transform:scale(1);opacity:1}}
@keyframes halo{from{box-shadow:0 0 0 0 color-mix(in srgb,var(--acento) 55%,transparent)}to{box-shadow:0 0 0 10px transparent}}
.carril .check.sello{animation:sello .6s var(--rebote)}
.carril a[aria-current="true"] .check.sello{animation:sello .6s var(--rebote),halo .6s var(--ease)}
/* El microcopy del check, visible: un trozo recortado del ticket — misma tinta hueso, un tono
   más claro que el papel para que se despegue del renglón, y canto punteado. */
.toast{position:fixed;z-index:60;left:50%;translate:-50% 0;top:calc(var(--nav-h) + 12px);white-space:nowrap;
  font:600 .7rem/1 var(--mono);letter-spacing:.06em;text-transform:uppercase;background:#242424;color:var(--hueso);
  border:1px dashed #4D4D4D;border-radius:4px;padding:.5rem .7rem;pointer-events:none;box-shadow:0 8px 24px rgba(0,0,0,.55);
  opacity:0;transform:translateY(-6px);transition:opacity var(--t1) var(--ease),transform var(--t1) var(--ease)}
.toast.ver{opacity:1;transform:none}
/* Móvil: arriba no cabe — bajo la nav y el carril fijos el papelito se sentaba encima del
   titular del renglón. Se va al pie, centrado, 16 px por encima del flotante de WhatsApp
   (que ocupa de 16 a 64 px), y entra subiendo. Es la zona que el pulgar ya no lee. */
@media(max-width:600px){.toast{top:auto;bottom:80px;transform:translateY(6px)}}
@media(min-width:1240px){.toast{left:calc(50% - 396px);translate:-100% 0;top:calc(var(--nav-h) + 88px)}}
/* Móvil: el número del renglón activo voltea como el rodillo de una vieja caja registradora.
   La animación se relanza sola porque el span pasa de display:none a inline al cambiar de renglón. */
@media(max-width:600px){.carril a[aria-current="true"] span:not(.check){animation:voltear .25s var(--ease)}}
@keyframes voltear{from{transform:rotateX(90deg);opacity:0}}

/* 3 · CIFRAS QUE CUENTAN — el JS pone data-a; aquí solo el barrido de "línea reimpresa"
   cuando pintar() cambia un [data-calc]. */
@keyframes reimprimir{from{clip-path:inset(0 100% 0 0)}}
.reimprime{animation:reimprimir .4s var(--ease)}

/* 4 · LA COSTURA CON SCROLL REAL: el bloque carbón sube y se redondea hasta ser un teléfono. */
.costura__abajo{transition:transform var(--t3) var(--ease),border-radius var(--t3) var(--ease)}
:where(html.js) #r06:not(.visto) .costura__abajo{transform:translateY(60px);border-radius:0}
@supports(animation-timeline:view()){
  :where(html.js) #r06:not(.visto) .costura__abajo{transform:none;border-radius:36px 36px 0 0}
  .costura__abajo{animation:coser linear backwards;animation-timeline:view();animation-range:entry 0% entry 70%}
  @keyframes coser{from{transform:translateY(60px);border-radius:0;opacity:.6}}
  /* El papel que queda arriba se apaga al salir: se acabó el papel. */
  .renglon[data-tramo="costura"]>:first-child{animation:desvanecer linear backwards;animation-timeline:view();animation-range:exit 0% exit 60%}
  @keyframes desvanecer{to{opacity:.5}}
}
/* La barra de la app se enciende: la hora se teclea (JS) y "Sincronizado" parpadea tres veces. */
@keyframes latir{50%{opacity:.25}}
#r06.visto .costura__abajo .barra-app>span:last-child{animation:latir .3s var(--ease) 3}
/* Barra de lectura: 2 px de brasa bajo la nav. Es el único dato vivo de toda la página. */
.progreso{position:fixed;left:0;right:0;top:calc(var(--nav-h) - 2px);height:2px;z-index:51;pointer-events:none;
  background:var(--acento);transform:scaleX(0);transform-origin:0 50%}
@supports(animation-timeline:scroll()){.progreso{animation:progreso linear both;animation-timeline:scroll(root)}}
@keyframes progreso{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* 5 · EL AGENTE SE ESCRIBE SOLO. El cursor del tecleo y la cascada del changelog. */
.teclea::after{content:"";display:inline-block;width:.1em;min-width:1px;height:1em;vertical-align:-.16em;background:currentColor;opacity:.45}
#r08 pre>span{display:block}
#r08 pre .reveal{transition-delay:calc(1.85s + var(--i,0)*120ms)}
#r08.visto .tarjeta .btn--acento{animation:pulso .5s var(--rebote) 1.7s}
@keyframes pulso{50%{transform:scale(1.06)}}
:where(html.js) #r08 .tarjeta+.tarjeta{transition-delay:1.95s}
/* Los renglones de la orden se imprimen de izquierda a derecha, uno tras otro. */
:where(html.js) .orden li{clip-path:inset(0 100% 0 0);transition:clip-path .4s var(--ease);transition-delay:calc(var(--i,0)*70ms)}
.visto .orden li{clip-path:inset(0 0 0 0)}
@media(prefers-reduced-motion:reduce){.orden li{clip-path:none}}
/* La línea de tiempo del arranque se traza hacia abajo. */
#r09 .orden{position:relative}
#r09 .orden::before{content:"";position:absolute;left:-.85rem;top:.4rem;bottom:.4rem;width:1px;background:currentColor;
  opacity:.28;transform:scaleY(0);transform-origin:50% 0;transition:transform var(--t3) var(--ease) .2s}
#r09.visto .orden::before{transform:scaleY(1)}
/* La tarjeta de la app en 04 pasa por sus tres estados: VER → ENTENDER → ACTUAR. Tres vueltas
   y se acaba: el bucle infinito es del teléfono del hero y del ticker, no de aquí. Sin
   fill-mode, al terminar cada párrafo vuelve a su estado natural — opacidad 1, los tres
   encendidos y legibles — que es el mismo reposo que ya tenían sin JS y con quietud. */
#r04.visto .tarjeta--app .grid3>*>p+p{animation:turno 7.2s var(--ease) 3;animation-delay:calc(var(--i,0)*-4.8s)}
/* .55 era el apagado sobre carbón (6.4:1). Sobre el ascua de la tarjeta cae: el turno se apaga
   menos, a .7, que sobre ascua sigue pasando el 4.5:1. */
@keyframes turno{0%,20%{opacity:1}32%,100%{opacity:.7}}
/* El panel de 11 flota con el scroll (parallax de un solo elemento, sin listeners). */
@supports(animation-timeline:view()){
  #r11 figure.tablet{animation:flotante linear both;animation-timeline:view();animation-range:entry 0% exit 100%}
  @keyframes flotante{from{transform:translateY(26px)}to{transform:translateY(-18px)}}
}

/* 6 · CERRAR LA CUENTA = CORTE DE TICKET. El CTA navega en el mismo clic; el gesto vive en el
   press: mientras el dedo está abajo el papel se levanta y gira un pelo sobre el botón (el JS
   pone ahí el pivote) y al soltar se asienta. Nada espera a que termine. */
.papel{transition:transform 160ms var(--ease-out)}
.papel.levanta{transform:translateY(-4px) rotate(-.15deg)}

/* 7 · MICROINTERACCIONES
   Todo lo presionable responde al BAJAR el dedo (:active), no al soltarlo, y la escala se
   queda entre .95 y .98. Los blancos chicos (casillas del carril, ☰, flotante) bajan a .95
   para que el hundido se note; chips y dolores, a .97/.98, porque son anchos. */
.chip:active{transform:scale(.97)}
.orden--tachable button:active{transform:scale(.98)}
.wa-flotante,.nav__menu>summary{transition:transform 160ms var(--ease-out)}
.carril a:active,.wa-flotante:active,.nav__menu>summary:active{transform:scale(.95)}
/* Los destinos del panel ☰ casi siempre cambian de página: sin el destello del navegador, el
   toque no respondía hasta que arrancaba la navegación y con mala red se sentía muerto. Se
   apagan al bajar el dedo; solo opacidad, que la quietud conserva. */
.nav__menu>nav a{transition:opacity 100ms var(--ease-out)}
.nav__menu>nav a:active{opacity:.6}
/* Lo que se toca no espera el doble toque (manipulation), y el texto de un CONTROL no se
   selecciona con un long-press. Nunca en body: el resumen y los montos son contenido y se
   copian. Va aquí, después de .orden--tachable button{all:unset}, que si no lo devolvería a auto. */
button,a,summary,[role="button"],input[type=range],.orden--tachable button{touch-action:manipulation}
.btn,.chip,.carril a,.nav__menu>summary,.wa-flotante,.orden--tachable button{user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}
/* El hover va detrás de un puntero fino, y :not(:active) para que el ratón también vea el hundido:
   con la misma especificidad, .btn:hover (que va después) le ganaba siempre a .btn:active. */
@media(hover:hover) and (pointer:fine){.btn:hover:not(:active){transform:translateY(-1px)}
  .nav__links a:not(.btn){background:linear-gradient(currentColor,currentColor) 0 100%/0 1.5px no-repeat;transition:background-size var(--t1) var(--ease),opacity var(--t1)}
  .nav__links a:not(.btn):hover{background-size:100% 1.5px}}
/* El ticker de capacidades: la tira de papel que sigue saliendo. Dos copias idénticas y
   -50% de recorrido, así el bucle no tiene costura. Sin animación se queda quieto y legible. */
.ticker{overflow:hidden;margin:2.5rem calc(-1 * var(--pad-x,0px)) 0;padding:.7rem 0;
  border-top:1px dashed var(--borde);border-bottom:1px dashed var(--borde);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.ticker__pista{display:flex;width:max-content;animation:correr 60s linear infinite;
  font:600 .7rem/1 var(--mono);letter-spacing:.14em;color:var(--medio);text-transform:uppercase;white-space:nowrap}
.ticker__pista>span{padding-right:2rem}
@keyframes correr{to{transform:translateX(-50%)}}
@media(hover:hover){.ticker:hover .ticker__pista{animation-play-state:paused}}
/* Transición entre páginas: el papel nuevo sube. Donde no hay soporte, se ignora. */
@view-transition{navigation:auto}
::view-transition-old(root){animation:fade-out 180ms var(--ease) both}
::view-transition-new(root){animation:subir-pg 260ms var(--ease) both}
@keyframes fade-out{to{opacity:0}}
@keyframes subir-pg{from{opacity:0;transform:translateY(10px)}}
@media(prefers-reduced-motion:reduce){@view-transition{navigation:none}}

/* ═══════════ 8 · LA IMPRESORA SACA EL TICKET (solo la home, una vez por sesión) ═══════════
   La escena entera vive en CSS con delays fijos y `forwards` donde hace falta: si el módulo
   JS no carga o revienta, la impresora se va igual y la página queda usable. El JS solo marca
   la sesión, suena los golpes, saca el nodo del DOM y retrasa su propia coreografía.
   `html.intro` lo pone el <script> del <head> — nunca sin JS, nunca con quietud, nunca con #hash.
   Actos: 0–450 despierta (cae, LED, display teclea) · 450–900 recibe la comanda (display,
   símbolo brasa) · 900–2400 imprime a tirones (papel+telón+cabezal+rodillo al mismo reloj) ·
   2400–2800 corta y despega. El JS acompaña con INTRO=2500 en comanda.js.
   El bloque se llama `.impresora`, NO `.intro`: la clase de estado la lleva el <html>, así que
   `.intro{display:none}` habría apagado la página entera y el remove() habría borrado el <html>. */
.impresora{display:none}
/* Un solo uso presupuestado de acento para toda la escena: LED, display, cabezal y el tercer
   renglón del símbolo son la MISMA luz brasa, definida aquí una vez (--led).
   --svgh es el alto real de la comandera en pantalla (viewBox 480×210), y de ahí sale cuánto
   tiene que subir el papel para nacer en la boca (ver html.intro .papel). Manda el ALTO y el
   ancho lo sigue (.impresora__svg): así --svgh no es una estimación del alto, es el alto.
   El tope de la mitad del hueco no es adorno: sin él, en apaisado (812×375) la comandera pide
   355px de los 319 que hay, el flex la encoge, --svgh deja de ser su alto real y --sube sale
   NEGATIVO — el ticket bajaría A la boca en vez de salir DE ella, y el telón (flex:1 sobre un
   basis de 0) se quedaría en cero. Con el tope al telón le queda siempre la mitad de arriba.
   svh, no vh: la escena es `position:fixed`, y una caja fija mide el viewport chico — el de la
   barra del navegador desplegada, que es justo la que hay al cargar. Con vh, en iOS el papel
   arrancaba ~75px por debajo de la boca y llegaba tarde a cada tirón. */
html.intro{--svgh:min(calc(min(calc(var(--papel-w) + 98px),100vw)*0.4375),calc((100svh - var(--nav-h))*0.5))}
html.intro .impresora{--led:var(--acento);display:flex;flex-direction:column;position:fixed;inset:var(--nav-h) 0 0;z-index:60;
  /* La escena es telón, no interfaz: nada aquí se toca. Sin esto la capa se traga TODOS los
     clics hasta los 2900 ms (visibility solo salta a hidden al final de imp-fin, y opacity:0
     no quita el hit-testing), y quien cae en la página no puede tocar el CTA del hero en casi
     tres segundos — sin ninguna señal de por qué. */
  pointer-events:none;
  animation:imp-fin .4s var(--ease) 2500ms forwards}
@keyframes imp-fin{to{opacity:0;visibility:hidden}}
/* La comandera vive al PIE, como en el mostrador, y al terminar se retira hacia abajo. */
.impresora__cabeza{background:var(--fondo);display:grid;place-items:start center;overflow:hidden;flex:none;
  animation:imp-irse .4s var(--ease) 2400ms forwards}
@keyframes imp-irse{to{transform:translateY(115%);opacity:0}}
/* El telón es el mostrador de arriba: cubre del techo a la boca y se repliega hacia arriba
   A TIRONES — los mismos siete tirones del papel, para que el frente de revelado y el ticket
   suban como una sola pieza. Una térmica no desliza: tira, respira, vuelve a tirar. */
.impresora__telon{flex:1;background:var(--fondo);transform-origin:50% 0;
  animation:telon-tirones 1.5s linear 900ms forwards}
@keyframes telon-tirones{0%{transform:scaleY(1)}
  9%{transform:scaleY(.86)}14%{transform:scaleY(.86)}
  23%{transform:scaleY(.70)}28%{transform:scaleY(.70)}
  38%{transform:scaleY(.53)}43%{transform:scaleY(.53)}
  54%{transform:scaleY(.37)}59%{transform:scaleY(.37)}
  70%{transform:scaleY(.22)}75%{transform:scaleY(.22)}
  86%{transform:scaleY(.08)}91%{transform:scaleY(.08)}
  100%{transform:scaleY(0)}}
/* La ranura tiene que medir lo que el ticket, o el papel no sale de la impresora: sale de
   detrás de una caja. La boca ocupa el 89% del viewBox, así que 720/0.89 ≈ papel + 98 — ese
   ancho ya vive dentro de --svgh, y aquí el ancho se deduce del alto para que el alto que
   dice la cuenta y el alto que se pinta sean el mismo número. */
.impresora__svg{height:var(--svgh);width:auto;display:block;
  animation:imp-caer .5s var(--rebote) both,imp-vibra 215ms steps(2,jump-none) 900ms 7}
/* Acto 1: la comandera sube al mostrador y asienta — es un fierro con peso, no un dibujo. */
@keyframes imp-caer{from{transform:translateY(36px);opacity:0}60%{opacity:1}to{transform:none}}
@keyframes imp-vibra{50%{transform:translateY(1.6px)}}
.pz-tapa{fill:#232323;stroke:#2e2e2e;stroke-width:1.5}
.pz-cuerpo{fill:#1a1a1a;stroke:#2a2a2a;stroke-width:2}
.pz-base{fill:#0B0B0B}
.pz-tx{font:600 10px/1 var(--mono);letter-spacing:.12em;fill:var(--medio)}
.pz-boton{fill:none;stroke:#3a3a3a;stroke-width:1.5}
/* El botón se hunde dos veces: al despertar y al arrancar la impresión. */
.pz-btn{transform-box:fill-box;transform-origin:center;animation:hundir .3s var(--ease),hundir .3s var(--ease) 900ms}
@keyframes hundir{40%,70%{transform:scale(.94)}}
/* El LED: dos parpadeos de arranque, tres lentos mientras imprime, y fijo al terminar. */
.pz-led{fill:var(--led);animation:led .2s steps(1) 2,led .5s 900ms 3}
@keyframes led{0%,45%{opacity:.15}50%,100%{opacity:1}}
/* El display narra los actos: cada mensaje entra por corte seco (steps), como LCD de a duro.
   El primero además se teclea — clip que abre en 12 golpes. */
.pz-display rect:first-child{fill:#0B0B0B;stroke:#2a2a2a;stroke-width:1.5}
.pz-d{font:700 12px/1 var(--mono);letter-spacing:.1em;fill:var(--led)}
.pz-d1{clip-path:inset(0 100% 0 0);animation:pz-teclea .35s steps(12) 80ms forwards,pz-off 0s linear 450ms forwards}
@keyframes pz-teclea{to{clip-path:inset(0 0 0 0)}}
.pz-d2,.pz-d3,.pz-d4{opacity:0}
.pz-d2{animation:pz-on 0s linear 450ms forwards,pz-off 0s linear 900ms forwards}
.pz-d3{animation:pz-on 0s linear 900ms forwards,pz-off 0s linear 2400ms forwards}
.pz-d4{animation:pz-on 0s linear 2400ms forwards}
@keyframes pz-on{to{opacity:1}}
@keyframes pz-off{to{opacity:0}}
/* La barra de progreso avanza en seis golpes, al ritmo de los tirones. */
.pz-prog{fill:var(--led);transform-box:fill-box;transform-origin:left center;transform:scaleX(0);
  animation:pz-avanza 1.5s steps(6,jump-none) 900ms forwards}
@keyframes pz-avanza{from{transform:scaleX(0)}to{transform:scaleX(1)}}
.pz-rejilla path{stroke:#232323;stroke-width:4;stroke-linecap:round}
/* El símbolo de la comanda grabado en el frente: sus dos renglones fijos, y el tercero —
   el que todavía no se cierra — se enciende cuando entra la orden. Acto 2 en una línea. */
.pz-simbolo rect{stroke:#3a3a3a;stroke-width:2}
.pz-s-r{stroke:#3a3a3a;stroke-width:2.5;stroke-linecap:round}
.pz-s-brasa{stroke:var(--led);stroke-width:2.5;stroke-linecap:round;stroke-dasharray:1;stroke-dashoffset:1;
  animation:pz-enciende .3s var(--ease) 560ms forwards}
@keyframes pz-enciende{to{stroke-dashoffset:0}}
.pz-labio{fill:#000}
/* El cabezal térmico: la línea de calor pulsa con cada tirón — es lo que "escribe" el ticket. */
.pz-cabezal{fill:var(--led);opacity:0;animation:pz-quema 1.5s linear 900ms}
@keyframes pz-quema{0%{opacity:0}5%{opacity:.9}12%{opacity:.15}
  23%{opacity:.9}30%{opacity:.15}38%{opacity:.9}45%{opacity:.15}
  54%{opacity:.9}61%{opacity:.15}70%{opacity:.9}77%{opacity:.15}
  86%{opacity:.9}94%{opacity:.2}100%{opacity:0}}
.pz-ranura{fill:var(--papel);stroke:#3D3D3D;stroke-width:1}
/* El rodillo dentado gira por pasos dentro de la boca: catorce dientes, el mismo reloj. */
.pz-rodillo{stroke:#303030;stroke-width:4;stroke-dasharray:6 5;
  animation:pz-gira 1.5s steps(14) 900ms}
@keyframes pz-gira{to{stroke-dashoffset:-44}}
/* Con intro, el papel no se imprime con su cortina: NACE EN LA BOCA y sube a tirones (los
   mismos siete del telón) hasta su lugar, y al final recibe el jalón del corte. --sube es la
   distancia de la boca al lugar del papel: (alto visible − 99% de la comandera) − top del
   papel (24 en escritorio, 44 en móvil por el carril fijo). La cortina propia se apaga. */
html.intro .papel::after{animation:none}
/* El jalón del corte gira sobre el borde de arriba, que es lo que se ve: sobre el centro de un
   papel de 10 mil px, .12deg movían el hero ~10 px de lado justo al terminar la impresión. */
html.intro .papel{transform-origin:50% 0;--sube:calc(100svh - var(--nav-h) - var(--svgh)*0.99 - 24px);
  animation:papel-tirones 1.5s linear 900ms backwards,papel-corte .35s var(--rebote) 2400ms}
@media(max-width:600px){html.intro .papel{--sube:calc(100svh - var(--nav-h) - var(--svgh)*0.99 - 44px)}}
@keyframes papel-tirones{0%{transform:translateY(var(--sube))}
  9%{transform:translateY(calc(var(--sube)*.86))}14%{transform:translateY(calc(var(--sube)*.86))}
  23%{transform:translateY(calc(var(--sube)*.70))}28%{transform:translateY(calc(var(--sube)*.70))}
  38%{transform:translateY(calc(var(--sube)*.53))}43%{transform:translateY(calc(var(--sube)*.53))}
  54%{transform:translateY(calc(var(--sube)*.37))}59%{transform:translateY(calc(var(--sube)*.37))}
  70%{transform:translateY(calc(var(--sube)*.22))}75%{transform:translateY(calc(var(--sube)*.22))}
  86%{transform:translateY(calc(var(--sube)*.08))}91%{transform:translateY(calc(var(--sube)*.08))}
  100%{transform:translateY(0)}}
@keyframes papel-corte{0%{transform:translateY(3px) rotate(-.12deg)}100%{transform:none}}
/* Y el hero no se asoma dos veces: el movimiento es el del papel. El teléfono conserva su flote. */
html.intro #r01>*{animation:none}
@media(min-width:601px){html.intro #r01 .telefono{animation:flotar 6s ease-in-out 3.6s infinite}}
html.intro .carril a{animation-delay:calc(2500ms + var(--i,0)*42ms)}

/* ═══════════ 9 · LA APP, DIBUJADA ═══════════
   El producto se enseña en marca ComandAI, no con capturas del sistema de un cliente: todo
   esto es HTML/CSS, con datos genéricos. Regla de color de las pantallas: el suelo es el ascua
   honda (ahí --medio da 6.3:1); los paneles son ascua de verdad (#3A1810) y encima SOLO va
   blanco/hueso o el gris claro --app-eti (5.9:1) — el --medio del sitio ahí da 2.8:1.
   Estados: brasa = listo/en vivo · maíz = pide atención · comal = crítico. */
.app{--medio:#9a9a9a;--app-eti:#D5E2DE;background:var(--ascua-honda);color:#fff;
  display:grid;align-content:start;gap:.55rem;padding:.7rem .75rem;border-radius:10px;overflow:hidden;
  font:.8rem/1.35 var(--sans)}
.telefono>.app{border-radius:28px;height:100%;padding:1.1rem .9rem;gap:.7rem}
.tablet>.app{aspect-ratio:4/3;border-radius:10px}
/* El panel ancho reparte su contenido en el alto que le toca; en móvil manda el contenido,
   porque a 16/10 la banda del modo isla — la prueba de la sección — quedaba fuera del marco. */
.tablet--panel>.app{aspect-ratio:16/10;align-content:space-between}
@media(max-width:600px){.tablet--panel>.app{aspect-ratio:auto}}
.app__barra{display:flex;justify-content:space-between;align-items:center;gap:.5rem;
  font:600 .6rem/1.2 var(--mono);letter-spacing:.06em;text-transform:uppercase;color:var(--medio);
  border-bottom:1px solid var(--borde-ascua);padding-bottom:.5rem}
/* El punto de "sincronizado": el latido del dato vivo. */
.app__vivo{width:7px;height:7px;border-radius:50%;background:var(--acento);display:inline-block;
  vertical-align:.05em;margin-right:.35rem;animation:latir 2.4s ease-in-out infinite}
.app__kpis{display:grid;grid-template-columns:1fr 1fr;gap:.4rem}
/* El panel ancho (r11) cabe en cuatro: dos sucursales, su suma y el costo, de un vistazo. */
.app__kpis--4{grid-template-columns:repeat(4,1fr)}
@media(max-width:600px){.app__kpis--4{grid-template-columns:1fr 1fr}}
.app__kpi{background:var(--ascua);border-radius:8px;padding:.5rem .6rem}
.app__kpi span{display:block;font:600 .55rem/1.2 var(--mono);letter-spacing:.07em;text-transform:uppercase;color:var(--app-eti)}
.app__kpi b{display:block;font:800 1.05rem/1.15 var(--mono);letter-spacing:-.02em;margin-top:.15rem}
/* Lo crítico se dice en rojo sobre su propio bloque oscuro, para no depender del ascua. */
.app__alerta{margin:0;background:var(--papel);border-left:3px solid var(--comal);border-radius:0 6px 6px 0;
  padding:.45rem .55rem;font-size:.72rem;line-height:1.35;color:var(--comal);max-width:none}
.app__alerta b{color:var(--comal)}
.app__piso{display:grid;grid-template-columns:repeat(6,1fr);gap:4px}
.app__mesa{border:1px solid var(--borde-ascua);border-radius:5px;padding:.3rem .1rem;text-align:center;
  font:600 .5rem/1.3 var(--mono);color:var(--medio)}
.app__mesa b{display:block;font-size:.62rem;color:inherit}
.app__mesa[data-e="ocupada"]{background:var(--ascua);border-color:var(--ascua);color:#fff}
.app__mesa[data-e="cobrar"]{background:var(--maiz);border-color:var(--maiz);color:var(--carbon)}
/* Una mesa cambia de estado sola cuando el renglón entra en cuadro: el piso está vivo. */
@keyframes a-cobrar{to{background:var(--maiz);border-color:var(--maiz);color:var(--carbon)}}
#r05.visto .app__mesa[data-cambia]{animation:a-cobrar .45s var(--ease) 1.9s forwards}
.app__eti{margin:0;font:600 .58rem/1.2 var(--mono);letter-spacing:.07em;text-transform:uppercase;color:var(--medio)}
.app__comanda{list-style:none;margin:0;padding:0;font:.72rem/1.6 var(--mono)}
.app__comanda li{display:flex;justify-content:space-between;gap:.6rem}
.app__comanda .app__total{border-top:1px dashed var(--borde-ascua);margin-top:.3rem;padding-top:.3rem;font-weight:700}
.app__estaciones{display:grid;grid-template-columns:1fr 1fr;gap:.6rem}
.app__tickets{list-style:none;margin:.35rem 0 0;padding:0;font:.66rem/1.7 var(--mono)}
.app__tickets li::before{content:"·";color:var(--medio);margin-right:.4rem}
.app__tickets li[data-ok]{color:var(--medio);text-decoration:line-through}
.app__tickets li[data-ok]::before{content:"✓";color:var(--acento);text-decoration:none}
.app__cliente{display:grid;gap:.5rem;justify-items:center;text-align:center;padding:.4rem 0}
.app__monto{margin:0;font:800 1.9rem/1 var(--mono);letter-spacing:-.03em}
.app__propinas{display:flex;gap:.35rem}
.app__propina{border:1px solid var(--borde-ascua);border-radius:999px;padding:.28rem .7rem;
  font:600 .65rem/1 var(--mono);color:var(--medio)}
.app__propina[data-sel]{background:var(--acento);border-color:var(--acento);color:var(--carbon)}
.app__boton{margin:.2rem 0 0;background:#fff;color:var(--carbon);border-radius:999px;
  padding:.4rem 1.4rem;font:700 .72rem/1.3 var(--sans)}
.app__isla{display:flex;align-items:center;gap:.5rem;margin:0;background:var(--papel);
  border:1px solid var(--maiz);border-radius:8px;padding:.5rem .6rem;color:var(--maiz);
  font:600 .6rem/1.3 var(--mono);letter-spacing:.05em;text-transform:uppercase;max-width:none}
.app__punto{width:8px;height:8px;border-radius:50%;background:var(--maiz);flex:none;
  animation:latir 1.4s ease-in-out infinite}
.app__lista{list-style:none;margin:0;padding:0;font:.7rem/1.9 var(--mono);color:var(--app-eti)}
/* La gráfica de ventas por hora: divs con altura, sin librería. La última barra es la hora que
   corre — el único brasa de la pantalla. */
.app__barras{display:flex;align-items:flex-end;gap:3px;height:70px}
.app__barras i{flex:1;background:var(--ascua);border-radius:2px 2px 0 0;height:var(--h);
  transform-origin:50% 100%;transition:transform var(--t3) var(--ease);transition-delay:calc(var(--i,0)*45ms)}
.app__barras i:last-child{background:var(--acento)}
:where(html.js) .renglon:not(.visto) .app__barras i{transform:scaleY(.06)}
.mockups{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));margin-top:2rem}
.mockups>figure{margin:0;align-self:start}
.mockups>.ancho{grid-column:1/-1}

/* ═══════════ 10 · EL KIT ═══════════
   Terminal, impresora e isla dibujadas en carbón, con el símbolo en la terminal. Sin fotos:
   todavía no existe la render del hardware y un stock de internet no es nuestra marca. */
.kit{display:block;width:100%;height:auto;margin:1.5rem 0}
.kit-cuerpo{fill:#1C1C1C;stroke:#333;stroke-width:2}
.kit-pantalla{fill:var(--ascua-honda);stroke:#333;stroke-width:1.5}
.kit-detalle{stroke:#3A3A3A;stroke-width:2;stroke-linecap:round}
.kit-tinta{fill:var(--hueso)}
.kit-eti{font:600 11px/1 var(--mono);letter-spacing:.14em;fill:var(--medio)}
.kit-marca{font:600 9px/1 var(--mono);letter-spacing:.16em;fill:var(--medio)}
.kit-led{fill:var(--acento);animation:led 1.8s ease-in-out infinite}
.kit-papel{fill:var(--papel);stroke:#3D3D3D;stroke-width:1}

/* Impresión: solo el papel, 80 mm */
@media print{body{background:#fff}.papel{background:#fff!important;color:#000!important}.nav,.wa-flotante,.pie,.carril,.btn,.progreso,.toast,.ticker{display:none!important}
  .escena{display:block;padding:0}.papel{box-shadow:none;width:80mm;margin:0}.papel::after{display:none}
  .renglon{padding:6mm 4mm;background:#fff!important;color:#000!important}
  .reveal{opacity:1;transform:none}.orden li{clip-path:none}.tachado{text-decoration:line-through}}
