/*
 * The Slip Builder's controls (SlipControls.js): toggle, stepper, range
 * slider, odometer, count badge, collapse, accordion and sheet. The screen
 * that composes them is slip-builder.css.
 *
 * Colours are the app's semantic tokens (tokens.css), and the motion scale is
 * declared once here on the screen root so both sheets read the same values:
 *
 *   --sd-fade      fills, recolours, cross-fades
 *   --sd-chevron   the accordion and drawer chevrons
 *   --sd-check     the checkmark's stroke draw
 *   --sd-odo       one odometer roll
 *   --sd-roll      a stepper value sliding 8pt
 *   --sd-pop       badge and dot pops
 *   --sd-pulse     the counter badge's scale pulse
 *   --sd-spring    anything that travels — heights, cards, chips
 *
 * Reduced motion cuts every one of these to a short opacity change at the
 * bottom of this file: no odometer, no pulses, no travel.
 *
 * Declared on every host that draws these controls, not only on the slip:
 * the results screen Build Slip opens (its odometers, risk badge and toasts),
 * the twelve tool pages (the Lineup Builder, the Odds Converter, the four
 * slip tools, the four staking calculators and the two Compare tools, whose
 * sheets, toasts and shared code fields all read it), the
 * account page (its toasts), the fixture page's Preview and Facts tabs (the
 * poll pills) and the Top Picks page (its sheets, pills, toasts and counter
 * blob), so one value here moves all of them the same way.
 */

.slip,
.slip-results,
.lineup-builder,
.odds-converter,
.slip-merger,
.slip-splitter,
.slip-optimizer,
.code-converter,
.calc,
.cmp,
.tf,
.account,
.fixture-preview,
.fixture-facts,
.fixture-props,
.fixture-predictions,
.bet-builder,
.slip-tray,
.top-picks {
  --sd-fade: 180ms;
  --sd-chevron: 200ms;
  --sd-check: 220ms;
  --sd-odo: 350ms;
  --sd-roll: 150ms;
  --sd-pop: 250ms;
  --sd-pulse: 250ms;
  --sd-spring: var(--spring-duration);
  --sd-thumb: 250ms;
  --se-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  /* The app's spring, and the press scale this screen's spec asks for. */
  --se-spring: var(--spring);
  --press-scale: 0.98;
}

/* --- Toggle ---------------------------------------------------------------- */

.slip-toggle {
  position: relative;
  flex: none;
  width: calc(39px * var(--scale));
  height: calc(24px * var(--scale));
  border-radius: var(--radius-full);
  background: var(--text-disabled);
  transition:
    background-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

.slip-toggle[aria-checked="true"] {
  background: var(--accent);
}

/* Only the thumb travels, so only the thumb springs. */
.slip-toggle__thumb {
  position: absolute;
  top: calc(3px * var(--scale));
  left: calc(3px * var(--scale));
  width: calc(19px * var(--scale));
  height: calc(19px * var(--scale));
  border-radius: var(--radius-full);
  background: var(--knob);
  box-shadow: 0 1px calc(3px * var(--scale)) rgb(var(--shadow-rgb) / 0.18);
  transition: transform var(--sd-fade) var(--se-spring);
}

.slip-toggle[aria-checked="true"] .slip-toggle__thumb {
  transform: translateX(calc(15px * var(--scale)));
}

/* --- Stepper --------------------------------------------------------------- */

.slip-stepper {
  display: inline-flex;
  align-items: center;
  gap: var(--space-15);
}

/* 32pt visual (scaled), 44pt hit whatever the scale: the pseudo-element pads
   the target out to 44 without growing the circle the eye sees. */
.slip-stepper__btn {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--control-xs);
  height: var(--control-xs);
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  transition:
    background-color var(--sd-fade) var(--se-out),
    color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

.slip-stepper__btn::before {
  content: "";
  position: absolute;
  inset: calc((calc(27px * var(--scale)) - calc(37px * var(--scale))) / 2);
}

.slip-stepper__btn[data-pressed="true"] {
  box-shadow: inset 0 0 0 calc(999px * var(--scale)) rgb(var(--text-rgb) / 0.06);
}

.slip-stepper__btn:disabled {
  color: var(--text-disabled);
  cursor: default;
}

.slip-stepper__value {
  position: relative;
  display: grid;
  width: calc(20px * var(--scale));
  text-align: center;
  color: var(--text);
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-none);
}

/* Old and new share one cell; each slides 8pt the way the number moved. */
.slip-stepper__digit {
  grid-area: 1 / 1;
  transition:
    transform var(--sd-roll) var(--se-out),
    opacity var(--sd-roll) var(--se-out);
}

.slip-stepper__digit[data-enter="up"] {
  transform: translateY(calc(7px * var(--scale)));
  opacity: 0;
}

.slip-stepper__digit[data-enter="down"] {
  transform: translateY(calc(-7px * var(--scale)));
  opacity: 0;
}

.slip-stepper__digit[data-leave="up"] {
  transform: translateY(calc(-7px * var(--scale)));
  opacity: 0;
}

.slip-stepper__digit[data-leave="down"] {
  transform: translateY(calc(7px * var(--scale)));
  opacity: 0;
}

/* --- Range slider ---------------------------------------------------------- */

.slip-range {
  position: relative;
  /* Room for the 22pt thumbs either side of the 6pt rail. */
  padding: var(--space-2) var(--space-2);
}

.slip-range__rail {
  position: relative;
  height: calc(5px * var(--scale));
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  /* Vertical pans stay the page's; horizontal ones are ours. */
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/*
 * A full-width gradient, clipped to the span — so the colours are sampled
 * across the whole domain and a low span shows the low end of the gradient.
 * `--fill` is set by the caller per slider.
 */
.slip-range__fill {
  position: absolute;
  inset: 0;
  border-radius: var(--radius-full);
  background: var(--fill, var(--accent));
  transition: clip-path var(--sd-thumb) var(--se-out);
}

/* 44pt hit area at any scale; the 22pt (scaled) circle the eye sees is the
   pseudo-element, centred in it. */
.slip-range__thumb {
  position: absolute;
  top: 50%;
  width: var(--tap);
  height: var(--tap);
  margin: 0;
  border-radius: var(--radius-full);
  transform: translate(-50%, -50%);
  touch-action: none;
  cursor: grab;
  transition: left var(--sd-thumb) var(--se-out);
}

.slip-range__thumb::before {
  content: "";
  position: absolute;
  inset: calc((calc(37px * var(--scale)) - calc(19px * var(--scale))) / 2);
  border-radius: var(--radius-full);
  background: var(--knob);
  border: 2px solid var(--ring, var(--accent));
  box-shadow: 0 1px calc(3px * var(--scale)) rgb(var(--shadow-rgb) / 0.14);
  transition:
    transform var(--sd-fade) var(--se-out),
    border-color var(--sd-fade) var(--se-out);
}

.slip-range__thumb:focus-visible {
  outline: none;
}

.slip-range__thumb:focus-visible::before {
  box-shadow: 0 1px calc(3px * var(--scale)) rgb(var(--shadow-rgb) / 0.14),
    0 0 0 3px rgb(var(--accent-rgb) / 0.25);
}

/* Under a finger nothing eases — the thumb is being held, not animated. */
.slip-range[data-dragging] .slip-range__thumb,
.slip-range[data-dragging] .slip-range__fill {
  transition: none;
}

.slip-range[data-dragging="0"] .slip-range__thumb[data-index="0"],
.slip-range[data-dragging="1"] .slip-range__thumb[data-index="1"] {
  cursor: grabbing;
  z-index: 1;
}

.slip-range[data-dragging="0"] .slip-range__thumb[data-index="0"]::before,
.slip-range[data-dragging="1"] .slip-range__thumb[data-index="1"]::before {
  transform: scale(1.15);
}

/* The value, riding just above the active thumb's circle. */
.slip-range__tip {
  position: absolute;
  bottom: calc(50% + calc(9px * var(--scale)) + calc(5px * var(--scale)));
  left: 50%;
  padding: var(--space-05) var(--space-1);
  border-radius: var(--radius-sm);
  background: rgb(var(--surface-inverse-rgb) / 0.9);
  color: var(--text-on-inverse);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-tight);
  white-space: nowrap;
  transform: translate(-50%, calc(3px * var(--scale)));
  opacity: 0;
  pointer-events: none;
  transition:
    opacity var(--sd-fade) var(--se-out),
    transform var(--sd-fade) var(--se-out);
}

.slip-range[data-dragging="0"] .slip-range__thumb[data-index="0"] .slip-range__tip,
.slip-range[data-dragging="1"] .slip-range__thumb[data-index="1"] .slip-range__tip {
  opacity: 1;
  transform: translate(-50%, 0);
}

.slip-range__ticks {
  position: relative;
  height: calc(12px * var(--scale));
  margin-top: var(--space-1);
}

.slip-range__tick {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  color: var(--text-disabled);
  font-size: var(--text-3xs);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-none);
}

/* --- Odometer -------------------------------------------------------------- */

.slip-odo {
  display: inline-flex;
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-none);
}

/* Each column shows one em of a ten-digit strip; `--d` picks which. */
.slip-odo__digit {
  position: relative;
  height: 1em;
  overflow: hidden;
  transition: opacity var(--sd-fade) var(--se-out);
}

.slip-odo__digit[data-state="enter"] {
  opacity: 0;
}

.slip-odo__strip {
  display: flex;
  flex-direction: column;
  transform: translateY(calc(var(--d, 0) * -1em));
  transition: transform var(--sd-odo) var(--se-out);
}

.slip-odo__strip[data-snap] {
  transition: none;
}

.slip-odo__n {
  display: block;
  height: 1em;
  line-height: var(--leading-none);
}

/* --- Count badge ----------------------------------------------------------- */

.slip-count {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  height: calc(22px * var(--scale));
  padding: 0 var(--space-15) 0 var(--space-05);
  border-radius: var(--radius-full);
  background: var(--accent);
  color: var(--text-inverse);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
}

.slip-count__num {
  display: grid;
  place-items: center;
  width: calc(14px * var(--scale));
  height: calc(14px * var(--scale));
  border-radius: var(--radius-full);
  background: var(--surface);
  color: var(--accent);
  font-size: var(--text-3xs);
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-none);
}

.slip-count__num[data-anim="bounce"] {
  animation: slip-bounce 200ms var(--se-spring);
}

@keyframes slip-bounce {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}

/* --- Collapse -------------------------------------------------------------- */

/* 0fr -> 1fr: an animated height without measuring one. */
.slip-collapse {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--sd-spring) var(--se-out);
}

.slip-collapse[data-shown="true"] {
  grid-template-rows: 1fr;
}

/* Contents fade in 120ms after a 60ms beat, so the box has started to open
   before anything appears inside it. */
.slip-collapse__inner {
  min-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity 120ms var(--se-out);
}

/* Child combinators throughout: collapses nest (an accordion inside a sport's
   mount slot), and a descendant selector would light a closed panel's inner
   from the open slot around it. */
.slip-collapse[data-shown="true"] > .slip-collapse__inner {
  opacity: 1;
  transition-delay: 60ms;
}

/* --- Rail ------------------------------------------------------------------ */

/*
 * A row of pills that scrolls sideways, bleeding to the screen edge the way
 * the league bubbles do on the home tab: SureTOOLS' categories, the Lineup
 * Builder's formations. The pills are the "When" pills; five or seven of
 * them do not fit a 390pt frame on one line, and a wrapped second row reads
 * as two groups rather than one rail. Callers add `u-scroll-x` and
 * `data-lenis-prevent-horizontal` (base.css, TabBar.js) so a trackpad can scroll
 * it and a finger can still scroll the page from it.
 */
.slip-rail {
  margin-inline: calc(var(--space-4) * -1);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.slip-rail::-webkit-scrollbar {
  display: none;
}

.slip-rail__track {
  display: flex;
  gap: var(--space-2);
  width: max-content;
  padding-inline: var(--space-4);
}

.slip-rail .slip-when {
  flex: none;
}

/* --- Accordion ------------------------------------------------------------- */

.slip-acc-list {
  display: flex;
  flex-direction: column;
}

/* A sport's accordion mounts and unmounts with its pill; the gap travels
   with it so the list closes up rather than leaving a hole. */
.slip-acc-slot[data-shown="true"] > .slip-collapse__inner {
  padding-bottom: var(--space-2);
}

.slip-acc-slot > .slip-collapse__inner {
  transition:
    opacity 120ms var(--se-out),
    padding-bottom var(--sd-spring) var(--se-out);
}

.slip-acc__head {
  display: flex;
  align-items: center;
  gap: var(--space-15);
  width: 100%;
  height: var(--control-md);
  padding: 0 var(--space-2) 0 var(--space-3);
  border-radius: var(--radius-lg);
  background: var(--surface-sunken);
  color: var(--text);
  text-align: left;
  transition: transform var(--spring-duration) var(--spring);
}

.slip-acc__head[data-pressed="true"] {
  box-shadow: inset 0 0 0 calc(999px * var(--scale)) rgb(var(--text-rgb) / 0.04);
}

.slip-acc__title {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
}

/* The collapsed header's mini-count — "Basketball · 2". */
.slip-acc__meta {
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}

.slip-acc__chevron {
  display: grid;
  place-items: center;
  width: calc(17px * var(--scale));
  height: calc(17px * var(--scale));
  color: var(--text-muted);
  transition: transform var(--sd-chevron) var(--se-out);
}

/* Down when closed, up when open. */
.slip-acc[data-open="true"] .slip-acc__chevron {
  transform: rotate(180deg);
}

.slip-acc__panel[data-shown="true"] > .slip-collapse__inner {
  padding-top: var(--space-2);
}

/* --- Sheet ----------------------------------------------------------------- */

.slip-sheet {
  position: fixed;
  /* The visible viewport rather than the layout one (core/viewport.js): with
     a keyboard up the sheet ends where the keys begin, so its panel stands on
     them instead of behind them. Unset, this is `inset: 0`. */
  inset: var(--vv-top, 0px) 0 auto;
  height: var(--vv-height, 100%);
  /* Above the fixture/club/league/player stack (80–98); the same band the
     filter sheet occupies, which this can never be open alongside. */
  z-index: 96;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  max-width: var(--app-max-width);
  margin-inline: auto;
}

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

/* Scrim at 40% ink, fading on the shared beat. */
.slip-sheet__scrim {
  position: absolute;
  /* On past the sheet's foot — the keyboard's top edge, with one up — so no
     strip of undimmed page shows while the keys slide in or out. */
  inset: 0 0 -100vh;
  background: var(--scrim);
  opacity: 0;
  transition: opacity var(--sd-fade) var(--se-out);
  transition-delay: var(--stagger-step);
}

.slip-sheet[data-open="true"] .slip-sheet__scrim {
  opacity: 0.4;
  transition-delay: 0ms;
}

.slip-sheet__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  /* A share of the sheet, which is the visible viewport — so the cap comes
     down with the keyboard — and free to shrink below any tool's own cap. */
  min-height: 0;
  max-height: min(80%, calc(544px * var(--scale)));
  padding-bottom: calc(var(--space-3) + var(--safe-bottom));
  background: var(--surface);
  border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
  box-shadow: var(--shadow-floating);
  transform: translateY(100%);
  transition: transform var(--sd-fade) var(--se-out);
}

/* An object arriving springs; on the way out it just leaves. */
.slip-sheet[data-open="true"] .slip-sheet__panel {
  transform: translateY(0);
  transition: transform var(--spring-duration) var(--spring) var(--stagger-step);
}

.slip-sheet__grabber {
  display: grid;
  place-items: center;
  padding: var(--space-15) 0 var(--space-05);
}

.slip-sheet__bar {
  width: calc(31px * var(--scale));
  height: calc(3px * var(--scale));
  border-radius: var(--radius-full);
  background: var(--border);
}

.slip-sheet__title {
  padding: var(--space-05) var(--space-4) var(--space-2);
  color: var(--text);
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
}

/* With the keyboard up the home indicator is under the keys; its inset is dead air. */
.slip-sheet[data-keyboard="true"] .slip-sheet__panel {
  padding-bottom: var(--space-3);
}

/* The title row with a control at its end — a Done, a Cancel. */
.slip-sheet__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding-right: var(--space-3);
}

.slip-sheet__head .slip-sheet__title {
  flex: 1;
  min-width: 0;
}

/* What stays put above the scrolling body: a search field, its filters. */
.slip-sheet__header {
  flex: none;
  padding: 0 var(--space-4);
}

/*
 * A sheet for searching keeps one height, so results arriving do not move it,
 * and fades up a short way instead of travelling from the bottom: the field it
 * opens focused is already where it will stay, and iOS has nothing to pan.
 */
.slip-sheet[data-size="tall"] .slip-sheet__panel {
  height: min(calc(100% - var(--safe-top) - var(--space-6)), calc(760px * var(--scale)));
  max-height: none;
  opacity: 0;
  transform: translateY(calc(24px * var(--scale)));
  transition:
    transform var(--sd-fade) var(--se-out),
    opacity var(--sd-fade) var(--se-out);
}

.slip-sheet[data-size="tall"][data-open="true"] .slip-sheet__panel {
  opacity: 1;
  transform: translateY(0);
  transition:
    transform var(--spring-duration) var(--spring),
    opacity var(--sd-fade) var(--se-out);
}

.slip-sheet__body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 0 var(--space-4);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.slip-sheet__copy {
  padding-bottom: var(--space-3);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--leading-relaxed);
}
