/* ═══════════════════════════════════════════════════════════════════════════
   Check-in console — CSS de pantalla
   Cliente: estudio boutique de ciclismo indoor (South Boston) · sobre MarianaTek
   DS: amalgama-design-system @ f657a24

   Reglas de la casa:
   · Nada de hex, px sueltos ni familias tipográficas escritas. Todo por token.
   · Este archivo NO pisa clases públicas de Embassy salvo donde hay un gap real
     del sistema, y ahí va declarado con `@ds-gap <id>` apuntando al issue.
     Ocho declarados, ni uno silencioso (FAILURES.md B2).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Capa de marca del cliente ─────────────────────────────────────────────
   Una sola familia en todo el producto. Se reasignan los tokens de rol; no se
   escribe la familia en ningún componente. Esto es white-label, no override:
   cuando el proyecto tenga su theme generado, esta regla se va a ese archivo. */
:root {
  /* Manrope, la familia de UI de Embassy (el --font-body del DS a partir de
     sep-2026; este commit fijado todavía dice Inter). Va embebida en
     fonts-manrope.css: sin red en runtime, igual que antes Epilogue. */
  --font-body: 'Manrope', 'Inter', sans-serif;
  --font-heading: var(--font-body);
  --font-mono: var(--font-body);
  /* El verde de «ya entró», en la caja y en la muestra de «Checked in». */
  --ck-done-surface: color-mix(in srgb, var(--color-success) 14%, var(--color-surface-container-high));
}

[hidden] { display: none !important; }

/* ── Estructura de pantalla ────────────────────────────────────────────────
   column-bleed adentro del shell: el plano de sala usa el monitor entero y el
   texto corrido se acota con .measure (COMPOSICION III·a·8). */
.ck-content { padding: 0; }
.ck-shell { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 1024px) {
  .ck-shell { grid-template-columns: 274px minmax(0, 1fr); align-items: start; }
}

/* ── Riel de agenda ────────────────────────────────────────────────────────
   Declara data-surface="container": todo lo que viva adentro toma ese fondo
   solo, sin que nadie escriba background. */
.ck-rail {
  display: flex; flex-direction: column; gap: var(--space-4); min-width: 0;
  background: var(--color-surface-container);
  border-bottom: 1px solid var(--color-outline-variant);
  padding: var(--space-4) var(--space-3);
}
@media (min-width: 1024px) {
  .ck-rail {
    border-bottom: 0; border-right: 1px solid var(--color-outline-variant);
    position: sticky; top: var(--topbar-height); height: calc(100vh - var(--topbar-height));
  }
}
.ck-rail-pad { padding-inline: var(--space-1); }
/* La fila de fecha es UN control con dos empujones al lado, no una barra de
   filtros: el picker lleva el tratamiento de campo del DS (date-picker-trigger
   + btn-tertiary, la composición del propio `Uso:` del componente) y las
   flechas van en btn-text, que no compite. */
/* Flechas y fecha van en UNA pieza: un fondo apenas más claro que el riel y un
   borde casi invisible. Con el campo del DS (borde de outline) la fecha era
   el borde más fuerte del riel y competía con la clase seleccionada. */
.ck-datebar {
  display: flex; align-items: center; gap: var(--space-0-5);
  height: 36px; padding: var(--space-0-5);
  border: 1px solid var(--color-surface-container-high);
  border-radius: var(--radius-full);
  background: var(--color-surface-container-low);
}
.ck-datebar .ck-nudge { border-radius: var(--radius-full); }
.ck-cal-foot {
  display: flex; justify-content: center; margin-top: var(--space-2); padding-top: var(--space-2);
  border-top: 1px solid color-mix(in srgb, var(--color-outline-variant) 40%, transparent);
}
.ck-datebar .ck-dp + .ck-nudge { color: var(--text-muted); }
.ck-dp { flex: 1; min-width: 0; }
/* @ds-gap embassy#13 — .date-picker-trigger fija `width: 240px`. Con las dos
   flechas al lado no entra en un riel de 296 y se desborda del padding: el
   componente no puede vivir en ninguna columna angosta. Debería ser un
   min-width, o un ancho que el contenedor pueda mandar.
   @ds-gap embassy#13 */
.ck-dp .date-picker-trigger { width: 100%; }
/* @ds-gap embassy#13 — adentro del stepper el trigger pierde su tratamiento de
   campo: el control es la pieza entera, no el botón del medio. */
.ck-dp .date-picker-trigger {
  height: 32px; border-color: transparent; background: transparent;
  justify-content: center; font-weight: var(--font-weight-regular);
}

/* ── Escala tipográfica del riel y el topbar ───────────────────────────
   Medida contra el refinamiento de Claude Design, rung por rung del DS.

   @ds-gap embassy#15 — el rastro vive en el topbar de una consola de
   mostrador: a distancia de escritorio, body-sm (12.5) no se lee de un
   vistazo. Sube un escalón, a body-lg. */
.ck-crumbs .breadcrumb-list { font-size: var(--font-size-body-lg); }

/* @ds-gap embassy#16 — seg-btn pinta el label con --color-on-surface, que
   es casi negro y está reservado para el contenido DENTRO de un
   componente: en el texto de una pantalla eso es A9. El grupo expone sus
   propias variables, así que se corrige por el punto de extensión del
   componente y no pisando la clase pública. */
.ck-range, .ck-theme {
  --seg-btn-label-color: var(--text-muted);
  --seg-btn-selected-label-color: var(--text-primary);
}


#ck-dlabel { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#ck-dpanel { z-index: 20; margin-top: var(--space-1); }
#ck-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); }
#ck-weekdays span { text-align: center; font-size: var(--font-size-badge); color: var(--text-muted); }

/* @ds-gap embassy#1 — Segmented Button no tiene modificador de ancho completo.
   En un riel de 296px el switch de vista tiene que ocupar el riel; hoy se
   encoge a su contenido y queda flotando a la izquierda. */
.ck-range .seg-btn { flex: 1 1 0; min-width: 0; }

.ck-sched { display: flex; flex-direction: column; gap: var(--space-2-5); flex: 1; overflow-y: auto; }

/* Las clases que ya pasaron, plegadas: arriba de la línea del ahora quedan
   solo las dos últimas. El resto está a un toque. */
.ck-earlier { display: flex; flex-direction: column; gap: var(--space-1); }
.ck-earlier-btn {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  width: 100%; min-height: 36px; padding: 0 var(--space-3);
  border: 0; border-radius: var(--radius-md); background: transparent; cursor: pointer;
  font-family: var(--font-body); font-size: var(--font-size-body-sm); font-weight: var(--font-weight-semibold);
  color: var(--text-secondary);
}
.ck-earlier-btn:hover { background: var(--color-surface-container-high); }
.ck-earlier-btn:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.ck-earlier-chev { color: var(--text-muted); transition: transform var(--duration-fast) var(--ease-default); }
.ck-earlier-btn[aria-expanded="true"] .ck-earlier-chev { transform: rotate(180deg); }

/* Jerarquía de selección — COMPOSICION.md §4c, tres significados y tres pesos:
   1 · qué clase estoy operando → primary-container   (el objeto de la pantalla)
   2 · qué filtro está activo   → secondary-container (lo maneja .chip, sin tocar)
   3 · cómo estoy mirando       → --ctx-track / --ctx-track-thumb (sin acento)  */

/* @ds-gap embassy#2 — list.md sigue definiendo el seleccionado como
   secondary-container, y §4c manda primary-container cuando la fila ES el
   objeto que se opera. Las dos reglas son ciertas y ninguna se refiere a la otra.
   @ds-gap embassy#3 — list-item tiene radio 0 y sangra de punta a punta; adentro
   de un riel con padding el seleccionado necesita forma propia. */
.ck-sched .list-item.is-selected {
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
  border-radius: var(--radius-md);
}
/* @ds-gap embassy#2 — sigue el mismo gap: el horario dentro de la fila
   seleccionada tiene que tomar el par del contenedor nuevo. */
.ck-sched .list-item.is-selected .ck-time { color: inherit; opacity: .75; }

/* @ds-gap embassy#3 — list-item sangra de punta a punta y tiene radio 0: adentro
   de un riel con padding, cada clase se lee como un bloque, no como una franja. */
.ck-sched .list-item { border-radius: var(--radius-md); min-height: 46px; padding: var(--space-2) var(--space-3); }
/* @ds-gap embassy#4 — list apila sus filas sin separación y no tiene variante de
   densidad: pegadas, nueve clases se leen como un bloque de texto y no como nueve
   cosas elegibles. */
.ck-sched .list { gap: var(--space-2-5); }
/* @ds-gap embassy#4 — y el nombre de la clase es el dato de la fila: va un escalón
   arriba, en 500, y en navy. list-item-headline lo pinta con --color-on-surface,
   que es casi negro y está reservado para el contenido DENTRO de un componente:
   en el texto de una página eso es A9 (CLAUDE.md, «si el texto sale negro, hay un
   token mal aplicado»).
   @ds-gap embassy#4 */
.ck-sched .list-item-headline {
  font-size: var(--font-size-heading-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}
/* @ds-gap embassy#4 */
.ck-sched .list-item.is-selected .list-item-headline { font-weight: var(--font-weight-bold); }
/* Con MarianaTek cada fila trae dos líneas (clase e instructora) y un día real
   tiene 28 clases: el riel se aprieta. Sigue en 44 px de alto por fila, el
   mínimo tocable; lo que se va es el aire entre filas y el escalón del título.
   La sembrada queda como el vanilla. */
.ck-sched--compact { gap: var(--space-3); }
.ck-sched--compact .list { gap: var(--space-0-5); }
.ck-sched--compact .list-item { padding-block: var(--space-1-5); }
.ck-sched--compact .list-item-text { gap: 0; }
.ck-sched--compact .list-item-headline { font-size: var(--font-size-body-md); line-height: 1.3; }
.ck-sched--compact .list-item-supporting { font-size: var(--font-size-caption); line-height: 1.3; }
.ck-time {
  flex: none; width: 62px;
  font-size: var(--font-size-body-sm);
  color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.ck-past { opacity: .4; }

.ck-nowline { display: flex; align-items: center; gap: var(--space-2); min-height: 44px; padding-inline: var(--space-1-5); }
.ck-nowline-dot { width: 7px; height: 7px; border-radius: var(--radius-full); background: var(--color-error); flex: none; }
.ck-nowline-rule { height: 1px; background: var(--color-error); flex: 1; }
.ck-nowline-t {
  font-size: var(--font-size-caption); font-weight: var(--font-weight-bold);
  color: var(--text-primary); font-variant-numeric: tabular-nums;
}
.ck-month-row {
  display: flex; justify-content: space-between; gap: var(--space-3);
  width: 100%; padding: var(--space-2) var(--space-3);
  border: 0; border-radius: var(--radius-md); background: transparent; cursor: pointer;
  font-family: var(--font-body); font-size: var(--font-size-body-md); color: var(--text-primary);
}
.ck-month-row:hover { background: var(--color-surface-container-high); }
.ck-month-row span:last-child { color: var(--text-muted); font-size: var(--font-size-body-sm); }

.ck-daygroup-h {
  margin-top: var(--space-4); padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--color-outline-variant);
  font-size: var(--font-size-caption); font-weight: var(--font-weight-semibold);
  color: var(--text-muted);
}

/* ── Cabecera de clase ─────────────────────────────────────────────────────── */
.ck-main { padding: var(--space-4) var(--space-5) var(--space-3-5); min-width: 0; }
/* @ds-gap embassy#12 — .page-header trae margin-bottom: 24px, fuera de la
   escala de la pantalla: entre el titular y la sala van 16. */
.ck-main .page-header { margin-bottom: var(--space-4); }
.ck-head-text { min-width: 0; }
.ck-title { font-size: var(--font-size-display); font-weight: var(--font-weight-extrabold); line-height: 1.1; letter-spacing: -0.02em; }
.ck-title-t { color: var(--text-secondary); font-weight: var(--font-weight-medium); }
.ck-notoday { vertical-align: middle; margin-left: var(--space-2); }
.ck-sub { color: var(--text-secondary); font-size: var(--font-size-body-md); margin-top: var(--space-2); }
.ck-tags { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }

/* ── Búsqueda y filtros ────────────────────────────────────────────────────
   design.md §5: la búsqueda y lo que filtra comparten ancho; acá manda la
   composición sobre el tope de 720 de component-rules/search.md.
   El arquetipo search-results admite la barra grande como superficie de
   operación (guidelines/screen-patterns.md §2). */
.ck-search { flex: 1 1 auto; min-width: 0; max-width: none; }
/* @ds-gap embassy#14 — .search-bar tiene dos alturas fijas y nada en el medio:
   56 suelta y 40 dentro de .search-row. En una consola de mostrador la píldora
   de 56 pesa más que el titular; el diseño la fija en 46. */
.ck-search { height: 44px; padding-inline: var(--space-3-5); gap: var(--space-2-5); background: var(--color-surface); border-color: transparent; }
/* @ds-gap embassy#14 */
.ck-search .search-bar-icon { width: 18px; height: 18px; }
/* @ds-gap embassy#14 */
.ck-search .search-bar-icon svg { width: 18px; height: 18px; }
/* @ds-gap embassy#14 */
.ck-search .search-bar-input { font-size: var(--font-size-body-lg); }

/* @ds-gap embassy#7 — .search-bar-icon declara --color-on-surface: el ícono
   queda más fuerte que el texto tipeado. Tiene que ser nivel 3. */
.ck-search .search-bar-icon { color: var(--text-muted); }

/* La barra de la sala: dos filas (buscar + llegada, banderas) y una línea que
   la separa del plano. */
.ck-roombar {
  display: flex; flex-direction: column; gap: var(--space-5);
  padding-bottom: var(--space-5); margin-bottom: var(--space-1);
  /* La línea separa la barra del plano sin competir con los bordes de las
     baldosas: el mismo outline-variant, a menos de la mitad. */
  border-bottom: 1px solid color-mix(in srgb, var(--color-outline-variant) 40%, transparent);
}
.ck-roombar-row { display: flex; align-items: center; gap: var(--space-4); }
/* @ds-gap embassy#9 — .toolbar trae margin-bottom: 16px propio; adentro de la
   barra de la sala lo manda el gap, y ese margen corría la línea 16px abajo. */
.ck-toolbar { display: flex; align-items: center; gap: var(--space-4); min-height: 36px; margin-bottom: 0; }
.ck-arrival {
  flex: none;
  --seg-btn-label-color: var(--text-muted);
  --seg-btn-selected-label-color: var(--text-primary);
}
/* @ds-gap embassy#18 — .seg-btn-group mide 36 (pista de 3px, segmentos de 30):
   al lado de la búsqueda de 44 quedaba más bajo. El canvas pide pista de 4px y
   segmentos de 36, así la búsqueda y el toggle comparten alto. */
.ck-arrival { padding: var(--space-1); gap: var(--space-0-5); border: 0; }
/* @ds-gap embassy#18 */
.ck-arrival .seg-btn {
  height: 36px; padding: 0 var(--space-3-5); gap: var(--space-2);
  font-size: var(--font-size-body-md); font-weight: var(--font-weight-medium);
}
/* @ds-gap embassy#18 */
.ck-arrival .seg-btn[aria-selected="true"] { font-weight: var(--font-weight-bold); }
.ck-arrival .ck-chip-n { font-weight: var(--font-weight-extrabold); }
/* Cada vista lleva la muestra de la baldosa que deja ver: gris la que falta,
   verde la que ya entró. Y «Checked in» elegido se pinta del verde de la sala. */
.ck-arrive-key {
  flex: none; width: 12px; height: 12px; border-radius: var(--radius-sm); box-sizing: border-box;
  border: 1px solid var(--color-outline); background: var(--color-surface-container-high);
}
.ck-arrival [data-arrive="done"] .ck-arrive-key { border: 1.5px solid var(--color-success); background: var(--ck-done-surface); }
.ck-arrival [data-arrive="done"] {
  --seg-btn-selected-container-color: color-mix(in srgb, var(--color-success) 16%, var(--color-surface-container-high));
}
/* @ds-gap embassy#9 — .result-count trae margin-bottom: 14px, un valor fuera de
   la escala, escrito en el propio DS. Adentro de una fila de toolbar descentra
   el conteo respecto de los chips. */
.ck-toolbar-end { margin-left: auto; display: flex; align-items: center; gap: var(--space-3); }
/* @ds-gap embassy#9 — y el conteo es contexto del resultado, no una etiqueta de
   control: va un escalón abajo de los chips, en body-sm. */
.ck-toolbar-end .result-count { margin: 0; font-size: var(--font-size-body-sm); }

/* @ds-gap embassy#5 — .chip usa --font-size-body-lg (14) donde la base de UI es
   body-md (13,5): el filtro es el texto más grande de la pantalla.
   @ds-gap embassy#6 — .chip declara --color-on-surface también apagado, así que
   el filtro inactivo pesa igual que el activo. Un control tocable no baja del
   nivel 2 (muted se lee deshabilitado); el contador, que sí es pasivo, baja uno. */
.ck-filters .chip { font-size: var(--font-size-body-md); }
/* @ds-gap embassy#6 */
.ck-filters .chip[aria-pressed="false"] { color: var(--text-secondary); }
/* @ds-gap embassy#6 */
.ck-filters .chip[aria-pressed="false"] .ck-chip-n { color: var(--text-muted); }
/* El contador va pegado a su etiqueta y en el mismo cuerpo: separado 16px y dos
   escalones más chico parecía otro dato, no el conteo de ese filtro. */
.ck-chip-n { margin-left: 0; font-size: var(--font-size-body-md); font-variant-numeric: tabular-nums; color: inherit; }

/* Chip de bandera: el .chip del DS con la muestra del color de su caja, así el
   filtro también explica el mapa. */
.ck-flagchips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
/* @ds-gap embassy#5 — .chip es píldora (radius-full). El filtro de bandera
   lleva la esquina de la baldosa que explica, radio 8, como en el canvas. */
.ck-fchip { height: 36px; border-radius: var(--radius-md); background: var(--color-surface-container); padding-inline: var(--space-2-5) var(--space-3); font-size: var(--font-size-body-md); font-weight: var(--font-weight-semibold); color: var(--text-primary); }
/* La muestra del chip es el ícono de la bandera (.ck-flag-ico, más abajo). */
.ck-fchip-n { font-weight: var(--font-weight-extrabold); font-variant-numeric: tabular-nums; }
/* El chip se pinta como la baldosa que filtra: borde y fondo de su bandera.
   Elegido, lleva el anillo de la baldosa seleccionada. */
.ck-fchip { border: 1.5px solid var(--flag); background: var(--flag-surface); }
.ck-fchip:hover:not(:disabled) { background: var(--flag-surface-hover); }
.ck-fchip[aria-pressed="true"] { color: var(--text-primary); border-color: var(--flag); background: var(--flag-surface-sel); box-shadow: var(--flag-ring); }
.ck-fchip:disabled { opacity: .45; cursor: default; }
.ck-fchip:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }

/* ── Resultados ────────────────────────────────────────────────────────────── */
.ck-results { margin-top: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.ck-result {
  display: grid; align-items: center; gap: var(--space-3);
  grid-template-columns: auto minmax(0,1fr) auto auto;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-outline-variant);
  border-radius: var(--radius-md); background: var(--color-surface-container); cursor: pointer;
}
.ck-result-active { background: color-mix(in srgb, var(--flag, var(--color-secondary)) 12%, var(--color-surface-container)); border-color: var(--flag, var(--color-secondary)); }
.ck-result-name { display: block; font-size: var(--font-size-body-lg); font-weight: var(--font-weight-semibold); color: var(--text-primary); }
.ck-result-cue { display: block; font-size: var(--font-size-body-sm); color: var(--text-secondary); }
.ck-result-bike { display: flex; align-items: baseline; gap: var(--space-2); font-variant-numeric: tabular-nums; }
.ck-result-bike-k { font-size: var(--font-size-caption); color: var(--text-muted); }
.ck-result-bike-v { font-size: var(--font-size-heading-xl); font-weight: var(--font-weight-bold); color: var(--text-primary); line-height: 1; }
/* Un punto del color de la bandera alcanza para clasificar la fila: el ícono en
   círculo competía con el número de bici, que es el dato que se dice en voz alta. */
.ck-result-dot { width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--flag, var(--color-outline)); flex: none; }
.ck-kbd { font-size: var(--font-size-badge); color: var(--text-muted); margin-left: var(--space-1); }
.ck-hint { margin-top: var(--space-2); font-size: var(--font-size-caption); color: var(--text-muted); }

/* ── Plano de sala ─────────────────────────────────────────────────────────
   @ds-gap embassy#8 — Embassy no tiene mapa de asientos. Se compone con tokens
   y se declara: 60 baldosas con estado (libre · hold · fuera de servicio ·
   ingresado), bandera de color + ícono y adyacencia entre dos bicis. */
.ck-room {
  background: var(--color-surface-container);
  border-radius: var(--radius-lg);
  padding: var(--space-3-5) var(--space-4);
  overflow-x: auto; align-self: start; margin-top: 0;
}
/* La instructora: una etiqueta sobre la primera fila, que marca el frente de
   la sala. Celeste para que resalte sobre el panel, y sin borde ni sombra
   para que no parezca un botón. */
.ck-stage {
  display: flex; align-items: center; justify-content: center; gap: var(--space-2-5);
  width: max-content; margin: var(--space-4) auto;
  height: 40px; padding: 0 var(--space-4) 0 var(--space-1);
  border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--color-secondary-container) 70%, var(--color-surface-container));
}
.ck-stage-av {
  width: 32px; height: 32px; display: grid; place-items: center; flex: none;
  border-radius: var(--radius-full); background: var(--color-primary); color: var(--color-on-primary);
  font-size: var(--font-size-body-sm); font-weight: var(--font-weight-extrabold);
}
.ck-stage-name { font-size: var(--font-size-body-lg); line-height: 1; font-weight: var(--font-weight-extrabold); color: var(--text-primary); }
.ck-stage-role { font-size: var(--font-size-body-sm); line-height: 1; font-weight: var(--font-weight-semibold); color: var(--text-secondary); }
/* La sala tiene 60 asientos en filas de 8·10·12·12·10·8. La baldosa NO se
   divide por la fila más larga: exprimida a 81px el apellido se corta
   («Sandbe…»), y en un mostrador el apellido es el dato. La baldosa queda en
   96px cuando el canvas da, y nunca por debajo de 84, que es lo que mide el
   apellido más largo del padrón («Sandberg» en semibold, 69px) más su padding.
   Las filas NO envuelven: una fila de la sala que continúa abajo deja una
   baldosa suelta que se lee como una fila de una persona, y eso es información
   falsa sobre la planta. Si ni con 84 entra, la sala se scrollea en horizontal
   —es un plano, no una lista— y eso ya lo resuelve el overflow de .ck-room. */
.ck-rows {
  display: flex; flex-direction: column; gap: var(--space-2-5);
  --ck-cols: 12;
  --ck-gap: var(--space-2);
  --ck-tile: clamp(84px, calc((100% - (var(--ck-cols) - 1) * var(--ck-gap)) / var(--ck-cols)), 96px);
}
.ck-row { display: flex; flex-wrap: nowrap; justify-content: center; gap: var(--ck-gap); }

/* El asiento: la baldosa y su botón de check-in de un click, uno encima del otro. */
.ck-seat { position: relative; flex: none; width: var(--ck-tile, 96px); min-width: 0; display: flex; }
/* Número arriba; nombre, apellido y lo que hay que decirle, abajo. El nombre
   es lo que se dice en la puerta ("Welcome, Daniel"), el apellido desambigua. */
.ck-bike {
  position: relative; flex: 1 1 auto; width: 100%; min-width: 0; height: var(--ck-tile-h, 86px);
  display: flex; flex-direction: column; gap: 1px; overflow: hidden;
  padding: 7px var(--space-2); border-radius: var(--space-2-5);
  border: 1px solid var(--color-outline-variant);
  background: var(--color-surface-container-high);
  color: var(--text-secondary); font-family: var(--font-body);
  text-align: left; cursor: pointer;
  transition: background var(--duration-fast) var(--ease-default),
              border-color var(--duration-fast) var(--ease-default),
              transform var(--duration-fast) var(--ease-default);
}
.ck-bike:hover { transform: translateY(-1px); }
.ck-bike:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.ck-bike-n {
  height: var(--ck-num-h, 22px); flex: none; display: flex; align-items: center;
  font-size: var(--font-size-caption); font-weight: var(--font-weight-semibold);
  color: var(--text-muted); line-height: 1; font-variant-numeric: tabular-nums;
}
.ck-bike-name {
  font-size: var(--font-size-body-lg); font-weight: var(--font-weight-medium);
  color: var(--text-primary); line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ck-bike-last {
  font-size: var(--font-size-body-sm); font-weight: var(--font-weight-medium); flex: none;
  color: var(--text-secondary); line-height: 1.1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Lo que se sabe de la persona de un vistazo, al pie de la caja: el conteo
   (o «Intro 2/3», en el color de la bandera). ClassPass va arriba, al lado
   del número, donde sobra lugar: al pie le comía el conteo. */
.ck-bike-meta {
  margin-top: auto; flex: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--font-size-badge); font-weight: var(--font-weight-semibold);
  color: var(--text-muted); line-height: 1.2; font-variant-numeric: tabular-nums;
}
.ck-f-intro .ck-bike-meta { color: var(--flag-text); font-weight: var(--font-weight-bold); }
.ck-bike-cp {
  flex: none; margin-left: var(--space-1); padding: 0 var(--space-1); border-radius: var(--radius-sm);
  font-size: var(--font-size-badge); font-weight: var(--font-weight-extrabold); letter-spacing: .02em; line-height: 14px;
  background: var(--color-on-surface); color: var(--color-surface);
}
.ck-bike-tag {
  margin-top: var(--space-0-5); flex: none;
  font-size: var(--font-size-badge); font-weight: var(--font-weight-bold);
  color: var(--flag-text, var(--flag)); line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Libre, hold y fuera de servicio: la palabra va pegada al número, sin la fila
   de 22 que reserva lugar para el botón de check-in. */
.ck-bike-free, .ck-bike-hold, .ck-bike-unav { gap: var(--space-1); }
.ck-bike-free .ck-bike-n, .ck-bike-hold .ck-bike-n, .ck-bike-unav .ck-bike-n { height: auto; }
.ck-bike-q { color: var(--text-secondary); font-weight: var(--font-weight-medium); }
/* Un canal, un significado: el peso dice QUÉ FALTA, no qué está marcado. Quien
   todavía no hizo check-in va en semibold; en cuanto entra, el nombre baja a
   regular y el trabajo pendiente queda solo en la sala. El flag no se suma al
   peso — lo dice el borde y el ícono — porque si todo lo pendiente y todo lo
   marcado pesan igual, el peso deja de decir nada. */
.ck-bike:not(.ck-bike-done):not(.ck-bike-free):not(.ck-bike-hold):not(.ck-bike-unav) .ck-bike-name {
  font-weight: var(--font-weight-extrabold);
}
.ck-bike-free { border-style: dashed; background: transparent; }
.ck-bike-hold { border-style: dashed; border-color: var(--color-outline); background: transparent; }
.ck-bike-unav { background: repeating-linear-gradient(135deg, var(--color-surface-container-high) 0 5px, var(--color-surface-container) 5px 10px); }
/* La baldosa dice su condición con fondo y borde: pendiente con bandera toma
   el color de la bandera, pendiente sin bandera queda gris, y quien ya entró
   pasa a verde con el tilde lleno. El verde significa UNA cosa: ya entró. Por
   eso la bandera «1st with» dejó el verde y es turquesa (ver .ck-f-instructor).
   La etiqueta de la bandera se queda, en su color, por si hay que decirle algo
   igual. */
.ck-bike-done .ck-bike-name { color: var(--text-primary); }

.ck-bike-dim { opacity: .3; }
.ck-bike-check {
  position: absolute; top: var(--space-1); right: var(--space-1-5); width: 24px; height: 24px; padding: 5px;
  border-radius: var(--radius-full); background: var(--color-success); color: var(--color-on-success);
}


/* ── Check-in desde la caja ─────────────────────────────────────────────
   Con el mouse encima, una franja «✓ Check in» sube desde el pie y tapa el
   conteo; al tocarla, el verde inunda la caja desde abajo y se asienta en el
   verde de «ya entró». Deshacer sigue en el snackbar. Es la excepción
   elegida a «nada se anima como respuesta a una acción» (README,
   Movimiento): entrar sin abrir el panel tiene que sentirse. */
.ck-qc {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; height: 26px;
  display: flex; align-items: center; justify-content: center; gap: 5px;
  border: 0; border-radius: 0 0 var(--space-2-5) var(--space-2-5);
  background: var(--color-success); color: var(--color-on-success);
  font: var(--font-weight-bold) var(--font-size-badge)/1 var(--font-body); cursor: pointer;
  clip-path: inset(100% 0 0 0);
  transition: clip-path var(--duration-normal) var(--ease-expressive), background var(--duration-fast) var(--ease-default);
}
.ck-qc svg { width: 12px; height: 12px; }
.ck-seat-quick:hover .ck-qc { clip-path: inset(0 0 0 0); }
.ck-qc:hover { background: var(--color-success-hover); }
.ck-seat-quick:hover .ck-bike { transform: none; }
/* Sin mouse (tablet) no hay hover que la muestre: queda a la vista, chica, en
   la esquina de abajo, sin tapar el conteo ni comerse el toque que abre el
   panel. */
@media (hover: none) {
  .ck-seat-quick .ck-qc {
    left: auto; right: var(--space-1); bottom: var(--space-1); width: 24px; height: 24px;
    border-radius: var(--radius-full); clip-path: none;
  }
  .ck-seat-quick .ck-qc span { display: none; }
  .ck-seat-quick .ck-bike-meta { padding-right: 26px; }
}

.ck-flood {
  position: absolute; inset: 0; pointer-events: none; border-radius: var(--space-2-5);
  background: color-mix(in srgb, var(--color-success) 55%, transparent);
  animation: ck-flood var(--duration-slow) var(--ease-default) forwards;
}
@keyframes ck-flood {
  0%   { clip-path: circle(0% at 50% 100%); opacity: 1; }
  55%  { clip-path: circle(150% at 50% 100%); opacity: 1; }
  100% { clip-path: circle(150% at 50% 100%); opacity: 0; }
}
.ck-seat-flash .ck-bike-check { animation: ck-pop var(--duration-medium) var(--ease-expressive) var(--duration-fast) both; }
@keyframes ck-pop {
  0% { transform: scale(.2) rotate(-25deg); opacity: 0; }
  70% { transform: scale(1.25) rotate(0); opacity: 1; }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .ck-qc { transition: none; }
  .ck-flood { animation-duration: 1ms; }
  .ck-seat-flash .ck-bike-check { animation: none; }
}

/* El ícono de la bandera: el mismo en la caja y en el chip, así el chip
   funciona de referencia del mapa. Círculo blanco con el trazo del color de
   la bandera, como en el diseño de Tomás. */
.ck-flag-ico {
  display: inline-grid; place-items: center; flex: none; box-sizing: border-box;
  width: 16px; height: 16px; border-radius: var(--radius-full);
  border: 1px solid var(--flag); background: var(--color-surface-container); color: var(--flag-text, var(--flag));
}
.ck-flag-ico svg { width: 10px; height: 10px; }
/* En la caja va arriba a la derecha, donde después aparece el tilde. */
.ck-bike-flagico { position: absolute; top: var(--space-1); right: var(--space-1); width: 22px; height: 22px; }
.ck-bike-flagico svg { width: 12px; height: 12px; }

/* Bandera: color + ícono, nunca color solo (F6). El mismo color viaja al sheet. */
/* Rojo: la oferta de bienvenida es la conversión que no se puede perder. */
.ck-f-intro      { --flag: var(--color-error);     --flag-text: var(--color-error-text); }
.ck-f-primera    { --flag: var(--color-info);      --flag-text: var(--color-info-text); }
/* Turquesa: Embassy no tiene un tono propio entre info y success, así que se
   mezcla de los dos. Queda lejos del verde del check-in y del azul de «First
   time». */
.ck-f-instructor {
  --flag: color-mix(in oklch, var(--color-info) 40%, var(--color-success));
  --flag-text: color-mix(in oklch, var(--color-info-text) 40%, var(--color-success-text));
}
.ck-f-hito       { --flag: var(--color-secondary); --flag-text: var(--color-secondary-text); }
.ck-f-alerta     { --flag: var(--color-warning);   --flag-text: var(--color-warning-text); }
.ck-f-none       { --flag: var(--color-secondary); }
/* La superficie de la bandera, una sola vez: la caja y el chip que la filtra
   la toman de acá (se calcula donde vive --flag). */
.ck-f-intro, .ck-f-primera, .ck-f-instructor, .ck-f-hito, .ck-f-alerta, .ck-f-none {
  --flag-surface: color-mix(in srgb, var(--flag) 12%, var(--color-surface-container-high));
  --flag-surface-hover: color-mix(in srgb, var(--flag) 20%, var(--color-surface-container-high));
  --flag-surface-sel: color-mix(in srgb, var(--flag) 16%, var(--color-surface-container-high));
  --flag-ring: 0 0 0 3px color-mix(in srgb, var(--flag) 28%, transparent);
}
/* Con bandera la baldosa entera toma su color; sin bandera queda gris. */
.ck-bike[data-flag] { border-width: 1.5px; border-color: var(--flag); background: var(--flag-surface); }

.ck-bike-sel { box-shadow: 0 0 0 3px color-mix(in srgb, var(--sel, var(--color-secondary)) 28%, transparent); border-color: var(--sel, var(--color-secondary)); }
.ck-bike-sel[data-flag] { --sel: var(--flag); background: var(--flag-surface-sel); }
.ck-bike-sel:not([data-flag]) { background: var(--color-secondary-container); }
.ck-bike-sel:not([data-flag]) .ck-bike-name, .ck-bike-sel:not([data-flag]) .ck-bike-n { color: var(--color-on-secondary-container); }

/* Ya entró: gana sobre la bandera y sobre la selección. */
.ck-bike.ck-bike-done, .ck-bike.ck-bike-done[data-flag] {
  --sel: var(--color-success);
  border-width: 1.5px; border-color: var(--color-success);
  background: var(--ck-done-surface);
}
.ck-bike.ck-bike-done.ck-bike-sel { background: color-mix(in srgb, var(--color-success) 20%, var(--color-surface-container-high)); }
.ck-bike.ck-bike-done.ck-bike-sel .ck-bike-name, .ck-bike.ck-bike-done.ck-bike-sel .ck-bike-n { color: inherit; }

.ck-pair {
  position: relative; display: flex; gap: var(--space-2);
  flex: none; width: calc(var(--ck-tile, 96px) * 2 + var(--ck-gap, 6px));
  padding: 3px; margin: -4px;
  border: 1px dashed var(--color-tertiary); border-radius: var(--radius-lg);
}
.ck-pair .ck-seat { flex: 1 1 0; width: auto; }
/* El contorno punteado alcanza para decir que vinieron juntas; el rótulo
   «Together» no se leía y chocaba con la fila de abajo. */

/* Leyenda: dos sistemas, dos grupos rotulados (Miller) */
.ck-legends { display: flex; flex-wrap: wrap; gap: var(--space-5) var(--space-8); margin-top: var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--color-outline-variant); }
/* Un solo rótulo en versalita en toda la pantalla, y clasifica grupos: el de la
   leyenda y el de las secciones del sheet son el mismo rol (COMPOSICION regla 1). */
.ck-cap {
  font-size: var(--font-size-badge); font-weight: var(--font-weight-semibold);
  letter-spacing: var(--letter-spacing-wide, .04em); text-transform: uppercase;
  color: var(--text-muted);
}
.ck-legend-t { margin-bottom: var(--space-2); }
.ck-legend { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); }
.ck-legend-item { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--font-size-caption); color: var(--text-secondary); }
.ck-legend-key { width: 14px; height: 14px; border-radius: var(--radius-sm); border: 2px solid var(--flag, var(--color-outline-variant)); color: var(--flag); display: grid; place-items: center; flex: none; }
.ck-legend-key svg { width: 9px; height: 9px; }
/* La bandera de la leyenda es un botón: filtra la sala por esa bandera. */
.ck-legend-btn {
  font: inherit; background: none; cursor: pointer;
  padding: var(--space-1) var(--space-2); margin: calc(-1 * var(--space-1)) calc(-1 * var(--space-2));
  border: 1px solid transparent; border-radius: var(--radius-full);
  transition: background var(--duration-fast) var(--ease-default), border-color var(--duration-fast) var(--ease-default);
}
.ck-legend-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--flag) 10%, transparent); }
.ck-legend-btn:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.ck-legend-btn.is-on {
  background: color-mix(in srgb, var(--flag) 14%, transparent); border-color: var(--flag);
  color: var(--text-primary); font-weight: var(--font-weight-semibold);
}
.ck-legend-btn:disabled { cursor: default; opacity: .45; }
.ck-legend-n { font-variant-numeric: tabular-nums; color: var(--text-muted); font-weight: var(--font-weight-semibold); }
.ck-legend-key-dashed { border-style: dashed; }

/* Skeleton con la silueta de destino: la sala, no cuatro barras (E3) */
.ck-sk-row { display: flex; flex-wrap: nowrap; justify-content: center; gap: var(--space-2); margin-bottom: var(--space-3); }
.ck-sk-tile { width: var(--ck-tile, 96px); height: 68px; border-radius: var(--radius-md); }

/* ── Ficha de persona (sheet) ──────────────────────────────────────────────── */
/* La identidad operativa es el número de bici: es lo que se dice en voz alta.
   Va en su propia caja, con el rótulo arriba y el estado abajo, para que el
   número sea lo primero que se lee y el badge no compita en la misma línea. */
.ck-id {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); margin-bottom: var(--space-5);
  padding: var(--space-4) var(--space-5);
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.ck-id-main { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.ck-id-v {
  font-size: var(--font-size-display); font-weight: var(--font-weight-bold);
  color: var(--text-primary); line-height: 1; font-variant-numeric: tabular-nums;
}
.ck-section + .ck-section { margin-top: var(--space-6); }
.ck-section-t { margin-bottom: var(--space-2); }
/* El grupo de pares es una caja, no filas flotando sobre el fondo del sheet:
   superficie + borde, y declara su contexto para que la lista de adentro tome
   ese mismo fondo sola (card.css declara --ctx-surface igual). */
.ck-group {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.ck-group-pad { padding: var(--space-4); }
.ck-k { color: var(--text-muted); font-weight: var(--font-weight-regular); }
.ck-v { color: var(--text-primary); font-weight: var(--font-weight-semibold); font-variant-numeric: tabular-nums; }
.ck-note { font-size: var(--font-size-body-md); color: var(--text-secondary); margin-bottom: var(--space-3); }
.ck-note strong { color: var(--text-primary); }
.ck-script { color: var(--text-primary); font-size: var(--font-size-heading-sm); font-weight: var(--font-weight-medium); line-height: 1.45; }
.ck-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-5); }
.ck-brief-icon { display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--radius-full); border: 1px solid var(--flag); color: var(--flag); flex: none; }
.ck-brief-icon svg { width: 14px; height: 14px; }
.ck-brief-list { display: flex; flex-direction: column; gap: var(--space-2); list-style: none; margin: 0; padding: 0; }
.ck-brief-row { width: 100%; text-align: left; }
.ck-list-item { cursor: pointer; }
.ck-list-item:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.ck-sheet-flag { display: flex; align-items: center; gap: var(--space-2); color: var(--flag); margin-bottom: var(--space-3); }
.ck-sheet-flag-icon { display: grid; place-items: center; width: 24px; height: 24px; border-radius: var(--radius-full); border: 1px solid var(--flag); flex: none; }
.ck-sheet-flag-icon svg { width: 13px; height: 13px; }
.ck-sheet-flag-t { font-size: var(--font-size-body-md); font-weight: var(--font-weight-semibold); }
.ck-sheet-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); }

/* ── Mover a alguien ───────────────────────────────────────────────────────
   De lugar se elige en la sala misma; de clase, en la ficha. */
.ck-move-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.ck-move-actions svg { flex: none; }
.ck-move-error { margin-bottom: var(--space-4); }
/* @ds-gap embassy#3 — list-item tiene radio 0 y sangra de punta a punta: dentro
   de la ficha cada clase es una opción suelta, como en el riel. */
.ck-move-row { width: 100%; text-align: left; border-radius: var(--radius-md); min-height: 52px; }
.ck-move-row.is-selected { background: var(--color-secondary-container); color: var(--color-on-secondary-container); }
.ck-move-row:disabled { opacity: .45; cursor: default; }
.ck-move-row:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.ck-move-row .list-item-headline { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); font-weight: var(--font-weight-semibold); }
.ck-move-here { flex: none; }
.ck-pickbar { margin-bottom: var(--space-4); }
/* Eligiendo lugar: lo libre invita (el borde punteado pasa a sólido y con
   acento), la persona que se mueve queda marcada, y lo que no se puede
   elegir se apaga. */
.ck-rows-pick .ck-bike-free { border-style: solid; border-color: var(--color-secondary); }
.ck-rows-pick .ck-bike:disabled { cursor: not-allowed; }
.ck-results-t { margin-bottom: 0; }

/* ── Estados de pantalla ───────────────────────────────────────────────────── */
.ck-state { padding-block: var(--space-10); }

/* @ds-gap embassy#11 — el bloque de puntero grueso de components.css levanta
   botones, seg-btn y toolbar-btn a 44px, y deja afuera tres controles que en un
   iPad de mostrador se tocan igual: el chip (32), el input de la search-bar (la
   píldora mide 56 pero el área que enfoca es el input, de 20) y el link del
   breadcrumb (20). Mismo media query que el del DS, para que entren juntos. */
@media (max-width: 768px), (pointer: coarse) {
  /* @ds-gap embassy#11 */
  .ck-filters .chip { min-height: 44px; }
  /* El bloque del DS levanta el alto de los botones, no el ancho: un btn-text
     de solo ícono queda en 40 de ancho. */
  .ck-nudge { min-width: 44px; }
  /* @ds-gap embassy#11 */
  .ck-search .search-bar-input { min-height: 44px; }
  /* @ds-gap embassy#11 */
  .ck-crumbs .breadcrumb-link { display: inline-flex; align-items: center; min-height: 44px; }
}

/* Lo que se desplaza de costado avisa que sigue: el borde que tiene más
   contenido detrás se desvanece (lo marca useEdgeFade). La máscara usa solo
   el alfa, así que el token de color da igual mientras sea opaco. */
.ck-edge-fade { --ck-fade: var(--space-8); }
.ck-edge-fade[data-fade-end="true"] {
  mask-image: linear-gradient(to right, var(--color-on-surface) calc(100% - var(--ck-fade)), transparent);
}
.ck-edge-fade[data-fade-start="true"] {
  mask-image: linear-gradient(to right, transparent, var(--color-on-surface) var(--ck-fade));
}
.ck-edge-fade[data-fade-start="true"][data-fade-end="true"] {
  mask-image: linear-gradient(to right, transparent, var(--color-on-surface) var(--ck-fade),
    var(--color-on-surface) calc(100% - var(--ck-fade)), transparent);
}

/* ── Mobile: estructura propia, no la misma grilla a otra escala (D7) ───────
   El riel no cabe al lado, así que sale del flujo y se abre como sheet desde
   abajo con el botón de clase; la sala scrollea por filas dentro de su panel y
   el check-in se hace desde la fila del resultado, sin pasar por el mapa. */
.ck-railbtn { display: none; }
.ck-rail-head { display: none; }
.ck-railscrim { display: none; }

@media (max-width: 1023px) {
  .ck-main { padding: var(--space-4); }
  /* El vanilla decidía esto con window.innerWidth < 1024 al pintar la cabecera.
     Medir el viewport en el render es exactamente lo que no se puede hacer
     cuando el HTML se genera en build: la misma decisión, en CSS. */
  .ck-sub-date { display: none; }
  .ck-title { font-size: var(--font-size-display); }
  .ck-room { padding-inline: var(--space-3); }

  .ck-railbtn { display: inline-flex; gap: var(--space-2); margin-bottom: var(--space-4); }
  /* @ds-gap embassy#12 — page-header no envuelve: con un titular largo y una
     acción al lado, en un teléfono la acción exprime al título hasta 19
     caracteres por línea (D16). La acción baja debajo del titular. */
  .ck-main .page-header { flex-wrap: wrap; }
  .ck-head-text { flex: 1 1 100%; }
  /* Lo que se desplaza es la planta, no el panel: la búsqueda y las banderas
     quedan quietas arriba. Las filas siguen centradas entre sí —la forma de
     la sala (8·10·12·12·10·8) es información—. La pista mide lo que el panel o
     lo que la fila más larga, lo que sea mayor: si la planta entra va al
     centro, y si no arranca en el borde y se desplaza, sin nada cortado a la
     izquierda (safe center no lo resolvía dentro de un scroller). */
  .ck-room { overflow-x: visible; }
  .ck-rows {
    display: grid; grid-template-columns: minmax(max-content, 1fr); justify-items: center;
    overflow-x: auto; overscroll-behavior-x: contain;
    margin-inline: calc(-1 * var(--space-3)); padding: 0 var(--space-3) var(--space-1);
  }
  .ck-row { justify-content: center; }
  .ck-railscrim {
    display: block; position: fixed; inset: 0; z-index: 39;
    background: var(--color-scrim, rgb(0 0 0 / .32));
  }
  .ck-rail {
    position: fixed; inset: auto 0 0 0; z-index: 40;
    max-height: 78vh; height: auto; border: 0;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--shadow-lg);
    transform: translateY(102%);
    transition: transform var(--duration-sheet) var(--ease-emphasized);
  }
  .ck-rail.is-open { transform: none; }
  /* Cerrada, la hoja sale también del orden de tabulación: correrla fuera de
     la pantalla la escondía a la vista, no al teclado. La visibilidad cambia
     al final del deslizamiento, no al principio. */
  .ck-rail:not(.is-open) { visibility: hidden; }
  .ck-rail { transition: transform var(--duration-sheet) var(--ease-emphasized), visibility 0s linear var(--duration-sheet); }
  .ck-rail.is-open { transition: transform var(--duration-sheet) var(--ease-emphasized), visibility 0s; }
  .ck-rail-head {
    display: flex; align-items: center; justify-content: space-between;
    margin: calc(-1 * var(--space-1)) 0 var(--space-1);
  }
  .ck-rail-title { font-size: var(--font-size-heading-sm); font-weight: var(--font-weight-bold); color: var(--text-primary); }
  .ck-rail-close { width: 44px; height: 44px; margin-right: calc(-1 * var(--space-2)); }
  /* En el teléfono el riel es una hoja pegada al borde de abajo: el
     calendario, que Embassy abre flotando debajo del campo, se salía de la
     pantalla en cuanto el alto no alcanzaba. Adentro de la hoja va en el
     flujo: empuja la agenda, que achica su scroll, y nada queda afuera. Las
     flechas miden lo mismo que el campo (44 px), así que siguen alineadas
     con él arriba. */
  .ck-datebar { align-items: flex-start; }
  #ck-dpanel { position: static; box-shadow: none; }
  .ck-sched { min-height: 0; }
  /* Y si ni así entra (un teléfono apaisado), la hoja entera se desplaza. */
  .ck-rail { overflow-y: auto; overscroll-behavior: contain; }
}
/* En el teléfono el tema lo pone el sistema: el selector del topbar le
   quitaba lugar al rastro, que es lo que se lee. */
/* Y el doble toque tampoco agranda: en un mostrador se toca rápido y seguido. */
html { touch-action: manipulation; }

@media (max-width: 768px) {
  .ck-theme { display: none; }

  /* En el teléfono la búsqueda ocupa su fila y la vista de llegada baja a la
     siguiente, a todo el ancho; las banderas se desplazan de costado. */
  .ck-roombar-row { flex-wrap: wrap; }
  .ck-arrival { flex: 1 1 100%; }
  .ck-arrival .seg-btn { flex: 1 1 0; min-width: 0; padding-inline: var(--space-2); gap: var(--space-1-5); }
  .ck-flagchips { flex-wrap: nowrap; overflow-x: auto; }
  .ck-fchip { flex: none; }

  /* La ficha: Embassy la mide en 100vh, que en Safari del teléfono es más
     alto que lo visible, y el pie —el Check in— quedaba debajo de la barra
     del navegador. Se mide contra lo visible (dvh), y la acción sube debajo
     del nombre, a todo el ancho: es lo que se viene a tocar. */
  #ck-sheet { height: 100dvh; padding-bottom: env(safe-area-inset-bottom); }
  #ck-sheet .sheet-footer { order: 1; margin-top: 0; padding: var(--space-4) var(--space-6) 0; }
  #ck-sheet .sheet-body { order: 2; padding-top: var(--space-4); padding-bottom: var(--space-6); }
  #ck-sheet .ck-sheet-actions { justify-content: stretch; }
  #ck-sheet .ck-sheet-actions > button { flex: 1 1 100%; }
}
/* En un teléfono la ficha de Embassy (75vw) deja una franja de 100px de la
   sala detrás: no alcanza para tocarla con intención y sí para tocarla sin
   querer. La ficha toma el ancho entero y se cierra con la X o con Escape.
   @ds-gap embassy#23 — sheet-content-right no tiene variante de ancho
   completo para pantallas angostas. */
@media (max-width: 560px) {
  #ck-sheet { width: 100vw; max-width: none; border-left-width: 0; }
}
/* ══ Movimiento ══════════════════════════════════════════════════════════
   Toda esta capa existe por un solo motivo: la pantalla se prende y se apaga
   con `hidden`, y `display:none` no tiene fotograma de salida. Sin
   @starting-style y transition-behavior:allow-discrete, el deslizamiento de
   500ms que Embassy ya declara en .sheet-content nunca corre —medido: un
   único valor de transform en 600ms— y todo lo que se esconde desaparece en
   seco.

   La regla de la pantalla también manda acá: nada se mete entre quien atiende
   y la próxima persona. El ingreso se confirma en el fotograma siguiente; lo
   que se anima es la aparición y la salida de las superficies, nunca la
   respuesta a una acción. Por eso no hay stagger, ni resortes, ni contadores
   que giran.

   Los cuatro @ds-gap de esta sección son el mismo defecto de Embassy visto en
   cuatro lugares: el DS define el movimiento de entrada (o directamente lo
   apaga) y no tiene historia de salida. Es un solo issue upstream. */

/* Velo de la ficha. Embassy lo hace aparecer con `animation: fadeIn`, que es
   solo de entrada: al cerrarse no hay nada que correr y el panel entero se
   corta. Con una transición en su lugar hay fotograma inicial —y por lo tanto
   el deslizamiento de .sheet-content, que Embassy ya declara, por fin corre—
   y hay salida. El `display` sale más tarde que la opacidad a propósito: la
   ficha necesita los 500ms completos para terminar de salir.
   @ds-gap embassy#18 */
.sheet-overlay {
  animation: none;
  opacity: 1;
  transition: opacity var(--duration-normal) var(--ease-default),
              display var(--duration-sheet) var(--ease-default) allow-discrete;
}
.sheet-overlay[hidden] { opacity: 0; }
@starting-style {
  .sheet-overlay { opacity: 0; }
}

/* El fotograma del que sale la ficha. Sin esto el panel ya nace en su lugar
   final y la transición de Embassy no tiene nada que interpolar. */
@starting-style {
  .sheet-content-right.open { transform: translateX(100%); }
}

/* Panel de fecha: Embassy lo trae con animación de entrada y sin salida.
   @ds-gap embassy#19 */
.date-picker-panel {
  animation: none;
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--duration-fast) var(--ease-default),
              transform var(--duration-fast) var(--ease-default),
              display var(--duration-fast) var(--ease-default) allow-discrete;
}
.date-picker-panel[hidden] { opacity: 0; transform: translateY(-4px); }
@starting-style {
  .date-picker-panel { opacity: 0; transform: translateY(-4px); }
}

/* Snackbar: Embassy define el movimiento apilado —el que corresponde adentro
   de un viewport— y después, más abajo en el mismo archivo, lo apaga con
   `animation: none`. Acá se reponen sus propias declaraciones, tal cual:
   los keyframes apilados, sus tiempos y sus curvas. No hay movimiento nuevo.

   Van los `-stack-`, no los centrados: `.snackbar-viewport .snackbar` pone
   `transform: none`, así que snackbar-in —que lleva translateX(-50%)— correría
   el cartel media pantalla al entrar.
   @ds-gap embassy#20 */
.snackbar-viewport .snackbar {
  animation: snackbar-stack-in 250ms var(--ease-default) both;
}
.snackbar-viewport .snackbar.snackbar--exit {
  animation: snackbar-stack-out 200ms ease-in forwards;
  transition: none;
}

/* Los chips no tienen transición en el DS y el filtro es lo que más se toca
   de la barra. @ds-gap embassy#21 */
.ck-filters .chip {
  transition: background var(--duration-fast) var(--ease-default),
              border-color var(--duration-fast) var(--ease-default),
              color var(--duration-fast) var(--ease-default);
}

/* ── Superficies propias ─────────────────────────────────────────────── */

/* El velo del riel entra y sale con el riel al que pertenece, no antes. */
.ck-railscrim {
  opacity: 1;
  transition: opacity var(--duration-normal) var(--ease-default),
              display var(--duration-sheet) var(--ease-default) allow-discrete;
}
.ck-railscrim[hidden] { opacity: 0; }
@starting-style {
  .ck-railscrim { opacity: 0; }
}

/* Resultados y su pista: suben 4px al aparecer. Es la superficie que más se
   prende y se apaga —una vez por nombre tipeado—, así que va rápida. */
.ck-results, .ck-hint {
  opacity: 1;
  transform: translateY(0);
  transition: opacity var(--duration-fast) var(--ease-default),
              transform var(--duration-fast) var(--ease-default),
              display var(--duration-fast) var(--ease-default) allow-discrete;
}
.ck-results[hidden], .ck-hint[hidden] { opacity: 0; transform: translateY(-4px); }
@starting-style {
  .ck-results, .ck-hint { opacity: 0; transform: translateY(-4px); }
}

/* Los estados vacíos y la silueta de carga se cruzan con la sala en vez de
   reemplazarla de golpe. */
.ck-state, #ck-noresults, #ck-empty, #ck-error, #ck-skeleton, .ck-rows, .ck-legends {
  opacity: 1;
  transition: opacity var(--duration-normal) var(--ease-default),
              display var(--duration-normal) var(--ease-default) allow-discrete;
}
.ck-state[hidden], #ck-noresults[hidden], #ck-empty[hidden], #ck-error[hidden],
#ck-skeleton[hidden], .ck-rows[hidden], .ck-legends[hidden] { opacity: 0; }
@starting-style {
  .ck-state, #ck-noresults, #ck-empty, #ck-error, #ck-skeleton, .ck-rows, .ck-legends { opacity: 0; }
}

/* El atenuado del filtro ya existía; lo que faltaba era que la opacidad
   estuviera en la lista de transiciones del lugar. */
.ck-bike {
  transition: background var(--duration-fast) var(--ease-default),
              border-color var(--duration-fast) var(--ease-default),
              opacity var(--duration-fast) var(--ease-default),
              box-shadow var(--duration-fast) var(--ease-default),
              transform var(--duration-fast) var(--ease-default);
}

/* El tilde del ingreso entra desde chico. Es lo único que se mueve como
   respuesta a una acción, y dura 120ms: confirma, no hace esperar. La
   excepción es el check-in desde la caja (.ck-flood, arriba). */
.ck-bike-check {
  transition: opacity var(--duration-fast) var(--ease-default),
              transform var(--duration-fast) var(--ease-expressive);
}
@starting-style {
  .ck-bike-check { opacity: 0; transform: scale(.4); }
}

@media (max-width: 1023px) and (prefers-reduced-motion: reduce) {
  .ck-rail { transition: none; }
}

/* Con movimiento reducido se van los desplazamientos y las escalas —que son
   los que marean— y se quedan los cruces de opacidad, que son seguros y son
   lo que evita que la pantalla parpadee. El `display` sigue con allow-discrete
   para que la salida no se corte. */
@media (prefers-reduced-motion: reduce) {
  .ck-bike:hover { transform: none; }
  .ck-bike-check { transition: opacity var(--duration-fast) var(--ease-default); }
  .sheet-content { transition: none; }
  .date-picker-panel, .date-picker-panel[hidden],
  .ck-results, .ck-hint, .ck-results[hidden], .ck-hint[hidden] { transform: none; }
  .snackbar-viewport .snackbar { animation: none; }
  .snackbar-viewport .snackbar.snackbar--exit { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  @starting-style {
    .ck-bike-check { transform: none; }
    .date-picker-panel, .ck-results, .ck-hint { transform: none; }
    .sheet-content-right.open { transform: translateX(0); }
  }
}

/* ── Escala de escritorio, un escalón abajo ──────────────────────────────
   Con la escala del canvas la consola se leía grande para un mostrador que se
   mira a 50cm: todo baja un escalón del DS. Controles de 40 y 32 (siguen
   arriba del piso tocable de 32), cuerpo de 13,5 a 12,5 y baldosas de 76. */
@media (min-width: 1024px) {
  .ck-title { font-size: var(--font-size-heading-xl); }
  .ck-sub { font-size: var(--font-size-body-sm); margin-top: var(--space-1-5); }

  .ck-rail { gap: var(--space-3); }
  .ck-sched .list-item { min-height: 40px; padding-block: var(--space-1-5); }
  /* @ds-gap embassy#4 */
  .ck-sched .list-item-headline { font-size: var(--font-size-body-lg); }
  .ck-time { width: 58px; font-size: var(--font-size-caption); }
  .ck-nowline { min-height: 36px; }
  .ck-earlier-btn { min-height: 32px; font-size: var(--font-size-caption); }

  /* @ds-gap embassy#14 */
  .ck-search { height: 40px; }
  /* @ds-gap embassy#14 */
  .ck-search .search-bar-input { font-size: var(--font-size-body-md); }
  /* @ds-gap embassy#14 */
  .ck-search .search-bar-icon, .ck-search .search-bar-icon svg { width: 16px; height: 16px; }
  /* @ds-gap embassy#18 */
  .ck-arrival .seg-btn { height: 32px; padding: 0 var(--space-3); font-size: var(--font-size-body-sm); }

  .ck-roombar { gap: var(--space-4); padding-bottom: var(--space-6); margin-bottom: 0; }
  .ck-toolbar { min-height: 32px; }
  .ck-flagchips { gap: var(--space-2-5); }
  /* @ds-gap embassy#5 */
  .ck-fchip { height: 32px; gap: var(--space-1-5); padding-inline: var(--space-2) var(--space-2-5); font-size: var(--font-size-body-sm); }

  .ck-stage { height: 34px; gap: var(--space-2); margin: var(--space-6) auto var(--space-5); padding: 0 var(--space-3) 0 var(--space-1); }
  .ck-stage-av { width: 26px; height: 26px; font-size: var(--font-size-badge); }
  .ck-stage-name { font-size: var(--font-size-body-md); }
  .ck-stage-role { font-size: var(--font-size-caption); }

  .ck-rows { gap: var(--space-2); }
  .ck-bike { padding: 5px 7px; --ck-num-h: 18px; border-radius: var(--radius-md); }
  .ck-bike-n { font-size: var(--font-size-badge); }
  .ck-bike-name { font-size: var(--font-size-body-md); line-height: 1.2; }
  .ck-bike-last { font-size: var(--font-size-caption); line-height: 1.2; }
  .ck-bike-tag { margin-top: 1px; font-size: var(--font-size-badge); line-height: 1.2; }
  .ck-bike-q { font-size: var(--font-size-body-md); }
  .ck-bike-check { width: 22px; height: 22px; padding: 5px; top: var(--space-1); right: var(--space-1); }
}

/* ── La sala entra entera en la pantalla ──────────────────────────────────
   En escritorio el plano no se scrollea: la columna principal mide lo que
   queda debajo del topbar y las seis filas se reparten ese alto. La baldosa
   llega a 78 cuando hay lugar (lleva el pie con el conteo) y baja hasta 66
   en pantallas más bajas; por debajo de eso el texto ya no entra y recién
   ahí scrollea (adentro de la sala, nunca la página). */
@media (min-width: 1024px) {
  .ck-main { height: calc(100vh - var(--topbar-height)); display: flex; flex-direction: column; }
  #ck-ride { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  #ck-ride[hidden] { display: none; }
  .ck-room { flex: 0 1 auto; align-self: stretch; min-height: 0; display: flex; flex-direction: column; overflow: auto; }
  .ck-room > * { flex: none; }
  .ck-room > .ck-rows:not([hidden]) { display: flex; flex: 0 1 auto; min-height: 0; }
  .ck-row { flex: 0 1 78px; min-height: 72px; }
  .ck-bike > * { flex-shrink: 0; }
  .ck-row > .ck-seat, .ck-row > .ck-pair { height: auto; }
  .ck-seat { align-self: stretch; }
  .ck-bike { height: auto; }
}
/* Pantallas bajas (una notebook con el navegador abierto): el aire vertical
   baja otro escalón y la baldosa puede llegar a 66. */
@media (min-width: 1024px) and (max-height: 770px) {
  .ck-room { padding: var(--space-3) var(--space-4); }
  .ck-roombar { gap: var(--space-3); padding-bottom: var(--space-4); }
  .ck-stage { margin: var(--space-4) auto var(--space-3); height: 30px; }
  .ck-stage-av { width: 22px; height: 22px; }
  .ck-rows { gap: var(--space-1-5); }
  .ck-row { min-height: 66px; }
  .ck-bike { padding-block: var(--space-1); --ck-num-h: 18px; }
  .ck-bike-name, .ck-bike-last, .ck-bike-tag, .ck-bike-meta { line-height: 1.15; }
  .ck-bike { --ck-num-h: 16px; }
  .ck-bike-tag { margin-top: 0; }
  .ck-bike-check, .ck-bike-flagico { top: var(--space-0-5); }
}

/* ── La hoja impresa ──────────────────────────────────────────────────────
   «Print» manda a papel lo que el mostrador necesita a mano: el titular de la
   clase, el mapa entero y el briefing debajo. Todo lo que es para operar
   (riel, buscador, filtros, la franja de check-in, el panel, los avisos) no
   va. La sala se ve completa aunque haya un filtro puesto: es la planta.
   Todo entra en una A4 apaisada. El margen de la hoja es cero y el aire lo
   pone el body: así el navegador no tiene dónde imprimir su encabezado y su
   pie (fecha, título, URL), que le comían una fila a la sala. */
.ck-print-brief { display: none; }

@media print {
  @page { size: A4 landscape; margin: 0; }
  html, body { background: none; }
  body { padding: 8mm 10mm; }
  * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }

  .topbar, .ck-rail, .ck-railscrim, .ck-railbtn, .header-actions,
  .ck-pickbar, .ck-roombar, #ck-error, #ck-noresults, #ck-skeleton,
  .sheet-overlay, .snackbar, .ck-qc, .ck-flood, .ck-drag-ghost, .ck-moveconfirm, nextjs-portal { display: none !important; }

  .ck-shell { display: block; }
  .ck-main, #ck-ride, .ck-room { height: auto; overflow: visible; display: block; padding: 0; }
  .ck-main .page-header { margin-bottom: var(--space-2); }
  .ck-title { font-size: var(--font-size-heading-xl); }
  .ck-sub { margin-top: 0; font-size: var(--font-size-body-sm); }
  /* En papel la fecha va siempre: la hoja queda en el mostrador. */
  .ck-sub-date { display: inline; }
  .ck-room { border: 0; background: none; box-shadow: none; }
  .ck-stage { margin: 0 auto var(--space-1-5); height: 26px; }
  .ck-stage-av { width: 20px; height: 20px; }
  .ck-row { flex: none; }

  /* La planta entra en el ancho de la hoja: la baldosa se achica todo lo que
     haga falta en lugar de cortar la sala por el costado. */
  .ck-rows { --ck-tile: calc((100% - (var(--ck-cols) - 1) * var(--ck-gap)) / var(--ck-cols)); gap: var(--space-1); --ck-gap: var(--space-1-5); }
  .ck-room > .ck-rows:not([hidden]) { display: flex; }
  .ck-row { min-height: 0; break-inside: avoid; }
  .ck-bike { --ck-tile-h: auto; --ck-num-h: 16px; height: auto; min-height: 50px; padding: 3px var(--space-1-5); gap: 0; transform: none; box-shadow: none; }
  .ck-bike-dim, .ck-seat-dim { opacity: 1; filter: none; }

  .ck-print-brief { display: block; margin-top: var(--space-2-5); }
  .ck-print-brief-t { display: inline; font-size: var(--font-size-body-md); font-weight: var(--font-weight-semibold); color: var(--text-primary); }
  .ck-print-brief-d { display: inline; margin: 0 0 0 var(--space-2); font-size: var(--font-size-body-sm); color: var(--text-secondary); }
  .ck-print-brief-list { list-style: none; margin: 0; padding: 0; margin-top: var(--space-1-5); display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0 var(--space-3); }
  .ck-print-brief-row { display: flex; align-items: flex-start; gap: var(--space-2); padding: 2px 0; break-inside: avoid; font-size: var(--font-size-caption); line-height: 1.3; color: var(--text-primary); }
  .ck-print-brief-row .ck-brief-icon { width: 18px; height: 18px; }
  .ck-print-brief-row .ck-brief-icon svg { width: 10px; height: 10px; }
  .ck-print-brief-text { display: flex; flex-direction: column; min-width: 0; }
  .ck-print-brief-text > :first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ck-print-brief-cue { color: var(--text-secondary); }
  /* Con un briefing largo (más de tres filas), la sala cede alto: sin la
     línea de clases cada caja baja, y la hoja sigue siendo una. */
  #ck-ride:has(.ck-print-brief-row:nth-child(16)) .ck-bike { min-height: 0; }
  #ck-ride:has(.ck-print-brief-row:nth-child(16)) .ck-bike-meta { display: none; }
}

/* ── Arrastrar en la sala ─────────────────────────────────────────────────
   La caja que se levanta queda como hueco en su lugar y una copia sigue al
   puntero; los lugares libres se marcan como en «Change bike» y el destino
   bajo el puntero se resalta. El apretado largo en la tablet no selecciona
   texto ni abre el menú del sistema. */
.ck-bike { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.ck-bike[data-dragging] { opacity: 0.35; border-style: dashed; }
.ck-rows[data-dragging] .ck-bike-free { border-style: solid; border-color: var(--color-secondary); }
.ck-rows[data-dragging] .ck-qc { display: none; }
.ck-rows[data-dragging] .ck-bike:hover { transform: none; }
.ck-bike[data-drop] {
  outline: 2px solid var(--color-secondary); outline-offset: 2px;
  background: var(--color-secondary-container);
}
.ck-drag-ghost {
  position: fixed; left: 0; top: 0; z-index: 1000; margin: 0;
  pointer-events: none; cursor: grabbing; opacity: 0.95;
  box-shadow: var(--shadow-lg);
  rotate: -2deg; scale: 1.04; transition: none;
}
@media (prefers-reduced-motion: reduce) { .ck-drag-ghost { rotate: none; scale: none; } }
