/**
 * The document surface: the management desktop. docs/07-diseno.md section 6.
 *
 * The desktop does not inherit the apparatus, it INVERTS it -- and inverts it
 * literally, with the mural's own two colours exchanged. Nothing here introduces a
 * ground, a radius, a shadow or a hue that the mural does not already have, with
 * the single exception of the secondary ink.
 *
 * The rule does all the structural work, exactly as it does on the mural. There
 * are no cards, no zebra striping, no cell borders and no boxes around fields:
 * a second ground would be ambience, and this direction has one ground.
 */

.gestio {
  min-height: 100dvh;
  background: var(--doc-fons);
  color: var(--doc-tinta);
  display: grid;
  grid-template-rows: auto auto 1fr;
  padding: 40px 24px;
  gap: 32px;
}

@media (min-width: 900px) {
  .gestio { padding: 56px 80px; }
}

/* --- The head: who is in, and the way out ------------------------------------ */

.gestio__cap {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.gestio__titol {
  margin: 0;
  font-size: var(--mida-36);
  font-weight: 550;
  letter-spacing: -0.01em;
}

.gestio__qui {
  margin: 0;
  font-size: var(--mida-14);
  color: var(--doc-tinta-suau);
}

/* --- Tabs. Four names on a line, a rule under the active one, no boxes ------- */

.pestanyes {
  display: flex;
  gap: 32px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--doc-filet);
}

.pestanya {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;               /* the active rule sits ON the table's rule */
  padding: 0 0 12px;
  font: inherit;
  font-size: var(--mida-18);
  color: var(--doc-tinta-suau);
  cursor: pointer;
  min-height: 44px;
}

.pestanya[aria-selected="true"] {
  color: var(--doc-tinta);
  font-weight: 550;
  border-bottom-color: var(--doc-tinta);
}

.pestanya:focus-visible {
  outline: 2px solid var(--doc-tinta);
  outline-offset: 4px;
}

/* --- The body ---------------------------------------------------------------- */

.gestio__cos { align-content: start; }

.gestio h2 {
  margin: 0 0 8px;
  font-size: var(--mida-21);
  font-weight: 550;
}

.gestio p { margin: 0 0 16px; max-width: 62ch; line-height: 1.5; }

.suau { color: var(--doc-tinta-suau); }

.buit--doc {
  color: var(--doc-tinta-suau);
  font-size: var(--mida-18);
  padding: 24px 0;
}

/* --- The table. Rule per row, and nothing else ------------------------------- */

.taula {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--mida-16);
  font-variant-numeric: tabular-nums;
}

.taula th,
.taula td {
  text-align: left;
  padding: 14px 16px 14px 0;
  border-bottom: 1px solid var(--doc-filet);
  vertical-align: baseline;
}

.taula th {
  font-weight: 550;
  font-size: var(--mida-14);
  color: var(--doc-tinta-suau);
}

/* Y SE ESCONDE EL TEXTO, NUNCA LA CELDA. `.nomes-veu` es `position: absolute`, asi que puesta
 * sobre el `<th>` lo saca de la fila: la cabecera se queda con tres celdas, las filas tienen
 * cuatro, y EL FILETE DE LA CABECERA ACABA DONDE EMPIEZA LA COLUMNA DE BOTONES. Se vio el 15 de
 * septiembre de 2026 en una captura del panel, no en una prueba: ningun auditor de
 * accesibilidad lo mira —esconder bien un texto no es una violacion— y a la vista es una linea
 * que se corta sin motivo. El `<th>` se queda, y dentro va un `<span class="nomes-veu">`.
 *
 * A header that is not drawn but is still said. The actions column needs a name for
   anybody reading with a screen reader -- and drawing "Accions" over a column of
   buttons is telling the reader what they can already see. */
.nomes-veu {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* Figures right, so a column of hours can be compared without reading it. */
.taula .xifra { text-align: right; padding-right: 0; }

/* A superseded or voided row is told apart by weight and by WORD, never by hue. */
.taula tr.antiga td { color: var(--doc-tinta-suau); }

.marca {
  font-size: var(--mida-12);
  color: var(--doc-tinta-suau);
  white-space: nowrap;
}

.taula__envolt { overflow-x: auto; }

/* --- Buttons. The mural's secondary, on the other ground --------------------- */

.accio {
  appearance: none;
  background: none;
  border: 1px solid var(--doc-tinta);
  border-radius: var(--radi);
  padding: 12px 20px;
  min-height: 44px;
  font: inherit;
  font-size: var(--mida-16);
  color: var(--doc-tinta);
  cursor: pointer;
}

.accio:hover { background: var(--doc-tinta); color: var(--doc-fons); }
.accio:focus-visible { outline: 2px solid var(--doc-tinta); outline-offset: 3px; }
.accio[disabled] { color: var(--doc-tinta-suau); border-color: var(--doc-filet); cursor: default; }
.accio[disabled]:hover { background: none; color: var(--doc-tinta-suau); }

.accio--discreta { border-color: var(--doc-filet); }

/* --- Fields. The vocabulary of `.codi` extended: a line, never a box --------- */

.camp { display: grid; gap: 6px; margin-bottom: 20px; max-width: 32rem; }

/* The label sits ABOVE the field, never inside it: a placeholder doing a label's work
   disappears exactly when it is needed. 6.5. `.tria` is excluded because it is not a
   label, it is the rule and the arrow wrapped around a select. */
.camp__nom,
.camp > span:not(.tria) {
  font-size: var(--mida-14);
  color: var(--doc-tinta-suau);
}

.camp input,
.camp select,
.camp textarea {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--doc-filet);
  border-radius: 0;
  padding: 10px 0;
  min-height: 44px;
  font: inherit;
  font-size: var(--mida-18);
  color: var(--doc-tinta);
}

.camp input:focus,
.camp select:focus,
.camp textarea:focus {
  outline: none;
  border-bottom-width: 2px;
  border-bottom-color: var(--doc-tinta);
  padding-bottom: 9px;               /* the line thickens inwards, nothing moves */
}

/* --- A block that needs saying, without becoming a card ---------------------- */

.avis--doc {
  border-top: 2px solid var(--doc-tinta);
  padding-top: 16px;
  margin-bottom: 32px;
  max-width: 62ch;
}

.avis--doc h2 { margin-bottom: 4px; }

/* --- Rows in the queue of things to look at ---------------------------------- */

.cosa {
  display: grid;
  gap: 8px;
  padding: 20px 0;
  border-bottom: 1px solid var(--doc-filet);
}

.cosa__que { font-size: var(--mida-18); max-width: 62ch; line-height: 1.45; }
.cosa__accions { display: flex; gap: 12px; flex-wrap: wrap; }

/* --- The dropdown: the same line, with the arrow drawn in it ------------------
   6.5 refuses the system box, not the element. `appearance: none` takes the box away
   and leaves the keyboard, the screen reader and the touch picker where they were --
   all three of which a listbox of our own would have had to rebuild, and would have
   rebuilt worse on the one surface in this product that is audited at AAA. */

.tria { position: relative; display: block; }

.tria select {
  appearance: none;
  width: 100%;
  padding-right: 28px;             /* room for the arrow, which is not a glyph */
  cursor: pointer;
}

/* Two strokes meeting, in the weight of the rule under the field. No character, no
   image, no font: the same trick the keypad's delete icon uses. */
.tria::after {
  content: "";
  position: absolute;
  right: 6px;
  top: 50%;
  width: 9px; height: 9px;
  margin-top: -7px;
  border-right: 2px solid var(--doc-tinta-suau);
  border-bottom: 2px solid var(--doc-tinta-suau);
  transform: rotate(45deg);
  pointer-events: none;
}

.tria:focus-within::after { border-color: var(--doc-tinta); }

/* --- The dialog. One surface: nothing in management is a browser box --------- */

.dialeg {
  border: 0;
  border-top: 2px solid var(--doc-tinta);   /* the filet again, doing the same job */
  border-radius: 0;
  padding: 0;
  max-width: 34rem;
  width: calc(100% - 32px);
  background: var(--doc-fons);
  color: var(--doc-tinta);
  /* The browser paints a field's own selection and its date picker in the SYSTEM accent,
     which on this surface is a colour the product does not own -- and 6.3 says there is
     no third hue here. This hands it our ink instead of hiding the control. */
  accent-color: var(--doc-tinta);
}

/* The date field's picker button is the system's, drawn in its own near-black. Muted to
   the secondary ink so it reads as part of the rule and not as a badge on top of it. */
.dialeg input::-webkit-calendar-picker-indicator {
  opacity: 0.55;
  cursor: pointer;
}

.dialeg input:focus::-webkit-calendar-picker-indicator { opacity: 1; }

.dialeg::backdrop { background: rgb(39 44 48 / 0.55); }

.dialeg__cos { padding: 32px 28px 28px; }

.dialeg__titol {
  margin: 0 0 8px;
  font-size: var(--mida-24);
  font-weight: 550;
  letter-spacing: -0.01em;
}

.dialeg__diu {
  margin: 0 0 24px;
  max-width: 48ch;
  line-height: 1.45;
  color: var(--doc-tinta-suau);
}

/* Said in the main ink and with a rule of its own: an error that whispers in a lighter
   grey is an error people scroll past. No red -- 6.3, there is no red on this surface. */
.dialeg__falta {
  margin: 0 0 20px;
  padding-left: 12px;
  border-left: 2px solid var(--doc-tinta);
  max-width: 48ch;
  line-height: 1.45;
}

.dialeg__accions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0;
}

/* --- What a field says when it is not there ---------------------------------
   A box that vanishes with no explanation reads as a fault. This takes its place and
   carries the reason, in the same ink as the rest: the notes field is gone from a sick
   leave because it is an art. 9 health datum, and saying so is cheaper than a support
   call about a field that "sometimes is not there". */
.dialeg__enlloc {
  padding-left: 12px;
  border-left: 2px solid var(--doc-filet);
  max-width: 48ch;
  line-height: 1.45;
  color: var(--doc-tinta-suau);
}

/* --- What is left of each permit, before anything is typed ------------------ */

.topes { margin-bottom: 32px; max-width: 42rem; }

.topes__nom {
  margin: 0 0 8px;
  font-size: var(--mida-14);
  font-weight: 550;
  color: var(--doc-tinta-suau);
}

.tope {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  margin: 0;
  padding: 10px 0;
  border-bottom: 1px solid var(--doc-filet);
  color: var(--doc-tinta-suau);
}

/* Nothing left is said with WEIGHT and the main ink, never with a hue: this surface has
   no red (6.3), and a permit that is used up is a fact rather than an alarm. */
.tope--esgotat { color: var(--doc-tinta); font-weight: 550; }

.tope__quant { font-variant-numeric: tabular-nums; text-align: right; }

/* The nesting, when it changes the answer. Indented under its permit because it is a
   qualification of that line and not a line of its own. */
.tope__dins {
  margin: -1px 0 0;
  padding: 8px 0 10px 16px;
  border-bottom: 1px solid var(--doc-filet);
  font-size: var(--mida-14);
  color: var(--doc-tinta-suau);
  max-width: 48ch;
}

/* The actions never crowd the figure to their left: a number touching a button reads as
   clipped, which is how it looked the first time this was rendered. */
.taula__accions {
  padding-left: 24px !important;
  white-space: nowrap;
  text-align: right;
}

/* --- Filters above the month ------------------------------------------------- */

.filtres { display: flex; gap: 32px; flex-wrap: wrap; align-items: flex-end; }
.filtres .camp { margin-bottom: 20px; max-width: 20rem; }

/* --- Why a row says what it says ---------------------------------------------
   No red, no badge, no alarm mark: section 6.3 says there is no red on this surface, and
   an ambiguous link is not an error. It gets the same ink and the same rule as everything
   else, because anything that looked like a fault would be read as one. */

.perque {
  padding: 4px 0 16px 20px;
  border-left: 2px solid var(--doc-filet);
  max-width: 62ch;
}

.perque__pas + .perque__pas { margin-top: 16px; }

.perque__diu { margin: 0; line-height: 1.5; }

/* The open case. Weight, not hue: this is the system declining to choose, said as the
   promise it is rather than as the failure it is not. */
.perque__obert {
  margin: 8px 0 0;
  font-weight: 550;
  line-height: 1.5;
}

/* Said once under the table, never per row: a repeated explanation starts to sound like
   an excuse. */
.regla--doc {
  margin: 32px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--doc-filet);
  max-width: 62ch;
  font-size: var(--mida-14);
  line-height: 1.5;
  color: var(--doc-tinta-suau);
}

/* --- The findings, listed ----------------------------------------------------
   A count without a list is a dead end the moment it passes one. No bullets and no
   indent borrowed from a document: a rule each, like every other list of records on
   this surface. */
.troballes {
  list-style: none;
  margin: 12px 0 20px;
  padding: 0;
  max-width: 62ch;
}

.troballes:empty { margin: 0; }

.troballes li {
  padding: 10px 0;
  border-bottom: 1px solid var(--doc-filet);
  line-height: 1.45;
}

/* --- El resumen: tres niveles y un solo gesto. docs/07-diseno.md 7.7 y 8.5 -------------
 *
 * NINGÚN FILETE POR FILA. El filete separa grupos, no filas -- una regla debajo de cada
 * línea es una tabla, y una tabla es justo lo que esta pantalla no puede ser. Solo arriba
 * y abajo del bloque.
 *
 * Una columna hasta ocho personas y dos a partir de nueve, que es la regla que el
 * escritorio ya usa desde la fase 5: guiado por el contenido. Y en orden de COLUMNA, no de
 * fila, o la lista ordenada se lee en zigzag. */

.resum__cap {
  margin: 0 0 10px;
  font-size: var(--mida-16);
  color: var(--doc-tinta-suau);
}

.resum__orfes {
  margin: 0 0 12px;
  font-size: var(--mida-16);
  font-weight: 550;
  color: var(--doc-tinta);
}

.resum {
  border-top: 1px solid var(--doc-filet);
  border-bottom: 1px solid var(--doc-filet);
  padding: 3px 0;
}

/* DOS COLUMNAS SON DOS LISTAS. Con un grid de `auto-flow: column` el panel desplegado no
   tiene dónde ir: se colocaba en la primera fila y empujaba la lista entera, y con las
   filas declaradas el navegador abría una tercera columna. Se vio al abrir un día en la
   pantalla de verdad, no en la maqueta -- la maqueta no desplegaba nada.

   Partida en dos mitades, cada detalle se abre dentro de su columna y no mueve la otra. */
@media (min-width: 1100px) {
  .resum--dues { display: grid; grid-template-columns: 1fr 1fr; gap: 0 48px; }
}
.resum__meitat { min-width: 0; }

.linia {
  display: grid;
  grid-template-columns: 92px 16px minmax(0, auto) minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0 8px;
  width: 100%;
  padding: 5px 0;
  text-align: left;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

/* La cifra manda: es el dato. El nombre es la etiqueta y se le nota. */
.linia__xifra {
  font-size: var(--mida-24);
  font-weight: var(--hora-pes);
  color: var(--doc-tinta);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  text-align: right;
  line-height: 1.05;
}

/* La unidad va FUERA de la celda de la cifra. Dentro, lo que se alinea es la «h» y no el
   número, y las cifras tabulares de IBM Plex -- que son el motivo por el que se eligió --
   quedan desperdiciadas. */
.linia__u { font-size: var(--mida-14); color: var(--doc-tinta-suau); line-height: 1.05; }

.linia__qui {
  font-size: var(--mida-16);
  color: var(--doc-tinta);
  line-height: 1.05;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* La incidencia, sin color y sin insignia: lo hace el peso, como los estados degradados
   del mural. Y va junto al nombre, que es donde viven las palabras. */
/* En su propia celda, y esta NO se recorta: el nombre puede perder la última palabra y
   seguir siendo el nombre; «2 correccions per confirmar» recortado deja de ser nada. */
.linia__marca {
  font-size: var(--mida-16);
  font-weight: 550;
  color: var(--doc-tinta);
  line-height: 1.05;
  white-space: nowrap;
}
.linia__marca:not(:empty)::before { content: '· '; font-weight: 400; }

.linia__contra {
  font-size: var(--mida-14);
  color: var(--doc-tinta-suau);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}

.linia[aria-expanded="true"] .linia__qui { font-weight: 550; }

/* Lo que llega. El CONTENEDOR no se anima: aparece a su tamaño y lo de dentro entra con
   opacidad y seis píxeles. Animar la altura enseña el texto a trozos -- se vio en la tira
   de fotogramas de docs/07 8.4 -- y además es lo más caro que hay. */
/* El detalle vive DENTRO de su columna, así que no puede permitirse la sangría de una
   pantalla entera: con 108 px de sangría y el día a 16 px, «08:00–13:00 · 15:00–18:00» se
   partía en dos líneas y cada fichaje ocupaba el doble. Se vio abriendo un día, no
   leyendo el CSS. */
.nivell { padding: 2px 0 12px 24px; }
.nivell > * { animation: arriba var(--durada-arriba) var(--corba-arriba) both; }
@keyframes arriba {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.dia {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0 14px;
  width: 100%;
  padding: 3px 0;
  text-align: left;
  background: none;
  border: 0;
  font: inherit;
  color: var(--doc-tinta);
  font-size: var(--mida-14);
  line-height: 1.3;
  cursor: pointer;
}
.dia__data { white-space: nowrap; }
.dia__hores {
  color: var(--doc-tinta-suau);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dia__total { font-weight: 550; font-variant-numeric: tabular-nums; white-space: nowrap; }

.fitxatge {
  display: grid;
  grid-template-columns: 52px 68px minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0 12px;
  margin: 0;
  padding: 1px 0;
  font-size: var(--mida-14);
  line-height: 1.3;
  color: var(--doc-tinta-suau);
}
.fitxatge__marca { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fitxatge__hora { font-variant-numeric: tabular-nums; color: var(--doc-tinta); }
.fitxatge.antiga .fitxatge__hora { text-decoration: line-through; }

/* El tercer nivel es una lista de horas, no una tabla de botones: la acción va en el peso
   del texto y no en una caja. Una caja por fichaje convierte un día partido en cuatro
   rectángulos, y eso ya lo decidió la fase 4 para el teclado. */
.fitxatge .accio {
  min-height: 0;
  white-space: nowrap;
  padding: 0;
  font-size: var(--mida-14);
  border: 0;
  background: none;
  text-decoration: underline;
  text-underline-offset: 3px;
  color: var(--doc-tinta-suau);
  cursor: pointer;
}
.fitxatge .accio:hover { color: var(--doc-tinta); }

/* ═══════════════════════════════════════════════════════════════════════════════════════
   DIRECCIÓN C — «EL DOSSIER». docs/07-diseno.md §10.2, elegida en §11.3 el 15/09/2026.

   La página es la única superficie. Lo que jerarquiza es la MEDIDA, la ESCALA y el FILETE,
   no un plano nuevo ni un color nuevo. Aquí no entra ni un token de color.

   TODO LO NUEVO LLEVA PREFIJO `g-`, y no es estilo: `.accio`, `.nomes-veu` y `.camp` chocaron
   el mismo día, y la última hizo que un render de una dirección de diseño estuviera juzgando
   un fallo nuestro. Lo exige `test/noms.test.js`.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* --- 1 · Tres pesos de filete donde había uno -------------------------------------------
   Es el vocabulario nuevo entero. 2 px agrupa lo que viene; 1 px separa filas; el hairline
   es el tercer nivel. Y el de 2 px va ENCIMA del título: un filete debajo cierra lo que
   acaba, y lo que hace falta aquí es abrir lo que empieza. */
.g-seccio {
  border-top: 2px solid var(--doc-tinta);
  padding-top: 14px;
  margin-top: 44px;
}
.g-seccio:first-child { margin-top: 24px; }

/* `.gestio h2` es (0,1,1) y esto era (0,1,0): el titulo salia a 18 px y el render lo enseño.
   Se sube a (0,2,0) en vez de tocar la regla de al lado, que viste los h2 que no son sección. */
.g-seccio .g-seccio__titol {
  font-size: var(--mida-36);
  font-weight: 400;
  letter-spacing: -.01em;
  margin: 0 0 var(--pas-lectura);
}
/* El recuento al lado del título: es un dato, no un adorno, así que va con su peso. */
.g-seccio .g-seccio__quants { font-weight: 550; }

/* --- 2 · La cifra: el tratamiento del mural, importado ----------------------------------
   Y LA REGLA QUE SALIÓ DE LA CRÍTICA (§11.2): la cifra grande es una CANTIDAD, nunca un
   instante. `26 h 30 min` y `1.284` la llevan; `13:02` es cuándo pasó y se queda dentro de
   la frase. Al mismo tamaño, una duración y una hora se leen como la misma clase de dato y
   no lo son. Lo comprueba `test/layout.test.js`. */
.g-xifra {
  font-size: var(--mida-60);
  font-weight: var(--hora-pes);
  font-stretch: 85%;
  font-variant-numeric: tabular-nums;
  line-height: .95;
  letter-spacing: -.02em;
  margin: 0;
}
.g-xifra__unitat {
  font-size: var(--mida-24);
  font-weight: 400;
  font-stretch: 100%;
}
/* Lo que la cifra significa, debajo y pequeño: se lee DESPUÉS del número, que es el orden en
   que se mira. Sin tercera tinta -- ver tokens.css. */
.g-xifra__que {
  font-size: var(--mida-14);
  color: var(--doc-tinta-suau);
  margin: 6px 0 0;
}

/* --- 3 · El tercer nivel, colgado ------------------------------------------------------
   Sin caja, sin fondo y sin color: sangría. Es lo que hace que un detalle se lea como
   detalle de la frase de encima y no como otra frase. */
.g-penjat {
  margin: var(--pas-lectura) 0 0 24px;
  font-size: var(--mida-16);
  color: var(--doc-tinta-suau);
  max-width: var(--doc-mesura);
}
.g-penjat p { margin: 0 0 var(--pas-lectura); }
.g-penjat p:last-child { margin-bottom: 0; }

/* --- 4 · La medida ---------------------------------------------------------------------
   Texto seguido acotado; las tablas NO. Los dos renders de la pasada 2 enseñaban la misma
   página con el 40 % derecho vacío, y en un dossier eso no es calma: es una página sin
   terminar. Una línea de 68 caracteres se lee de un barrido; una de 140, no. */
.g-mesura { max-width: var(--doc-mesura); }

/* Las acciones de una cosa cuelgan con su detalle. Es lo que la dirección D no podía hacer: allí
   vivían fuera del plano y tres cosas distintas compartían una fila de botones sin dueño. */
.cosa__accions { margin-left: 24px; }

/* --- 5 · Densidad: dos, y se decide por lo que hace el ojo ------------------------------ */
.taula th,
.taula td { padding-top: var(--pas-lectura); padding-bottom: var(--pas-lectura); }
.camp { margin-bottom: var(--pas-treball); }

/* --- 6 · El movimiento que ya estaba decidido y no se aplicaba --------------------------
   `--durada-arriba` y `--corba-arriba` existen desde la 7.5 y en esta hoja no aparecían.
   Lo que llega es el CONTENIDO: el contenedor no se mueve, la translación es de 8 px y solo
   se animan `opacity` y `transform`. Regla de §8.5, aplicada donde no se aplicaba.

   Y no retrasa nada: el contenido ya está en el DOM cuando esto empieza. */
@keyframes g-arriba {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.g-arriba { animation: g-arriba var(--durada-arriba) var(--corba-arriba) both; }

@media (prefers-reduced-motion: reduce) {
  .g-arriba { animation: none; }
}
