/* ==========================================================================
   LIFE OS — CHROME Y COMPONENTES
   --------------------------------------------------------------------------
   Todo lo que no es «una pantalla concreta»: el marco del dispositivo, la
   barra de estado, la pila de vistas con sus transiciones, el cajón
   lateral, la barra de ámbitos con su orbe, el menú radial de esferas y
   el sistema de componentes.

   Dos reglas de oro de este archivo:

   1. NADA usa `position: fixed`. Dentro de `.app` hay ancestros con
      `transform` (la pila anima, el lienzo se desplaza al abrir el cajón) y
      un ancestro transformado se convierte en el bloque contenedor de sus
      descendientes fixed — dejarían de ser fijos. Todo es `absolute`.

   2. Nada que cambie en cada frame de scroll se escribe en un ancestro con
      muchos hijos. `--n` es heredada: puesta en la vista invalidaba el
      estilo de sus ~230 nodos por frame (1,54 ms); puesta en la barra,
      0,12 ms. Trece veces más barato, y era el tirón de la Home.

   Índice:
     1. Escena y marco del dispositivo
     2. Fondo: acuarela y grano
     3. Barra de estado e isla dinámica
     4. Pila de vistas y transiciones
     5. Barra de navegación
     6. Scroll, titular grande y tirar-para-refrescar
     7. Cajón lateral
     8. Barra de ámbitos y orbe
     9. Menú radial de esferas
    10. Componentes
    11. Apariciones
    12. Aviso flotante
    13. Teléfono real
    14. Movimiento reducido
   ========================================================================== */


/* `--n` = cuánto se ha desplazado la vista (0 arriba del todo, 1 desplazada).
   Registrarla como <number> la vuelve tipada: el navegador la interpola sin
   reparsear la cadena en cada escritura. */
@property --n {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}


/* ==========================================================================
   1. ESCENA Y MARCO DEL DISPOSITIVO
   ========================================================================== */

.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.escena {
  position: relative;
  display: grid;
  place-items: center;
  height: 100%;
  padding: var(--e-5);
  background:
    radial-gradient(120% 90% at 50% -10%, color-mix(in oklab, var(--sol) 34%, transparent), transparent 62%),
    radial-gradient(90% 70% at 85% 100%, color-mix(in oklab, var(--bruma) 26%, transparent), transparent 58%),
    var(--papel);
  transition: background-color var(--d-medio) var(--ease-entrada);
}

/* Firma discreta del estudio, solo en escritorio */
.escena__ficha {
  position: absolute;
  top: var(--e-6);
  left: var(--e-8);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.escena__marca {
  font-size: var(--ui-caption);
  font-weight: 700;
  letter-spacing: 0.22em;
  color: var(--tinta-2);
}

.escena__nota {
  font-size: var(--ui-caption);
  color: var(--tinta-3);
}

/* El marco: titanio oscuro con un filo de luz arriba a la izquierda */
.marco {
  position: relative;
  width: 393px;
  height: 852px;
  flex: none;
  padding: 11px;
  border-radius: 56px;
  background: linear-gradient(145deg, #55575e 0%, #24262b 22%, #1b1d21 55%, #3d3f45 100%);
  box-shadow:
    0 0 0 1px rgb(255 255 255 / 0.10) inset,
    0 2px 3px rgb(255 255 255 / 0.18) inset,
    0 34px 70px -18px rgb(24 21 17 / 0.42),
    0 10px 24px -8px rgb(24 21 17 / 0.28);
  transform: scale(var(--escala, 1));
  transform-origin: center center;
}

/* Botones físicos: puro atrezo, pero sin ellos el marco no se lee */
.marco__boton {
  position: absolute;
  width: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, #303237, #4a4c52);
}

.marco__boton--silencio  { left: -2px; top: 132px; height: 30px; }
.marco__boton--vol-mas   { left: -2px; top: 188px; height: 58px; }
.marco__boton--vol-menos { left: -2px; top: 262px; height: 58px; }
.marco__boton--lateral   { right: -2px; top: 216px; height: 92px;
  background: linear-gradient(270deg, #303237, #4a4c52); }

.app {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 45px;
  background-color: var(--papel);
  isolation: isolate;
  transition: background-color var(--d-medio) var(--ease-entrada);

  /* La app es el contenedor de referencia de toda su tipografía fluida.
     Dentro de un marco de 393 px, `vw` mide el viewport del NAVEGADOR (en
     escritorio, 1400 px): cualquier clamp() con vw se dispara al máximo y
     los titulares revientan las tarjetas. Con `cqi` la medida es el ancho
     real de la app, y la misma hoja sirve para el marco y para un iPhone. */
  container-type: inline-size;
  container-name: app;
}


/* ==========================================================================
   2. FONDO: ACUARELA Y GRANO
   ========================================================================== */

.cielo {
  position: absolute;
  inset: 0 0 auto 0;
  /* Llega por debajo de la primera tarjeta a propósito: esa tarjeta es de
     cristal y necesita paisaje detrás para tener algo que refractar. Un
     cristal sobre un fondo plano no se lee como cristal. */
  height: 470px;
  z-index: var(--z-fondo);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--d-medio) var(--ease-entrada);
}

/* Solo asoma en las dos pantallas de resumen: en un listado estorbaría */
.app--con-cielo .cielo { opacity: 1; }

/* Los defs no pintan: solo guardan gradientes, filtros y la máscara. */
.cielo__defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* CADA capa de paralaje es un div con capa de composición propia. Antes el
   `will-change` estaba puesto en los `<g>` del SVG, donde NO sirve de nada:
   un elemento interno de un SVG no se promociona ni en Blink ni en WebKit.
   Así que mover la cordillera —que lleva un `feGaussianBlur` de desviación
   16 y va bajo máscara— recalculaba desenfoque y máscara en cada fotograma
   de scroll. Ese era el tirón de la pantalla de inicio.

   Con el div promovido, el desenfoque se rasteriza UNA vez y el paralaje
   pasa a ser un movimiento de textura en la GPU. */
.cielo__capa {
  position: absolute;
  inset: 0;
  will-change: transform;
}

.cielo__lienzo {
  width: 100%;
  height: 100%;
}

.cielo__ridge--3 { fill: color-mix(in oklab, var(--bruma) 34%, transparent); }
.cielo__ridge--2 { fill: color-mix(in oklab, var(--bruma) 52%, transparent); }
.cielo__ridge--1 { fill: color-mix(in oklab, var(--bruma) 76%, transparent); }
.cielo__bruma    { fill: color-mix(in oklab, var(--lienzo) 72%, transparent); }
.cielo__pino     { fill: color-mix(in oklab, var(--bruma) 96%, var(--tinta) 16%); }
.cielo__aves     { fill: none; stroke: color-mix(in oklab, var(--tinta) 42%, transparent); stroke-width: 1.5; stroke-linecap: round; }

/* El grano ya no es un elemento sino una capa de fondo (ver `--grano` en
   base.css): se pinta en el lienzo y en cada vista, cuesta cero capas de
   composición y no se interpone entre las barras de cristal y su fondo. */


/* ==========================================================================
   3. BARRA DE ESTADO E ISLA DINÁMICA
   ========================================================================== */

.estado {
  position: absolute;
  inset: 0 0 auto 0;
  height: var(--alto-estado);
  z-index: var(--z-estado);
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* El reloj, la isla y los iconos comparten eje óptico, como en iOS: la
     caja de contenido se recorta a la banda exacta de la isla en vez de
     centrarse en toda la barra, que dejaba el reloj 4 px más abajo. */
  padding: var(--isla-top) 30px calc(var(--alto-estado) - var(--isla-top) - var(--isla-alto));
  color: var(--tinta-fuerte);
  pointer-events: none;
}

.estado__hora {
  font-size: 0.9375rem;
  font-weight: 650;
  letter-spacing: 0;
  font-variant-numeric: proportional-nums;
}

.isla {
  position: absolute;
  top: var(--isla-top);
  left: 50%;
  translate: -50% 0;
  width: 124px;
  height: var(--isla-alto);
  border-radius: var(--r-full);
  background: #000;
}

.estado__iconos {
  display: flex;
  align-items: center;
  gap: 6px;
}

.estado__ico { height: 11px; width: auto; }
.estado__ico--bateria { height: 12px; }


/* ==========================================================================
   4. PILA DE VISTAS Y TRANSICIONES
   --------------------------------------------------------------------------
   Dos gramáticas, como en iOS:
     · entre secciones (cajón o ámbito) → fundido corto, sin lateral;
     · a una ficha → push desde la derecha, el padre retrocede y se apaga.
   ========================================================================== */

.lienzo-app {
  position: absolute;
  inset: 0;
  z-index: var(--z-contenido);
  background-color: var(--papel);
  background-image: var(--grano);
  /* Origen por defecto para la hoja: encoge hacia el centro superior, como
     en iOS. El cajón lo cambia a `left center`, que es lo suyo. */
  transform-origin: 50% 0;
  /* Siempre recortado: al desplazarse con el cajón le nacen esquinas
     redondeadas y nada debe asomar por fuera durante el arrastre. */
  overflow: hidden;
  transition:
    transform var(--d-bouncy) var(--muelle-smooth),
    border-radius var(--d-bouncy) var(--muelle-smooth),
    box-shadow var(--d-bouncy) var(--muelle-smooth);
}

/* Con una hoja encima, la app retrocede: el gesto insignia de iOS para
   decir «esto de arriba es lo que manda ahora». Sin esta regla la hoja
   parece pegada sobre una pantalla que sigue estando al frente. */
.lienzo-app--atras {
  transform: scale(0.922) translateY(10px);
  border-radius: var(--r-2xl);
}

/* Con el cajón abierto la app se aparta y encoge, y deja ver lo de detrás */
.lienzo-app--desplazado {
  transform-origin: left center;
  transform: translateX(74%) scale(0.86);
  border-radius: var(--r-2xl);
  overflow: hidden;
  /* En oscuro la sombra parda no separa nada: hace falta un filo de luz */
  box-shadow:
    -1px 0 0 var(--cristal-borde),
    -14px 0 50px -10px rgb(20 17 12 / 0.28);
}

.pila {
  position: absolute;
  inset: 0;
  /* Por encima del cielo, que es hermano suyo dentro del lienzo */
  z-index: 1;
}

.vista {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  /* Fondo ambiental: dos manchas de color enormes y tenues bajo el papel.
     Sin ellas una tarjeta translúcida sobre papel liso es indistinguible
     de una opaca — el cristal necesita variación detrás para existir. */
  background-color: var(--papel);
  background-image:
    radial-gradient(92% 46% at 86% 0%, color-mix(in oklab, var(--sol) 30%, transparent), transparent 64%),
    radial-gradient(86% 42% at 4% 82%, color-mix(in oklab, var(--bruma) 26%, transparent), transparent 62%),
    var(--grano);
}

/* El ámbito tiñe el ambiente: Trabajo amanece cálido, Personal respira verde */
.app[data-ambito="personal"] .vista {
  background-image:
    radial-gradient(92% 46% at 86% 0%, color-mix(in oklab, var(--salvia) 16%, transparent), transparent 64%),
    radial-gradient(86% 42% at 4% 82%, color-mix(in oklab, var(--bruma) 30%, transparent), transparent 62%),
    var(--grano);
}

/* `hidden` pierde contra cualquier `display` de clase: hay que decirlo */
.vista[hidden] { display: none; }

/* Las dos vistas con hero dejan ver la acuarela del amanecer */
.vista[data-hero] {
  background-color: transparent;
  /* Sin grano propio: ya lo pone el lienzo. Con los dos, la textura se
     duplica justo encima de la acuarela y se ve sucia. */
  background-image: none;
}

/* Velo que oscurece la vista que se queda detrás en un push */
.vista::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 50;
  background-color: rgb(20 17 12 / 0.20);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-pagina) var(--ease-pagina);
}

/* La capa de composición se pide SOLO mientras la vista se mueve y se
   suelta al acabar. Puesta en `.vista` a secas estaba en las 44 vistas y de
   forma permanente: mantenía la visible en una textura de 371 × 830 —unos
   11 MB a 3x— que había que rehacer en cada fotograma de scroll. */
.vista--anima {
  transition: transform var(--d-pagina) var(--ease-pagina);
  will-change: transform;
}

.vista--fuera  { transform: translateX(100%); }
.vista--detras { transform: translateX(-24%); }
.vista--detras::after { opacity: 1; }

/* Cruce entre secciones: fundido corto, sin desplazamiento lateral */
.vista--cruce {
  transition:
    opacity 0.26s var(--ease-entrada),
    transform 0.34s var(--muelle-smooth);
}

.vista--cruce-fuera  { opacity: 0; transform: scale(0.985); }
.vista--cruce-dentro { opacity: 0; transform: scale(1.012); }

/* Sombra del borde izquierdo de la ficha que entra: la profundidad de iOS */
/* Cuando la pila se corta y una ficha cambia de contenido SIN moverse —volver
   a un tipo que ya estaba apilado—, hay que decirlo. Sin nada, el contenido
   salta de golpe y se lee como un fallo de pintado, no como una navegación.
   Se anima el lienzo y no la vista entera: la barra no tiene por qué parpadear. */
.vista--cambia .lienzo-scroll {
  animation: fichaCambia var(--d-rapido) var(--ease-entrada);
}

@keyframes fichaCambia {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}

.vista--detalle::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -18px;
  width: 18px;
  background: linear-gradient(90deg, transparent, rgb(20 17 12 / 0.13));
  pointer-events: none;
}


/* ==========================================================================
   5. BARRA DE NAVEGACIÓN
   ========================================================================== */

.navbar {
  /* Respaldo: hasta que el manejador de scroll la escribe, la barra no
     tiene --n y toda la lámina saldría opaca de golpe. */
  --n: 0;
  position: absolute;
  inset: 0 0 auto 0;
  z-index: var(--z-nav);
  height: calc(var(--alto-estado) + var(--alto-nav));
  padding-top: var(--alto-estado);
}

/* El cristal aparece progresivamente según `--n`. El desenfoque solo se
   enciende cuando hay algo que desenfocar (clase `--velada`): en reposo,
   un backdrop-filter activo cuesta una recomposición por frame para nada. */
.navbar__cristal {
  position: absolute;
  inset: 0;
  opacity: var(--n);
  background-color: var(--cristal-fuerte);
  box-shadow:
    inset 0 0.5px 0 var(--cristal-filo),
    0 0.5px 0 var(--linea);
}

.navbar--velada .navbar__cristal {
  -webkit-backdrop-filter: var(--cristal-filtro);
  backdrop-filter: var(--cristal-filtro);
}

.navbar__fila {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-2);
  height: var(--alto-nav);
  padding-inline: var(--margen);
}

.navbar__titulo {
  font-size: var(--ui-body);
  font-weight: 650;
  color: var(--tinta-fuerte);
  /* La columna del medio se ajusta al título: si uno largo no cupiera,
     empujaría los flancos en vez de cortarse. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: var(--n);
  transform: translateY(calc((1 - var(--n)) * 7px));
}

.navbar__titulo--centro {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  /* El título va centrado, así que su borde izquierdo cae en
     50 % − max/2. Con 55 % empezaba en el 22,5 % y se metía debajo del
     botón de atrás, que llega al 42 %. */
  max-width: 40%;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* El espejo exacto del botón de la izquierda, margen negativo incluido:
   con 40 px planos frente a los 34 px reales del botón, el título quedaba
   3 px corrido hacia la izquierda. */
.navbar__hueco { width: 44px; margin-right: -10px; }

/* Dos acciones juntas a la derecha: el margen negativo lo lleva solo la
   última, si no la pareja se despega del borde */
.navbar__par {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}

.navbar__par .icono-btn { margin-right: 0; }
/* -10 y no -8: es el espejo exacto de .icono-btn--izq. Con 8 el icono de
   la campana caía 2 px más adentro que el del menú, y en una barra con el
   logotipo centrado esa asimetría se nota. */
.navbar__par .icono-btn:last-child { margin-right: -10px; }

/* Métrica real de iOS: el chevron mide 22 px, va pegado al texto (gap
   negativo: el trazo deja aire óptico de sobra), el texto es el nombre de
   la pantalla de la que vienes, y el área de toque llega a 44 px de alto
   aunque el botón se vea más bajo. */
.navbar__atras {
  transition:
    opacity var(--d-micro) var(--ease-entrada),
    transform var(--d-snappy) var(--muelle-snappy);
}

/* ==========================================================================
   EL CHROME DE LAS FICHAS · dos cápsulas que flotan
   --------------------------------------------------------------------------
   Una ficha no lleva barra. Lleva dos cápsulas de vidrio de 36 px flotando
   sobre el contenido —el chevron a la izquierda, la acción a la derecha, sin
   una palabra— y entre ellas, nada.

   Lo que pasa al subir el scroll lo gobierna «--n», que el manejador ya
   escribía en la propia barra (app.js, «actualizarScroll»): a la vez aparece
   el título, se materializa la lámina de lado a lado y las cápsulas se
   disuelven dentro de ella. Al final del recorrido la barra es la de toda la
   vida; al principio no existe. Antes «navbar--fija» dejaba el título clavado
   en 1 y esa mitad de la película no se veía nunca.

   La caja de la barra NO cambia de altura a propósito: «altoChrome()» la
   cachea y tres elementos pegajosos anclan su «top» a --alto-nav. Lo que
   encoge es el vidrio, no el sitio que ocupa.
   ========================================================================== */

/* El dedo pasa por el hueco entre cápsulas: si no, los 98 px de arriba de cada
   ficha son una zona muerta donde el scroll no agarra. */
.vista--detalle .navbar { pointer-events: none; }

/* Solo los BOTONES. El título dentro de la lista dejaba una tira central de
   157 px donde el dedo tampoco agarraba el scroll, que es exactamente la zona
   muerta que esta regla venía a quitar.

   Y va por elemento, no por clase. Con la lista cerrada a dos clases, el botón
   «Terminar» de la sesión en vivo —que no es ni un «atrás» ni una acción de
   icono— nacía sin pointer-events y era el único control muerto de toda la
   app: se veía, se leía, y no pasaba nada al pulsarlo. Cualquier botón que
   alguien ponga aquí mañana tiene el mismo derecho a recibir el dedo. */
.vista--detalle .navbar__fila button { pointer-events: auto; }

/* Las dos cápsulas son gemelas: mismo tamaño, mismo vidrio, mismo peso. El
   botón de volver deja de ser un enlace de texto —y con él se va el problema
   de si «Presupuestos» cabe o no al lado del título. */
.vista--detalle .navbar__atras {
  /* z-index propio para que el vidrio de ::before se quede DENTRO del botón y
     no caiga detrás de la lámina grande. Un contexto de apilado a secas no
     estorba al desenfoque; «isolation» sí lo haría. */
  position: relative;
  z-index: 0;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  /* Explícito aunque hoy no haya nada que anular: las dos cápsulas son
     gemelas por diseño y no por casualidad. Devolverle a «.navbar__atras» el
     «margin-left: -10px» de un botón de barra de iOS —que es lo natural—
     desplazaría esta 10 px y rompería la simetría sin avisar. */
  margin: 0;
  border-radius: var(--r-full);
  color: var(--tinta-fuerte);
}

.vista--detalle .navbar__accion {
  position: relative;
  z-index: 0;
  width: 36px;
  height: 36px;
  margin: 0;
}

/* El vidrio mide 36 px; lo que se toca sigue midiendo 44, que es el mínimo
   del HIG. Es la misma regla que ya seguía «.icono-btn»: puede encoger lo que
   se ve, nunca lo que se toca. */
.vista--detalle .navbar__atras::after,
.vista--detalle .navbar__accion::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: inherit;
}

/* El vidrio va en su propia lámina para poder desvanecerlo con --n sin tocar
   el icono, que tiene que seguir leyéndose encima de lo que sea. */
.vista--detalle .navbar__atras::before,
.vista--detalle .navbar__accion::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background-color: var(--cristal-fuerte);
  border: 0.5px solid var(--cristal-borde);
  /* El canto NO puede ser el de siempre. Lo que pasa por debajo de la cápsula
     no es el fondo de la app: son tarjetas, y las tarjetas están hechas del
     mismo material —0,78 de blanco con filo blanco— así que una cápsula con
     el vidrio de la casa sobre una tarjeta es invisible y solo se lee el
     chevron suelto, que es justo lo que había que evitar.
     Un aro de tinta al 9 % lo resuelve en los dos temas a la vez: en claro es
     un canto oscuro sobre blanco, y en oscuro «--tinta» es clara, así que el
     mismo aro sale luminoso sobre la tarjeta oscura. Y la sombra es de verdad,
     no la de reposo: si algo flota, tiene que dar sombra. */
  box-shadow:
    inset 0 0.5px 0 var(--cristal-filo),
    0 0 0 0.5px color-mix(in oklab, var(--tinta) 9%, transparent),
    0 2px 6px color-mix(in oklab, var(--tinta) 10%, transparent);
  -webkit-backdrop-filter: var(--cristal-filtro-corto);
  backdrop-filter: var(--cristal-filtro-corto);
  /* Se disuelve según la lámina grande se materializa. Dos vidrios apilados
     no se pueden desenfocar dos veces, y al final del recorrido el botón
     tiene que quedar igual que el de cualquier sección. */
  opacity: calc(1 - var(--n));
}

/* Con la lámina ya entera, el desenfoque de las cápsulas no pinta nada (su
   opacidad es < 0,02) y cuesta una recomposición por fotograma. Se apaga.
   El vidrio, solo en su momento. */
.vista--detalle .navbar--asentada .navbar__atras::before,
.vista--detalle .navbar--asentada .navbar__accion::before {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.vista--detalle .navbar__atras .ico { width: 20px; height: 20px; }

.vista--detalle .navbar__atras:active {
  opacity: 1;
  transform: scale(0.90);
}

/* El hueco de la derecha, en las fichas que no tienen acción, copia el tamaño
   de la cápsula para que el título siga cayendo en el eje. */
.vista--detalle .navbar__hueco { width: 36px; margin-right: 0; }

/* El buscador es la excepción: no tiene titular grande que se vaya, así que
   su título no tendría de qué materializarse. Se queda encendido. */
.vista--detalle[data-vista="buscar"] .navbar__titulo { opacity: 1; transform: none; }

/* La marca queda centrada entre el botón de menú y el de avisos */
/* Al eje de la pantalla y no al del hueco sobrante. Repartir el espacio
   entre un botón a la izquierda y DOS a la derecha dejaba el logotipo
   24,5 px corrido, y en una barra tan desnuda se nota. Va absoluto, igual
   que el título de las fichas, que tiene el mismo problema y lo resuelve
   así desde el principio. */
.marca {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.marca__logo {
  width: 19px;
  height: 19px;
  fill: var(--tinta-fuerte);
}

.marca__texto {
  font-size: var(--ui-title3);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--tinta-fuerte);
}

.icono-btn {
  position: relative;
  display: grid;
  place-items: center;
  /* 44 px es el mínimo del HIG. El icono sigue midiendo 20; lo que crece es
     el área de toque, que es lo que falla en un dedo. */
  width: 44px;
  height: 44px;
  margin-right: -10px;
  border-radius: var(--r-full);
  color: var(--tinta-fuerte);
  transition: background-color var(--d-micro) var(--ease-entrada),
              transform var(--d-snappy) var(--muelle-snappy);
}

.icono-btn--izq { margin-right: 0; margin-left: -10px; }

.icono-btn:active {
  background-color: color-mix(in oklab, var(--tinta) 8%, transparent);
  transform: scale(0.90);
}

.navbar__accion { color: var(--indigo-vivo); }

.punto-aviso {
  position: absolute;
  top: 8px;
  right: 9px;
  width: 8px;
  height: 8px;
  border-radius: var(--r-full);
  background-color: var(--rojo);
  box-shadow: 0 0 0 2px var(--papel);
}


/* ==========================================================================
   6. SCROLL, TITULAR GRANDE Y TIRAR-PARA-REFRESCAR
   ========================================================================== */

.scroll {
  flex: 1;
  min-height: 0;             /* sin esto el hijo flex no encoge y no hay scroll */
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.scroll::-webkit-scrollbar { display: none; }

.lienzo-scroll {
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
  padding:
    calc(var(--alto-estado) + var(--alto-nav) + var(--e-2))
    var(--margen)
    /* Sitio de sobra para que el orbe nunca tape la última fila */
    calc(var(--alto-barra) + var(--alto-indicador) + 3.75rem);
}

/* Titular grande: la voz serif del proyecto, no la bold de UIKit */
.titular { margin-block: var(--e-2) var(--e-1); }

.titular__texto {
  font-family: var(--font-display);
  font-variation-settings: var(--fraunces);
  font-size: var(--fs-large);
  font-weight: 500;
  line-height: 1.06;
  letter-spacing: var(--tracking-hero);
  color: var(--tinta-fuerte);
}

.titular__pie {
  margin-top: 6px;
  font-size: var(--ui-sub);
}

/* Tirar para refrescar */
.pull {
  position: absolute;
  top: calc(var(--alto-estado) + var(--alto-nav) - 6px);
  left: 50%;
  translate: -50% 0;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  opacity: var(--pull, 0);
  z-index: 5;
  pointer-events: none;
}

.pull__aro {
  width: 20px;
  height: 20px;
  border-radius: var(--r-full);
  border: 2px solid var(--linea);
  border-top-color: var(--salvia);
  transform: rotate(calc(var(--pull, 0) * 320deg));
}

.pull--girando .pull__aro { animation: girar 0.7s linear infinite; }

@keyframes girar { to { transform: rotate(360deg); } }


/* ==========================================================================
   7. CAJÓN LATERAL
   --------------------------------------------------------------------------
   No se superpone: vive detrás y es la app la que se aparta. Por eso el
   gesto se siente físico — mueves una cosa para ver la otra.
   ========================================================================== */

.cajon {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: var(--z-cajon);
  display: flex;
  flex-direction: column;
  width: 74%;
  padding:
    calc(var(--alto-estado) + var(--e-3))
    var(--e-4)
    calc(var(--alto-indicador) + var(--e-4))
    var(--e-5);
  /* Entra con un desfase respecto al lienzo: parece que lo empuja */
  opacity: 0;
  transform: translateX(-10%);
  pointer-events: none;
  transition:
    opacity var(--d-rapido) var(--ease-entrada),
    transform var(--d-bouncy) var(--muelle-smooth);
}

.app--cajon .cajon {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.cajon__cabeza {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  width: calc(100% + 16px);
  margin: 0 -8px var(--e-2);
  padding: 8px;
  border-radius: var(--r-md);
  text-align: left;
  transition: background-color var(--d-micro) var(--ease-entrada);
}

.cajon__cabeza:active { background-color: color-mix(in oklab, var(--tinta) 6%, transparent); }
.cajon__cabeza .ico--chevron { margin-left: auto; }

.cajon__quien {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  font-size: var(--ui-caption);
}

.cajon__quien strong {
  font-size: var(--ui-sub);
  font-weight: 650;
  color: var(--tinta-fuerte);
}

.cajon__etiqueta {
  padding-left: 2px;
  padding-bottom: var(--e-2);
}

.cajon__nav {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}

.cajon__nav::-webkit-scrollbar { display: none; }

.cajon__pie {
  padding-top: var(--e-3);
  border-top: 1px solid var(--linea);
}

/* Las filas del cajón no llevan separador: el ritmo lo da el espacio */
.lista--cajon > li .fila::after { display: none; }

/* El resalte de la fila activa es MÁS ANCHO que su texto. Hacerlo con
   `margin-inline: -8px` en la fila lo recorta contra el `overflow-y: auto`
   del carril (que convierte el eje X en `auto` y lo corta por la
   izquierda). Se invierten los papeles: el acolchado va en el contenedor
   y la fila no lleva margen negativo propio. */
.cajon__nav {
  padding-inline: 8px;
  margin-inline: -8px;
}

.lista--cajon .fila {
  gap: var(--e-3);
  padding: 9px 8px;
  border-radius: var(--r-md);
}

/* Cabecera de grupo del cajón: pegajosa, para que con quince destinos sepas
   siempre en qué bloque estás mientras recorres la lista. */
.cajon__grupo {
  position: sticky;
  top: -1px;
  z-index: 2;
  margin: var(--e-4) -8px 2px;
  padding: 7px 8px 5px;
}

/* El velo NO va en la propia cabecera sino en una lámina detrás, y por dos
   razones. Una: así se puede desvanecer por abajo sin llevarse el texto por
   delante —el corte en seco era lo que la hacía leerse como un recuadro
   pegado encima de la lista y no como parte de ella. Dos: el redondeo de
   arriba la emparenta con las filas del cajón, que son pastillas; una banda
   recta de borde a borde ahí dentro desentona.
   El «z-index: -1» no se escapa hacia atrás porque la cabecera ya abre
   contexto de apilado con su «z-index: 2», y eso —a diferencia de
   «isolation»— no corta el desenfoque de fondo. */
.cajon__grupo::before {
  content: '';
  position: absolute;
  inset: -12px 0 -16px;
  z-index: -1;
  border-radius: var(--r-md) var(--r-md) 0 0;
  background-color: color-mix(in oklab, var(--papel) 78%, transparent);
  /* La falda cae FUERA de la caja: 12 px por arriba, para que no haya
     costura entre este vidrio y el de la barra de navegación, y 16 por
     abajo, para que el contenido no se corte bajo la cabecera sino que se
     evapore. Dentro de su propia caja la máscara es opaca del todo: meter
     el degradado por dentro desvanecía el pie de las letras y, peor, dejaba
     leer nítida la fila que pasaba por debajo. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 12px, #000 calc(100% - 16px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 12px, #000 calc(100% - 16px), transparent 100%);
}

/* En reposo la cabecera es texto limpio: el vidrio solo existe cuando hay
   algo pasando por debajo, y un backdrop-filter encendido para nada cuesta
   una recomposición por fotograma. */
.cajon__grupo.pegada::before {
  -webkit-backdrop-filter: var(--cristal-filtro-corto);
  backdrop-filter: var(--cristal-filtro-corto);
}

/* El filo de medio píxel: el único acuse de recibo de que la cabecera se ha
   quedado clavada. Va en su propio pseudoelemento para que caiga en el borde
   de verdad y no 16 px más abajo, donde acaba la falda. */
.cajon__grupo::after,
.grupo__titulo::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 0.5px;
  background-color: var(--linea);
  opacity: 0;
  transition: opacity var(--d-rapido) var(--ease-entrada);
}

.cajon__grupo.pegada::after,
.grupo__titulo.pegada::after { opacity: 1; }

.cajon__grupo:first-child { margin-top: 0; }

.cajon__grupo h3 {
  font-size: var(--ui-caption);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-etiqueta);
  color: var(--tinta-3);
}

.lista--cajon .fila--activa {
  background-color: color-mix(in oklab, var(--indigo) 10%, transparent);
}

.lista--cajon .fila--activa .fila__titulo { color: var(--indigo); font-weight: 650; }
.lista--cajon .fila--activa .chip { background-color: var(--indigo); color: var(--sobre-color); }

/* Telón invisible: con el cajón abierto, tocar la app la devuelve */
.tapa {
  position: absolute;
  inset: 0;
  z-index: var(--z-tapa);
  background: transparent;
  cursor: pointer;
}

.tapa[hidden] { display: none; }


/* ==========================================================================
   8. BARRA DE ÁMBITOS Y ORBE
   --------------------------------------------------------------------------
   Dos mundos y un botón. La barra no navega entre secciones (de eso se
   encarga el cajón): cambia de ÁMBITO, que es una decisión mayor.
   ========================================================================== */

.barra {
  position: absolute;
  left: var(--margen);
  right: var(--margen);
  bottom: calc(var(--alto-indicador) - 3px);
  z-index: var(--z-barra);
  display: grid;
  grid-template-columns: 1fr calc(var(--orbe) + 18px) 1fr;
  align-items: stretch;
  height: var(--alto-barra);
  padding: 6px;
  border-radius: var(--r-xl);

  /* EL VIDRIO VA AQUÍ, no en el hijo `.barra__cristal`. Un descendiente con
     `z-index: -1` no recibe backdrop en Chromium: el desenfoque se aplica
     sobre vacío y la barra queda como un rectángulo translúcido plano. Y la
     `mask` de abajo convierte además a `.barra` en raíz de backdrop, con lo
     que cualquier hijo se quedaría sin fondo que desenfocar. En el propio
     elemento enmascarado sí funciona, y la máscara recorta también el fondo
     desenfocado, así que la semiluna se conserva. */
  background-color: var(--cristal);
  -webkit-backdrop-filter: var(--cristal-filtro);
  backdrop-filter: var(--cristal-filtro);

  border: 0.5px solid var(--cristal-borde);
  box-shadow:
    inset 0 0.5px 0 var(--cristal-filo),
    var(--sombra-2);
  isolation: isolate;

  /* LA SEMILUNA. No es un aro pintado encima del cristal sino un hueco
     recortado EN el cristal: la lamina de vidrio se abre para dejar pasar
     el orbe, igual que la barra de iOS se abre alrededor de un boton
     elevado. El centro del circulo esta 2 px por encima del borde
     superior de la barra, que es justo donde cae el centro del orbe. */
  -webkit-mask: radial-gradient(circle var(--hueco-orbe) at 50% -2px, transparent 99%, #000 100%);
  mask: radial-gradient(circle var(--hueco-orbe) at 50% -2px, transparent 99%, #000 100%);
}

.barra__cristal {
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
}

/* Reflejo diagonal: una lámina de vidrio no es uniforme, recoge luz arriba */
.barra__cristal::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(152deg, var(--cristal-brillo), transparent 46%);
  pointer-events: none;
}

.barra__op {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-width: 0;
  border-radius: var(--r-lg);
  color: var(--tinta-3);
  font-size: var(--ui-caption2);
  font-weight: 550;
  transition:
    color var(--d-rapido) var(--ease-entrada),
    background-color var(--d-rapido) var(--ease-entrada);
}

.barra__op .ico {
  width: 23px;
  height: 23px;
  transition: transform var(--d-snappy) var(--muelle-snappy);
}

/* La pastilla activa es la misma lámina de vidrio que la barra, teñida de
   acción. El relleno lo pone `--indigo-suave` (claro #e6ecf6 / oscuro
   #1b2536): en oscuro se HUNDE en vez de iluminarse. Aclararla con blancos
   literales la acercaba al color de su propio texto y lo dejaba en 1,4:1. */
.barra__op--activa {
  color: var(--indigo-vivo);
  background-image:
    linear-gradient(180deg, var(--cristal-brillo),
      color-mix(in oklab, var(--cristal-brillo) 30%, transparent)),
    linear-gradient(0deg,
      color-mix(in oklab, var(--indigo-suave) 82%, transparent),
      color-mix(in oklab, var(--indigo-suave) 82%, transparent));
  box-shadow:
    inset 0 0.5px 0 var(--cristal-filo),
    0 1px 3px rgb(20 17 12 / 0.07);
}

.barra__op--activa .ico { transform: translateY(-1px) scale(1.06); }
.barra__op:active .ico  { transform: scale(0.88); }

/* El orbe: sobresale de la barra y lleva su propio halo de luz */
.orbe {
  position: absolute;
  left: 50%;
  /* Sobresale de la barra, encajado en el hueco que ella le abre. Lo que
     antes chirriaba no era que sobresaliera sino el aro de papel opaco
     que llevaba alrededor: eso era una pegatina. El recorte del cristal
     hace el mismo trabajo sin ensuciar nada. */
  bottom: calc(var(--alto-indicador) - 3px + var(--alto-barra) - 30px);
  translate: -50% 0;
  z-index: var(--z-orbe);
  display: grid;
  place-items: center;
  width: var(--orbe);
  height: var(--orbe);
  border-radius: var(--r-full);
  background:
    radial-gradient(125% 118% at 30% 16%,
      color-mix(in oklab, var(--indigo) 46%, white), transparent 62%),
    linear-gradient(180deg, color-mix(in oklab, var(--indigo) 86%, white), var(--indigo) 72%);
  color: var(--sobre-color);
  box-shadow:
    inset 0 1px 1px rgb(255 255 255 / 0.45),
    inset 0 -8px 14px -8px rgb(0 0 0 / 0.38),
    0 3px 10px -3px color-mix(in oklab, var(--indigo) 46%, transparent),
    0 8px 22px -8px color-mix(in oklab, var(--indigo) 34%, transparent);
  transition:
    transform var(--d-bouncy) var(--muelle-bouncy),
    box-shadow var(--d-medio) var(--ease-entrada);
}

/* Hilo de luz de medio píxel siguiendo el canto del recorte: sin él, el
   hueco de la barra termina en un corte romo y se nota que es una máscara. */
.orbe::before {
  content: "";
  position: absolute;
  inset: calc((var(--orbe) - var(--hueco-orbe) * 2) / 2);
  border-radius: 50%;
  border: 0.5px solid var(--cristal-filo);
  pointer-events: none;
  transition: opacity var(--d-rapido) var(--ease-entrada);
}

/* Con el radial abierto la barra está tapada: el hilo que traza su recorte
   se queda sin nada que trazar y se lee como un aro suelto. Fuera. */
.orbe--abierto::before { opacity: 0; }

/* La gota de luz: lo que convierte un círculo plano en un cuerpo con volumen */
.orbe::after {
  content: "";
  position: absolute;
  top: 7px;
  left: 50%;
  width: 26px;
  height: 13px;
  translate: -50% 0;
  border-radius: 50%;
  background: linear-gradient(180deg, rgb(255 255 255 / 0.55), rgb(255 255 255 / 0));
  filter: blur(1.5px);
  pointer-events: none;
}

.orbe__mas {
  width: 25px;
  height: 25px;
  transition: rotate var(--d-bouncy) var(--muelle-bouncy);
}

/* Halo que late una vez al abrir: el acuse de recibo del gesto */
.orbe__halo {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-color: color-mix(in oklab, var(--indigo) 30%, transparent);
  opacity: 0;
  pointer-events: none;
}

.orbe:active { transform: translateY(1px) scale(0.92); }

/* Al abrir, el orbe se levanta fuera de la barra y crece: la prominencia
   se la gana en el momento en que importa, no de forma permanente. */
.orbe--abierto {
  transform: translateY(-14px) scale(1.08);
  box-shadow:
    inset 0 1px 1px rgb(255 255 255 / 0.45),
    inset 0 -8px 14px -8px rgb(0 0 0 / 0.38),
    0 10px 24px -6px color-mix(in oklab, var(--indigo) 55%, transparent),
    0 22px 50px -14px color-mix(in oklab, var(--indigo) 45%, transparent);
}

.orbe--abierto .orbe__mas { rotate: 135deg; }

.orbe--abierto .orbe__halo { animation: halo 0.62s var(--ease-salida); }

@keyframes halo {
  from { opacity: 0.55; transform: scale(1); }
  to   { opacity: 0;    transform: scale(2.1); }
}

/* La portada no es una pantalla de la app: no lleva su chrome */
.app--portada .barra,
.app--portada .orbe { opacity: 0; pointer-events: none; }

.app--portada .barra,
.app--portada .orbe {
  transition: opacity var(--d-rapido) var(--ease-entrada);
}

.indicador {
  position: absolute;
  bottom: 9px;
  left: 50%;
  translate: -50% 0;
  z-index: var(--z-estado);
  width: 140px;
  height: 5px;
  border-radius: var(--r-full);
  background-color: var(--tinta-fuerte);
  opacity: 0.30;
  pointer-events: none;
}


/* ==========================================================================
   9. MENÚ RADIAL DE ESFERAS
   --------------------------------------------------------------------------
   Al pulsar el orbe, cinco esferas se elevan en arco. Cada una parte del
   centro del orbe con escala 0,25 y viaja a su posición con muelle y un
   desfase de 38 ms. Al cerrar, el orden se invierte y va más rápido: en
   iOS todo cierra antes de lo que abre.
   ========================================================================== */

.radial {
  position: absolute;
  inset: 0;
  z-index: var(--z-radial);
}

.radial[hidden] { display: none; }

.radial__telon {
  position: absolute;
  inset: 0;
  width: 100%;
  background-color: color-mix(in oklab, var(--papel) 42%, transparent);
  -webkit-backdrop-filter: blur(26px) saturate(150%);
  backdrop-filter: blur(26px) saturate(150%);
  opacity: 0;
  transition: opacity var(--d-medio) var(--ease-entrada);
  cursor: default;
}

.radial--abierto .radial__telon { opacity: 1; }

/* Foco de luz centrado en el orbe: da a las esferas una fuente lumínica
   comun y convierte cinco circulos sueltos en una composicion. Entra un
   pelo despues que el telon para que se lea como que el boton se enciende. */
.radial__telon::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: calc(var(--alto-indicador) - 3px + var(--alto-barra) - 30px + var(--orbe) / 2);
  width: 460px;
  height: 460px;
  translate: -50% 50%;
  border-radius: 50%;
  background: radial-gradient(circle,
    color-mix(in oklab, var(--sol) 40%, transparent) 0%,
    color-mix(in oklab, var(--sol) 14%, transparent) 38%,
    transparent 68%);
  opacity: 0;
  transition: opacity 0.5s var(--ease-entrada) 0.08s;
  pointer-events: none;
}

.radial--abierto .radial__telon::after { opacity: 1; }

/* Ancla de 0 × 0 en el centro exacto del orbe */
.radial__esferas {
  position: absolute;
  left: 50%;
  /* +14 px: el orbe se levanta esa misma distancia al abrirse, así que el
     arco nace exactamente de donde está el botón en ese momento. */
  bottom: calc(var(--alto-indicador) - 3px + var(--alto-barra) - 30px + var(--orbe) / 2 + 14px);
  width: 0;
  height: 0;
}

.esfera {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  width: 58px;
  /* En reposo: encogida en el centro del orbe */
  transform: translate(-50%, 50%) scale(0.25);
  opacity: 0;
  transition:
    transform 0.26s var(--ease-entrada) calc((4 - var(--i, 0)) * 16ms),
    opacity 0.18s var(--ease-entrada) calc((4 - var(--i, 0)) * 16ms);
}

.radial--abierto .esfera {
  transform: translate(calc(-50% + var(--x)), calc(50% + var(--y))) scale(1);
  opacity: 1;
  transition:
    transform var(--d-bouncy) var(--muelle-bouncy) calc(var(--i, 0) * 38ms),
    opacity 0.24s var(--ease-entrada) calc(var(--i, 0) * 38ms);
}

/* Cristal líquido: fondo translúcido teñido del color de la acción, canto
   especular arriba, sombra interior abajo (el grosor del vidrio) y un halo
   de color proyectado. Las cuatro capas juntas leen como una cuenta de
   vidrio; cualquiera de ellas sola, como un círculo de color. */
.esfera__btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: var(--r-full);
  background:
    radial-gradient(132% 120% at 28% 16%,
      var(--cristal-filo), var(--cristal-brillo) 44%, transparent 74%),
    linear-gradient(180deg,
      color-mix(in oklab, var(--esfera-tono) var(--esfera-mezcla-a), var(--esfera-lamina)),
      color-mix(in oklab, var(--esfera-tono) var(--esfera-mezcla-b), var(--esfera-lamina)));
  -webkit-backdrop-filter: blur(16px) saturate(210%);
  backdrop-filter: blur(16px) saturate(210%);
  border: 0.5px solid var(--cristal-borde);
  box-shadow:
    inset 0 1px 1.5px var(--cristal-filo),
    inset 0 -9px 15px -9px color-mix(in oklab, var(--esfera-tono) 62%, transparent),
    0 10px 24px -8px color-mix(in oklab, var(--esfera-tono) 46%, transparent),
    0 2px 8px rgb(20 17 12 / 0.10);
  transition: transform var(--d-snappy) var(--muelle-snappy);
}

/* El reflejo especular, descentrado: una esfera nunca brilla en el centro */
.esfera__btn::after {
  content: "";
  position: absolute;
  top: 6px;
  left: 12px;
  width: 20px;
  height: 11px;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--cristal-filo), transparent);
  filter: blur(1.2px);
  pointer-events: none;
}

.esfera__btn .ico { width: 23px; height: 23px; position: relative; z-index: 1; }
.esfera__btn:active { transform: scale(0.90); }

/* Cada esfera solo declara SU color: el resto del cristal lo monta la
   regla de arriba a partir de `--esfera-tono`. */
.esfera__btn--salvia { --esfera-tono: var(--salvia);      color: var(--salvia); }
.esfera__btn--indigo { --esfera-tono: var(--indigo-vivo); color: var(--indigo-vivo); }
.esfera__btn--ambar  { --esfera-tono: var(--ambar);       color: var(--ambar); }
.esfera__btn--rojo   { --esfera-tono: var(--rojo);        color: var(--rojo); }
.esfera__btn--rosa   { --esfera-tono: color-mix(in oklab, var(--sol) 62%, var(--rojo));
                       color: color-mix(in oklab, var(--rojo) 74%, var(--tinta)); }
/* Grafito: para la quinta esfera. Rojo y rosa contiguos se leian como el
   mismo boton repetido; el neutro rompe la pareja sin meter otro color. */
.esfera__btn--neutro { --esfera-tono: var(--tinta-2);     color: var(--tinta); }

.esfera__nombre {
  font-size: var(--ui-caption);
  font-weight: 650;
  letter-spacing: -0.005em;
  color: var(--tinta-fuerte);
  text-align: center;
  white-space: nowrap;
  /* Sobre un fondo desenfocado el texto pierde borde: se le devuelve */
  text-shadow: 0 1px 3px color-mix(in oklab, var(--papel) 90%, transparent);
}


/* ==========================================================================
   10. COMPONENTES
   ========================================================================== */

/* ----- Icono base ------------------------------------------------------- */

.ico {
  width: 20px;
  height: 20px;
  flex: none;
  color: inherit;
}

.ico--salvia { color: var(--salvia); }

.ico--chevron {
  width: 15px;
  height: 15px;
  color: var(--tinta-3);
  opacity: 0.75;
}

.ico--abajo { rotate: 90deg; }


/* ----- Tarjeta ------------------------------------------------------------ */

/* TODAS las tarjetas son cristal. Lo que las hace leerse como vidrio no
   es el desenfoque sino la suma de translucidez + canto especular + borde
   de medio píxel. El `backdrop-filter` se reserva a `.tarjeta--cristal`,
   las que flotan sobre la acuarela: desenfocar un degradado liso no
   cambia un píxel de la imagen y cuesta una recomposición por frame. */
.tarjeta {
  position: relative;
  padding: var(--e-4);
  border-radius: var(--r-lg);
  background-color: var(--cristal-fuerte);
  border: 0.5px solid var(--cristal-borde);
  box-shadow:
    inset 0 0.5px 0 var(--cristal-filo),
    var(--sombra-1);
}

/* El reflejo diagonal, en las tarjetas grandes */
.tarjeta::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  background: linear-gradient(158deg, var(--cristal-brillo), transparent 34%);
  pointer-events: none;
}

.tarjeta > * { position: relative; z-index: 1; }

.tarjeta--lista { padding-bottom: var(--e-1); }

/* Tarjeta de cristal: reservada a la primera tarjeta de cada resumen, que
   es la que flota sobre la acuarela. Usarla sobre papel liso no aporta
   nada y cuesta una recomposición del desenfoque en cada scroll. */
.tarjeta--cristal {
  background-color: var(--cristal-fuerte);
  -webkit-backdrop-filter: var(--cristal-filtro);
  backdrop-filter: var(--cristal-filtro);
  border: 0.5px solid var(--cristal-borde);
  box-shadow:
    inset 0 0.5px 0 var(--cristal-filo),
    var(--sombra-2);
}

.tarjeta__cabeza {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--e-3);
  margin-bottom: var(--e-2);
}

.tarjeta__titulo {
  font-size: var(--ui-body);
  font-weight: 650;
  letter-spacing: -0.015em;
  color: var(--tinta-fuerte);
}

.tarjeta__eyebrow {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: var(--e-3);
  font-size: var(--ui-sub);
  font-weight: 550;
  color: var(--tinta-2);
}

.enlace {
  font-size: var(--ui-sub);
  font-weight: 550;
  color: var(--indigo-vivo);
  display: inline-flex;
  align-items: center;
  /* El texto mide 17 px de alto; el área de toque tiene que llegar a 44 sin
     mover la línea base, así que crece por acolchado y se recupera con
     margen negativo. */
  min-height: 44px;
  margin-block: -14px;
  padding-inline: 4px;
  margin-inline: -4px;
  gap: 2px;
  transition: opacity var(--d-micro) var(--ease-entrada);
}

.enlace:active { opacity: 0.45; }


/* ----- Listas y filas ------------------------------------------------------
   Lista agrupada de iOS: el separador NO llega al borde izquierdo, arranca
   donde arranca el texto. Se dibuja con un pseudo-elemento en la fila, no
   con border, para poder sangrarlo. */

.lista { display: flex; flex-direction: column; }

.fila {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--e-3);
  width: 100%;
  min-height: 52px;
  padding: 11px 2px;
  text-align: left;
  color: inherit;
  font-size: var(--ui-sub);
  border-radius: var(--r-sm);
  transition: background-color var(--d-micro) var(--ease-entrada),
              transform var(--d-snappy) var(--muelle-snappy);
}

.lista > li:not(:last-child) .fila::after {
  content: "";
  position: absolute;
  left: calc(34px + var(--e-3));
  right: 0;
  bottom: 0;
  height: 1px;
  background-color: var(--linea-suave);
}

/* Si la fila no lleva chip, el separador arranca del borde del texto */
.lista--desnuda > li:not(:last-child) .fila::after { left: 2px; }

button.fila:active {
  background-color: color-mix(in oklab, var(--tinta) 5%, transparent);
  transform: scale(0.988);
}

.fila--estatica { cursor: default; }

.fila__cuerpo {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1;
  min-width: 0;
}

/* `text-overflow` solo actúa sobre una caja de UNA línea: sin `nowrap` la
   elipsis era inerte y «F-2024-024» se partía por el guion. */
.fila__titulo {
  font-size: var(--ui-sub);
  font-weight: 500;
  color: var(--tinta);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Y los títulos que SON frases (avisos, tarjetas de repaso, resultados de
   búsqueda) no se cortan a una línea: se recortan a dos. */
.lista--frases .fila__titulo,
.lista--tarjetas .fila__titulo {
  white-space: normal;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  line-height: 1.32;
}

.fila__pie {
  font-size: var(--ui-footnote);
  color: var(--tinta-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fila__valor {
  font-size: var(--ui-sub);
  font-weight: 550;
  color: var(--tinta-2);
  white-space: nowrap;
}

.fila__valor--fuerte {
  font-size: var(--ui-body);
  font-weight: 700;
  color: var(--tinta-fuerte);
}

.fila--total { border-top: 1px solid var(--linea-suave); margin-top: 2px; }

.aviso { color: var(--ambar); font-weight: 600; }

.vacio {
  padding: var(--e-5) var(--e-2) var(--e-6);
  text-align: center;
  font-size: var(--ui-sub);
  color: var(--tinta-3);
}

.vacio[hidden] { display: none; }


/* ----- Filtros en carril ---------------------------------------------------- */

.filtros {
  position: sticky;
  top: calc(var(--alto-estado) + var(--alto-nav) - 6px);
  z-index: 7;
  display: flex;
  gap: var(--e-2);
  overflow-x: auto;
  padding-block: 9px;
  /* El carril sangra hasta los bordes: los chips no mueren en el margen */
  margin-inline: calc(var(--margen) * -1);
  padding-inline: var(--margen);
  scrollbar-width: none;
}

.filtros::-webkit-scrollbar { display: none; }

/* El velo del carril solo cuando hace falta: en reposo los chips ya tienen su
   propio vidrio y el fondo es el mismo papel, así que el velo no se veía y el
   desenfoque trabajaba de balde.

   El carril no puede llevar falda como las cabeceras: tiene overflow propio
   —los chips ruedan en horizontal— y eso recorta cualquier pseudoelemento que
   sobre por fuera. Su transición al contenido se hace con una sombra de papel
   difuminada, que no la recorta nadie. */
.filtros.pegada {
  background-color: color-mix(in oklab, var(--papel) 72%, transparent);
  -webkit-backdrop-filter: var(--cristal-filtro-corto);
  backdrop-filter: var(--cristal-filtro-corto);
  box-shadow:
    0 0.5px 0 var(--linea),
    0 10px 14px -4px color-mix(in oklab, var(--papel) 82%, transparent);
}

/* SIN desenfoque propio: el chip vive dentro de `.filtros`, que ya lo lleva,
   y no se puede desenfocar dos veces lo mismo. Eran 31 de los 67 cristales
   del documento, todos dentro del elemento pegajoso —el peor sitio, porque
   su fondo cambia de verdad en cada fotograma de scroll. Se ve idéntico. */
.filtro {
  flex: none;
  padding: 8px 15px;
  border-radius: var(--r-full);
  background-color: var(--cristal);
  border: 0.5px solid var(--cristal-borde);
  box-shadow:
    inset 0 0.5px 0 var(--cristal-filo),
    var(--sombra-1);
  font-size: var(--ui-footnote);
  font-weight: 600;
  color: var(--tinta-2);
  transition:
    background-color var(--d-rapido) var(--ease-entrada),
    color var(--d-rapido) var(--ease-entrada),
    transform var(--d-snappy) var(--muelle-snappy);
}

.filtro[aria-pressed="true"],
.filtro--activo {
  background-color: var(--tinta-fuerte);
  color: var(--papel);
}

.filtro:active { transform: scale(0.94); }


/* ----- Chip de icono -------------------------------------------------------- */

.chip {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 11px;
  background-color: var(--lienzo-3);
  color: var(--tinta-2);
  transition: background-color var(--d-rapido) var(--ease-entrada),
              color var(--d-rapido) var(--ease-entrada);
}

.chip .ico { width: 18px; height: 18px; }

.chip--salvia { background-color: var(--salvia-suave); color: var(--salvia); }
.chip--indigo { background-color: var(--indigo-suave); color: var(--indigo-vivo); }
.chip--ambar  { background-color: var(--ambar-suave);  color: var(--ambar); }
.chip--rojo   { background-color: var(--rojo-suave);   color: var(--rojo); }
.chip--rosa   { background-color: color-mix(in oklab, var(--sol) 40%, var(--lienzo));
                color: color-mix(in oklab, var(--rojo) 78%, var(--tinta)); }
.chip--neutro { background-color: var(--lienzo-3); color: var(--tinta-2); }

.chip--grande { width: 44px; height: 44px; border-radius: 14px; }
.chip--grande .ico { width: 22px; height: 22px; }


/* ----- Control segmentado --------------------------------------------------- */

.segmentado {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 2px;
  padding: 3px;
  border-radius: var(--r-md);
  background-color: color-mix(in oklab, var(--lienzo-3) 78%, transparent);
}

.segmentado--tres { grid-template-columns: repeat(3, 1fr); }

.segmentado__pulgar {
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: calc((100% - 6px) / 2 - 1px);
  border-radius: 13px;
  background-color: var(--lienzo);
  box-shadow: var(--sombra-1);
  transform: translateX(calc(var(--idx, 0) * (100% + 2px)));
  transition: transform var(--d-snappy) var(--muelle-snappy);
}

.segmentado--tres .segmentado__pulgar { width: calc((100% - 6px) / 3 - 1.4px); }

.segmentado__op {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 9px 4px;
  border-radius: 13px;
  font-size: var(--ui-sub);
  font-weight: 550;
  color: var(--tinta-2);
  transition: color var(--d-rapido) var(--ease-entrada),
              transform var(--d-snappy) var(--muelle-snappy);
}

.segmentado__op .ico { width: 18px; height: 18px; }

.segmentado__op[aria-selected="true"],
.segmentado__op[aria-checked="true"] { color: var(--tinta-fuerte); }

.segmentado__op[aria-selected="true"] .ico,
.segmentado__op[aria-checked="true"] .ico { color: var(--salvia); }

.segmentado__op:active { transform: scale(0.955); }


/* ----- Botones -------------------------------------------------------------- */

.boton-circulo {
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  flex: none;
  border-radius: var(--r-full);
  background-color: var(--indigo);
  color: var(--sobre-color);
  box-shadow: 0 4px 14px -3px color-mix(in oklab, var(--indigo) 45%, transparent);
  transition: transform var(--d-snappy) var(--muelle-snappy),
              background-color var(--d-rapido) var(--ease-entrada);
}

.boton-circulo .ico { width: 24px; height: 24px; }
.boton-circulo:active { transform: scale(0.90); }

.boton-circulo--grande { width: 74px; height: 74px; }
.boton-circulo--grande .ico { width: 28px; height: 28px; }

.boton-pildora {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 12px 18px;
  border-radius: var(--r-full);
  font-size: var(--ui-sub);
  font-weight: 600;
  transition: transform var(--d-snappy) var(--muelle-snappy),
              background-color var(--d-rapido) var(--ease-entrada);
}

.boton-pildora .ico { width: 18px; height: 18px; }
.boton-pildora:active { transform: scale(0.955); }

.boton-pildora--primario {
  background-color: var(--indigo);
  color: var(--sobre-color);
  box-shadow: 0 4px 14px -4px color-mix(in oklab, var(--indigo) 45%, transparent);
}

.boton-pildora--fantasma {
  background-color: var(--lienzo-3);
  color: var(--tinta-2);
}


/* ----- Interruptor ---------------------------------------------------------- */

.interruptor {
  position: relative;
  width: 51px;
  height: 31px;
  flex: none;
  border-radius: var(--r-full);
  background-color: var(--lienzo-3);
  transition: background-color var(--d-rapido) var(--ease-entrada);
}

.interruptor__pomo {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 27px;
  height: 27px;
  border-radius: var(--r-full);
  background-color: #fff;
  box-shadow: 0 1px 3px rgb(20 17 12 / 0.22);
  transition: transform var(--d-snappy) var(--muelle-snappy),
              width var(--d-snappy) var(--muelle-snappy);
}

.interruptor--on { background-color: var(--salvia); }
.interruptor--on .interruptor__pomo { transform: translateX(20px); }

/* El pomo se estira un pelo al pulsarlo: el detalle que nadie copia */
.interruptor:active .interruptor__pomo { width: 32px; }
.interruptor--on:active .interruptor__pomo { transform: translateX(15px); }


/* ----- Barra de progreso ------------------------------------------------------ */

.barra-prog {
  height: 7px;
  border-radius: var(--r-full);
  background-color: var(--lienzo-3);
  overflow: hidden;
}

/* `scaleX` y no `width`: animar el ancho maqueta en cada fotograma, y en
   Proyectos son cinco barras a la vez mientras la vista además entra
   deslizándose. `--p` va sin unidad (0.65) porque `scaleX()` no admite
   porcentajes. */
.barra-prog__relleno {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: inherit;
  background-color: var(--salvia);
  transform: scaleX(var(--p, 0));
  transform-origin: left center;
  transition: transform var(--d-gentle) var(--muelle-smooth);
}



/* ----- Anillo de progreso -------------------------------------------------------
   El trazo se dibuja con stroke-dasharray: el perímetro completo como guion
   y el resto como hueco. `--dash` lo calcula el JS con el radio real, así el
   mismo componente sirve a cualquier tamaño. */

.anillo {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);   /* empieza arriba, no a las 3 en punto */
}

.anillo__pista,
.anillo__trazo {
  fill: none;
  stroke-width: 11;
  stroke-linecap: round;
}

.anillo__pista { stroke: var(--lienzo-3); }

.anillo__trazo {
  stroke: var(--salvia);
  stroke-dasharray: var(--dash, 0) var(--resto, 999);
  transition: stroke-dasharray var(--d-gentle) var(--muelle-smooth);
}

.anillo__trazo--indigo { stroke: var(--indigo-vivo); }
.anillo__trazo--ambar  { stroke: var(--ambar); }

.anillo__cifra {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1px;
  font-size: var(--ui-title2);
  font-weight: 650;
  letter-spacing: -0.03em;
  color: var(--tinta-fuerte);
}

.anillo__cifra small {
  font-size: 0.6em;
  font-weight: 550;
  color: var(--tinta-2);
  align-self: center;
  margin-top: 0.35em;
}

.anillo__cifra--medio { font-size: var(--ui-title1); }


/* ----- Sellos y estados --------------------------------------------------------- */

.sello {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px;
  border-radius: var(--r-full);
  font-size: var(--ui-footnote);
  font-weight: 600;
  background-color: var(--lienzo-3);
  color: var(--tinta-2);
  white-space: nowrap;
}

.sello--ambar  { background-color: var(--ambar-suave);  color: var(--ambar); }
.sello--salvia { background-color: var(--salvia-suave); color: var(--salvia); }
.sello--rojo   { background-color: var(--rojo-suave);   color: var(--rojo); }
.sello--indigo { background-color: var(--indigo-suave); color: var(--indigo-vivo); }

/* Para lo que ni está bien ni está mal: un borrador, un rechazo, una pausa.
   Sin este, el sello se quedaba con el fondo por defecto y no decía nada. */
.sello--neutro { background-color: var(--lienzo-3);     color: var(--tinta-2); }

.sello--lienzo {
  flex-direction: column;
  gap: 0;
  padding: 10px 14px;
  border-radius: var(--r-md);
  background-color: var(--lienzo-2);
  text-align: center;
}

.sello--lienzo strong { font-size: var(--ui-body); color: var(--tinta-fuerte); }
.sello--lienzo small  { font-size: var(--ui-caption); color: var(--tinta-3); font-weight: 500; }

/* Estado con punto: el punto lo dibuja un ::before, nunca un carácter */
.estado-punto {
  display: inline-flex;
  /* Con `center`, un estado de dos líneas en columna estrecha («Calidad
     buena» en las minifichas) dejaba el punto flotando en el hueco del
     interlineado. Se ancla al PRIMER renglón. */
  align-items: flex-start;
  gap: 6px;
  font-size: var(--ui-footnote);
  line-height: 1.35;
  color: var(--tinta-2);
}

.estado-punto::before {
  content: "";
  width: 7px;
  height: 7px;
  /* Centrado en la caja de la primera línea: (1.35em − 7px) / 2 */
  margin-top: calc((1.35em - 7px) / 2);
  border-radius: var(--r-full);
  background-color: currentColor;
  flex: none;
}

.estado-punto--vivo  { color: var(--salvia); }
.estado-punto--aviso { color: var(--ambar); }
.estado-punto--alto  { color: var(--rojo); }
.estado-punto--apagado { color: var(--tinta-3); }

.delta {
  display: flex;
  align-items: center;
  /* Los 4 px son SOLO de columna: separan el icono del porcentaje. En fila
     tienen que ser 0, porque un `.tenue` baja a su propia línea de flex y
     ese row-gap se sumaría al interlineado — desnivelaba 4 px las líneas
     base de las tres columnas del trío. */
  column-gap: 4px;
  row-gap: 0;
  flex-wrap: wrap;
  font-size: var(--ui-caption2);
  line-height: 1.35;
  color: var(--tinta-3);
}

/* El matiz («vs. mes pasado») baja a su propia línea: apretado junto al
   porcentaje se parte por donde no debe y deja columnas de tres alturas. */
.delta .tenue { flex-basis: 100%; }

.delta .ico { width: 13px; height: 13px; }
.delta--sube { color: var(--salvia); }
.delta--baja { color: var(--salvia); }
.delta--baja .ico { rotate: 180deg; }
.delta--ojo  { color: var(--ambar); }


/* ----- Monograma ------------------------------------------------------------------ */

.monograma {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 11px;
  background-color: var(--tinta-fuerte);
  color: var(--lienzo);
  font-size: var(--ui-sub);
  font-weight: 700;
}

.monograma--grande {
  width: 52px;
  height: 52px;
  border-radius: 16px;
  font-size: var(--ui-title2);
}

/* Los tres tonos de marca pasan por token: con `#fff` fijo, en oscuro el
   texto caía sobre un salvia claro y dejaba de leerse. */
.monograma--startify { background-color: var(--marca-grafito); color: var(--papel); }
.monograma--technova { background-color: var(--indigo); color: var(--sobre-color); }
.monograma--green    { background-color: var(--salvia); color: var(--sobre-color); }
.monograma--neutro   { background-color: var(--lienzo-3); color: var(--tinta-2); }

/* Tonos genéricos para clientes y leads que no son marcas de la casa */
.monograma--indigo { background-color: var(--indigo);      color: var(--sobre-color); }
.monograma--salvia { background-color: var(--salvia);      color: var(--sobre-color); }
.monograma--ambar  { background-color: var(--ambar);       color: var(--sobre-color); }
.monograma--rosa   { background-color: var(--indigo-vivo); color: var(--sobre-color); }


/* ----- Cronómetro ------------------------------------------------------------------- */

.cronometro {
  font-size: var(--fs-dato);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1.05;
  color: var(--tinta-fuerte);
  font-variant-numeric: tabular-nums;
}

.cronometro--grande { font-size: clamp(1.9rem, 1.50rem + 4cqi, 2.6rem); }


/* En oscuro un separador a 1,11:1 no separa nada y las listas se aplanan en
   un solo bloque gris. El divisor sube al token de línea completo. */
:root[data-tema="oscuro"] .lista > li:not(:last-child) .fila::after,
:root[data-tema="oscuro"] .campo-form + .campo-form::before,
:root[data-tema="oscuro"] .trio__col + .trio__col::before {
  background-color: var(--linea);
}

/* Estos separan con borde, no con fondo: pintarles background les llenaría
   el panel entero. */
:root[data-tema="oscuro"] .hoy__aparte,
:root[data-tema="oscuro"] .fila--total,
:root[data-tema="oscuro"] .cajon__pie {
  border-color: var(--linea);
}


/* ==========================================================================
   11. APARICIONES
   --------------------------------------------------------------------------
   Cada tarjeta entra desde abajo con un desfase de 55 ms por índice. La
   clase `.js` la pone el script: sin JS todo nace visible.
   ========================================================================== */

.js [data-aparece] {
  opacity: 0;
  transform: translateY(14px);
}

.js [data-aparece].visible {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.5s var(--ease-entrada) calc(var(--i, 0) * 55ms),
    transform 0.62s var(--muelle-smooth) calc(var(--i, 0) * 55ms);
}

/* Estado asentado: el contenido ya está donde tiene que estar, pase lo que
   pase con la transición. Un navegador que deja de componer (pestaña en
   segundo plano) congela la transición a medio camino y las tarjetas se
   quedarían translúcidas para siempre. Ningún contenido depende de que
   una animación llegue a su fin. */
.js [data-aparece].asentado {
  opacity: 1;
  transform: none;
  transition: none;
}


/* ==========================================================================
   12. AVISO FLOTANTE
   ========================================================================== */

.aviso-flotante {
  position: absolute;
  left: 50%;
  /* Debajo de la banda del chrome, no encima. Antes caía a 60 px y tapaba de
     borde a borde las dos cápsulas de las fichas —tres vidrios apilados en la
     misma franja— y en las secciones se comía el título de la barra. Y
     «avisar()» se llama desde dentro de las fichas, no solo desde fuera. */
  top: calc(var(--alto-estado) + var(--alto-nav) + 8px);
  z-index: var(--z-aviso);
  display: flex;
  align-items: center;
  gap: 9px;
  max-width: calc(100% - var(--margen) * 2);
  padding: 11px 17px;
  border-radius: var(--r-full);
  background-color: var(--cristal);
  -webkit-backdrop-filter: var(--cristal-filtro);
  backdrop-filter: var(--cristal-filtro);
  border: 0.5px solid var(--cristal-borde);
  box-shadow:
    inset 0 0.5px 0 var(--cristal-filo),
    var(--sombra-2);
  font-size: var(--ui-sub);
  font-weight: 550;
  color: var(--tinta-fuerte);
  translate: -50% 0;
  transform: translateY(-18px) scale(0.94);
  opacity: 0;
  transition: transform var(--d-bouncy) var(--muelle-bouncy),
              opacity var(--d-rapido) var(--ease-entrada);
}

.aviso-flotante[hidden] { display: none; }

.aviso-flotante--visible { transform: translateY(0) scale(1); opacity: 1; }

.aviso-flotante__ico { color: var(--salvia); display: grid; place-items: center; }


/* ==========================================================================
   13. TELÉFONO REAL
   --------------------------------------------------------------------------
   Por debajo de 520 px el escaparate sobra: fuera marco, fuera sombras,
   la app ocupa la pantalla y el chrome respeta las áreas seguras reales.
   ========================================================================== */

@media (max-width: 520px) {

  .escena { padding: 0; background: var(--papel); }

  .escena__ficha { display: none; }

  .marco {
    width: 100%;
    height: 100dvh;
    padding: 0;
    border-radius: 0;
    box-shadow: none;
    background: none;
    transform: none;
  }

  .marco__boton { display: none; }

  .app { border-radius: 0; }

  /* La barra de estado y el indicador los pone el sistema, no nosotros */
  .estado,
  .isla,
  .indicador { display: none; }

  :root {
    --alto-estado: max(env(safe-area-inset-top), 18px);
    --alto-indicador: max(env(safe-area-inset-bottom), 12px);
  }
}


/* ==========================================================================
   14. MOVIMIENTO REDUCIDO
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {

  .vista--anima,
  .vista--cruce { transition: none; }

  .vista--cambia .lienzo-scroll { animation: none; }

  .vista--cruce-fuera,
  .vista--cruce-dentro { opacity: 1; transform: none; }

  /* El paralaje del paisaje se apaga: es el peor ofensor vestibular. Y con
     él se suelta la capa de composición, que sin movimiento solo gasta. */
  .cielo__capa { transform: none !important; will-change: auto; }

  .pull--girando .pull__aro { animation: none; }

  .orbe--abierto .orbe__halo { animation: none; }

  /* Las esferas aparecen ya colocadas, sin arco ni escalonado */
  .esfera { transition-delay: 0ms; }
  .radial--abierto .esfera { transition-delay: 0ms; }
}
