/* ══ La hoja de Atelier ═══════════════════════════════════════════════════
   Los tokens y las reglas de docs/DESIGN.md, aplicados de verdad. Se lee de
   arriba abajo: fuente, tokens, base, chrome, formularios y luego cada
   componente en el orden en que aparece en la aplicación. */

/* Archivo, autoalojada. El taller tiene mala cobertura y la fuente no puede
   depender de una petición externa. Un solo archivo variable por rango: pesos
   400-700 y el eje de anchura, que es la razón de elegirla — la matrícula se
   compone estrechando la misma familia. */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("/assets/archivo-latin-2348e0b4.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+20AC, U+2122, U+2212, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url("/assets/archivo-latin-ext-f1d50082.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+2113, U+2C60-2C7F;
}

:root {
  --paper: #F6F7F5;
  --card: #FFFFFF;
  --ink: #16181C;
  --ink-soft: #5F6873;
  --rule: #DFE2DE;
  --plate: #123A8F;
  --space: 4px;

  /* Derivados: el azul de matrícula posado sobre el papel, para el fondo de
     lo que está seleccionado, y una línea más clara que --rule para separar
     dentro de una tarjeta sin cortarla en dos. */
  --plate-tint: #E7EDF9;
  --plate-deep: #0C2A6B;
  --hairline: #EBEDE9;
  /* El gris de lo que responde al ratón y de lo marcado sin elegir: la tinta
     al 5 % sobre el papel, el mismo que ya llevan las filas y el muelle. Se
     usaba en el calendario sin estar definido, y sus botones no respondían. */
  --wash: color-mix(in srgb, var(--ink) 5%, var(--paper));
  /* Lo que todavía no ha pasado se lee igual que lo demás, solo que apagado:
     un peldaño futuro del color de una línea no se lee, y el cliente que abre
     esto quiere ver el camino entero. 4.5:1 sobre blanco. */
  --ink-faint: #6F7781;
  /* Y lo que está detrás: lo que el horario ofrece y nadie ha cogido todavía.
     Se lee cuando se le busca y no compite con el trabajo dibujado encima, que
     es lo que se viene a mirar. 3,4:1 sobre blanco, que es el suelo de lo que
     no es texto de lectura. */
  --ink-ghost: #868D96;
  /* La raya de puntos de lo que se ofrece. Es más oscura y más fría que
     --hairline -la raya continua de las horas- a propósito: las dos se cruzan
     en la misma rejilla y del mismo gris no se distinguían, y entonces la
     rejilla no decía cuál era la hora y cuál el rato ofrecido. */
  --dash: #B7BFC7;
  --alarm: #C2452D;

  /* Dos alturas y no cinco: una tarjeta apoyada en el papel y una tarjeta que
     flota por encima del flujo. La diferencia entre las dos es la jerarquía. */
  --lift-rest: 0 1px 1px rgb(22 24 28 / 4%), 0 2px 6px rgb(22 24 28 / 4%);
  --lift-float: 0 1px 2px rgb(22 24 28 / 6%), 0 12px 24px -8px rgb(22 24 28 / 18%);

  /* El radio crece con la jerarquía: una fila casi recta, una tarjeta redonda,
     un panel más, y la píldora solo para lo que se pulsa. */
  --r-row: 8px;
  --r-card: 14px;
  --r-panel: 20px;
  --r-pill: 999px;

  /* Las bandas del sistema —la hora arriba, la raya del gesto abajo— solo se
     descuentan donde de verdad las hay: con la aplicación guardada en la
     pantalla de inicio, que es cuando el papel llega hasta los cuatro bordes y
     el sistema pinta encima. En un navegador se las come ya la barra de
     direcciones, y descontarlas otra vez es aire de más antes del título y
     debajo del muelle. Chrome devuelve cero ahí y no se notaba; Firefox
     devuelve la banda entera y sí. */
  --band-top: 0px;
  --band-bottom: 0px;
}

@media (display-mode: standalone), (display-mode: fullscreen) {
  :root {
    --band-top: env(safe-area-inset-top);
    --band-bottom: env(safe-area-inset-bottom);
  }
}

*, *::before, *::after { box-sizing: border-box; }

/* El papel también en la raíz, y `color-scheme` para decirlo. El fondo de
   `body` se propaga al lienzo, pero no a lo que queda fuera del documento: la
   banda del sistema en una pantalla guardada en el inicio y el rebote al tirar
   del final de la página los pinta el navegador, y sin esto los pinta de
   negro. Es el listón negro que salía debajo del muelle. */
html {
  background: var(--paper);
  color-scheme: light;
  /* Sin el recuadro azul que el navegador pinta encima de lo que se acaba de
     tocar. Esto se guarda en el inicio del móvil y se usa como una aplicación,
     y en una aplicación un botón no parpadea en azul para avisar de que era un
     enlace: se pulsa y pasa lo que tiene que pasar. Lo que se toca ya se ve
     hundido por su cuenta, y el foco de teclado no es esto: ese es el aro de
     `:focus-visible`, que sigue donde estaba. */
  -webkit-tap-highlight-color: transparent;
}

body {
  margin: 0;
  padding: var(--band-top) calc(var(--space) * 5) calc(var(--space) * 26);
  background: var(--paper);
  color: var(--ink);
  font: 400 16px/1.55 "Archivo", system-ui, sans-serif;
  font-variant-numeric: tabular-nums;
  -webkit-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
}

main { max-width: 640px; margin: 0 auto; padding-top: calc(var(--space) * 6); }

/* El azul de matrícula es el único acento. Un enlace visitado no cambia de
   color: aquí no se navega por un sitio, se trabaja. */
a, a:visited { color: var(--plate); text-decoration-thickness: 1px; text-underline-offset: 2px; }

/* ── Tipografía ───────────────────────────────────────────────────────────
   Una sola familia. La jerarquía la hacen el peso y el tamaño, nunca una
   versalita espaciada encima del bloque. */
h1 {
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.15;
  margin: 0 0 calc(var(--space) * 3);
}
h2 {
  font-size: 18px;
  font-weight: 650;
  letter-spacing: -0.01em;
  margin: calc(var(--space) * 9) 0 calc(var(--space) * 3);
}
.lede { margin: 0 0 calc(var(--space) * 6); color: var(--ink-soft); max-width: 56ch; }

/* Los datos que acompañan a un título no se cosen con puntos medios: se
   separan con espacio, y así cada idioma los parte donde le toca y ninguno
   arrastra una puntuación que no significa nada. Ver docs/DESIGN.md. */
.meta { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 1) calc(var(--space) * 4); color: var(--ink-soft); }
p.meta { margin: 0 0 calc(var(--space) * 6); }
span.meta, dd.meta { display: inline-flex; }
/* Una matrícula no se subraya: es una placa, y una placa con una raya debajo
   deja de parecerse a una placa. El enlace se nota al pasar por encima. */
.meta a { margin-right: 0; min-height: 0; text-decoration: none; }
.meta a:hover .plate { border-color: var(--plate); }
.hint { color: var(--ink-soft); font-size: 14px; }

/* ── El chrome ────────────────────────────────────────────────────────────
   Arriba el sitio donde se está; abajo, a dónde se puede ir. Ninguno de los
   dos se lleva atención: son el marco del trabajo. */
/* Las dos barras cruzan la pantalla entera, pero lo que llevan dentro va en la
   misma columna que el contenido. En un ordenador, una marca pegada al borde
   izquierdo con el título a cuatrocientos píxeles no parece la misma
   aplicación, y cuatro destinos repartidos en mil doscientos píxeles son cuatro
   botones de trescientos: eso no es un destino, es una pancarta. */
.bar-inner {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 3);
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
}
.dock .bar-inner { gap: calc(var(--space) * 1); }
.bar-inner > * { min-width: 0; }

/* El nombre de la cuenta va al lado de la marca y se parte en dos líneas si
   hace falta: un taller no se llama igual de largo en cada sitio, y cortar un
   nombre con puntos suspensivos es peor que bajarlo una línea. */
.whose { color: var(--ink-soft); font-size: 15px; line-height: 1.2; }

/* La marca: el mismo icono que queda en la pantalla de inicio del móvil y el
   nombre al lado. Con el icono, la barra deja de ser una línea de texto y se
   reconoce de un vistazo cuál de las aplicaciones abiertas es esta. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-width: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--plate);
}
.brand-name { white-space: nowrap; }

/* Los iconos de la interfaz. Heredan el color de la fila y no tienen ninguno
   propio: un icono con color de marca dentro de una fila de texto se lee como
   un botón que no es. */
.icon { flex: none; display: block; }

/* ── El menú de la cabecera ───────────────────────────────────────────────
   Una sola cosa que se abre y lleva a cualquier sitio: se escribe arriba una
   matrícula o un nombre y lo encontrado sustituye al menú, y debajo están lo
   que se empieza, los sitios sin pestaña, la cuenta y la salida.

   Es un <details>, así que abre y cierra sin JavaScript; el controlador
   `popup` solo añade lo que se espera de un menú —fuera y Escape lo cierran,
   Ctrl+K lo abre, y el cursor cae ya en el campo—. Ver docs/DESIGN.md. */
/* El menú es el extremo derecho de la barra: lo demás son destinos y él es
   desde donde se llega a todo lo que no lo es. */
.jump { position: relative; }

.jump-open {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  padding: calc(var(--space) * 1) calc(var(--space) * 2);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  list-style: none;
  cursor: pointer;
}
.jump-open::-webkit-details-marker { display: none; }

/* El nombre de la aplicación y dónde se está, uno encima del otro: "Atelier"
   con "Garage Dubois" debajo en pequeño es la misma respuesta que daban antes
   la marca a un lado y el nombre de la cuenta al otro, dicha en un solo sitio. */
.jump-brand {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  line-height: 1.15;
}
.jump-brand .brand-name { font-size: 15px; font-weight: 700; letter-spacing: -0.02em; color: var(--plate); }
.jump-where { overflow: hidden; font-size: 12px; font-weight: 500; color: var(--ink-soft); text-overflow: ellipsis; white-space: nowrap; }

/* En un móvil no cabe: se queda el icono y las iniciales, que es exactamente
   lo que se ve en Fizzy. El nombre entero está dentro, en la primera línea del
   panel. */
@media (max-width: 519px) {
  .jump-open > .jump-brand { display: none; }
}
@media (hover: hover) {
  .jump-open:hover { background: var(--card); border-color: var(--rule); }
}
.jump-open:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }
.jump[open] > .jump-open { background: var(--card); border-color: var(--rule); }

/* Las iniciales de la cuenta. No es una foto ni un color por persona: es la
   forma más corta de decir en cuál se está sin escribir el nombre dos veces,
   y en un móvil el nombre largo se queda fuera y esto no. */
.avatar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--r-pill);
  background: var(--plate-tint);
  color: var(--plate-deep);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* Quién es, dentro del panel: el mismo círculo del botón y el nombre entero
   al lado. No es un rótulo de bloque, es la respuesta a en qué cuenta estoy. */
.jump-whose {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 3);
  margin: 0 0 calc(var(--space) * 2);
  padding: calc(var(--space) * 2) calc(var(--space) * 3);
  color: var(--ink);
  font-size: 15px;
  font-weight: 650;
}

/* En un ordenador el panel cuelga del botón y flota por encima del flujo, así
   que lleva la sombra que flota. Sube y se alinea a la derecha porque el botón
   está abajo a la derecha; en la consola, donde el muelle va arriba a la
   izquierda, baja y se alinea a la izquierda. */
.sheet-grip { display: none; }
.sheet-title { margin: 0 0 calc(var(--space) * 3); font-size: 15px; font-weight: 650; }

.jump-panel {
  position: absolute;
  right: 0;
  bottom: calc(100% + var(--space) * 2);
  z-index: 20;
  width: max-content;
  /* Lo ancho que tiene que ser para que las tres tarjetas de lo que se empieza
     quepan en una fila: partidas en dos y una, la de abajo queda coja. */
  min-width: 344px;
  max-width: min(380px, calc(100vw - var(--space) * 10));
  padding: calc(var(--space) * 2);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}

/* ── El menú en un móvil: una hoja que sube ───────────────────────────────
   De ancho entero y pegada al borde de abajo, como en Fizzy. Colgando de un
   botón, el panel medía lo que le dejaba el botón —unos dedos de ancho contra
   un borde— y encima se salía de la pantalla cuando el botón ya estaba al pie.
   Una hoja que sube usa el ancho que hay, se lee de un vistazo y se cierra
   tocando fuera, que aquí es media pantalla y no un filo.

   Lo de detrás se apaga: mientras la hoja está abierta no se trabaja con lo de
   debajo, y el velo lo dice sin escribirlo. */
@media (max-width: 759px) {
  .jump-panel { padding: calc(var(--space) * 3); }
  .jump-whose { font-size: 17px; }
}

/* El campo de buscar, con la lupa dentro. Es lo primero del panel porque es lo
   primero que se hace: en un taller con doscientos coches, llegar a la ficha
   escribiendo tres letras de la matrícula es más corto que cualquier lista. */
.jump-find { position: relative; margin: 0 0 calc(var(--space) * 2); }
.jump-find .icon {
  position: absolute;
  left: calc(var(--space) * 3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--ink-soft);
  pointer-events: none;
}
.jump-find input[type="search"] {
  width: 100%;
  min-height: 44px;
  margin: 0;
  padding-left: calc(var(--space) * 9);
  border-radius: var(--r-row);
  background: var(--paper);
  font-size: 15px;
}
.jump-find input[type="search"]::-webkit-search-cancel-button { cursor: pointer; }

/* La tecla que abre el menú, dibujada como una tecla. En un móvil no hay
   teclado y no se dibuja: sería enseñar un atajo que nadie puede pulsar. */
.jump-key:empty { display: none; }
.jump-key {
  position: absolute;
  right: calc(var(--space) * 2);
  top: 50%;
  transform: translateY(-50%);
  padding: 2px calc(var(--space) * 1.5);
  border: 1px solid var(--rule);
  border-radius: 5px;
  background: var(--card);
  color: var(--ink-soft);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  pointer-events: none;
}
@media (max-width: 519px) {
  .jump-key { display: none; }
}

/* Lo que se empieza, en tarjetas. Son las cosas por las que se abre el menú
   con el coche delante, y una fila de texto de quince píxeles no se acierta
   con el pulgar sucio: aquí el dibujo es grande y lo que se toca es la tarjeta
   entera. Las que son tres caben en tres columnas; las que son dos, en dos. */
.jump-does {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: calc(var(--space) * 2);
  margin-bottom: calc(var(--space) * 2);
}
.jump-do {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 2);
  min-height: 84px;
  padding: calc(var(--space) * 3) calc(var(--space) * 2);
  border-radius: var(--r-card);
  background: var(--paper);
  color: var(--ink);
  font-size: 13px;
  font-weight: 550;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
}
.jump-do:visited { color: var(--ink); }
.jump-do .icon { flex: none; width: 24px; height: 24px; color: var(--plate); }
@media (hover: hover) {
  .jump-do:hover { background: var(--plate-tint); color: var(--plate-deep); }
}
.jump-do:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

.jump-list { margin: 0; padding: 0; list-style: none; }
.jump-list + .jump-list { margin-top: calc(var(--space) * 2); padding-top: calc(var(--space) * 2); border-top: 1px solid var(--hairline); }
.jump-list form { margin: 0; }

/* Una fila del menú es una fila: radio de fila, no de píldora, y ocupa el
   ancho entero para que el dedo no tenga que apuntar. El icono ayuda a
   encontrarla la cuarta vez; la palabra la dice siempre. */
.jump-row {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 3);
  width: 100%;
  min-height: 44px;
  padding: 0 calc(var(--space) * 3);
  border: 0;
  border-radius: var(--r-row);
  background: transparent;
  box-shadow: none;
  color: var(--ink);
  font-size: 15px;
  font-weight: 550;
  text-align: left;
  text-decoration: none;
}
.jump-row .icon { flex: none; color: var(--ink-soft); }
.jump-row .plate { flex: none; }
.jump-what { flex: 1; min-width: 0; }
.jump-row:hover { background: var(--paper); color: var(--ink); border: 0; }
.jump-row:hover .icon { color: var(--plate); }
.jump-row:focus-visible { outline: 2px solid var(--plate); outline-offset: -2px; }
.jump-row.current { background: var(--plate-tint); color: var(--plate-deep); font-weight: 650; }
.jump-row.current .icon { color: var(--plate-deep); }

/* El número de una fila del menú es el mismo de la campana: el mismo dato dos
   veces en la misma barra no puede tener dos aspectos. */
.jump-row .count {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: #fff;
  font-size: 13px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}

/* No haber encontrado nada se dice, y se dice con lo que se buscó delante: así
   se ve la errata sin volver a mirar el campo. */
.jump-nothing {
  margin: 0;
  padding: calc(var(--space) * 3);
  color: var(--ink-soft);
  font-size: 15px;
}

/* ── El muelle ────────────────────────────────────────────────────────────
   Los destinos y, en el extremo derecho de la misma píldora, el elemento que
   es la marca y el menú. Es el chrome entero de la aplicación: no hay barra
   arriba, porque la marca es el botón del menú y el botón del menú está aquí.

   Flota: una píldora apoyada sobre la pantalla y no una banda pegada al borde.
   Una banda parte la pantalla en dos y se lleva una franja entera de alto; una
   píldora se posa encima y deja verse lo que pasa por debajo. Es lo que hace
   Fizzy y es lo que se pidió.

   Va abajo porque esto se usa de pie, con una mano y con el pulgar. La consola
   lo sube en un ordenador, y esa es la única diferencia entre las dos. */
.dock {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 20;
  padding: 0 calc(var(--space) * 4);
  /* El hueco de abajo no es aire: es lo que separa la píldora de la barra de
     gestos del teléfono. Con doce píxeles, el pulgar que va a la campana roza
     la raya del sistema y se sale de la aplicación. Veinticuatro, y cada uno
     pulsa lo suyo. Donde el sistema dice cuánto se aparta —la aplicación
     guardada en el inicio—, manda él si pide más. */
  padding-bottom: max(calc(var(--space) * 6), var(--band-bottom));
}

/* El muelle se aparta mientras hay teclado delante.

   En un móvil el teclado se come media pantalla y la píldora se queda flotando
   justo encima de él: tapa el campo que se está rellenando y el botón que va
   debajo. Estuvo arreglado pantalla por pantalla, quitándole el muelle entero a
   las dos puertas, y así no valía: cualquier formulario de dentro tiene el
   mismo problema —una matrícula, una nota, una hora— y de esos no se puede
   quitar la navegación.

   Así que se va y vuelve solo. Quien lo manda es el teclado y no el campo: el
   teclado se esconde con su propio botón sin soltar el campo, y entonces ya no
   hay nada que tapar. Quien lo nota es keyboard_controller.js, midiendo lo que
   encoge la ventana.

   Solo donde se toca con el dedo: con ratón se escribe en un teclado que no
   tapa nada, y una barra que desaparece al tabular es un susto.

   Irse no se anima y volver sí. El teclado sube tapando la pantalla y la
   píldora tiene que no estar ya; cualquier cosa que dure se ve como un
   estorbo que se retira tarde. Al bajar el teclado, en cambio, se descubre un
   hueco vacío y la barra sube a ocuparlo: ahí el movimiento es la respuesta.
   La transición se declara en el estado al que se llega, así que la del muelle
   quieto es la de volver. */
@media (pointer: coarse) {
  .dock { transition: transform 160ms ease, opacity 120ms ease, visibility 160ms; }

  body.keyboard .dock {
    transition: none;
    transform: translateY(150%);
    opacity: 0;
    visibility: hidden;
  }
}

/* La píldora es la barra entera: los destinos y el menú dentro del mismo
   filo. El menú vivía fuera, en su propio cuadrado al lado, y ahí se leía como
   otra cosa —un botón suelto que alguien se dejó— en vez de como el extremo de
   la barra. Es una sola pieza y se dibuja como una sola pieza.

   El filo lo pinta un pseudoelemento y no la caja: `backdrop-filter` hace de
   la caja el marco de referencia de todo lo que lleve dentro con posición
   fija, y la hoja del menú es fija. Pintado detrás, el vidrio es el mismo y la
   hoja sigue midiéndose contra la pantalla. */
.dock .bar-inner {
  position: relative;
  padding: calc(var(--space) * 1.5);
}
.dock .bar-inner::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--card) 92%, transparent);
  box-shadow: var(--lift-float);
  backdrop-filter: saturate(180%) blur(12px);
}

/* Los destinos se llevan el sitio que sobra; el menú mide lo suyo y no se
   encoge. */
.dock-nav {
  flex: 1;
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 1);
  min-width: 0;
}
.dock-nav > a {
  position: relative;
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 2);
  min-width: 0;
  min-height: 44px;
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  font-size: 15px;
  font-weight: 550;
  text-decoration: none;
  white-space: nowrap;
}
@media (hover: hover) {
  .dock-nav > a:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); color: var(--ink); }
}
.dock-nav > a.current { background: var(--plate-tint); color: var(--plate-deep); font-weight: 650; }
.dock-nav > * > .icon { flex: none; }

/* El número que lleva un destino: lo que espera en él. Se posa en la esquina
   del dibujo, porque al lado no cabe y debajo rompería la altura. Si es cero
   no se dibuja: un contador a cero es ruido donde luego hay que ver una cifra. */
.dock-nav > a .count {
  position: absolute;
  top: calc(var(--space) * 1);
  right: calc(50% - 18px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: #fff;
  font-size: 11px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.dock-nav > a.current .count { background: var(--plate-deep); }

/* La campana es un destino más y se dibuja como los demás: se estira igual, se
   enciende igual, lleva su cifra en la misma esquina y su palabra al lado. Era
   el único sitio de la fila sin nada escrito, y en una pantalla ancha un dibujo
   suelto entre cuatro palabras se lee como otra cosa. Donde no cabe, la palabra
   se recorta con la de sus vecinos -la regla de abajo- y queda el dibujo. */
.dock .bell-link {
  position: relative;
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 2);
  min-width: 0;
  min-height: 44px;
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  font-size: 15px;
  font-weight: 550;
  text-decoration: none;
  white-space: nowrap;
}
@media (hover: hover) {
  .dock .bell-link:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); color: var(--ink); }
}
.dock .bell-link.current { background: var(--plate-tint); color: var(--plate-deep); font-weight: 650; }
.dock .bell-link .count {
  position: absolute;
  top: calc(var(--space) * 1);
  right: calc(50% - 18px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: #fff;
  font-size: 11px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
/* Sin avisos no hay cifra. El hueco se queda escrito igualmente —es lo que se
   reemplaza solo cuando llega uno— y es la hoja la que no lo dibuja. */
.dock .bell-link .count:empty { display: none; }
.dock .bell-link.current .count { background: var(--plate-deep); }

/* El menú es el extremo derecho de la barra, dentro del mismo filo, y se
   dibuja como los destinos: mismo alto, mismo radio, mismo dibujo de línea al
   mismo color. Era un azulejo azul de 28 px, la pieza más pequeña de la barra
   justo en el extremo donde cae el pulgar, y un cuadrado saturado de esquinas
   duras clavado en el remate redondo de una píldora se lee como una pegatina
   puesta encima. Una barra es una fila de sitios donde se toca; lo que rompe
   la fila no se lee mejor, se lee como otra cosa.

   Lo único que lo distingue es que no se estira —no es un destino, es desde
   donde se llega a todo lo demás— y por eso mide lo suyo. */
.dock .jump { flex: none; }
.dock .jump-open {
  position: relative;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  margin-left: calc(var(--space) * 1);
  color: var(--ink-soft);
}
@media (hover: hover) {
  .dock .jump-open:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); color: var(--ink); }
}
.dock .jump[open] > .jump-open { background: var(--plate-tint); color: var(--plate-deep); }

/* Dentro de la fila -el muelle de la aplicación- se reparte el ancho como
   todos: mismo hueco, mismo dibujo en el centro de su hueco. Fuera de ella
   -la consola, que arriba lleva su nombre escrito al lado- mide lo suyo, que
   es lo que dicen las reglas de arriba. */
.dock-nav > .jump { flex: 1; min-width: 0; }
.dock-nav > .jump > .jump-open { width: 100%; margin-left: 0; }

/* Por debajo de 760 px la palabra de un destino se recorta y queda el dibujo:
   cuatro palabras y un número no caben en una píldora de 375 px. Recortada y
   no quitada, para que quien escucha la pantalla la siga oyendo. */
@media (max-width: 759px) {
  .dock-nav > a .tab-said { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

/* En una pantalla ancha la palabra vuelve al lado del dibujo: hay sitio de
   sobra y una fila de dibujos sueltos no se lee. */
@media (min-width: 760px) {
  .dock .jump-open {
    width: auto;
    height: auto;
    min-height: 44px;
    padding: calc(var(--space) * 1) calc(var(--space) * 3);
    border-radius: var(--r-pill);
    gap: calc(var(--space) * 2);
  }
  .dock-nav > .jump > .jump-open { width: 100%; }

  /* Y la cifra se pone detrás de la palabra, en la fila, en vez de posarse en
     la esquina del dibujo: con la palabra puesta, el centro del destino cae
     sobre el texto, y la cifra quedaba encima de él tapándolo. */
  .dock-nav > a .count, .dock .bell-link .count {
    position: static;
    top: auto;
    right: auto;
  }
}

/* Dentro de la fila del muelle el menú no lleva la marca: es un sitio donde se
   toca como los demás, con su dibujo y su palabra, y nada que lo haga más ancho
   ni más alto que sus vecinos. Llevaba "Atelier" con el nombre de la cuenta
   debajo, y eso lo convertía en otra cosa metida en medio de una fila de
   iguales. El nombre de la cuenta se lee en la primera línea del panel, que es
   cuando se pregunta.

   Fuera de la fila -la consola, donde el menú cuelga al final de la barra de
   arriba- la marca se queda y la palabra sobra: el nombre ya está escrito al
   lado y decirlo dos veces no lo dice mejor. */
.dock-nav > .jump > .jump-open .jump-brand { display: none; }
.jump-open .tab-said { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

@media (min-width: 760px) {
  .dock-nav > .jump > .jump-open .tab-said {
    position: static;
    width: auto;
    height: auto;
    clip-path: none;
    font-size: 15px;
    font-weight: 550;
  }
}

/* Un panel es una tarjeta sin filo de etapa: lo que se agrupa y se lee, no lo
   que está en una etapa. El radio es el de un panel, no el de una tarjeta. */
.panel {
  margin-bottom: calc(var(--space) * 4);
  padding: calc(var(--space) * 5);
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-rest);
}
.panel > :first-child { margin-top: 0; }
.panel > :last-child { margin-bottom: 0; }
/* El título de una sección va dentro de su tarjeta, que es de lo que es
   título. Sin esto se despega del contenido que encabeza. */
.panel > h2 { margin-top: 0; }
.panel-name { margin: 0 0 calc(var(--space) * 1); font-size: 20px; font-weight: 700; letter-spacing: -0.02em; }
.panel-price { margin: 0 0 calc(var(--space) * 4); font-size: 17px; font-weight: 650; color: var(--ink-soft); }

/* ── La consola de la plataforma ──────────────────────────────────────────
   Quien lleva el negocio no está en un taller con las manos sucias: está
   sentado, delante de una pantalla ancha, y lo que mira son listas de cuentas
   con seis datos por fila. Por eso la columna es más ancha que la de un
   taller: 640 px para una fila de seis datos es una fila partida en tres.

   El chrome es el mismo muelle que el resto de la aplicación, y toda la
   diferencia es dónde se posa: aquí sube arriba en un ordenador, porque una
   píldora flotando al pie taparía la última fila de una lista larga. En un
   móvil flota al pie como en todas partes.

   El papel, los tokens y la tipografía son los mismos. No se inventa un tema
   oscuro de administrador: es el mismo producto visto desde el otro lado.
   Ver docs/SPEC.md 18 y docs/DESIGN.md. */
body.console main { max-width: 900px; }
/* Con el muelle arriba no hay nada flotando al pie que tapar, así que el papel
   que se deja abajo para que la píldora no se coma la última fila sobra. */
@media (min-width: 760px) {
  body.console { padding-bottom: calc(var(--space) * 12); }
}
.console-dock .bar-inner { max-width: 900px; }

@media (min-width: 760px) {
  .console-dock {
    position: sticky;
    inset: auto;
    top: 0;
    z-index: 10;
    margin: 0 calc(var(--space) * -5);
    padding: calc(var(--space) * 2) calc(var(--space) * 5);
    background: color-mix(in srgb, var(--paper) 88%, #fff);
    border-bottom: 1px solid var(--hairline);
    backdrop-filter: saturate(180%) blur(12px);
  }
  /* Arriba, la marca va primero y los destinos detrás: es el orden en el que
     se lee una cabecera. Abajo es al revés, porque el pulgar llega antes a la
     derecha y lo que más se abre es el menú. */
  .console-dock .jump { order: -1; }
  /* Pegada al papel, la píldora sobra: aquí no flota nada. */
  .console-dock .dock-nav {
    flex: 0 1 auto;
    margin-left: auto;
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
    backdrop-filter: none;
  }
  /* Aquí sí llevan relleno, y por eso pueden: no se reparten el ancho, miden
     lo que miden sus palabras. En el muelle de la aplicación ninguno lo lleva,
     porque una caja no puede medir menos que su propio relleno y eso hacía que
     un hueco con relleno saliera más ancho que el menú, que no lo lleva. */
  .console-dock .dock-nav > a { flex: none; padding: 0 calc(var(--space) * 3); }
  .console-dock .dock-nav > a .count { position: static; right: auto; top: auto; }
  .console-dock .jump-open { border-color: transparent; background: none; box-shadow: none; }
  .console-dock .jump-open:hover { background: var(--card); border-color: var(--rule); }
  .console-dock .jump[open] > .jump-open { background: var(--card); border-color: var(--rule); }
  /* Y el panel vuelve a colgar hacia abajo y por la izquierda, que es de donde
     cuelga un menú cuyo botón está arriba a la izquierda. */
  .console-dock .jump-panel {
    top: calc(100% + var(--space) * 2);
    bottom: auto;
    left: 0;
    right: auto;
  }
}

/* ── Lo que pide una decisión hoy ─────────────────────────────────────────
   La primera sección del resumen, y la que hace que la consola sirva para
   trabajar y no solo para mirar. Cada línea lleva a la pantalla donde se
   resuelve; ninguna está a cero. */
.attention { margin-bottom: calc(var(--space) * 4); }
.attention h2 { margin-top: 0; }

/* La sección ya es la tarjeta: las alertas son sus filas. */
.alerts li { border-bottom: 1px solid var(--hairline); }
.alerts li:last-child { border-bottom: 0; }
.alerts li a {
  display: flex;
  align-items: baseline;
  gap: calc(var(--space) * 3);
  min-height: 52px;
  padding: calc(var(--space) * 2) 0;
  color: var(--ink);
  text-decoration: none;
}
/* El número delante y grande: se cuenta antes de leer qué es. */
.alert-count {
  min-width: 2ch;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.alert-what { font-weight: 550; }
/* Cada aviso lleva a donde se resuelve, y se dibuja como lo que es: una fila
   que se abre, con el galón de las filas de Réglages. */
.alerts li a::after {
  content: "";
  align-self: center;
  flex: none;
  width: 9px;
  height: 14px;
  margin-left: auto;
  background: currentColor;
  color: var(--ink-faint);
  clip-path: polygon(14% 8%, 30% 0, 86% 50%, 30% 100%, 14% 92%, 58% 50%);
}
@media (hover: hover) {
  .alerts li a:hover .alert-what { color: var(--plate); text-decoration: underline; text-underline-offset: 3px; }
}

/* Cuando no hay nada, se dice con la misma calma con la que se diría en voz
   alta. Ni una tarjeta vacía ni un dibujo: una frase. */
.all-well { margin: 0; font-size: 17px; font-weight: 600; }

/* ── La ficha de una cuenta ───────────────────────────────────────────────
   Quién es y en qué estado está arriba, en una línea; lo que gasta, en
   cifras; y debajo, las dos cosas que se deciden —el plan y el acceso— lado a
   lado en un ordenador, porque son las dos respuestas posibles a quien
   escribe. Quién entra y qué ha pasado van después a lo ancho: son listas, y
   una lista partida en una columna de trescientos píxeles se lee a trozos. */
.record-state { margin: calc(var(--space) * -2) 0 calc(var(--space) * 6); }

.record { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--space) * 4); align-items: start; margin-bottom: calc(var(--space) * 4); }
@media (min-width: 760px) {
  .record:has(> .panel + .panel) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.record > .panel { margin-bottom: 0; }
.record .stack { max-width: none; }
.record .with-button { max-width: none; }
/* Lo que cuelga de un panel sin ser otro panel: un título pequeño y una
   línea encima, que separa sin anidar tarjetas. */
.panel-sub {
  margin: calc(var(--space) * 5) 0 calc(var(--space) * 3);
  padding-top: calc(var(--space) * 4);
  border-top: 1px solid var(--hairline);
  font-size: 15px;
  font-weight: 650;
}

/* Una persona de la cuenta: el nombre y su papel a la izquierda, y la
   dirección a la derecha, que es lo que se copia para contestarle. */
.rows li.person { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name mail" "hint mail"; gap: 2px calc(var(--space) * 3); padding-block: calc(var(--space) * 2); }
.rows li.person .person-mail { grid-area: mail; min-height: 44px; color: var(--plate); overflow-wrap: anywhere; }
@media (max-width: 559px) {
  .rows li.person { grid-template-columns: 1fr; grid-template-areas: "name" "hint" "mail"; }
  .rows li.person .person-mail { min-height: 32px; }
}

/* Lo que no se deshace, en su tarjeta: el título en rojo y una línea gris que
   lo dice. Las filas que borran algo de verdad se abren aquí y piden el
   nombre; su palabra va en rojo para que no se confunda con ir a otra parte. */
.grave-panel > h2 { margin-bottom: calc(var(--space) * 1); color: var(--alarm); }
.grave-panel > .hint { margin: 0 0 calc(var(--space) * 2); }
/* Lejos de guardar: lo que no se deshace no puede estar a un dedo del botón
   que se pulsa cada vez. */
form + .grave-panel { margin-top: calc(var(--space) * 12); }
.grave-panel > .panel-save { margin-top: calc(var(--space) * 3); }
.rows li.drop { display: block; }
.rows li.drop > details > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 52px;
  color: var(--alarm);
  font-weight: 550;
  list-style: none;
}
.rows li.drop > details > summary::-webkit-details-marker { display: none; }
.rows li.drop > details > summary::after {
  content: "";
  width: 7px;
  height: 7px;
  margin-right: 2px;
  border-right: 2px solid currentcolor;
  border-bottom: 2px solid currentcolor;
  transform: translateY(-2px) rotate(45deg);
}
.rows li.drop > details[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.rows li.drop > details > .hint { margin: 0 0 calc(var(--space) * 3); }
.rows li.drop .stack { max-width: none; padding-bottom: calc(var(--space) * 4); }
.rows li.drop .panel-save { margin-top: calc(var(--space) * 2); }
/* Una fila de alguien a quien se puede borrar: quién es en tinta, como en
   cualquier lista, y el verbo a la derecha en rojo, que es lo que abre. */
.rows li.drop .drop-who { display: flex; flex-direction: column; gap: calc(var(--space) * 1); padding-block: calc(var(--space) * 2); color: var(--ink); }
.rows li.drop .drop-do { margin-left: auto; font-size: 14px; text-align: right; }
.rows li.drop > details > summary:has(.drop-do) { gap: calc(var(--space) * 3); }

/* Acotar el registro: tres preguntas y el botón en una línea en un
   ordenador, apoyado en el pie de los campos; en un móvil, una debajo de
   otra y el botón a lo ancho. */
.log-filters { display: grid; gap: calc(var(--space) * 3); align-items: end; }
.log-filters .field { display: flex; flex-direction: column; gap: calc(var(--space) * 1); min-width: 0; }
.log-filters label { font-size: 14px; font-weight: 550; color: var(--ink-soft); }
.log-filters > button { display: inline-flex; align-items: center; justify-content: center; gap: calc(var(--space) * 2); }
.log-filters > button .icon { width: 18px; height: 18px; }
@media (min-width: 760px) {
  .log-filters { grid-template-columns: repeat(3, minmax(0, 1fr)) auto; }
}

/* Un par de nombre y cifra separados por novecientos píxeles deja de ser un
   par: el ojo no los junta. Dentro de un panel de la consola cada par es una
   fila, con la línea de las filas debajo, y la línea lleva el ojo de un lado
   al otro. */
body.console .panel > .totals { gap: 0; }
body.console .panel > .totals > dt { padding-right: calc(var(--space) * 4); }
body.console .panel > .totals > :is(dt, dd) { display: flex; align-items: center; min-height: 44px; border-bottom: 1px solid var(--hairline); }
body.console .panel > .totals > dd { justify-content: flex-end; font-weight: 650; }
body.console .panel > .totals > :is(dt, dd):nth-last-child(-n + 2) { border-bottom: 0; }

/* El nombre del mes cabe entero en una consola: partir `septiembre 2026` en
   dos líneas para ahorrar treinta píxeles de una pantalla de novecientos es
   ahorrar donde no falta. */
@media (min-width: 560px) {
  body.console .bars li { grid-template-columns: 120px 1fr 40px; }
}

/* De quién habla la pantalla cuando se llega a ella desde una cuenta, y por
   dónde se vuelve al registro entero. Sin esto se llegaba y no se salía. */
.narrowed { margin: calc(var(--space) * -2) 0 calc(var(--space) * 5); }

/* Las fórmulas se comparan. Una debajo de otra obliga a recordar lo que decía
   la anterior; al lado, la diferencia se ve. En un móvil vuelven a la pila. */
.plan-cards { display: grid; gap: calc(var(--space) * 4); align-items: start; margin-bottom: calc(var(--space) * 5); }
/* La rejilla ya separa las tarjetas: el margen de panel encima del hueco las
   dejaba a dos dedos unas de otras. */
.plan-cards .panel { margin-bottom: 0; }
/* El pie de una tarjeta que se cambia: la misma barra de celdas que el pie de
   un aviso, de filo a filo, y la tarjeta recoge su relleno de abajo para que
   la barra sea el borde. */
.panel:has(> .panel-foot) { padding-bottom: 0; overflow: hidden; }
.panel-foot { display: flex; margin: calc(var(--space) * 4) calc(var(--space) * -5) 0; border-top: 1px solid var(--hairline); }
.panel-foot > * { flex: 1 1 0; }
.panel-foot > a.notice-act { color: var(--plate); text-decoration: none; }
@media (min-width: 760px) {
  .plan-cards { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
}

/* Los topes de una fórmula: cinco cifras cortas, en dos columnas desde que
   caben. Una debajo de otra eran cinco campos de lado a lado para escribir
   tres dígitos. */
.limits { display: grid; gap: calc(var(--space) * 4); margin-top: calc(var(--space) * 4); }
.limits .field { display: flex; flex-direction: column; gap: calc(var(--space) * 1); }
.limits label { font-size: 14px; font-weight: 550; color: var(--ink-soft); }
@media (min-width: 560px) {
  .limits { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── La pantalla de la formula ────────────────────────────────────────────
   Arriba, en un panel, la formula que se lleva y lo que va del mes; debajo,
   las que hay, para comparar. Antes el titulo, el nombre de la formula y la
   fecha de caducidad eran tres frases sueltas una debajo de otra, y las
   tarjetas de las formulas se tocaban entre ellas: eran tarjetas de coche
   -con filo de etapa y todo- apiladas sin separacion. */
.plan-now { margin-top: calc(var(--space) * 5); }
.plan-now .panel-name { font-size: 24px; }
.plan-now .panel-price { color: var(--ink); }
.plan-now .panel-top .panel-price { margin-bottom: calc(var(--space) * 2); }
.plan-until { margin: 0 0 calc(var(--space) * 5); }
.plan-month {
  margin: 0 0 calc(var(--space) * 4);
  padding-top: calc(var(--space) * 4);
  border-top: 1px solid var(--hairline);
  font-size: 14px;
  font-weight: 650;
  color: var(--ink-soft);
}

/* Lo gastado del mes. El nombre y la cifra en la misma linea, y la barra
   debajo cruzando la tarjeta: asi se ve de lejos lo que queda sin dividir dos
   numeros de cabeza. La cifra esta escrita, la barra es la forma. */
.gauges { display: flex; flex-direction: column; gap: calc(var(--space) * 4); margin: 0; padding: 0; list-style: none; }
.gauge-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: calc(var(--space) * 3);
  margin: 0;
  font-size: 15px;
}
.gauge-name { color: var(--ink-soft); }
.gauge-count { flex: none; font-weight: 650; font-variant-numeric: tabular-nums; }
.gauge-open { margin-left: calc(var(--space) * 2); color: var(--ink-soft); font-weight: 400; }
.gauge-track {
  display: block;
  height: 6px;
  margin-top: calc(var(--space) * 2);
  border-radius: var(--r-pill);
  background: var(--hairline);
}
.gauge-fill { display: block; height: 6px; border-radius: var(--r-pill); background: var(--plate); }
/* Un tope alcanzado se dice con el color de lo que va mal, y ademas con la
   cifra, que ya esta escrita al lado. */
.gauge-fill.gauge-full { background: var(--alarm); }

/* Las formulas, en una tabla: cada rotulo una vez, a la izquierda, y una
   columna por formula. La que se lleva es la columna encendida -tinte y
   texto hondo, como todo lo encendido-, con los extremos redondeados para
   que se lea como una pieza de arriba abajo y no como casillas pintadas.
   Si la consola crea una cuarta formula y no cabe, la tabla se corre dentro
   de su marco y la pagina no se desborda. */
.plan-table-frame { margin: 0 calc(var(--space) * -2); overflow-x: auto; }
.plan-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.plan-table th, .plan-table td { padding: calc(var(--space) * 3) var(--space); vertical-align: middle; }
.plan-table tbody th { padding-left: calc(var(--space) * 2); }
.plan-table tbody th, .plan-table tbody td { border-top: 1px solid var(--hairline); }
.plan-table tbody th { font-weight: 400; color: var(--ink-soft); text-align: left; }
.plan-table tbody td { text-align: center; font-weight: 650; }
/* Las columnas de las formulas miden lo que su cifra y su precio; el resto
   del ancho es para los rotulos, que son lo que se parte en lineas. */
.plan-table thead th { width: 60px; vertical-align: top; text-align: center; }
.plan-table-name { display: block; font-size: 16px; font-weight: 700; letter-spacing: -0.01em; }
.plan-table-price {
  display: block;
  margin-top: calc(var(--space) * 1);
  font-size: 14px;
  font-weight: 400;
  color: var(--ink-soft);
}
/* Entre los topes y lo que trae una formula, un filo mas marcado: son dos
   preguntas distintas, cuanto cabe y que hace. */
.plan-table tbody + tbody tr:first-child > * { border-top-color: var(--rule); }
.plan-table .icon { display: inline-block; vertical-align: middle; color: var(--plate); }
.plan-table-off .icon { color: var(--dash); }

.plan-table .plan-table-mine { background: var(--plate-tint); color: var(--plate-deep); }
.plan-table thead .plan-table-mine { border-radius: var(--r-card) var(--r-card) 0 0; }
.plan-table .plan-table-mine .plan-table-price { color: var(--plate-deep); }
.plan-table > :last-child > tr:last-child > .plan-table-mine { border-radius: 0 0 var(--r-card) var(--r-card); }
.plan-table .plan-table-mine .icon { color: var(--plate-deep); }
.plan-table tfoot td { padding-top: calc(var(--space) * 4); text-align: center; }

.plan-table-note { margin: calc(var(--space) * 4) 0 0; }

/* El veredicto de la pantalla de salud. Una frase, y el punto de delante dice
   lo mismo que la frase para quien no distingue el verde del óxido. */
.verdict {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  margin: 0 0 calc(var(--space) * 8);
  font-size: 18px;
  font-weight: 600;
}
.verdict::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: var(--r-pill);
  background: currentcolor;
}
.verdict.well { color: var(--stage-ready); }
.verdict.unwell { color: var(--alarm); }

/* La salida. Es lo único de esta barra que lleva a otra aplicación, así que se
   separa del nombre y no del todo: nadie tiene que buscarla. */
.leave { margin-left: auto; font-size: 15px; font-weight: 550; white-space: nowrap; }

/* Los chips de la lista de cuentas. Cada uno dice a la vez qué hay y qué se
   está mirando: el número contesta la pregunta antes de hacerla. */
.chips { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 2); margin-bottom: calc(var(--space) * 5); }
.chip, .chip:visited {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 40px;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--ink-soft);
  font-size: 15px;
  font-weight: 550;
  text-decoration: none;
}
.chip:hover { border-color: var(--ink-soft); color: var(--ink); }
.chip.current, .chip.current:visited { background: var(--plate-tint); border-color: transparent; color: var(--plate-deep); font-weight: 650; }
.chip .count { color: inherit; opacity: 0.7; font-variant-numeric: tabular-nums; }

/* Una fila que se marca: la casilla delante y fuera del enlace, porque son
   dos cosas que se tocan y no comparten pieza. El resto es una fila de lista
   como todas, con su nombre, su línea gris y su galón. */
.rows li.picking { flex-wrap: nowrap; gap: calc(var(--space) * 3); }
.rows li.picking > a { flex: 1; min-width: 0; }
/* Donde la fila no lleva a ninguna parte, tocarla entera marca: la casilla
   sola es un blanco de veinte píxeles. */
.rows li.picking > .pick-what { display: flex; flex: 1; flex-direction: column; gap: 2px; min-width: 0; padding-block: calc(var(--space) * 2); cursor: pointer; }
.picked-bar.settled .stack { max-width: none; }
.picked-bar.settled .hint { margin: 0; }
.rows input[type="checkbox"], .pick-all input[type="checkbox"] { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--plate); }
.pick-all {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 3);
  min-height: 44px;
  margin-top: calc(var(--space) * -2);
  border-bottom: 1px solid var(--hairline);
  font-size: 14px;
  font-weight: 550;
  color: var(--ink-soft);
  cursor: pointer;
}
/* El estado va pegado al nombre: es de quien es, no otro dato de la línea. */
.place-name .state { margin-left: calc(var(--space) * 2); vertical-align: 1px; }
/* Lo que está parado se dice con palabra y con color, no solo con color. */
.meta .held { color: var(--alarm); font-weight: 650; }
.narrow-by { margin-bottom: calc(var(--space) * 5); }

/* La barra de lo marcado. Se queda pegada abajo porque es donde está la mano
   cuando se acaba de marcar la última fila, y no existe si no hay nada. Flota
   y lleva el filo azul de lo elegido: con el blanco y el filo de una tarjeta
   se leía como otra fila más de la lista. */
.picked-bar {
  position: sticky;
  /* Por encima del muelle, que flota abajo en un móvil: pegada al borde se
     quedaba debajo de él con el botón tapado. */
  bottom: calc(var(--space) * 19 + max(var(--space) * 6, var(--band-bottom)));
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--space) * 3);
  margin-top: calc(var(--space) * 4);
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border: 2px solid var(--plate);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}
@media (min-width: 760px) {
  body.console .picked-bar { bottom: calc(var(--space) * 4); }
}
/* `display: flex` gana al `[hidden]` del navegador, y la barra salía con la
   selección vacía. */
.picked-bar[hidden] { display: none; }
/* La de borrar visitas va en su sitio, debajo de la lista: pegada abajo tapaba
   las casillas que se acababan de marcar, y lo que borra se lee antes de
   escribir el nombre, no mientras se desplaza. */
.picked-bar.settled { position: static; flex-direction: column; align-items: stretch; border-color: var(--alarm); }
.picked-count { margin: 0; font-size: 15px; font-weight: 650; color: var(--plate-deep); font-variant-numeric: tabular-nums; }
.picked-does { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2); margin-left: auto; }
.picked-does > button { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); min-height: 44px; padding: 0 calc(var(--space) * 4); font-size: 14px; }
.picked-does > button .icon { width: 18px; height: 18px; color: var(--ink-soft); }
.picked-does > .with-button { width: auto; }
.picked-does > .with-button > select { flex: 0 1 auto; padding-right: calc(var(--space) * 8); }

/* Un panel con precio a la derecha y el nombre a la izquierda: son lo mismo
   leído de dos maneras y van en la misma línea. */
.panel-top { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: calc(var(--space) * 3); }
.panel-top .panel-name, .panel-top .panel-price { margin-bottom: calc(var(--space) * 4); }
.panel-does { margin: calc(var(--space) * 4) 0 0; }
/* El título de una sección con su botón al lado va pegado arriba, como el
   que va solo: `.panel > h2` no lo alcanza dentro de su fila. */
.panel > .panel-top:first-child h2 { margin-top: 0; }
.panel.now .rows { margin: 0; }
.message-sheet { padding-bottom: 0; overflow: hidden; }
/* Con la hoja de qué día vuelve abierta, la ficha no la recorta. */
.message-sheet:has(.postpone[open]) { overflow: visible; }
.message-sheet .notice-foot { margin: calc(var(--space) * 4) calc(var(--space) * -5) 0; }
.message-body { margin: calc(var(--space) * 2) 0; }
/* Una persona del equipo: el nombre y, debajo, lo que puede hacer. */
.member-name { display: flex; flex-direction: column; padding-block: calc(var(--space) * 2); }
/* Una dirección que se copia: su nombre encima y el texto entero debajo, que
   se parte donde haga falta y se selecciona de un toque. */
.rows li.address { flex-direction: column; align-items: stretch; gap: calc(var(--space) * 1); padding-block: calc(var(--space) * 3); }
.address-name { font-weight: 550; }
.address code { overflow-wrap: anywhere; user-select: all; color: var(--ink-soft); font-size: 13px; }
.address-form { margin-top: calc(var(--space) * 4); }
/* El pie de un paso del asistente: guardar y seguir, y debajo saltárselo, los
   dos a lo ancho. Lo último, dónde vuelve a estar esto. */
.onward { display: flex; flex-direction: column; gap: calc(var(--space) * 3); margin: calc(var(--space) * 6) 0 0; }
.onward .panel-save { margin: 0; }
.onward-later { margin: 0; text-align: center; }
/* El botón que cierra un formulario de panel, cuando el panel es una lista
   larga de interruptores o campos: a lo ancho, alto de pulgar, con su dibujo
   y su palabra. Una píldora pequeña al final de nueve filas se perdía debajo
   de la última y parecía otra fila más. Ver docs/DESIGN.md, "Botones". */
button.panel-save, summary.panel-save, a.panel-save {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 2);
  width: 100%;
  min-height: 52px;
  font-size: 16px;
}
button.panel-save .icon, summary.panel-save .icon, a.panel-save .icon { width: 18px; height: 18px; }

/* Un enlace que hace de botón. Lo es cuando lleva a la pantalla de crear algo:
   no cambia nada por sí mismo, así que no puede ser un botón de verdad. */
.button-link, .button-link:visited {
  display: inline-flex;
  align-items: center;
  min-height: 46px;
  padding: 0 calc(var(--space) * 5);
  border: 1px solid var(--plate);
  border-radius: var(--r-pill);
  background: var(--plate);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--lift-rest);
}
.button-link:hover { background: var(--plate-deep); border-color: var(--plate-deep); color: #fff; }
/* La fila de lo que se puede hacer en una pantalla: modificar, borrar, empezar
   otra cosa. Todo lo que hay dentro se dibuja igual —la píldora blanca con un
   filo—, venga de un enlace o de un formulario: al pulgar le da igual cuál de
   los dos es, y dos cosas que se pulsan igual no pueden parecer distintas. */
.does {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--space) * 3);
  margin: calc(var(--space) * 6) 0;
}
.does form { margin: 0; }
.does > a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: 0;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--ink);
  font-weight: 550;
  text-decoration: none;
  box-shadow: var(--lift-rest);
}
.does > a:hover { border-color: var(--ink-soft); }
/* Lo que empieza algo sí es el azul: en una fila de cuatro píldoras blancas,
   la que abre trabajo nuevo es la que se busca. */
/* El fondo va aquí y no solo en `.button-link`: `.does > a` pesa más que una
   clase suelta, así que sin esto la píldora azul salía blanca con letra
   blanca dentro, es decir, vacía. */
.does > a.button-link { background: var(--plate); border-color: var(--plate); color: #fff; }
.does > a.button-link:hover { background: var(--plate-deep); border-color: var(--plate-deep); }
.does button, .does input[type="submit"] { min-height: 44px; }

/* Una promoción: el código y en qué anda en la primera línea, lo que da y a
   quién se le dio debajo, y revocar a la derecha, que es lo único que se le
   hace. El código se escribe como se lee al dictarlo, ancho y separado. */
.rows li.code-row { flex-wrap: nowrap; align-items: center; gap: calc(var(--space) * 4); padding-block: calc(var(--space) * 3); }
.code-said { display: flex; flex: 1; flex-direction: column; gap: calc(var(--space) * 1); min-width: 0; }
.code-said .place-name { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2); }
.code-word { font-weight: 700; letter-spacing: 0.06em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.code-said .meta a { min-height: 32px; color: var(--plate); }
.code-said .meta time { color: var(--ink-soft); }
.rows li.code-row > form { flex: none; }

/* En qué anda una promoción, en una palabra y en un color. */
.state {
  display: inline-flex;
  align-items: center;
  padding: 0 calc(var(--space) * 2);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 650;
}
.state.live { background: var(--plate-tint); color: var(--plate-deep); }
.state.revoked, .state.expired { color: var(--alarm); }

/* Doce meses en barras. Una lista de doce números no dice si sube o baja, y es
   lo único que se le pregunta a esa sección. La barra es decoración: el número
   está escrito al lado y se lee igual sin ver el color. */
.bars { display: flex; flex-direction: column; gap: calc(var(--space) * 2); margin: 0; padding: 0; list-style: none; }
.bars li { display: grid; grid-template-columns: 80px 1fr 32px; align-items: center; gap: calc(var(--space) * 3); }
.bar-name { color: var(--ink-soft); font-size: 14px; }
.bar-track { height: 10px; border-radius: var(--r-pill); background: var(--hairline); }
/* El relleno es un SVG vacío al que la vista le da el ancho como atributo: la
   política de contenido no deja pasar un `style=`, y con uno todos los meses
   se dibujaban llenos. El color y el radio se los pone aquí. */
.bar-fill { display: block; height: 10px; border-radius: var(--r-pill); background: var(--plate); }
.bar-count { font-size: 14px; font-weight: 650; text-align: right; font-variant-numeric: tabular-nums; }

/* ── Formularios ──────────────────────────────────────────────────────────
   Se rellenan de pie, con el móvil en una mano. Campos altos, bordes
   tranquilos, y el foco siempre visible. */
.stack { display: flex; flex-direction: column; gap: calc(var(--space) * 2); max-width: 420px; }
/* Un botón mide lo que dice, no lo que mide el formulario. Estirado al ancho
   de la columna deja de parecer un botón y parece una barra. Ver DESIGN.md. */
.stack input[type="submit"], .stack button[type="submit"] { align-self: flex-start; }
.stack label { font-size: 14px; font-weight: 550; color: var(--ink-soft); }
.stack.wide { max-width: 640px; }

/* Dos campos cortos en una línea. Un código postal y una ciudad son un dato
   partido en dos, y uno debajo del otro los separa más de lo que están. En un
   móvil vuelven a la pila, porque ahí no caben dos. */
.two-up { display: grid; grid-template-columns: 1fr; gap: calc(var(--space) * 2); }
.two-up .field { display: flex; flex-direction: column; gap: calc(var(--space) * 1); }
/* Dos campos cortos -dos cifras- van lado a lado también en un teléfono. */
.two-up.two-up-narrow { grid-template-columns: 1fr 1fr; gap: calc(var(--space) * 3); }
.panel > .two-up + .field { margin-top: calc(var(--space) * 2); }
@media (min-width: 480px) {
  .two-up { grid-template-columns: 1fr 1fr; gap: calc(var(--space) * 3); }
}

input[type="text"], input[type="email"], input[type="number"], input[type="password"],
input[type="datetime-local"], input[type="date"], input[type="time"], input[type="tel"],
input[type="search"], input[type="url"], select, textarea {
  width: 100%;
  min-height: 46px;
  padding: calc(var(--space) * 2) calc(var(--space) * 3);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  background: var(--card);
  color: inherit;
  font: inherit;
  box-shadow: inset 0 1px 1px rgb(22 24 28 / 3%);
}
textarea { min-height: 96px; line-height: 1.5; resize: vertical; }
/* El desplegable del sistema se deja dibujado igual que un campo para quien
   entre sin JavaScript. Con JavaScript se tapa y encima va `.chooser`, que es
   la lista de la casa: ver más abajo. */
select {
  appearance: none;
  padding-right: calc(var(--space) * 10);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%235F6873' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-position: right calc(var(--space) * 4) center;
  background-size: 12px 8px;
  background-repeat: no-repeat;
  cursor: pointer;
}
@media (hover: hover) {
  select:hover { border-color: var(--ink-soft); }
}
input:focus, select:focus, textarea:focus { border-color: var(--plate); }

/* ── El desplegable de la casa ────────────────────────────────────────────
   La rueda gris de Android no se parece a nada de aquí, y la lista del
   navegador tampoco. Esta se dibuja con el mismo papel, la misma tipografía y
   el mismo radio que todo lo demás, y es igual en un móvil y en un escritorio.

   El `select` de verdad sigue debajo y sigue siendo el que viaja en el
   formulario: sin JavaScript no hay `.chooser` y se ve el nativo de siempre. */
.chooser { position: relative; width: 100%; }

/* Tapado, no borrado: un campo con `display: none` deja de contar para el
   formulario en algunos navegadores, y este tiene que contar siempre. */
.chooser-real {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  min-height: 0;
  opacity: 0;
  pointer-events: none;
}

/* Lo elegido, en la misma caja que un campo de texto. No es una píldora azul:
   esto no se pulsa para hacer algo, se pulsa para elegir. */
.chooser-shown {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--space) * 3);
  width: 100%;
  min-height: 46px;
  padding: calc(var(--space) * 2) calc(var(--space) * 3);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  background: var(--card);
  color: var(--ink);
  font: inherit;
  font-weight: 400;
  text-align: left;
  box-shadow: inset 0 1px 1px rgb(22 24 28 / 3%);
  cursor: pointer;
}
.chooser-shown::after {
  content: "";
  flex: none;
  width: 12px;
  height: 8px;
  background: currentColor;
  color: var(--ink-soft);
  clip-path: polygon(9% 18%, 0 32%, 50% 82%, 100% 32%, 91% 18%, 50% 60%);
}
.chooser-shown:hover { background: var(--card); border-color: var(--ink-soft); }
.chooser-shown:active { transform: none; box-shadow: inset 0 1px 1px rgb(22 24 28 / 3%); }
.chooser-shown[aria-expanded="true"] { border-color: var(--plate); }
/* Lo que todavía no se ha elegido se lee apagado: "En cualquier sitio" no es
   una respuesta, es la falta de una. */
.chooser-empty .chooser-label { color: var(--ink-soft); }
.chooser-shown:disabled { background: var(--paper); color: var(--ink-soft); cursor: default; }
.chooser-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* La lista flota por encima del flujo, como todo lo que se abre encima de una
   pantalla. Se recorta a la altura de la pantalla y no a un número de filas:
   una lista de treinta ciudades es una lista, no una ventana. */
.chooser-list {
  position: absolute;
  z-index: 30;
  top: calc(100% + var(--space));
  left: 0;
  right: 0;
  max-height: min(320px, 50vh);
  overflow-y: auto;
  padding: var(--space);
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  background: var(--card);
  box-shadow: var(--lift-float);
  overscroll-behavior: contain;
}
/* Un desplegable al pie de la pantalla abre hacia arriba: abajo no cabe. */
.chooser-list.chooser-up { top: auto; bottom: calc(100% + var(--space)); }

.chooser-choice {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 44px;
  padding: 0 calc(var(--space) * 3);
  border: 0;
  border-radius: var(--r-row);
  background: none;
  color: var(--ink);
  font: inherit;
  text-align: left;
  box-shadow: none;
  cursor: pointer;
}
.chooser-choice:hover { background: var(--paper); color: var(--ink); }
.chooser-choice:active { transform: none; }
.chooser-choice[aria-selected="true"] { background: var(--plate-tint); color: var(--plate-deep); font-weight: 650; }
.chooser-choice:disabled { color: var(--ink-faint); cursor: default; }
.chooser-choice:disabled:hover { background: none; }
/* El filo de foco va por dentro: la lista recorta lo que se sale, y un filo
   por fuera del primero y del último se queda cortado a la mitad. */
.chooser-choice:focus-visible { outline: 2px solid var(--plate); outline-offset: -2px; }
.chooser-choice[hidden] { display: none; }
/* El nombre de un grupo de opciones -el día, sobre sus horas-: se lee, no se
   pulsa. */
.chooser-group { margin: calc(var(--space) * 2) 0 0; padding: calc(var(--space) * 2) calc(var(--space) * 3) calc(var(--space) * 1); color: var(--ink-soft); font-size: 13px; font-weight: 650; }
.chooser-group:first-child { margin-top: 0; }

/* El buscador de una lista larga va el primero y se queda arriba mientras la
   lista corre debajo: lo que se busca se corrige sin volver a subir. */
.chooser-search {
  position: sticky;
  top: calc(var(--space) * -1);
  z-index: 1;
  width: 100%;
  margin-bottom: var(--space);
  box-shadow: 0 calc(var(--space) * -1) 0 var(--card);
}

/* Lo escrito no deja ninguna: se dice, en gris, donde estarían. */
.chooser-none { margin: 0; padding: calc(var(--space) * 3); color: var(--ink-soft); font-size: 15px; }
.chooser-none[hidden] { display: none; }

/* La puerta es oscura y la lista no puede salir blanca encima. */
.door .chooser-shown {
  border-color: var(--night-rule);
  background: var(--night-soft);
  color: var(--night-ink);
  box-shadow: none;
}
.door .chooser-shown::after { color: var(--night-ink-soft); }
.door .chooser-list { border-color: var(--night-rule); background: #10182A; }
.door .chooser-choice { color: var(--night-ink); }
.door .chooser-choice:hover { background: var(--night-soft); color: var(--night-ink); }

/* El botón es una píldora: se ve que se pulsa antes de leer lo que dice, y se
   hunde un pelo al pulsarla. */
input[type="submit"], button {
  min-height: 46px;
  padding: 0 calc(var(--space) * 5);
  border: 1px solid var(--plate);
  border-radius: var(--r-pill);
  background: var(--plate);
  color: #fff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--lift-rest);
}
input[type="submit"]:hover, button:hover { background: var(--plate-deep); border-color: var(--plate-deep); }
input[type="submit"]:active, button:active { transform: translateY(1px); box-shadow: none; }

.quiet button, button.quiet, button.small.quiet, input[type="submit"].quiet {
  background: var(--card);
  color: var(--ink);
  border-color: var(--rule);
  font-weight: 550;
}
.quiet button:hover, button.quiet:hover, input[type="submit"].quiet:hover { background: var(--paper); border-color: var(--ink-soft); }
/* Y un enlace dibujado como botón también puede ser el callado: dejar las cosas
   como estaban no pesa lo mismo que moverle la hora a dos clientes. */
a.button-link.quiet, a.button-link.quiet:visited, summary.button-link.quiet { background: transparent; border-color: var(--rule); color: var(--ink-soft); }
a.button-link.quiet:hover, summary.button-link.quiet:hover { background: var(--paper); border-color: var(--ink-soft); color: var(--ink); }

.triage button.small, button.small { min-height: 44px; padding: 0 calc(var(--space) * 4); font-size: 14px; }

/* Lo que no se deshace. Va al final de la pantalla, detrás de un pliegue, y con
   una sola línea roja que la separa del resto: --alarm es lo que se ha roto, y
   un borrado a propósito todavía no lo está. Ver docs/DESIGN.md. */
.grave { margin-top: calc(var(--space) * 12); padding-top: calc(var(--space) * 6); border-top: 1px solid var(--alarm); }
.grave h2 { color: var(--alarm); }
.grave details { margin-top: calc(var(--space) * 4); }
.grave details > summary, .rows details > summary { cursor: pointer; }
.grave details[open] > summary { margin-bottom: calc(var(--space) * 2); font-weight: 600; }
.grave .stack { margin-top: calc(var(--space) * 3); }

/* El selector lleva el tipo a propósito: `input[type="submit"]` pesa más que
   una clase suelta, y sin esto el botón de borrar salía azul. */
input[type="submit"].grave-button, button.grave-button { background: var(--alarm); border-color: var(--alarm); }
input[type="submit"].grave-button:hover, button.grave-button:hover { background: #9E3624; border-color: #9E3624; }

/* Un pliegue se abre, y hay que verlo antes de pulsarlo: el color no basta. */
.grave details > summary::after {
  content: "";
  width: 7px;
  height: 7px;
  border-right: 2px solid currentcolor;
  border-bottom: 2px solid currentcolor;
  transform: translateY(-2px) rotate(45deg);
}
.grave details[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.grave details > summary { display: flex; align-items: center; gap: calc(var(--space) * 2); }

:focus-visible { outline: 3px solid var(--plate); outline-offset: 2px; }

/* Un enlace solo en un párrafo sin clase es una acción, no una frase: se
   dibuja como un botón tranquilo para que el pulgar sepa dónde va. Un párrafo
   con clase es contenido —un título de resultado, una pista— y se queda como
   está. */
main p:not([class]) > a:only-child, .back-link > a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--ink);
  font-weight: 550;
  text-decoration: none;
  box-shadow: var(--lift-rest);
}
main p:not([class]) > a:only-child:hover, .back-link > a:hover { border-color: var(--ink-soft); }
main p a { min-height: 44px; display: inline-flex; align-items: center; margin-right: calc(var(--space) * 4); }

/* Un taller que empieza no tiene nada que mirar. La pantalla vacía no es un
   dibujo con una frase simpática: dice qué va a pasar y por dónde se empieza.
   Ver docs/DESIGN.md. */
.start { margin-top: calc(var(--space) * 6); }
.start .lede { margin-bottom: calc(var(--space) * 5); }
.start-doors { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 3); margin: 0; }

/* ── La bienvenida ────────────────────────────────────────────────────────
   La primera pantalla, y una sola: quién es y cómo se llama. El idioma ya
   viene del navegador, así que no se pregunta arriba: se corrige abajo, donde
   está quien lo necesita y no estorba a quien no. Ver docs/SPEC.md 16. */
.welcome { max-width: 460px; margin: 0 auto; padding-top: calc(var(--space) * 6); }
.welcome .mark { margin-bottom: calc(var(--space) * 5); }
.welcome-who { margin: calc(var(--space) * -2) 0 calc(var(--space) * 6); color: var(--ink-soft); font-size: 14px; }
.welcome .stack { max-width: none; gap: calc(var(--space) * 4); }

.cards { display: flex; flex-direction: column; gap: calc(var(--space) * 3); margin: 0; padding: 0; border: 0; }

/* ── La entrada ───────────────────────────────────────────────────────────
   Las dos pantallas de entrar: la dirección y el código. No son pantallas de
   trabajo ni son la puerta: son un umbral, y por eso lo único que hay es una
   tarjeta centrada con la marca encima. Nada más cabe aquí. */
.gate {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--space) * 6);
  min-height: 72vh;
  justify-content: center;
  padding-block: calc(var(--space) * 8);
}

/* La tarjeta flota: es lo único que hay en la pantalla y no está apoyada en
   una lista, así que la altura la separa del papel. */
.gate-card {
  width: 100%;
  max-width: 400px;
  padding: calc(var(--space) * 8);
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}

.gate-card h1 { margin: 0 0 calc(var(--space) * 2); font-size: 26px; }
.gate-card .lede { margin: 0 0 calc(var(--space) * 6); }

/* Aquí el botón sí cruza la tarjeta de lado a lado: no hay nada más que pulsar
   en toda la pantalla, y el pulgar llega desde donde esté. */
.gate-form { max-width: none; gap: calc(var(--space) * 2); }
.gate-form input[type="submit"] { align-self: stretch; margin-top: calc(var(--space) * 2); }
.gate-form input[type="email"], .gate-form input[type="text"] { min-height: 52px; font-size: 17px; }

/* El código se lee de un correo y se teclea de memoria: ancho, separado y en
   cifras grandes, para no perder el sitio a medias. */
.code-field {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: 0.34em;
  text-align: center;
  text-indent: 0.34em;   /* compensa el espacio que la última cifra arrastra */
}

.mark { display: flex; align-items: center; gap: calc(var(--space) * 3); margin: 0 0 calc(var(--space) * 6); }
.mark-icon { border-radius: 10px; }
.mark-name { font-size: 19px; font-weight: 700; letter-spacing: -0.02em; }

.gate-fine { margin: calc(var(--space) * 6) 0 0; color: var(--ink-soft); font-size: 14px; }

/* Pedir otro código y cambiar de dirección son la misma cosa dicha dos veces:
   van juntos, pequeños, y ninguno de los dos parece el botón principal. */
.gate-again { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 4); margin-top: calc(var(--space) * 5); }
.gate-again form { margin: 0; }

button.as-link, .as-link, a.as-link:visited {
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: var(--plate);
  font-size: 14px;
  font-weight: 550;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
button.as-link:hover, .as-link:hover { background: none; color: var(--plate-deep); }
button.as-link:active { transform: none; }

.gate .tongues { margin-top: 0; }

/* El alta del segundo factor necesita sitio para el QR, y el QR necesita
   marco blanco alrededor o la cámara del teléfono no lo encuentra. */
.gate-card.wide-card { max-width: 460px; }
.qr {
  width: 216px;
  margin: 0 auto calc(var(--space) * 5);
  padding: calc(var(--space) * 3);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background: #fff;
}
.qr svg { display: block; width: 100%; height: auto; }

.by-hand { margin-bottom: calc(var(--space) * 6); font-size: 14px; }
.by-hand > summary { cursor: pointer; color: var(--ink-soft); }
/* La clave escrita se copia a mano, cifra a cifra: separada y en grupos. */
.secret {
  margin: calc(var(--space) * 2) 0 0;
  padding: calc(var(--space) * 3);
  border-radius: var(--r-row);
  background: var(--paper);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 15px;
  letter-spacing: 0.12em;
  overflow-wrap: anywhere;
}

/* ── La puerta ────────────────────────────────────────────────────────────
   La pantalla que ve quien llega de fuera, y la única del producto que no es
   papel claro. No es una contradicción con DESIGN.md: la aplicación se usa de
   pie en un taller con las puertas abiertas, y esto se lee sentado. En cuanto
   se entra, todo vuelve a ser papel.

   Los tokens de la puerta viven aquí y no en :root a propósito: nada de lo de
   abajo puede escaparse a una pantalla de trabajo. El azul es el mismo de la
   matrícula, subido hasta que se lee sobre lo oscuro; los colores de etapa son
   los mismos de siempre, que es lo que permite enseñar el producto de verdad. */
.door {
  --night: #0E1620;
  --night-soft: #16202B;
  --night-rule: #253243;
  --night-ink: #F1F3F6;
  --night-ink-soft: #A3B0C0;
  --beam: #7FA6EE;      /* --plate a plena luz: el mismo azul, legible en negro */
  --beam-deep: #4F7BD0;

  max-width: 1040px;
  margin: 0 auto;
  color: var(--night-ink);
}

/* El fondo oscuro cruza la pantalla entera, no solo la columna: se pinta en la
   raíz y en el cuerpo, que es lo único que alcanza también al rebote del final
   de la página y a las bandas del sistema. Nada de capas por debajo: desde que
   la raíz tiene su propio fondo, el del cuerpo ya no se propaga al lienzo y
   tapaba cualquier cosa puesta detrás. El valor va escrito porque `--night`
   vive dentro de `.door` y aquí todavía no se ve. */
html:has(.door), body:has(.door) { background: #0E1620; color-scheme: dark; }
main:has(.door) { max-width: none; padding: 0; }

.door h2, .door h3 { letter-spacing: -0.02em; }
.door h2 { margin: 0 0 calc(var(--space) * 4); font-size: clamp(30px, 4.4vw, 46px); font-weight: 700; line-height: 1.1; }
.door h3 { margin: 0 0 calc(var(--space) * 3); font-size: 21px; font-weight: 700; }
.door p { margin: 0 0 calc(var(--space) * 4); }

/* La cabecera: marca, la frase de una línea en medio, y las dos puertas. Es
   la de Fizzy y funciona porque la frase es una y cabe. */
.door-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--space) * 3) calc(var(--space) * 6);
  padding: calc(var(--space) * 5) 0;
}
.door-brand { order: 1; margin: 0; color: var(--night-ink); font-size: 22px; font-weight: 700; letter-spacing: -0.02em; }
/* La frase va en medio y las puertas al final aunque en el HTML vengan al
   revés: en el documento entran primero las dos puertas, que es lo que busca
   quien llega a entrar y lo primero que tiene que encontrar el teclado. */
.door-pitch { order: 2; flex: 1; margin: 0; min-width: 220px; color: var(--night-ink-soft); font-size: 15px; }
.door-ways { order: 3; display: flex; flex-wrap: wrap; align-items: center; margin-left: auto; gap: calc(var(--space) * 3); }
/* En un ordenador la pieza se disuelve y la marca, la frase y las puertas
   vuelven a ser tres cosas de la misma línea. */
.door-head { display: contents; }

/* Un enlace que es una acción es la misma píldora que un botón: llena para lo
   que se quiere que se pulse, con un filo para lo de al lado. */
.door-button, .door-quiet {
  display: inline-flex;
  align-items: center;
  min-height: 46px;
  padding: 0 calc(var(--space) * 5);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: var(--beam);
  color: #10182A;
  font-weight: 650;
  text-decoration: none;
  white-space: nowrap;
}
.door-button:visited { color: #10182A; }
.door-button:hover { background: #9BBCF5; }
.door-button:active, .door-quiet:active { transform: translateY(1px); }

.door-quiet, .door-quiet:visited { background: transparent; border-color: var(--night-rule); color: var(--night-ink); font-weight: 600; }
.door-quiet:hover { border-color: var(--night-ink-soft); background: var(--night-soft); }

.door-button.big, .door-quiet.big { min-height: 56px; padding: 0 calc(var(--space) * 8); font-size: 18px; }

/* ── La foto del producto ──
   Una pantalla de Aujourd'hui dibujada con el HTML de verdad, dentro de un
   marco de navegador y sobre luz de color. Una captura envejece sola y solo
   está en un idioma; esto se traduce con la aplicación. */
.shot {
  margin: calc(var(--space) * 4) 0 calc(var(--space) * 12);
  padding: calc(var(--space) * 5) calc(var(--space) * 5) 0;
  border-radius: var(--r-panel) var(--r-panel) 0 0;
  background: linear-gradient(112deg, #F2A9C4 0%, #C9A6E8 38%, #8FB6F2 72%, #7FE3DA 100%);
}
.shot-frame {
  overflow: hidden;
  border-radius: 12px 12px 0 0;
  background: var(--card);
  box-shadow: 0 -2px 40px rgb(16 24 32 / 22%);
}
.shot-chrome { display: flex; gap: 7px; padding: calc(var(--space) * 3) calc(var(--space) * 4); border-bottom: 1px solid var(--hairline); }
.shot-chrome span { width: 11px; height: 11px; border-radius: var(--r-pill); background: var(--rule); }

/* La pantalla se corta por abajo a propósito: un tablero que termina con un
   palmo de blanco parece un tablero vacío, y lo que dice el corte es que hay
   más. Es lo que hace Fizzy con el suyo. */
.shot-screen { max-height: 520px; padding: calc(var(--space) * 5) calc(var(--space) * 6) 0; color: var(--ink); overflow: hidden; }
.shot-title { margin: 0 0 calc(var(--space) * 5); font-size: 26px; font-weight: 700; letter-spacing: -0.025em; }
.shot-band {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  margin: calc(var(--space) * 5) 0 calc(var(--space) * 1);
  font-size: 15px;
  font-weight: 650;
}
.shot-band .count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: #fff;
  font-size: 13px;
  font-weight: 650;
}
.shot-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--space) * 2) calc(var(--space) * 4);
  margin: 0;
  padding: calc(var(--space) * 3) 0;
  border-bottom: 1px solid var(--hairline);
  font-size: 15px;
}
.shot-row:last-child { border-bottom: 0; }
/* Lo que dijo el cliente va debajo, en una línea: es lo que se lee para
   decidir si corre prisa. */
/* La etapa lleva su punto y su nombre, como en todas partes: el color nunca va
   solo. Ver docs/DESIGN.md. */
.shot-stage { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); font-size: 14px; font-weight: 600; }
.shot-stage::before { content: ""; width: 8px; height: 8px; border-radius: var(--r-pill); background: currentcolor; }
.shot-stage.stage-repair { color: var(--stage-repair); }
.shot-stage.stage-quote_sent { color: var(--stage-quote); }
.shot-stage.stage-waiting_part { color: var(--stage-part); }
.shot-stage.stage-ready { color: var(--stage-ready); }
.shot-stage.stage-diagnostic { color: var(--stage-diagnostic); }

/* El titular: lo único de todo el producto que crece con la ventana. La
   segunda línea se apaga, que es lo que hace que la primera pese. */
.door-headline {
  margin: 0 0 calc(var(--space) * 14);
  font-size: clamp(38px, 6.6vw, 68px);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.03em;
  text-align: center;
}
.door-headline span { display: block; color: var(--night-ink-soft); }

/* ── La carta ──
   Una hoja de papel en mitad de la pantalla oscura. Es lo único que se lee
   despacio, y por eso es lo único que no es oscuro: dos columnas con el
   pliegue en medio, como una hoja abierta. */
.letter {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: calc(var(--space) * 12);
  margin-bottom: calc(var(--space) * 16);
  padding: calc(var(--space) * 12) calc(var(--space) * 10);
  border-radius: 4px;
  background: var(--card);
  background-image: linear-gradient(90deg, transparent calc(50% - 24px), rgb(22 24 28 / 7%) 50%, transparent calc(50% + 24px));
  color: var(--ink);
  box-shadow: 0 24px 60px -20px rgb(0 0 0 / 55%);
}
.letter p { margin: 0 0 calc(var(--space) * 5); max-width: 44ch; }
.letter-turn { font-weight: 700; }
.letter-sign { margin-top: calc(var(--space) * 8); }
.letter-who { display: block; font-weight: 700; }
.letter-role { display: block; color: var(--ink-soft); font-size: 14px; font-style: italic; }

/* ── Las bandas ── */
.door-band { padding: calc(var(--space) * 14) 0; text-align: center; }
.door-band > h2 { text-align: center; }
.door-sub { margin: 0 auto calc(var(--space) * 10); max-width: 56ch; color: var(--night-ink-soft); font-size: 19px; }

.door-halves {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: calc(var(--space) * 6);
  text-align: left;
}
.door-halves article {
  padding: calc(var(--space) * 8);
  border: 1px solid var(--night-rule);
  border-radius: var(--r-panel);
  background: var(--night-soft);
}
.door-halves p { color: var(--night-ink-soft); }
/* La escalera es la del producto y se dibuja en papel, como la ve el cliente:
   volver a pintarla en oscuro sería enseñar algo que no existe. */
.door-halves .ladder { margin-bottom: 0; }

.door-list { margin: 0; padding: 0; list-style: none; }
.door-list li { padding: calc(var(--space) * 3) 0; border-bottom: 1px solid var(--night-rule); }
.door-list li:last-child { border-bottom: 0; }

/* Lo pequeño va seguido en un solo párrafo, con el nombre de cada cosa en
   negrita: seis tarjetas con un icono cada una dirían que son seis funciones
   grandes, y no lo son. */
.door-run { margin: 0 auto; max-width: 60ch; font-size: 21px; line-height: 1.5; color: var(--night-ink-soft); }
.door-run b { color: var(--night-ink); font-weight: 700; }

.door-prices { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: calc(var(--space) * 4); text-align: left; }
.price { padding: calc(var(--space) * 6); border: 1px solid var(--night-rule); border-radius: var(--r-card); background: var(--night-soft); }
.price-name { margin: 0; color: var(--night-ink-soft); font-size: 14px; }
.price-figure { margin: calc(var(--space) * 1) 0 0; font-size: 30px; font-weight: 700; letter-spacing: -0.03em; }
.price-note { margin: calc(var(--space) * 1) 0 0; color: var(--night-ink-soft); font-size: 14px; }

/* Autoalojarse dibujado como lo que es: un plano. La retícula es la única
   textura de esta pantalla, igual que las franjas de peligro son la única de
   la aplicación. */
.blueprint {
  margin: calc(var(--space) * 4) 0;
  padding: calc(var(--space) * 16) calc(var(--space) * 8);
  border-radius: var(--r-panel);
  background-color: #16307A;
  background-image: linear-gradient(rgb(255 255 255 / 7%) 1px, transparent 1px),
                    linear-gradient(90deg, rgb(255 255 255 / 7%) 1px, transparent 1px);
  background-size: 28px 28px;
  text-align: center;
}
.blueprint h2 { margin-left: auto; margin-right: auto; max-width: 20ch; }
.blueprint p { margin: 0 auto; max-width: 58ch; color: #C9D8F7; font-size: 18px; }

/* Las preguntas: una fila por pregunta, y la respuesta debajo cuando se pide.
   Sin JavaScript, porque un <details> ya lo hace. */
.door-asks { display: flex; flex-direction: column; gap: calc(var(--space) * 3); text-align: left; }
.door-ask { border-radius: var(--r-card); background: var(--night-soft); }
.door-ask > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--space) * 4);
  min-height: 60px;
  padding: calc(var(--space) * 3) calc(var(--space) * 6);
  list-style: none;
  cursor: pointer;
  font-size: 17px;
  font-weight: 650;
}
.door-ask > summary::-webkit-details-marker { display: none; }
.door-ask > summary::after {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  background: linear-gradient(var(--night-ink-soft) 0 0) center/14px 2px no-repeat,
              linear-gradient(var(--night-ink-soft) 0 0) center/2px 14px no-repeat;
}
.door-ask[open] > summary::after { background: linear-gradient(var(--night-ink-soft) 0 0) center/14px 2px no-repeat; }
.door-ask > summary:hover { color: var(--beam); }
.door-ask p { margin: 0; padding: 0 calc(var(--space) * 6) calc(var(--space) * 6); max-width: 64ch; color: var(--night-ink-soft); }

.door-close { padding: calc(var(--space) * 16) 0 calc(var(--space) * 10); text-align: center; }
.door-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: calc(var(--space) * 3); margin: 0 0 calc(var(--space) * 4); }
.door-fine { margin: 0; color: var(--night-ink-soft); font-size: 14px; }

.door-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--space) * 4);
  padding: calc(var(--space) * 8) 0 calc(var(--space) * 14);
  border-top: 1px solid var(--night-rule);
}
.door-made { margin: 0; max-width: 52ch; color: var(--night-ink-soft); font-size: 14px; }
.door-foot .tongues { margin-top: 0; }
.door-foot .tongue, .door-foot .tongue:visited { border-color: var(--night-rule); background: transparent; color: var(--night-ink-soft); }
.door-foot .tongue:hover { background: var(--night-soft); border-color: var(--night-ink-soft); color: var(--night-ink); }
.door-foot .tongue.current, .door-foot .tongue.current:visited { background: var(--beam); border-color: transparent; color: #10182A; }

/* En un móvil: la carta deja de ser una hoja abierta y pasa a ser una hoja.
   Ver docs/DESIGN.md. */
@media (max-width: 720px) {
  .letter { grid-template-columns: 1fr; gap: 0; padding: calc(var(--space) * 8) calc(var(--space) * 6); background-image: none; }
}
/* Las dos puertas se quedan arriba también en un móvil. Estaban escondidas
   porque las mismas vuelven a salir más abajo, pero quien llega a entrar no
   baja a buscarlas: viene a entrar, y lo hace desde arriba a la derecha, que
   es donde se entra en todas partes. Caben: la marca a la izquierda, las dos
   puertas a la derecha, y la frase debajo en su línea. */
@media (max-width: 560px) {
  .door-top { gap: calc(var(--space) * 2); padding-block: calc(var(--space) * 4); }
  /* La marca y las puertas, una línea que no se parte. La frase baja sola. */
  .door-head { display: flex; align-items: center; gap: calc(var(--space) * 2); width: 100%; }
  .door-ways { margin-left: auto; gap: calc(var(--space) * 2); flex-wrap: nowrap; min-width: 0; }
  /* Apretadas, porque las dos y la marca tienen que caber en 375 px en los
     tres idiomas, y "Créer un compte" es lo que manda. */
  .door-button, .door-quiet { min-height: 40px; padding: 0 calc(var(--space) * 3); font-size: 14px; }
  .door-brand { font-size: 19px; }
  .door-pitch { flex-basis: 100%; min-width: 0; }
  .shot { margin-bottom: calc(var(--space) * 10); padding-inline: calc(var(--space) * 3); }
  .shot-screen { max-height: 380px; padding: calc(var(--space) * 4) calc(var(--space) * 4) 0; }
  .door-band, .blueprint { padding-block: calc(var(--space) * 10); }
  .blueprint { padding-inline: calc(var(--space) * 5); }
}

.cards { display: flex; flex-direction: column; gap: calc(var(--space) * 3); margin: 0; padding: 0; border: 0; }

/* La tarjeta elegida se enciende entera, no solo su botón: es lo que se ha
   dicho de uno mismo, y tiene que verse desde un brazo de distancia. */
.card-choice {
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  background: var(--card);
  box-shadow: var(--lift-rest);
}
/* Por el botón de su cabecera y no por cualquiera: la del taller lleva dentro
   los planes, que también se marcan, y se encendía sin estar elegida. */
.card-choice:has(> .choice-head input:checked) { border-color: var(--plate); box-shadow: var(--lift-float); }
.card-choice:hover { border-color: var(--ink-soft); }
.card-choice:has(> .choice-head input[type="radio"]:focus-visible) { outline: 3px solid var(--plate); outline-offset: 2px; }

.choice-head {
  display: flex;
  align-items: flex-start;
  gap: calc(var(--space) * 3);
  min-height: 44px;
  padding: calc(var(--space) * 4) calc(var(--space) * 5);
  cursor: pointer;
}
.choice-head input[type="radio"] { width: 22px; height: 22px; margin: 2px 0 0; accent-color: var(--plate); flex: none; }
.choice-title { display: block; font-size: 18px; font-weight: 650; letter-spacing: -0.01em; }
.choice-hint { display: block; margin-top: calc(var(--space) * 1); font-size: 14px; font-weight: 400; color: var(--ink-soft); }
/* Una opción que todavía no se puede elegir: apagada, sin campo, con su
   círculo vacío donde iría el de marcar, y dicha en su título. */
.card-choice.is-soon { border-style: dashed; background: transparent; box-shadow: none; }
.card-choice.is-soon:hover { border-color: var(--rule); }
.card-choice.is-soon .choice-title { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2); color: var(--ink-soft); }
.choice-off { flex: none; width: 22px; height: 22px; margin-top: 2px; border: 1.5px solid var(--rule); border-radius: 50%; }
/* En el asistente, dónde se dibuja cada día: el dibujo en su título. */
.setup-design h2 { display: flex; align-items: center; gap: calc(var(--space) * 2); }
.setup-design h2 .icon { flex: none; width: 20px; height: 20px; color: var(--plate); }
.setup-design .hint { margin: 0; }

.choice-fields {
  display: flex;
  flex-direction: column;
  gap: calc(var(--space) * 2);
  padding: 0 calc(var(--space) * 5) calc(var(--space) * 5);
}
.choice-fields[hidden] { display: none; }
.choice-fields label { font-size: 14px; font-weight: 550; color: var(--ink-soft); }
.choice-fields label + input { margin-bottom: calc(var(--space) * 1); }

/* Los planes, en una lista en el teléfono -el nombre a un lado y el precio al
   otro, que es lo que se compara- y uno al lado del otro en cuanto caben: en
   fila de tres en un teléfono, el tercero caía solo en otro renglón. */
.plan-picks {
  display: flex;
  flex-direction: column;
  gap: calc(var(--space) * 2);
  margin: calc(var(--space) * 2) 0 0;
  padding: 0;
  border: 0;
}
.plan-picks legend { margin-bottom: calc(var(--space) * 2); padding: 0; font-size: 14px; font-weight: 550; color: var(--ink-soft); }
.choice-fields .plan-pick {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: calc(var(--space) * 1) calc(var(--space) * 3);
  min-height: 48px;
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  color: var(--ink);
  cursor: pointer;
}
@media (min-width: 760px) {
  .plan-picks { flex-direction: row; }
  .choice-fields .plan-pick { flex: 1 1 0; flex-direction: column; justify-content: center; min-width: 0; min-height: 56px; padding: calc(var(--space) * 2) calc(var(--space) * 3); }
}
/* El botón de verdad sigue ahí, escondido, como en los tipos de cita: el
   teclado y el lector de pantalla encuentran un grupo de opciones. */
.plan-pick input[type="radio"] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.plan-pick-name { font-size: 15px; font-weight: 650; }
.plan-pick-price { font-size: 13px; font-weight: 450; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.plan-pick:has(input:checked) { border-color: var(--plate); background: var(--plate-tint); box-shadow: inset 0 0 0 1px var(--plate); }
.plan-pick:has(input:checked) .plan-pick-price { color: var(--plate-deep); }
.plan-pick:has(input:focus-visible) { outline: 2px solid var(--plate); outline-offset: 2px; }
@media (hover: hover) {
  .plan-pick:hover { border-color: var(--ink-soft); }
}

/* El código solo se pide con un plan de pago marcado: con el gratis no hay
   nada que abrir, y un campo de más es una pregunta de más. */
.plan-code { display: flex; flex-direction: column; gap: calc(var(--space) * 2); margin-top: calc(var(--space) * 2); }
.choice-fields:has(.plan-pick input[data-free="true"]:checked) .plan-code { display: none; }

/* Los idiomas se escriben cada uno en el suyo: en esta pantalla todavía no
   sabemos cuál habla quien mira. Ver Language. */
.tongues { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 2); margin-top: calc(var(--space) * 10); }
.tongues form { margin: 0; }
/* La píldora de un idioma es la misma se llegue por un botón —la bienvenida,
   que cambia el idioma de la cuenta— o por un enlace —la puerta, donde todavía
   no hay cuenta que cambiar—. El aspecto lo lleva la clase, no la etiqueta. */
.tongues button, .tongue {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--ink-soft);
  font-size: 15px;
  font-weight: 550;
  text-decoration: none;
  box-shadow: none;
}
.tongues button:hover, .tongue:hover { background: var(--card); border-color: var(--rule); color: var(--ink); }
.tongues button.current, .tongue.current { background: var(--plate-tint); border-color: transparent; color: var(--plate-deep); }

.switch input[type="checkbox"] { width: 22px; height: 22px; accent-color: var(--plate); }

.switch { display: flex; align-items: center; gap: calc(var(--space) * 3); min-height: 44px; }

/* Qué avisos salen por correo: una fila de Réglages por tipo, el nombre a la
   izquierda y el interruptor a la derecha. La fila entera es la etiqueta, así
   que se enciende tocando la frase, que es donde cae el pulgar. Un interruptor
   y no una casilla porque dice "llega o no llega", no "elige varios". */
.email-kinds { margin: calc(var(--space) * 2) 0 calc(var(--space) * 3); }
.email-kinds li { flex-wrap: nowrap; }
.email-kinds .email-kind {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--space) * 4);
  width: 100%;
  min-height: 52px;
  color: var(--ink);
  font-size: 16px;
  font-weight: 550;
  cursor: pointer;
}
.email-kind-said { display: flex; flex-direction: column; gap: calc(var(--space) * 1); padding: calc(var(--space) * 2) 0; }
.email-kind input[role="switch"] {
  appearance: none;
  position: relative;
  flex: none;
  width: 44px;
  height: 28px;
  margin: 0;
  border-radius: var(--r-pill);
  background: var(--rule);
  cursor: pointer;
  transition: background-color 120ms ease;
}
.email-kind input[role="switch"]::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--card);
  box-shadow: var(--lift-rest);
  transition: transform 120ms ease;
}
.email-kind input[role="switch"]:checked { background: var(--plate); }
.email-kind input[role="switch"]:checked::after { transform: translateX(16px); }
.email-kind input[role="switch"]:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

/* Lo que acaba de pasar. Se aparta con el pulgar hacia cualquier lado, o
   tocándolo: ver dismissing_controller.js. Por eso es una hoja que se mueve y
   no un párrafo, y por eso el dedo que va hacia abajo desplaza la pantalla
   -pan-y- mientras el que va de lado se lleva el aviso. */
/* Los avisos flotan arriba, encima de todo, como los de un teléfono: dentro de
   la pantalla la empujaban hacia abajo al llegar. La caja no se toca -deja
   pasar los dedos a lo de debajo-; los avisos sí. */
.flashes {
  position: fixed;
  top: calc(var(--band-top) + var(--space) * 3);
  right: 0;
  left: 0;
  z-index: 60;
  display: grid;
  gap: calc(var(--space) * 2);
  width: min(560px, calc(100% - var(--space) * 8));
  margin: 0 auto;
  pointer-events: none;
}
/* Oscuro y no blanco: un aviso blanco sobre una pantalla de tarjetas blancas
   era una tarjeta más, y lo que acaba de pasar se perdía. La tinta es el único
   fondo que no lleva ninguna otra pieza, y por eso se ve. */
.flash {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 3);
  margin: 0;
  padding: calc(var(--space) * 3) calc(var(--space) * 4) calc(var(--space) * 3) calc(var(--space) * 3);
  border: 1px solid var(--ink);
  border-radius: var(--r-card);
  background: var(--ink);
  color: #fff;
  font-weight: 550;
  line-height: 1.35;
  box-shadow: var(--lift-float);
  cursor: pointer;
  pointer-events: auto;
  touch-action: none;
  user-select: none;
  -webkit-touch-callout: none;
  animation: flash-drop 260ms cubic-bezier(0.2, 0.9, 0.3, 1.15) backwards;
}
.flash-mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r-pill);
  background: var(--plate-tint);
  color: var(--plate);
}
.flash-mark .icon { width: 18px; height: 18px; stroke-width: 2.4; }
.flash-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
/* La cruz, al final y apagada: es la salida, no lo que se viene a leer. */
.flash-close {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  margin: calc(var(--space) * -1) calc(var(--space) * -2) calc(var(--space) * -1) 0;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: none;
  color: inherit;
  opacity: 0.7;
  box-shadow: none;
  cursor: pointer;
}
.flash-close .icon { width: 18px; height: 18px; }
.flash-close:hover { opacity: 1; background: rgb(255 255 255 / 0.12); }
.flash-close:active { transform: none; }
.flash-close:focus-visible { outline: 2px solid #fff; outline-offset: 0; opacity: 1; }
/* Baja desde fuera de la pantalla y se asienta con un pelo de rebote, que es
   como llega un aviso a un teléfono. */
@keyframes flash-drop {
  from { transform: translateY(calc(-100% - var(--space) * 6)); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .flash { animation: none; }
}
/* Lo que no ha salido es lo que se ha roto: el rojo de alarma entero. */
.flash.alert { border-color: var(--alarm); background: var(--alarm); }
.flash.alert .flash-mark { background: #fff; color: var(--alarm); }
/* Mientras el dedo está encima, la hoja va con él y no llega tarde. Al
   soltarla vuelve a su sitio -o se va del todo- con la transición puesta. */
.flash:not(.swiping) { transition: transform 200ms ease-out, opacity 200ms ease-out; }
/* Se ha empujado bastante: al soltar se va. Se dice levantando el papel, que
   es lo que hace un papel al que ya se ha despegado de la mesa. */
.flash.reached { box-shadow: var(--lift-float); }
.flash.gone { opacity: 0; }

.errors {
  margin: 0 0 calc(var(--space) * 4);
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border: 1px solid var(--alarm);
  border-radius: var(--r-card);
  background: var(--card);
  color: var(--alarm);
  list-style-position: inside;
}
.errors li + li { margin-top: calc(var(--space) * 1); }

/* ── La matrícula ─────────────────────────────────────────────────────────
   El identificador real de un coche. Es el único elemento con permiso para
   llamar la atención, y se compone como la placa: banda azul con la F, fondo
   blanco, borde fino, la misma familia estrechada. Ver docs/DESIGN.md. */
.plate {
  display: inline-flex;
  align-items: stretch;
  overflow: hidden;
  min-height: 26px;
  border: 1px solid var(--ink);
  border-radius: 4px;
  background: var(--card);
  color: var(--ink);
  font-size: 15px;
  font-weight: 700;
  font-stretch: 88%;
  letter-spacing: 0.05em;
  line-height: 24px;
  padding-right: calc(var(--space) * 2);
  white-space: nowrap;
}
.plate-band {
  display: flex;
  align-items: center;
  padding: 0 calc(var(--space) * 1.5);
  margin-right: calc(var(--space) * 2);
  background: var(--plate);
  color: #fff;
  font-size: 11px;
  font-stretch: 100%;
  letter-spacing: 0;
}

/* ── Aujourd'hui ──────────────────────────────────────────────────────────
   Los colores de etapa son el sistema entero, y ninguno es rojo: el rojo es
   --alarm y dice que algo va mal. Ver docs/DESIGN.md. */
:root {
  --stage-diagnostic: #5B6B7A;
  --stage-quote:      #7A5AA6;
  --stage-part:       #9E6716;
  --stage-repair:     #0F6E80;
  --stage-ready:      #2E7D4F;
}

.screen-head { display: flex; align-items: baseline; justify-content: space-between; gap: calc(var(--space) * 4); margin-bottom: calc(var(--space) * 5); }
.screen-head h1 { margin-bottom: 0; }
/* Lo que se hace con toda la pantalla, en un icono a la derecha del título,
   como el `+` y el hoy de la agenda. Se centra con el título y no con su
   línea base: un dibujo no tiene letra en la que apoyarse. */
.screen-head-tool, .screen-head-tool:visited {
  display: inline-flex;
  flex: none;
  align-self: center;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-row);
  color: var(--ink-soft);
}
.screen-head-tool:hover { background: var(--wash); color: var(--ink); }
.screen-head-tool:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }
/* Lo que se empieza desde toda la pantalla y necesita su palabra: anotar en la
   bandeja. La misma píldora de filo sobre el papel que la fecha de Aujourd'hui:
   llena de azul era la pieza más fuerte de la pantalla, por encima de lo que
   espera en la bandeja, que es lo que se viene a mirar. Es el `summary` de su
   hoja. */
summary.screen-head-start {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink);
  font-size: 14px;
  font-weight: 550;
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
}
summary.screen-head-start::-webkit-details-marker { display: none; }
summary.screen-head-start .icon { flex: none; width: 18px; height: 18px; color: var(--ink-soft); }
summary.screen-head-start:hover,
.caller[open] > summary.screen-head-start { border-color: var(--ink-soft); background: var(--wash); }
summary.screen-head-start:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }
/* En un móvil, al lado de un título largo, la palabra no cabe: queda el
   dibujo en un círculo de pulgar y la palabra en el `aria-label`. */
@media (max-width: 559px) {
  summary.screen-head-start:has(> .screen-head-word) { justify-content: center; width: 44px; padding: 0; }
  summary.screen-head-start > .screen-head-word { display: none; }
}
.screen-head > .caller { flex: none; align-self: center; position: relative; }
/* La fecha de Aujourd'hui, que abre ese día en la agenda. Píldora de filo
   sobre el mismo papel: es un sitio al que ir, no algo que empieza, y el azul
   lleno se queda para lo que empieza. */
.screen-head-date, .screen-head-date:visited {
  display: inline-flex;
  flex: none;
  align-self: center;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink);
  font-size: 14px;
  font-weight: 550;
  text-decoration: none;
}
.screen-head-date .icon { flex: none; width: 18px; height: 18px; color: var(--ink-soft); }
.screen-head-date:hover { border-color: var(--ink-soft); background: var(--wash); }
.screen-head-date:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

/* La etapa va escrita y en su color, con un punto delante: el color solo no
   comunica nada a quien no lo distingue. */
.card-stage::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: calc(var(--space) * 2);
  border-radius: 50%;
  background: currentcolor;
  vertical-align: 0.08em;
}

.stage-diagnostic { color: var(--stage-diagnostic); }
.stage-quote_sent { color: var(--stage-quote); }
.stage-waiting_part { color: var(--stage-part); }
.stage-repair { color: var(--stage-repair); }
.stage-ready { color: var(--stage-ready); }
.stage-none { color: var(--ink-soft); }

/* Cuántos hay es un dato, no un adorno: ficha al lado del título, en la misma
   tinta secundaria que todo lo que acompaña. */
.count { font-weight: 400; color: var(--ink-soft); }
h2 .count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  height: 24px;
  padding: 0 calc(var(--space) * 2);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--card);
  font-size: 13px;
  vertical-align: 2px;
}

/* ── Las listas ───────────────────────────────────────────────────────────
   Una lista es una lista: filas separadas por una línea fina, sin tarjeta ni
   sombra. Lo que flota es lo que está por encima del flujo, y nada más. */
.rows { list-style: none; margin: 0; padding: 0; }
/* Una fila escondida está escondida: `display: flex` le gana al `hidden` del
   navegador, y quien filtraba seguía viéndolo todo. */
.rows li[hidden] { display: none; }
.rows li {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: calc(var(--space) * 1) calc(var(--space) * 4);
  min-height: 52px;
  align-items: center;
  padding-inline: calc(var(--space) * 2);
  margin-inline: calc(var(--space) * -2);
  border-bottom: 1px solid var(--hairline);
}

/* La fila entera lleva a un sitio, así que la fila entera responde. Solo donde
   hay ratón: en un móvil no existe el "por encima", y un resaltado que se queda
   pegado después del toque dice que sigues ahí cuando ya te has ido. */
@media (hover: hover) {
  .rows li:has(a):hover { background: color-mix(in srgb, var(--ink) 5%, var(--paper)); border-radius: var(--r-row) var(--r-row) 0 0; }
}
.rows li:last-child { border-bottom: 0; }
.rows li a { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); min-height: 44px; color: var(--ink); text-decoration: none; }
.rows li a:hover { color: var(--plate); }
/* La fila entera es el enlace, no solo la placa: el resto del contenido flota
   dentro de la misma pieza pulsable. */
.rows li a.full-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: calc(var(--space) * 1) calc(var(--space) * 4);
  width: 100%;
}
.rows li a.full-row > span:first-child { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); }
.places { margin-top: calc(var(--space) * 9); }
.places li a { flex: 1; font-weight: 550; }
.places li a:hover { color: var(--plate); }
/* Dentro de una tarjeta la lista ya está agrupada por el título de la tarjeta:
   el hueco de arriba separaba la lista de su propio título. */
.panel > .places { margin-top: calc(var(--space) * 4); }
.panel > .places + .panel-save { margin-top: calc(var(--space) * 4); }

/* Un sitio de Réglages: el nombre y, debajo, lo que hay dentro. Ocupa la fila
   entera —se pulsa con el pulgar, no con la punta del dedo— y lleva el galón a
   la derecha para que se lea como lo que es, algo que se abre. */
/* El selector lleva la fila a propósito: `.rows li a` pesa más que `.place a`
   y sin esto la fila se quedaba en la línea de `.rows`, con el nombre y lo que
   dice uno al lado del otro. */
.rows li.place a {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "name arrow" "hint arrow";
  gap: 2px calc(var(--space) * 3);
  width: 100%;
  padding-block: calc(var(--space) * 2);
}
.place-name { grid-area: name; font-weight: 550; }
/* Una matrícula con su coche al lado, en la línea del nombre: en tinta, como el nombre. */
.place-name.meta { color: var(--ink); gap: calc(var(--space) * 1) calc(var(--space) * 3); }
.place-hint { grid-area: hint; color: var(--ink-soft); font-size: 14px; font-weight: 400; line-height: 1.4; }
/* Lo que reclama atención en un coche: en rojo y no en una banda aparte. El
   color no va solo: la frase lo dice escrito, y el triángulo lo separa del
   punto de una etapa. */
.place-hint .place-alert { display: inline-flex; align-items: center; gap: calc(var(--space) * 1); color: var(--alarm); font-weight: 650; }
.place-alert .icon { flex: none; width: 16px; height: 16px; stroke-width: 2; }
.rows li.place a::after {
  content: "";
  grid-area: arrow;
  align-self: center;
  width: 9px;
  height: 14px;
  background: currentColor;
  color: var(--ink-faint);
  clip-path: polygon(14% 8%, 30% 0, 86% 50%, 30% 100%, 14% 92%, 58% 50%);
}
.rows li.place a:hover::after { color: var(--plate); }

/* Lo que todavía no se abre: apagado, sin galón, y dicho en su título. */
.is-soon h2 { display: flex; align-items: center; gap: calc(var(--space) * 2); color: var(--ink-soft); }
.soon { padding: 2px calc(var(--space) * 2); border: 1px solid var(--rule); border-radius: var(--r-pill); color: var(--ink-soft); font-size: 12px; font-weight: 550; }
.rows li.soon-place { display: grid; grid-template-areas: "name" "hint"; gap: 2px; padding-block: calc(var(--space) * 2); }
.soon-place .place-name { color: var(--ink-soft); }
.soon-place .place-hint { color: var(--ink-faint); }

/* Tomar el coche en carga. Es lo que se viene a hacer cuando alguien está en
   el mostrador, y pesa como tal en todas partes: lleno, a lo ancho, alto de
   pulgar, con el coche dibujado delante de la palabra. En una fila va debajo
   del enlace y aparte de él: dos cosas pulsables no comparten pieza. */
.take-in { flex-basis: 100%; width: 100%; margin: 0 0 calc(var(--space) * 3); }
.take-in button, .take-in > summary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 2);
  width: 100%;
  min-height: 52px;
  font-size: 16px;
}
.take-in .icon { flex: none; width: 20px; height: 20px; }
/* En una fila, el botón se separa de lo que dice la fila: pegado a ella, la
   línea de quién espera en el mostrador chocaba con él. */
.rows li.place > .take-in { margin-top: calc(var(--space) * 1); }
/* En la fila de una cita, el botón va a su derecha y a la altura del dedo, no
   a lo ancho: tres botones de lado a lado eran tres bandas azules y la cita se
   leía partida entre su línea y su botón. El galón sobra, porque al lado ya
   hay algo que se toca y la fila sigue abriéndose entera. */
.rows li.place:has(> .take-in) { flex-wrap: nowrap; padding-block: calc(var(--space) * 2); }
.rows li.place:has(> .take-in) > a { flex: 1; min-width: 0; }
.rows li.place:has(> .take-in) > a::after { display: none; }
.rows li.place > .take-in { flex: none; width: auto; margin: 0; }
.rows li.place > .take-in button, .rows li.place > .take-in > summary {
  min-height: 44px;
  padding: 0 calc(var(--space) * 4);
  font-size: 15px;
}
.rows li.place > .take-in .icon { width: 18px; height: 18px; }
.rows li.place > details.take-in .car-choice { left: auto; right: 0; }
.here-since { display: inline-flex; align-items: center; gap: calc(var(--space) * 1); color: var(--plate-deep); font-weight: 600; }
.here-since .icon { flex: none; width: 16px; height: 16px; }
/* Sin coche, el botón abre la hoja que pregunta cuál: es un <details>, y su
   <summary> se dibuja igual que el botón al que sustituye. */
details.take-in { position: relative; }
.take-in > summary, .ticket-does > summary, .car-pick-open { list-style: none; cursor: pointer; }
.take-in > summary::-webkit-details-marker, .ticket-does > summary::-webkit-details-marker,
.car-pick-open::-webkit-details-marker { display: none; }

/* ── Qué coche es ─────────────────────────────────────────────────────────
   La hoja que sale del botón de recibir, o del de llegar, cuando la cita se
   cogió sin coche. En un ordenador cuelga del botón; en un móvil sube desde
   abajo como todas (ver "Las hojas", al final). Arriba los coches que ya se
   conocen, uno por línea, y debajo, en el taller, otra matrícula. */
.car-choice {
  position: absolute;
  left: 0;
  top: calc(100% + var(--space) * 2);
  z-index: 30;
  width: 100%;
  min-width: 300px;
  max-width: 440px;
  padding: calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
  text-align: left;
}
.car-choice .triage { padding-bottom: 0; }
.car-choice-or { margin: calc(var(--space) * 4) 0 calc(var(--space) * 2); color: var(--ink-soft); font-size: 14px; font-weight: 600; }
.car-choice-new { margin: 0; }
.car-choice-other { margin: calc(var(--space) * 3) 0 0; }
.car-choice-other button { width: 100%; min-height: 48px; }
/* En la hoja de la cita de la agenda va suelta, debajo de quién es. */
.car-choice-here { flex-basis: 100%; margin: 0 0 calc(var(--space) * 3); }

/* La línea del billete que pregunta con qué coche se viene: se lee como la
   línea del coche que ocuparía, en azul porque se pulsa. */
.car-pick { position: relative; margin: calc(var(--space) * 3) 0 0; }
.car-pick-open {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  color: var(--plate);
  font-weight: 600;
}
.car-pick-open .icon { flex: none; width: 20px; height: 20px; }

/* Lo que ahora mismo vale, cuando no se puede cambiar desde aquí. */
.setting-now { margin: 0 0 calc(var(--space) * 1); }

/* ── El botón al lado del campo ───────────────────────────────────────────
   Un campo y el botón que lo manda son una sola cosa, y el botón debajo los
   separa: entre los dos quedaba una línea en blanco que no significa nada, y
   en un móvil empujaba el botón fuera de la pantalla. Van en la misma línea
   mientras quepan, y cuando no —un campo estrecho de verdad— el botón baja
   solo, que es lo que hace un `flex-wrap`. */
/* El campo y su botón son **una sola pieza**: el filo lo lleva la pieza, el
   campo de dentro no lleva ninguno, y el botón va posado a la derecha por
   dentro del filo. Un campo y un botón separados por un hueco son dos cosas
   que hay que relacionar mirando; esto es una.

   El foco se dibuja alrededor de la pieza entera, que es lo que se ve como un
   control: un anillo alrededor del campo de dentro, que no tiene borde propio,
   no se entendería. */
.with-button {
  display: flex;
  align-items: center;
  gap: var(--space);
  width: 100%;
  max-width: 420px;
  padding: var(--space);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--card);
  box-shadow: inset 0 1px 1px rgb(22 24 28 / 3%);
}
.with-button:focus-within { border-color: var(--plate); outline: 2px solid var(--plate); outline-offset: -2px; }
.stack.wide .with-button { max-width: 640px; }

.with-button > input:not([type="submit"]), .with-button > select, .with-button > .chooser {
  flex: 1 1 8ch;
  width: auto;
  min-width: 0;
  min-height: 44px;
  border: 0;
  border-radius: var(--r-pill);
  background: none;
  box-shadow: none;
}
.with-button > input:not([type="submit"]) { padding-left: calc(var(--space) * 4); }
.with-button > input:focus { outline: none; }
/* El desplegable de la casa dentro de la pieza: sin caja propia, porque la
   caja es la pieza. La lista que abre sí es suya y sigue igual. */
.with-button > .chooser .chooser-shown { min-height: 44px; border-color: transparent; background: none; box-shadow: none; }
.with-button > .chooser .chooser-shown:hover { border-color: transparent; }
.with-button > .chooser .chooser-shown[aria-expanded="true"] { border-color: transparent; }

/* El botón no se encoge ni se parte: si lo que dice no cabe, lo que hay que
   acortar es lo que dice. Un botón con puntos suspensivos dentro no se pulsa
   porque ya no se sabe qué hace. */
.with-button > input[type="submit"], .with-button > button {
  flex: none;
  min-height: 44px;
  padding-inline: calc(var(--space) * 4);
  white-space: nowrap;
}

.excerpt { flex-basis: 100%; color: var(--ink-soft); font-size: 14px; margin-bottom: calc(var(--space) * 2); }
code { font-size: 13px; word-break: break-all; }

/* El triaje: lo que dice el mensaje y los coches a los que puede ir, a la vez
   y sin abrir nada. Ranger cuesta un toque, y el pulgar no tiene que apuntar. */
.rows details > summary {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--space) * 2);
  align-items: baseline;
  min-height: 52px;
  padding: calc(var(--space) * 2) 0;
  cursor: pointer;
}
.rows details > summary::marker { color: var(--ink-soft); }
.said {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--space) * 1) calc(var(--space) * 3);
  align-items: baseline;
  width: 100%;
  padding-top: calc(var(--space) * 3);
}
.said .excerpt { margin-bottom: 0; }
.sender { font-weight: 650; }
.rows li.urgent .sender { box-shadow: inset 3px 0 0 var(--ink); padding-left: calc(var(--space) * 2); }
/* Las etapas a las que se puede ir llevan su color, el mismo de la tarjeta y
   el mismo de la banda. El color no va solo: la etapa está escrita al lado del
   punto, como en todas partes. */
.stage-chip { border-color: var(--rule); }
button.stage-chip.stage-diagnostic { color: var(--stage-diagnostic); }
button.stage-chip.stage-quote_sent { color: var(--stage-quote); }
button.stage-chip.stage-waiting_part { color: var(--stage-part); }
button.stage-chip.stage-repair { color: var(--stage-repair); }
button.stage-chip.stage-ready { color: var(--stage-ready); }
.stage-chip:hover { border-color: currentcolor; background: var(--paper); }
.stage-chip::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: calc(var(--space) * 2);
  border-radius: 50%;
  background: currentcolor;
}

/* Se archiva un mensaje pulsando la matrícula del coche, así que el botón es
   el soporte de la placa: se aparta y la deja verse. Al lado va de quién es el
   coche, y al final por qué se propone: se confirma lo que ya se sabe. */
.plate-button, .triage button.plate-button {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 52px;
  padding: calc(var(--space) * 2) calc(var(--space) * 3);
  background: var(--card);
  border-color: var(--rule);
  color: var(--ink);
  font-weight: 550;
  text-align: left;
}
.plate-button:hover, .triage button.plate-button:hover { background: var(--paper); border-color: var(--plate); }

.triage {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--space) * 2);
  align-items: center;
  width: 100%;
  padding-bottom: calc(var(--space) * 3);
}
/* Un coche por línea: tres matrículas en fila no se leen, y media matrícula
   no se pulsa con el pulgar. */
.triage .button_to { flex: 1 1 100%; }
.triage .button_to button.plate-button { width: 100%; }
.plate-button .plate { flex: none; }
.plate-button .who { flex: 1; min-width: 0; font-weight: 550; }
/* Lo que se sabe del coche, sin más: `.who` es la tarjeta de quién escribe y
   le ponía marco. */
.plate-button-name { flex: 1; min-width: 0; font-weight: 550; }
.plate-button .hint { flex: none; max-width: 38%; font-size: 12px; line-height: 1.2; text-align: right; }
.plate-button.wide { width: 100%; }
.rows li:has(.plate-button) { padding-block: calc(var(--space) * 1); }

/* La búsqueda solo aparece con JavaScript, porque sin él es un campo que no
   hace nada: la lista entera ya está debajo. */
.filter-field { width: 100%; margin-bottom: calc(var(--space) * 3); }

/* ── Los avisos ───────────────────────────────────────────────────────────
   Tres montones, como las citas del conductor: lo que pide algo, lo que se
   apartó para un día y lo que ya se miró. Cada montón es un pliegue con su
   nombre sobre una línea, y solo el primero viene abierto.

   Un aviso es una tarjeta y no una fila, por la misma razón que en la bandeja:
   una fila se lee y una tarjeta se empuja. A la izquierda queda vista, a la
   derecha se abre el día en que tiene que volver, y mantenerla pulsada abre lo
   mismo. Ver swipe_controller.js y docs/DESIGN.md. */
.bundle.bundle-active .bundle-name { color: var(--plate); }
.bundle.bundle-snoozed .bundle-name, .bundle.bundle-seen .bundle-name { color: var(--ink-soft); }

/* No queda nada activo. Se dice con una frase corta y una marca, no con un
   hueco: entre dos pliegues cerrados, el hueco no se lee como "está todo". */
.all-clear {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  margin: 0 0 calc(var(--space) * 5);
  color: var(--ink-soft);
  font-size: 15px;
}
.all-clear .icon { color: var(--plate); }

.notices {
  list-style: none;
  display: grid;
  gap: calc(var(--space) * 2.5);
  margin: calc(var(--space) * 3) 0 0;
  padding: 0;
}

.notice-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-card);
  background: var(--card);
  box-shadow: var(--lift-rest);
}
/* El filo redondeado recorta la cara al empujarla, pero recortaría también el
   panel de "Más tarde": mientras está abierto, la tarjeta deja de recortar y
   sube por encima del muelle, que vive a 20. Con menos, la tarjeta encerraba
   su panel -y en un móvil su hoja, aunque la hoja esté a 40- en un piso por
   debajo del muelle, que tapaba los últimos días y el botón de fijar. Es lo
   mismo que hace la franja abierta de la agenda. */
.notice-card:has(.postpone[open]), .notice-card:has(.take-in[open]) { overflow: visible; z-index: 41; }
/* Sin recorte, las esquinas las pone la cara: si no, salía recta por arriba y
   la celda gris de "Más tarde" asomaba en pico por abajo. */
.notice-card .card-face { border-radius: inherit; }
/* Lo que ya se miró se queda en su tarjeta, pero plana: sin sombra y con un
   filo fino. Apoyada en el papel sin tarjeta se leía como texto suelto con un
   botón enorme debajo, y no como lo mismo de antes ya mirado. */
.notice-card.notice-seen { box-shadow: 0 0 0 1px var(--hairline); }

/* El dibujo del tipo en su columna y todo lo escrito en la otra: los botones
   se alinean con la frase y no con el borde, y la lista se lee por la
   izquierda como una columna de dibujos. */
.notice-card .card-face {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  column-gap: calc(var(--space) * 3);
  align-items: start;
  padding: calc(var(--space) * 4) calc(var(--space) * 4) 0;
  /* Mantener pulsada una tarjeta abre su menú, así que aguantar el dedo encima
     no puede levantar la lupa del sistema ni pintar media frase de azul. */
  user-select: none;
  -webkit-touch-callout: none;
}
.notice-card.notice-seen .card-face { padding-top: calc(var(--space) * 3); }

/* Lo activo se dice en el dibujo, con el tinte del montón al que pertenece;
   lo agendado y lo visto lo llevan gris. */
.notice-mark {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink-soft);
}
.notice-card.notice-active .notice-mark { background: var(--plate-tint); color: var(--plate); }

.notice-body {
  display: flex;
  flex-direction: column;
  gap: calc(var(--space) * 1.5);
  min-width: 0;
  /* La frase va a media altura del dibujo cuando cabe en una línea. */
  padding-top: calc(var(--space) * 0.5);
}

/* Lo que pasó, escrito entero: es la única línea que hay que leer, y lleva a
   la pantalla del asunto. Sin leer no es un color, es el peso. */
.notice-what {
  display: block;
  color: var(--ink);
  font-size: 16px;
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1.3;
  text-decoration: none;
  overflow-wrap: anywhere;
}
.notice-what:hover { color: var(--plate); }
.notice-card.notice-seen .notice-what { color: var(--ink-soft); font-weight: 550; }
/* Se toca la tarjeta entera, que es lo que hace el pulgar. Los botones de
   abajo se levantan por encima con su propio z-index. */
.notice-what::after { content: ""; position: absolute; inset: 0; z-index: 0; }

.notice-about.meta { margin: 0; gap: calc(var(--space) * 1) calc(var(--space) * 2); font-size: 13px; }
.notice-about time { color: var(--ink-soft); white-space: nowrap; }
/* La matrícula aquí acompaña a la frase y no la encabeza: más pequeña que en
   la ficha, donde es lo que se busca. */
.notice-about .plate { min-height: 22px; font-size: 13px; }
.notice-about .plate-band { font-size: 10px; }

/* Cuándo vuelve lo agendado. Sin esta línea, un montón de tarjetas apartadas
   no dice para cuándo se apartó ninguna. */
.notice-until {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  margin: 0;
  color: var(--ink-soft);
  font-size: 14px;
}
.notice-until .icon { width: 16px; height: 16px; }

/* La barra de lo que se hace con el aviso, al pie y de lado a lado de la
   tarjeta, separada de lo escrito por un filo fino. Cada acción es una celda
   igual que se acierta con el pulgar entero, y entre celdas otro filo: se lee
   como el pie del aviso y no como dos píldoras sueltas debajo de la frase.
   Se levanta por encima del enlace estirado —va después en el documento y le
   basta con estar posicionada—, pero sin `z-index`: con él, la barra se
   convierte en un piso aparte y la hoja que sube desde aquí dentro se queda
   encerrada debajo del muelle. */
.notice-foot {
  position: relative;
  grid-column: 1 / -1;
  display: flex;
  margin: calc(var(--space) * 4) calc(var(--space) * -4) 0;
  border-top: 1px solid var(--hairline);
}
.notice-card.notice-seen .notice-foot { margin-top: calc(var(--space) * 3); }
/* En el aviso de quien llega, encima del pie y de lado a lado de lo escrito.
   Se levanta sobre el enlace estirado como el pie, sin `z-index`. */
.notice-card .take-in { position: relative; grid-column: 1 / -1; margin: calc(var(--space) * 4) 0 0; }
.notice-foot > form, .notice-foot > .postpone, .notice-foot > a { flex: 1 1 0; min-width: 0; margin: 0; }
.notice-foot > * + * { border-left: 1px solid var(--hairline); }

.notice-act {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 2);
  width: 100%;
  min-height: 48px;
  padding: 0 calc(var(--space) * 2);
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: var(--ink-soft);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.notice-act > span { overflow-wrap: anywhere; }
.notice-act .icon { flex: none; width: 18px; height: 18px; }
.notice-act:hover { background: none; border: 0; }
/* El tono al pasar por encima, solo donde hay ratón: en un móvil se queda
   pegado después del toque y la celda parece seguir pulsada. */
@media (hover: hover) {
  .notice-act:hover { background: var(--paper); color: var(--ink); }
  }
.notice-act:focus-visible { outline: 2px solid var(--plate); outline-offset: -2px; }
.notice-act:active { transform: none; }
/* Con tres celdas -lo agendado también se puede traer ya- no caben el dibujo
   y la palabra lado a lado a 375 px, y "Bring back" se partía en dos líneas.
   El dibujo sube encima de la palabra y cada celda sigue diciendo una cosa. */
.notice-foot:has(> :nth-child(3)) .notice-act {
  flex-direction: column;
  gap: calc(var(--space) * 1);
  min-height: 56px;
  font-size: 13px;
  line-height: 1.2;
  text-align: center;
}
/* Las celdas de las esquinas siguen el redondeo de la tarjeta: sin esto, el
   gris de encima asomaba recto por fuera de la curva mientras la tarjeta deja
   de recortar con el panel abierto. */
.notice-foot > :first-child .notice-act { border-bottom-left-radius: var(--r-card); }
.notice-foot > :last-child .notice-act { border-bottom-right-radius: var(--r-card); }
/* Vista resuelve el aviso y es lo que se viene a hacer: la única celda azul.
   Aplazar y devolver son grises porque no cierran nada. */
.notice-act.resolve { color: var(--plate); }
/* Lo ya mirado ofrece dos salidas del mismo peso: volver a Activas, en azul,
   y quitarlo, en el rojo de lo que no tiene vuelta. */
.notice-card.notice-seen .notice-act { color: var(--plate); }
.notice-card.notice-seen .notice-act.drop { color: var(--alarm); }
/* Borrar un mensaje también va en rojo: no tiene vuelta. */
.declining > .notice-act.drop { color: var(--alarm); }

/* ── Marcar lo visto ──────────────────────────────────────────────────────
   El círculo de marcar va en la esquina de arriba de cada aviso visto. En una
   pantalla grande, o donde hay ratón, está siempre, que es como se descubre;
   en un móvil sale al empezar a marcar manteniendo pulsado uno, y hasta
   entonces no ocupa sitio.
   Se levanta sobre el enlace estirado de la tarjeta, que la cubre entera.
   Ver marking_controller.js. */
.notice-pick {
  position: absolute;
  top: calc(var(--space) * 1);
  right: calc(var(--space) * 1);
  z-index: 1;
  display: none;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: none;
  box-shadow: none;
  cursor: pointer;
}
.notice-pick::before {
  content: "";
  width: 22px;
  height: 22px;
  border: 2px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--card);
}
.notice-pick:hover { border: 0; background: none; }
.notice-pick:hover::before { border-color: var(--plate); }
.notice-pick:focus-visible { outline: 2px solid var(--plate); outline-offset: -4px; }
.notice-pick:active { transform: none; }
.notice-card.marked .notice-pick::before {
  border-color: var(--plate);
  background: var(--plate);
  box-shadow: inset 0 0 0 4px var(--card);
}
.notice-piles.marking .notice-pick { display: grid; }
/* La frase no se mete debajo del círculo. */
.notice-piles.marking .notice-seen .notice-body { padding-right: calc(var(--space) * 8); }
@media (min-width: 760px), (hover: hover) and (pointer: fine) {
  .notice-pick { display: grid; }
  .notice-seen .notice-body { padding-right: calc(var(--space) * 8); }
}
/* Marcado es un filo azul, el de lo elegido, y la frase en su tinta. */
.notice-card.notice-seen.marked { box-shadow: 0 0 0 2px var(--plate); }
.notice-card.marked .notice-what { color: var(--plate-deep); }
/* Mientras se marca, tocar marca: el enlace no promete abrir nada ni se
   subraya, y el texto no se selecciona con el dedo aguantado. */
.notice-piles .notice-seen .notice-what { -webkit-touch-callout: none; }
.notice-piles.marking .notice-seen .notice-what:hover { color: inherit; }
@media (max-width: 759px) {
  /* Sitio debajo del último aviso para que suba por encima de la hoja. */
  .notice-piles.marking { padding-bottom: calc(var(--space) * 80); }
}
@media (min-width: 760px) {
  .notice-piles.marking { padding-bottom: calc(var(--space) * 20); }
}

/* ── Cuándo tiene que volver ──────────────────────────────────────────────
   Un <details> que en un ordenador cuelga del botón y en un móvil sube como
   una hoja desde abajo, igual que el menú de la cabecera. Dos días escritos
   —mañana y dentro de una semana— y, debajo, uno cualquiera. No se pide hora:
   vuelve a primera hora de la mañana. Ver Notification::WAKING_HOUR. */
.postpone { position: relative; }
.postpone-open::-webkit-details-marker, .postpone-open::marker { display: none; content: ""; }
.postpone[open] > .postpone-open { background: var(--paper); color: var(--ink); }

.postpone-panel {
  position: absolute;
  left: 0;
  /* Cuelga hacia abajo y no hacia arriba: con cuatro días y no dos ya no cabe
     siempre por encima de un botón que puede estar a un dedo del borde de
     arriba de la pantalla, y por debajo la página sigue y hay sitio. */
  top: calc(100% + var(--space) * 2);
  z-index: 20;
  width: max-content;
  min-width: 300px;
  max-width: min(360px, calc(100vw - var(--space) * 10));
  padding: calc(var(--space) * 3);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}
/* Cuatro días en dos columnas: apretados en una sola caían en una hoja larga
   que empujaba el campo y su botón contra el borde de abajo del teléfono. En
   dos, la hoja se queda baja y separada de él aunque haya cuatro y no dos. */
.postpone-quick {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: calc(var(--space) * 3);
  margin-bottom: calc(var(--space) * 4);
}
.postpone-quick form { margin: 0; }
.postpone-quick button { width: 100%; min-height: 44px; padding-inline: calc(var(--space) * 2); }
.postpone-day { display: flex; gap: calc(var(--space) * 2); margin: 0; }
.postpone-day input[type="date"] { flex: 1; min-width: 0; }
.postpone-day input[type="submit"] { flex: none; }

@media (max-width: 759px) {
  .postpone-panel { padding: calc(var(--space) * 3); }
  .postpone-day { margin-bottom: calc(var(--space) * 2); }
}

/* Una lista vacía se lee como vacía a propósito, no como media pantalla que
   no ha cargado. */
.column-empty { margin: 0; color: var(--ink-soft); font-size: 15px; }

/* La etapa es el color de la tarjeta, y además va escrita. El filo de color
   es ancho y llega a las esquinas: se ve desde un metro. */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: calc(var(--space) * 2);
  padding: calc(var(--space) * 4) calc(var(--space) * 4) calc(var(--space) * 4) calc(var(--space) * 5);
  border: 1px solid var(--hairline);
  border-left: 5px solid var(--ink-soft);
  border-radius: var(--r-card);
  background-color: var(--card);
  box-shadow: var(--lift-rest);
}
.card-diagnostic { border-left-color: var(--stage-diagnostic); }
.card-quote_sent { border-left-color: var(--stage-quote); }
.card-waiting_part { border-left-color: var(--stage-part); }
.card-repair { border-left-color: var(--stage-repair); }
.card-ready { border-left-color: var(--stage-ready); }
.card-none { border-left-color: var(--rule); }

.card-head, a.card-head:visited { color: var(--ink); }
.card-head { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2) calc(var(--space) * 3); min-height: 44px; color: var(--ink); text-decoration: none; }
.card-head:hover .card-vehicle { color: var(--plate); }
.card-vehicle { font-size: 17px; font-weight: 650; letter-spacing: -0.01em; }
.card-stage { margin: 0; font-size: 14px; font-weight: 650; }
/* Lo terminado va en gris, con su sello. */
.done { color: var(--ink-soft); }
.stamp {
  font-size: 13px;
  font-weight: 650;
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  padding: calc(var(--space) * 1) calc(var(--space) * 2);
}

/* Una pantalla vacía es una invitación a hacer algo, y se lee como un título.
   Detrás de un formulario o de una lista necesita aire: pegada al botón de
   arriba parece que el botón haya contestado. */
.empty-title { font-size: 20px; font-weight: 650; letter-spacing: -0.01em; }
h2.empty-title { margin-top: 0; }
p.empty-title { margin: calc(var(--space) * 8) 0 calc(var(--space) * 2); }

/* ── La ficha del coche ───────────────────────────────────────────────────
   Una página larga que se lee, no cinco pestañas. */
.fiche-head h1 { margin-bottom: calc(var(--space) * 2); }
.contacts { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 2); }
.contact {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--ink);
  font-weight: 550;
  text-decoration: none;
  box-shadow: var(--lift-rest);
}
a.contact:visited { color: var(--ink); }
.contact:hover { border-color: var(--ink-soft); }
.current .card { margin-bottom: calc(var(--space) * 2); }

.timeline { display: flex; flex-direction: column; gap: calc(var(--space) * 5); }
.entry { border-left: 2px solid var(--rule); padding-left: calc(var(--space) * 4); }
.entry-head { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 2) calc(var(--space) * 3); align-items: baseline; margin: 0; font-size: 14px; color: var(--ink-soft); }
.entry-who { font-weight: 650; color: var(--ink); }
.entry-body { margin: calc(var(--space) * 1) 0 0; }
.entry-body p { margin: 0 0 calc(var(--space) * 2); }
.entry-stage_changed .entry-body, .entry-finished .entry-body { font-weight: 650; }
.entry-note { border-left-color: var(--ink); }
.entry-platform { border-left-color: var(--plate); }
.entry-publish { display: flex; align-items: center; gap: calc(var(--space) * 3); margin-top: calc(var(--space) * 2); }
.note-form { max-width: none; margin-top: calc(var(--space) * 6); }

/* ── La cabecera de un coche y de su reparación ───────────────────────────
   La matrícula manda, y debajo, de más a menos: qué coche es, de quién, y los
   botones que llaman. El dueño no es una píldora suelta que parece un botón:
   es un nombre con su dibujo, y los botones de al lado dicen qué abren. */
.car-head, .job-head, .customer-head { margin-bottom: calc(var(--space) * 6); }

/* El título y, a su derecha, modificarlo: arriba, pequeño y callado, que es
   donde se busca lo que se hace pocas veces. Borrar vive dentro de modificar. */
.head-line { display: flex; align-items: flex-start; justify-content: space-between; gap: calc(var(--space) * 3); }
.head-line h1 { min-width: 0; margin-bottom: calc(var(--space) * 4); overflow-wrap: anywhere; }
.head-edit, .head-edit:visited {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 40px;
  padding: 0 calc(var(--space) * 3);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--ink);
  font-size: 14px;
  font-weight: 550;
  text-decoration: none;
  list-style: none;
  cursor: pointer;
}
.head-edit::-webkit-details-marker { display: none; }
.head-edit:hover { border-color: var(--ink-soft); }
.head-edit .icon { width: 16px; height: 16px; color: var(--ink-soft); }
.panel-top .head-edit { margin-bottom: calc(var(--space) * 3); }
/* Las opciones de una ficha -modificarla, borrarla- en un círculo con la
   rueda, como la de Réglages en el muelle: es la puerta a lo que se hace pocas
   veces, no una acción con nombre. La palabra va en el aria-label. */
.head-edit.head-options { justify-content: center; width: 44px; min-height: 44px; padding: 0; border-radius: 50%; }
.head-edit.head-options .icon { width: 20px; height: 20px; }

/* Modificar, desplegado: cuelga del botón en un ordenador -a la derecha,
   porque el botón vive a la derecha de la cabecera- y sube como una hoja en
   un móvil, igual que el resto de lo que se abre en la aplicación. */
.job-edit { position: relative; }
.job-edit[open] > .head-edit { border-color: var(--ink-soft); }
.job-edit-panel {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space) * 2);
  z-index: 20;
  width: max-content;
  min-width: 320px;
  max-width: min(420px, calc(100vw - var(--space) * 10));
  /* Cuelga de un botón que vive arriba y llega hasta el muelle, que flota
     abajo: sin tope, el pie del panel -guardar y borrar- quedaba debajo del
     muelle hasta desplazar la página. Lo que no cabe se desplaza dentro. Los
     272 px son lo que hay por encima del botón más el muelle. */
  max-height: calc(100dvh - 272px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}
.job-edit-panel > :first-child { margin-top: 0; }
/* Guardar y borrar, de lado a lado: en un panel estrecho no queda nada a la
   derecha de un botón corto, y el pulgar acierta mejor una tira entera. Borrar
   sigue lejos de guardar, detrás de su raya. */
.job-edit-panel .stack input[type="submit"] { align-self: stretch; }
.job-edit-panel .drop-row { display: grid; gap: calc(var(--space) * 2); margin-top: calc(var(--space) * 6); }
.job-edit-panel .drop-row button { width: 100%; }

/* ── Quién es ─────────────────────────────────────────────────────────────
   La persona y su coche en una sola tarjeta, como un contacto del teléfono:
   las iniciales, y al lado el nombre con la matrícula, uno junto al otro
   cuando caben en la misma línea. Los botones que llaman cierran la tarjeta,
   separados por una raya: son otra cosa que se hace con la misma persona. */
.who {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: calc(var(--space) * 4);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background: var(--card);
  box-shadow: var(--lift-rest);
}
.who-top { display: flex; align-items: center; gap: calc(var(--space) * 3); width: 100%; }
.who-avatar { flex: none; width: 40px; height: 40px; font-size: 14px; }

/* El nombre arriba y el coche debajo, siempre, los dos alineados a la misma
   izquierda junto a las iniciales. Uno al lado del otro "mientras cabían" los
   dejaba en una pantalla ancha separados por un hueco y a alturas distintas:
   la placa es una caja y el nombre una línea de texto, y alineados por la
   base no casaban nunca. */
.who-lines {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(var(--space) * 1);
  min-width: 0;
}
/* El nombre lleva aquí su propio enlace y no uno alrededor de toda la fila
   -de ahí el selector por `.who-lines`- porque el mismo nombre de clase vive
   también en la tarjeta de la bandeja, sin enlace y sin estos colores. */
.who-lines .who-name, .who-lines .who-name:visited {
  font-size: 18px;
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: var(--ink);
  text-decoration: none;
  overflow-wrap: anywhere;
}
.who-lines .who-name:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.who-car, .who-car:visited {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--space) * 1) calc(var(--space) * 3);
  min-height: 28px;
  color: var(--ink-soft);
  text-decoration: none;
}
.who-car:hover { color: var(--ink); }
.who-car:hover .plate { border-color: var(--plate); }
.who .contacts {
  margin-top: calc(var(--space) * 3);
  padding-top: calc(var(--space) * 3);
  border-top: 1px solid var(--hairline);
}
/* En la ficha del cliente el nombre ya es el título: la tarjeta empieza por
   los botones que llaman, sin raya encima. */
.who > .contacts:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.who-follows {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  margin: calc(var(--space) * 3) 0 0;
  color: var(--ink-soft);
  font-size: 14px;
}
.who-follows:first-child { margin-top: 0; }
.who-follows .icon { flex: none; width: 18px; height: 18px; color: var(--plate); }
/* En la tarjeta, los botones son teselas: el dibujo encima y la palabra
   debajo, repartiéndose el ancho. Tres píldoras con su palabra al lado no
   caben en 375 px dentro de una tarjeta, y la tercera caía sola a otra línea. */
/* La tarjeta alinea lo suyo a la izquierda, y una rejilla alineada así mide
   lo que su primera tesela: sin estirarla, las tres caían una debajo de otra.
   Hasta cuatro van en una fila y se reparten el ancho entero, quepa lo que
   quepa: con columnas de ancho mínimo, cuatro teselas dejaban vacía la mitad
   derecha de la tarjeta en un ordenador. A partir de cinco —dos teléfonos y un
   correo— parten en filas iguales, de tres o de cuatro, para que ninguna se
   quede sola en la última. */
.who .contacts {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--space);
  align-self: stretch;
}
.who .contacts:has(> :nth-child(5)) { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.who .contacts:has(> :nth-child(7)) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.who .contact {
  flex-direction: column;
  justify-content: center;
  gap: calc(var(--space) * 1);
  min-width: 0;
  min-height: 60px;
  padding: calc(var(--space) * 2) 0;
  border-radius: var(--r-row);
  box-shadow: none;
  font-size: 13px;
  line-height: 1.2;
  text-align: center;
}
/* En un ordenador cada tesela mide tres dedos: el dibujo vuelve al lado de la
   palabra, como en un botón, y la fila no gasta la altura de dos líneas. */
@media (min-width: 760px) {
  .who .contact { flex-direction: row; gap: calc(var(--space) * 2); min-height: 48px; font-size: 14px; }
}
.car-head h1 { display: flex; margin-bottom: calc(var(--space) * 3); }
.car-head h1 .plate { min-height: 34px; font-size: 20px; }

/* La reparación se nombra como la nombra el taller: de quién es, y su
   matrícula al lado; si no caben, la matrícula baja entera. Cada uno lleva a
   su ficha. */
.job-title { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2) calc(var(--space) * 3); }
.job-owner, .job-owner:visited { color: inherit; text-decoration: none; }
.job-owner:hover { color: var(--plate); }
.job-car { display: inline-flex; text-decoration: none; }
.job-car .plate { min-height: 30px; font-size: 18px; }
.job-car:hover .plate { border-color: var(--plate); }
.car-model { margin: 0 0 calc(var(--space) * 1); font-size: 22px; font-weight: 650; letter-spacing: -0.015em; line-height: 1.2; }
p.car-facts { margin: 0 0 calc(var(--space) * 4); font-variant-numeric: tabular-nums; }
/* Tres botones de contacto caben en una línea de 375 px si no llevan más
   relleno del que necesitan: partidos en dos parecían dos cosas distintas. */
.contact { gap: calc(var(--space) * 2); padding-inline: calc(var(--space) * 3); }
.contact .icon { color: var(--plate); }

/* ── Lo que hay dentro ahora ──────────────────────────────────────────────
   Flota, porque es lo que se viene a mirar: si el coche está dentro y en qué
   punto. Si no está, la misma tarjeta invita a abrir una reparación. */
.panel.now { box-shadow: var(--lift-float); }
.panel.now.is-out { box-shadow: var(--lift-rest); }
.now-job, .now-job:visited {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(var(--space) * 1);
  padding: calc(var(--space) * 3) 0;
  color: var(--ink);
  text-decoration: none;
}
.now-title { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; }
.now-job:hover .now-title { color: var(--plate); }
.now .card-stage { margin: 0; font-weight: 650; }

/* ── La vía ───────────────────────────────────────────────────────────────
   Las etapas en fila vertical, unidas por un raíl: la de ahora encendida en su
   color y con un halo, las de atrás con su marca y su fecha, las de delante
   con el anillo vacío. Cada parada que no es la de ahora es un botón de fila
   entera, y la flecha de la derecha dice que se va a algún sitio. */
.track-panel { box-shadow: var(--lift-float); }
.track-panel .panel-top h2 { margin: 0 0 calc(var(--space) * 1); }
.promise { margin: 0; color: var(--ink-soft); font-size: 14px; font-variant-numeric: tabular-nums; }

.track { list-style: none; margin: 0 calc(var(--space) * -2); padding: 0; }
/* El color de cada parada lo pone su etapa (`.stage-repair`…), y de él salen
   la marca, el halo y el fondo: aquí no se pisa. */
.stop { position: relative; }
.stop-arrival, .stop-end { color: var(--ink-soft); }

.stop, .stop-move {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  align-items: center;
  column-gap: calc(var(--space) * 2);
  min-height: 52px;
  padding: calc(var(--space) * 1) calc(var(--space) * 2);
}
.stop:has(> .stop-form, > .stop-move) { display: block; padding: 0; }
.stop-form { margin: 0; }

/* El botón pierde todo lo que tiene de píldora: aquí la fila entera es lo que
   se pulsa, y parecerse a una fila es lo que la hace legible entre las demás.
   El devis y la factura son enlaces que se dibujan igual. */
.stop-move, a.stop-move:visited { color: inherit; text-decoration: none; }
button.stop-move, a.stop-move {
  width: 100%;
  border: 0;
  border-radius: var(--r-row);
  background: transparent;
  box-shadow: none;
  color: inherit;
  font-weight: 400;
  text-align: left;
}
button.stop-move:hover, a.stop-move:hover { background: color-mix(in srgb, currentcolor 7%, var(--card)); }
button.stop-move:active { transform: none; }

/* El raíl pasa por debajo de las marcas y no se anuncia. */
.stop::before {
  content: "";
  position: absolute;
  left: calc(var(--space) * 2 + 13px);
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--hairline);
}
.stop:first-child::before { top: 50%; }
.stop:last-child::before { bottom: 50%; }

.stop-mark {
  position: relative;
  justify-self: center;
  width: 14px;
  height: 14px;
  border: 2px solid var(--rule);
  border-radius: 50%;
  background: var(--card);
}
.stop-name { color: var(--ink); line-height: 1.3; }
.stop time { font-size: 14px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.stop-go { display: inline-flex; color: var(--ink-faint); }
.stop-go .icon { width: 18px; height: 18px; }
.stop-move:hover .stop-go { color: currentcolor; }

.stop.future .stop-name, .stop.skipped .stop-name { color: var(--ink-soft); }
.stop.skipped .stop-mark { border-style: dashed; }
.stop.past .stop-mark { border-color: currentcolor; background: currentcolor; }
.stop.past .stop-mark::after {
  content: "";
  position: absolute;
  left: 2px;
  top: 0;
  width: 4px;
  height: 7px;
  border: solid var(--card);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* La de ahora: su color de fondo apenas, la marca llena con un halo, y debajo
   cuánto lleva ahí. Es la fila que se lee primero sin buscarla. */
.stop.current {
  border-radius: var(--r-row);
  background: color-mix(in srgb, currentcolor 9%, var(--card));
  row-gap: calc(var(--space) * 1);
  padding-block: calc(var(--space) * 3);
}
.stop.current .stop-mark {
  width: 18px;
  height: 18px;
  border-color: currentcolor;
  background: currentcolor;
  box-shadow: 0 0 0 4px color-mix(in srgb, currentcolor 22%, transparent);
}
.stop.current .stop-name { font-size: 18px; font-weight: 700; letter-spacing: -0.01em; }
.stop-arrival.current, .stop-end.current { color: var(--ink); }
.stop-since { grid-column: 2 / -1; font-size: 14px; color: var(--ink-soft); }
/* Atascado: la cinta de peligro del taller, en pequeño, delante de los días. */
.stop-since.stuck { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); color: var(--ink); font-weight: 650; }
.stop-since.stuck::before {
  content: "";
  width: 20px;
  height: 8px;
  border-radius: 2px;
  background: repeating-linear-gradient(45deg, #16181C 0 4px, #E8C547 4px 8px);
}

.track-foot {
  display: flex;
  align-items: flex-start;
  gap: calc(var(--space) * 2);
  margin: calc(var(--space) * 4) 0 0;
  padding-top: calc(var(--space) * 4);
  border-top: 1px solid var(--hairline);
  color: var(--ink-soft);
  font-size: 14px;
}
.track-foot .icon { flex: none; width: 18px; height: 18px; color: var(--plate); }

/* ── El hilo ──────────────────────────────────────────────────────────────
   Una conversación partida por días. Cada entrada cuelga de un raíl con el
   dibujo de lo que es —mensaje, nota, foto— o el punto del color de la etapa.
   Lo que escribe el cliente va en su bocadillo; lo del taller, sobre el papel
   de la tarjeta. Es la diferencia entre lo que llega y lo que se hace. */
.thread-day + .thread-day { margin-top: calc(var(--space) * 6); }
.thread-date {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 3);
  margin: 0 0 calc(var(--space) * 3);
  font-size: 14px;
  font-weight: 650;
  color: var(--ink-soft);
}
.thread-date::after { content: ""; flex: 1; height: 1px; background: var(--hairline); }
.thread-empty { margin: 0; color: var(--ink-soft); }

.thread .timeline { gap: 0; }
.thread .entry {
  position: relative;
  display: grid;
  grid-template-columns: 32px 1fr;
  column-gap: calc(var(--space) * 3);
  padding: 0 0 calc(var(--space) * 5);
  border: 0;
}
.thread .entry::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 32px;
  bottom: 0;
  width: 2px;
  background: var(--hairline);
}
.thread .entry:last-child { padding-bottom: 0; }
.thread .entry:last-child::before { display: none; }

.entry-node {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--rule);
  border-radius: 50%;
  background: var(--card);
}
/* El punto de una etapa toma el color de su etapa; los dibujos, la tinta. */
.entry-node:not(.entry-stage) { color: var(--ink-soft); }
.entry-node .icon { width: 16px; height: 16px; }
.entry-message .entry-node { border-color: transparent; background: var(--plate-tint); color: var(--plate-deep); }
.entry-note .entry-node, .entry-photo .entry-node { color: var(--ink); }
/* Un cambio de etapa es un punto de su color, sin dibujo: el mismo punto que
   lleva la etapa en la tarjeta del tablero. */
.entry-node.entry-stage { border: 0; background: var(--card); }
.entry-node.entry-stage::after { content: ""; width: 12px; height: 12px; border-radius: 50%; background: currentcolor; box-shadow: 0 0 0 4px color-mix(in srgb, currentcolor 18%, transparent); }

.entry-main { min-width: 0; padding-top: calc(var(--space) * 1); }
.thread .entry-head { gap: calc(var(--space) * 1) calc(var(--space) * 3); }
.thread .entry-head time { margin-left: auto; font-variant-numeric: tabular-nums; }
.entry-channel {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0 calc(var(--space) * 2);
  border-radius: var(--r-pill);
  background: var(--paper);
  font-size: 13px;
}
.thread .entry-body { margin-top: calc(var(--space) * 2); overflow-wrap: anywhere; }
.thread .entry-body p:last-child { margin-bottom: 0; }
.entry-said {
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border-radius: 4px var(--r-card) var(--r-card) var(--r-card);
  background: var(--plate-tint);
  color: var(--ink);
}
.thread .entry-stage_changed .entry-body, .thread .entry-finished .entry-body { margin-top: calc(var(--space) * 1); font-weight: 650; }

.thread .entry-publish { flex-wrap: wrap; justify-content: space-between; gap: calc(var(--space) * 2) calc(var(--space) * 3); }
.thread .entry-publish form { margin: 0; }
/* El papel del que habla una línea, a un toque desde ella. */
.entry-link { margin: calc(var(--space) * 2) 0 0; }
.entry-link a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; }
.seen { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); font-size: 14px; color: var(--ink-soft); }
.seen .icon { width: 16px; height: 16px; }
.seen-public { color: var(--plate-deep); font-weight: 550; }

/* ── Escribir en el hilo ─────────────────────────────────────────────────
   Debajo del último mensaje, como en cualquier conversación: se lee lo que
   pasó y se contesta justo ahí. */
.composer {
  margin-top: calc(var(--space) * 6);
  padding-top: calc(var(--space) * 5);
  border-top: 1px solid var(--hairline);
}
.composer-note { margin: 0; }
.composer-note label { display: block; margin-bottom: calc(var(--space) * 2); font-weight: 650; }
.composer-note textarea { width: 100%; }
.composer-who { display: grid; gap: calc(var(--space) * 1); margin: calc(var(--space) * 4) 0 0; padding: 0; list-style: none; font-size: 14px; color: var(--ink-soft); }
.composer-who li { display: flex; align-items: flex-start; gap: calc(var(--space) * 2); }
.composer-who .icon { flex: none; width: 16px; height: 16px; margin-top: 2px; }

/* Escribir y fotografiar a partes iguales: dos teselas del mismo alto que se
   reparten el ancho, una llena porque manda lo escrito y otra con filo. */
.composer-does {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: calc(var(--space) * 3);
  margin-top: calc(var(--space) * 3);
}
.composer-does .photo-form { margin: 0; }
/* Teselas, como los botones de contacto: el dibujo encima y la frase debajo.
   Con la frase al lado del dibujo, "Publier une photo" partía en dos líneas
   dentro de media pantalla. */
.composer-write, .photo-button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 1);
  width: 100%;
  min-height: 64px;
  padding: calc(var(--space) * 2) calc(var(--space) * 3);
  border-radius: var(--r-card);
  font-size: 15px;
  text-align: center;
  line-height: 1.2;
}
.composer-write .icon, .photo-button .icon { flex: none; width: 20px; height: 20px; }
/* Con un cliente que sigue el coche, lo que manda es contestarle: va lleno y a
   lo ancho arriba, y la nota interna baja a tesela con filo, como la foto. */
.composer-answers .composer-reply { grid-column: 1 / -1; }
.composer-answers .composer-write:not(.composer-reply) {
  border: 1px solid var(--rule);
  background: var(--card);
  color: var(--ink);
  box-shadow: var(--lift-rest);
}
.composer-answers .composer-write:not(.composer-reply):hover { border-color: var(--ink-soft); background: var(--card); }
.composer-answers .composer-write:not(.composer-reply) .icon { color: var(--plate); }

/* La foto: la píldora con filo, y el campo del archivo encima de ella entero
   y transparente, para que el dedo caiga en el campo y no en la etiqueta. */
.photo-button {
  position: relative;
  border: 1px solid var(--rule);
  background: var(--card);
  color: var(--ink);
  font-weight: 600;
  box-shadow: var(--lift-rest);
  cursor: pointer;
}
.photo-button:hover { border-color: var(--ink-soft); }
.photo-button .icon { color: var(--plate); }
.photo-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}
.photo-button:focus-within { outline: 3px solid var(--plate); outline-offset: 2px; }
/* Mientras sube, lo dice, y no se vuelve a pulsar encima. */
.photo-busy { display: none; }
.photo-form[aria-busy="true"] .photo-say { display: none; }
.photo-form[aria-busy="true"] .photo-busy { display: inline; }
.photo-form[aria-busy="true"] .photo-button { color: var(--ink-soft); pointer-events: none; }
.photo-form[aria-busy="true"] .photo-button .icon { animation: pulse 1s ease-in-out infinite alternate; }
@keyframes pulse { to { opacity: 0.3; } }
@media (prefers-reduced-motion: reduce) {
  .photo-form[aria-busy="true"] .photo-button .icon { animation: none; }
}

/* ── Los papeles y las visitas ───────────────────────────────────────────
   Filas planas dentro de su tarjeta: el nombre, el estado y, pegado a la
   derecha, el importe o la fecha, que es lo que se busca con los ojos. */
.papers .full-row { display: grid; grid-template-columns: 1fr auto; gap: 0 calc(var(--space) * 3); padding-block: calc(var(--space) * 2); }
.paper-name { font-weight: 600; }
.paper-state { grid-row: 2; font-size: 14px; color: var(--ink-soft); }
.paper-amount { grid-row: 1 / 3; grid-column: 2; font-weight: 650; font-variant-numeric: tabular-nums; }

/* Una visita: arriba cuándo, con cómo acabó pegado a la derecha, y debajo
   para qué vino, cortado a dos líneas. Con `.rows li a` delante: la fila de
   `.rows` pesaba más, la dejaba en una línea que parte donde quiere, y un
   mensaje largo del cliente se llevaba la fecha y el estado a cualquier
   sitio. */
.rows li a.visit {
  display: grid;
  gap: calc(var(--space) * 1);
  width: 100%;
  padding-block: calc(var(--space) * 3);
}
.visit-top { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--space) * 3); }
.visit-when { color: var(--ink); font-size: 15px; font-weight: 650; font-variant-numeric: tabular-nums; }
.visit-top .stamp { flex: none; }
.visit-name {
  display: -webkit-box;
  overflow: hidden;
  color: var(--ink-soft);
  font-size: 15px;
  line-height: 1.4;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}
.rows li a.visit:hover .visit-name { color: var(--ink); }


/* ── La carta y la ficha pública ────────────────────────────────────────── */
.service-name { font-weight: 650; }

/* La ficha pública es la única pantalla que ve alguien que no ha entrado
   nunca, así que respira más que el resto. Arriba quién es, con su marca de
   iniciales, la nota que lleva a las opiniones y lo que cuenta de sí mismo.
   Ver docs/DESIGN.md. */
.storefront-head { margin-bottom: calc(var(--space) * 6); }
/* La marca y el nombre en una línea, la firma del taller. Un nombre largo
   parte en su columna y la marca se queda a media altura de lo que ocupe. */
.storefront-title { display: flex; align-items: center; gap: calc(var(--space) * 4); margin-bottom: calc(var(--space) * 3); }
.storefront-mark {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: var(--r-card);
  background: var(--plate);
  color: #fff;
  font-size: 20px;
  font-weight: 750;
  letter-spacing: 0.02em;
}
.storefront h1 { min-width: 0; margin: 0; font-size: 34px; line-height: 1.1; overflow-wrap: anywhere; }
/* `p.storefront-city` y no la clase sola: `p.meta` le ponía su margen de
   abajo y la ciudad se quedaba a un palmo de lo que cuenta el taller. */
p.storefront-city { display: flex; flex-wrap: wrap; align-items: baseline; gap: calc(var(--space) * 1) calc(var(--space) * 4); margin: 0; color: var(--ink-soft); font-size: 17px; }
.storefront-rating, .storefront-rating:visited { display: inline-flex; align-items: baseline; gap: calc(var(--space) * 2); color: var(--ink-soft); text-decoration: none; }
.storefront-rating .rating-figure { color: var(--ink); }
.storefront-rating > span:last-child { font-size: 15px; text-decoration: underline; text-underline-offset: 3px; }
.storefront-about { margin: calc(var(--space) * 4) 0 0; color: var(--ink-soft); font-size: 17px; line-height: 1.55; }

/* ── Con foto ─────────────────────────────────────────────────────────────
   La foto cubre lo de arriba de la página, de borde a borde en el móvil y
   desde el techo, y el nombre va encima en blanco, sobre una sombra que baja
   hacia el pie para que se lea sobre cualquier foto. La tarjeta de pedir cita
   se monta sobre su borde de abajo -algo más de un cuarto de ella dentro de
   la foto- y queda flotando: es lo primero que se hace, y así se ve primero.
   Solo si el taller ha puesto una: sin foto no se pinta ninguna de relleno. */
.storefront.with-cover .storefront-head {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 320px;
  margin: calc((var(--band-top) + var(--space) * 6) * -1) calc(var(--space) * -5) 0;
  padding: calc(var(--band-top) + var(--space) * 16) calc(var(--space) * 5) calc(var(--space) * 28);
  overflow: hidden;
  color: #fff;
}
.storefront.with-cover .storefront-head::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to bottom, rgb(14 18 26 / 15%) 0%, rgb(14 18 26 / 35%) 45%, rgb(14 18 26 / 80%) 100%);
}
.storefront-cover { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; }
.storefront.with-cover h1 { color: #fff; text-shadow: 0 1px 2px rgb(0 0 0 / 30%); }
.storefront.with-cover .storefront-mark { box-shadow: 0 0 0 2px rgb(255 255 255 / 90%); }
.storefront.with-cover .storefront-city,
.storefront.with-cover .storefront-rating,
.storefront.with-cover .storefront-rating:visited,
.storefront.with-cover .storefront-rating .rating-figure { color: rgb(255 255 255 / 90%); }
.storefront.with-cover .storefront-about { color: rgb(255 255 255 / 88%); }
.storefront.with-cover .storefront-does {
  position: relative;
  margin-top: calc(var(--space) * -22);
  box-shadow: var(--lift-float);
}
/* En un ordenador la foto es una banda de la columna, con sus esquinas, y la
   tarjeta entra un poco hacia dentro de sus bordes: a lo ancho de la banda se
   leía pegada a ella y no flotando encima. */
@media (min-width: 760px) {
  .storefront.with-cover .storefront-head {
    min-height: 360px;
    margin: 0;
    padding: calc(var(--space) * 16) calc(var(--space) * 8) calc(var(--space) * 28);
    border-radius: var(--r-panel);
  }
  .storefront.with-cover .storefront-does { margin-inline: calc(var(--space) * 6); }
}

/* Lo que se viene a hacer: el próximo hueco en su tinte, pedir cita a lo
   ancho y, debajo, llamar, escribir y llegar en teselas que se reparten el
   ancho: el dibujo encima y la palabra debajo. */
.storefront-next { display: flex; align-items: center; gap: calc(var(--space) * 2); margin: 0 0 calc(var(--space) * 4); padding: calc(var(--space) * 3) calc(var(--space) * 4); border-radius: var(--r-row); background: var(--plate-tint); color: var(--plate-deep); font-weight: 650; }
.storefront-next .icon { flex: none; width: 18px; height: 18px; }
.storefront-ask-hint { margin: calc(var(--space) * 2) 0 0; text-align: center; }
.storefront-tiles { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: calc(var(--space) * 2); margin-top: calc(var(--space) * 5); padding-top: calc(var(--space) * 5); border-top: 1px solid var(--hairline); }
.storefront-tile, .storefront-tile:visited {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 1);
  min-height: 64px;
  padding: calc(var(--space) * 2);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
}
.storefront-tile .icon { color: var(--plate); }
.storefront-tile:hover { border-color: var(--ink-soft); }
.storefront-tile:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

/* La carta de un taller se lee como la de un restaurante: qué es, qué cuesta,
   cuánto dura. Nada de tarjetas ni de sombras: son filas de una lista. */
/* Cada servicio en su baldosa: el papel de la pantalla, sin filo ni sombra,
   y aire entre una y otra. Separados por una raya fina, con su descripción, su
   duración y su botón de reservar debajo, no se veía dónde acababa uno y
   empezaba el siguiente, y el botón del último parecía de toda la carta. No es
   una tarjeta dentro de la tarjeta: no flota, solo agrupa. */
.menu { display: flex; flex-direction: column; gap: calc(var(--space) * 3); list-style: none; margin: 0; padding: 0; }
.menu li { padding: calc(var(--space) * 4); border-radius: var(--r-card); background: var(--paper); }
.menu-line { display: flex; align-items: baseline; justify-content: space-between; gap: calc(var(--space) * 4); }
.menu-name { margin: 0; font-size: 17px; font-weight: 650; }
.menu-line .menu-price { flex: none; margin: 0; text-align: right; }
.menu-about { margin: calc(var(--space) * 1) 0 0; color: var(--ink-soft); }
.menu-terms { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 1) calc(var(--space) * 2); margin: calc(var(--space) * 2) 0 0; color: var(--ink-soft); font-size: 14px; }
.menu-terms .icon { flex: none; width: 16px; height: 16px; }
.menu-price { font-weight: 650; }
.menu-duration { color: var(--ink-soft); }

/* ── El anuario ───────────────────────────────────────────────────────────
   Una tarjeta por taller, con lo que hace falta para elegir sin abrir
   ninguna: dónde está, qué nota tiene, qué hace y cuándo tiene hueco.
   Una fila de texto no dejaba comparar dos. Ver docs/SPEC.md 8. */
.found { list-style: none; margin: 0; padding: 0; display: grid; gap: calc(var(--space) * 3); }
/* Dos o más por fila, y entonces cada tarjeta toma sus cuatro filas de la
   lista -nombre, dónde, qué hace, cuándo- con `subgrid`: la dirección de una
   cae a la altura de la de su vecina aunque un nombre ocupe dos renglones, y
   la que no dice qué hace deja ese hueco en blanco en vez de subir lo demás. */
@media (min-width: 640px) {
  .found { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
  .found > .found-card { display: grid; grid-row: span 4; grid-template-rows: subgrid; align-content: start; }
  .found-head { grid-row: 1; }
  .found-where { grid-row: 2; align-self: start; }
  .found-does { grid-row: 3; align-self: start; }
  .found-when { grid-row: 4; }
}
.found-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: calc(var(--space) * 2);
  padding: calc(var(--space) * 5);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background: var(--card);
  box-shadow: var(--lift-rest);
}
.found-head { display: flex; align-items: flex-start; gap: calc(var(--space) * 3); }
.found-title { flex: 1; display: flex; flex-direction: column; gap: calc(var(--space) * 1); min-width: 0; }
.found-name { margin: 0; font-size: 19px; font-weight: 700; letter-spacing: -0.015em; line-height: 1.25; }
.found-name a { color: var(--ink); text-decoration: none; }
/* Al pasar el ratón se enciende la tarjeta y no el nombre: el enlace es la
   tarjeta entera, y un nombre subrayado decía que solo él llevaba a algún
   sitio. */
@media (hover: hover) {
  .found-card:hover { border-color: var(--rule); box-shadow: var(--lift-float); }
}

/* Se toca la tarjeta entera y no solo el nombre: es lo que hace el pulgar, y
   un blanco de doscientos pixeles que no lleva a ninguna parte se lee como que
   la tarjeta esta apagada. El enlace del nombre se estira por encima de todo
   lo demas; la estrella se levanta por encima de el para seguir siendo suya. */
.found-open::after { content: ""; position: absolute; inset: 0; z-index: 0; border-radius: var(--r-card); }
.found-card:focus-within { box-shadow: var(--lift-rest), 0 0 0 2px var(--plate); }

/* La estrella: el taller al que se vuelve, arriba del todo de la lista.
   Encendida se rellena y apagada es el mismo trazo hueco. */
.star { flex: none; display: inline-flex; position: relative; z-index: 2; margin: calc(var(--space) * -1) calc(var(--space) * -1) 0 0; }
.star form { margin: 0; }
.star-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  min-height: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: none;
  box-shadow: none;
  color: var(--ink-soft);
  cursor: pointer;
}
.star-mark:hover { background: var(--plate-tint); color: var(--plate); }
.star-on { color: var(--plate); }
.star-on .icon { fill: currentColor; }
/* La dirección entera, no solo la ciudad: es lo primero que se mira para saber
   si pilla cerca, y hasta ahora había que abrir la ficha para verla. */
.found-where { display: flex; align-items: flex-start; gap: calc(var(--space) * 2); margin: 0; color: var(--ink-soft); font-size: 14px; }
.found-where .icon, .found-when .icon { flex: none; width: 18px; height: 18px; margin-top: 1px; }
/* Lo que hace, como texto en fila y no como botones: no se pulsa. */
.found-does { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 1) calc(var(--space) * 2); margin: 0; }
.found-does span { padding: calc(var(--space) * 1) calc(var(--space) * 2); border-radius: var(--r-row); background: var(--paper); color: var(--ink-soft); font-size: 14px; font-weight: 550; }
/* Cuándo y cuánto, al pie y de lado a lado: la franja es lo que se compara
   entre dos talleres. Con hueco, en el tinte de lo encendido. */
.found-when {
  display: flex;
  align-items: flex-start;
  gap: calc(var(--space) * 3);
  margin: auto calc(var(--space) * -5) calc(var(--space) * -5);
  padding: calc(var(--space) * 3) calc(var(--space) * 5);
  border-top: 1px solid var(--hairline);
  border-radius: 0 0 var(--r-card) var(--r-card);
  color: var(--ink-soft);
  font-size: 14px;
}
.found-when.is-free { background: var(--plate-tint); color: var(--plate-deep); }
.found-terms { display: flex; flex-wrap: wrap; gap: 0 calc(var(--space) * 3); min-width: 0; }
.found-slot { font-weight: 650; }
.found-price { font-weight: 550; }
.found-card { gap: calc(var(--space) * 3); }

/* Dónde está el taller, en su tarjeta y arriba del todo. */
.where-map { margin: calc(var(--space) * 2) 0 0; }
.where-when { margin: calc(var(--space) * 6) 0 calc(var(--space) * 2); font-size: 15px; font-weight: 650; }
.where-hours { display: grid; grid-template-columns: auto 1fr; gap: calc(var(--space) * 1) calc(var(--space) * 4); margin: 0; font-size: 14px; }
.where-hours dt { color: var(--ink-soft); }
.where-hours dd { margin: 0; font-variant-numeric: tabular-nums; }

/* ── El planificador ──────────────────────────────────────────────────────
   El color ya está gastado en las etapas y no se pide prestado: aquí el tipo
   de cita va escrito y el estado se dice con el borde. Ver docs/DESIGN.md. */

/* El planificador es la única pantalla que rompe la columna de 640 px, y solo
   en semana y mes: siete días dentro de la columna son siete tiras de cuarenta
   píxeles donde una hora no cabe. Ver docs/DESIGN.md. */
@media (min-width: 760px) {
  .wide-out {
    width: min(calc(100vw - 40px), 1120px);
    margin-left: calc((640px - min(calc(100vw - 40px), 1120px)) / 2);
  }
}

.surcharge { font-weight: 650; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* Un botón escondido sigue siendo un botón para el navegador, y las medidas
   de su sitio —el alto del pulgar, el relleno— lo dejaban de cuarenta y cuatro
   píxeles recortado encima de otra cosa. Escondido quiere decir de un píxel. */
.visually-hidden { min-height: 0; padding: 0; border: 0; }

/* ── Buscar un taller ─────────────────────────────────────────────────────
   Se busca escribiendo y la lista se rehace sola: no hay botón de buscar
   porque no hay nada que confirmar. Lo único que se pulsa aquí es el pliegue
   de los filtros, y va donde estaba el botón —dentro del filo de la caja—,
   que es donde el pulgar ya estaba. Cuatro desplegables antes de la primera
   respuesta no son una búsqueda, son un formulario. */
.finder { position: relative; margin-bottom: calc(var(--space) * 6); }

/* La caja de buscar un taller es la misma pieza de arriba —`.with-button`— y
   solo cambia en que aquí ocupa la columna entera y se apoya en el papel. */
.finder .with-button { max-width: none; box-shadow: var(--lift-rest); }

/* El pliegue de los filtros, posado por dentro del filo. Se dibuja como lo que
   es —algo que se pulsa y se abre— y no con el triángulo del navegador, que en
   tres sistemas son tres dibujos distintos. */
.finder-more { flex: none; }
.finder-more > summary {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  padding-inline: calc(var(--space) * 3);
  border-radius: var(--r-pill);
  color: var(--plate);
  font-size: 15px;
  font-weight: 550;
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
}
.finder-more > summary::-webkit-details-marker { display: none; }
.finder-more > summary:hover, .finder-more[open] > summary { background: var(--plate-tint); }

/* Los filtros, en una hoja: en un móvil sube desde abajo y en un ordenador
   flota en medio, como todo lo que se abre aquí. Dentro, la ciudad y lo que
   se necesita son desplegables con buscador, uno debajo de otro. */
.filter-panel { width: min(520px, calc(100vw - var(--space) * 8)); }
.filter-field { display: grid; gap: calc(var(--space) * 2); margin-bottom: calc(var(--space) * 4); }
.filter-field > label { font-size: 15px; font-weight: 650; }
/* La lista se abre dentro de la hoja y la empuja, en vez de flotar encima:
   flotando se recortaba contra el filo de la hoja y abría un segundo scroll
   dentro del suyo, y el dedo que corría la lista cerraba la hoja. Así lo que
   se corre es la hoja entera, y el buscador se queda pegado arriba. */
.filter-panel .chooser-list {
  position: static;
  max-height: none;
  overflow: visible;
  margin-top: calc(var(--space) * 2);
  box-shadow: none;
}
.filter-panel .chooser-search { top: 0; box-shadow: 0 calc(var(--space) * -2) 0 var(--card); }
.filter-panel .panel-save { margin-top: calc(var(--space) * 5); }
.filter-switch { display: flex; align-items: center; gap: calc(var(--space) * 3); min-height: 44px; margin-top: calc(var(--space) * 2); font-weight: 550; }

/* En un ordenador los filtros cuelgan de su botón, debajo de la caja y por la
   derecha, que es donde está el botón: en medio de la pantalla se leían como
   otra cosa, lejos de la lista que afinan. La lista de cada desplegable vuelve
   a flotar con su alto tope y se corre por dentro: empujando la hoja, cien
   ciudades la sacaban por abajo de la pantalla. Aquí no hay dedo que la cierre
   al correrla, que era la razón de empujar en el móvil. */
@media (min-width: 760px) {
  .finder .with-button { position: relative; }
  .finder .with-button:has(.finder-more:focus-within) { border-color: var(--rule); outline: none; }
  .finder-more > .filter-panel {
    position: absolute;
    inset: calc(100% + var(--space) * 2) 0 auto auto;
    width: min(440px, 100%);
    max-height: none;
    margin: 0;
    overflow: visible;
  }
  .filter-panel .chooser-list {
    position: absolute;
    max-height: min(320px, 50vh);
    overflow-y: auto;
    margin-top: 0;
    box-shadow: var(--lift-float);
  }
}

/* La nota de una valoración: cinco estrellas grandes que se tocan, y la
   tocada se enciende con las de antes, como se lee una nota. El botón de
   verdad está escondido dentro de cada una. */
.stars-pick { margin: 0; padding: 0; border: 0; }
.stars-pick legend { margin-bottom: calc(var(--space) * 3); padding: 0; font-size: 17px; font-weight: 650; }
.stars-pick-row { display: flex; gap: calc(var(--space) * 2); }
.stars-pick-star {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  max-width: 72px;
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  background: var(--card);
  color: var(--rule);
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
}
.stars-pick-star input { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.stars-pick-star:has(input:focus-visible) { outline: 2px solid var(--plate); outline-offset: 2px; }
.stars-pick-row:has(> :nth-child(1) input:checked) > :nth-child(-n+1),
.stars-pick-row:has(> :nth-child(2) input:checked) > :nth-child(-n+2),
.stars-pick-row:has(> :nth-child(3) input:checked) > :nth-child(-n+3),
.stars-pick-row:has(> :nth-child(4) input:checked) > :nth-child(-n+4),
.stars-pick-row:has(> :nth-child(5) input:checked) > :nth-child(-n+5) { border-color: var(--plate); background: var(--plate-tint); color: var(--plate); }

/* Cada criterio, en una fila: su nombre y cinco cifras que se tocan. Se
   reparten el ancho para que las cuatro filas se lean alineadas. */
.chips.score-pick { flex-wrap: nowrap; }
.chips.score-pick .chip { flex: 1 1 0; justify-content: center; max-width: 72px; padding: 0; font-variant-numeric: tabular-nums; }
.chips.score-pick:last-child { margin-bottom: 0; }
.review-form .panel-save { margin-top: calc(var(--space) * 5); }

/* El día y la hora de una recogida, cada uno en su campo y a medias del
   ancho, con su dibujo delante. Son los del sistema: en un teléfono abren su
   calendario y su reloj. La flecha del navegador se esconde porque el campo
   entero ya los abre, y el dibujo de delante dice qué es cada uno. */
.moment-pick { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: calc(var(--space) * 2); min-width: 0; margin: 0; padding: 0; border: 0; }
.moment-pick legend { grid-column: 1 / -1; margin-bottom: calc(var(--space) * 2); padding: 0; font-size: 14px; font-weight: 550; color: var(--ink-soft); }
.moment-field {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-width: 0;
  min-height: 52px;
  padding: 0 calc(var(--space) * 3);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  background: var(--card);
  cursor: pointer;
}
.moment-field .icon { flex: none; width: 20px; height: 20px; color: var(--plate); }
.moment-field:focus-within { border-color: var(--plate); outline: 2px solid var(--plate); outline-offset: -2px; }
.moment-field input {
  flex: 1;
  width: 100%;
  min-width: 0;
  min-height: 48px;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.moment-field input:focus { outline: none; }
.moment-field input::-webkit-calendar-picker-indicator { display: none; }
.pickup-form .panel-save { margin-top: calc(var(--space) * 4); }

/* Un grupo de pastillas que se eligen: la etiqueta encima y las opciones en
   fila, partiendo donde no quepan. La elegida, llena de azul. El botón de
   verdad sigue ahí, escondido, para el teclado y el lector de pantalla. */
.chips { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 2); min-width: 0; margin: 0 0 calc(var(--space) * 5); padding: 0; border: 0; }
.chips legend { width: 100%; margin-bottom: calc(var(--space) * 2); padding: 0; font-size: 14px; font-weight: 550; color: var(--ink-soft); }
.chip {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--ink);
  font-size: 15px;
  font-weight: 550;
  cursor: pointer;
}
.chip input { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.chip:has(input:checked) { background: var(--plate); border-color: var(--plate); color: #fff; }
.chip:has(input:focus-visible) { outline: 2px solid var(--plate); outline-offset: 2px; }
@media (hover: hover) {
  .chip:hover { border-color: var(--ink-soft); }
  .chip:has(input:checked):hover { border-color: var(--plate-deep); }
}

/* Cuántos hay, antes de la lista, y cómo se vuelve a la entera si está
   afinada: las dos cosas en la misma línea porque son la misma pregunta. */
.found-count { display: flex; flex-wrap: wrap; align-items: baseline; gap: calc(var(--space) * 1) calc(var(--space) * 4); margin: 0 0 calc(var(--space) * 3); color: var(--ink-soft); font-size: 14px; font-weight: 550; }
.found-count a { font-size: 14px; }

/* Reservar desde la ficha pública se abre en su sitio, sin salir de la carta.
   Cerrado es un botón de filo a lo ancho del servicio, con su dibujo y la
   punta que dice que se abre: el enlace azul suelto que era no se leía como
   lo que se viene a hacer. Abierto se tiñe, como un pliegue abierto. */
.booking-open { margin-top: calc(var(--space) * 4); }
.booking-toggle {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 48px;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  background: var(--card);
  color: var(--plate);
  font-weight: 650;
  cursor: pointer;
  list-style: none;
}
.booking-toggle::-webkit-details-marker { display: none; }
.booking-toggle .icon { flex: none; width: 18px; height: 18px; }
.booking-toggle .icon:last-child { margin-left: auto; transition: transform 120ms ease; }
.booking-toggle:hover { border-color: var(--plate); }
.booking-toggle:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }
.booking-open[open] > .booking-toggle { border-color: var(--plate-tint); background: var(--plate-tint); color: var(--plate-deep); }
.booking-open[open] > .booking-toggle .icon:last-child { transform: rotate(180deg); }
.booking-form { margin: calc(var(--space) * 4) 0 calc(var(--space) * 2); gap: calc(var(--space) * 3); }

/* Las horas son filas que se tocan enteras; la elegida, en el tinte de lo
   elegido. Un botón de radio de 22 px solo en una fila de texto se acertaba
   a medias. */
.hours-open { display: grid; gap: calc(var(--space) * 2); margin: 0; padding: 0; border: 0; }
.hours-open legend { margin-bottom: calc(var(--space) * 2); padding: 0; color: var(--ink-soft); font-size: 14px; font-weight: 550; }
.booking-form .booking-hour {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 3);
  min-height: 52px;
  padding: 0 calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  background: var(--card);
  color: var(--ink);
  font-size: 16px;
  font-weight: 550;
  cursor: pointer;
}
.booking-hour input[type="radio"] { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--plate); }
.booking-form .booking-hour:has(input:checked) { border-color: var(--plate); background: var(--plate-tint); color: var(--plate-deep); }
.booking-hour:has(input:focus-visible) { outline: 2px solid var(--plate); outline-offset: 2px; }
.booking-form .panel-save { margin-top: calc(var(--space) * 2); }

/* ── Las citas del conductor ──────────────────────────────────────────────
   Repartidas en cuatro montones, y cada montón es un pliegue: el nombre a la
   izquierda, la cuenta al lado, y la línea que llega hasta la punta del final.
   La línea no es adorno: es lo que dice dónde acaba un montón y empieza otro
   sin poner un título a cada uno, que en una pantalla de trescientos setenta y
   cinco píxeles son cuatro renglones robados a las tarjetas. */
.bundle { margin-bottom: calc(var(--space) * 6); }
.bundle-line {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  cursor: pointer;
  list-style: none;
}
.bundle-line::-webkit-details-marker { display: none; }
.bundle-name { font-size: 15px; font-weight: 650; letter-spacing: -0.01em; }
.bundle-count { color: var(--ink-soft); font-size: 14px; font-weight: 550; }
/* La línea se come el hueco que sobre, así que el nombre manda y la punta se
   queda pegada al filo derecho, que es donde el pulgar la busca. */
.bundle-rule { flex: 1; height: 1px; background: var(--rule); }
.bundle-line .icon { flex: none; color: var(--ink-soft); transition: transform 120ms ease; }
.bundle[open] > .bundle-line .icon { transform: rotate(180deg); }

/* El color del montón lo lleva el nombre, y lo repite el filo izquierdo de sus
   tarjetas. Es el mismo azul de matrícula de siempre para lo que viene, el
   rojo solo para lo que se anuló, y gris para lo que ya no se va a tocar: un
   montón no es una alarma, y cuatro colores encendidos no dicen nada. */
.bundle.upcoming .bundle-name { color: var(--plate); }
.bundle.cancelled .bundle-name { color: var(--alarm); }
.bundle.past .bundle-name, .bundle.archived .bundle-name { color: var(--ink-soft); }

/* Su propio nombre y no `.dates`: ese es la rejilla de siete columnas de las
   fechas que se marcan en el horario, y con el mismo nombre cada tarjeta se
   quedaba en un séptimo del ancho, con la fecha partida en tres renglones. */
.date-cards { list-style: none; margin: calc(var(--space) * 3) 0 0; padding: 0; display: grid; gap: calc(var(--space) * 3); }

/* Una cita es una tarjeta y no una fila: la fecha, el taller, el coche y en
   qué anda no caben en un renglón, y sin ellos había que abrirlas una por una
   para saber cuál era la del martes. La hoja del calendario a la izquierda,
   lo escrito a su lado, y el pie a lo ancho. Ver docs/SPEC.md 7. */
.date-card {
  position: relative;
  padding: calc(var(--space) * 4);
  border-radius: var(--r-card);
  background: var(--card);
  box-shadow: var(--lift-rest);
}
/* Sin filo de color: el montón ya dice lo que viene y lo anulado con su
   nombre, y la hoja del calendario en azul lo repite en cada tarjeta. Un filo
   más era la tercera vez. */
/* Lo archivado se apoya en el papel en vez de levantarse de él: sigue estando
   y se lee igual, pero deja de pedir la vista. */
.date-card.archived { background: var(--paper); box-shadow: none; }

/* La cabecera de todo lo que tiene día y hora: la hoja a la izquierda y, en
   columna a su lado, en qué anda, la hora y una línea. En qué anda iba a la
   derecha de la hora y le quitaba medio ancho: "Todavía sin hora" se partía
   casi siempre en dos renglones. */
.date-head { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: calc(var(--space) * 4); }
.date-head-text { display: flex; flex-direction: column; align-items: flex-start; gap: calc(var(--space) * 1); min-width: 0; }
.date-head-text p { margin: 0; }
.date-head-hour { font-size: 24px; font-weight: 750; letter-spacing: -0.02em; line-height: 1.15; font-variant-numeric: tabular-nums; }
/* Sin hora, lo que se lee es que no la hay, no una cifra: a tamaño de título
   de tarjeta y apagado. */
.date-head-hour.is-empty { font-size: 18px; font-weight: 650; letter-spacing: 0; color: var(--ink-soft); }
.date-head-line { color: var(--ink-soft); font-size: 14px; }
.date-card.past .date-head-hour, .date-card.cancelled .date-head-hour, .date-card.archived .date-head-hour { color: var(--ink-soft); font-weight: 650; }
.date-card.cancelled .state { color: var(--alarm); }

.date-where { font-size: 16px; font-weight: 550; }
.date-where a { color: var(--ink); text-decoration: none; }
.date-where a:hover { color: var(--plate); }
/* Se toca la tarjeta entera, como en el anuario: es lo que hace el pulgar, y
   un blanco que no lleva a ninguna parte se lee como que está apagada. */
.date-open::after { content: ""; position: absolute; inset: 0; z-index: 0; border-radius: var(--r-card); }
.date-open:focus-visible { outline: none; }
.date-card:focus-within { box-shadow: var(--lift-rest), 0 0 0 2px var(--plate); }

.date-what { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 1) calc(var(--space) * 2); margin: calc(var(--space) * 3) 0 0; padding-top: calc(var(--space) * 3); border-top: 1px solid var(--hairline); font-size: 14px; color: var(--ink-soft); }
.date-what:empty { display: none; }

/* El pie de la tarjeta es el del aviso: una celda a lo ancho, bajo un filo. */
.date-foot { margin-inline: calc(var(--space) * -4); margin-bottom: calc(var(--space) * -4); }
.date-foot > :only-child .notice-act, .date-foot > a.notice-act:only-child { border-bottom-left-radius: var(--r-card); border-bottom-right-radius: var(--r-card); }

/* La hoja del calendario: el día de la semana, el número y el mes, apilados en
   un cuadro. Azul para lo que viene, papel para lo demás: es el mismo color
   que el filo de su tarjeta y no dice nada más. */
.date-leaf {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 56px;
  padding: calc(var(--space) * 2) calc(var(--space) * 2);
  border-radius: var(--r-row);
  background: var(--paper);
  color: var(--ink-soft);
  line-height: 1.1;
  text-align: center;
}
.date-card.upcoming .date-leaf, .ticket.upcoming .date-leaf { background: var(--plate-tint); color: var(--plate-deep); }
.date-leaf-weekday, .date-leaf-month { font-size: 12px; font-weight: 650; text-transform: uppercase; letter-spacing: 0.04em; }
.date-leaf-day { font-size: 24px; font-weight: 750; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.date-leaf.is-blank { min-height: 72px; border: 1px dashed var(--dash); background: none; }

/* ── Los días cerrados ─────────────────────────────────────────────────────
   Una fila por cierre: la hoja del calendario, qué días en palabras con lo
   que dura y el porqué debajo, y borrar como un dibujo al final. Borrar era
   una píldora con su palabra que, en cuanto el cierre tenía horas, bajaba a
   una línea propia. */
.rows li.closed-day {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: calc(var(--space) * 4);
  padding-block: calc(var(--space) * 3);
}
.closed-day.upcoming .date-leaf { background: var(--plate-tint); color: var(--plate-deep); }
.closed-day-text { display: flex; flex-direction: column; gap: calc(var(--space) * 1); }
.closed-day-text p { margin: 0; }
.closed-day-name { font-weight: 650; }
.closed-day .meta { font-size: 14px; }
.closed-day:not(.upcoming) .closed-day-name { color: var(--ink-soft); }
.closed-day-form { display: contents; }
button.closed-day-erase {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--r-row);
  background: none;
  color: var(--ink-soft);
  box-shadow: none;
}
button.closed-day-erase:hover { background: var(--wash); color: var(--alarm); }
button.closed-day-erase:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

/* ── Una cita, vista por el conductor ─────────────────────────────────────
   Un billete: la hoja, la hora grande, en qué anda y el coche, y debajo lo
   único que se viene a hacer el día de la cita. Lo que viene flota, como lo
   que espera una respuesta en el garaje. */
.ticket.upcoming { box-shadow: var(--lift-float); }
.ticket .date-leaf { min-width: 64px; }
.ticket .date-leaf-day { font-size: 28px; }
.ticket .date-head-hour:not(.is-empty) { font-size: 28px; }
.hour-choice + .ticket { margin-top: calc(var(--space) * 4); }
/* Lo que se viene a comprobar, una cosa por línea con su dibujo delante: el
   coche, el tipo, lo que se le contó. El dibujo dice qué es cada línea sin
   rótulo encima. */
.ticket-facts { list-style: none; margin: calc(var(--space) * 4) 0 0; padding: 0; border-top: 1px solid var(--hairline); }
.ticket-facts > li { display: flex; align-items: flex-start; gap: calc(var(--space) * 3); min-height: 44px; padding: calc(var(--space) * 3) 0 0; }
.ticket-facts > li > .icon { flex: none; width: 20px; height: 20px; margin-top: 2px; color: var(--ink-soft); }
.ticket-fact { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 1) calc(var(--space) * 3); min-width: 0; }
.ticket-fact.ticket-said { display: block; color: var(--ink-soft); overflow-wrap: anywhere; }
.ticket-facts .car-pick { flex: 1; }
.state.cancelled { color: var(--alarm); }
.ticket-what { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 1) calc(var(--space) * 3); margin: calc(var(--space) * 4) 0 0; padding-top: calc(var(--space) * 4); border-top: 1px solid var(--hairline); color: var(--ink-soft); font-size: 14px; }
/* Lo que escribió el taller, con quién lo dice encima: es una cita de otro,
   y se lee como tal. */
.ticket-quote { margin: calc(var(--space) * 4) 0 0; padding: calc(var(--space) * 3) calc(var(--space) * 4); border-radius: var(--r-row); background: var(--paper); }
.ticket-quote figcaption { font-size: 14px; font-weight: 600; color: var(--ink-soft); }
.ticket-quote blockquote { margin: calc(var(--space) * 1) 0 0; overflow-wrap: anywhere; }
.ticket-quote blockquote p { margin: 0; }
.ticket-note { margin: calc(var(--space) * 4) 0 0; padding: calc(var(--space) * 3) calc(var(--space) * 4); border-radius: var(--r-row); background: var(--plate-tint); color: var(--plate-deep); font-weight: 550; }
.ticket-does { position: relative; margin: calc(var(--space) * 5) 0 0; }
.ticket-does + .hint { margin: calc(var(--space) * 2) 0 0; text-align: center; }
.ticket-said p { margin: 0 0 calc(var(--space) * 2); }
.ticket-said p:last-child { margin-bottom: 0; }
/* En el taller, lo que se viene a hacer con el billete es recibir el coche, y
   cierra la tarjeta como el "ya estoy aquí" del conductor. */
.ticket > .take-in { margin: calc(var(--space) * 5) 0 0; }

/* ── La escalera del cliente ──────────────────────────────────────────────
   Vertical, un peldaño por línea: el actual en tinta plena, los pasados con su
   marca y su fecha, los futuros apagados. Sin barra de progreso ni porcentaje:
   un coche no está al 60 %. Ver docs/DESIGN.md. */
.ladder {
  list-style: none;
  margin: 0 0 calc(var(--space) * 8);
  padding: calc(var(--space) * 2) calc(var(--space) * 5);
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-rest);
}

.rung {
  position: relative;
  display: grid;
  grid-template-columns: 24px 1fr auto;
  align-items: baseline;
  gap: calc(var(--space) * 2);
  min-height: 48px;
  padding: calc(var(--space) * 2) 0;
  color: var(--ink-faint);
}

/* La marca la pone el CSS y no el texto: un peldaño no se lee en voz alta
   diciendo "palomita". El hilo que los une tampoco se anuncia. */
.rung::before { content: ""; grid-column: 1; color: inherit; font-size: 15px; }
.rung::after {
  content: "";
  position: absolute;
  left: 7px;
  top: 32px;
  bottom: -4px;
  width: 2px;
  background: var(--hairline);
}
.rung:last-child::after { display: none; }
.rung.past { color: var(--ink-soft); }
.rung.past::before { content: "✓"; }
.rung.current { color: var(--ink); font-weight: 650; }
.rung.current::before { content: "●"; }

.rung time { grid-column: 3; font-size: 14px; font-variant-numeric: tabular-nums; }
.rung-line { grid-column: 2 / -1; margin: calc(var(--space) * 1) 0 0; font-weight: 400; font-size: 14px; color: var(--ink-soft); }

/* Una foto en el hilo es una miniatura que se toca: entera tapaba todo lo
   demás. Recortada a 4:3, que es como sale del móvil, para que varias fotos
   se lean como una fila de pruebas y no como carteles. Entera, en su página. */
.entry-shot {
  display: block;
  width: min(100%, 200px);
  margin: calc(var(--space) * 2) 0;
  overflow: hidden;
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background: var(--paper);
}
.entry-shot img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.entry-shot:hover { border-color: var(--ink-soft); }
.photo-full { display: block; width: 100%; height: auto; margin: calc(var(--space) * 2) 0; border-radius: var(--r-card); }


/* El garaje del cliente: una tarjeta por coche, tranquila y con aire. Un
   cliente abre esto cuatro veces en una semana; no necesita densidad. */
.garage { display: flex; flex-direction: column; gap: calc(var(--space) * 4); }
.car {
  padding: calc(var(--space) * 5);
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-rest);
}
.car h2, .car h3 { margin: 0; font-size: 17px; }
.car-name { margin: calc(var(--space) * 2) 0 0; font-size: 18px; font-weight: 650; letter-spacing: -0.01em; }
.car-stage { margin: calc(var(--space) * 3) 0 0; font-weight: 650; }
/* Dónde está y qué se puede hacer con él. El taller va debajo de la etapa
   porque la pregunta es "en qué anda", y la respuesta completa es las dos
   cosas: en qué etapa y en qué taller. */
.car-where { margin: calc(var(--space) * 1) 0 0; color: var(--ink-soft); }
/* Lo que se hace hoy con ese coche, al pie de su tarjeta y a lo ancho: es lo
   único que se pulsa de ella además de la matrícula, y una píldora pequeña al
   final de una tarjeta se leía como algo añadido. Ver docs/DESIGN.md. */
.car-does { margin: calc(var(--space) * 4) 0 0; }
a.button-link.car-does, form.car-does button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 48px;
}
/* Seguir o ver no empieza nada nuevo: blanco con filo, y en tinta, que es lo
   que se lee como pulsable y no como apagado. */
a.button-link.car-does, a.button-link.car-does:visited { background: var(--card); border-color: var(--rule); color: var(--ink); }
a.button-link.car-does:hover { background: var(--paper); border-color: var(--ink-soft); color: var(--ink); }
/* El devis que espera respuesta, dentro de la tarjeta del coche: el dibujo
   del papel, qué se pide y cuánto, en el tinte de lo que está encendido; y
   debajo el botón azul que lleva a contestarlo. Seguir la reparación queda
   como un enlace callado: no es lo que se viene a hacer hoy. */
.car-asks { display: flex; align-items: center; gap: calc(var(--space) * 3); margin: calc(var(--space) * 4) 0 0; padding: calc(var(--space) * 3) calc(var(--space) * 4); border-radius: var(--r-card); background: var(--plate-tint); color: var(--plate-deep); }
.car-asks-mark { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: var(--r-pill); background: var(--card); color: var(--plate); }
.car-asks-mark .icon { width: 20px; height: 20px; }
.car-asks-body { min-width: 0; }
.car-asks-what { margin: 0; font-size: 17px; font-weight: 650; }
.car-asks .car-asks-meta { margin: calc(var(--space) * 1) 0 0; font-size: 14px; }
.car-asks p:last-child { margin-bottom: 0; }
.car-asks-price { font-weight: 700; font-variant-numeric: tabular-nums; }
a.car-answer { margin-top: calc(var(--space) * 3); }
.car .quote-waiting { margin-top: calc(var(--space) * 4); }
.car-asks + .car-answer, .quote-waiting .car-asks { margin-top: 0; }
.quote-waiting .car-answer { margin-top: calc(var(--space) * 3); }
/* En el seguimiento va arriba y flota: es lo que la pantalla pide hacer. */
.panel.quote-asks { box-shadow: var(--lift-float); }
.car-follow, .car-follow:visited { display: flex; align-items: center; justify-content: center; min-height: 44px; margin-top: calc(var(--space) * 1); color: var(--ink-soft); font-weight: 550; text-decoration: none; }
.car-follow:hover { color: var(--ink); }

/* La última visita del coche, que se abre: el coche entregado no se pierde. */
.car-last, .car-last:visited { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--space) * 3); min-height: 44px; margin: calc(var(--space) * 2) 0 0; color: var(--ink-soft); font-size: 14px; text-decoration: none; }
.car-last .icon { flex: none; width: 18px; height: 18px; }
.car-last:hover { color: var(--ink); }

/* La matrícula y el nombre abren el coche para cambiarlo. */
.car-plate, .car-plate:visited {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(var(--space) * 2);
  color: var(--ink);
  text-decoration: none;
}
.car-plate .car-name { margin: 0; }
.car-plate:hover .plate { border-color: var(--plate); }
.garage { margin-bottom: calc(var(--space) * 4); }

/* ── El inicio del conductor ──────────────────────────────────────────────
   Tarjetas sueltas, no dentro de una sección: el coche ya es una tarjeta, y
   meterla en otra deja de agrupar nada. Lo que agrupa es el título con su
   cifra, apoyado en el papel. Ver docs/DESIGN.md, "Las secciones son
   tarjetas". */
.home-title { display: flex; align-items: center; gap: calc(var(--space) * 2); margin: calc(var(--space) * 8) 0 calc(var(--space) * 3); font-size: 20px; }
h1 + .home-title, .quote-asks + .home-title { margin-top: calc(var(--space) * 4); }
.home-title + .date-cards { margin-top: 0; }
.home-job .car-plate + .car-where { margin-top: calc(var(--space) * 1); }
/* La escalera de cada coche, en pequeño: sin marco propio porque ya está
   dentro de la tarjeta del coche, y con los peldaños más juntos. Se lee
   entera igual: el camino es lo que contesta. */
.ladder.is-compact { margin: calc(var(--space) * 4) 0 0; padding: calc(var(--space) * 1) 0 0; border: 0; border-top: 1px solid var(--hairline); border-radius: 0; box-shadow: none; }
.ladder.is-compact .rung { min-height: 36px; padding: calc(var(--space) * 1) 0; font-size: 15px; }
.ladder.is-compact .rung::after { top: 26px; }


/* ── Devis y facturas ─────────────────────────────────────────────────────
   La tabla es lo único que puede ser más ancho que la columna, y entonces se
   desplaza sola dentro de su caja. */
.lines { overflow-x: auto; margin-bottom: calc(var(--space) * 4); }
.lines table { width: 100%; border-collapse: collapse; font-size: 14px; }
.lines th, .lines td { padding: calc(var(--space) * 3) calc(var(--space) * 2); border-bottom: 1px solid var(--hairline); text-align: left; }
.lines th { font-weight: 550; color: var(--ink-soft); }
/* Dentro de su tarjeta el papel ya tiene margen: las celdas se aprietan para
   que las cuatro columnas quepan en 375 px sin desplazarse de lado. */
.panel .lines th, .panel .lines td { padding-inline: calc(var(--space) * 1); }
.panel .lines :is(th, td):first-child { padding-left: 0; }
.panel .lines :is(th, td):last-child { padding-right: 0; }
.line-kind { display: block; color: var(--ink-soft); }
.lines .figure { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

.totals { display: grid; grid-template-columns: 1fr auto; gap: calc(var(--space) * 2) calc(var(--space) * 4); margin: 0 0 calc(var(--space) * 6); }
.totals dt { color: var(--ink-soft); }
.totals dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
.totals .due { font-weight: 700; color: var(--ink); font-size: 20px; }

/* ── El papel que se escribe ──────────────────────────────────────────────
   Un devis o una factura en una sola pantalla: de dónde sale arriba, las
   líneas en su tarjeta con los totales al pie, el papel propio si lo hay, y al
   final lo que se hace con él, a lo ancho. */
.paper-head { margin-bottom: calc(var(--space) * 5); }
.paper-head .head-line { align-items: center; }
.paper-head h1 { margin: 0; }
.paper-head .meta { margin: calc(var(--space) * 2) 0 0; }
.back-to, .back-to:visited {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  margin-bottom: calc(var(--space) * 1);
  color: var(--ink-soft);
  font-weight: 550;
  text-decoration: none;
}
.back-to .icon { width: 18px; height: 18px; }
.back-to:hover { color: var(--ink); }

.paper-form { display: flex; flex-direction: column; gap: calc(var(--space) * 4); }
.paper-form .panel, .paper-form .errors { margin: 0; }

.line-rows { list-style: none; margin: 0; padding: 0; counter-reset: line; }
/* Cada línea es un bloque con su raya debajo: qué es, a lo ancho, y sus
   cifras en una rejilla. Dos por fila en un móvil, las cuatro en una tableta. */
.line-row { padding: calc(var(--space) * 4) 0; border-bottom: 1px solid var(--hairline); }
.line-row:first-child { padding-top: 0; }
/* Marcar la casilla de quitar es quitarla, también sin JavaScript. */
.line-row:has(input[name$="[_destroy]"]:checked) { display: none; }
.line-top { display: flex; align-items: center; gap: calc(var(--space) * 2); }
.line-label { flex: 1; min-width: 0; font-weight: 600; }
.line-remove {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-pill);
  color: var(--ink-faint);
  cursor: pointer;
}
.line-remove:hover { background: var(--paper); color: var(--alarm); }
.line-remove:focus-within { outline: 3px solid var(--plate); outline-offset: 2px; }
.line-figures { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: calc(var(--space) * 3); margin-top: calc(var(--space) * 3); }
.line-figures span { display: flex; flex-direction: column; gap: calc(var(--space) * 1); min-width: 0; }
.line-figures label { font-size: 13px; font-weight: 550; color: var(--ink-soft); }
@media (min-width: 560px) {
  .line-figures { grid-template-columns: 5rem minmax(0, 1fr) 6.5rem minmax(0, 1fr); }
}

/* Añadir una línea es una fila más que todavía no está: el mismo ancho que
   las de encima, con el filo de puntos de lo que se va a escribir. */
button.line-add {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 2);
  width: 100%;
  min-height: 48px;
  margin-top: calc(var(--space) * 4);
  border: 1px dashed var(--dash);
  border-radius: var(--r-row);
  background: transparent;
  box-shadow: none;
  color: var(--plate);
}
button.line-add:hover { border-color: var(--plate); background: var(--plate-tint); }
.line-add .icon, .menu-chip .icon { width: 18px; height: 18px; }

.from-the-menu { margin-top: calc(var(--space) * 5); }
.from-the-menu h3 { margin: 0 0 calc(var(--space) * 2); font-size: 14px; font-weight: 600; color: var(--ink-soft); }
.menu-chips { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 2); }
button.menu-chip {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 1);
  min-height: 40px;
  padding: 0 calc(var(--space) * 3) 0 calc(var(--space) * 2);
  border-color: var(--rule);
  background: var(--card);
  box-shadow: none;
  color: var(--ink);
  font-size: 14px;
  font-weight: 550;
}
button.menu-chip:hover { border-color: var(--ink-soft); background: var(--paper); }
.menu-chip .icon { color: var(--plate); }

.paper-totals { margin: calc(var(--space) * 5) 0 0; padding-top: calc(var(--space) * 4); border-top: 1px solid var(--rule); }

/* El papel propio: una caja de puntos que se toca para elegir el archivo. El
   campo del sistema va encima, transparente: su "ningún archivo" no habla el
   idioma de la cuenta, y elegir ya guarda y vuelve con el nombre puesto. */
.paper-upload .hint { margin: 0 0 calc(var(--space) * 4); }
.upload-drop {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--space) * 1);
  padding: calc(var(--space) * 5) calc(var(--space) * 4);
  border: 1px dashed var(--dash);
  border-radius: var(--r-card);
  text-align: center;
  cursor: pointer;
}
.upload-drop:hover, .upload-drop:focus-within { border-color: var(--plate); background: var(--plate-tint); }
.upload-drop > .icon { width: 26px; height: 26px; color: var(--plate); }
.upload-say { font-weight: 650; color: var(--plate); }
.upload-drop .hint { margin: 0; }
.upload-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
/* Las fotos de una petición de cita: cuadradas, en fila de tres, cada una con
   su cruz para quitarla. La cruz es un círculo pequeño, pero lo que se toca
   mide 44 px. La caja de elegir se va cuando ya están las tres. */
.request-shots-pick { display: flex; flex-direction: column; gap: calc(var(--space) * 2); }
.request-shots { display: grid; grid-template-columns: repeat(3, 1fr); gap: calc(var(--space) * 2); margin: 0; padding: 0; list-style: none; }
.request-shots:empty { display: none; }
.request-shot { position: relative; }
.request-shot img, .request-shot a { display: block; }
.request-shot img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--r-card); background: var(--paper); }
.request-shot-drop {
  position: absolute;
  top: 0;
  right: 0;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
}
.request-shot-drop .icon { width: 28px; height: 28px; padding: calc(var(--space) * 1.5); border-radius: var(--r-pill); background: var(--card); box-shadow: var(--lift-float); color: var(--ink); }
.upload-drop[hidden] { display: none; }
.upload-done { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--space) * 3); }
.upload-file { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); min-width: 0; min-height: 44px; font-weight: 600; overflow-wrap: anywhere; }
.upload-file .icon { flex: none; }
.upload-done form, .upload-done button { flex: none; }

/* La foto de la ficha en Réglages, recortada a lo ancho como sale arriba de
   la página, con quitarla encima de su esquina. */
.cover-pick { margin: calc(var(--space) * 6) 0; }
.cover-title { margin: 0; color: var(--ink-soft); font-size: 14px; font-weight: 550; }
.cover-pick > .hint { margin: 0 0 calc(var(--space) * 2); }
.cover-now { position: relative; margin: 0; }
.cover-now img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--r-card); background: var(--paper); }
.cover-now button {
  position: absolute;
  top: calc(var(--space) * 2);
  right: calc(var(--space) * 2);
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  background: var(--card);
  box-shadow: var(--lift-float);
}
.cover-now button .icon { width: 16px; height: 16px; }

.paper-until { display: flex; flex-direction: column; gap: calc(var(--space) * 1); }
.paper-until label { font-size: 14px; font-weight: 550; color: var(--ink-soft); }
@media (min-width: 560px) {
  .paper-until { max-width: 16rem; }
}

/* Lo que se hace con el papel, al final y a lo ancho: el azul que lo manda
   arriba y guardar a medias debajo, callado. En un ordenador se ponen en fila,
   el que manda a la derecha, que es donde acaba la lectura. */
.paper-does { display: flex; flex-direction: column; gap: calc(var(--space) * 3); margin: calc(var(--space) * 2) 0 0; }
.paper-does > *, .paper-does form, .paper-does button, .paper-does .button-link { width: 100%; }
.paper-does form { margin: 0; }
.paper-does button, .paper-does .button-link { justify-content: center; gap: calc(var(--space) * 2); min-height: 52px; }
.paper-does .button-link { display: flex; }
.paper-does .icon { width: 18px; height: 18px; }
button.paper-send { display: flex; align-items: center; font-size: 17px; }
@media (min-width: 760px) {
  .paper-does { flex-direction: row-reverse; justify-content: flex-start; }
  .paper-does > *, .paper-does form, .paper-does button, .paper-does .button-link { width: auto; }
  .paper-does button, .paper-does .button-link { padding-inline: calc(var(--space) * 6); }
}

/* La misma fila fuera de un papel: lo que se hace con una cita al final de su
   pantalla. Solo sus hijos directos: lo que va dentro de una hoja que se abre
   desde aquí tiene su propia forma. */
.wide-does { display: flex; flex-direction: column; gap: calc(var(--space) * 3); margin: calc(var(--space) * 6) 0; }
.wide-does > form { margin: 0; }
.wide-does > form > button { display: flex; align-items: center; justify-content: center; gap: calc(var(--space) * 2); width: 100%; min-height: 52px; }
.wide-does > form > button .icon { flex: none; width: 18px; height: 18px; }
@media (min-width: 760px) {
  .wide-does { flex-direction: row-reverse; justify-content: flex-start; }
  .wide-does > form > button { width: auto; padding-inline: calc(var(--space) * 6); }
}

/* Dentro de un panel, la fila ancha sigue a lo de encima sin el aire de fin
   de pantalla. La hoja que abre un <summary> se dibuja como sus vecinos. */
.wide-does.kind-next { margin: calc(var(--space) * 5) 0 0; }
/* Aquí el azul va el último en el orden del documento -poner la hora, luego
   enviar-, así que en fila no se invierte: sigue quedando a la derecha. */
@media (min-width: 760px) {
  .wide-does.kind-next { flex-direction: row; justify-content: flex-end; }
}
.wide-does > details > summary { display: flex; align-items: center; justify-content: center; gap: calc(var(--space) * 2); min-height: 52px; list-style: none; cursor: pointer; }
.wide-does > details > summary::-webkit-details-marker, .wide-does > details > summary::marker { display: none; content: ""; }
.wide-does > details > summary .icon { flex: none; width: 18px; height: 18px; }
.wide-does > details > summary.button-link.quiet { color: var(--ink); background: var(--card); }
.kind-next-hint { margin: calc(var(--space) * 3) 0 0; text-align: center; }
@media (min-width: 760px) {
  .wide-does > details > summary { padding-inline: calc(var(--space) * 6); }
  .kind-next-hint { text-align: right; }
}

/* ── Elegir una hora ──────────────────────────────────────────────────────
   La semana en una tira -un día por columna, los que tienen alguna libre- y
   debajo las horas del señalado, en botones que se aciertan con el pulgar.
   El día se señala con una radio escondida en su etiqueta, y `:has()` enseña
   su rejilla: sin JavaScript. Ver shared/_hour_picker. */
/* Dos tiras, una encima de otra. Arriba los días, en tarjetas altas que se
   corren con el dedo; debajo, en una banda de papel con el día escrito
   encima, las horas del día marcado, en otra tira que se corre igual. Partidas
   en filas, las horas quedaban debajo de una fila de días que no era la suya
   y días y horas se leían como una sola rejilla.

   Las tiras llegan hasta el filo de la hoja: lo que asoma cortado en el borde
   es lo que dice que hay más. En un ordenador los días caben y las horas
   parten en filas, que con ratón no se corre nada de lado. */
/* `--bleed` es el relleno de lo que la envuelve -una tarjeta, o la hoja del
   móvil, que lleva menos-, y es lo que las tiras salen hasta el filo. La
   columna es `minmax(0, 1fr)`: con la de fábrica, la tira medía lo que miden
   todos sus días juntos y la hoja entera se corría de lado. */
.hour-picker { --bleed: calc(var(--space) * 5); display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--space) * 3); margin: 0; }
@media (max-width: 759px) {
  .sheet .hour-picker { --bleed: calc(var(--space) * 4); }
}
.hour-days, .hour-times {
  display: flex;
  gap: calc(var(--space) * 2);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
}
.hour-days::-webkit-scrollbar, .hour-times::-webkit-scrollbar { display: none; }
.hour-days {
  margin-inline: calc(var(--bleed) * -1);
  padding: calc(var(--space) * 0.5) var(--bleed);
  scroll-padding-inline: var(--bleed);
}
.hour-day {
  position: relative;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  width: 64px;
  min-height: 72px;
  padding: calc(var(--space) * 2) 0;
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  background: var(--card);
  color: var(--ink-soft);
  line-height: 1.1;
  cursor: pointer;
  scroll-snap-align: start;
}
.hour-day-pick { position: absolute; opacity: 0; pointer-events: none; }
.hour-day-weekday, .hour-day-month { font-size: 12px; font-weight: 650; text-transform: uppercase; letter-spacing: 0.02em; }
.hour-day-number { font-size: 20px; font-weight: 750; color: var(--ink); font-variant-numeric: tabular-nums; }
.hour-day:hover { border-color: var(--ink-soft); }
.hour-day:has(.hour-day-pick:checked) { border-color: var(--plate); background: var(--plate); color: #fff; }
.hour-day:has(.hour-day-pick:checked) .hour-day-number { color: #fff; }
.hour-day:has(.hour-day-pick:focus-visible) { outline: 2px solid var(--plate); outline-offset: 2px; }

/* La banda de las horas: papel y no tarjeta, con el día marcado escrito en
   su cabeza. Una por día, y sale la del día marcado: el mismo puesto en su
   tira que el día en la suya. Son siete como mucho. */
.hour-grid {
  display: none;
  margin-inline: calc(var(--bleed) * -1);
  padding: calc(var(--space) * 3) 0 calc(var(--space) * 4);
  background: var(--paper);
  border-block: 1px solid var(--hairline);
}
.hour-picker:has(.hour-day:nth-child(1) .hour-day-pick:checked) .hour-grid:nth-child(1),
.hour-picker:has(.hour-day:nth-child(2) .hour-day-pick:checked) .hour-grid:nth-child(2),
.hour-picker:has(.hour-day:nth-child(3) .hour-day-pick:checked) .hour-grid:nth-child(3),
.hour-picker:has(.hour-day:nth-child(4) .hour-day-pick:checked) .hour-grid:nth-child(4),
.hour-picker:has(.hour-day:nth-child(5) .hour-day-pick:checked) .hour-grid:nth-child(5),
.hour-picker:has(.hour-day:nth-child(6) .hour-day-pick:checked) .hour-grid:nth-child(6),
.hour-picker:has(.hour-day:nth-child(7) .hour-day-pick:checked) .hour-grid:nth-child(7) { display: block; }
.hour-grid-day {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  margin: 0 0 calc(var(--space) * 3);
  padding-inline: var(--bleed);
  color: var(--plate-deep);
  font-size: 14px;
  font-weight: 650;
}
.hour-grid-day::first-letter { text-transform: uppercase; }
.hour-times { padding: calc(var(--space) * 0.5) var(--bleed); scroll-padding-inline: var(--bleed); }
.hour-times > .hour-pick { flex: none; min-width: 76px; scroll-snap-align: start; }
@media (min-width: 760px) {
  .hour-picker { --bleed: calc(var(--space) * 5); }
  .hour-days, .hour-grid { margin-inline: 0; }
  .hour-days { padding-inline: 0; }
  /* Los siete caben: se reparten el ancho en vez de correrse. */
  .hour-day { flex: 1 1 0; width: auto; min-width: 56px; }
  .hour-grid { border: 1px solid var(--hairline); border-radius: var(--r-card); }
  .hour-times { flex-wrap: wrap; overflow: visible; }
}
button.hour-pick, label.hour-pick {
  min-height: 48px;
  padding: 0 calc(var(--space) * 2);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  background: var(--card);
  color: var(--ink);
  font-size: 16px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  box-shadow: none;
}
button.hour-pick:hover { border-color: var(--plate); background: var(--plate-tint); color: var(--plate-deep); }

/* La hora que se marca antes de reservarla: la radio va escondida en su
   botón, y la marcada se llena de azul, como el día. */
label.hour-pick { position: relative; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.hour-pick-input { position: absolute; opacity: 0; pointer-events: none; }
label.hour-pick:has(.hour-pick-input:checked) { border-color: var(--plate); background: var(--plate); color: #fff; }
label.hour-pick:has(.hour-pick-input:focus-visible) { outline: 2px solid var(--plate); outline-offset: 2px; }
label.hour-pick:hover { border-color: var(--plate); }
/* La hora que el taller ya le rechazó: en su sitio, apagada y sin pulsarse. */
button.hour-pick:disabled, label.hour-pick:has(.hour-pick-input:disabled) {
  border-color: var(--hairline);
  background: var(--wash);
  color: var(--ink-faint);
  box-shadow: none;
  cursor: not-allowed;
}
.hour-confirm { margin-top: calc(var(--space) * 2); }
/* Hasta que no hay hora marcada, el botón está pero no pesa. */
.hour-picker:not(:has(.hour-pick-input:checked)) .hour-confirm .panel-save { background: var(--wash); border-color: var(--wash); color: var(--ink-soft); box-shadow: none; }

/* Lo que espera al cliente en su cita: elegir hora. Flota, sin filo. */
.hour-choice { box-shadow: var(--lift-float); }
.hour-choice h2 { margin-bottom: calc(var(--space) * 1); }
.hour-choice-what { margin: 0 0 calc(var(--space) * 4); color: var(--ink-soft); font-size: 14px; }

/* La hoja de poner la hora: las libres arriba y cualquier otra debajo, tras
   una raya. Más ancha que las otras hojas: la tira de siete días no cabe en
   380 px sin apretarse. */
.ask-panel.hour-panel { width: min(520px, calc(100vw - var(--space) * 8)); }
@media (max-width: 759px) {
  .ask-panel.hour-panel { width: auto; }
}
.hour-part h3 { margin: 0 0 calc(var(--space) * 3); font-size: 15px; font-weight: 650; }
.hour-any { margin-top: calc(var(--space) * 6); padding-top: calc(var(--space) * 5); border-top: 1px solid var(--hairline); }
.hour-any-form { display: grid; grid-template-columns: 1fr 1fr; gap: calc(var(--space) * 3); }
.hour-any-form .hour-any-day, .hour-any-form .panel-save { grid-column: 1 / -1; }
.hour-any-form .field { display: flex; flex-direction: column; gap: calc(var(--space) * 1); min-width: 0; }
.hour-any-form label { font-size: 14px; font-weight: 550; color: var(--ink-soft); }
.hour-any-form input, .hour-any-form select { width: 100%; min-width: 0; }

/* Tirar algo: lejos de lo que se usa, detrás de una raya y en el rojo de las
   alarmas, que es lo único que se pinta de ese color. */
.drop-row { margin-top: calc(var(--space) * 10); padding-top: calc(var(--space) * 4); border-top: 1px solid var(--hairline); }
.drop-row form { margin: 0; }
/* Un botón y no un enlace: en rojo suelto sobre el papel se perdía al final de
   la pantalla. Hueco y con el filo rojo, para que no pese lo que pesa guardar,
   que es lo que se viene a hacer. De lado a lado en el móvil, donde lo busca el
   pulgar; en un ordenador, del largo de lo que dice, salvo en un panel
   estrecho, donde el ancho es el del panel. */
button.drop-button {
  width: 100%;
  background: var(--card);
  border-color: var(--alarm);
  color: var(--alarm);
  box-shadow: none;
}
button.drop-button:hover { background: var(--alarm); border-color: var(--alarm); color: #fff; }
@media (min-width: 760px) {
  button.drop-button { width: auto; }
  .job-edit-panel button.drop-button { width: 100%; }
}

/* El mismo botón cuando abre una hoja antes de tirar nada: anular una cita
   pregunta por qué. Es un <summary>, así que se le da la forma a mano. */
summary.drop-summary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 2);
  min-height: 52px;
  padding: 0 calc(var(--space) * 6);
  border: 1px solid var(--alarm);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--alarm);
  font-weight: 600;
  list-style: none;
  cursor: pointer;
}
summary.drop-summary::-webkit-details-marker, summary.drop-summary::marker { display: none; content: ""; }
summary.drop-summary .icon { flex: none; width: 18px; height: 18px; }
summary.drop-summary:hover, .cancelling[open] > summary.drop-summary { background: var(--alarm); color: #fff; }
summary.drop-summary:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

/* Los motivos que se dicen casi siempre, uno por botón y a lo ancho: la frase
   entera se lee antes de mandarla, porque es lo que va a leer el cliente. La
   flecha dice que sale de un toque. */
.cancel-reasons { display: flex; flex-direction: column; gap: calc(var(--space) * 2); margin: calc(var(--space) * 3) 0 calc(var(--space) * 5); }
.cancel-reasons form { margin: 0; }
button.cancel-reason {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--space) * 3);
  width: 100%;
  min-height: 52px;
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  background: var(--card);
  color: var(--ink);
  font-weight: 500;
  line-height: 1.35;
  text-align: left;
  box-shadow: none;
}
button.cancel-reason:hover { background: var(--paper); border-color: var(--ink-soft); color: var(--ink); }
button.cancel-reason .icon { flex: none; width: 18px; height: 18px; color: var(--alarm); }
.cancel-own { padding-top: calc(var(--space) * 4); border-top: 1px solid var(--hairline); }

/* El aviso con el que se llegó, al pie de la pantalla del asunto. Es la
   tarjeta de la lista sin enlace: ya se está donde llevaba. */
.at-hand { margin: calc(var(--space) * 6) 0; box-shadow: var(--lift-rest); }
.at-hand .notice-what::after { content: none; }
.at-hand .notice-what:hover { color: var(--ink); }
p.notice-what { margin: 0; }


/* Lo que la pantalla del cliente pide hacer va en su propia caja, y solo eso.
   Es la única caja de la aplicación con el borde en azul de matrícula. */
/* Lo que espera una respuesta del cliente. Una sola forma para las dos
   pantallas donde aparece —el garaje y el seguimiento—, porque es la misma
   cosa: el filo azul y la sombra que flota. El color no se gasta en un fondo
   de alarma; la urgencia es posición, y esto va arriba. Ver docs/DESIGN.md. */
.asks, .waiting {
  padding: calc(var(--space) * 5);
  margin-bottom: calc(var(--space) * 6);
  border: 1px solid var(--plate);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}
.asks h2, .waiting h2 { margin: 0 0 calc(var(--space) * 2); font-size: 18px; }
.asks p { margin: 0 0 calc(var(--space) * 3); }

/* La recogida: en qué quedó, dicho en una línea con su dibujo, y debajo lo que
   se hace. Lo que espera a quien mira va en azul: es su turno. */
.pickup-state { display: flex; align-items: flex-start; gap: calc(var(--space) * 2); margin: 0 0 calc(var(--space) * 3); font-weight: 600; }
.pickup-state .icon { flex: none; width: 20px; height: 20px; margin-top: 1px; color: var(--ink-soft); }
.pickup-state.pending, .pickup-state.pending .icon { color: var(--plate-deep); }
.pickup-state.agreed .icon { color: var(--plate); }
.pickup-form { margin: 0; }
.pickup-or { margin: calc(var(--space) * 3) 0 0; }
.pickup-other { margin-top: calc(var(--space) * 3); }
/* Las paradas "Llegada" y "Listo" abren su hoja —la llegada, la recogida—: su
   <summary> es la fila de la vía, y lo anotado va debajo del nombre, en la
   segunda columna. */
.stop:has(> :is(.pickup-sheet, .reception-sheet)) { display: block; padding: 0; }
:is(.pickup-sheet, .reception-sheet) > summary { list-style: none; cursor: pointer; }
:is(.pickup-sheet, .reception-sheet) > summary::-webkit-details-marker,
:is(.pickup-sheet, .reception-sheet) > summary::marker { display: none; content: ""; }
summary.stop-move { border-radius: var(--r-row); }
summary.stop-move:hover { background: color-mix(in srgb, currentcolor 7%, var(--card)); }
summary.stop-move:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }
.stop.current > :is(.pickup-sheet, .reception-sheet) > summary.stop-move { row-gap: calc(var(--space) * 1); padding-block: calc(var(--space) * 3); }
.stop-pickup { grid-column: 2 / -1; font-size: 14px; }
.stop-pickup .pickup-state { margin: 0; font-weight: 600; color: var(--ink); }
.stop-pickup .pickup-state .icon { width: 18px; height: 18px; }
.stop-pickup-ask { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); color: var(--plate-deep); font-weight: 650; }
.stop-pickup-ask .icon { flex: none; width: 18px; height: 18px; color: var(--plate); }
/* Los kilómetros con que entró, al lado de "Llegada": se leen en la vía sin
   abrir nada. Si la línea no da, bajan enteros al renglón de debajo. */
.stop-lead { display: flex; flex-wrap: wrap; align-items: center; column-gap: calc(var(--space) * 3); row-gap: calc(var(--space) * 1); min-width: 0; }
.stop-lead > :not(.stop-name) { font-size: 14px; }
.stop-reading { display: inline-flex; align-items: center; gap: calc(var(--space) * 2); color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.stop-reading .icon { flex: none; width: 18px; height: 18px; color: var(--ink-soft); }

/* ── La llegada ───────────────────────────────────────────────────────────
   Los kilómetros, grandes y con su unidad al lado dentro del mismo campo: se
   escriben de pie junto al coche, mirando el contador. Las fotos, en una
   rejilla de miniaturas, como en el registro. */
.with-unit {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  padding-right: calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  background: var(--card);
}
.with-unit:focus-within { border-color: var(--plate); outline: 2px solid var(--plate); outline-offset: -2px; }
.with-unit > input {
  flex: 1;
  min-width: 0;
  min-height: 52px;
  border: 0;
  background: none;
  box-shadow: none;
  font-size: 22px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.with-unit > input:focus { outline: none; }
/* Sin flechas: los kilómetros se escriben, nadie los sube de uno en uno. */
.with-unit > input::-webkit-inner-spin-button, .with-unit > input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.with-unit > input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.with-unit-word { flex: none; color: var(--ink-soft); font-weight: 600; }
.entry-shots, .reception-shots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: calc(var(--space) * 2);
  margin: calc(var(--space) * 2) 0;
}
.entry-shots .entry-shot { width: 100%; margin: 0; }
.reception-shots img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--r-row); }
/* La hoja: en qué quedó, aceptar si le toca, otra hora, y "cuando quiera"
   tras un "o" que dice que son dos caminos y no dos pasos. */
/* La recogida del conductor, como el billete de su cita: flota, porque es lo
   que la pantalla le pide hoy. Lo que se hace ahora, a lo ancho; proponer otra
   hora y cómo llegar, filas debajo. */
.pickup-ticket { box-shadow: var(--lift-float); }
.pickup-ticket-title { display: flex; align-items: center; gap: calc(var(--space) * 2); margin: 0 0 calc(var(--space) * 4); font-size: 17px; font-weight: 650; }
.pickup-ticket-title .icon { flex: none; width: 20px; height: 20px; color: var(--plate); }
.pickup-now:empty { display: none; }
.pickup-now > .ticket-does, .pickup-now > .pickup-form { margin: calc(var(--space) * 5) 0 0; }
.pickup-now > .ticket-does + .ticket-does { margin-top: calc(var(--space) * 3); }
.pickup-hint { margin: calc(var(--space) * 2) 0 0; text-align: center; }
.pickup-more { margin: calc(var(--space) * 4) 0 0; border-top: 1px solid var(--hairline); }
.pickup-more:empty { display: none; }
.pickup-other-open { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--space) * 3); min-height: 52px; list-style: none; cursor: pointer; }
.pickup-other-open::-webkit-details-marker, .pickup-other-open::marker { display: none; content: ""; }
.pickup-other-open .icon { flex: none; width: 18px; height: 18px; color: var(--ink-soft); }
.pickup-other-open .place-name { flex: 1; }
.pickup-ticket .date-leaf { background: var(--plate-tint); color: var(--plate-deep); }

/* La hoja cuelga de la parada, que va en el color de su etapa: dentro se
   vuelve a la tinta, o todo lo escrito salía en verde. */
.pickup-panel, .reception-panel { color: var(--ink); cursor: auto; }
.pickup-panel .pickup-accept { margin: 0 0 calc(var(--space) * 5); }
.pickup-panel .pickup-state { margin-bottom: calc(var(--space) * 4); }
.pickup-or-line { display: flex; align-items: center; gap: calc(var(--space) * 3); margin: calc(var(--space) * 4) 0 0; color: var(--ink-soft); font-size: 14px; }
.pickup-or-line::before, .pickup-or-line::after { content: ""; flex: 1; height: 1px; background: var(--hairline); }
.pickup-panel .pickup-or { margin-top: calc(var(--space) * 3); }
/* Rechazar es un botón como aceptar, al lado: su hoja cuelga en medio. */
.paper-does summary.button-link { display: flex; align-items: center; justify-content: center; gap: calc(var(--space) * 2); min-height: 52px; list-style: none; cursor: pointer; }
.paper-does summary.button-link::-webkit-details-marker { display: none; }

/* La nota en cifra y las estrellas al lado: 4,3 dice más que cuatro dibujos y
   medio. Ver docs/DESIGN.md. */
.rating { display: inline-flex; align-items: baseline; gap: calc(var(--space) * 2); }
.rating-figure { font-weight: 700; font-size: 18px; font-variant-numeric: tabular-nums; }
.rating-stars { color: var(--ink-soft); letter-spacing: 1px; }

/* Lo que dicen sus clientes. Arriba la nota en cifra grande con sus
   estrellas, y al lado las cuatro barras finas por criterio: en un ordenador
   una junto a otra, en un móvil una encima de otra. Debajo, las opiniones en
   fila y separadas por una línea: una tarjeta dentro de la sección era una
   caja dentro de otra. */
.score { display: grid; gap: calc(var(--space) * 5); margin: 0 0 calc(var(--space) * 2); padding-bottom: calc(var(--space) * 5); border-bottom: 1px solid var(--hairline); }
@media (min-width: 560px) {
  .score:has(.score-criteria) { grid-template-columns: auto 1fr; align-items: center; gap: calc(var(--space) * 8); }
}
.panel > .score:only-child { margin: 0; padding-bottom: 0; border-bottom: 0; }
.score-figure { display: flex; flex-direction: column; gap: calc(var(--space) * 1); }
.score-number { font-size: 48px; font-weight: 750; letter-spacing: -0.03em; line-height: 1; font-variant-numeric: tabular-nums; }
.score-figure .rating-stars { color: var(--ink); font-size: 18px; }
.score-count { color: var(--ink-soft); font-size: 14px; }
.score-criteria { gap: calc(var(--space) * 3); }
.score-criteria .gauge-top { font-size: 14px; }

/* Las opiniones del lado del taller: una tarjeta por opinión, porque cada
   una se decide —responder o señalar—. Señalar va al pie, en su celda y
   separado de responder por la línea: pesan lo contrario y no pueden estar a
   un dedo. */
.review-cards { list-style: none; display: grid; gap: calc(var(--space) * 4); margin: 0; padding: 0; }
.review.review-card { padding: calc(var(--space) * 5) calc(var(--space) * 5) 0; border: 1px solid var(--hairline); border-radius: var(--r-card); background: var(--card); box-shadow: var(--lift-rest); }
p.review-car.meta { margin: calc(var(--space) * 4) 0 0; color: var(--ink-soft); font-size: 14px; }
.review-scores { margin: calc(var(--space) * 3) 0 0; color: var(--ink-soft); font-size: 14px; }
.review-scores strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.review-answer { margin-top: calc(var(--space) * 4); }
.review-foot { margin: calc(var(--space) * 5) calc(var(--space) * -5) 0; }
.review-foot > :only-child, .review-foot > :only-child .notice-act { flex: 1; border-radius: 0 0 var(--r-card) var(--r-card); }
.review-flagged { margin: 0; cursor: default; }
/* En la consola, de qué taller habla la opinión va encima de todo: es lo
   primero que se pregunta quien modera, y lleva a su ficha. */
.review-about { margin: 0 0 calc(var(--space) * 3); font-size: 14px; font-weight: 650; }
.review-about a { color: var(--plate); text-decoration: none; }
.review-foot > form { flex: 1 1 0; }
.review-foot .notice-act { border-radius: 0; }
.review-foot > form:first-child .notice-act { border-bottom-left-radius: var(--r-card); }
.review-foot > form:last-child .notice-act { border-bottom-right-radius: var(--r-card); }
.reviews { list-style: none; margin: 0; padding: 0; }
.review { padding: calc(var(--space) * 5) 0; border-bottom: 1px solid var(--hairline); }
.review:last-child { padding-bottom: 0; border-bottom: 0; }
.review-head { display: flex; align-items: center; gap: calc(var(--space) * 3); }
.review-head .avatar { width: 40px; height: 40px; font-size: 14px; }
.review-who { flex: 1; display: flex; flex-direction: column; min-width: 0; margin: 0; line-height: 1.3; }
.review-who strong { font-weight: 650; }
.review-who time { color: var(--ink-soft); font-size: 14px; }
.review-stars { flex: none; color: var(--ink); letter-spacing: 1px; }
.review-body { margin: calc(var(--space) * 3) 0 0; color: var(--ink); font-size: 16px; line-height: 1.55; overflow-wrap: anywhere; }
.review-body p { margin: 0 0 calc(var(--space) * 2); }
.review-body p:last-child { margin-bottom: 0; }
.review-reply { margin-top: calc(var(--space) * 4); padding: calc(var(--space) * 3) calc(var(--space) * 4); border-radius: var(--r-row); background: var(--paper); overflow-wrap: anywhere; }
.review-reply-who { margin: 0 0 calc(var(--space) * 1); font-size: 14px; font-weight: 650; }
.review-reply p { margin: 0; }
.review-reply .review-reply-who { margin-bottom: calc(var(--space) * 1); }
.scores { display: grid; grid-template-columns: 1fr auto; gap: calc(var(--space) * 1) calc(var(--space) * 4); margin: calc(var(--space) * 3) 0; font-size: 14px; }
.scores dt { color: var(--ink-soft); }
.scores dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }

/* Lo que hay que prever tiene su sección, y nunca la banda de prioridad: no
   corre prisa hoy. Ver docs/SPEC.md 12. */
.maintenance { margin-bottom: calc(var(--space) * 7); }
.maintenance h2 { font-size: 15px; font-weight: 650; color: var(--ink-soft); margin: 0 0 calc(var(--space) * 2); }
.due-line { display: block; }
.maintenance .rows li { padding: calc(var(--space) * 3) 0; }
.maintenance form { margin-top: calc(var(--space) * 2); }

.offer-price { font-weight: 700; font-size: 20px; }

/* Las cifras del panel. Un grupo de cifras es una sola tarjeta, y cada cifra
   una fila: el nombre y la comparación a la izquierda, el número a la
   derecha. Una tarjeta por cifra apilaba nueve tarjetas en un móvil antes de
   llegar a nada. En un ordenador, las filas se ponen en columnas separadas
   por un filo. "120,00 €" no se parte: la cifra no se estrecha nunca. */
.figures {
  display: grid;
  margin-bottom: calc(var(--space) * 4);
  padding: calc(var(--space) * 1) calc(var(--space) * 5);
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-rest);
}
.figure-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "label value" "note value";
  align-items: center;
  column-gap: calc(var(--space) * 4);
  padding: calc(var(--space) * 3) 0;
  border-bottom: 1px solid var(--hairline);
}
.figure-card:last-child { border-bottom: 0; }
@media (min-width: 760px) {
  .figures { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); padding: 0; }
  .figure-card {
    grid-template-columns: auto;
    grid-template-areas: "label" "value" "note";
    align-content: start;
    padding: calc(var(--space) * 5);
    border-bottom: 0;
  }
  .figure-card + .figure-card { border-left: 1px solid var(--hairline); }
}

/* Dentro de la tarjeta de su sección, las cifras ya están en una tarjeta. */
.panel > .figures { margin: 0; padding: 0; border: 0; border-radius: 0; box-shadow: none; }
.panel > .figures + .totals { margin-top: calc(var(--space) * 3); padding-top: calc(var(--space) * 3); border-top: 1px solid var(--hairline); }
@media (min-width: 760px) {
  .panel > .figures .figure-card:first-child { padding-left: 0; }
}
.wide-card { margin-bottom: calc(var(--space) * 3); }
.figure-label { grid-area: label; margin: 0; font-size: 14px; color: var(--ink-soft); }
.figure-value { grid-area: value; margin: 0; font-size: 24px; font-weight: 700; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.figure-value.quiet { font-size: 17px; font-weight: 550; color: var(--ink-soft); letter-spacing: 0; }
.figure-note { grid-area: note; margin: calc(var(--space) * 1) 0 0; font-size: 13px; color: var(--ink-soft); }
@media (min-width: 760px) {
  .figure-value { margin-top: calc(var(--space) * 1); font-size: 30px; }
}

/* La salida al pie de una pantalla: separada del contenido para que no se
   pulse al terminar de leer. */
.back-link { margin-top: calc(var(--space) * 8); }

/* El aviso del plan. Discreto y al final: no compite con el trabajo del día.
   Ver docs/SPEC.md 15. */
.plan-note { margin-top: calc(var(--space) * 7); color: var(--ink-soft); font-size: 14px; }

/* El registro del panel: una línea por entrada, leída de corrido y no como una
   tabla de la base de datos. Ver docs/SPEC.md 18. */
/* Una entrada del registro: lo que pasó, y debajo cuándo, quién y de qué
   coche en una línea gris. La frase manda porque es lo que se busca; la hora
   es lo que se comprueba después. */
.rows.log li { display: flex; flex-direction: column; align-items: stretch; gap: calc(var(--space) * 1); padding-block: calc(var(--space) * 3); }
.log-what { font-weight: 550; }
.log-meta { font-size: 14px; gap: calc(var(--space) * 1) calc(var(--space) * 3); }
.log-meta .plate { font-size: 12px; }

/* ── El asistente de configuración ────────────────────────────────────────
   Cuatro preguntas, una por pantalla. Se dice en cuál se está antes del
   título, porque lo primero que quiere saber quien contesta un cuestionario es
   cuánto le queda. Ver docs/SPEC.md 16. */
.step-count {
  margin: 0 0 calc(var(--space) * 2);
  color: var(--ink-soft);
  font-size: 14px;
  font-weight: 650;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* La lista de lo que va a preguntar, en la portada. Lo ya contestado lleva una
   marca; lo demás no lleva nada, porque no está mal, solo no está. */
.rows.steps { counter-reset: step; }
.rows.steps > li {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "mark what" "mark hint";
  gap: 0 calc(var(--space) * 3);
  padding-block: calc(var(--space) * 3);
}
.rows.steps > li::before {
  counter-increment: step;
  content: counter(step);
  grid-area: mark;
  align-self: center;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--rule);
  border-radius: 50%;
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 650;
}
.rows.steps > li.done::before {
  content: "✓";
  border-color: var(--plate);
  background: var(--plate);
  color: #fff;
}
.step-what { grid-area: what; font-weight: 550; }
.step-hint { grid-area: hint; color: var(--ink-soft); font-size: 14px; line-height: 1.4; }

/* ── La bandeja ───────────────────────────────────────────────────────────
   Quién ha escrito al taller y todavía espera algo. No es una lista de
   mensajes: es una pila de decisiones que se va vaciando, y por eso cada uno
   es una tarjeta y no una fila. Una fila se lee; una tarjeta se empuja.

   El gesto no hace nada que los botones escritos dentro no hagan: al soltar
   pulsa el mismo botón. Ver swipe_controller.js y docs/DESIGN.md. */
.inbox {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: calc(var(--space) * 3);
  margin: 0 0 calc(var(--space) * 6);
  padding: 0;
}

.inbox-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-card);
  background: var(--card);
  box-shadow: var(--lift-rest);
}
/* Con su hoja abierta —qué día vuelve, o por qué se borra— la tarjeta deja de
   recortar lo que sale de ella, como la de un aviso. Las esquinas las pone
   entonces la cara. */
.inbox-card:has(.postpone[open]) { overflow: visible; z-index: 41; }
.inbox-card .card-face { border-radius: inherit; }

/* Lo que asoma por debajo mientras se empuja: qué va a pasar al soltar. Está
   siempre debajo y no se ve nunca hasta que hay un dedo encima. */
.card-rails {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--paper);
}
.card-rail {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  padding: 0 calc(var(--space) * 5);
  font-size: 15px;
  font-weight: 600;
  opacity: 0;
}
.card-rail.on-left { color: var(--plate-deep); }
.card-rail.on-right { color: var(--ink-soft); }
:is(.inbox-card, .notice-card).swiping-right .card-rails { background: var(--plate-tint); }
:is(.inbox-card, .notice-card).swiping-right .on-left { opacity: 1; }
:is(.inbox-card, .notice-card).swiping-left .card-rails { background: var(--hairline); }
:is(.inbox-card, .notice-card).swiping-left .on-right { opacity: 1; }
/* Se ha empujado bastante: al soltar pasa. Se dice engordando la palabra, no
   pintando la tarjeta de rojo: --alarm es lo que se ha roto. */
:is(.inbox-card, .notice-card).reached .card-rail { font-size: 16px; font-weight: 700; }

.card-face {
  position: relative;
  padding: calc(var(--space) * 4);
  background: var(--card);
  /* El dedo que sube y baja hace scroll; el que va de lado es nuestro. */
  touch-action: pan-y;
  transition: transform 200ms ease;
}
/* Un enlace dentro de una tarjeta no se arrastra: el navegador se quedaba el
   gesto para su propio arrastrar-y-soltar —empezaba a llevarse la dirección—,
   cancelaba el puntero a mitad de camino y la tarjeta se quedaba clavada. */
.card-face a { -webkit-user-drag: none; }

/* Mientras va con el dedo no hay transición, o iría un paso por detrás. */
:is(.inbox-card, .notice-card).swiping .card-face { transition: none; }
/* Y cuando ya se ha decidido, se va del todo: volver a su sitio y desaparecer
   medio segundo después haría parecer que el gesto no ha servido. */
:is(.inbox-card, .notice-card).gone .card-face { transition: transform 160ms ease; }

/* Lo urgente no lleva color: lleva la posición —está arriba— y una raya de
   tinta en el filo. Ver docs/DESIGN.md. */
.inbox-card.urgent .card-face { box-shadow: inset 3px 0 0 var(--ink); }

.card-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start;
  gap: calc(var(--space) * 3);
  margin: 0 0 calc(var(--space) * 3);
}
.card-head .card-when { padding-top: calc(var(--space) * 0.5); }

/* Quién ha escrito: el nombre grande y, debajo, el número en pequeño y
   apagado. Un número de teléfono no dice quién es nadie. */
.sender { display: flex; flex-direction: column; min-width: 0; }
.sender-name { font-size: 17px; font-weight: 650; letter-spacing: -0.01em; line-height: 1.25; overflow-wrap: anywhere; }
.sender-handle { color: var(--ink-soft); font-size: 13px; font-weight: 400; line-height: 1.3; }
.card-when { flex: none; color: var(--ink-soft); font-size: 13px; }

/* Por dónde llegó, qué pide y si corre prisa: escrito, en la línea de datos
   de debajo de la frase. Eran pastillas con filo encima de la frase, y tres
   pastillas en cada tarjeta de la pila se leían antes que lo que se decía. */
.card-about { margin: calc(var(--space) * 2) 0 calc(var(--space) * 3); font-size: 14px; }
.card-urgent { color: var(--ink); font-weight: 650; }
/* Una marca suelta al lado de una opción: la propuesta del triaje. */
.tag {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0 calc(var(--space) * 2);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  font-size: 12px;
  font-weight: 550;
}

/* Lo que dijo. La frase entera lleva al mensaje completo: leerlo del todo
   cuesta un toque y no hay que ir a buscar dónde se abre. */
.card-said { display: block; margin-bottom: calc(var(--space) * 3); color: var(--ink); text-decoration: none; }
.card-said:hover { color: var(--plate); }
.card-filed { display: flex; align-items: center; gap: calc(var(--space) * 2); margin: 0 0 calc(var(--space) * 3); color: var(--ink-soft); font-size: 14px; }
/* La tarjeta se decide por su pie, como un aviso: una celda por acción, de
   lado a lado. Ver .notice-foot. */
.inbox-card .card-face { padding-bottom: 0; }
.inbox-card .card-said { margin-bottom: 0; font-size: 16px; line-height: 1.45; }

/* ── Los montones de la bandeja ───────────────────────────────────────────
   Los mismos pliegues que los avisos: lo que espera, lo apartado y lo
   guardado. Dentro de un pliegue la pila se separa de su línea como la de los
   avisos, y la última no deja hueco antes del pliegue siguiente. */
.bundle > .inbox { margin: calc(var(--space) * 3) 0 0; }
.bundle.bundle-waiting .bundle-name { color: var(--plate); }
.bundle.bundle-later .bundle-name, .bundle.bundle-saved .bundle-name { color: var(--ink-soft); }
.inbox-card .notice-until { margin: calc(var(--space) * 2) 0 0; }
.inbox-card .card-filed { margin: calc(var(--space) * 2) 0 0; }
.inbox-card .notice-foot { margin-top: calc(var(--space) * 3); }

/* Lo guardado se marca como un aviso visto: el círculo en la esquina, y el
   filo azul de lo elegido. La hora se aparta del círculo cuando está. */
.inbox-card.marked { box-shadow: 0 0 0 2px var(--plate); }
.inbox-card.marked .notice-pick::before {
  border-color: var(--plate);
  background: var(--plate);
  box-shadow: inset 0 0 0 4px var(--card);
}
.inbox-card.marked .card-said { color: var(--plate-deep); }
.inbox-saved .card-said { -webkit-touch-callout: none; }
.notice-piles.marking .inbox-saved .card-head { padding-right: calc(var(--space) * 9); }
.notice-piles.marking .inbox-saved .card-said:hover { color: inherit; }
@media (min-width: 760px), (hover: hover) and (pointer: fine) {
  .inbox-saved .card-head { padding-right: calc(var(--space) * 9); }
}

/* ── Lo que viene a la bandeja ───────────────────────────────────────────
   WhatsApp, el correo y los SMS todavía no entran. El panel lo dice con su
   marca de próximamente y enseña en tres líneas lo que hará: el dibujo en un
   círculo, como el de las tarjetas, el nombre y una línea. Al pie, a lo ancho,
   lo único que ya se hace aquí. */
.inbox-soon { display: flex; flex-direction: column; align-items: flex-start; }
.inbox-soon-mark {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin-bottom: calc(var(--space) * 4);
  border-radius: 50%;
  background: var(--plate-tint);
  color: var(--plate);
}
.inbox-soon-mark .icon { width: 28px; height: 28px; }
.inbox-soon h2 { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2); margin: 0 0 calc(var(--space) * 2); }
.inbox-soon > .hint { margin: 0 0 calc(var(--space) * 4); }
.inbox-soon-steps { align-self: stretch; margin: 0 0 calc(var(--space) * 5); padding: 0; list-style: none; }
.inbox-soon-steps li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "mark name" "mark hint";
  column-gap: calc(var(--space) * 3);
  padding-block: calc(var(--space) * 3);
  border-top: 1px solid var(--hairline);
}
.inbox-soon-step-mark {
  grid-area: mark;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink-soft);
}
.inbox-soon-step-name { grid-area: name; font-weight: 650; }
.inbox-soon-step-hint { grid-area: hint; color: var(--ink-soft); font-size: 14px; line-height: 1.4; }
.inbox-soon > .panel-save { align-self: stretch; }
/* Anotar una llamada abre su hoja aquí mismo, como desde el menú: el botón es
   el <summary> y ocupa el ancho igual que cuando era un enlace. */
summary.button-link { list-style: none; cursor: pointer; }
summary.button-link::-webkit-details-marker, summary.button-link::marker { display: none; content: ""; }
.notice-foot > a.notice-act { flex: 1 1 0; min-width: 0; text-decoration: none; }

/* El silencio de los avisos. Es una línea pequeña y no un interruptor grande:
   se usa poco, y lo que importa es que diga hasta cuándo. */
.hush { margin: 0 0 calc(var(--space) * 4); }
.hush > summary {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  color: var(--ink-soft);
  font-size: 14px;
  font-weight: 550;
  list-style: none;
  cursor: pointer;
}
.hush > summary::-webkit-details-marker { display: none; }
.hush-spans { display: flex; flex-wrap: wrap; gap: calc(var(--space) * 2); margin-bottom: calc(var(--space) * 2); }
/* El dibujo, lo que dice y cómo se deshace, en una línea: volver a encender es
   la respuesta a lo que se acaba de leer, y debajo en azul parecía otra cosa. */
.hushed {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: calc(var(--space) * 3);
  margin: 0 0 calc(var(--space) * 4);
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  color: var(--ink-soft);
  font-size: 14px;
}
.hushed .icon, .hush .icon { flex: none; }
.hushed form { margin: 0; }
.hushed > span { min-width: 0; }

/* Lo apartado, plegado: alguien decidió no mirarlo todavía, y enseñarlo
   abierto sería deshacer esa decisión. */
.later > summary {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  font-weight: 550;
  cursor: pointer;
}
.later[open] > summary { margin-bottom: calc(var(--space) * 2); }
/* Un pliegue se abre, y hay que verlo antes de pulsarlo: una fila plana no
   dice que tenga nada dentro. */
.later > summary::after {
  content: "";
  width: 9px;
  height: 14px;
  margin-left: auto;
  background: currentColor;
  color: var(--ink-faint);
  clip-path: polygon(14% 8%, 30% 0, 86% 50%, 30% 100%, 14% 92%, 58% 50%);
  transition: transform 150ms ease;
}
.later[open] > summary::after { transform: rotate(90deg); }
.later > summary::-webkit-details-marker { display: none; }

/* Lo que dijo, otra vez, mientras se elige el coche: nadie se acuerda de un
   mensaje que leyó hace dos pantallas. */
.said-again { margin-bottom: calc(var(--space) * 4); }
.said-again .excerpt { margin: calc(var(--space) * 2) 0 0; }

/* Un coche entre los que se elige para guardar un mensaje: la fila entera es
   el botón, porque tocarla guarda, y se ve como cualquier otra fila con su
   galón. El formulario que dibuja `button_to` ocupa la fila de lado a lado. */
.rows li.place > form.button_to { flex: 1; min-width: 0; margin: 0; }
.rows li.place button.place-pick {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "name arrow" "hint arrow";
  gap: 2px calc(var(--space) * 3);
  width: 100%;
  min-height: 44px;
  padding: calc(var(--space) * 2) 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-weight: 400;
  text-align: left;
  box-shadow: none;
}
.rows li.place button.place-pick:active { transform: none; }
.rows li.place button.place-pick::after {
  content: "";
  grid-area: arrow;
  align-self: center;
  width: 9px;
  height: 14px;
  background: currentColor;
  color: var(--ink-faint);
  clip-path: polygon(14% 8%, 30% 0, 86% 50%, 30% 100%, 14% 92%, 58% 50%);
}
@media (hover: hover) {
  .rows li.place:has(.place-pick):hover { background: color-mix(in srgb, var(--ink) 5%, var(--paper)); border-radius: var(--r-row) var(--r-row) 0 0; }
  .rows li.place button.place-pick:hover::after { color: var(--plate); }
}
/* Lo que cierra cada lista —apuntar el coche, o al cliente— va a lo ancho
   debajo de ella, separado por el aire de una fila. */
.likely .rows + .newcomer, .all .hint + .newcomer { margin-top: calc(var(--space) * 4); }

/* El coche lo marcó una persona desde la bandeja, y lo desmarca una persona:
   el tablero no se lo quita solo. */
.attending {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: calc(var(--space) * 3);
  margin: 0 0 calc(var(--space) * 4);
  padding: calc(var(--space) * 3) calc(var(--space) * 4);
  border: 1px solid var(--plate);
  border-radius: var(--r-panel);
  background: var(--plate-tint);
  color: var(--plate-deep);
  font-weight: 550;
}
.attending > span { min-width: 0; }
.attending form { margin: 0; }

/* Solo se mueve lo que responde a una acción, y ni eso para quien ha pedido
   que nada se mueva. Ver docs/DESIGN.md. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
  input[type="submit"]:active, button:active { transform: none; }
}

/* ── El horario: el mes ───────────────────────────────────────────────────
   La rejilla del mes se dibuja también en el móvil, al revés que la del
   planificador. Allí cada casilla lleva algo que leer y en 375 px no cabe;
   aquí lo único que hay dentro es dónde tocar y un dibujo de tres barras, y
   siete columnas de cuarenta y siete píxeles entran de sobra.
   Ver docs/DESIGN.md. */

/* La fila de arriba: el mes a la izquierda -y es el botón que abre los doce-,
   y a la derecha el que devuelve a hoy y el que dibuja una banda. */
.calendar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--space) * 2);
  margin-bottom: calc(var(--space) * 3);
}
/* El mes cede el sitio y los botones no: son cuatro cuadrados de cuarenta y
   cuatro píxeles y no hay nada que recortarles, mientras que un nombre de mes
   largo cabe recortado. Sin esto, la fila se salía por la derecha en cuanto la
   pantalla era estrecha y el puntero fino -las dos flechas puestas-. */
.calendar-name {
  overflow: hidden;
  min-width: 0;
  margin: 0;
  font-size: 20px;
  font-weight: 650;
  letter-spacing: -0.01em;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.monthpick { position: relative; min-width: 0; }
.monthpick-open {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 1);
  min-width: 0;
  min-height: 44px;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}
.monthpick-open::-webkit-details-marker, .monthpick-open::marker { display: none; content: ""; }
.monthpick-open .icon { flex: none; color: var(--ink-soft); transition: transform 150ms ease; }
.monthpick[open] .monthpick-open .icon { transform: rotate(180deg); }
.monthpick-panel {
  position: absolute;
  left: 0;
  top: calc(100% + var(--space) * 2);
  z-index: 20;
  width: max-content;
  /* Lo ancho que tiene que ser para que los doce meses quepan en tres columnas
     con su nombre entero: "Septembre" y "Diciembre" en trescientos píxeles
     salían partidos por la mitad o pegados al borde de su casilla. */
  min-width: 380px;
  max-width: min(420px, calc(100vw - var(--space) * 10));
  padding: calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}

/* Los doce meses del año, en tres por cuatro. Se pasa de año con el pulgar y,
   para quien no desliza, con las dos flechas de la cabecera. */
.yearpick-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: calc(var(--space) * 3);
}
.yearpick-name { font-size: 17px; font-weight: 650; }
.yearpick-way, .yearpick-way:visited {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-pill);
  color: var(--ink-soft);
}
.yearpick-way:hover { color: var(--ink); }
.yearpick-ahead .icon { transform: rotate(180deg); }
.yearpick-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: calc(var(--space) * 2); }
.yearpick-month, .yearpick-month:visited {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 calc(var(--space) * 1);
  border-radius: var(--r-row);
  color: var(--ink);
  font-size: 14px;
  font-weight: 550;
  text-align: center;
  text-decoration: none;
}
.yearpick-month:hover { background: var(--wash); }
.yearpick-month.now { box-shadow: inset 0 0 0 2px var(--plate); }
.yearpick-month.here { background: var(--plate); color: #fff; font-weight: 650; }

/* Llevarme a hoy, y dibujar sobre el día señalado.

   Todo lo que se pulsa en el calendario dice su color también para cuando ya
   se ha visitado: un año donde octubre está azul y noviembre no cuenta por
   dónde ha andado quien lo mira, y eso no es una diferencia entre dos meses.
   El color de los enlaces visitados pesa más que una clase suelta. */
.calendar-does { display: flex; flex: none; align-items: center; gap: calc(var(--space) * 1); }
.calendar-today, .calendar-today:visited, .calendar-add, .calendar-add:visited {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-row);
  color: var(--ink);
  text-decoration: none;
}
.calendar-today:hover, .calendar-add:hover { background: var(--wash); }
/* El botón de hoy lleva escrito el día de hoy: así dice algo aunque ya se esté
   en el mes, y es lo que se busca al pulsarlo. */
.calendar-today-number {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 1.7px solid currentcolor;
  border-radius: 7px;
  font-size: 13px;
  font-weight: 650;
  line-height: 1;
}

/* El calendario se pasa de mes con el pulgar. El navegador se queda con el
   desplazamiento vertical -que es lo que se le pide subiendo y bajando- y nos
   deja el horizontal, que aquí es cambiar de mes. */
.pager { touch-action: pan-y; }

/* Los dos meses. Donde hay pulgar, el camino es el gesto y las flechas no se
   dibujan: son dos sitios más donde el dedo se equivoca al lado de una casilla
   de cuarenta y siete píxeles. Donde hay puntero no hay gesto que valga, así
   que se dibujan.

   Y escondidas siguen siendo enlaces a los que llega el tabulador: basta con
   que uno reciba el foco para que los dos vuelvan a la pantalla, porque un
   enlace que se pulsa a ciegas no es un enlace. */
.pager-ways { display: flex; }
/* Donde hay pulgar el camino es el gesto, y donde la pantalla es estrecha no
   caben: la fila de arriba son cuatro cuadrados de cuarenta y cuatro píxeles al
   lado del nombre del mes, y en 412 px se salía por la derecha. En las dos, el
   selector de meses sigue llevando a cualquier mes. */
@media not all and (min-width: 600px) and (hover: hover) and (pointer: fine) {
  .pager-ways:not(:focus-within) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
}
.calendar-way, .calendar-way:visited {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-row);
  color: var(--ink-soft);
}
.calendar-way:hover { background: var(--wash); color: var(--ink); }
.calendar-way-ahead .icon { transform: rotate(180deg); }
.pager-said { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* ── Pasar de mes y de año: el papel se mueve ─────────────────────────────
   El mes de al lado está de verdad al lado. El marco recorta, y dentro de él
   van dos rejillas: la que se está mirando y la que viene, pegada al borde y
   fuera de lo que se ve. El dedo corre las dos a la vez.

   Esto se hacía con una transición de vistas y no podía ir bien: el navegador
   congelaba la pantalla mientras el servidor contestaba, y lo que se veía era
   un tirón y luego un parpadeo. Ver pager_controller.js. */
/* El marco recorta un poco más allá de su borde: el anillo de foco de una
   casilla del calendario se sale cuatro píxeles por los lados, y recortado al
   ras se quedaba a medias en la primera columna y en la última. Lo que asoma
   del papel de al lado mientras se pasa son esos cuatro píxeles, que son la
   columna de las semanas y están vacíos. */
.paper { position: relative; overflow: clip; overflow-clip-margin: 4px; }
/* El papel de un día recorta a los lados y no por arriba y por abajo: el
   formulario de una cita cuelga de ella y se sale de la rejilla, y recortado
   quedaba medio dentro. */
.daypaper { overflow-x: clip; overflow-y: visible; }
.paper > * { transform: translateX(0); }
.paper-twin { position: absolute; top: 0; left: 0; width: 100%; }

/* Solo al soltar el dedo el papel recorre por su cuenta lo que le queda.
   Mientras se arrastra va pegado al dedo, sin suavizar nada: un papel que
   llega tarde a donde está el dedo se lee como un papel que va mal. */
.pager.turning .paper > * { transition: transform 240ms ease; }
@media (prefers-reduced-motion: reduce) {
  .pager.turning .paper > * { transition: none; }
}

.calendar { width: 100%; border-collapse: separate; border-spacing: 2px; table-layout: fixed; }
/* La semana del año, a la izquierda de su fila. Es la única cifra del
   calendario que no es un día, así que se escribe más pequeña y más apagada:
   se busca cuando se busca, y el resto del tiempo no estorba. */
.calendar-weeks {
  width: 26px;
  padding: 0;
  font-size: 11px;
  font-weight: 550;
  color: var(--ink-faint);
  text-align: center;
}
.calendar th {
  padding: calc(var(--space) * 1) 0;
  font-size: 12px;
  font-weight: 550;
  color: var(--ink-soft);
  text-align: center;
}
.calendar th abbr { text-decoration: none; }
.calendar td { padding: 0; }
.calendar td a {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--space) * 1);
  min-height: 52px;
  padding: calc(var(--space) * 1.5) calc(var(--space) * 1);
  border: 1px solid var(--hairline);
  border-radius: var(--r-row);
  background: var(--card);
  color: var(--ink);
  text-decoration: none;
  /* Mantener pulsado un día es marcarlo, y con Mayúsculas se coge un tramo: el
     navegador contestaba a lo mismo con su menú de enlace y con una selección
     de texto azul por encima del calendario. Dentro de la casilla no hay nada
     que copiar, solo una cifra de dos dígitos. Ver picking_controller.js. */
  user-select: none;
  -webkit-touch-callout: none;
}
@media (hover: hover) {
  .calendar td a:hover { border-color: var(--plate); }
}
/* El cerco del foco se sale de la casilla y las casillas se pintan en el orden
   en que están escritas: el de un martes quedaba medio tapado por el miércoles
   y por el martes de la semana siguiente. Se levanta un piso para que se vea
   entero, que un cerco a medias no se lee como el sitio donde está el teclado. */
.calendar td a:focus-visible {
  z-index: 1;
  outline: 2px solid var(--plate);
  outline-offset: 2px;
}
.calendar .outside a { background: transparent; border-color: transparent; color: var(--ink-faint); }
.calendar .today a { box-shadow: inset 0 0 0 2px var(--plate); }

/* Un día bloqueado entero va tachado, con la misma raya diagonal con la que se
   tacha una franja en la rejilla del día: es lo mismo dicho en pequeño. Sin
   ella, un día que ya no ofrece nada se leía igual que uno lleno de horas
   libres, porque la casilla es la misma y el punto es uno más. */
.calendar td a.closed {
  background-image: repeating-linear-gradient(135deg, var(--rule) 0 3px, transparent 3px 7px);
  border-color: var(--rule);
  color: var(--ink-soft);
}
/* Sobre el azul del día que se está mirando la raya va en blanco, como la de
   una franja bloqueada en la rejilla del día: en gris no se veía. */
.calendar .picked a.closed {
  background-image: repeating-linear-gradient(135deg, rgb(255 255 255 / 30%) 0 3px, transparent 3px 7px);
}
/* El día que se está mirando abajo va lleno, no perfilado: perfilado ya está
   hoy, y dos perfiles no se distinguen de un vistazo. */
.calendar .picked a { background: var(--plate); border-color: var(--plate); color: #fff; }
/* Los días marcados con el dedo para tratarlos de una vez. Se ven marcados y no
   señalados: el señalado es uno y dice qué se está mirando abajo, y estos son
   varios y dicen qué se va a cambiar. Por eso van perfilados y en el papel de
   la aplicacion, no llenos como el señalado. */
.calendar td a.marked {
  background: var(--wash);
  border-color: var(--ink);
  box-shadow: inset 0 0 0 2px var(--ink);
}
.calendar .picked a.marked { background: var(--plate); box-shadow: inset 0 0 0 2px var(--ink); }

/* Mientras se marca, el dedo marca: no desplaza la pantalla ni pasa de mes, y
   el navegador no ofrece copiar el número del día. */
.monthdays.picking .calendar { touch-action: none; user-select: none; }

/* Lo que se hace con los días marcados. En un ordenador flota encima del
   muelle, que es donde está el puntero cuando se acaba de marcar el último;
   pegada al final del calendario quedaba debajo de la barra de abajo y no se
   veía. En un móvil sube desde el borde como los demás paneles y se va tirando
   de ella hacia abajo, que es el gesto que ya se conoce de todos ellos.

   No apaga el calendario, al revés que las otras hojas: está abierta
   justamente mientras se siguen marcando días. Ver sheet_controller.js. */

/* En un ordenador va en azul de matrícula y no en papel blanco. Con el mismo
   blanco, el mismo ancho y el mismo filo que el muelle, y apoyada justo encima
   de él, las dos se leían como una sola pieza de dos pisos. Y no son la misma
   clase de cosa: el muelle es el mobiliario -está siempre, es de vidrio y deja
   verse lo que pasa por debajo- y esta es la consecuencia de lo que se acaba
   de hacer, que se va en cuanto se suelta. El azul no es un color nuevo: es
   con el que esta aplicación dice "esto está elegido", el mismo que llevan los
   días marcados debajo. Ver docs/DESIGN.md. */
@media (min-width: 760px) {
  .monthdays .picked-bar {
    position: fixed;
    right: calc(var(--space) * 5);
    /* Con aire de por medio: el muelle mide catorce y su hueco de abajo, y
       apoyada en su borde no había nada que dijera que son dos piezas. */
    bottom: calc(var(--space) * 19 + max(var(--space) * 6, var(--band-bottom)));
    left: calc(var(--space) * 5);
    z-index: 30;
    /* Mide lo que dice. Estirada a la columna entera dejaba un palmo de vacío
       entre la cifra y los botones, que es el hueco de un dato que falta. */
    justify-content: center;
    width: max-content;
    max-width: min(640px, calc(100% - var(--space) * 10));
    margin: 0 auto;
    padding: calc(var(--space) * 2) calc(var(--space) * 2)
             calc(var(--space) * 2) calc(var(--space) * 5);
    border-color: var(--plate-deep);
    border-radius: var(--r-pill);
    background: var(--plate);
    color: #fff;
  }
  .monthdays .picked-does { margin-left: calc(var(--space) * 2); }

  /* Dentro del azul, los botones se dan la vuelta: el que hace la cosa va en
     blanco lleno y el otro en filo blanco. Un botón azul sobre azul no es un
     botón, es un texto. */
  .monthdays .picked-bar input[type="submit"], .monthdays .picked-bar button {
    border-color: #fff;
    background: #fff;
    color: var(--plate-deep);
    box-shadow: none;
  }
  .monthdays .picked-bar input[type="submit"]:hover,
  .monthdays .picked-bar button:hover {
    border-color: var(--plate-tint);
    background: var(--plate-tint);
  }
  /* El filo del tipo cuenta tanto como una clase, así que la regla de arriba
     le ganaba a `.quiet` y los dos primeros botones salían iguales: el que
     bloquea se leía como un segundo botón principal. */
  .monthdays .picked-bar input[type="submit"].quiet,
  .monthdays .picked-bar button.quiet {
    border-color: color-mix(in srgb, #fff 55%, transparent);
    background: transparent;
    color: #fff;
  }
  .monthdays .picked-bar input[type="submit"].quiet:hover,
  .monthdays .picked-bar button.quiet:hover {
    border-color: #fff;
    background: color-mix(in srgb, #fff 14%, transparent);
    color: #fff;
  }
  .monthdays .picked-bar :focus-visible { outline-color: #fff; }
}

@media (max-width: 759px) {
  .monthdays .picked-bar {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 40;
    max-width: none;
    margin-top: 0;
    /* Debajo del último botón va el hueco que se le deja al muelle: la barra
       del sistema -la raya del gesto, o los tres botones de Android- se dibuja
       ahí mismo, y con dieciséis píxeles el pulgar que iba a bloquear unos días
       salía de la aplicación. Donde el sistema dice cuánto se aparta -la
       aplicación guardada en el inicio-, se le suma a lo nuestro. */
    padding-bottom: max(calc(var(--space) * 8), calc(var(--band-bottom) + var(--space) * 4));
    animation: sheet-rise 200ms ease both;
  }
  /* La cifra de lo marcado se lee debajo del agarradero, y las dos cosas que se
     hacen con los días van una encima de otra y de lado a lado, como las filas
     del menú: dos píldoras repartiéndose el ancho se acaban leyendo como una
     sola cosa partida, y con el pulgar sucio lo que se acierta es una franja
     entera y no media. Cerrar no lleva fila propia: de la hoja se tira hacia
     abajo, y fuera de la rejilla se toca. */
  .monthdays .picked-bar .sheet-head { width: 100%; margin-bottom: 0; }
  .monthdays .picked-does {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    margin-left: 0;
    gap: calc(var(--space) * 2);
  }
  .monthdays .picked-does input[type="submit"] {
    width: 100%;
    min-height: 52px;
    border-radius: var(--r-row);
    font-size: 16px;
  }
}
.calendar-number { font-size: 14px; font-weight: 600; line-height: 1; }

/* Lo que ofrece el día, en puntos del color de su tipo. Es un dibujo y no una
   cifra: lo que se pregunta mirando un mes es si el día está puesto, no cuántos
   tramos tiene. Cuatro puntos es todo lo que cabe en una casilla de un móvil,
   y a partir de ahí la respuesta ya es la misma: ese día está lleno. */
.calendar-dots { display: flex; flex-wrap: wrap; justify-content: center; gap: 3px; max-width: 100%; }
.calendar-dot { display: block; width: 5px; height: 5px; border-radius: var(--r-pill); background: var(--kind, var(--ink-soft)); }
.calendar-dot:nth-child(n + 5) { display: none; }
/* Sobre el azul del día que se está mirando, los puntos van en blanco: el color
   del tipo sobre azul no se ve, y un día señalado sigue teniendo que decir que
   trae algo. Es lo mismo que hace la raya de un día bloqueado, y lo que trae de
   qué clase es está escrito justo debajo. */
.calendar .picked .calendar-dot { background: rgb(255 255 255 / 85%); }

/* Los tipos de cita se pintan con la paleta de las etapas: es la misma
   aplicación y no hacen falta cinco colores nuevos para decir cinco cosas.
   Cualquiera es el azul de matrícula porque es la banda que lo acepta todo, y
   lo bloqueado es gris porque no es un trabajo, es su ausencia. */
.kind-general { --kind: var(--plate); }
.kind-inspection { --kind: var(--stage-diagnostic); }
.kind-repair { --kind: var(--stage-quote); }
.kind-priority { --kind: var(--stage-part); }
.kind-urgent { --kind: var(--stage-repair); }
.kind-closed { --kind: var(--ink-soft); }

/* ── El horario: el día que se está mirando ───────────────────────────────
   Debajo del mes, cómo va a ir el día señalado. Es una mirada y no un sitio
   donde tocar: para cambiar algo está el botón que lleva al día de verdad. */
.picked { margin-top: calc(var(--space) * 5); }
.picked-head {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 1);
  margin-bottom: calc(var(--space) * 3);
}
.picked-name { margin: 0; min-width: 0; font-size: 20px; font-weight: 650; letter-spacing: -0.01em; }
/* Debajo del mes las flechas se aprietan contra el nombre y el botón de editar
   se va al otro extremo: el nombre y sus dos días son una sola pieza. */
.picked-head .picked-name { flex: 0 1 auto; }
.picked-edit {
  display: inline-flex;
  flex: none;
  margin-left: auto;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  padding: 0 calc(var(--space) * 3);
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 550;
  text-decoration: none;
}
.picked-edit:hover { background: var(--wash); color: var(--ink); }

/* La misma rejilla del día, a un tercio: las mismas sesenta filas de cuarto de
   hora, de cinco píxeles en vez de dieciséis. No cabe nada escrito dentro y no
   se escribe nada: lo que se pregunta aquí es cómo va el día, no a qué hora. */
.daysketch { display: grid; grid-template-columns: 34px 1fr; gap: calc(var(--space) * 1); }
.daysketch-rule { display: grid; font-size: 11px; font-weight: 550; color: var(--ink-faint); }
.daysketch-rule span { transform: translateY(-5px); }
.daysketch-canvas {
  display: grid;
  grid-template-columns: 1fr;
  border: 1px solid var(--hairline);
  border-radius: var(--r-row);
  background: repeating-linear-gradient(var(--hairline) 0 1px, transparent 1px 60px);
}
.daysketch-stretch {
  grid-column: 1;
  display: block;
  margin: 0 2px;
  border-radius: 3px;
  background-color: var(--kind, var(--ink-soft));
}
@media (hover: hover) {
  .daysketch-stretch:hover { filter: brightness(1.12); }
}
/* Lo que se ofrece y nadie ha cogido, en el dibujo pequeño de la agenda: se ve
   la forma del día sin que compita con el trabajo. */
.daysketch-stretch.kind-free { background-color: var(--hairline); }
.daysketch-stretch.kind-closed {
  background-image: repeating-linear-gradient(135deg, rgb(255 255 255 / 18%) 0 4px, transparent 4px 8px);
}

/* ── El horario: la jornada ───────────────────────────────────────────────
   Quince horas de alto, una hora cada sesenta y cuatro píxeles. Una banda de
   media hora mide treinta y dos, que es donde todavía cabe una línea de texto;
   por debajo de eso la hora escrita deja de leerse y el dibujo se queda solo. */
/* La cabecera del día, en una sola línea: la vuelta al mes, qué día es y qué se
   hace con él. El día va abreviado y en el cuerpo de un título de sección y no
   en el de una pantalla: escrito entero y a veinticuatro píxeles ocupaba dos
   renglones en un móvil y empujaba la rejilla fuera de la pantalla. */
/* En un móvil la línea no da para todo -la vuelta al mes, los dos días de al
   lado, el nombre y lo que se hace con el día entero- y entonces se parte en
   dos: arriba de qué día se trata, debajo qué se hace con él. No se aprieta ni
   se recorta el nombre: un día que se lee a medias no se lee. */
.dayhead {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--space) * 2);
  margin-bottom: calc(var(--space) * 4);
}
/* El nombre del día no se parte en dos renglones: si la línea no da para todo,
   lo que baja es lo que se hace con el día, no de qué día se trata. */
.dayhead-name {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: 17px;
  font-weight: 650;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* Vaciar el día, al lado de repartirlo: son las dos cosas que se hacen con el
   día entero, y se dibujan iguales para que se lean como una pareja. */
.dayhead-clears { flex: none; margin: 0; }
.dayhead-clear {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  padding: 0 calc(var(--space) * 3);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  background: transparent;
  box-shadow: none;
  color: var(--ink-soft);
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
}
.dayhead-clear:hover { border-color: var(--ink-soft); background: var(--wash); color: var(--ink); }

/* El horario del mismo día, dentro de la agenda. Solo el reloj: con el rótulo
   escrito, la línea no daba para el nombre del día, el horario y llevarse el
   día a otro, y lo de llevárselo bajaba a un segundo renglón. Un reloj dentro de
   un calendario no necesita que le pongan "horario" al lado.
   Ver workshop/planning/days/show. */
.dayhead-hours {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  text-decoration: none;
}
.dayhead-hours:hover { border-color: var(--ink-soft); background: var(--wash); color: var(--ink); }
.dayhead-back {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: calc(var(--space) * -2);
  border-radius: var(--r-pill);
  color: var(--ink-soft);
}
.dayhead-back:hover { background: var(--wash); color: var(--ink); }

/* Anotar una cita sin arrastrar. Arrastrar sobre un rato libre es lo rápido,
   pero pide el día a la vista y una mano suelta; con el teléfono en la oreja se
   pulsa el más. Va lleno de color y los demás de la línea van huecos: de todo
   lo que se hace aquí, esto es lo único que se viene a hacer. */
.dayhead-add, .dayhead-add:visited {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: #fff;
  text-decoration: none;
}
.dayhead-add:hover { background: var(--plate-deep); }
/* Y llevarse el día se queda en la flecha, como el horario se queda en el
   reloj: con "Déplacer" escrito, la línea no daba para los cuatro botones en
   375 px y se partía en dos renglones. Ver workshop/planning/days/moving. */
.dayhead-move .repeat-open { justify-content: center; width: 44px; padding: 0; }
.dayhead-add:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

/* Repartir este día a los demás. Es lo que evita dibujar treinta días iguales,
   pero no es lo que se viene a hacer todos los días: por eso es un botón que
   abre, y no dos formularios escritos debajo de la rejilla. */
.repeat { position: relative; }
.repeat { flex: none; }
.repeat-open {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  /* Apretado a los lados: en la cabecera de un día de 375 px comparte línea con
     el nombre del día y el reloj del horario, y doce píxeles a cada lado la
     bajaban a un segundo renglón. */
  padding: 0 calc(var(--space) * 2);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
  list-style: none;
}
.repeat-open::-webkit-details-marker, .repeat-open::marker { display: none; content: ""; }

/* Las dos maneras de decir dónde más, una debajo de otra y separadas por una
   raya: los días de la semana y unas fechas sueltas. Van en el mismo
   formulario, porque se marca y se copia de una vez. */
.spread { margin: 0; }
.spread-name { margin: 0 0 calc(var(--space) * 1); font-size: 15px; font-weight: 650; }
.spread .hint { margin: 0 0 calc(var(--space) * 3); }
.spread-dates { margin-top: calc(var(--space) * 5); padding-top: calc(var(--space) * 5); border-top: 1px solid var(--rule); }
.spread input[type="submit"] { width: 100%; }

/* La semana entera en una fila de siete pastillas, y el mes en su rejilla. Se
   marcan las que se quieran y se copia al final con el botón: copiar pisa el
   horario de esos días y no se deshace tocando otra vez, así que no se hace
   nada mientras el dedo pasa por encima.

   Cada pastilla es una casilla de verdad con su etiqueta encima: sin
   JavaScript se marca igual, y el teclado la alcanza como a cualquier otra. */
.weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: calc(var(--space) * 1); }
.weekday-pick, .date-pick {
  position: relative;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  border: 1px solid var(--rule);
  border-radius: var(--r-row);
  color: var(--ink-soft);
  font-size: 12px;
  font-weight: 550;
  cursor: pointer;
}
.weekday-pick:hover, .date-pick:hover { border-color: var(--ink-soft); background: var(--wash); color: var(--ink); }
.weekday-pick input, .date-pick input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.weekday-pick:has(input:checked), .date-pick:has(input:checked),
.weekday-pick:has(input:checked):hover, .date-pick:has(input:checked):hover {
  background: var(--plate);
  border-color: var(--plate);
  color: #fff;
}
.weekday-pick:has(input:focus-visible), .date-pick:has(input:focus-visible) { outline: 2px solid var(--plate); outline-offset: 2px; }
.repeat-open:hover { border-color: var(--ink-soft); color: var(--ink); }
.repeat-panel {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space) * 2);
  z-index: 20;
  width: max-content;
  min-width: 340px;
  max-width: min(400px, calc(100vw - var(--space) * 10));
  padding: calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}

.daygrid {
  display: grid;
  grid-template-columns: 46px 1fr;
  gap: calc(var(--space) * 1);
  margin-bottom: calc(var(--space) * 3);
}

.daygrid-rule { display: grid; }
.daygrid-hour {
  font-size: 12px;
  font-weight: 550;
  color: var(--ink-soft);
  /* La hora se escribe donde empieza, no en medio de su franja: es la línea
     que se está mirando al buscar las ocho. */
  transform: translateY(-6px);
}

.daygrid-canvas {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background:
    repeating-linear-gradient(var(--hairline) 0 1px, transparent 1px 64px);
  /* El gesto vertical lo reparte el controlador: la página se desplaza mientras
     no se esté dibujando, y en cuanto se dibuja deja de desplazarse.
     Ver schedule_controller.js. */
  touch-action: pan-y;
}
.daysheet.drawing .daygrid-canvas { touch-action: none; user-select: none; }

/* Una franja del horario. Va en su columna y en sus filas, y las filas las
   dicen las clases `rs-` y `re-` de abajo: aquí no hay estilos en línea.

   No se llama `.band`: eso ya es el carrusel de Aujourd'hui, y dos cosas
   distintas con el mismo nombre acaban pintándose la una a la otra. */
.stretch {
  position: relative;
  grid-column: 1;
  min-width: 0;
  margin: 1px 2px;
}
/* El <details> llena la franja: la cara es lo que se ve en la rejilla y el
   formulario cuelga de ella. Los tiradores van fuera, hermanos suyos, porque
   el navegador esconde lo que hay dentro de un <details> cerrado y ellos tienen
   que poder salir sin que el formulario se abra. */
.stretch-body { height: 100%; }

/* La cara de la franja: lo que se ve en la rejilla y lo que se toca para
   abrirla. El color lo pone su tipo. */
.stretch-face {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  overflow: hidden;
  height: 100%;
  padding: calc(var(--space) * 1) calc(var(--space) * 2);
  border-radius: 6px;
  background-color: var(--kind, var(--ink-soft));
  color: #fff;
  font-size: 12px;
  line-height: 1.2;
  cursor: pointer;
  list-style: none;
  /* El rótulo no se selecciona. Mantener pulsada una franja es cogerla, y el
     navegador del teléfono contestaba a ese mismo gesto marcando el texto de
     dentro: la hora se encendía y se apagaba mientras la franja se movía.
     Ver schedule_controller.js. */
  user-select: none;
  -webkit-touch-callout: none;
}
.stretch-face::-webkit-details-marker, .stretch-face::marker { display: none; content: ""; }
@media (hover: hover) {
  .stretch-face:hover { filter: brightness(1.12); }
}
/* La cita en su hueco. Va en una línea y no en tres: media hora mide treinta y
   dos píxeles, que es donde cabe un renglón, y quien mira una mañana busca a
   quién tiene a las ocho, no de qué tipo es. Lo demás cae debajo cuando la cita
   es lo bastante larga para que quepa. Ver workshop/planning/days/show. */
.stretch-booked {
  flex-flow: row wrap;
  align-items: baseline;
  justify-content: flex-start;
  column-gap: calc(var(--space) * 2);
}
.stretch-booked .stretch-what { flex: 1 1 auto; min-width: 0; font-weight: 650; }
.stretch-booked .stretch-each { flex: none; }

.stretch-when { font-weight: 650; font-variant-numeric: tabular-nums; }
.stretch-what { font-weight: 550; opacity: 0.92; }
.stretch-each { opacity: 0.8; }
.stretch-face:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

/* Los dos tiradores, uno en cada borde. Salen al mantener pulsada la franja y
   no al tocarla: tocarla abre su formulario, que en un móvil sube desde abajo y
   taparía justo lo que hay que ver para tirar. Sobresalen de la franja para que
   quepa el dedo aunque la franja sea de un cuarto de hora. */
.stretch-grip {
  display: none;
  position: absolute;
  left: 50%;
  z-index: 3;
  width: 44px;
  /* Cuarenta y cuatro píxeles, que es lo que mide un dedo, y partidos por el
     borde: la mitad dentro de la franja y la mitad fuera. Medían veintidós y
     los botones de la aplicación nunca bajan de cuarenta y cuatro, así que el
     navegador los estiraba hacia dentro y la rayita quedaba a media altura de
     donde se tira. */
  height: 44px;
  min-height: 0;
  margin-left: -22px;
  padding: 0;
  border: 0;
  background: transparent;
  /* Sin la sombra de los botones: en una cita corta el tirador de en medio
     sobresalía por debajo y su sombra dibujaba un recuadro blanco. */
  box-shadow: none;
  cursor: ns-resize;
  touch-action: none;
}
/* Un tirador no es un botón de guardar: el azul de los botones al pasar por
   encima lo pintaba entero, y de la franja salía un círculo azul marino donde
   tenía que haber una rayita. La regla de los botones lleva pseudoclase y pesa
   más que una clase suelta, así que hay que contestarle con otra. */
.stretch-grip:hover, .stretch-grip:active { background: transparent; border-color: transparent; }
.stretch-grip:active { transform: none; box-shadow: none; }
.stretch-grip::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 26px;
  height: 6px;
  margin: -3px 0 0 -13px;
  border: 1.5px solid #fff;
  border-radius: var(--r-pill);
  background: var(--kind, var(--ink-soft));
}
.stretch.held .stretch-grip { display: block; }
/* Con ratón no hay dedo que mantener pulsado, así que los tiradores salen al
   pasar por encima de la franja y se quedan mientras su formulario está
   abierto. Es lo que hace cualquier calendario de escritorio, y lo que espera
   quien llega con un puntero fino. */
@media (hover: hover) and (pointer: fine) {
  .stretch:hover .stretch-grip,
  .stretch:has(.stretch-body[open]) .stretch-grip { display: block; }
}
.stretch-grip-top { top: -22px; }
.stretch-grip-end { bottom: -22px; }
.stretch-grip:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

/* El tirador de en medio se lleva la franja entera sin cambiar lo que dura.
   Cubre lo que queda de ella entre los dos bordes, porque una franja se coge
   por donde sea y no por un punto: buscar un asa de veintidós píxeles con el
   pulgar en una franja de un cuarto de hora es buscar. */
.stretch-grip-whole {
  /* Por debajo de los dos bordes: ellos son los finos y tienen que ganar donde
     se pisen, que en una franja corta es casi toda. Cubre la franja entera y
     nada más: dejándole veintidós píxeles a cada borde, en una de un cuarto de
     hora no le quedaba alto y se salía por debajo. */
  z-index: 2;
  top: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: auto;
  margin-left: 0;
  border-radius: 6px;
  cursor: grab;
}
.stretch-grip-whole:active { cursor: grabbing; }
/* Las dos rayitas de agarre, como las de los bordes pero tumbadas una sobre
   otra: dicen que de aquí se tira, y no hacia dónde. */
.stretch-grip-whole::before {
  width: 18px;
  height: 2px;
  margin: -4px 0 0 -9px;
  border: 0;
  background: rgb(255 255 255 / 70%);
  box-shadow: 0 5px 0 rgb(255 255 255 / 70%);
}
.stretch-drawn .stretch-grip-whole::before { background: var(--plate); box-shadow: 0 5px 0 var(--plate); }

/* Lo bloqueado va encima y rayado: no es una banda más, es lo que tacha las que
   tenga debajo. */
/* Una franja con los tiradores fuera va por encima de sus vecinas: los
   tiradores sobresalen de ella, y por debajo quedaban detrás de la de al lado. */
.stretch.held { z-index: 5; }

/* Y la que va en el dedo, por encima de todas y levantada del papel: se lleva
   cruzando a las demás sin apartarlas, así que tiene que verse pasar por encima
   y no metiéndose entre ellas. Ver schedule_controller.js. */
.stretch.carried { z-index: 6; }
.stretch.carried .stretch-face { box-shadow: var(--lift-float); }

.stretch.kind-closed { z-index: 2; }
.stretch.kind-closed .stretch-face {
  background-image: repeating-linear-gradient(135deg, rgb(255 255 255 / 18%) 0 6px, transparent 6px 12px);
}

/* La franja que todavía no existe. No tiene tipo ni se ha guardado, así que se
   dibuja como un hueco marcado y no como una pieza puesta. */
.stretch-drawn { z-index: 4; }
.stretch-drawn .stretch-face {
  background: var(--plate-tint);
  border: 2px dashed var(--plate);
  color: var(--plate-deep);
}
.stretch-drawn .stretch-grip::before { background: var(--plate); border-color: #fff; }

/* La hora que eligió el cliente y el taller todavía no ha aceptado, dibujada en
   su día: tampoco es oficial, así que se dibuja como la franja que todavía no
   existe -tinte y filo discontinuo-, que es como la agenda dice "solicitada".
   Va por encima de las demás citas para que se vea entera si las pisa. */
.stretch-proposed { z-index: 4; }
.stretch-proposed .stretch-face {
  background: var(--plate-tint);
  border: 2px dashed var(--plate);
  color: var(--plate-deep);
}
.stretch-proposed .stretch-grip::before { background: var(--plate); border-color: #fff; }
.stretch-proposed .stretch-grip-whole::before { background: var(--plate); box-shadow: 0 5px 0 var(--plate); }
/* Las demás citas de ese día se leen y no se tocan: se cambian en la agenda. */
.stretch-still { pointer-events: none; }
.stretch-still .stretch-face { margin: 0; cursor: default; }

/* La rejilla dentro de la cita: el día escrito como título y, a su derecha,
   el dibujo que abre ese día en la agenda. */
.fitting-head { display: flex; align-items: center; justify-content: space-between; gap: calc(var(--space) * 3); }
.fitting-head h2 { margin: 0; }
.fitting > .hint { margin: calc(var(--space) * 1) 0 calc(var(--space) * 5); }
.fitting .daygrid { margin-bottom: 0; }

/* Lo que el taller ofrece y nadie ha cogido, detrás de lo cogido y en gris. No
   es otra cosa que pulsar: es el fondo sobre el que se lee el trabajo, y por
   eso no lleva color de tipo, ni sombra, ni nada que lo levante del papel. Se
   ve, y no resalta. Ver workshop/planning/days/show. */
.opening {
  position: relative;
  z-index: 1;
  grid-column: 1;
  min-width: 0;
  margin: 1px 2px;
  pointer-events: none;
}
.opening-face {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: calc(var(--space) * 2);
  overflow: hidden;
  height: 100%;
  margin: 0;
  padding: calc(var(--space) * 1) calc(var(--space) * 2);
  /* La raya se ve: es lo que dice dónde acaba un rato y empieza el siguiente,
     y a `--hairline` sobre el papel blanco había que buscarla. Se queda de
     puntos -lo que se ofrece no es una pieza puesta- y con su propio gris, más
     oscuro que el de las horas: las dos rayas se cruzan en la misma rejilla y
     tienen que decirse aparte de una ojeada.
     Lo escrito dentro va al revés, más apagado: el rato ofrecido es el fondo
     sobre el que se lee el trabajo, y su letra no se lee, se reconoce. */
  border: 1px dashed var(--dash);
  border-radius: 6px;
  color: var(--ink-ghost);
  font-size: 11px;
  line-height: 1.2;
}
.opening-when { font-weight: 650; font-variant-numeric: tabular-nums; }
.opening-each { margin-left: auto; }
/* Lo tachado tampoco es una pieza puesta: es lo que quita las que haya debajo,
   y se dibuja rayado como en el horario. */
.opening-closed .opening-face {
  border-style: solid;
  background-image: repeating-linear-gradient(135deg, var(--wash) 0 5px, transparent 5px 10px);
}

/* Lo cogido va por encima de lo que se ofrece. */
.daygrid-canvas .stretch { z-index: 2; }

/* Lo escondido se esconde. `hidden` lo apaga el navegador con una regla de
   menos peso que una clase, así que una franja seguía dibujándose después de
   soltarla. */
.stretch[hidden] { display: none; }

/* El formulario de una franja. Cuelga de ella en un ordenador y sube como una
   hoja desde abajo en un móvil, como el resto de lo que se abre en esta
   aplicación. Sin JavaScript se abre igual: es un <details>. */
/* Una franja con su formulario abierto va por encima de todo lo demás: el panel
   es más ancho que ella y se le sale por los lados —por debajo quedaba medio
   tapado por la franja de al lado— y se sale también de la rejilla hacia el
   muelle, que vive a 20.

   Y el papel deja de empujar mientras el formulario está abierto: un
   `transform` convierte a su elemento en el techo de todo lo que lleve dentro,
   y por alto que fuera el panel se quedaba debajo del muelle. Mientras hay un
   formulario abierto no se está pasando de día. Ver pager_controller.js. */
.stretch:has(.stretch-body[open]) { z-index: 41; }
.paper:has(.stretch-body[open]) > * { transform: none; }

.stretch-panel {
  position: absolute;
  left: 0;
  top: calc(100% + var(--space) * 2);
  z-index: 30;
  width: max-content;
  /* Lo ancho que tiene que ser para que los cinco tipos quepan en dos
     renglones y las dos horas quepan lado a lado. Más estrecho, el panel era
     una columna larguísima que no cabía de arriba abajo en la pantalla. */
  min-width: 380px;
  max-width: min(440px, calc(100vw - var(--space) * 10));
  padding: calc(var(--space) * 4);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
  cursor: auto;
}
/* El que no cabe debajo de su franja se sube lo justo para verse entero, y si
   ni así cabe, se desplaza por dentro. Cuánto se sube lo decide el controlador
   al abrirlo, porque depende de dónde esté la franja y de lo alta que sea la
   ventana. Ver schedule_controller.js. */
@media (min-width: 760px) {
  .stretch-panel { overflow-y: auto; overscroll-behavior: contain; }
}
.stretch-panel > :first-child { margin-top: 0; }
.stretch-panel form { margin: 0 0 calc(var(--space) * 3); }
.stretch-panel form:last-child { margin-bottom: 0; }
/* Quién está dentro va encima de las horas, y separado de ellas: es otra
   cosa, no el primer campo del formulario. */
.stretch-panel > .rows { margin-bottom: calc(var(--space) * 5); }
.stretch-panel .take-in { margin-bottom: calc(var(--space) * 2); }
/* Quién está dentro, como una fila que abre su cita; recibir el coche, a lo
   ancho debajo; moverla, tras una raya; y anular al final, a lo ancho y en
   rojo. Eran cuatro píldoras pequeñas una debajo de otra. */
.stretch-panel > .stretch-who { margin: 0 0 calc(var(--space) * 3); }
.stretch-who .place-hint.meta { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 1) calc(var(--space) * 2); }
.stretch-who .plate { min-height: 22px; font-size: 13px; }
.stretch-panel form.stretch-move { margin: calc(var(--space) * 4) 0 0; padding-top: calc(var(--space) * 4); border-top: 1px solid var(--hairline); }
.stretch-drop { display: flex; flex-direction: column; gap: calc(var(--space) * 2); margin-top: calc(var(--space) * 4); padding-top: calc(var(--space) * 4); border-top: 1px solid var(--hairline); }
/* Lo que se lee de una cita terminada: quién, lo que pasó en dos columnas, y
   a lo ancho los dos sitios donde sigue todo. */
.stretch-done-who { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2) calc(var(--space) * 3); margin: 0 0 calc(var(--space) * 4); font-size: 17px; }
.stretch-done-who .plate { min-height: 22px; font-size: 13px; }
.stretch-done-facts { margin: 0 0 calc(var(--space) * 5); padding-top: calc(var(--space) * 4); border-top: 1px solid var(--hairline); }
.stretch-done-facts dd { overflow-wrap: anywhere; }
.stretch-done-does { display: flex; flex-direction: column; gap: calc(var(--space) * 2); }
.stretch-done + .stretch-done { margin-top: calc(var(--space) * 6); padding-top: calc(var(--space) * 6); border-top: 1px solid var(--hairline); }
a.panel-save.button-link.quiet { background: var(--card); color: var(--ink); box-shadow: none; }
a.panel-save.button-link.quiet .icon { color: var(--ink-soft); }
button.panel-save.quiet { background: var(--card); border-color: var(--rule); color: var(--ink); box-shadow: none; }
button.panel-save.quiet:hover { background: var(--paper); border-color: var(--ink-soft); }
.sign-out { margin: calc(var(--space) * 6) 0 0; }

/* La cita terminada sigue en su hueco, apagada: estuvo, pero ya no es
   trabajo que venga. */
.stretch.is-done .stretch-face { background: var(--wash); color: var(--ink-soft); }
.stretch.is-done .stretch-each { display: inline-flex; align-items: center; gap: calc(var(--space) * 1); opacity: 1; font-weight: 650; }
.stretch.is-done .stretch-each .icon { width: 14px; height: 14px; }
.stretch-title { margin: 0 0 calc(var(--space) * 2); font-size: 15px; font-weight: 650; }

/* Los tipos de cita, en pastillas con su color. Son cinco y caben en dos
   renglones; en una lista de botones redondos eran cinco filas de cuarenta y
   cuatro píxeles, media hoja para una pregunta que se contesta de una ojeada.
   La elegida va llena de su color y se ve encendida desde lejos. */
.kinds {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--space) * 2);
  margin: 0 0 calc(var(--space) * 4);
  padding: 0;
  border: 0;
}
.kinds legend { width: 100%; margin-bottom: calc(var(--space) * 2); padding: 0; font-size: 14px; font-weight: 550; color: var(--ink-soft); }
.kind-pick {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  min-height: 44px;
  padding: 0 calc(var(--space) * 3);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  color: var(--ink);
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
}
/* El botón de verdad sigue ahí, escondido: el teclado y el lector de pantalla
   siguen encontrando un grupo de opciones, y lo que se dibuja es la pastilla. */
.kind-pick input[type="radio"] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.kind-dot { flex: none; width: 10px; height: 10px; border-radius: var(--r-pill); background: var(--kind, var(--ink-soft)); }
.kind-pick:has(input:checked) { background: var(--kind, var(--plate)); border-color: var(--kind, var(--plate)); color: #fff; }
.kind-pick:has(input:checked) .kind-dot { background: #fff; }
.kind-pick:has(input:focus-visible) { outline: 2px solid var(--plate); outline-offset: 2px; }
@media (hover: hover) {
  .kind-pick:hover { border-color: var(--ink-soft); }
}
/* En una cita las pastillas no marcan un formulario: cada una lo cambia al
   pulsarla, así que son botones. Se dibujan como las del horario y no como la
   píldora azul, y la del tipo de ahora va llena de su color y no se pulsa. */
.kinds form { margin: 0; }
button.kind-pick, button.kind-pick:hover { background: var(--card); border-color: var(--rule); color: var(--ink); box-shadow: none; }
@media (hover: hover) {
  button.kind-pick:hover { border-color: var(--ink-soft); }
}
.kind-pick.is-current { background: var(--kind); border-color: var(--kind); color: #fff; cursor: default; }
.kind-pick.is-current .kind-dot { background: #fff; }

/* Las dos salidas de la hoja, en una fila y del tamaño de lo que dicen. Una
   debajo de otra y a todo lo ancho pesaban más que todo lo que hay encima. */
.stretch-does { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2); margin-top: calc(var(--space) * 4); }
.stretch-does form { margin: 0; }
.stretch-does input[type="submit"], .stretch-does button { min-height: 44px; }

/* Y las que ocupan la hoja entera, una debajo de otra. Es para cuando lo que
   hay debajo es el final de la hoja -anotar la cita, contestar a la pregunta de
   correrle la hora a alguien- y no hay nada más que hacer ahí: el pulgar cae en
   cualquier sitio del renglón y acierta. */
.stretch-does-wide { flex-direction: column; align-items: stretch; }
.stretch-does-wide > * { width: 100%; }
.stretch-does-wide input[type="submit"], .stretch-does-wide .button-link { width: 100%; text-align: center; }

/* Quién viene, en la cita que se está anotando. Dar de alta a quien no está
   va dentro de la lista, detrás del buscador, y su botón de debajo solo se ve
   sin JavaScript, que es cuando la lista es la del sistema y no tiene dónde
   llevarlo. Ver chooser_controller.js. */
.pick:has(> .chooser) > .newcomer > summary { display: none; }

/* A lo ancho, como todo lo que cierra o abre una hoja: una píldora al lado de
   la lista dejaba el nombre del cliente en tres letras y un punto. */
.newcomer-open {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--space) * 2);
  min-height: 52px;
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  color: var(--ink);
  font-weight: 550;
  cursor: pointer;
  list-style: none;
}
.newcomer-open:hover { border-color: var(--ink-soft); }
.newcomer-open::-webkit-details-marker, .newcomer-open::marker { display: none; content: ""; }

/* Lo mismo dentro de la lista: una fila más, pero la que da de alta, en el
   azul de lo que se pulsa y separada de los nombres por su raya. */
.chooser-add {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 2);
  width: 100%;
  min-height: 48px;
  margin-bottom: var(--space);
  padding: 0 calc(var(--space) * 3);
  border: 0;
  border-bottom: 1px solid var(--hairline);
  border-radius: 0;
  background: none;
  color: var(--plate-deep);
  font: inherit;
  font-weight: 650;
  text-align: left;
  box-shadow: none;
  cursor: pointer;
}
.chooser-add:hover { background: var(--plate-tint); color: var(--plate-deep); }
.chooser-add:active { transform: none; }
.chooser-add:focus-visible { outline: 2px solid var(--plate); outline-offset: -2px; }
.chooser-add .icon { flex: none; width: 20px; height: 20px; }

/* La hoja del cliente nuevo y la de la cita no cuelgan de su botón como
   cuelgan casi todas: se abren desde otra hoja -el menú, la cita de la
   agenda- que ya está donde cabe, y colgadas de un botón a media hoja se
   salían por abajo de la ventana. En un ordenador flotan en medio de la
   pantalla y en un móvil suben desde el borde de abajo, una encima de otra.

   Se centran con márgenes y no con `transform`: una caja transformada es el
   marco de todo lo fijo que lleve dentro, y la hoja del cliente nuevo, que va
   dentro de la de la cita, se quedaba encerrada en ella. */
.newcomer-panel, .booker-panel, .ask-panel {
  position: fixed;
  inset: 0;
  z-index: 46;
  width: min(380px, calc(100vw - var(--space) * 8));
  height: fit-content;
  max-height: 86dvh;
  margin: auto;
  overflow-y: auto;
  padding: calc(var(--space) * 5);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}
.booker-panel { z-index: 45; width: min(440px, calc(100vw - var(--space) * 8)); }
@media (max-width: 759px) {
  .newcomer-panel, .booker-panel, .ask-panel { width: auto; margin: 0; max-height: 82dvh; }
}

/* La de la bandeja sí cuelga de su botón: se abre desde la cabecera, arriba
   del todo, donde debajo cabe siempre. En medio de la pantalla se leía como
   otra cosa que había salido de ninguna parte. Del borde derecho, que es donde
   está el botón. */
@media (min-width: 760px) {
  .screen-head > .caller > .booker-panel {
    position: absolute;
    inset: calc(100% + var(--space) * 2) 0 auto auto;
    max-height: calc(100dvh - var(--space) * 40);
    margin: 0;
  }
}

/* Las dos tarjetas del menú que abren una hoja son un <details>: la tarjeta es
   su botón, y ocupa la celda entera como las que son un enlace. */
.jump-does > details { display: grid; }
summary.jump-do { list-style: none; cursor: pointer; }
summary.jump-do::-webkit-details-marker, summary.jump-do::marker { display: none; content: ""; }

/* La pregunta antes de correrle la hora a nadie. Cuelga en medio de la
   pantalla en un ordenador y sube desde el borde de abajo en un móvil, como
   todo lo que se abre aquí. Llega abierta desde el servidor, así que no tiene
   botón que la abra: lo que se ve es la pregunta. */
.shoving { display: contents; }
.shoving-panel {
  position: fixed;
  left: 50%;
  top: 50%;
  z-index: 45;
  width: min(440px, calc(100vw - var(--space) * 8));
  transform: translate(-50%, -50%);
  padding: calc(var(--space) * 5);
  border: 1px solid var(--rule);
  border-radius: var(--r-panel);
  background: var(--card);
  box-shadow: var(--lift-float);
}
.shoving-panel .rows { margin-bottom: calc(var(--space) * 4); }
@media (max-width: 759px) {
  .shoving-panel { left: 0; top: auto; width: auto; transform: none; }
}

/* A quién se le cuenta lo que ha pasado, y por dónde. */
.tells { margin: calc(var(--space) * 4) 0; }
.tell {
  display: flex;
  align-items: center;
  gap: calc(var(--space) * 3);
  min-height: 44px;
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
}
.tells .hint { margin: calc(var(--space) * 1) 0 0; }

/* ── Las hojas ────────────────────────────────────────────────────────────
   Todo lo que se abre en esta aplicación es un panel de <details> marcado
   `.sheet`: cuelga de su botón donde hay sitio y sube desde el borde de abajo
   donde no lo hay. Dónde cuelga lo dice cada uno -el menú por la derecha, los
   meses por la izquierda, la franja debajo de sí misma- y está escrito más
   arriba, cada uno junto a lo suyo; lo que es igual en todas está aquí.

   Va al final del archivo a propósito: corrige lo que cada panel dice de sí
   mismo, y en una hoja de estilo manda la última regla que se lee. */

/* Nada aparece de golpe. En un ordenador el panel se asienta un dedo desde
   donde cuelgue -unos cuelgan hacia arriba y otros hacia abajo, y un movimiento
   corto vale para los dos-; en un móvil sube desde el borde, que es la misma
   distancia que recorre al cerrarse con el dedo. */
@keyframes sheet-settle { from { opacity: 0; transform: translateY(4px); } }
@keyframes sheet-rise { from { transform: translateY(100%); } }

/* La hoja vuelve a su sitio sola cuando se suelta antes de tiempo. Mientras se
   arrastra no hay transición: la hoja va con el dedo. */
.sheet { transition: transform 200ms ease; }
.sheet.dragging { transition: none; user-select: none; }
/* Solo hacia atrás: una animación que se queda puesta al acabar deja la hoja
   transformada, y una hoja transformada encierra a las que se abren desde
   ella. */
details[open] > .sheet { animation: sheet-settle 140ms ease backwards; }

@media (max-width: 759px) {
  /* Lo de detrás se apaga mientras la hoja está abierta, y el velo baja con
     ella: mientras se tira, lo de debajo se va encendiendo, y eso es lo que
     dice que se está yendo antes de que se haya ido. `--veil` lo escribe
     sheet_controller.js con el dedo puesto.

     La franja del horario es la excepción: mientras su formulario está abierto
     se sigue tirando de sus dos bordes sobre la rejilla, y un velo por encima
     dejaría los tiradores donde se ven pero no se tocan. */
  details[open]:has(> .sheet)::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 39;
    background: rgb(22 24 28 / calc(32% * var(--veil, 1)));
  }
  .stretch-body[open]::before { display: none; }

  /* Por encima del muelle, que está a 20: la hoja sube desde el mismo borde
     donde vive el muelle, y por debajo le tapaba lo que se venía a pulsar. */
  .dock:has(details[open] > .sheet) { z-index: 41; }

  details[open] > .sheet { animation: sheet-rise 200ms ease backwards; }
  .sheet {
    position: fixed;
    inset: auto 0 0 0;
    top: auto;
    z-index: 40;
    width: auto;
    min-width: 0;
    max-width: none;
    /* Contra la ventana que se ve -`dvh`- y no contra la grande: con `vh`, la
       hoja se mide como si la barra del navegador no estuviera y sobresale por
       abajo justo mientras la barra está puesta. */
    max-height: 82dvh;
    overflow-y: auto;
    /* Ni pasa el desplazamiento a lo de detrás ni hace el rebote de Android al
       llegar arriba: ahí, lo que sigue bajando es la hoja entera. */
    overscroll-behavior: none;
    padding: calc(var(--space) * 4);
    /* Y por abajo, sitio para la raya del gesto. Se descuenta siempre y no solo
       donde `env()` la declara: en un navegador de móvil devuelve cero y la
       barra del sistema se pinta encima igual, y el botón de guardar quedaba
       debajo de ella. Ver docs/DESIGN.md. */
    padding-bottom: max(calc(var(--space) * 8), calc(var(--band-bottom) + var(--space) * 4));
    border: 0;
    border-top: 1px solid var(--rule);
    border-radius: var(--r-panel) var(--r-panel) 0 0;
    /* De la hoja se tira desde cualquier sitio, así que el gesto vertical es
       nuestro en toda ella: `pan-y` deja que el navegador la desplace por
       dentro mientras haya algo que desplazar, y el controlador se lo quita
       cuando la hoja ya está por arriba del todo. */
    touch-action: pan-y;
  }

  /* Mientras una hoja está abierta, lo de debajo no se desplaza. Ya está
     apagado por el velo, y encima se movía: al desplazar, el navegador del
     móvil enseña y esconde su barra, y una hoja pegada al borde de abajo sube
     y baja con ella. Ver sheet_controller.js. */
  html.sheet-open, html.sheet-open body { overflow: hidden; }

  /* Una hoja se agarra por arriba, y de ella se tira hacia abajo para cerrarla.
     Se agarra por toda la cabecera y no por la barrita: cuatro píxeles no se
     aciertan con el pulgar, y el dedo se pone donde ve sitio. La barrita se
     queda, porque es lo que dice que de ahí se tira. */
  .sheet-head {
    touch-action: none;
    user-select: none;
    cursor: grab;
  }
  .sheet-head:active { cursor: grabbing; }
  .sheet-grip {
    display: block;
    width: 72px;
    height: 22px;
    margin: calc(var(--space) * -1) auto calc(var(--space) * 2);
    border-radius: var(--r-pill);
    background: linear-gradient(var(--rule), var(--rule)) center / 40px 4px no-repeat;
  }
  .sheet-title { font-size: 17px; }
}

/* Un pliegue: lo que no se abre todos los días, con su título pulsable. */
.fold + .fold { margin-top: calc(var(--space) * 3); }
.fold > summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  font-weight: 600;
  cursor: pointer;
}
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::before { content: "+"; width: 20px; color: var(--ink-soft); }
.fold[open] > summary::before { content: "−"; }
.fold > summary:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

/* Las fechas que se marcan para repartirles el día. Es la rejilla del mes otra
   vez, en pequeño y con casillas: se reconoce sin explicarla. */
.dates {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  margin: 0 0 calc(var(--space) * 3);
  padding: 0;
  border: 0;
}
.date-pick { font-size: 13px; }
/* La fecha del propio día no se copia sobre sí misma: ya es ella. Se escribe
   apagada y sin borde, para que se lea como el sitio donde se está. */
.date-pick.itself, .date-pick.itself:hover { border-color: transparent; background: transparent; color: var(--ink-faint); cursor: default; }
.date-away, .date-away:hover { border-color: transparent; background: transparent; }

/* Una cita que se ha quedado debajo de un rato bloqueado, con las dos salidas
   que tiene: otra hora, o ninguna. */
.clash .does { margin-top: calc(var(--space) * 2); }

/* ── El historial ────────────────────────────────────────────────────────
   Dos pestañas, las citas y los coches, como una sola pieza partida en dos: la
   que se mira, encendida. Las mismas, con las que hagan falta, reparten el día
   de costumbre en el asistente. Debajo, los meses como paneles, y al borde la barra
   que se recorre con el dedo para saltar a uno. */
.tabs {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: calc(var(--space) * 1);
  margin-bottom: calc(var(--space) * 6);
  padding: calc(var(--space) * 1);
  border-radius: var(--r-pill);
  background: var(--wash);
}
.tabs a, .tabs a:visited {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 calc(var(--space) * 3);
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  font-weight: 550;
  text-align: center;
  text-decoration: none;
}
.tabs a:hover { color: var(--ink); }
.tabs a[aria-current="page"] { background: var(--plate-tint); color: var(--plate-deep); }
.tabs a:focus-visible { outline: 2px solid var(--plate); outline-offset: 2px; }

/* La barra va al lado de la lista y no encima: tapar el galón de las filas
   con ella era tapar a dónde se va. */
.history { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: calc(var(--space) * 2); }
.history-month { scroll-margin-top: calc(var(--space) * 4); }
.history-month + .history-month { margin-top: calc(var(--space) * 4); }
/* En un ordenador la barra sale de la columna: dentro la estrechaba, y los
   meses quedaban más cortos que las pestañas de encima. */
@media (min-width: 760px) {
  .history { grid-template-columns: minmax(0, 1fr) 0; gap: calc(var(--space) * 4); }
}

/* Quieta mientras la lista corre, de debajo de las pestañas hasta encima del
   muelle: es donde el pulgar la busca, y no se mete debajo de nada al
   desplazar. `touch-action` se la quita al navegador, que si no haría scroll
   con el mismo gesto. */
.scrubber {
  position: sticky;
  top: calc(var(--band-top) + var(--space) * 40);
  align-self: start;
  display: flex;
  flex-direction: column;
  width: 28px;
  height: calc(100dvh - var(--band-top) - var(--space) * 66);
  touch-action: none;
  user-select: none;
}
.scrubber-mark {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}
.scrubber-mark::before {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: var(--r-pill);
  background: var(--dash);
}
.scrubber-mark:focus-visible { outline: 2px solid var(--plate); outline-offset: -2px; border-radius: var(--r-row); }
.scrubber-year {
  position: absolute;
  inset: 50% auto auto 50%;
  transform: translate(-50%, -50%);
  padding: 0 var(--space);
  border-radius: var(--r-row);
  background: var(--paper);
  color: var(--ink-soft);
  font-size: 11px;
  font-weight: 550;
  line-height: 1.2;
}
/* El nombre del mes, al lado del dedo y no debajo: debajo no se ve. */
.scrubber-bubble {
  position: absolute;
  right: calc(100% + var(--space) * 3);
  transform: translateY(-50%);
  padding: calc(var(--space) * 2) calc(var(--space) * 4);
  border-radius: var(--r-pill);
  background: var(--plate);
  color: #fff;
  font-weight: 550;
  white-space: nowrap;
  box-shadow: var(--lift-float);
  pointer-events: none;
}
.scrubber-bubble[hidden] { display: none; }

/* ── Marcar en el historial ───────────────────────────────────────────────
   Mantener pulsada una fila la marca. El teléfono no enseña su vista previa
   del enlace ni selecciona el texto con ese gesto: el gesto es nuestro. Ver
   marking_controller.js. */
.history .place a { -webkit-touch-callout: none; }
.history.marking .place a { user-select: none; }

/* Mientras se marca, el galón de cada fila se vuelve el círculo que dice si
   está marcada: tocar ya no abre, y un galón prometía que sí. */
.history.marking .rows li.place a::after {
  width: 22px;
  height: 22px;
  border: 2px solid var(--rule);
  border-radius: var(--r-pill);
  background: transparent;
  clip-path: none;
}
.history.marking .rows li.place.marked a::after {
  border-color: var(--plate);
  background: var(--plate);
  box-shadow: inset 0 0 0 4px var(--card);
}
.history .rows li.place.marked .place-name { color: var(--plate-deep); }

.marking-bar { background: var(--card); }
.marking-bar[hidden] { display: none; }
.marking-bar .picked-count { text-align: center; }

/* Cómo se marca más de una vez, en las tarjetas del menú: se aciertan con el
   pulgar sin apuntar, y es la misma clase de cosa, algo que se empieza. */
.marking-picks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(var(--space) * 2);
  margin: calc(var(--space) * 3) 0;
}
button.jump-do { width: 100%; border: 0; box-shadow: none; font-size: 13px; }
button.jump-do:hover { border: 0; background: var(--paper); }
/* El campo de fecha cubre la tarjeta entera y no se ve: lo que se toca es la
   tarjeta, y lo que se abre es el calendario del sistema. */
.marking-until { position: relative; cursor: pointer; }
.marking-until input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}
.marking-until:focus-within { outline: 2px solid var(--plate); outline-offset: 2px; }

/* Borrar va aparte y debajo: lo de arriba marca y se deshace tocando, esto no. */
.marking-drop { padding-top: calc(var(--space) * 3); border-top: 1px solid var(--hairline); }

@media (max-width: 759px) {
  /* Sitio debajo de la última fila para que suba por encima de la hoja. */
  .history.marking { padding-bottom: calc(var(--space) * 80); }
}

/* En un ordenador es una sola fila encima del muelle, con filo azul y del
   ancho de lo que dice: blanca, del ancho del muelle y pegada a él se leía como
   un segundo piso suyo, y colgada a un lado tapaba los círculos de marcar. El
   azul es el de lo elegido, que es de lo que habla. Ver docs/DESIGN.md. */
@media (min-width: 760px) {
  .marking-bar {
    position: fixed;
    right: 0;
    bottom: calc(var(--space) * 19 + max(var(--space) * 6, var(--band-bottom)));
    left: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: calc(var(--space) * 3);
    width: max-content;
    max-width: calc(100% - var(--space) * 10);
    margin: 0 auto;
    padding: calc(var(--space) * 2) calc(var(--space) * 2) calc(var(--space) * 2) calc(var(--space) * 5);
    border: 2px solid var(--plate);
    border-radius: var(--r-pill);
    background: var(--card);
    box-shadow: var(--lift-float);
  }
  .marking-bar .sheet-head { display: none; }
  .marking-bar .picked-count { white-space: nowrap; }
  .marking-picks { display: flex; margin: 0; }
  .marking-picks .jump-do {
    flex-direction: row;
    min-height: 44px;
    padding: 0 calc(var(--space) * 4);
    border-radius: var(--r-pill);
    font-size: 14px;
    white-space: nowrap;
  }
  .marking-picks .jump-do .icon { width: 18px; height: 18px; }
  .marking-drop { padding-top: 0; border-top: 0; }
  .marking-drop .panel-save { width: auto; min-height: 44px; padding: 0 calc(var(--space) * 5); font-size: 15px; }
  .history.marking { padding-bottom: calc(var(--space) * 20); }
}

/* ── El horario que se dibuja con el dedo ─────────────────────────────────
   La rejilla de un día: quince horas en pasos de quince minutos, o sea sesenta
   filas. Una banda se coloca diciendo en qué fila empieza y en cuál acaba.

   Las filas se escriben en clases y no en un atributo `style` porque la
   politica de contenido de esta aplicacion no deja estilos en linea -ver
   config/initializers/content_security_policy.rb-, que es la misma razon por
   la que las barras del panel de plataforma son SVG con `width`. Son ciento
   veinte reglas mecanicas y por eso van juntas, en dos parrafos, fuera del
   camino de lo que se lee. Ver docs/DESIGN.md. */
.rs-1 { grid-row-start: 1; } .rs-2 { grid-row-start: 2; } .rs-3 { grid-row-start: 3; } .rs-4 { grid-row-start: 4; } .rs-5 { grid-row-start: 5; } .rs-6 { grid-row-start: 6; } .rs-7 { grid-row-start: 7; } .rs-8 { grid-row-start: 8; } .rs-9 { grid-row-start: 9; } .rs-10 { grid-row-start: 10; } .rs-11 { grid-row-start: 11; } .rs-12 { grid-row-start: 12; } .rs-13 { grid-row-start: 13; } .rs-14 { grid-row-start: 14; } .rs-15 { grid-row-start: 15; } .rs-16 { grid-row-start: 16; } .rs-17 { grid-row-start: 17; } .rs-18 { grid-row-start: 18; } .rs-19 { grid-row-start: 19; } .rs-20 { grid-row-start: 20; } .rs-21 { grid-row-start: 21; } .rs-22 { grid-row-start: 22; } .rs-23 { grid-row-start: 23; } .rs-24 { grid-row-start: 24; } .rs-25 { grid-row-start: 25; } .rs-26 { grid-row-start: 26; } .rs-27 { grid-row-start: 27; } .rs-28 { grid-row-start: 28; } .rs-29 { grid-row-start: 29; } .rs-30 { grid-row-start: 30; } .rs-31 { grid-row-start: 31; } .rs-32 { grid-row-start: 32; } .rs-33 { grid-row-start: 33; } .rs-34 { grid-row-start: 34; } .rs-35 { grid-row-start: 35; } .rs-36 { grid-row-start: 36; } .rs-37 { grid-row-start: 37; } .rs-38 { grid-row-start: 38; } .rs-39 { grid-row-start: 39; } .rs-40 { grid-row-start: 40; } .rs-41 { grid-row-start: 41; } .rs-42 { grid-row-start: 42; } .rs-43 { grid-row-start: 43; } .rs-44 { grid-row-start: 44; } .rs-45 { grid-row-start: 45; } .rs-46 { grid-row-start: 46; } .rs-47 { grid-row-start: 47; } .rs-48 { grid-row-start: 48; } .rs-49 { grid-row-start: 49; } .rs-50 { grid-row-start: 50; } .rs-51 { grid-row-start: 51; } .rs-52 { grid-row-start: 52; } .rs-53 { grid-row-start: 53; } .rs-54 { grid-row-start: 54; } .rs-55 { grid-row-start: 55; } .rs-56 { grid-row-start: 56; } .rs-57 { grid-row-start: 57; } .rs-58 { grid-row-start: 58; } .rs-59 { grid-row-start: 59; } .rs-60 { grid-row-start: 60; } .rs-61 { grid-row-start: 61; }

.re-2 { grid-row-end: 2; } .re-3 { grid-row-end: 3; } .re-4 { grid-row-end: 4; } .re-5 { grid-row-end: 5; } .re-6 { grid-row-end: 6; } .re-7 { grid-row-end: 7; } .re-8 { grid-row-end: 8; } .re-9 { grid-row-end: 9; } .re-10 { grid-row-end: 10; } .re-11 { grid-row-end: 11; } .re-12 { grid-row-end: 12; } .re-13 { grid-row-end: 13; } .re-14 { grid-row-end: 14; } .re-15 { grid-row-end: 15; } .re-16 { grid-row-end: 16; } .re-17 { grid-row-end: 17; } .re-18 { grid-row-end: 18; } .re-19 { grid-row-end: 19; } .re-20 { grid-row-end: 20; } .re-21 { grid-row-end: 21; } .re-22 { grid-row-end: 22; } .re-23 { grid-row-end: 23; } .re-24 { grid-row-end: 24; } .re-25 { grid-row-end: 25; } .re-26 { grid-row-end: 26; } .re-27 { grid-row-end: 27; } .re-28 { grid-row-end: 28; } .re-29 { grid-row-end: 29; } .re-30 { grid-row-end: 30; } .re-31 { grid-row-end: 31; } .re-32 { grid-row-end: 32; } .re-33 { grid-row-end: 33; } .re-34 { grid-row-end: 34; } .re-35 { grid-row-end: 35; } .re-36 { grid-row-end: 36; } .re-37 { grid-row-end: 37; } .re-38 { grid-row-end: 38; } .re-39 { grid-row-end: 39; } .re-40 { grid-row-end: 40; } .re-41 { grid-row-end: 41; } .re-42 { grid-row-end: 42; } .re-43 { grid-row-end: 43; } .re-44 { grid-row-end: 44; } .re-45 { grid-row-end: 45; } .re-46 { grid-row-end: 46; } .re-47 { grid-row-end: 47; } .re-48 { grid-row-end: 48; } .re-49 { grid-row-end: 49; } .re-50 { grid-row-end: 50; } .re-51 { grid-row-end: 51; } .re-52 { grid-row-end: 52; } .re-53 { grid-row-end: 53; } .re-54 { grid-row-end: 54; } .re-55 { grid-row-end: 55; } .re-56 { grid-row-end: 56; } .re-57 { grid-row-end: 57; } .re-58 { grid-row-end: 58; } .re-59 { grid-row-end: 59; } .re-60 { grid-row-end: 60; } .re-61 { grid-row-end: 61; }

/* Y lo alto que mide cada rejilla, que depende de cuantas horas enseñe: la
   agenda se cine a lo que el dia tiene y el horario ensena la jornada entera.
   Una hora son sesenta y cuatro pixeles arriba y veinte en el dibujo pequeno,
   y cada hora son cuatro filas de cuarto. Son reglas mecanicas, como las de las
   filas, y por eso van aqui abajo y en dos parrafos. */
.dh-1 .daygrid-rule { grid-template-rows: repeat(1, 64px); } .dh-1 .daygrid-canvas { grid-template-rows: repeat(4, 16px); } .dh-2 .daygrid-rule { grid-template-rows: repeat(2, 64px); } .dh-2 .daygrid-canvas { grid-template-rows: repeat(8, 16px); } .dh-3 .daygrid-rule { grid-template-rows: repeat(3, 64px); } .dh-3 .daygrid-canvas { grid-template-rows: repeat(12, 16px); } .dh-4 .daygrid-rule { grid-template-rows: repeat(4, 64px); } .dh-4 .daygrid-canvas { grid-template-rows: repeat(16, 16px); } .dh-5 .daygrid-rule { grid-template-rows: repeat(5, 64px); } .dh-5 .daygrid-canvas { grid-template-rows: repeat(20, 16px); } .dh-6 .daygrid-rule { grid-template-rows: repeat(6, 64px); } .dh-6 .daygrid-canvas { grid-template-rows: repeat(24, 16px); } .dh-7 .daygrid-rule { grid-template-rows: repeat(7, 64px); } .dh-7 .daygrid-canvas { grid-template-rows: repeat(28, 16px); } .dh-8 .daygrid-rule { grid-template-rows: repeat(8, 64px); } .dh-8 .daygrid-canvas { grid-template-rows: repeat(32, 16px); } .dh-9 .daygrid-rule { grid-template-rows: repeat(9, 64px); } .dh-9 .daygrid-canvas { grid-template-rows: repeat(36, 16px); } .dh-10 .daygrid-rule { grid-template-rows: repeat(10, 64px); } .dh-10 .daygrid-canvas { grid-template-rows: repeat(40, 16px); } .dh-11 .daygrid-rule { grid-template-rows: repeat(11, 64px); } .dh-11 .daygrid-canvas { grid-template-rows: repeat(44, 16px); } .dh-12 .daygrid-rule { grid-template-rows: repeat(12, 64px); } .dh-12 .daygrid-canvas { grid-template-rows: repeat(48, 16px); } .dh-13 .daygrid-rule { grid-template-rows: repeat(13, 64px); } .dh-13 .daygrid-canvas { grid-template-rows: repeat(52, 16px); } .dh-14 .daygrid-rule { grid-template-rows: repeat(14, 64px); } .dh-14 .daygrid-canvas { grid-template-rows: repeat(56, 16px); } .dh-15 .daygrid-rule { grid-template-rows: repeat(15, 64px); } .dh-15 .daygrid-canvas { grid-template-rows: repeat(60, 16px); }

.dh-1 .daysketch-rule { grid-template-rows: repeat(1, 20px); } .dh-1 .daysketch-canvas { grid-template-rows: repeat(4, 5px); } .dh-2 .daysketch-rule { grid-template-rows: repeat(2, 20px); } .dh-2 .daysketch-canvas { grid-template-rows: repeat(8, 5px); } .dh-3 .daysketch-rule { grid-template-rows: repeat(3, 20px); } .dh-3 .daysketch-canvas { grid-template-rows: repeat(12, 5px); } .dh-4 .daysketch-rule { grid-template-rows: repeat(4, 20px); } .dh-4 .daysketch-canvas { grid-template-rows: repeat(16, 5px); } .dh-5 .daysketch-rule { grid-template-rows: repeat(5, 20px); } .dh-5 .daysketch-canvas { grid-template-rows: repeat(20, 5px); } .dh-6 .daysketch-rule { grid-template-rows: repeat(6, 20px); } .dh-6 .daysketch-canvas { grid-template-rows: repeat(24, 5px); } .dh-7 .daysketch-rule { grid-template-rows: repeat(7, 20px); } .dh-7 .daysketch-canvas { grid-template-rows: repeat(28, 5px); } .dh-8 .daysketch-rule { grid-template-rows: repeat(8, 20px); } .dh-8 .daysketch-canvas { grid-template-rows: repeat(32, 5px); } .dh-9 .daysketch-rule { grid-template-rows: repeat(9, 20px); } .dh-9 .daysketch-canvas { grid-template-rows: repeat(36, 5px); } .dh-10 .daysketch-rule { grid-template-rows: repeat(10, 20px); } .dh-10 .daysketch-canvas { grid-template-rows: repeat(40, 5px); } .dh-11 .daysketch-rule { grid-template-rows: repeat(11, 20px); } .dh-11 .daysketch-canvas { grid-template-rows: repeat(44, 5px); } .dh-12 .daysketch-rule { grid-template-rows: repeat(12, 20px); } .dh-12 .daysketch-canvas { grid-template-rows: repeat(48, 5px); } .dh-13 .daysketch-rule { grid-template-rows: repeat(13, 20px); } .dh-13 .daysketch-canvas { grid-template-rows: repeat(52, 5px); } .dh-14 .daysketch-rule { grid-template-rows: repeat(14, 20px); } .dh-14 .daysketch-canvas { grid-template-rows: repeat(56, 5px); } .dh-15 .daysketch-rule { grid-template-rows: repeat(15, 20px); } .dh-15 .daysketch-canvas { grid-template-rows: repeat(60, 5px); }
