/*
 * @cfm/client-tg — client Mini App styles ("Спектр" + Golos Text; IBM Plex Mono
 * is retained only for requisites/IBAN via var(--mono)).
 *
 * A NON-CUSTODIAL referral metasearch UI: an amount-hero calculator, a ranked
 * comparison board, a per-provider consent confirmation, an honest deal tracker
 * ("чей ход"), and a rating prompt. It authors no rate, initiates no payment,
 * and holds no funds. Every server/provider string is inserted via
 * textContent/esc() in app.js — this file only styles the shell.
 *
 * Design tokens + the self-hosted Plex faces live in tokens.css. This sheet is
 * component styling only; it references var(--…) tokens exclusively.
 */

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  /* Telegram's WebView paints its OWN blue rectangle over any tapped element,
     which lands on top of a designed :active state and squares off our radii.
     We draw the pressed state ourselves (see :active below). */
  -webkit-tap-highlight-color: transparent;
}

html,
body {
  min-height: 100%;
  background: var(--bg);
}

body {
  color: var(--ink);
  font-family: var(--ff);
  font-variant-numeric: tabular-nums;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
}

/*
 * A tap must not leave a focus ring behind. Pointer focus is silent; keyboard
 * focus still gets a visible ring (:focus-visible), so dropping the tap ring
 * costs no accessibility.
 */
button:focus {
  outline: none;
}

button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.hidden {
  display: none !important;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------------ *
 * App shell — a phone-width column, one screen visible at a time.
 * ------------------------------------------------------------------ */

.app {
  max-width: var(--col);
  margin: 0 auto;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg);
  box-shadow: 0 0 0 1px var(--line);
}

.screen {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

.tgbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 13px 15px 11px;
  background: var(--bg);
  border-bottom: 1px solid transparent;
}

.tgbar-title {
  flex: 1;
  text-align: center;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.tgbar-back {
  position: absolute;
  left: 12px;
  width: 30px;
  height: 30px;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 24px;
  line-height: 1;
  border-radius: var(--r-md);
}

.tgbar-back:active {
  background: var(--s2);
}

/* The scrollable body of each screen. A flex column so .foot can sink. */
.scroll {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 8px 18px calc(20px + env(safe-area-inset-bottom));
  overflow-y: auto;
}

.center-screen {
  text-align: center;
}

.foot {
  margin-top: auto;
  padding-top: var(--xxl);
}

/* The calculator's CTA lives inside the <form>, not directly under .scroll, so
   .foot's `margin-top:auto` had no flex context to resolve against — the button
   floated mid-screen with dead space beneath it. Make the form the flex column
   that fills .scroll, and the CTA sinks to the bottom the way every other
   screen's does, with the slack becoming deliberate air above it. */
#calc-form {
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* ------------------------------------------------------------------ *
 * Typography helpers
 * ------------------------------------------------------------------ */

.eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.hd {
  font-size: 25px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 6px 0 6px;
}

.sub {
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
  margin-bottom: 14px;
}

.quiet {
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}

.quiet.tiny {
  font-size: 12px;
  margin-top: 8px;
}

.center {
  text-align: center;
}

.mono {
  font-family: var(--mono);
  font-weight: 500;
}

/* The action colour is white, so a link cannot BE the accent — it would read as
   body text. Links are quiet and carry an underline to stay legible as links. */
.link {
  border: 0;
  background: none;
  color: var(--muted);
  font-family: var(--ff);
  font-weight: 600;
  font-size: inherit;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--line2);
}

/* ------------------------------------------------------------------ *
 * Cards / blocks
 * ------------------------------------------------------------------ */

.card {
  background: var(--s1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 14px;
  margin-top: 14px;
}

.block {
  margin-top: 18px;
}

.block-title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 9px;
}

.mini-card {
  background: var(--s1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 12px 13px;
  margin-bottom: var(--l);
}

/* A deliberate group break before the input group (was an accidental 10+14
   margin sum). */
#view-kyc .field:first-of-type {
  margin-top: var(--xxl);
}

.mini-title {
  font-weight: 600;
  font-size: 13px;
  margin-bottom: 3px;
}

/* ------------------------------------------------------------------ *
 * Fields
 * ------------------------------------------------------------------ */

.field {
  display: grid;
  gap: 6px;
  margin-top: 14px;
}

.field > span {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* A short uppercase code (residency ISO), not a full-width free-text box. */
.code-field {
  max-width: 8ch;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

/* The reliance/CDD clause carries the non-custodial truth — give it a real group
   break so it anchors instead of trailing as list-item #2 under the field note. */
.kyc-reliance {
  margin-top: var(--xxl);
}

/* NOTE: keep this selector plain `input` (specificity 0,0,1). Scoping it with
   `:not([type=checkbox])…` raises specificity to (0,2,1) and starts OVERRIDING
   `.amount-input` (0,1,0) — which reintroduced the 14px radius, a border and a
   15px font on the hero amount fields. Checkbox chrome is neutralised in the
   checkbox rule instead (see `.consent input[type="checkbox"]`). */
input,
textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--s1);
  color: var(--ink);
  padding: 12px 13px;
  font-size: 15px;
  font-weight: 600;
  outline: none;
}

textarea {
  min-height: 78px;
  resize: vertical;
  line-height: 1.45;
  font-weight: 400;
}

input::placeholder,
textarea::placeholder {
  color: var(--faint);
  font-weight: 400;
}

input:focus,
textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--asoft);
}

/* ------------------------------------------------------------------ *
 * Buttons
 * ------------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1.5px solid transparent;
  border-radius: var(--r-btn);
  background: var(--s2);
  color: var(--ink);
  padding: 16px;
  font-family: var(--ff);
  font-size: 16px;
  font-weight: 700;
  line-height: 1;
}

.btn.primary {
  font-weight: 800;
}

.btn.block {
  width: 100%;
}

.btn.primary {
  background: var(--accent);
  color: var(--on);
}

.btn.ok {
  background: var(--s1);
  color: var(--ink);
  border-color: var(--line2);
}

.btn.warn {
  background: var(--s1);
  color: var(--warn);
  border-color: color-mix(in srgb, var(--warn) 34%, var(--line));
}

.btn.link-btn {
  background: none;
  color: var(--muted);
  padding: 11px 0 2px;
}

.btn + .btn {
  margin-top: 9px;
}

.btn:active {
  transform: scale(0.99);
  filter: brightness(0.94);
}

.btn:disabled {
  opacity: 0.45;
  pointer-events: none;
}

.row:active,
.resume:active,
.prov-row:active,
.city-row-item:active,
.reroute-alt:active,
.chip:active,
.sheet-x:active,
.locate:active {
  filter: brightness(1.35);
}

.is-busy {
  opacity: 0.6;
  pointer-events: none;
}

/* ------------------------------------------------------------------ *
 * Segmented control (method) + off-screen direction group
 * ------------------------------------------------------------------ */

/* --xxl here is the GROUP BREAK: the hero above, the parameters below. */
.seg-row {
  display: flex;
  gap: var(--m);
  margin-top: var(--xxl);
}

.seg {
  flex: 1;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--s1);
  color: var(--muted);
  padding: 12px 8px;
  font-size: 13.5px;
  font-weight: 600;
  transition:
    color 0.15s,
    background 0.15s,
    box-shadow 0.15s;
}

/* The active method carries its OWN colour on the bottom edge — the identity
   palette's second home (see tokens.css: colour = belonging). */
.seg.is-active {
  background: var(--s2);
  color: var(--ink);
  border-color: var(--line2);
  font-weight: 700;
  box-shadow: inset 0 -3px 0 var(--mc, transparent);
}

.seg[data-method="cash"] {
  --mc: var(--m-cash);
}

.seg[data-method="bank"] {
  --mc: var(--m-bank);
}

.seg[data-method="qr"] {
  --mc: var(--m-qr);
}

/* Our own pressed feedback, now that the WebView's blue box is gone. */
.seg:active {
  background: var(--s2);
}

.seg.is-active:active {
  background: var(--s3);
}

/* ------------------------------------------------------------------ *
 * Calculator — the quote card.
 *
 * Spacing is a HIERARCHY, not one flat rhythm: --l is the working gap, --m
 * binds the rate footnote to the number it explains, --xxl breaks the hero away
 * from the parameters below it.
 * ------------------------------------------------------------------ */

.resume {
  display: flex;
  align-items: center;
  gap: var(--l);
  width: 100%;
  text-align: left;
  background: var(--s1);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  color: var(--ink);
  padding: 12px 14px;
  margin-top: var(--m);
}

.resume-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: var(--r-pill);
  background: var(--pos);
  animation: live 2.4s ease-in-out infinite;
}

@keyframes live {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.3;
  }
}

.resume-tx {
  flex: 1;
  min-width: 0;
}

.resume-t1 {
  display: block;
  font-size: 13px;
  font-weight: 700;
}

.resume-t2 {
  display: block;
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 1px;
}

.resume-go {
  flex: none;
  font-size: 12.5px;
  font-weight: 700;
  background: var(--s3);
  border-radius: var(--r-pill);
  padding: 7px 13px;
}

.qcard {
  background: var(--s1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--xl) 18px;
  margin-top: var(--l);
}

.amount-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
}

.amount-row,
.get-row {
  display: flex;
  align-items: center;
  gap: var(--l);
  margin-top: 6px;
}

.amount-input {
  flex: 1;
  min-width: 0;
  width: 100%;
  border: 0;
  background: none;
  padding: 0;
  font-family: var(--ff);
  font-weight: 800;
  font-size: 42px;
  /* THE caret fix. The base input{} reset gives every input `border-radius:
     var(--r-md)` (14px) + `overflow: clip`, and this bare hero field silently
     inherited it. An input clips its own content — including the CARET and the
     selection — to that rounded rectangle, so at the start of the field the caret
     sits in the rounded corner and gets its top and bottom shaved off (the short
     caret; the selection box is rounded for the same reason). The field has no
     visible border or background, so there is nothing to round: square it off and
     the caret is full height at every position.
     line-height is only the secondary rule — the box must be >= the caret's glyph
     height (~50.7px) or a too-short box (the original 1.1 → 46px) clips it
     vertically; 1.25 gives that with headroom. */
  line-height: 1.25;
  border-radius: 0;
  letter-spacing: -0.02em;
  color: var(--ink);
  caret-color: var(--ink);
  transition: opacity 0.12s;
}

/* Nothing to quote yet — the placeholder is a hint, never a stand-in number. */
.amount-input::placeholder {
  color: var(--faint);
  font-weight: 800;
  opacity: 1;
}

/* The hero amounts are bare numbers on the card, not boxes. A focus ring around
   one reads as chrome nobody asked for — and the caret already says where you
   are typing, so nothing is lost by dropping it here. */
.amount-input:focus,
.amount-input:focus-visible {
  outline: none;
  box-shadow: none;
}

/* Only a genuinely slow board earns a waiting state (see scheduleQuote): the
   DERIVED side dims while its answer is in flight. Never the side being typed. */
.amount-input.is-waiting {
  opacity: 0.4;
}

/* Both currency labels are read-only pair tags — neither is a picker — sitting
   beside a typeable amount, so they are ONE homogeneous element: bare text,
   matched type, no container. A filled pill on only the give side read as a
   different, tappable component next to a plain get label; dropping it makes the
   give/get units true twins and lets the amount stay the sole hero. */
.unit {
  flex: none;
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
}

.qsep {
  display: flex;
  align-items: center;
  gap: var(--l);
  margin: var(--l) 0;
}

.qrule {
  flex: 1;
  height: 1px;
  background: var(--line);
}

.swap {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--s2);
  color: var(--ink);
  transition: transform 0.3s cubic-bezier(0.4, 1.4, 0.5, 1);
}

.swap:active {
  transform: rotate(180deg);
}

/* ------------------------------------------------------------------ *
 * The provider row — the disclosure that the number above is THEIRS.
 * ------------------------------------------------------------------ */

.prov-row {
  display: flex;
  align-items: center;
  gap: var(--l);
  width: 100%;
  text-align: left;
  border: 0;
  border-top: 1px solid var(--line);
  background: none;
  color: var(--ink);
  margin-top: var(--xl);
  padding: var(--l) 0 0;
}

/* A provider's mark: a monogram until it uploads a logo, in the colour hashed
   from its name. In "Спектр" this is where the app's only colour lives. */
.mark {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: var(--r-pill);
  color: var(--mark-ink);
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* Sized to the offer amount's line box (below), so the top-aligned mark centres
   on the FIRST line — the amount — instead of riding high above the block. */
.mark.sm {
  width: 28px;
  height: 28px;
  font-size: 12px;
}

.prov-mid {
  flex: 1;
  min-width: 0;
}

.prov-name {
  display: block;
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.prov-rate {
  display: block;
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 1px;
}

.prov-end {
  display: flex;
  align-items: center;
  gap: var(--m);
  flex: none;
}

/* Not the largest amount → the honest delta, never an empty gap. */
.prov-tag {
  font-size: 11px;
  font-weight: 600;
  color: var(--faint);
}

.prov-tag.is-top {
  color: var(--pos);
  font-weight: 700;
}

.chev {
  display: flex;
  color: var(--faint);
}

.quote-note {
  border-top: 1px solid var(--line);
  margin-top: var(--xl);
  padding-top: var(--l);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}

/* The footnote belongs to the NUMBER above it (--m), then the parameters
   below start a new group (--xxl). */
.disclose {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: var(--m);
  padding: 0 2px;
}

.disclose .link {
  font-size: inherit;
}

/* A plain settings row (city). */
.row {
  display: flex;
  align-items: center;
  gap: var(--l);
  width: 100%;
  text-align: left;
  background: var(--s1);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  color: var(--ink);
  padding: 13px 15px;
  margin-top: var(--l);
}

.row-ic {
  display: flex;
  flex: none;
  color: var(--faint);
}

.row-v {
  flex: 1;
  font-size: 14px;
  font-weight: 600;
}

.row-s {
  font-size: 12px;
  color: var(--faint);
}

/* ------------------------------------------------------------------ *
 * Sheets — overlays above the current screen (offers, city). They never
 * unmount the calculator, so the amount you typed survives the trip.
 * ------------------------------------------------------------------ */

.veil {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: rgba(0, 0, 0, 0.6);
}

.sheet {
  position: fixed;
  z-index: 21;
  bottom: 0;
  left: 50%;
  width: min(var(--col), 100%);
  max-height: 84vh;
  max-height: 84dvh;
  display: flex;
  flex-direction: column;
  background: var(--s1);
  border-top: 1px solid var(--line2);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  padding: var(--m) var(--xl) calc(var(--xl) + env(safe-area-inset-bottom));
  /* Off-screen by default; translateX keeps it centred in the phone column. */
  transform: translate(-50%, 102%);
  transition: transform 0.34s cubic-bezier(0.32, 0.72, 0.24, 1);
}

.sheet.is-up {
  transform: translate(-50%, 0);
}

.grab {
  width: 36px;
  height: 4px;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--line2);
  margin: 2px auto var(--l);
}

.sheet-head {
  display: flex;
  align-items: flex-start;
  gap: var(--m);
  padding-bottom: var(--l);
}

/* Title + contextual summary stack as a title/caption pair; the summary is a
   caption BENEATH the title, never wedged inline competing with it and the X. */
.sheet-headings {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sheet-title {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.sheet-sub {
  font-size: 12.5px;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

.sheet-x {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--s3);
  color: var(--muted);
}

.sheet-list {
  overflow-y: auto;
  margin: 0 -2px;
  padding: 0 2px;
}

/* The disclaimer and the "Как считается рейтинг" link stacked, not fighting for
   one row's width: sharing a space-between row squeezed the link into a 3-line
   wrap. Each now owns its line — the link stays a single, quiet affordance. */
.sheet-foot {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--m);
  flex: none;
  padding-top: var(--l);
}

.sheet-foot .quiet.tiny {
  margin-top: 0;
}

#offers-rank-link {
  align-self: flex-start;
  white-space: nowrap;
  font-size: 13px;
  padding: 4px 0;
}

.locate {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--m);
  width: 100%;
  padding: 13px;
  border: 1px dashed var(--line2);
  border-radius: var(--r-md);
  background: none;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  margin-bottom: var(--m);
}

.city-row-item {
  display: flex;
  align-items: center;
  gap: var(--l);
  width: 100%;
  text-align: left;
  border: 0;
  border-radius: var(--r-md);
  background: var(--s2);
  color: var(--ink);
  padding: 13px 12px;
}

.city-row-item.is-on {
  background: var(--s3);
}

.city-n {
  flex: 1;
  font-size: 14.5px;
  font-weight: 600;
}

.city-c {
  font-size: 11.5px;
  color: var(--faint);
}

/* ------------------------------------------------------------------ *
 * Offers
 * ------------------------------------------------------------------ */

.chips-row {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding-bottom: var(--l);
}

.chip {
  flex: none;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--s2);
  color: var(--muted);
  padding: 8px 14px;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
}

.chip.is-active {
  background: var(--accent);
  color: var(--on);
  font-weight: 700;
}

.list {
  display: flex;
  flex-direction: column;
  gap: var(--m);
}

.offer-card {
  display: flex;
  align-items: flex-start;
  gap: var(--l);
  width: 100%;
  text-align: left;
  background: var(--s2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  padding: 14px;
  color: var(--ink);
  font-family: var(--ff);
}

/* The card you picked is bordered in that provider's OWN colour. */
.offer-card.is-chosen {
  border-color: var(--pc, var(--line2));
  background: var(--s3);
}

.offer-card:active {
  background: var(--s3);
}

.offer-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.offer-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--m);
}

.offer-get {
  font-size: 23px;
  font-weight: 800;
  letter-spacing: -0.01em;
  /* An explicit line box (== the 28px mark) so the leading mark aligns to the
     amount's optical centre; tabular figures keep the column from jittering. */
  line-height: 28px;
  font-variant-numeric: tabular-nums;
}

.offer-get small {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--muted);
  margin-left: 4px;
}

.offer-delta {
  flex: none;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--faint);
}

.offer-delta.best {
  color: var(--pos);
  font-weight: 700;
}

.offer-name {
  font-size: 13.5px;
  font-weight: 700;
}

.offer-rate {
  flex: none;
  font-size: 11.5px;
  color: var(--faint);
}

.offer-facts {
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
  margin-top: 2px;
}

.fact {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.05);
  padding: 4px 9px;
  border-radius: var(--r-pill);
}

/* ------------------------------------------------------------------ *
 * Summary list (confirm + order details + mismatch) — <dl class="sum">
 * ------------------------------------------------------------------ */

.sum {
  display: grid;
  grid-template-columns: auto 1fr;
  background: var(--s1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  margin-top: 8px;
}

.sum dt,
.sum dd {
  padding: 11px 13px;
  border-top: 1px solid var(--line);
  font-size: 13.5px;
}

.sum dt {
  color: var(--muted);
}

.sum dd {
  text-align: right;
  font-weight: 600;
  word-break: break-word;
}

.sum dt:first-of-type,
.sum dd:first-of-type {
  border-top: 0;
}

/* ------------------------------------------------------------------ *
 * How-it-works line + consent
 * ------------------------------------------------------------------ */

/* A quiet framing note, one group-break below the summary. It sits on CARD
   level (--s1 + hairline), not the lighter inset --s2 — a top-level --s2 pill
   made muted boilerplate the brightest, most button-like thing on the screen. */
.how {
  margin-top: var(--xxl);
  padding: 11px 13px;
  background: var(--s1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.45;
}

/* The consent box is the act the screen exists for, so it separates as its own
   group (a real --xxl break, not the off-token 14px paragraph gap it had). */
.consent {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 12px;
  background: var(--s1);
  margin-top: var(--xxl);
}

/* Confirm screen focal point: the caption is muted (not the faintest ink on the
   page) and the payout leads as a hero, so the one decision screen opens on WHAT
   you get rather than reading as a flat receipt. Scoped to #confirm-kv so the
   shared order-details .sum table is untouched. */
#view-confirm .amount-label {
  color: var(--muted);
}

#confirm-kv .is-lead {
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Neutralise the base text-field chrome ON the checkbox itself (higher
   specificity than the plain `input` reset), so the tick stays a native
   checkbox with no stray border/radius/background/focus-halo — WITHOUT raising
   the base reset's specificity and clobbering .amount-input. */
.consent input[type="checkbox"] {
  width: 21px;
  height: 21px;
  flex: none;
  margin-top: 1px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  accent-color: var(--accent);
}

.consent-text {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink);
}

/* ------------------------------------------------------------------ *
 * Order status — "чей ход" pill, heading, timer, timeline
 * ------------------------------------------------------------------ */

.turn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--aink);
  background: var(--asoft);
  padding: 4px 10px;
  border-radius: var(--r-pill);
  margin: 4px 0 8px;
}

.turn i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.turn.wait {
  color: var(--muted);
  background: var(--s2);
}

.turn.wait i {
  background: var(--faint);
}

.shd {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin-bottom: 4px;
}

.stm {
  font-size: 12.5px;
  color: var(--muted);
  margin-bottom: 6px;
}

.stm b {
  color: var(--ink);
  font-family: var(--mono);
  font-weight: 500;
}

.tl {
  margin: 14px 0 4px;
  padding-left: 3px;
  list-style: none;
}

.tl li {
  display: flex;
  gap: 12px;
  padding-bottom: 14px;
  position: relative;
}

.tl li:last-child {
  padding-bottom: 0;
}

.tl li::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 15px;
  bottom: -1px;
  width: 2px;
  background: var(--line);
}

.tl li:last-child::before {
  display: none;
}

.tl .d {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  flex: none;
  margin-top: 1px;
  z-index: 1;
  border: 2px solid var(--line);
  background: var(--bg);
}

.tl .done .d {
  background: var(--accent);
  border-color: var(--accent);
}

.tl .done::before {
  background: var(--accent);
}

/* The active node is the anchor — "now" must be the brightest mark, not a hollow
   ring lost on the near-black ground. Filled + a soft halo sets it apart from the
   solid (but ring-less) done dots. */
.tl .act .d {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent);
}

.tl .t {
  font-size: 13px;
  line-height: 1.35;
}

.tl .act .t {
  font-weight: 600;
}

.tl .fut .t {
  color: var(--faint);
}

.tl .t small {
  display: block;
  color: var(--muted);
  font-size: 11px;
  font-weight: 400;
  margin-top: 1px;
}

/* Requisites + trust line */

.reqs {
  background: var(--s2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 11px 12px;
  margin: 4px 0 12px;
}

.reqs pre {
  white-space: pre-wrap;
  word-break: break-word;
  font-family: var(--mono);
  font-weight: 500;
  font-size: 12.5px;
  color: var(--ink);
}

#btn-copy-reqs {
  margin-top: 11px;
}

/* Exception-panel body copy (mismatch / refund / dispute): calm and present in
   full ink, not the app's quietest muted-tiny tier — a stressful moment needs
   the reassurance to anchor, never to disappear. */
.exc-intro {
  color: var(--ink);
  font-size: 13.5px;
  line-height: 1.5;
  margin-bottom: var(--l);
}

/* "Что-то пошло не так?" as a person asking, not an ALL-CAPS system eyebrow. */
.exc-opener {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: var(--m);
}

/* "You pay the provider directly; the platform never touches your money" is the
   product's one differentiator — it must land with weight (ink), not whisper in
   muted fine-print. The shield icon keeps the accent. */
.trust {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 12.5px;
  color: var(--ink);
  line-height: 1.4;
  margin: var(--l) 0 var(--xl);
}

.trust-ic {
  flex: none;
  color: var(--accent);
  margin-top: 1px;
}

/* ------------------------------------------------------------------ *
 * Cash collection — the code + QR the client presents at the office.
 * ------------------------------------------------------------------ */

.pickup-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--m);
  background: var(--s2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--xl) 16px;
  margin: 8px 0 12px;
}

/* The QR sits on white — a scanner needs the light quiet-zone the SVG carries. */
.pickup-qr {
  width: 148px;
  height: 148px;
  border-radius: var(--r-md);
  background: #fff;
  padding: 8px;
}

.pickup-qr svg {
  display: block;
  width: 100%;
  height: 100%;
}

.pickup-code-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
}

.pickup-code {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 30px;
  line-height: 1.1;
  letter-spacing: 0.18em;
  color: var(--ink);
  user-select: all;
}

/* Saved instruments (returning short path — masked, read-only) */

.saved-instrument {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 10px 12px;
  background: var(--s1);
}

.si-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  word-break: break-word;
}

.si-masked {
  font-size: 13px;
  white-space: nowrap;
}

/* Reroute alternatives */

.reroute-alt {
  display: flex;
  align-items: center;
  gap: var(--l);
  width: 100%;
  text-align: left;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 11px 12px;
  background: var(--s1);
  color: var(--ink);
}

/* The chosen alternative is bordered in that provider's OWN colour, like the
   board — reassigning to a stranger should still speak the "colour = belonging"
   language, not a generic white. */
.reroute-alt.is-selected {
  border-color: var(--pc, var(--accent));
  background: var(--asoft);
}

.alt-mid {
  flex: 1;
  min-width: 0;
}

.alt-name {
  font-size: 13px;
  font-weight: 600;
  word-break: break-word;
}

.alt-amount {
  flex: none;
  font-size: 14px;
  white-space: nowrap;
}

/* Names the provider the fresh consent is actually for. */
.reroute-chosen {
  color: var(--ink);
  font-weight: 600;
  font-size: 13px;
  margin: var(--l) 0 var(--m);
}

/* ------------------------------------------------------------------ *
 * Rating / done
 * ------------------------------------------------------------------ */

.ok-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin: 24px auto 16px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on);
}

.ok-badge.soft {
  width: 48px;
  height: 48px;
  background: var(--asoft);
  color: var(--accent);
}

/* The completion climax — the emotional payoff of the whole flow. The badge pops
   in and the check draws itself, once, when the screen appears (JS toggles
   .is-in). Honoured only where motion is welcome; otherwise it just renders. */
@media (prefers-reduced-motion: no-preference) {
  .ok-badge.is-in {
    animation: badge-pop 0.42s cubic-bezier(0.32, 0.72, 0.24, 1) both;
  }
  .ok-badge.is-in svg path {
    stroke-dasharray: 40;
    stroke-dashoffset: 40;
    animation: check-draw 0.45s ease 0.16s forwards;
  }
  .ok-badge.is-in ~ .dhd,
  .ok-badge.is-in ~ .dsub {
    animation: rise-in 0.4s ease 0.1s both;
  }
}

@keyframes badge-pop {
  0% {
    transform: scale(0.6);
    opacity: 0;
  }
  60% {
    transform: scale(1.08);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

@keyframes check-draw {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes rise-in {
  0% {
    transform: translateY(6px);
    opacity: 0;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

.dhd {
  font-size: 23px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-bottom: 4px;
}

.dsub {
  color: var(--muted);
  font-size: 14px;
  margin-bottom: 20px;
}

/* No 20px void under a missing subtitle (the rating screen when there's no
   completed-summary line). */
.dsub:empty {
  margin-bottom: 0;
}

/* The thank-you screen is a clean close: centre the badge + copy as a group with
   the CTA just under, instead of pinning a small badge to the top over a void. */
#view-done .scroll {
  justify-content: center;
}

#view-done .foot {
  margin-top: var(--xxl);
}

.dsub b {
  color: var(--ink);
  font-weight: 600;
}

.rate {
  text-align: center;
  border-top: 1px solid var(--line);
  padding-top: 18px;
}

.rate-prompt {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 10px;
}

.stars {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-bottom: 14px;
}

.star {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--s1);
  color: var(--faint);
  font-size: 21px;
  font-weight: 700;
  transition:
    color 0.12s,
    background 0.12s,
    border-color 0.12s,
    transform 0.1s;
}

/* The thing the user is invited to touch must respond. */
.star:active {
  transform: scale(0.9);
  background: var(--s2);
}

.star.is-on {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--asoft);
}

.toggle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 4px;
  text-align: left;
}

.toggle-row input[type="checkbox"] {
  width: 20px;
  height: 20px;
  flex: none;
  accent-color: var(--accent);
}

.toggle-row span {
  font-size: 13px;
  color: var(--muted);
}

/* ------------------------------------------------------------------ *
 * Notices
 * ------------------------------------------------------------------ */

.notice {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--s2);
  color: var(--ink);
  padding: 11px 12px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  margin-top: 12px;
}

.notice.is-info {
  border-color: color-mix(in srgb, var(--accent) 26%, var(--line));
  background: var(--asoft);
  color: var(--aink);
}

.notice.is-ok {
  border-color: color-mix(in srgb, var(--pos) 30%, var(--line));
  background: color-mix(in srgb, var(--pos) 9%, var(--s1));
  color: var(--pos);
}

.notice.is-error {
  border-color: color-mix(in srgb, var(--danger) 30%, var(--line));
  background: color-mix(in srgb, var(--danger) 8%, var(--s1));
  color: var(--danger);
}

/* Quiet-disclosure inline note (fallback when Telegram's native alert is absent). */
.explainer {
  margin-top: 12px;
  padding: 11px 12px;
  background: var(--s2);
  border-radius: var(--r-md);
}
