/*
 * The Slip Merger (SlipMerger.js) — the Slips category's first screen, over
 * the SureTOOLS tab.
 *
 * The shell is the Odds Converter's, which is the Lineup Builder's, which is
 * the player page's: a fixed page that fades while its sheet rises, at
 * z-index 70 — over the tab panes, under the fixture page's 80 and the player
 * page's 98. Restated here rather than shared for the reason odds-converter.css
 * gives; there are now three copies of it, and the day a fourth tool lands the
 * four want one `.tool-page` between them.
 *
 * The page is two views in one scroller — the pasted codes, and the slip they
 * merged into — so nothing here is pinned and everything scrolls. One bookmaker
 * sits above the codes, because a merge is of one bookmaker.
 *
 * Separation is tonal, as everywhere else in this corner of the app: white
 * cards on the off-white page, the sunken grey inside them, nothing casts a
 * shadow. The **one deliberate exception is the merged slip** — it is not a
 * summary of the controls above it, it is the object the user came for and
 * will send on to somebody else, so it is drawn as a printed slip: notched
 * along both edges, ruled with dots, its code in tracked capitals where the
 * counter's stamp would be.
 *
 * Platform discs carry a brand hue through `--brand`, set inline from
 * `data/slip-merger.js`. That is data reaching the stylesheet, the way a club's
 * colour does — not a token, and never mixed with one.
 */

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

.slip-merger {
  --enter-y: 12px;
  /* The merged slip's notch radius, and the page's gutter. */
  --sm-notch: 8px;
  --sm-gutter: var(--space-4);

  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  max-width: var(--app-max-width);
  margin-inline: auto;
  background: var(--bg);
  opacity: 0;
  transition: opacity var(--duration) var(--easing);
}

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

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

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

  opacity: 1;
}

.slip-merger__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 tab pane under it keeps its place. */
.slip-merger__body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
}

.sm {
  display: flex;
  flex-direction: column;
  padding-bottom: calc(var(--space-8) + var(--safe-bottom));
}

.sm-view {
  display: flex;
  flex-direction: column;
}

/* --- Top row and title ----------------------------------------------------------- */

.sm-top {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-3) 0;
}

.sm-top__gap {
  flex: 1;
}

.sm-title {
  margin: var(--space-3) var(--sm-gutter) 0;
  color: var(--text);
  font-size: var(--text-2xl);
  font-weight: 800;
  letter-spacing: -0.5px;
  line-height: 1.1;
}

/* --- Section labels ---------------------------------------------------------------- */

.sm-label {
  margin: var(--space-5) var(--sm-gutter) var(--space-3);
  color: var(--text);
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
}

.sm-section__sub {
  margin: 0 var(--sm-gutter) var(--space-3);
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: 1.4;
}

/* --- Platform discs ------------------------------------------------------------------ */

/* The monogram on a brand-coloured disc — the Slip Builder's league chip
   placeholder, doing the same job for a bookmaker that has no crest here. */
.sm-disc {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-full);
  background: var(--brand, var(--text-muted));
  color: var(--text-inverse);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  line-height: 1;
}

.sm-disc--sm {
  width: 20px;
  height: 20px;
  font-size: 9px;
}

.sm-disc--lg {
  width: 38px;
  height: 38px;
  font-size: var(--text-xs);
}

/* --- A slip row ------------------------------------------------------------------------ */

.sm-rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0 var(--sm-gutter);
}

.sm-row {
  padding: var(--space-3);
  border-radius: var(--radius-xl);
  background: var(--surface);
  transition: box-shadow var(--sd-fade) var(--se-out);
}

/* A resolved row wears the platform it was booked at down its leading edge —
   the one place the brand is load-bearing rather than decorative, since two
   rows on two bookmakers is the case this tool exists for. */
.sm-row[data-status="loaded"] {
  box-shadow: inset 3px 0 0 var(--brand);
}

.sm-row[data-status="error"] {
  box-shadow: inset 0 0 0 1.5px var(--warning-soft);
}

/* One line, one field. The platform cluster that used to share it moved to the
   top of the screen when a merge became one bookmaker's worth of codes, and a
   letter badge here would only repeat the "Slip A" chip below it. */
.sm-row__main {
  display: flex;
  align-items: center;
}

/* --- The bookmaker ---------------------------------------------------------------------- */

/*
 * One control for the whole merge, above the codes rather than inside each of
 * them. A selector per row would be quietly offering a merge across bookmakers,
 * and there is no such thing: a code is only a slip at the platform that issued
 * it, and the merged slip has to be bookable where its parts came from.
 */
.sm-picker {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: calc(100% - var(--sm-gutter) * 2);
  min-height: 64px;
  margin: var(--space-4) var(--sm-gutter) 0;
  padding: 0 var(--space-3);
  border-radius: var(--radius-xl);
  background: var(--surface);
  text-align: left;
  transition: transform var(--spring-duration) var(--spring);
}

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

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

.sm-picker__label {
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.sm-picker__name {
  color: var(--text);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The rule said out loud, once, under the control that enforces it. */
.sm-picker__note {
  margin: var(--space-2) var(--sm-gutter) 0;
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: 1.4;
}

/* A chevron that leads somewhere points on, rather than down. */
.sm-row__chevron {
  flex: none;
  display: grid;
  place-items: center;
  color: var(--text-muted);
  transform: rotate(-90deg);
}

/* --- The code field ---------------------------------------------------------------------- */

.sm-row__field {
  flex: 1;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  height: 40px;
  padding: 0 5px 0 var(--space-3);
  border-radius: 13px;
  background: var(--surface-sunken);
  cursor: text;
}

/* The ring goes on the field, not on the bare input inside it — the search
   overlay's note, for the same reason: an outline on a nested input traces a
   box nobody drew. */
.sm-row__field:focus-within {
  box-shadow: 0 0 0 2px rgb(var(--accent-rgb) / 0.35);
}

/*
 * Tracked capitals, because that is how a booking code is printed everywhere
 * it is ever seen — on the bookmaker's own slip, in the tipster's broadcast —
 * and a code set as ordinary text stops looking like a code.
 */
.sm-row__input,
.sm-row__code {
  flex: 1;
  min-width: 0;
  color: var(--text);
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sm-row__input {
  height: 100%;
  border: 0;
  background: none;
}

.sm-row__input::placeholder {
  color: var(--text-muted);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  text-transform: none;
}

.sm-row__input:focus-visible {
  outline: none;
}

/* A code being fetched is not a code you are still typing, so it greys until
   the answer lands. */
.sm-row[data-status="loading"] .sm-row__code {
  color: var(--text-muted);
}

.sm-row__paste {
  flex: none;
  height: 30px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-full);
  background: var(--accent);
  color: var(--accent-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  transition:
    background-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

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

.sm-row__copy {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-full);
  color: var(--text-secondary);
  transition:
    background-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

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

/* The one thing on this page that turns continuously, and only while a code is
   actually in the air. The line beside it says the same thing in words, which
   is what lets reduced motion stop it dead. */
.sm-spinner {
  flex: none;
  width: 16px;
  height: 16px;
  margin-right: var(--space-1);
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: var(--radius-full);
  animation: sm-spin 700ms linear infinite;
}

@keyframes sm-spin {
  to {
    transform: rotate(360deg);
  }
}

/* --- The row's second line --------------------------------------------------------------- */

.sm-row__foot {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 24px;
  margin-top: var(--space-2);
}

/* What the row is doing while a code is in the air, in words. */
.sm-row__status {
  flex: none;
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 8px;
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}

.sm-row__chips {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.sm-chip {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  white-space: nowrap;
}

/* Which slip this is on the merged one — the letter every leg is provenanced
   with further down, introduced here where it is assigned. */
.sm-chip--slip {
  background: var(--accent-tint);
  color: var(--accent);
}

.sm-chip--odds {
  background: var(--surface-sunken);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.sm-row__clear {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  margin-left: auto;
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text-muted);
  transition:
    background-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

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

/* --- A row that could not resolve ------------------------------------------------------------ */

/* Never a dead end: the code stays editable and the retry is right there. */
.sm-row__error {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px dashed var(--border);
}

.sm-row__error-text {
  flex: 1;
  color: var(--warning-strong);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: 1.35;
}

.sm-row__retry {
  flex: none;
  height: 28px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-full);
  background: var(--accent-tint);
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  transition: transform var(--spring-duration) var(--spring);
}

/* --- Add another slip --------------------------------------------------------------------------- */

.sm-add {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: calc(100% - var(--sm-gutter) * 2);
  min-height: 56px;
  margin: var(--space-2) var(--sm-gutter) 0;
  padding: 0 var(--space-3);
  border-radius: var(--radius-xl);
  /* Drawn as the outline of a card that is not there yet. */
  box-shadow: inset 0 0 0 1.5px var(--border);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  text-align: left;
  transition:
    background-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

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

.sm-add__mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  background: var(--accent-tint);
  color: var(--accent);
}

/* --- The merge CTA -------------------------------------------------------------------------------- */

.sm-cta {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: var(--space-6) var(--sm-gutter) 0;
}

.sm-merge {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: 54px;
  border-radius: var(--radius-lg);
  background: var(--accent);
  color: var(--accent-text);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  transition:
    background-color var(--sd-fade) var(--se-out),
    color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

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

/* Grey until two codes have actually come back. A CTA that looks alive before
   it can do anything is a promise the screen cannot keep. */
.sm-merge:disabled {
  background: var(--surface-sunken);
  color: var(--text-disabled);
}

.sm-merge__hint {
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  text-align: center;
}

.sm-clear-all {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  align-self: center;
  min-height: 44px;
  margin-top: var(--space-5);
  padding: 0 var(--space-4);
  border-radius: var(--radius-full);
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  transition: transform var(--spring-duration) var(--spring);
}

.sm-clear-all[data-pressed="true"] {
  background: var(--surface-sunken);
}

/* --- The platform sheet ------------------------------------------------------------------------------ */

.sm-platforms {
  display: flex;
  flex-direction: column;
}

.sm-platform {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: 60px;
  padding: var(--space-2) var(--space-1);
  text-align: left;
  transition: transform var(--spring-duration) var(--spring);
}

.sm-platform + .sm-platform {
  border-top: 1px solid var(--border);
}

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

.sm-platform .sm-disc {
  width: 34px;
  height: 34px;
  font-size: var(--text-xs);
}

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

.sm-platform__name {
  color: var(--text);
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
}

/* Rule 4, said before it bites: a platform that will not carry two markets on
   one game is going to ask about it at the merge. */
.sm-platform__note {
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
}

.sm-platform__mark {
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  box-shadow: inset 0 0 0 2px var(--border-strong);
}

.sm-platform[data-current="true"] .sm-platform__mark {
  background: var(--accent);
  box-shadow: inset 0 0 0 2px var(--accent), inset 0 0 0 5px var(--surface);
}

/* --- Clashes -------------------------------------------------------------------------------------------- */

/* The heading is amber only while something is actually waiting on the user;
   once every clash is answered the section stops shouting and becomes a record
   of what was decided. */
.sm-section--clash[data-open="true"] .sm-label {
  color: var(--warning-strong);
}

.sm-clashes {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0 var(--sm-gutter);
}

.sm-clash {
  padding: var(--space-3);
  border-radius: var(--radius-xl);
  background: var(--surface);
  /* The one bordered card on the page. A clash is the only thing here the
     screen is actively waiting on, and tone alone does not carry that. */
  box-shadow: inset 0 0 0 1.5px var(--warning-soft);
  transition: box-shadow var(--sd-fade) var(--se-out);
}

.sm-clash[data-settled="true"] {
  box-shadow: inset 0 0 0 1.5px var(--success-soft);
}

.sm-clash__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-1) var(--space-3);
}

.sm-clash__mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  background: var(--warning-soft);
  color: var(--warning-strong);
  transition:
    background-color var(--sd-fade) var(--se-out),
    color var(--sd-fade) var(--se-out);
}

.sm-clash[data-settled="true"] .sm-clash__mark {
  background: var(--success-soft);
  color: var(--success-strong);
}

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

.sm-clash__match {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  line-height: 1.25;
}

.sm-clash__market {
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
}

.sm-clash__sub {
  margin: 0 var(--space-1) var(--space-3);
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: 1.4;
}

.sm-options {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.sm-option {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: 50px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  text-align: left;
  transition:
    background-color var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

/* The radio's ring and dot, drawn rather than borrowed: `Indicator` is built
   at the slip's 0.75 scale and this page runs at full size. */
.sm-option__mark {
  position: relative;
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  box-shadow: inset 0 0 0 2px var(--border-strong);
  transition: box-shadow var(--sd-fade) var(--se-out);
}

.sm-option__mark::after {
  content: "";
  position: absolute;
  inset: 4px;
  border-radius: var(--radius-full);
  background: var(--accent);
  transform: scale(0);
  transition: transform var(--sd-pop) var(--se-spring);
}

.sm-option[aria-checked="true"] {
  background: var(--accent-tint);
}

.sm-option[aria-checked="true"] .sm-option__mark {
  box-shadow: inset 0 0 0 2px var(--accent);
}

.sm-option[aria-checked="true"] .sm-option__mark::after {
  transform: scale(1);
}

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

.sm-option__sel {
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: 1.25;
}

/* Which slip this side of the argument came off. Without it the user is being
   asked to choose between two anonymous opinions. */
.sm-option__note {
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
}

.sm-option__odds {
  flex: none;
  color: var(--text-secondary);
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}

/* --- The merged slip ------------------------------------------------------------------------------------- */

/*
 * Notched down both long edges, the way a torn ticket is. Two repeating radial
 * masks — one row of half-circles bitten out of the top, one out of the bottom
 * — intersected so the card keeps everything neither of them removed.
 *
 * The base rule is a plain rounded card, and the notches are added only where
 * `mask-composite` exists: without it the two masks would union into no mask at
 * all, which is exactly the card the base rule already drew. Nothing is lost
 * but the teeth.
 */
.sm-receipt {
  position: relative;
  margin: var(--space-4) var(--sm-gutter) 0;
  padding: var(--space-5) var(--space-4) var(--space-4);
  border-radius: var(--radius-xl);
  background: var(--surface);
}

@supports (mask-composite: intersect) or (-webkit-mask-composite: source-in) {
  .sm-receipt {
    border-radius: 0;
    -webkit-mask-image:
      radial-gradient(var(--sm-notch) at 50% 0, #0000 98%, #000 100%),
      radial-gradient(var(--sm-notch) at 50% 100%, #0000 98%, #000 100%);
    mask-image:
      radial-gradient(var(--sm-notch) at 50% 0, #0000 98%, #000 100%),
      radial-gradient(var(--sm-notch) at 50% 100%, #0000 98%, #000 100%);
    -webkit-mask-size: calc(var(--sm-notch) * 2.5) 100%;
    mask-size: calc(var(--sm-notch) * 2.5) 100%;
    -webkit-mask-repeat: repeat-x;
    mask-repeat: repeat-x;
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
  }
}

.sm-receipt__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding-bottom: var(--space-4);
}

/* The line above the code, at the size a printed slip sets its own name. */
.sm-eyebrow {
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.sm-code {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.sm-code__value {
  color: var(--text);
  font-size: 30px;
  font-weight: 800;
  letter-spacing: 0.06em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

/* No code until the slip has stopped arguing with itself: a reference that
   changed under the user would be worse than none at all. */
.sm-code__value[data-pending="true"] {
  color: var(--text-disabled);
  font-size: var(--text-xl);
  letter-spacing: 0;
}

.sm-code__pending {
  max-width: 28ch;
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: 1.4;
  text-align: center;
}

.sm-code__copy {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  transition: transform var(--spring-duration) var(--spring);
}

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

.sm-sources__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
}

.sm-sources__note {
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
}

/* The dotted rules a printed slip is ruled with. A border rather than a row of
   characters, so it never wraps and never gets read out. */
.sm-rule {
  height: 0;
  border-top: 1.5px dashed var(--border);
}

/* --- The legs ------------------------------------------------------------------------------------ */

.sm-legs {
  display: flex;
  flex-direction: column;
  padding: var(--space-2) 0;
  list-style: none;
}

.sm-leg {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) 0;
}

.sm-leg + .sm-leg {
  border-top: 1px solid var(--border);
}

.sm-leg__text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.sm-leg__match {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
}

.sm-leg__teams {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sm-leg__when {
  flex: none;
  color: var(--text-disabled);
  font-variant-numeric: tabular-nums;
}

.sm-leg__sel {
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: 1.25;
}

/*
 * Provenance. Every leg says which pasted slips it came off, because the whole
 * claim this tool makes is that it invented nothing — and a claim nobody can
 * check on the page is not worth making.
 */
.sm-leg__from {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 1px;
}

.sm-leg__letter {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  border-radius: var(--radius-full);
  background: var(--accent-tint);
  color: var(--accent);
  font-size: 10px;
  font-weight: var(--weight-bold);
  line-height: 1;
}

.sm-leg__note {
  color: var(--text-muted);
  font-size: 10px;
  font-weight: var(--weight-medium);
}

/* A leg that rode because the user settled a clash, marked as theirs. */
.sm-leg__tag {
  display: inline-flex;
  align-items: center;
  height: 16px;
  padding: 0 6px;
  border-radius: var(--radius-full);
  background: var(--success-soft);
  color: var(--success-strong);
  font-size: 10px;
  font-weight: var(--weight-bold);
  white-space: nowrap;
}

.sm-leg__odds {
  flex: none;
  color: var(--text);
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}

/* --- Totals ---------------------------------------------------------------------------------------- */

.sm-totals {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) 0 var(--space-3);
}

.sm-total {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.sm-total--odds {
  align-items: flex-end;
  text-align: right;
}

.sm-total__label {
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.sm-total__value {
  color: var(--text);
  font-size: var(--text-xl);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

/* The combined odds are the number the merge exists to produce, so they are
   the largest thing on the paper after the code itself. */
.sm-total--odds .sm-total__value {
  font-size: 28px;
}

.sm-warn {
  padding-bottom: var(--space-2);
  color: var(--warning-strong);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: 1.4;
}

/* --- Where the code is for ------------------------------------------------------------------------------ */

/* A label rather than a control: the merged slip is booked where its parts came
   from, and that was chosen at the top of the codes view. */
.sm-target {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  height: 46px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
}

.sm-target__label {
  flex: 1;
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.sm-target__name {
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  white-space: nowrap;
}

.sm-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
  padding-top: var(--space-3);
}

.sm-action {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: 48px;
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  transition:
    background-color var(--sd-fade) var(--se-out),
    opacity var(--sd-fade) var(--se-out),
    transform var(--spring-duration) var(--spring);
}

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

/* Share is the one thing on this page that leaves it, so it is the one filled
   button on it. */
.sm-action--share {
  background: var(--accent);
  color: var(--accent-text);
}

.sm-action--share[data-pressed="true"] {
  background: var(--accent-pressed);
}

.sm-action:disabled {
  opacity: 0.45;
}

/* --- The About sheet ------------------------------------------------------------------------------------- */

/* The Slip Builder's sheet at this page's full size, not its 0.75 — the same
   three overrides the two tool pages before this one make. */
.slip-merger .slip-sheet__panel {
  max-height: min(84dvh, 760px);
}

.slip-merger .slip-sheet__title {
  padding: var(--space-1) var(--space-4) var(--space-3);
  font-size: var(--text-lg);
}

.slip-merger .slip-sheet__body {
  padding: 0 var(--space-4) var(--space-4);
}

.sm-about {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.sm-about__row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sm-about__term {
  color: var(--text);
  font-size: var(--text-md);
  font-weight: var(--weight-bold);
}

.sm-about__text {
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: 1.45;
}

/* --- Short screens ------------------------------------------------------------------------------------------ */

@media (max-height: 700px) {
  .sm-title {
    font-size: var(--text-xl);
  }

  .sm-code__value {
    font-size: 26px;
  }

  .sm-total--odds .sm-total__value {
    font-size: 24px;
  }
}

/* --- Motion --------------------------------------------------------------------------------------------------- */

/*
 * A number that changed without anybody having pressed it rises through its
 * fade — the Odds Converter's swap.
 */
.sm-total__value[data-anim="swap"] {
  animation: sm-swap var(--sd-pop) var(--se-out);
}

@keyframes sm-swap {
  0% {
    transform: translateY(4px);
    opacity: 0;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

/*
 * The merged slip printing itself. It feeds down out of the top edge the way
 * paper leaves a machine — the one beat this page has, and it fires only when
 * the slip is genuinely a different slip.
 */
.sm-receipt[data-anim="print"] {
  animation: sm-print var(--sd-spring) var(--se-out);
}

@keyframes sm-print {
  0% {
    transform: translateY(-6px);
    opacity: 0.4;
    clip-path: inset(0 0 22% 0);
  }
  100% {
    transform: translateY(0);
    opacity: 1;
    clip-path: inset(0 0 0 0);
  }
}

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

@media (prefers-reduced-motion: reduce) {
  .slip-merger {
    --sd-fade: 100ms;
    --sd-pop: 0ms;
    --sd-spring: 0ms;
    --se-spring: ease-out;
  }

  .slip-merger__sheet {
    transform: none;
  }

  .slip-merger [data-anim] {
    animation: none !important;
  }

  /* The one thing here that never stops turning, which is exactly what this
     setting is asking not to have. The row still says "Getting the slip" in
     words, so nothing is lost but the spin. */
  .sm-spinner {
    animation: none;
    border-top-color: var(--border-strong);
  }
}

/* --- Booking, and what was left off ----------------------------------------------------------------- */

/* The bookmaker refused: the note turns, and a way to ask again sits under it. */
.sm-code__pending[data-tone="error"] {
  color: var(--error);
}

.sm-code__retry {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  height: 30px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  transition: transform var(--spring-duration) var(--spring);
}

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

/* Legs that were on a code and are not on the merge, named. Muted rather than
   alarming: nothing went wrong, a game simply kicked off. */
.sm-skipped {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.sm-skipped__row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
}

.sm-skipped__teams {
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: line-through;
}

.sm-skipped__sel {
  color: var(--text-disabled);
  font-size: var(--text-xs);
}
