/* ===========================================================================
   Mioo — medios: el vídeo de presentación y la grabadora
   ---------------------------------------------------------------------------
   Salió de `estilos.css` cuando ese archivo llegó a 909 líneas y la regla del
   proyecto son 900. El corte no es por la mitad: aquí está TODO lo que solo
   existe cuando hay cámara o archivo de por medio —el campo del perfil, la
   grabadora a pantalla completa y la revisión—, y nada de eso lo usa el resto
   de la aplicación.

   No declara ni un token. Los usa todos de `estilos.css`, que se carga antes:
   si algún día esta hoja necesitara un color o una duración propios, sería la
   señal de que la pieza no encaja en el sistema.
   =========================================================================== */

/* === vídeo de presentación ===============================================
   Todo lo de aquí usa los tokens que ya existen. No hay un color, un radio ni
   una duración nuevos: si algo necesitara uno, sería señal de que no encaja. */

/* La tarjeta vacía: una sola fila que se pulsa entera, con la flecha diciendo
   que lleva a otro sitio. Mismo gesto que el paso de la hoja de guardar. */
.video-vacio { display: flex; align-items: center; gap: var(--esp-3); width: 100%;
               min-height: 76px; padding: 14px 16px; border: 0; border-radius: var(--r-lg);
               background: var(--superficie); color: var(--tinta); text-align: left;
               cursor: pointer; font: inherit;
               transition: transform var(--dur-1) var(--curva); }
.video-vacio:active { transform: scale(.985); }
.video-vacio__icono { flex: none; width: 44px; height: 44px; border-radius: var(--r-md);
                      display: grid; place-items: center; background: var(--fondo); }
.video-vacio__icono svg { width: 22px; height: 22px; fill: none; stroke: var(--mioo);
                          stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.video-vacio__tx { flex: 1; min-width: 0; }
.video-vacio__n { display: block; font-weight: 600; font-size: .9375rem; }
.video-vacio__s { display: block; font-size: .75rem; color: var(--tinta-3); line-height: 1.45; margin-top: 2px; }
.video-vacio__flecha { flex: none; width: 18px; height: 18px; fill: none; stroke: var(--tinta-3);
                       stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

/* El vídeo ya subido. VERTICAL, porque así se graba y así se mira en un teléfono.
   No ocupa el ancho entero a propósito: un 9:16 a 430px mediría 764px de alto y se
   comería la pantalla. 220px de ancho dan una tarjeta que se ve entera de un
   vistazo y sigue siendo inequívocamente vertical.
   El fondo oscuro es del contenedor para que un vídeo que no encaje —una webcam
   de ordenador puede no dar vertical— no deje franjas del color del tema, que es
   lo que hace que parezca un fallo de maquetación. */
/* La tarjeta recién subida entra con el verbo que ya existe —`entrada`, 10px de
   subida y fundido—, el mismo que usa una vista al navegar. Aparecer de golpe donde
   antes había una fila deja al ojo sin saber de dónde salió. */
.video-caja--entra { animation: entrada var(--dur-2) var(--curva) both; }
.video-caja { position: relative; aspect-ratio: 9 / 16; width: 168px;
              border-radius: var(--r-lg); overflow: hidden; background: #0B0B0C; }
/* `contain`, no `cover`: la tarjeta enseña el vídeo ENTERO.
   Recortar aquí volvía a mentir sobre lo que hay dentro del archivo, y encima
   sumaba zoom al que ya trae la cámara. Las franjas del contenedor son negras. */
.video-caja__pieza { width: 100%; height: 100%; object-fit: contain; display: block; }

.video-caja__play { position: absolute; inset: 0; margin: auto; width: 58px; height: 58px;
                    border: 0; border-radius: var(--r-full); cursor: pointer;
                    background: rgba(255, 255, 255, .92); color: #0B0B0C;
                    display: grid; place-items: center;
                    transition: transform var(--dur-1) var(--curva), opacity var(--dur-1) var(--curva); }
.video-caja__play:active { transform: scale(.92); }
.video-caja__play svg { width: 26px; height: 26px; fill: currentColor; stroke: none; margin-left: 3px; }
/* Cuando ya está sonando manda el navegador: nuestro botón sobra y se va. */
.video-campo--sonando .video-caja__play { opacity: 0; pointer-events: none; }
.video-caja__dura { position: absolute; right: 10px; bottom: 10px;
                    padding: 3px 9px; border-radius: var(--r-full);
                    background: rgba(0, 0, 0, .55); color: #fff;
                    font-size: .75rem; font-weight: 580; font-variant-numeric: tabular-nums;
                    /* El play y la pastilla se van por el mismo motivo, así que se van
                       igual y a la vez. Sin esto, la pastilla desaparecía de golpe
                       mientras el play se fundía: dos cosas que responden al mismo
                       hecho contando historias distintas. */
                    transition: opacity var(--dur-1) var(--curva); }
.video-campo--sonando .video-caja__dura { opacity: 0; }

/* El vídeo se acomoda como «Tu foto»: la pieza a la izquierda y a su lado lo que
   se puede hacer con ella. Antes era una tarjeta suelta a lo ancho con los botones
   debajo, y quedaba como un bloque aparte en medio de una pantalla que por lo
   demás es una columna de filas. Ahora las dos secciones de medios tienen el mismo
   ritmo, y la de vídeo ocupa la mitad de alto. */
.video-campo--lleno { display: flex; gap: var(--esp-4); align-items: flex-start; }
.video-campo__pie { flex: 1; min-width: 0; display: flex; flex-direction: column;
                    align-items: flex-start; gap: 10px; }
.video-campo__acciones { display: flex; gap: 6px; flex-wrap: wrap; }
/* La barra de subida cruza las dos columnas: es del conjunto, no de una pieza. */
.video-campo--lleno .video-barra { width: 100%; }

/* La barra de subida. Existe porque son megabytes por red móvil: sin ella, cinco
   segundos de espera parecen que la app se colgó. */
.video-barra { height: 4px; margin-top: 10px; border-radius: var(--r-full);
               background: var(--superficie-2); overflow: hidden;
               transition: opacity var(--dur-2) var(--curva); }
/* Al 100% la barra se va y el texto pasa a «Guardando…». Una barra llena e inmóvil
   parece rota, y una indeterminada en bucle está prohibida por el sistema: los
   bucles piden atención para siempre y a los tres segundos son ruido. */
.video-barra--hecha { opacity: 0; }
.video-barra__hilo { display: block; height: 100%; width: 0;
                     background: var(--mioo); border-radius: var(--r-full);
                     transition: width var(--dur-2) var(--curva); }

/* Las dos opciones del menú: icono, título y una línea que dice qué va a pasar
   —incluido que la galería abre el selector del teléfono—. */
.boton--opcion { justify-content: flex-start; gap: var(--esp-3); width: 100%;
                 min-height: 72px; padding: 12px 14px; text-align: left; font-weight: 500; }
.boton--opcion svg { flex: none; width: 24px; height: 24px; }
.opcion__tx { flex: 1; min-width: 0; }
.opcion__n { display: block; font-weight: 620; font-size: .9375rem; line-height: 1.3; }
.opcion__s { display: block; font-size: .75rem; font-weight: 400; color: var(--tinta-3);
             line-height: 1.45; margin-top: 3px; white-space: normal; }

/* === la grabadora ========================================================
   A pantalla completa y con controles propios, como el escáner. Nada nativo:
   los controles del navegador traen su tipografía, su idioma y su color, y en
   medio de esta pantalla se ven como lo que son, otra aplicación. */

/* Anclada al viewport VISIBLE, no al de la maqueta.
   `inset: 0` a secas se extiende POR DEBAJO de la barra de Safari en iPhone, y ahí
   es donde quedaban el disparador y los botones de la revisión: dibujados, pero
   detrás del navegador y sin poder tocarse. Con la equis oculta durante la
   revisión, eso dejaba al usuario encerrado.
   `--teclado` lo mantiene `seguirViewport()` leyendo visualViewport, y la hoja
   inferior ya lo usaba por exactamente el mismo motivo desde hace meses. Esta
   lección estaba escrita en este repositorio y no la apliqué aquí. */
.grabadora { position: fixed; inset: 0 0 var(--teclado, 0px) 0; z-index: 60; background: #000;
             display: grid; place-items: center; overflow: hidden;
             animation: aparecer var(--dur-2) var(--curva) both; }
/* Espejo, porque una cámara frontal sin espejo se siente ajena: mueves la mano a
   la derecha y la imagen va a la izquierda. Solo la VISTA previa; lo grabado se
   queda como es. */
/* `cover` SOLO cuando la cámara da vertical de verdad.
   Con un sensor horizontal metido a la fuerza en una pantalla de pie, `cover`
   recorta el 73% del ancho: la cara llena el encuadre y parece un zoom absurdo —
   y encima lo grabado seguía siendo horizontal, así que la vista previa mentía
   sobre el resultado. Cuando no se consigue vertical, `contain`: se ve con
   franjas, pero se ve LO QUE SE VA A GRABAR. */
.grabadora__vista { position: absolute; inset: 0; width: 100%; height: 100%;
                    object-fit: contain; transform: scaleX(-1); }

.grabadora__cima { position: absolute; top: 0; left: 0; right: 0;
                   padding: calc(env(safe-area-inset-top, 0px) + 14px) 18px 14px;
                   display: flex; align-items: center; justify-content: space-between;
                   background: linear-gradient(rgba(0, 0, 0, .5), transparent); }
.grabadora__cerrar { width: 44px; height: 44px; border: 0; border-radius: var(--r-full);
                     background: rgba(0, 0, 0, .38); color: #fff; cursor: pointer;
                     display: grid; place-items: center; }
.grabadora__cerrar svg { width: 22px; height: 22px; fill: none; stroke: currentColor;
                         stroke-width: 2; stroke-linecap: round; }
.grabadora__reloj { color: #fff; font-size: .9375rem; font-weight: 620;
                    font-variant-numeric: tabular-nums; opacity: 0; padding: 4px 12px;
                    border-radius: var(--r-full); background: rgba(0, 0, 0, .38);
                    transition: opacity var(--dur-2) var(--curva); }
.grabadora--grabando .grabadora__reloj { opacity: 1; }

.grabadora__pie { position: absolute; left: 24px; right: 24px;
                  bottom: calc(env(safe-area-inset-bottom, 0px) + 132px);
                  text-align: center; color: rgba(255, 255, 255, .82);
                  font-size: .8125rem; line-height: 1.5; }
.grabadora__mando { position: absolute; left: 0; right: 0;
                    bottom: calc(env(safe-area-inset-bottom, 0px) + 34px);
                    display: grid; place-items: center; }

/* El disparador: un aro blanco con un punto dentro. Grabando, el punto se encoge
   y se vuelve cuadrado — el mismo lenguaje que la cámara del teléfono, que es lo
   que la gente ya sabe leer sin que nadie se lo explique. */
.grabadora__disparo { width: 76px; height: 76px; border-radius: var(--r-full);
                      border: 4px solid rgba(255, 255, 255, .9); background: transparent;
                      cursor: pointer; display: grid; place-items: center; padding: 0; }
.grabadora__punto { width: 58px; height: 58px; border-radius: var(--r-full);
                    background: var(--rec);
                    transition: width var(--dur-2) var(--curva), height var(--dur-2) var(--curva),
                                border-radius var(--dur-2) var(--curva); }
.grabadora--grabando .grabadora__punto { width: 28px; height: 28px; border-radius: 7px; }

/* El aro de los 30 segundos, alrededor del disparador. Un número que baja se lee;
   un aro que se cierra se VE sin leerlo, y grabando no se está leyendo. */
.grabadora__aro { position: absolute; left: 50%; translate: -50% 0;
                  bottom: calc(env(safe-area-inset-bottom, 0px) + 26px);
                  width: 92px; height: 92px; transform: rotate(-90deg);
                  pointer-events: none; opacity: 0;
                  transition: opacity var(--dur-2) var(--curva); }
.grabadora--grabando .grabadora__aro { opacity: 1; }
.grabadora__aro circle { fill: none; stroke-width: 4; stroke-linecap: round; }
.grabadora__aro-via { stroke: rgba(255, 255, 255, .22); }
/* Lineal a propósito, y es doctrina: el progreso se pega al último valor REAL, y
   con la salida suave de la casa el aro frenaría en cada décima — el tiempo restante
   parecería mentira. El «120ms» estaba escrito a mano; es exactamente `--dur-1`. */
.grabadora__aro-vivo { stroke: var(--rec); transition: stroke-dashoffset var(--dur-1) linear; }


/* === revisar lo grabado ==================================================
   Grabar y publicar son dos decisiones y aquí se separan: se ve lo que salió y
   se decide. Ocupa la grabadora entera porque en ese momento no hay nada más
   que hacer, y media pantalla con la cámara viva detrás sería ruido. */

.revision { position: absolute; inset: 0; background: #000;
            display: grid; grid-template-rows: 1fr auto;
            animation: aparecer var(--dur-2) var(--curva) both; }

/* `pointer-events: none` en el vídeo, y `z-index` en los botones.
   ESTE era el fallo que dejaba encerrado al operador. Su iPhone lo dijo con
   nombre y apellidos: en el centro de «Subir a mi perfil» y de «Repetir», quien
   recibía el toque era `g-repro` — el <video> estaba ENCIMA y se quedaba todos
   los toques. Los botones estaban ahí, en pantalla y en su sitio; simplemente no
   les llegaba nada.
   Safari resuelve `height: 100%` dentro de una fila `1fr` contra el contenedor
   entero, no contra la fila, así que el vídeo se estiraba sobre los botones. En
   Chromium no pasa, y por eso ninguna de mis 35 pruebas lo vio.
   El vídeo no es interactivo —los controles son nuestros—, así que no perder los
   toques no le quita nada, y `z-index` sobre la barra de decisión lo garantiza
   aunque la maqueta vuelva a torcerse. */
.revision__pieza { width: 100%; height: 100%; object-fit: contain; min-height: 0;
                   pointer-events: none; }
.revision__decidir { position: relative; z-index: 1; }
.revision__sonido { position: absolute; top: calc(env(safe-area-inset-top, 0px) + 14px); right: 18px;
                    width: 44px; height: 44px; border: 0; border-radius: var(--r-full);
                    background: rgba(0, 0, 0, .45); color: #fff; cursor: pointer;
                    display: grid; place-items: center; }
.revision__sonido svg { width: 21px; height: 21px; fill: none; stroke: currentColor;
                        stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.revision__decidir { padding: 16px 20px calc(env(safe-area-inset-bottom, 0px) + 20px);
                     background: linear-gradient(transparent, rgba(0, 0, 0, .75) 22%); }
.revision__nota { color: rgba(255, 255, 255, .78); font-size: .8125rem;
                  line-height: 1.5; text-align: center; margin-bottom: 12px; }
/* Sobre negro, el botón suave de la app no se ve: aquí lleva su propio par. */
.revision__repetir { margin-top: 10px; background: rgba(255, 255, 255, .14); color: #fff; }
.revision__repetir svg { stroke: currentColor; }

/* Mientras se revisa, la cámara y sus mandos sobran — pero la SALIDA no.
   Esconder la equis durante la revisión dejaba dos únicas puertas, «Subir» y
   «Repetir»; si cualquiera de las dos fallaba, no había forma de salir. Una
   pantalla a pantalla completa siempre tiene que poder cerrarse: es la regla, y
   cuesta menos que el fallo que evita. */
.grabadora--revisando .grabadora__pie,
.grabadora--revisando .grabadora__mando,
.grabadora--revisando .grabadora__aro { display: none; }
.grabadora--revisando .grabadora__reloj { display: none; }
/* La equis se sube por encima de la revisión, que la tapaba con su `inset: 0`. */
.grabadora--revisando .grabadora__cima { background: none; z-index: 2; pointer-events: none; }
.grabadora--revisando .grabadora__cerrar { pointer-events: auto; }


/* El engranaje del perfil. Discreto: es una salida, no una acción de la pantalla,
   y compite con nada. Alineado con el título por `align-items: baseline` de
   `.encabezado`, así que se le compensa el descuadre óptico a mano. */
.engrane { flex: none; width: 44px; height: 44px; margin: -10px -10px -10px 0;
           border-radius: var(--r-full); display: grid; place-items: center;
           color: var(--tinta-3); align-self: center;
           transition: color var(--dur-1) var(--curva), transform var(--dur-1) var(--curva); }
.engrane:hover { text-decoration: none; color: var(--tinta); }
.engrane:active { transform: scale(.9); }
.engrane svg { width: 23px; height: 23px; fill: none; stroke: currentColor;
               stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }


/* El vídeo de otra persona, en su ficha.
   A la izquierda y pequeño, como su foto: la ficha es una columna de filas y una
   tarjeta a lo ancho la rompería. `contain` sobre negro, igual que en todas
   partes — el archivo se enseña entero venga con la proporción que venga. */
.video-ficha { margin-top: var(--esp-4); width: 150px; }
.video-ficha__pieza { display: block; width: 100%; aspect-ratio: 9 / 16;
                      object-fit: contain; background: #0B0B0C;
                      border-radius: var(--r-lg); }
