/*
 * The slip results screen (SlipResults.js) — what Build Slip opens over the
 * Quick Slip tab — and the booking flow that follows it.
 *
 * The shell is the tool pages' (see odds-converter.css for the long form): a
 * fixed page at z-index 70 that fades while its sheet rises, with its own
 * scrolling body so the builder under it keeps its place. Everything inside
 * is drawn through the builder's own knob — every length is a design-frame
 * value times `--slip-scale` (tokens.css), hairlines and 44pt hit areas
 * excepted — and reads the same semantic tokens and the same `--sd-*` motion
 * scale (slip-controls.css lists this root as a host), so the two screens
 * are one flow rather than two products.
 *
 * The top of the page is the slip drawn as a ticket, one white card that
 * carries the confirmation, the composition and its risk, the kickoff
 * window, and past a perforation the total odds and the booking action.
 *
 * The platform picker restates the Advanced Markets sheet's chrome — scrim,
 * the grey stack layer, a large top radius, a circular X in the head — for
 * the reason code-converter.css gives: that chrome is named for that sheet.
 * Separation is tonal throughout — page, field, card — and nothing here
 * casts a shadow but the nav row's two buttons, which are the app's.
 */

/* --- Shell ---------------------------------------------------------------------- */

.slip-results {
  --enter-y: 12px;

  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  max-width: var(--app-max-width);
  margin-inline: auto;
  background: var(--bg);
  color: var(--text);
  font-size: calc(var(--text-base) * var(--slip-scale));
  line-height: 1.35;
  opacity: 0;
  transition: opacity var(--duration) var(--easing);
}

.slip-results[hidden] {
  display: none;
}

.slip-results [hidden] {
  display: none !important;
}

.slip-results[data-open="true"] {
  --enter-y: 0px;

  opacity: 1;
}

.slip-results__sheet {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding-top: var(--safe-top);
  transform: translateY(var(--enter-y));
  transition: transform var(--duration) var(--easing);
}

/* The page's own scroller, so the builder under it keeps its place. */
.slip-results__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
}

/* The toasts sit at the foot of the page rather than above the nav's
   footprint (the slip's default) — there is no nav under this page. */
.slip-results .slip-toasts {
  position: absolute;
  right: 0;
  bottom: calc(var(--space-4) + var(--safe-bottom));
  left: 0;
}

/* --- Nav row ---------------------------------------------------------------------- */

/* Leave on the left, share on the right, the slip's name between them. The
   buttons are the app's white chips at their full size: this row is chrome,
   and chrome is not scaled with the document under it. */
.sr-nav {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-3) 0;
}

.sr-nav__title {
  flex: 1;
  min-width: 0;
  color: var(--text);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- The document -------------------------------------------------------------------- */

.sr {
  display: flex;
  flex-direction: column;
  gap: calc(20px * var(--slip-scale));
  padding: calc(var(--space-4) * var(--slip-scale)) calc(var(--space-5) * var(--slip-scale))
    calc(var(--space-8) * var(--slip-scale) + var(--safe-bottom));
}

.sr-label {
  color: var(--text);
  font-size: calc(var(--text-md) * var(--slip-scale));
  font-weight: var(--weight-bold);
}

/* --- The ticket ------------------------------------------------------------------------ */

/*
 * The slip's header is the slip itself, drawn as a ticket: a white card,
 * the confirmation as its eyebrow with the strategy chip opposite, the
 * composition as its headline with the risk badge beside it — the builder's
 * readout-and-badge row — the kickoff window under them, and past a
 * perforation the stub, where the total odds and the one action sit. The
 * notches are the page showing through the card's edges, which is why the
 * card clips.
 */
.sr-ticket {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: calc(16px * var(--slip-scale)) calc(16px * var(--slip-scale)) calc(14px * var(--slip-scale));
  border-radius: calc(18px * var(--slip-scale));
  background: var(--surface);
  overflow: hidden;
}

/* Three hairlines at roughly 75°, oversized and cut by the card's edges. */
.sr-ticket__mark {
  position: absolute;
  top: -20%;
  right: 0;
  width: 55%;
  height: 140%;
  pointer-events: none;
}

.sr-ticket__mark line {
  stroke: var(--border);
  stroke-opacity: 0.6;
  stroke-width: 1;
}

/* The rows are positioned so they paint over the hairlines behind them. */
.sr-ticket__head,
.sr-ticket__row,
.sr-ticket__window,
.sr-ticket__short,
.sr-ticket__tear,
.sr-ticket__stub {
  position: relative;
}

.sr-ticket__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(8px * var(--slip-scale));
}

/* "Slip Generated" — the confirmation, as an eyebrow rather than a dialog. */
.sr-ticket__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: calc(6px * var(--slip-scale));
  min-width: 0;
  color: var(--text-muted);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

.sr-ticket__tick {
  flex: none;
  display: grid;
  place-items: center;
  width: calc(18px * var(--slip-scale));
  height: calc(18px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--success-soft);
  color: var(--success-strong);
}

.sr-ticket__tick[data-anim="pop"] {
  animation: slip-dot-pop var(--sd-pop) var(--se-spring);
}

/* The strategy that shaped the slip, with the glyph its card wears on the builder. */
.sr-ticket__strategy {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: calc(5px * var(--slip-scale));
  height: calc(24px * var(--slip-scale));
  padding: 0 calc(9px * var(--slip-scale)) 0 calc(7px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-size: calc(11px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

/* The composition and its risk — the builder's own readout row. */
.sr-ticket__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(10px * var(--slip-scale));
  margin-top: calc(10px * var(--slip-scale));
}

.sr-ticket__h1 {
  display: inline-flex;
  align-items: baseline;
  gap: calc(6px * var(--slip-scale));
  min-width: 0;
  color: var(--text);
  font-size: calc(27px * var(--slip-scale));
  font-weight: 800;
  letter-spacing: -0.5px;
  line-height: 1.1;
  white-space: nowrap;
}

.sr-ticket__h1 .slip-odo {
  font-variant-numeric: tabular-nums;
}

.sr-ticket__window {
  display: flex;
  align-items: center;
  gap: calc(6px * var(--slip-scale));
  margin-top: calc(6px * var(--slip-scale));
  color: var(--text-secondary);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  line-height: 1.3;
}

.sr-ticket__clock {
  flex: none;
  display: grid;
  place-items: center;
  color: var(--text-muted);
}

.sr-ticket__window-text {
  min-width: 0;
  transition:
    opacity var(--sd-fade) var(--se-out),
    transform var(--sd-fade) var(--se-out);
}

/* `refresh()` in core/transitions.js: the line dips out and back in around a rewrite. */
.sr-ticket__window-text[data-state="leave"],
.sr-ticket__window-text[data-state="enter"] {
  opacity: 0;
  transform: translateY(calc(2px * var(--slip-scale)));
}

/* Below the range floor the count line keeps the user honest — amber, non-blocking. */
.sr-ticket__short {
  padding-top: calc(8px * var(--slip-scale));
}

/* The perforation: a dashed line edge to edge, and a bite out of either side. */
.sr-ticket__tear {
  height: 0;
  margin: calc(14px * var(--slip-scale)) calc(-16px * var(--slip-scale));
  border-top: 1.5px dashed var(--border-strong);
}

.sr-ticket__tear::before,
.sr-ticket__tear::after {
  content: "";
  position: absolute;
  top: 50%;
  width: calc(20px * var(--slip-scale));
  height: calc(20px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--bg);
  transform: translateY(-50%);
}

.sr-ticket__tear::before {
  left: calc(-10px * var(--slip-scale));
}

.sr-ticket__tear::after {
  right: calc(-10px * var(--slip-scale));
}

/* The stub: the total odds on the left, the action taking the rest of the
   row — and the whole row when the two will not share it. */
.sr-ticket__stub {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(12px * var(--slip-scale));
}

.sr-ticket__odds {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sr-ticket__odds-label {
  color: var(--text-muted);
  font-size: calc(10.5px * var(--slip-scale));
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* No total while any leg is unpriced: a dash, not a number pretending. */
.sr-odds__none {
  color: var(--text-disabled);
  font-size: calc(24px * var(--slip-scale));
  font-weight: 800;
  line-height: 1;
}

/* "11.03", every digit on the odometer — the actualisation of the builder's
   estimate line, rolling the way its counter does. */
.sr-odds__num {
  display: inline-flex;
  align-items: baseline;
  color: var(--text);
  font-size: calc(24px * var(--slip-scale));
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* The bridge into the booking flow — the accent fill, since it is the one
   primary action on the page, the way Build Slip was on the one before. */
.sr-generate {
  position: relative;
  flex: 1 1 calc(170px * var(--slip-scale));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(8px * var(--slip-scale));
  height: calc(44px * var(--slip-scale));
  padding: 0 calc(16px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--accent);
  color: var(--accent-text);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-bold);
  white-space: nowrap;
  transition:
    background-color var(--sd-fade) var(--se-out),
    color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

.sr-generate[data-pressed="true"] {
  background: var(--accent-pressed);
}

.sr-generate:disabled {
  background: var(--surface-pressed);
  color: var(--text-disabled);
  cursor: default;
}

/* Busy is disabled too — a second tap has to wait — but it must not look spent. */
.sr-generate[data-busy="true"]:disabled {
  background: var(--accent);
  color: var(--accent-text);
}

.sr-generate[data-done="true"] {
  background: var(--success);
  color: var(--text-inverse);
}

.sr-generate__glyph,
.sr-generate__spinner,
.sr-generate__tick {
  display: grid;
  place-items: center;
  width: calc(18px * var(--slip-scale));
  height: calc(18px * var(--slip-scale));
}

.sr-generate__spinner {
  width: calc(16px * var(--slip-scale));
  height: calc(16px * var(--slip-scale));
  border: 2px solid rgb(var(--text-inverse-rgb) / 0.35);
  border-top-color: var(--text-inverse);
  border-radius: var(--radius-full);
  animation: ci-spin 700ms linear infinite;
}

.sr-generate__spinner,
.sr-generate__tick {
  display: none;
}

.sr-generate[data-busy="true"] .sr-generate__glyph,
.sr-generate[data-done="true"] .sr-generate__glyph {
  display: none;
}

.sr-generate[data-busy="true"] .sr-generate__spinner {
  display: grid;
}

.sr-generate[data-done="true"] .sr-generate__tick {
  display: grid;
  animation: icon-toggle var(--spring-duration) var(--spring);
}

/* --- Booking codes ---------------------------------------------------------------------- */

.sr-codes {
  display: flex;
  flex-direction: column;
  gap: calc(10px * var(--slip-scale));
  padding: calc(14px * var(--slip-scale)) calc(16px * var(--slip-scale)) calc(16px * var(--slip-scale));
  border-radius: calc(18px * var(--slip-scale));
  background: var(--surface);
}

/*
 * The bookie rail: every bookmaker as a chip, this person's own first, the
 * one whose code is on show filled. A tap gets that bookie's code — the one
 * the slip has, or a new one — so switching bookies is one tap, never a
 * sheet. It bleeds to the card's edges the way the tab rails bleed to the
 * screen's.
 */
.sr-bookies {
  margin: 0 calc(-16px * var(--slip-scale));
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.sr-bookies::-webkit-scrollbar {
  display: none;
}

.sr-bookies__track {
  display: flex;
  gap: calc(8px * var(--slip-scale));
  width: max-content;
  padding: calc(2px * var(--slip-scale)) calc(16px * var(--slip-scale));
}

.sr-bookie {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: calc(7px * var(--slip-scale));
  height: calc(38px * var(--slip-scale));
  padding: 0 calc(12px * var(--slip-scale)) 0 calc(7px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-size: calc(12.5px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  white-space: nowrap;
  transition:
    background-color var(--sd-fade) var(--se-out),
    color var(--sd-fade) var(--se-out),
    opacity var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

.sr-bookie[aria-pressed="true"] {
  background: var(--accent);
  color: var(--text-inverse);
}

.sr-bookie[data-pressed="true"] {
  box-shadow: inset 0 0 0 999px rgb(var(--text-rgb) / 0.04);
}

/* An empty slip has nothing to book; the chips wait rather than vanish. */
.sr-bookie:disabled {
  opacity: 0.45;
  cursor: default;
}

/* The brand disc — a league chip's placeholder crest, doing the same job for a bookmaker. */
.sr-bookie__disc {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: calc(24px * var(--slip-scale));
  height: calc(24px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--brand, var(--text-muted));
  color: var(--text-inverse);
  font-size: max(8px, calc(9px * var(--slip-scale)));
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  line-height: 1;
}

.sr-bookie[aria-pressed="true"] .sr-bookie__disc {
  box-shadow: 0 0 0 1.5px rgb(var(--text-inverse-rgb) / 0.35);
}

.sr-bookie__disc--find {
  background: var(--surface-pressed);
  color: var(--text-secondary);
}

/* A bookie the slip already holds a current code on. */
.sr-bookie__ready {
  position: absolute;
  right: calc(-3px * var(--slip-scale));
  bottom: calc(-3px * var(--slip-scale));
  display: none;
  place-items: center;
  width: calc(12px * var(--slip-scale));
  height: calc(12px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--success);
  color: var(--text-inverse);
  box-shadow: 0 0 0 1.5px var(--surface-sunken);
}

.sr-bookie[aria-pressed="true"] .sr-bookie__ready {
  box-shadow: 0 0 0 1.5px var(--accent);
}

.sr-bookie[data-ready="true"] .sr-bookie__ready {
  display: grid;
}

/* While its code is in the air the disc turns into a spinner. */
.sr-bookie[data-busy="true"] .sr-bookie__disc {
  background: rgb(var(--text-inverse-rgb) / 0.25);
  color: transparent;
}

.sr-bookie[data-busy="true"] .sr-bookie__disc::after {
  content: "";
  position: absolute;
  inset: calc(4px * var(--slip-scale));
  border: 2px solid rgb(var(--text-inverse-rgb) / 0.4);
  border-top-color: var(--text-inverse);
  border-radius: var(--radius-full);
  animation: ci-spin 700ms linear infinite;
}

.sr-bookie[data-busy="true"] .sr-bookie__ready {
  display: none;
}

/* The dashed field the code sits in. */
.sr-code {
  display: flex;
  align-items: center;
  gap: calc(10px * var(--slip-scale));
  min-height: calc(56px * var(--slip-scale));
  padding: calc(8px * var(--slip-scale)) calc(8px * var(--slip-scale)) calc(8px * var(--slip-scale)) calc(14px * var(--slip-scale));
  border: 1.5px dashed var(--border-strong);
  border-radius: calc(14px * var(--slip-scale));
  background: var(--surface-sunken);
}

/* Tracked capitals — how a booking code is printed everywhere it is seen. */
.sr-code__text {
  flex: 1;
  min-width: 0;
  color: var(--text);
  font-size: calc(20px * var(--slip-scale));
  font-weight: 800;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sr-code__status {
  flex: 1;
  min-width: 0;
  color: var(--text-muted);
  font-size: calc(12.5px * var(--slip-scale));
  font-weight: var(--weight-semibold);
}

.sr-code .ci-spinner {
  margin: 0;
}

/* Before any code: the field waits, and says what fills it. */
.sr-code[data-status="empty"] .ci-spinner,
.sr-code[data-status="empty"] .sr-code__text,
.sr-code[data-status="empty"] .sr-code__copy,
.sr-code[data-status="empty"] .sr-code__regen,
.sr-code[data-status="ready"] .ci-spinner,
.sr-code[data-status="ready"] .sr-code__status,
.sr-code[data-status="ready"] .sr-code__regen,
.sr-code[data-status="loading"] .sr-code__text,
.sr-code[data-status="loading"] .sr-code__copy,
.sr-code[data-status="loading"] .sr-code__regen,
.sr-code[data-status="failed"] .ci-spinner,
.sr-code[data-status="failed"] .sr-code__status,
.sr-code[data-status="failed"] .sr-code__copy {
  display: none;
}

/* A bookmaker that would not book: the field says so and offers the retry. */
.sr-code[data-status="failed"] {
  border-color: var(--warning);
}

.sr-code[data-status="failed"] .sr-code__text {
  display: block;
  color: var(--text-disabled);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  letter-spacing: 0;
}

.sr-bookie[data-failed="true"] .sr-bookie__disc::before {
  content: "";
  position: absolute;
  right: calc(-3px * var(--slip-scale));
  bottom: calc(-3px * var(--slip-scale));
  width: calc(10px * var(--slip-scale));
  height: calc(10px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--warning);
  box-shadow: 0 0 0 1.5px var(--surface-sunken);
}

/* Copy confirms where the finger is: the label itself turns to "Copied". A
   floor on the width so the swap does not shuffle the field. */
.sr-code__copy,
.sr-code__regen {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(6px * var(--slip-scale));
  height: calc(36px * var(--slip-scale));
  min-width: calc(104px * var(--slip-scale));
  padding: 0 calc(12px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--accent);
  color: var(--accent-text);
  font-size: calc(12.5px * var(--slip-scale));
  font-weight: var(--weight-bold);
  white-space: nowrap;
  transition:
    background-color var(--sd-fade) var(--se-out),
    color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

.sr-code__copy[data-pressed="true"],
.sr-code__regen[data-pressed="true"] {
  background: var(--accent-pressed);
}

.sr-code__copy[data-copied="true"] {
  background: var(--success);
}

.sr-code__regen {
  background: var(--warning-soft);
  color: var(--warning-strong);
}

/* Whole bookings read calm; partial ones do not get to. */
.sr-code__meta {
  color: var(--success-strong);
  font-size: calc(12.5px * var(--slip-scale));
  font-weight: var(--weight-semibold);
}

.sr-code__meta[data-partial="true"] {
  color: var(--warning-strong);
}

.sr-code__stale {
  color: var(--warning-strong);
  font-size: calc(12.5px * var(--slip-scale));
  font-weight: var(--weight-semibold);
}

/* --- The picks a bookmaker left out ---------------------------------------------------------- */

/* Named, struck, and given the bookmaker's reason — under the code field and
   in the confirmation sheet alike. */
.sr-lost {
  display: flex;
  flex-direction: column;
  gap: calc(6px * var(--slip-scale));
  list-style: none;
}

.sr-lost__row {
  display: flex;
  align-items: center;
  gap: calc(10px * var(--slip-scale));
  padding: calc(8px * var(--slip-scale)) calc(12px * var(--slip-scale));
  border-radius: calc(11px * var(--slip-scale));
  background: var(--warning-soft);
}

.sr-lost__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sr-lost__match {
  color: var(--text-muted);
  font-size: calc(11px * var(--slip-scale));
  font-weight: var(--weight-medium);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sr-lost__pick {
  color: var(--text-secondary);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  text-decoration: line-through;
  text-decoration-color: var(--text-disabled);
}

.sr-lost__why {
  flex: none;
  max-width: 42%;
  color: var(--warning-strong);
  font-size: calc(10.5px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  line-height: 1.3;
  text-align: right;
}

/* --- Predictions ------------------------------------------------------------------------------ */

.sr-preds {
  display: flex;
  flex-direction: column;
  gap: calc(12px * var(--slip-scale));
}

.sr-preds__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(12px * var(--slip-scale));
}

/* Teaches the gesture before it is needed: the arrow nudges left twice on
   arrival and then sits still. */
.sr-hint {
  display: inline-flex;
  align-items: center;
  gap: calc(5px * var(--slip-scale));
  height: calc(26px * var(--slip-scale));
  padding: 0 calc(10px * var(--slip-scale)) 0 calc(8px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text-muted);
  font-size: calc(11px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

.sr-hint .icon {
  animation: sr-nudge 1.6s var(--se-out) 700ms 2;
}

@keyframes sr-nudge {
  0%,
  60%,
  100% {
    transform: translateX(0);
  }
  30% {
    transform: translateX(calc(-3px * var(--slip-scale)));
  }
}

/* The server's rule, said plainly: a booked slip keeps its picks. */
.sr-locked {
  display: flex;
  align-items: flex-start;
  gap: calc(6px * var(--slip-scale));
  padding: calc(10px * var(--slip-scale)) calc(12px * var(--slip-scale));
  border-radius: calc(12px * var(--slip-scale));
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-size: calc(12.5px * var(--slip-scale));
  font-weight: var(--weight-medium);
  line-height: 1.4;
}

.sr-locked .icon {
  flex: none;
  margin-top: 1px;
  color: var(--text-muted);
}

.sr-swipe[data-locked="true"] {
  touch-action: auto;
}

.sr-list {
  display: flex;
  flex-direction: column;
}

/*
 * The swipe wrapper is the keyed node. A margin rather than the list's gap,
 * so a card leaving can close its own space; the height goes on the
 * 0fr -> 1fr trick the collapses use, so nothing is measured.
 */
.sr-swipe {
  position: relative;
  display: grid;
  grid-template-rows: 1fr;
  margin-bottom: calc(12px * var(--slip-scale));
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  transition:
    grid-template-rows var(--sd-fade) var(--se-out),
    margin-bottom var(--sd-fade) var(--se-out),
    opacity var(--sd-fade) var(--se-out),
    transform var(--sd-fade) var(--se-out);
}

.sr-swipe:last-child {
  margin-bottom: 0;
}

/* Enter and leave from `keyed()` in core/transitions.js: cards arrive one
   after another, and a removed one closes up. */
.sr-swipe[data-state="enter"] {
  opacity: 0;
  transform: translateY(calc(10px * var(--slip-scale)));
  transition-delay: calc(var(--i, 0) * var(--stagger-step));
}

.sr-swipe[data-state="leave"] {
  grid-template-rows: 0fr;
  margin-bottom: 0;
  opacity: 0;
}

.sr-swipe__clip {
  position: relative;
  min-height: 0;
  overflow: hidden;
  border-radius: calc(18px * var(--slip-scale));
}

/* The destructive action under the card, revealed as the card slides. */
.sr-swipe__under {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: calc(16px * var(--slip-scale));
  background: var(--error);
  color: var(--text-inverse);
  /* Painted only while a swipe is in progress, held open or committing: a
     red ground under a card at rest fringed its rounded corners. It goes
     a beat after the card has sprung back. */
  opacity: 0;
  transition: opacity var(--sd-fade) var(--se-out) 200ms;
}

.sr-swipe[data-dragging] .sr-swipe__under,
.sr-swipe[data-open="true"] .sr-swipe__under,
.sr-swipe[data-state="gone"] .sr-swipe__under {
  opacity: 1;
  transition: none;
}

/* Progressive, never a pop: it grows and fills in with the swipe. */
.sr-swipe__remove {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(3px * var(--slip-scale));
  min-width: calc(72px * var(--slip-scale));
  color: inherit;
  font-size: calc(11px * var(--slip-scale));
  font-weight: var(--weight-bold);
  opacity: var(--reveal, 0);
  transform: scale(calc(0.7 + 0.3 * var(--reveal, 0)));
  transition:
    transform var(--duration-press) var(--easing),
    opacity var(--duration-press) var(--easing);
}

.sr-swipe[data-dragging] .sr-swipe__remove {
  transition: none;
}

.sr-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: calc(10px * var(--slip-scale));
  padding: calc(14px * var(--slip-scale)) calc(16px * var(--slip-scale));
  background: var(--surface);
  border-radius: calc(18px * var(--slip-scale));
  transform: translateX(var(--dx, 0px));
  transition: transform var(--spring-duration) var(--spring);
}

/* Under a finger nothing eases — the card is being held. */
.sr-swipe[data-dragging] .sr-card {
  transition: none;
}

/* A change in the air: the card waits, and its pill says so. */
.sr-card[data-busy="true"] {
  opacity: 0.7;
  pointer-events: none;
}

.sr-card__change[data-busy="true"] .sr-card__change-chevron {
  display: none;
}

/* A committed swipe: the card leaves the way it was going. */
.sr-swipe[data-state="gone"] .sr-card {
  transform: translateX(-110%);
  transition: transform 180ms var(--se-out);
}

.sr-card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(8px * var(--slip-scale));
}

.sr-card__league {
  display: inline-flex;
  align-items: center;
  gap: calc(6px * var(--slip-scale));
  min-width: 0;
  color: var(--text-muted);
  font-size: calc(12px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sr-card__league-glyph {
  display: grid;
  place-items: center;
  color: var(--text-muted);
}

/* "19:45" with the hours dark and the minutes muted. */
.sr-card__time {
  flex: none;
  display: inline-flex;
  align-items: baseline;
  color: var(--text);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}

.sr-card__colon,
.sr-card__minutes {
  color: var(--text-muted);
}

.sr-card__main {
  display: flex;
  align-items: center;
  gap: calc(12px * var(--slip-scale));
}

.sr-card__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: calc(4px * var(--slip-scale));
}

.sr-card__fixture {
  color: var(--text-muted);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-medium);
}

/* Always Market: Pick, in bold; it dips and returns when the pick changes. */
.sr-card__pick {
  color: var(--text);
  font-size: calc(15px * var(--slip-scale));
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
  line-height: 1.25;
  transition:
    opacity var(--sd-fade) var(--se-out),
    transform var(--sd-fade) var(--se-out);
}

.sr-card__pick[data-state="leave"],
.sr-card__pick[data-state="enter"] {
  opacity: 0;
  transform: translateY(calc(3px * var(--slip-scale)));
}

.sr-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: calc(6px * var(--slip-scale));
  margin-top: calc(2px * var(--slip-scale));
}

/* "Banker" on an anchor pick, "Pinned Line" on a line the Advanced Markets
   sheet set — the two places the config shows through on a card. */
.sr-tag {
  display: inline-flex;
  align-items: center;
  gap: calc(4px * var(--slip-scale));
  height: calc(20px * var(--slip-scale));
  padding: 0 calc(8px * var(--slip-scale));
  border-radius: var(--radius-full);
  font-size: calc(var(--text-2xs) * var(--slip-scale));
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

.sr-tag--banker {
  background: var(--accent-tint);
  color: var(--accent);
}

.sr-tag--pinned {
  background: var(--surface-sunken);
  color: var(--text-secondary);
}

/* Two crests in dashed rings. */
.sr-crests {
  flex: none;
  display: flex;
  align-items: center;
  gap: calc(6px * var(--slip-scale));
}

.sr-crest {
  display: grid;
  place-items: center;
  width: calc(40px * var(--slip-scale));
  height: calc(40px * var(--slip-scale));
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius-full);
  background: var(--surface);
}

.sr-crest .logo {
  background: none;
}

.sr-crest .logo--monogram {
  background: var(--surface-sunken);
  font-size: calc(9px * var(--slip-scale));
}

/* "Change Prediction" — the tinted pill at the card's foot. */
.sr-card__change {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(6px * var(--slip-scale));
  width: 100%;
  height: calc(40px * var(--slip-scale));
  border-radius: calc(12px * var(--slip-scale));
  background: var(--accent-tint);
  color: var(--accent);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-bold);
  transition:
    background-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

.sr-card__change[data-pressed="true"] {
  box-shadow: inset 0 0 0 999px rgb(var(--text-rgb) / 0.04);
}

.sr-card__change-chevron {
  transition: transform var(--sd-chevron) var(--se-out);
}

.sr-card__change[aria-expanded="true"] .sr-card__change-chevron {
  transform: rotate(180deg);
}

/* The inline picker under the pill: the other picks the config allows. */
.sr-picker[data-shown="true"] > .slip-collapse__inner {
  padding-top: calc(4px * var(--slip-scale));
}

.sr-alts {
  display: flex;
  flex-direction: column;
}

.sr-alt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(10px * var(--slip-scale));
  width: 100%;
  min-height: calc(46px * var(--slip-scale));
  padding: calc(8px * var(--slip-scale)) 0;
  border-top: 1px solid var(--border);
  text-align: left;
  transition: transform var(--spring-duration) var(--spring);
}

.sr-alt[data-pressed="true"] {
  box-shadow: inset 0 0 0 999px rgb(var(--text-rgb) / 0.03);
}

.sr-alt__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sr-alt__pick {
  color: var(--text);
  font-size: calc(13.5px * var(--slip-scale));
  font-weight: var(--weight-semibold);
}

.sr-alt__pinned {
  color: var(--text-muted);
  font-size: calc(11px * var(--slip-scale));
  font-weight: var(--weight-medium);
}

.sr-alt__side {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: calc(8px * var(--slip-scale));
}

.sr-alt__odds {
  display: inline-flex;
  align-items: center;
  height: calc(24px * var(--slip-scale));
  padding: 0 calc(10px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text);
  font-size: calc(var(--text-xs) * var(--slip-scale));
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}

.sr-alts__empty {
  padding: calc(10px * var(--slip-scale)) 0;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: calc(12.5px * var(--slip-scale));
  font-weight: var(--weight-medium);
}

.sr-alts__loading {
  display: flex;
  align-items: center;
  gap: calc(8px * var(--slip-scale));
}

.sr-alts__loading .ci-spinner {
  margin: 0;
}

/* An empty slip is a screen, not a blank: one line, and the add row under it. */
.sr-empty {
  padding: calc(20px * var(--slip-scale)) calc(16px * var(--slip-scale));
  border-radius: calc(18px * var(--slip-scale));
  background: var(--surface);
  color: var(--text-muted);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-medium);
  text-align: center;
}

/* "Add More Games" — the dashed, muted row at the list's foot. A request,
   not a picker: its wait and its outcome show on the row itself. */
.sr-add {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(8px * var(--slip-scale));
  width: 100%;
  height: calc(50px * var(--slip-scale));
  border: 1.5px dashed var(--border-strong);
  border-radius: calc(16px * var(--slip-scale));
  color: var(--text-muted);
  font-size: calc(14px * var(--slip-scale));
  font-weight: var(--weight-bold);
  transition:
    color var(--sd-fade) var(--se-out),
    border-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

.sr-add[data-pressed="true"] {
  color: var(--text-secondary);
  border-color: var(--text-muted);
}

.sr-add:disabled {
  cursor: default;
}

.sr-add[data-locked="true"] {
  opacity: 0.45;
}

.sr-add__plus,
.sr-add__tick {
  display: grid;
  place-items: center;
  width: calc(20px * var(--slip-scale));
  height: calc(20px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--surface-pressed);
  color: var(--text-secondary);
}

.sr-add__spinner {
  width: calc(16px * var(--slip-scale));
  height: calc(16px * var(--slip-scale));
  border: 2px solid var(--border-strong);
  border-top-color: var(--text-secondary);
  border-radius: var(--radius-full);
  animation: ci-spin 700ms linear infinite;
}

.sr-add__spinner,
.sr-add__tick {
  display: none;
}

.sr-add[data-busy="true"] .sr-add__plus,
.sr-add[data-done="true"] .sr-add__plus {
  display: none;
}

.sr-add[data-busy="true"] .sr-add__spinner {
  display: grid;
}

/* The game has landed: a green beat on the row before it goes back to asking. */
.sr-add[data-done="true"] {
  border-color: var(--success);
  color: var(--success-strong);
}

.sr-add[data-done="true"] .sr-add__tick {
  display: grid;
  background: var(--success-soft);
  color: var(--success-strong);
  animation: icon-toggle var(--spring-duration) var(--spring);
}

/* --- The confirmation ------------------------------------------------------------------------------ */

.sr-confirm {
  display: flex;
  flex-direction: column;
}

.sr-confirm__body {
  color: var(--text-secondary);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-medium);
  line-height: 1.45;
}

.sr-confirm .sr-lost {
  margin-top: calc(12px * var(--slip-scale));
}

.sr-confirm__actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(8px * var(--slip-scale));
  margin-top: calc(20px * var(--slip-scale));
}

/* Nothing could be booked: there is no partial code to offer, so the one
   button left is the way out. */
.sr-confirm__actions[data-only="true"] {
  grid-template-columns: minmax(0, 1fr);
}

.sr-confirm__back,
.sr-confirm__go {
  height: calc(48px * var(--slip-scale));
  border-radius: calc(12px * var(--slip-scale));
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-bold);
  transition:
    background-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

.sr-confirm__back {
  background: var(--surface-sunken);
  color: var(--text);
}

.sr-confirm__go {
  background: var(--accent);
  color: var(--accent-text);
}

.sr-confirm__go[data-pressed="true"] {
  background: var(--accent-pressed);
}

/* --- The platform picker ------------------------------------------------------------------------------ */

/* The Advanced Markets chrome, restated: scrim, the stack layer, a large top
   radius, a circular X in the head. */
.sr-platforms {
  --srp-enter: var(--spring-duration);
  --srp-exit: 320ms;
  --srp-lag: 40ms;

  position: fixed;
  inset: 0;
  z-index: 96;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  max-width: var(--app-max-width);
  margin-inline: auto;
}

.sr-platforms[hidden] {
  display: none;
}

.sr-platforms__scrim {
  position: absolute;
  inset: 0;
  background: var(--text);
  opacity: 0;
  transition: opacity var(--sd-fade) var(--se-out);
}

.sr-platforms[data-open="true"] .sr-platforms__scrim {
  opacity: 0.55;
}

.sr-platforms__stack {
  position: absolute;
  right: calc(16px * var(--slip-scale));
  bottom: 0;
  left: calc(16px * var(--slip-scale));
  height: calc(84dvh + 12px * var(--slip-scale));
  border-radius: calc(24px * var(--slip-scale)) calc(24px * var(--slip-scale)) 0 0;
  background: var(--slip-stack);
  transform: translateY(var(--rest-y, 100%));
  transition: transform var(--srp-exit) var(--se-out);
}

.sr-platforms[data-open="true"] .sr-platforms__stack {
  --rest-y: 0px;

  transition: transform var(--srp-enter) var(--spring) var(--srp-lag);
}

.sr-platforms__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 84dvh;
  background: var(--surface);
  border-radius: calc(28px * var(--slip-scale)) calc(28px * var(--slip-scale)) 0 0;
  overflow: hidden;
  transform: translateY(var(--rest-y, 100%));
  transition: transform var(--srp-exit) var(--se-out);
}

.sr-platforms[data-open="true"] .sr-platforms__panel {
  --rest-y: 0px;

  transition: transform var(--srp-enter) var(--spring);
}

.sr-platforms__head {
  flex: none;
  display: flex;
  align-items: center;
  height: calc(80px * var(--slip-scale));
  padding: 0 calc(20px * var(--slip-scale));
  border-bottom: 1px solid var(--border);
}

/* 56pt visual, 44pt hit whatever the scale — the Advanced Markets close. */
.sr-platforms__close {
  --press-scale: 0.94;

  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: calc(56px * var(--slip-scale));
  height: calc(56px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
}

.sr-platforms__close::before {
  content: "";
  position: absolute;
  inset: min(0px, calc((56px * var(--slip-scale) - 44px) / 2));
  border-radius: inherit;
}

.sr-platforms__close[data-pressed="true"] {
  box-shadow: inset 0 0 0 999px rgb(var(--text-rgb) / 0.04);
}

.sr-platforms__title {
  flex: none;
  display: inline-flex;
  align-items: center;
  height: calc(48px * var(--slip-scale));
  margin-inline: auto;
  padding: 0 calc(22px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text);
  font-size: calc(16px * var(--slip-scale));
  font-weight: var(--weight-bold);
  white-space: nowrap;
}

/* Balances the close button so the title pill sits centred. */
.sr-platforms__spacer {
  flex: none;
  width: calc(56px * var(--slip-scale));
}

.sr-platforms__body {
  flex: 1;
  min-height: 0;
  padding: calc(16px * var(--slip-scale)) calc(20px * var(--slip-scale)) calc(24px * var(--slip-scale) + var(--safe-bottom));
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.sr-platforms .slip-search {
  margin-bottom: calc(16px * var(--slip-scale));
}

.sr-platforms__label {
  margin: calc(8px * var(--slip-scale)) 0 calc(10px * var(--slip-scale));
  color: var(--text);
  font-size: calc(var(--text-md) * var(--slip-scale));
  font-weight: var(--weight-bold);
}

/* "Popular Sites": four tiles across. */
.sr-tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: calc(10px * var(--slip-scale));
  margin-bottom: calc(16px * var(--slip-scale));
}

.sr-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(8px * var(--slip-scale));
  min-width: 0;
  padding: calc(12px * var(--slip-scale)) calc(4px * var(--slip-scale));
  border-radius: calc(16px * var(--slip-scale));
  background: var(--surface-sunken);
  color: var(--text);
  font-size: calc(11px * var(--slip-scale));
  font-weight: var(--weight-semibold);
  transition:
    background-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

.sr-tile[data-pressed="true"] {
  background: var(--surface-pressed);
}

.sr-tile__disc {
  position: relative;
  display: grid;
  place-items: center;
  width: calc(48px * var(--slip-scale));
  height: calc(48px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--brand, var(--text-muted));
  color: var(--text-inverse);
  font-size: calc(13px * var(--slip-scale));
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
}

/* A bookmaker the slip already has a current code on. */
.sr-tile__ready {
  position: absolute;
  right: calc(-2px * var(--slip-scale));
  bottom: calc(-2px * var(--slip-scale));
  display: none;
  place-items: center;
  width: calc(18px * var(--slip-scale));
  height: calc(18px * var(--slip-scale));
  border-radius: var(--radius-full);
  background: var(--success);
  color: var(--text-inverse);
  box-shadow: 0 0 0 2px var(--surface-sunken);
}

.sr-tile[data-ready="true"] .sr-tile__ready {
  display: grid;
}

.sr-tile__name {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* "Others": rows with the round discs. */
.sr-prows {
  display: flex;
  flex-direction: column;
}

.sr-prow {
  display: flex;
  align-items: center;
  gap: calc(12px * var(--slip-scale));
  width: 100%;
  min-height: calc(60px * var(--slip-scale));
  padding: calc(8px * var(--slip-scale)) 0;
  border-bottom: 1px solid var(--border);
  text-align: left;
  transition: transform var(--spring-duration) var(--spring);
}

.sr-prow:last-child {
  border-bottom: 0;
}

.sr-prow[data-pressed="true"] {
  box-shadow: inset 0 0 0 999px rgb(var(--text-rgb) / 0.04);
}

.sr-prow__name {
  flex: 1;
  min-width: 0;
  color: var(--text);
  font-size: calc(15px * var(--slip-scale));
  font-weight: var(--weight-bold);
}

.sr-prow__ready {
  color: var(--success-strong);
  font-size: calc(11px * var(--slip-scale));
  font-weight: var(--weight-semibold);
}

.sr-prow__chevron {
  color: var(--text-muted);
  transform: rotate(-90deg);
}

/* --- Reduced motion ---------------------------------------------------------------------------------- */

/*
 * Movement becomes a short fade: the odometers snap, the tick is simply
 * drawn, the cards neither fly nor stagger, the picker sheet fades in place.
 */
@media (prefers-reduced-motion: reduce) {
  .slip-results {
    --sd-fade: 100ms;
    --sd-chevron: 100ms;
    --sd-check: 0ms;
    --sd-odo: 0ms;
    --sd-roll: 0ms;
    --sd-pop: 0ms;
    --sd-spring: 0ms;
    --se-spring: ease-out;
  }

  .sr-platforms {
    --srp-enter: 0ms;
    --srp-exit: 0ms;
    --srp-lag: 0ms;
  }

  .slip-results [data-anim],
  .sr-hint .icon,
  .sr-generate__spinner,
  .sr-generate__tick,
  .sr-add__spinner,
  .sr-add__tick,
  .sr-bookie[data-busy="true"] .sr-bookie__disc::after {
    animation: none !important;
  }

  .sr-swipe,
  .sr-card,
  .sr-swipe__remove {
    transition: none;
  }

  .sr-swipe[data-state="enter"] {
    transform: none;
  }

  .sr-platforms__panel,
  .sr-platforms__stack {
    transform: none !important;
    transition: opacity 100ms ease-out !important;
  }

  .sr-platforms[data-open="false"] .sr-platforms__panel,
  .sr-platforms[data-open="false"] .sr-platforms__stack {
    opacity: 0;
  }
}
