/*
 * AFA Escola El Cim — tokens de identidad visual
 * Fuente unica de verdad del diseno. Lo consumen: PWA del carnet,
 * validador publico y (desde el dia 22) el tema propio de WordPress.
 * Servido en las tres piezas como /shared/css/tokens.css via alias Nginx.
 *
 * Paleta: "el cim" = la cumbre. Azul de montana + naranja de sol.
 * Contrastes: NO se anotan a mano. Los calcula `php bin/contrast.php`, que lee
 * este fichero, resuelve las variables y comprueba cada pareja que se usa de
 * verdad contra WCAG 2.1. Devuelve 1 si alguna incumple, así que se pasa
 * DESPUES de sustituir la paleta y ANTES de desplegar.
 *
 * Lo que hay que saber al cambiar la paleta:
 *  - El par flojo es blanco/naranja: 3.00:1. Sirve para texto GRANDE y nada
 *    mas. "Grande" en WCAG son 24px, o 18.7px si va en negrita — un titular
 *    de 17px en negrita NO cuenta, y es el error facil.
 *  - El par blanco/naranja al reves (naranja sobre blanco) mide igual: el
 *    contraste es simetrico. Da lo mismo cual va de fondo.
 *  - Los tintes 050 son fondos de distintivo con su 600 encima. Van justos:
 *    el verde daba 4.49 contra un minimo de 4.5 y hubo que aclararlo.
 */
:root {
  /* Marca */
  --afa-blau-900:    #10243A;
  --afa-blau-700:    #1B3A5C;
  --afa-blau-500:    #2C5F8D;
  --afa-taronja-500: #E07A2F;
  /*
   * EL TINTE PÀL·LID ÉS EL DEL DISSENY, i abans no ho era. Aquí hi havia
   * `#FDF1E6`, que és nostre de sempre: al handoff de Claude Design NO apareix
   * ni una vegada, i el seu pàl·lid —el de la càpsula de «Gestió» a la barra i
   * el de les seccions actives— és aquest. La diferència és d'un punt per
   * canal i es podria defensar que no es nota; el projecte ja va pagar una
   * vegada per dir això d'un blau que tenia el doble de lluminància, així que
   * va el valor d'ells. De passada millora: 700 a sobre passa de 4,58 a 4,64.
   */
  --afa-taronja-050: #FEF3E2;
  --afa-taronja-200: #F0D7AE;   /* la vora de la càpsula de Gestió */
  /*
   * LOS DOS NARANJAS OSCUROS, y llegan tarde: hasta el 15 de septiembre esta
   * paleta NO tenia ningun naranja que se pudiera usar como TINTA sobre claro.
   * `--afa-taronja-500` sobre crema da 2.83:1 — no llega ni a texto grande — y
   * eso ya habia mordido dos veces: el titulo de la credencial tuvo que subir
   * de cuerpo para acogerse al 3.0 de texto grande, y la etiqueta «Codi ja
   * vençut» no se pudo pintar de naranja.
   *
   * Medidos:
   *   700 sobre crema ............. 4.80:1   (tinta pequeña, AA)
   *   700 sobre taronja-050 ....... 4.58:1   (tinta sobre el tinte)
   *   crema sobre 800 ............. 4.96:1   (fondo grande con texto encima)
   *
   * Y la regla contraintuitiva que hay que recordar: sobre el naranja VIVO el
   * blanco da 3.00:1 y el azul marino da 5.24:1. La tinta sobre naranja vivo
   * es AZUL, no blanca.
   */
  --afa-taronja-700: #A85A00;   /* tinta sobre fondo claro */
  --afa-taronja-300: #E89A3C;   /* antetítulo y codi sobre la tarjeta oscura */  --afa-taronja-800: #B8490A;   /* fondo grande, con crema o blanco encima */
  --afa-crema:       #FBF8F3;

  /*
   * ── LOS GRISES CÁLIDOS DE 2A ─────────────────────────────────────────
   *
   * Nuestros grises son FRÍOS (#C8CDD4, #EDEFF2) y el diseño de Claude Design
   * trabaja sobre una base cálida. No se sustituyen: conviven, porque los
   * fríos siguen sirviendo al validador y a la web.
   *
   * `--afa-calid-600` ES UNA DESVIACIÓN MEDIDA, y hay que decirlo: el diseño
   * usa #8A8578 para las etiquetas inactivas de la barra (3,68:1 sobre blanco)
   * y #A39C8E para el número de versión (2,53:1 sobre la crema). Los dos
   * INCUMPLEN AA a 9,5px, y son texto que hay que leer — la navegación y el
   * número que se dice por teléfono. #767166 es el gris más claro de esa misma
   * familia que llega: 4,86:1 sobre blanco y 4,51:1 sobre crema.
   */
  /*
   * ── LOS VALORES EXACTOS DE CLAUDE DESIGN ─────────────────────────────
   *
   * DECIDÍ REUTILIZAR LOS NUESTROS DICIENDO QUE LA DIFERENCIA ERA
   * IMPERCEPTIBLE, Y NO LO ES. David lo vio poniendo una captura al lado de
   * la otra. Lo peor es el azul de la tarjeta:
   *
   *   --afa-blau-900 #10243A .... luminancia 0,017
   *   --afa-marina   #16385A .... luminancia 0,037   ← el del diseño
   *
   * Más del DOBLE de claro. En una masa del tamaño de la credencial eso no es
   * un matiz: es otra tarjeta. El naranja y la crema son sutiles de uno en uno
   * y se suman.
   *
   * No sustituyen a los nuestros: los de marca siguen sirviendo al validador,
   * a la web y a la zona de gestión. Estos cuatro son los del CARNET.
   */
  --afa-marina:        #16385A;   /* el azul de la credencial */
  --afa-taronja-viu:   #E07B00;   /* el ángulo — más puro que el nuestro */
  --afa-crema-calida:  #FBF6EE;   /* el fondo de la app */
  --afa-verd-valid:    #1E7A4C;   /* la pastilla VÀLID */

  --afa-blau-950:    #0E2740;   /* la cabecera de la zona de gestión */
  --afa-blau-200:    #9FB3C8;   /* etiquetas sobre la tarjeta oscura */
  --afa-calid-100:   #E6DFD3;   /* separadores */
  --afa-calid-200:   #DED7CA;   /* bordes */
  --afa-calid-600:   #767166;   /* texto secundario — desviación medida */

  /*
   * La monoespaciada. Estaba escrita a pelo en cuatro sitios —la versión, el
   * codi, el número de socia y las etiquetas del registro— y las cuatro eran
   * la misma pila. Se usa donde las CIFRAS se alinean o se deletrean en voz
   * alta, no por gusto tipográfico.
   */
  --afa-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --afa-blanc:       #FFFFFF;

  /* Estado del carnet — nunca solo color: van siempre con icono ✓/✗ */
  --afa-verd-600:    #1B7F46;
  /* Verde CLARO, para tinta sobre la credencial marina: el 600 allí da 2,26:1. */
  --afa-verd-300:    #7BD6A3;
  --afa-verd-050:    #EAF7EF;   /* aclarado: con #E8F5ED el par daba 4.49 */
  --afa-vermell-600: #B3261E;

  /*
   * ── LES DUES MARQUES QUE VAN DARRERE DEL QR ──────────────────────────
   *
   * El tick del carnet vigent i la creu del caducat. Les va triar David el 20
   * de setembre de 2026, i els valors NO són decoratius: estan MESURATS.
   *
   * Van dibuixats a sota del codi, a la capa blanca, i el QR els tapa amb els
   * mòduls foscos deixant passar els clars. O sigui que el color d'aquí acaba
   * essent el d'un mòdul CLAR, i si s'enfosqueix, el lector deixa de
   * distingir-lo del fosc que té al costat.
   *
   * Mesurat amb un descodificador de debò i la imatge degradada, el QR pelat
   * aguanta 2,50 / 1,75 / 1,00 de desenfocament a 240 / 180 / 120 px. Amb
   * aquests dos colors se'n perd **un esglaó**, i David ho va acceptar sabent-ho:
   * els que no en costaven cap eren més apagats i no es llegien com un tick.
   *
   * **QUI CANVIÏ AQUESTS DOS VALORS HA DE TORNAR A MESURAR.** Un vermell fosc
   * és el pitjor de tots: el `--afa-vermell-600` d'aquí sobre es menja la
   * MEITAT del marge. Hi ha prova a `bin/proves/carnet.php` que falla si es
   * toquen sense passar pel banc, perquè aquí un error no es veu: el codi se
   * segueix llegint a la pantalla i falla a la càmera d'un comerç.
   *
   * No van a `bin/contrast.php` i tampoc és un descuit: allà es mesuren
   * parelles de TEXT sobre fons, i això no és text ni es llegeix. El seu
   * guardià és el banc de descodificació, no la WCAG.
   */
  --afa-verd-tick:   #00D95F;   /* el tick del carnet vigent */
  --afa-vermell-creu: #FF5A5F;  /* la creu del carnet caducat */
  --afa-vermell-050: #FBEAE9;
  /* La vora del xip d'avís (disseny 3D). El seu tint sol no es distingeix del
     fons del xip; aquesta és la vora que el disseny hi posa. */
  --afa-vermell-200: #EFD3D3;

  /* Neutros */
  /* El negre de la casa. Avui no el demana cap regla —`--afa-text` és
     `--afa-blau-900`— i es queda com a extrem de l'escala: una escala amb
     un forat al final convida a inventar-se un negre. */
  --afa-gris-900: #1A1D21;
  --afa-gris-600: #48505B;
  /* La xifra secundària de les píndoles del Compte (disseny 3B). És el seu
     gris, més clar que el 600, i sobre blanc fa 5,02:1. */
  --afa-gris-500: #67707C;
  --afa-gris-300: #C8CDD4;
  --afa-gris-100: #EDEFF2;

  /* Semanticos */
  --afa-fons:          var(--afa-crema);
  --afa-text:          var(--afa-blau-900);
  --afa-text-suau:     var(--afa-gris-600);
  --afa-primari:       var(--afa-blau-700);
  --afa-primari-text:  var(--afa-blanc);
  --afa-accent:        var(--afa-taronja-500);
  /* LA TINTA SOBRE EL TARONJA ÉS BLAVA, no blanca, i per això té token
     propi encara que avui no el demani cap regla: sobre `--afa-taronja-viu`
     el blanc dona 3,00 i el marí 5,24. El dia que algú escrigui damunt del
     taronja, la resposta ja hi és i no cal tornar-la a mesurar. */
  --afa-accent-text:   var(--afa-blau-900);
  --afa-vora:          var(--afa-gris-300);

  /* Tipografia: pila del sistema. Cero webfonts — en 4G dentro del
     colegio cada peticion cuenta, y el carnet debe pintar al instante. */
  --afa-font: system-ui, -apple-system, "Segoe UI", Roboto,
              "Helvetica Neue", Arial, sans-serif;
  /* Para tablas de datos y registros: las cifras tienen que alinearse en
     columna, y una proporcional no lo hace. */
  --afa-font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --afa-mida-xs:  0.8125rem;
  --afa-mida-s:   0.9375rem;
  --afa-mida-m:   1.0625rem;
  --afa-mida-l:   1.375rem;
  --afa-mida-xl:  1.875rem;
  --afa-mida-xxl: 2.5rem;
  --afa-pes-normal: 400;
  --afa-pes-fort:   600;
  --afa-pes-molt:   800;

  /* Espaciado (escala de 4) */
  --afa-espai-1: 0.25rem;
  --afa-espai-2: 0.5rem;
  --afa-espai-3: 0.75rem;
  --afa-espai-4: 1rem;
  --afa-espai-5: 1.5rem;
  --afa-espai-6: 2rem;
  --afa-espai-7: 3rem;

  /*
   * Capas translúcidas. Viven aquí y no escritas en cada hoja porque llevan
   * DENTRO un color de la paleta: un rgba() suelto por ahí se queda con el
   * azul viejo el día que cambie la paleta, y no se nota hasta que alguien lo
   * mira de cerca. Si se toca --afa-blau-900, hay que tocar --afa-vel.
   *
   * Se escriben en rgba y no con color-mix() a propósito: color-mix pide
   * navegadores recientes y, si no lo entiende, la declaración se cae entera
   * y el velo del diálogo desaparece. Un valor literal funciona en todo.
   */
  --afa-vel:        rgba(16, 36, 58, .6);      /* velo detrás de los diálogos */
  /* El velo CLARO, sobre el fondo de la app: la cobertura de «esperant
     connexió». Lleva dentro --afa-crema-calida (#FBF6EE); si esa cambia, esta
     también. */
  --afa-vel-clar:   rgba(251, 246, 238, .92);
  --afa-realc-clar: rgba(255, 255, 255, .14);  /* realce sobre fondo oscuro */
  --afa-vora-clara: rgba(255, 255, 255, .35);  /* borde sobre fondo oscuro */

  /* Formas y sombras */
  --afa-radi-s: 6px;
  --afa-radi-m: 12px;
  --afa-radi-l: 20px;
  --afa-ombra-1: 0 1px 3px rgba(16,36,58,.12);
  --afa-ombra-2: 0 6px 20px rgba(16,36,58,.16);

  /* Objetivo tactil minimo (accesibilidad) */
  --afa-tap-min: 48px;
}

/*
 * NADA de franjas de color a la izquierda de las cajas.
 *
 * Es un recurso cómodo y por eso está en todas partes, lo que hace que un
 * proyecto parezca hecho con la plantilla de otro. Aquí los estados se marcan
 * de dos maneras propias:
 *
 *  - Los avisos sin leer llevan el TRIÁNGULO del logotipo (la muntanya, el
 *    "cim") delante del título. Es el motivo de la casa, no un adorno
 *    genérico.
 *  - Los mensajes de aviso llevan una MARCA CIRCULAR con el mismo lenguaje
 *    de símbolos que el validador (✓ / ✗ / !), sobre fondo teñido.
 *
 * En los dos casos el color va acompañado de forma y de peso tipográfico, así
 * que siguen funcionando sin distinguir colores.
 */

/*
 * El atributo hidden tiene que ganar SIEMPRE.
 *
 * El navegador lo aplica con una regla propia, [hidden] { display: none }, que
 * pesa menos que cualquier clase. Así que un `display: flex` en una clase lo
 * anula sin avisar: el elemento sigue oculto para los lectores de pantalla
 * pero se ve en pantalla.
 *
 * Es exactamente lo que pasó con las notas: la caja estaba vacía y "oculta",
 * pero .nota { display: flex } la mantenía visible, y como la marca circular
 * es un pseudoelemento, en el móvil aparecía un (!) suelto debajo del carnet.
 *
 * Este es el sitio donde !important es correcto: hidden es una instrucción
 * semántica y ninguna regla de maquetación debería poder contradecirla.
 */
[hidden] { display: none !important; }

/*
 * El carnet se ensena a un comerciante y se escanea con otra camara:
 * el QR tiene que ser negro sobre blanco SIEMPRE. Por eso fijamos el
 * esquema claro y no ofrecemos modo oscuro en la pantalla del carnet;
 * iOS oscurece de oficio si no se declara.
 */
:root { color-scheme: light; }

/* Respeta a quien pide menos movimiento */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/*
 * ── TORNAR, A L'ESTIL DE L'iPHONE ───────────────────────────────────────
 *
 * Cheuró i, al costat, **el nom d'on es torna**. El cheuró sol és el que fa
 * servir iOS i aquí no n'hi ha prou: al projecte una icona mai és l'única
 * senyal, i a més el destí d'aquesta pantalla no és obvi — s'hi arriba des de
 * «La meva família» i des d'enlloc més.
 *
 * NO ÉS EL BOTÓ QUE ES VA TREURE AL MATÍ. Aquell deia «Torna al carnet» a
 * TOTES les pantalles interiors i repetia la primera pestanya de la barra.
 * Aquest puja un nivell d'una jerarquia que la barra no pot recórrer.
 *
 * VIU AQUÍ, al fitxer que carreguen totes les pàgines, perquè el fan servir
 * les DUES zones: la pantalla del codi al carnet i les subpantalles de gestió.
 * A `/gestio/familia` ja n'hi havia un d'escrit a mà —un `←` dins d'un
 * `.boto--text`— i era el començament del mateix problema de sempre: dos
 * controls que fan el mateix amb marcatge i pinta diferents. El pinta
 * `Disseny::enrere()`, que és `<a>` o `<button>` segons calgui.
 *
 * ON FA FALTA I ON NO: fa falta quan el pare NO és a la barra ni a les
 * pestanyes. «Avisos», «Quotes» o «Usos» hi són, així que allà seria repetir
 * el que ja hi ha a un dit del polze.
 */
.enrere {
  display: inline-flex;
  align-items: center;
  gap: var(--afa-espai-1);
  margin-bottom: var(--afa-espai-3);
  padding: var(--afa-espai-2) var(--afa-espai-2) var(--afa-espai-2) 0;
  background: none;
  border: 0;
  font-family: inherit;
  font-size: var(--afa-mida-s);
  font-weight: var(--afa-pes-fort);
  color: var(--afa-primari);
  cursor: pointer;
}

.enrere__fletxa { width: 1.1em; height: 1.1em; flex: none; }

/* ──────────────────────────────────────────────────────────────────────────
 * LA COLUMNA QUE SOSTIENE UNA BARRA INFERIOR
 *
 * Vive AQUÍ, en el único fichero que cargan todas las páginas del proyecto, y
 * no en cada hoja. Estuvo escrita dos veces —una en `app.css` para `.barra` y
 * otra en `gestio.css` para `.g__barra`— y David lo cortó en seco: *«esto me
 * dice que has vuelto a duplicar código y no has tenido la premisa de
 * deduplicación presente»*. Tenía razón: son el mismo componente con dos
 * pieles, y la parte que hay que acertar es justo la compartida.
 *
 * QUÉ RESUELVE, que no es cosmético. En una PWA de iOS una barra
 * `position: fixed; bottom: 0` NO llega al borde físico de la pantalla: se
 * compone contra un viewport que no es el que se ve, y ningún valor de
 * `bottom` lo corrige. La forma que sí funciona —la de Kronos— es que la barra
 * sea el ÚLTIMO ELEMENTO DEL FLUJO dentro de una columna del alto de la
 * pantalla, con `sticky` para que se pegue abajo mientras se recorre una
 * pantalla larga.
 *
 * LAS TRES PIEZAS HACEN FALTA:
 *   .pantalla        la columna, para que una pantalla corta empuje la barra
 *   .pantalla__cos   lo que crece; sin esto la barra queda a media altura
 *   .pantalla__barra `sticky`; sin esto se queda al final de un documento largo
 *
 * Y el relleno inferior del cuerpo pasa a cero: el hueco del indicador de
 * inicio lo pone la barra en su propio relleno, que es donde el color es el
 * suyo. Dejándolo en el cuerpo quedaría una franja del color del fondo POR
 * DEBAJO de la barra.
 *
 * Las hojas de cada zona ponen solo la PIEL —fondo, borde, relleno, rejilla—
 * y ni una propiedad de posición. Hay prueba de eso en bin/proves/disseny.php.
 * ────────────────────────────────────────────────────────────────────────── */
/*
 * EL ANCLA DE ALTURA ES `height: 100%` EN `<html>`, NO UNA UNIDAD DE VIEWPORT.
 *
 * Esto estaba como `min-height: 100dvh` y David lo destapó navegando: la barra
 * quedaba separada del suelo en las pantallas CORTAS —la portada del carnet, el
 * Inici de gestión— y bien en las largas —avisos, quotes, la tabla de
 * famílies—. Ese reparto es el diagnóstico: en una pantalla larga el documento
 * hace scroll y `sticky` pega la barra contra el viewport VISUAL, que es el
 * bueno; en una corta no hay scroll y la barra se queda donde la deja la
 * altura declarada. Si esa altura es menor que la pantalla, la barra flota.
 *
 * Y por eso era errático al abrir la app: depende de cuándo iOS ha terminado
 * de decidir esa medida.
 *
 * `100%` de `<html>` se resuelve contra el bloque contenedor inicial, que es la
 * ventana. Es lo que hace Kronos, que se comporta bien, y yo lo cambié por
 * `dvh` «porque es más simple». Era una desviación y costó esto.
 */
html { height: 100%; }

.pantalla {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  padding-bottom: 0;
}

/*
 * ── `min-width: 0`, Y NO ES UN DETALLE ────────────────────────────────────
 *
 * Un elemento flexible NO se encoge por debajo del ancho mínimo de su
 * contenido: `min-width` vale `auto` por defecto y eso significa «lo que pida
 * lo de dentro». Con una tabla ancha —la de Famílies, la de Diners— el cuerpo
 * se ensanchaba, y con él el `<body>`: la página entera se iba a la derecha
 * arrastrando la cabecera y la barra. Lo vio David deslizando: «se desplaza
 * TODO, barras superiores e inferiores inclusive».
 *
 * Es una regresión de la columna flexible: antes el cuerpo era un bloque y los
 * bloques sí se quedan en su sitio. Con `min-width: 0` el cuerpo vuelve a
 * medir lo que la pantalla, y quien desborda —la caja de la tabla, que ya
 * tiene su `overflow-x: auto`— se desplaza SOLA, por dentro.
 *
 * Lo que NO se puede hacer es poner `overflow-x: hidden` en el cuerpo o en el
 * `<body>`: `position: sticky` deja de funcionar en cuanto un antepasado tiene
 * un `overflow` distinto de `visible`, así que eso arreglaría el arrastre
 * horizontal rompiendo el suelo de la barra.
 */
.pantalla > .pantalla__cos {
  flex: 1 1 auto;
  min-width: 0;
  /*
   * `width: 100%` Y NO CONFIAR EN EL ESTIRAMIENTO. Medido: con solo
   * `min-width: 0` el cuerpo seguía midiendo 894 px dentro de una columna de
   * 375. El motivo es fino y vale la pena escribirlo: en una columna flexible
   * el ancho es el eje TRANSVERSAL, y ahí el elemento se estira solo si no
   * tiene márgenes `auto`. `.g__cos` lleva `margin: 0 auto` para centrarse en
   * escritorio, así que el estiramiento estaba desactivado y el elemento
   * medía su contenido — la tabla entera.
   *
   * Con el ancho declarado, el cuerpo mide lo que la columna y el
   * `max-width` de cada zona sigue mandando donde sobra sitio.
   */
  width: 100%;
}

.pantalla__barra {
  position: sticky;
  bottom: 0;
  z-index: 20;
  /*
   * EL SUELO DE LA BARRA, TAMBIÉN AQUÍ. Estaba escrito igual en las dos hojas:
   * `max()` y NO una suma —sumando, en un iPhone con recorte quedaban 14 + 34
   * = 48 px de hueco muerto bajo las etiquetas— y en su propio longhand, NO
   * dentro del atajo `padding`: si Safari no parsea `max()` con `env()` dentro
   * del atajo descarta las CUATRO medidas y la barra se queda sin suelo.
   *
   * Por eso cada zona pone solo el relleno HORIZONTAL, con `padding-inline`:
   * un `padding` de atajo en la hoja de la zona —que se carga después— se
   * llevaría por delante esta línea sin que nadie lo notara.
   */
  padding-top: 9px;
  padding-bottom: 14px;
  padding-bottom: max(14px, env(safe-area-inset-bottom, 0px));
}

/* ──────────────────────────────────────────────────────────────────────────
 * LA PÍNDOLA D'UN FULL — una sola declaració, dos noms
 *
 * El «Compte» del carnet i el full de cada pestanya de Gestió són el mateix
 * moviment i el mateix objecte: una fulla que puja des de la barra amb les
 * seves opcions en píndoles blanques. La pell era IDÈNTICA escrita a
 * `app.css` i a `gestio.css`… tret de l'ombra, que només tenia una. El
 * resultat: les de Gestió es llegien planes contra el blanc del full, i David
 * ho va dir —*«necesitan más contraste respecto de lo que tienen detrás»*—.
 *
 * Les diferències reals de cada zona (l'espai, el cos de lletra, la icona i
 * la xifra del carnet) es queden a la seva hoja. El que és igual, aquí.
 *
 * La vora puja de `--afa-calid-100` a `--afa-calid-200`: la píndola és blanca
 * damunt d'un full blanc, així que la vora és l'ÚNICA cosa que en diu on
 * comença i on acaba. L'ombra sola no dibuixa el costat de dalt.
 * ────────────────────────────────────────────────────────────────────────── */
.menu__opcio,
.g__full-opcio {
  background: var(--afa-blanc);
  border: 1px solid var(--afa-calid-200);
  border-radius: 999px;
  box-shadow: 0 6px 16px rgba(20, 33, 46, .09);
  color: var(--afa-text);
  font-weight: var(--afa-pes-fort);
  text-align: left;
  text-decoration: none;
}

/*
 * SE ACABA EL REBOTE ELÁSTICO.
 *
 * David, con el 14 Pro Max: «al deslizar el dedo hacia la parte superior el
 * contenido pasa por debajo de la hora, la cobertura, el wifi y la batería».
 * Eso es el rebote de iOS: la página no está haciendo scroll —ya está arriba
 * del todo— sino estirándose por encima de su propio borde, y ahí arriba no
 * hay nada que la aparte del reloj.
 *
 * En los DOS elementos a propósito: unos navegadores leen la propiedad del
 * `<html>` para el viewport y otros la propagan desde el `<body>`. Poniéndola
 * en ambos no hay que acertar con cuál.
 *
 * Lo que se pierde es el «tirar para recargar», que en una PWA instalada no
 * existe, y la sensación de goma.
 */
html, body { overscroll-behavior: none; }

/*
 * ── EL RECORTE DE LA PANTALLA, PARA TODAS LAS PÁGINAS ─────────────────────
 *
 * Estaba SOLO en `app.css`, o sea solo en la shell del carnet. Consecuencia
 * medida en el iPhone de David: la cabecera de la zona de gestión se dibujaba
 * POR DEBAJO del reloj y de la batería —«Zona de gestió» encima de «21:53»— y
 * lo mismo les pasaba a `/registre`, `/codis` y `/clau`.
 *
 * Es el mismo fallo de siempre: una regla estructural escrita en la hoja de
 * UNA zona. Vive aquí, que es el fichero que cargan todas.
 *
 * El relleno de abajo lo quita `.pantalla`: donde hay barra inferior, el hueco
 * del indicador de inicio lo pone ella en su propio relleno, que es donde el
 * color es el suyo.
 */
body {
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
}


/* ═══════════════════════════════════════════════════════════════════════════
 * LA CASELLA D'UN FORMULARI — la comparteixen el panell i el convit
 *
 * Vivia a `gestio.css` i el 30 de setembre va aparèixer la segona: el comerç
 * que accepta l'acord de col·laboració marca una casella igual, i aquella
 * pàgina carrega `app.css`, no `gestio.css`. Copiar-la hauria repetit la part
 * delicada —la retícula de dues columnes— i el dia que una es toqués, l'altra
 * es quedaria enrere.
 *
 * `.camp` és una COLUMNA: etiqueta a dalt, camp a sota. Una casella és una
 * FILA: quadre a l'esquerra i text a la dreta, amb l'ajuda per sota alineada
 * amb el text i no amb el quadre. Per això és un modificador i no una classe
 * nova: segueix sent un camp d'un formulari.
 *
 * El quadre fa 20px i l'àrea que es prem és tota l'etiqueta, que passa de
 * sobres dels 24px que demana WCAG 2.5.8.
 * ═══════════════════════════════════════════════════════════════════════════ */

/*
 * `.camp.camp--casella` I NO `.camp--casella` A SEQUES, i la cosa val per a
 * qualsevol regla que aquest full vulgui compartir.
 *
 * `tokens.css` es carrega PRIMER i `app.css` i `gestio.css` després. Totes
 * dues declaren `.camp { display: block }`, que pesa exactament el mateix
 * (0,1,0) i va després: guanya. El resultat va ser una casella amb el quadre
 * a sobre del text en comptes d'al costat, i sense cap error enlloc.
 *
 * Amb les dues classes (0,2,0) la regla compartida guanya allà on es faci
 * servir, que és el que ha de passar quan el full de baix és el que defineix
 * el component.
 */
.camp.camp--casella {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--afa-espai-2);
  row-gap: var(--afa-espai-1);
  align-items: center;
  cursor: pointer;
}

.camp--casella input[type="checkbox"] {
  width: 20px;
  height: 20px;
  margin: 0;
  accent-color: var(--afa-blau-700);
  cursor: pointer;
}

/* L'etiqueta d'una casella no va en versaletes: aquí no encapçala un camp,
   és la frase que es llegeix al costat del quadre. */
.camp--casella .camp__etiqueta {
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--afa-mida-s);
  color: var(--afa-blau-900);
}

/* L'ajuda d'un camp, sota l'etiqueta i sense competir-hi. Dins d'una casella
   salta la columna del quadre i s'alinea amb el text. */
.camp__pista {
  display: block;
  margin-top: var(--afa-espai-1);
  font-size: var(--afa-mida-xs);
  color: var(--afa-text-suau);
}

.camp--casella .camp__pista { grid-column: 2; }
