/* The pay.iamlukia.com redesign's system (PAY-KITS-DEMO-REDESIGN-STYLE-1), from the handoff vendored
   at docs/handoff-2026-09-30-pay-redesign/. Its README's token list and the prototype's inline
   values are the source; where this file departs from them it says so beside the rule.

   Still deliberately NOT a copy of the lab's /payments/ showcase. Those two are different
   artefacts — one a seeded fiction, one a live table of real sandbox payments — and making them
   resemble each other would create a cross-repo duplication with nothing detecting drift between
   them.

   Every colour is a light-dark() pair under color-scheme: light dark, so the page follows the OS
   and there is no toggle. No shadows anywhere: depth is borders and surface contrast only. */

/* Self-hosted rather than linked from Google Fonts, decided at implementation as the row asked.
   A link would have been this origin's first third-party request — no CSP exists in this repo to
   stop it — and every page view would hand Google the visitor's address, on a demo whose checkout
   tells the visitor that nothing here identifies them. Latin subsets only, from the same files
   Google serves; the OFL texts sit beside them. A glyph outside the subset falls back to the
   system face, which is what the glyph discs below rely on anyway. */
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/instrument-sans-latin.woff2") format("woff2");
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/jetbrains-mono-500-latin.woff2") format("woff2");
}

:root {
  color-scheme: light dark;

  --bg: light-dark(#f4f6f8, #0f1215);
  --surface: light-dark(#ffffff, #181c21);
  --input: light-dark(#ffffff, #0f1215);
  --line: light-dark(#e3e7ec, #242a32);
  --input-line: light-dark(#d5dae1, #2f3641);
  --divider: light-dark(#eef1f4, #20262e);
  --text: light-dark(#111418, #e8ebef);
  --muted: light-dark(#5f6975, #98a2ad);

  --brand: #0f3d24;
  --on-brand: #ffffff;
  --on-brand-muted: #b9d9c4;

  /* Two accents, and the split is a measured departure from the handoff. Its #1f8a4c is right as
     a FILL (discs, progress, the brand mark) and short of WCAG AA as small TEXT: 4.04:1 on the
     light page, 4.29:1 on the dark one and 3.26:1 on the dark green chip. The handoff already
     names #3fb26f as "bright on dark", so dark text uses it (6.99:1 on the page, 5.30:1 on the
     chip); light text is darkened the least that clears 4.5:1 on every light surface it sits on
     (#187a41: 4.97 page, 5.39 card, 4.75 tint, 5.21 amber row). */
  --accent: #1f8a4c;
  --accent-text: light-dark(#187a41, #3fb26f);
  --accent-bright: #3fb26f;

  --tint: light-dark(#e6f4ec, #14301f);
  --tint-muted: light-dark(#3d5a48, #98c2a8);
  --tint-line: light-dark(#c7e0d0, #2f5a3e);

  --amber: light-dark(#8a5a00, #f0c060);
  --amber-chip: light-dark(#fff4d6, #3a2c0c);
  --amber-row: light-dark(#fffbf0, #181610);
  --amber-line: light-dark(#f0c060, #8a5a00);
  --amber-dot: #c98a00;

  --red: light-dark(#8a2f2f, #f09a9a);
  --red-chip: light-dark(#fbe7e7, #3a1a1a);

  --neutral: light-dark(#e9edf1, #20262e);
  --numeral: light-dark(#c5cad2, #3a424d);

  /* The merchant's mark (PAY-KITS-CHECKOUT-LINK-ACCENT-UNMEASURED-1). A checkout's accent, 0 to 3,
     indexes four tokens named as the apps name theirs — ink, ok, created, link — and colours the
     mark ONLY: the trading name's initial, in --bg, on a --mark-N tile. A logo replaces the mark.
     The kicker, the Pay button, status words and money keep the system's colours on every accent,
     the apps' rule, so a merchant's choice can never make the page illegible. --link is the one
     new colour; the other three are tokens above, already measured as text.

     Figures for the initial (--bg) on each tile, light / dark. MarkContrastTest recomputes every
     one from this file's own values and fails on a drift or on anything under 4.5:
       --mark-0  ink      17.0474 / 15.7122
       --mark-1  ok        4.9717 /  6.9869
       --mark-2  created   5.4710 / 11.1069
       --mark-3  link      7.5148 /  8.8539 */
  --link: light-dark(#1d4f91, #8db4ee);
  --mark-0: var(--text);
  --mark-1: var(--accent-text);
  --mark-2: var(--amber);
  --mark-3: var(--link);

  --gutter: clamp(20px, 5vw, 48px);
  --sans: "Instrument Sans", system-ui, -apple-system, "Helvetica Neue", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font: 16px/1.5 var(--sans);
  color: var(--text);
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
  isolation: isolate;
}

/* The ground fills the whole window (PORTFOLIO-SITES-FILL-THE-VIEWPORT-1). Brave draws a raster
   tile holding only the ground colour as a flat compositor fill, outside the colour-profile
   transform, and a tile holding content colour-managed, so a page shorter than the window can show
   a band a few levels off from a tile boundary down. This fixed backdrop is one solid layer over
   the viewport, so every tile reads alike; `isolation: isolate` keeps it above any ground an
   element paints for itself. Ported from circle-connect's base.css with that addition, measured on
   readlater. No headless engine reproduces the band, so no test here can see it.

   It is screen-only: the receipt's print sheet sets a white body, and a backdrop above it would
   print the page ground instead wherever background printing is on. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--bg);
}

@media print {
  body::before { display: none; }
}

main { flex: 1 0 auto; min-width: 0; }

a { color: inherit; }
a:focus-visible, button:focus-visible, input:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

h1, h2, p { margin: 0; text-wrap: pretty; }

code, .mono { font: 500 13px var(--mono); }
code {
  background: var(--neutral);
  padding: 2px 6px;
  border-radius: 5px;
}

@keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.7); } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ---------------------------------------------------------------- nav, progress, footer */

.nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  padding: 20px var(--gutter);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
  font-weight: 700;
  text-decoration: none;
}
.brand-disc {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 22px;
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
}
.nav-links a { text-decoration: none; }
.nav-links a:hover { color: var(--text); }
.nav-links a[aria-current="page"] { color: var(--text); font-weight: 600; }

/* The landing's nav sits inside the hero, on the brand green. */
.nav--hero { padding: 20px 0; border-bottom: 0; }
.nav--hero .brand-disc { background: var(--accent-bright); }
.nav--hero .nav-links { color: var(--on-brand-muted); }
.nav--hero .nav-links a:hover { color: var(--on-brand); }
.nav--hero .nav-cta { color: var(--on-brand); font-weight: 600; }

/* Static per page — 25 % on checkout, 75 % while the return page waits, 100 % once confirmed. A
   progress bar that animated toward a state nobody has reported would be the redirect-as-proof
   mistake drawn as a graphic. */
.progress {
  height: 5px;
  background: linear-gradient(90deg, var(--accent) var(--done, 0%), var(--line) var(--done, 0%));
}
.progress--25 { --done: 25%; }
.progress--75 { --done: 75%; }
.progress--100 { --done: 100%; }
.progress--stopped { background: var(--red); }
/* The lapsed bar: --muted, a non-text mark, 5.15 light / 7.25 dark on --bg. */
.progress--lapsed { background: var(--muted); }

.foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 16px;
  padding: 18px var(--gutter);
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--muted);
}
.foot code { font-size: 12px; background: none; padding: 0; }

/* ---------------------------------------------------------------- shared type and controls */

.kicker { font-size: 13px; font-weight: 600; color: var(--accent-text); }

.title {
  font-size: clamp(28px, 4vw, 36px);
  line-height: 1.08;
  letter-spacing: -.025em;
  font-weight: 700;
  text-wrap: balance;
}
.title--status { font-size: clamp(26px, 4vw, 34px); line-height: 1.1; }

.lead { color: var(--muted); font-size: 16px; line-height: 1.5; }
.footnote { font-size: 13px; color: var(--muted); line-height: 1.5; }
/* The app's claim code on signin/open-app.html: read off one screen and typed into another, so large,
   monospaced and spaced, and never wrapped inside its eight characters. */
.sign-in-code { margin: 4px 0; }
.sign-in-code code { font: 600 clamp(28px, 7vw, 40px)/1.2 var(--mono); letter-spacing: .12em; white-space: nowrap; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font: 600 15px/1.2 var(--sans);
  padding: 14px 22px;
  border: 1px solid transparent;
  border-radius: 12px;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { opacity: .92; }
.btn:disabled { opacity: 1; cursor: default; }
.btn--primary { background: var(--brand); color: var(--on-brand); }
.btn--secondary { background: var(--surface); border-color: var(--input-line); color: inherit; }
.btn--light { background: #ffffff; color: var(--brand); }
.btn--ghost { background: transparent; border-color: rgba(255, 255, 255, .3); color: var(--on-brand); }
.btn--block { width: 100%; font-size: 16px; padding: 15px; }

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 12px;
  justify-content: center;
  align-items: center;
}

.message { font-size: 14px; font-weight: 600; }
.message--error { color: var(--red); }
.message--notice { color: var(--accent-text); }

/* The pulse, on "Listening for PayFast" and on CREATED rows still inside the ITN wait. Off under
   reduced motion along with every other animation here — the dot still shows, it just holds. */
.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
  animation: pulse 1.4s ease-in-out infinite;
}
.dot--accent { background: var(--accent); }
.dot--bright { background: var(--accent-bright); }
.dot--amber { background: var(--amber-dot); }

/* ---------------------------------------------------------------- page shells */

/* A centred column under the nav: checkout, return. */
.page {
  display: grid;
  align-content: start;
  justify-items: center;
  gap: 28px;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  padding: clamp(32px, 6vw, 56px) var(--gutter);
  text-align: center;
}
.intro { display: grid; gap: 10px; justify-items: center; max-width: 540px; }
.intro--narrow { max-width: 480px; }
/* A merchant's link page (batch 378.4): their logo above their name. Shape only — no colour, so
   nothing here owes a contrast figure. The image is MerchantLogo's re-encoded square PNG. */
.merchant-logo { display: block; width: 56px; height: 56px; border-radius: 12px; object-fit: cover; }
/* The mark: a 56 px tile in the merchant's accent holding their initial in --bg. A logo replaces it
   and has no tile behind it, as on the apps: a transparent logo would vanish on a dark accent. */
.mark {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 14px;
  overflow: hidden;
  color: var(--bg);
  font-size: 24px;
  font-weight: 700;
}
.m-logo-set { border: 1px solid var(--line); border-radius: 14px; }
.mark--0 { background: var(--mark-0); }
.mark--1 { background: var(--mark-1); }
.mark--2 { background: var(--mark-2); }
.mark--3 { background: var(--mark-3); }

/* One glyph, one heading, a paragraph: cancel and every edge page. */
.status-page {
  min-height: 70vh;
  display: grid;
  place-items: center;
  padding: 40px var(--gutter);
  text-align: center;
}
.status-page--brand { min-height: 80vh; background: var(--brand); color: var(--on-brand); }
.status-page--brand .lead,
.status-page--brand .footnote { color: var(--on-brand-muted); }
.status-page--brand strong { color: var(--on-brand); }
.stack { display: grid; gap: 14px; justify-items: center; max-width: 440px; }
.stack--wide { max-width: 480px; gap: 16px; }

/* The glyph discs (✓ × ✉ ↩ ⏱ ? →) are decoration and every one carries aria-hidden; the heading
   beside it says the same thing in words. */
.disc {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 18px;
  flex: none;
}
.disc--neutral { background: var(--neutral); color: var(--muted); }
.disc--tint { background: var(--tint); color: var(--accent-text); }
.disc--on-brand { background: rgba(255, 255, 255, .12); color: var(--on-brand); }

/* ---------------------------------------------------------------- landing */

.hero {
  background: var(--brand);
  color: var(--on-brand);
  padding: 0 var(--gutter) clamp(36px, 6vw, 56px);
}
.hero-body {
  display: grid;
  gap: 20px;
  max-width: 600px;
  padding-top: clamp(24px, 5vw, 44px);
}
.eyebrow {
  justify-self: start;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--accent-bright);
}
.hero h1 {
  font-size: clamp(36px, 6vw, 56px);
  line-height: 1.02;
  letter-spacing: -.03em;
  font-weight: 700;
}
.hero-lead { font-size: clamp(16px, 2vw, 19px); line-height: 1.5; color: var(--on-brand-muted); }
.hero .actions { justify-content: flex-start; gap: 12px; margin-top: 6px; }

/* 1280px, not the 1100px every other page uses: pass 2 (batch 383.1, delta (f)) lets the step cards
   grow on a desktop, and the extra width is where they grow into. */
.landing-body {
  display: grid;
  gap: 24px;
  max-width: 1280px;
  margin: 0 auto;
  padding: clamp(20px, 4vw, 40px) var(--gutter);
}
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Every clamp() below is pass 2's desktop scale-up, at the handoff's values. Each floor is the phone
   size, within 2px of pass 1's fixed one; the growth is all above it. */
.step {
  display: grid;
  gap: 14px;
  align-content: space-between;
  min-height: clamp(160px, 21vw, 290px);
  padding: clamp(24px, 3vw, 40px) clamp(22px, 2.8vw, 34px);
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--surface);
}
.step > div { display: grid; gap: 4px; }
.step-n { font-size: clamp(40px, 5.6vw, 76px); font-weight: 700; letter-spacing: -.04em; line-height: 1; color: var(--numeral); }
.step-title { font-size: clamp(15px, 1.8vw, 22px); font-weight: 600; }
.step-body { font-size: clamp(13.5px, 1.35vw, 17px); line-height: 1.45; opacity: .8; }
.step--live { background: var(--brand); color: var(--on-brand); }
.step--live .step-n { color: var(--accent-bright); }
.live-caption { display: flex; gap: 10px; align-items: center; font-size: 14px; color: var(--muted); }

/* ---------------------------------------------------------------- checkout */

.form-card {
  display: grid;
  gap: 16px;
  width: 100%;
  max-width: 440px;
  padding: clamp(18px, 3vw, 26px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  text-align: left;
}
.field { display: grid; gap: 6px; font-size: 13px; font-weight: 600; color: var(--muted); }

/* Inputs carry min-width: 0 and a small size attribute in the markup, so their intrinsic width
   never widens the column on a 390 px phone. */
.text-input {
  width: 100%;
  min-width: 0;
  font: 16px var(--sans);
  padding: 13px 14px;
  border: 1px solid var(--input-line);
  border-radius: 12px;
  background: var(--input);
  color: var(--text);
}
.amount-box {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid var(--input-line);
  border-radius: 12px;
  background: var(--input);
}
.amount-box:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.amount-prefix { font-size: 20px; font-weight: 600; color: var(--muted); }
.amount-input {
  flex: 1;
  width: 100%;
  min-width: 0;
  font: 600 24px var(--sans);
  font-variant-numeric: tabular-nums;
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--text);
}
/* The box draws the focus ring for it, so the input's own would be a second ring inside the first. */
.amount-input:focus-visible { outline: none; }
.form-card .footnote { text-align: center; }
/* A payment link's item and amount (batch 340.6): shown in the inputs' place, set by the merchant. */
.fixed-amount { font: 600 24px var(--sans); font-variant-numeric: tabular-nums; color: var(--text); }
.fixed-item { font: 400 16px var(--sans); color: var(--text); overflow-wrap: anywhere; }
/* A subscription's amount sub-line (design pass 15 § 3.1.4, batch 418.3): mono 12 dim, under the amount.
   --muted on --surface, the pair the terms' keys use: 5.58 light / 6.61 dark. */
.fixed-amount-sub { display: block; font: 500 12px var(--mono); color: var(--muted); }
/* A payment link's micro-label (design pass 13 § 1.2, PublicLink.dc.html): --muted on --bg, 5.15 light /
   7.25 dark. Upper-cased here, so the trading name inside it is sent as the merchant typed it. */
.link-micro {
  font: 500 11px var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  overflow-wrap: anywhere;
}

/* A recurring link's terms (design pass 14 § 3.2, PublicLink.dc.html terms=subscription|card): a 96px key
   column beside each sentence, a rule between rows, as drawn. Inside the form card, so the heading and
   keys are --muted on --surface 5.58 light / 6.61 dark, and the sentences --text on --surface 18.47 /
   14.31. The one weight of the mono face this site ships is 500, so the keys are 500, not the board's 400. */
.link-terms { display: grid; gap: 4px; text-align: left; min-width: 0; }
.link-terms-heading {
  font: 500 11px var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
}
.terms { margin: 0; border-top: 1px solid var(--line); }
.term {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 12px;
  padding: 10px 2px;
  border-bottom: 1px solid var(--line);
}
.term dt { font: 500 12.5px var(--mono); color: var(--muted); }
.term dd { margin: 0; font-size: 14px; line-height: 1.5; color: var(--text); overflow-wrap: anywhere; }

/* The privacy page (PAY-DEMO-NO-PRIVACY-PAGE-ON-PAY-IAMLUKIA-COM-1), laid out by its design response
   (PAY-DEMO-PRIVACY-PAGE-DESIGN-1, docs/handoff-2026-10-21-pay-privacy/). No new token: every colour
   is a pairing already in use here (--text and --muted on --bg and --surface, the chips' own pairs,
   the .claim box's --tint pair). The eyebrow is the one change of pairing: .eyebrow is --accent-bright,
   about 2.5:1 on --bg, so this page's takes --accent-text, as .kicker already does. */
.prose-page { width: 100%; max-width: 1100px; margin: 0 auto; padding: clamp(32px, 6vw, 56px) var(--gutter); }
.prose { display: grid; gap: 14px; max-width: 66ch; min-width: 0; text-align: left; }
.prose h2 { margin: 18px 0 0; font-size: 18px; line-height: 1.3; letter-spacing: -.01em; }
.prose p, .prose li { margin: 0; font-size: 15px; line-height: 1.6; color: var(--text); }
.prose ul { display: grid; gap: 8px; margin: 0; padding-left: 1.2em; list-style: disc; }
.prose .term { grid-template-columns: minmax(0, 9.5rem) minmax(0, 1fr); }
.prose .term dt { overflow-wrap: anywhere; }
.term-life { color: var(--muted); }
.eyebrow--text { color: var(--accent-text); }

.privacy { display: grid; gap: 28px; }
.privacy-head { display: grid; gap: 14px; max-width: 66ch; }
.privacy-head .lead strong { color: var(--text); }
.privacy .dot { animation: none; }
.privacy-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 12px;
  max-width: 880px;
}
.privacy-card {
  display: grid;
  gap: 8px;
  align-content: start;
  padding: 18px 20px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
}
.privacy-card p { margin: 0; }
.privacy-card-title { font-size: 17px; font-weight: 700; letter-spacing: -.01em; }
.privacy-card-body { font-size: 14px; line-height: 1.5; color: var(--muted); }

.privacy-body { display: flex; gap: 56px; align-items: flex-start; }
.privacy-toc { display: none; }
@media (min-width: 700px) {
  .privacy-toc {
    display: grid;
    flex: none;
    width: 160px;
    position: sticky;
    top: 24px;
  }
}
.privacy-toc .panel-head { text-transform: uppercase; }
.privacy-toc a { padding: 5px 0; font-size: 14px; font-weight: 500; color: var(--muted); text-decoration: none; }
.privacy-toc a:hover { color: var(--text); }
.privacy-toc .privacy-toc-delete { color: var(--accent-text); }

.privacy-panel {
  display: grid;
  gap: 6px;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
}
.prose .privacy-panel-lead { font-weight: 600; }

.privacy-rows { border-top: 1px solid var(--line); }
.privacy-row { display: grid; gap: 8px; padding: 14px 0; border-bottom: 1px solid var(--line); }

/* The sub-processors: one markup, two layouts. At width a table whose header row names the columns,
   so each row's labels are hidden from sight (not from a screen reader); below 600px each processor
   stacks into its name over labelled lines, because a scrolled table would hide WHY, and WHY is the
   point. */
.subs { display: grid; border-top: 1px solid var(--line); }
.subs-head { display: none; }
.sub { padding: 12px 2px; border-bottom: 1px solid var(--line); }
.sub-who { margin: 0 0 6px; font-size: 15px; font-weight: 600; letter-spacing: 0; }
.sub-lines { display: grid; grid-template-columns: 5.5rem minmax(0, 1fr); gap: 4px 10px; margin: 0; }
.sub-lines > div { display: contents; }
.sub-lines dt { font: 500 11px/21px var(--mono); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.sub-lines dd { margin: 0; font-size: 14px; line-height: 1.5; color: var(--text); }
@media (min-width: 600px) {
  .subs-head, .sub {
    display: grid;
    grid-template-columns: minmax(0, 9.5rem) minmax(0, 1fr) minmax(0, 1fr);
    gap: 16px;
  }
  .subs-head {
    padding: 10px 2px;
    border-bottom: 1px solid var(--line);
    font: 500 11px var(--mono);
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .sub-who { margin: 0; font-size: 14px; line-height: 1.5; }
  .sub-lines { display: contents; }
  .sub-lines dt {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .sub-lines > div:last-child dd { color: var(--muted); }
}

/* The inline link at each point of collection: sign-in, checkout (PAY-DEMO-PRIVACY-PAGE-DESIGN-1). */
.privacy-link { color: var(--text); font-weight: 600; }
.foot a[aria-current="page"] { color: var(--text); font-weight: 600; }

/* M11's list (batch 340 slice 1; one row per provider since design pass 11). The selected row is
   filled and edged; the provider's name sits over the methods it takes. */
.methods { display: grid; gap: 8px; border: 0; margin: 0; padding: 0; min-width: 0; }
.methods legend { padding: 0; margin-bottom: 6px; }
.method {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--input-line);
  border-radius: 12px;
  background: var(--input);
  cursor: pointer;
}
.method:has(.method-radio:checked) { background: var(--tint); border-color: var(--accent); }
.method:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.method-radio { margin: 0; accent-color: var(--brand); }
.method-copy { display: grid; gap: 2px; flex: 1; min-width: 0; }
.method-title { font-size: 15px; font-weight: 600; color: var(--text); }
.method-sub { font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.form-card .methods-note { text-align: left; }
/* A once-link under way (design pass 11, PublicLink.dc.html): the rows are dimmed by colour, never by
   opacity, so each figure is a measured pair — --muted on --input 5.58 light / 7.25 dark. No row is
   chosen while the link takes nothing. */
.methods:disabled .method { cursor: default; }
.methods:disabled .method:has(.method-radio:checked) { background: var(--input); border-color: var(--input-line); }
.methods:disabled .method-title { color: var(--muted); }
/* The disabled button the under-way page draws: --muted on --surface, 5.58 light / 6.61 dark. */
.btn--quiet { background: transparent; border-color: var(--input-line); color: var(--muted); }

/* The amber panel a once-link under way draws above the form. Title --amber on --amber-row 5.73 light /
   10.69 dark; body --text on --amber-row 17.86 / 15.12. */
.link-panel {
  display: grid;
  gap: 6px;
  max-width: 440px;
  width: 100%;
  padding: 13px 14px;
  text-align: left;
  background: var(--amber-row);
  border-left: 3px solid var(--amber-line);
}
.link-panel-title { font: 500 14px/1.45 var(--mono); color: var(--amber); }
.link-panel-body { font-size: 14px; line-height: 1.55; color: var(--text); }

/* ---------------------------------------------------------------- redirecting */

.spinner {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 3px solid var(--line);
  border-top-color: var(--accent);
  animation: spin .9s linear infinite;
}
.redirect-title { font-size: 24px; letter-spacing: -.02em; font-weight: 700; }
.redirect-page .lead { font-size: 15px; }
.redirect-page code { background: none; padding: 0; }
.link-button {
  font: inherit;
  font-weight: 600;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  text-decoration: underline;
  cursor: pointer;
}

/* ---------------------------------------------------------------- return: the four-step track */

.track {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}
.track-step {
  display: grid;
  gap: 10px;
  justify-items: center;
  align-content: center;
  min-height: clamp(130px, 16vw, 220px);
  padding: clamp(20px, 2.8vw, 36px) clamp(16px, 2.4vw, 28px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
}
.track-disc {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 14px;
  font-weight: 700;
  background: var(--accent);
  color: #ffffff;
}
.track-title { font-size: 14px; font-weight: 600; }
.track-time { font-size: 12px; color: var(--muted); background: none; padding: 0; }
.track-step--waiting { border-color: var(--amber-line); }
.track-step--waiting .track-disc { background: var(--amber-chip); color: var(--amber); }
.track-step--stopped .track-disc { background: var(--red-chip); color: var(--red); }
/* A lapsed hold (batch 418.1, design pass 15 § 0.1: LAPSED is dim): --muted on --neutral, 4.74 light /
   5.88 dark; never the stop grammar, which stays a decline's and REVERSED's. */
.track-step--lapsed .track-disc { background: var(--neutral); color: var(--muted); }
.ref-line { font-size: 13px; color: var(--muted); }
.ref-line code { background: none; padding: 0; }

/* ---------------------------------------------------------------- transactions */

.wide {
  display: grid;
  align-content: start;
  gap: 24px;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  padding: clamp(28px, 5vw, 44px) var(--gutter);
}
.tx-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 12px 16px;
}
.tx-head-copy { display: grid; gap: 6px; }
.tx-title { font-size: clamp(26px, 4vw, 32px); letter-spacing: -.025em; font-weight: 700; }
.tx-sub { font-size: 15px; color: var(--muted); }
.live-pill {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--on-brand);
  background: var(--brand);
  padding: 9px 14px;
  border-radius: 999px;
  white-space: nowrap;
}

.rows { display: grid; gap: 10px; }

/* A row is a <details> card since batch 383.1 (pass 2's delta (a)): the summary is the row as pass 1
   drew it, and the panel under it holds the legs and the details. overflow: hidden keeps the panel's
   top border inside the card's radius, as the prototype's does. */
.row {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  animation: rise .35s ease-out both;
}
.row--CREATED { background: var(--amber-row); }
.row-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 20px;
  padding: 16px 20px;
  cursor: pointer;
  list-style: none;
}
.row-summary::-webkit-details-marker { display: none; }
.row-summary:focus-visible { outline-offset: -2px; border-radius: 14px; }
.row-main { display: grid; gap: 2px; flex: 1 1 180px; min-width: 0; }
.row-item { font-size: 15px; font-weight: 600; overflow-wrap: anywhere; }
.row-meta { display: flex; flex-wrap: wrap; gap: 4px 8px; font-size: 13px; color: var(--muted); }
.row-meta code { font-size: 12.5px; background: none; padding: 0; }
.row-status { display: grid; gap: 3px; flex: 1 1 200px; min-width: 0; }
.row-note { font-size: 12.5px; color: var(--muted); }
.row-amount {
  display: grid;
  gap: 4px;
  justify-items: end;
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 16px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* The handoff's #1f8a4c is short of AA as 13px text (see --accent-text), so the toggle uses the
   text accent, as every other small green word here does. */
.row-toggle { font-size: 13px; font-weight: 600; color: var(--accent-text); }
.row-toggle-open { display: none; }
.row[open] .row-toggle-open { display: inline; }
.row[open] .row-toggle-closed { display: none; }
.row--empty { display: flex; justify-content: center; padding: 16px 20px; color: var(--muted); font-size: 15px; }

.row-panel {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: 20px 40px;
  padding: 18px 20px 20px;
  border-top: 1px solid var(--line);
  animation: rise .25s ease-out both;
}
.panel-col { display: grid; align-content: start; }
.panel-head { margin-bottom: 6px; font: 500 11px var(--mono); letter-spacing: .06em; color: var(--muted); }
.leg {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) auto;
  gap: 4px 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--divider);
}
.leg-dot {
  width: 12px;
  height: 12px;
  margin-top: 3px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--accent);
}
.leg--wait .leg-dot { background: var(--amber-chip); border-color: var(--amber-dot); }
.leg--none .leg-dot { background: transparent; border-color: var(--numeral); }
.leg--fail .leg-dot { background: #c94a4a; border-color: #c94a4a; }
.leg-copy { display: grid; gap: 2px; min-width: 0; }
.leg-label { font-size: 14px; font-weight: 600; }
.leg-sub { font-size: 12.5px; line-height: 1.4; color: var(--muted); text-wrap: pretty; }
.leg-time { font-size: 12.5px; font-variant-numeric: tabular-nums; background: none; padding: 0; }
.leg--wait .leg-time { color: var(--amber); }
.leg--none .leg-time { color: var(--muted); }
.kvs { margin: 0; }
.kv {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--divider);
  font-size: 14px;
}
.kv dt { color: var(--muted); }
.kv dd { margin: 0; font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

/* One chip per PaymentStatus name — CREATED, COMPLETE, CANCELLED, FAILED; REFUNDED and REVERSED
   (batch 413.2) take the neutral chip. CANCELLED is a status
   core still has even though this demo never reaches it from a cancel (PayFast sends nothing on
   one), so it gets a chip rather than degrading to an unstyled word. Adding a status to core
   without a rule here degrades to a neutral chip, never to nothing. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  justify-self: start;
  font-size: 12px;
  font-weight: 600;
  padding: 6px 11px;
  border-radius: 999px;
  background: var(--neutral);
  color: var(--muted);
}
.chip--CREATED { background: var(--amber-chip); color: var(--amber); }
.chip--COMPLETE { background: var(--tint); color: var(--accent-text); }
.chip--FAILED { background: var(--red-chip); color: var(--red); }

.claim {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 16px;
  align-items: center;
  justify-content: space-between;
  padding: 20px 22px;
  background: var(--tint);
  border-radius: 16px;
}
.claim-copy { display: grid; gap: 2px; flex: 1 1 240px; }
.claim-title { font-size: 16px; font-weight: 600; }
.claim-sub { font-size: 14px; color: var(--tint-muted); }
.claim-controls { display: flex; gap: 8px; flex: 1 1 260px; max-width: 360px; }
.claim-controls .text-input { flex: 1; font-size: 14px; padding: 11px 14px; border-color: var(--tint-line); border-radius: 10px; }
.claim-controls .btn { font-size: 14px; padding: 11px 16px; border-radius: 10px; white-space: nowrap; }

/* ---------------------------------------------------------------- receipt */

.receipt-page { display: grid; justify-items: center; gap: 16px; padding: clamp(28px, 5vw, 56px) var(--gutter); }
.receipt {
  width: 100%;
  max-width: 440px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  overflow: hidden;
}
.receipt-head {
  display: grid;
  gap: 8px;
  justify-items: center;
  padding: 28px 24px 22px;
  text-align: center;
  background: var(--tint);
}
.receipt-disc {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 18px;
  font-weight: 700;
  background: var(--accent);
  color: #ffffff;
}
.receipt-label { font-size: 13px; font-weight: 600; color: var(--accent-text); }
.receipt-amount { font-size: 40px; font-weight: 700; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.receipt-item { font-size: 14px; color: var(--tint-muted); overflow-wrap: anywhere; }
.receipt-rows { margin: 0; padding: 8px 24px; }
.receipt-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--divider);
  font-size: 14px;
}
.receipt-row dt { color: var(--muted); }
.receipt-row dd { margin: 0; font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.receipt-note { padding: 14px 24px 0; margin: 0; font-size: 14px; line-height: 1.5; text-align: center; overflow-wrap: anywhere; }
.receipt-foot { padding: 14px 24px 22px; font-size: 12.5px; line-height: 1.5; text-align: center; color: var(--muted); }
.receipt-links { display: flex; flex-wrap: wrap; gap: 16px; justify-content: center; font-size: 14px; color: var(--muted); }

/* ---------------------------------------------------------------- merchant area (batch 383.2)

   The handoff's Merchant Area shell, slice 1. No new colour: every value is an existing token, so
   no contrast figure here is new. The amber eyebrow is --amber, the same pair already measured as
   chip text; the brand card is --brand / --on-brand, as the landing's live step. */

.brand-sub { font-weight: 500; color: var(--muted); }
.merchant-who { align-items: center; gap: 10px 14px; flex-wrap: wrap; }
.merchant-who form { margin: 0; }
.merchant-email { font-size: 13px; }
.btn--small { font-size: 13px; padding: 7px 12px; border-radius: 9px; }

.tick { display: flex; gap: 10px; align-items: flex-start; font-size: 14px; text-align: left; }
.tick input { width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--accent); flex: none; }
.tick > span { display: grid; gap: 2px; }
.code-input { font: 600 24px var(--mono); letter-spacing: .4em; text-align: center; max-width: 280px; justify-self: center; }

.m-body {
  display: flex;
  flex-wrap: wrap;
  gap: 24px clamp(24px, 4vw, 48px);
  padding: clamp(20px, 4vw, 36px) var(--gutter);
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  flex: 1 0 auto;
}
.m-menu { flex: 0 1 210px; display: grid; align-content: start; gap: 2px; }
.m-menu-item {
  display: flex;
  justify-content: space-between;
  font-size: 14px;
  font-weight: 500;
  padding: 10px 12px;
  border-radius: 10px;
  color: var(--muted);
  text-decoration: none;
}
.m-menu-item[aria-current="page"] { font-weight: 600; background: var(--surface); color: var(--text); }
.m-main { flex: 1 1 480px; min-width: 0; }
.m-page { display: grid; gap: 22px; }

.m-refusal {
  display: grid;
  gap: 14px;
  justify-items: start;
  padding: clamp(24px, 4vw, 40px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
}
.eyebrow--amber { color: var(--amber); }

.m-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 14px; }
.m-card {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 10px;
  min-height: clamp(150px, 15vw, 200px);
  padding: clamp(20px, 2.6vw, 28px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
}
.m-card-label { font-size: 13px; font-weight: 600; color: var(--muted); }
.m-card-number { font-size: clamp(36px, 4.4vw, 52px); font-weight: 700; letter-spacing: -.04em; line-height: 1; font-variant-numeric: tabular-nums; }
.m-card-number--time { font-size: clamp(26px, 3vw, 36px); letter-spacing: -.02em; }
.m-card-note { font-size: 13.5px; color: var(--muted); }
.m-card--brand { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.m-card--brand .m-card-label,
.m-card--brand .m-card-note { color: var(--on-brand-muted); }
a.m-card { color: inherit; text-decoration: none; }
a.m-card--brand { color: var(--on-brand); }

/* Slice 2: the five record screens. Still no new colour — the red badge and count are the failed
   chip's measured pair, the amber edge and count the pending chip's, and the decided box is the
   tint the receipt header already uses. */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.m-menu-item { align-items: center; gap: 8px; }
.m-badge {
  font-size: 11.5px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--red-chip);
  color: var(--red);
  font-variant-numeric: tabular-nums;
}
.m-h2 { font-size: 17px; font-weight: 700; }
.m-filters { display: flex; flex-wrap: wrap; gap: 8px; }
.m-filter {
  font-size: 13px;
  font-weight: 600;
  padding: 7px 13px;
  border: 1px solid var(--input-line);
  border-radius: 999px;
  color: inherit;
  text-decoration: none;
}
.m-filter[aria-current="page"] { background: var(--text); border-color: var(--text); color: var(--bg); }
.m-empty { font-size: 14px; color: var(--muted); }
.m-empty--dashed { padding: 22px; border: 1px dashed var(--input-line); border-radius: 14px; }

.m-rows, .m-trail { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.m-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 20px;
  padding: 16px 20px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
}
.m-row-main { display: grid; gap: 3px; flex: 1 1 200px; min-width: 0; }
.m-row-status { display: grid; gap: 6px; justify-items: start; flex: 2 1 240px; min-width: 0; }
.m-row-sub { font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.m-row-note { font-size: 12.5px; color: var(--muted); line-height: 1.45; overflow-wrap: anywhere; }
.m-row-end { font: 500 12.5px var(--mono); color: var(--muted); }
.m-ref { font: 600 14px var(--mono); overflow-wrap: anywhere; }
.m-link { color: var(--accent-text); font-family: var(--sans); font-weight: 600; }
.m-pager { display: flex; gap: 18px; font-size: 14px; font-weight: 600; }
.m-pager a { color: var(--accent-text); }

.m-mismatch {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  overflow: hidden;
}
.m-mismatch--open { border-color: var(--amber-line); }
.m-mismatch-body { display: grid; gap: 12px; justify-items: start; padding: 18px 20px; }
.m-mismatch-body .m-row-main { width: 100%; }
.m-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)); gap: 10px; width: 100%; }
.m-tile { display: grid; gap: 4px; padding: 12px 14px; background: var(--bg); border-radius: 12px; }
.m-tile-value { font: 600 15px var(--mono); }
.m-decide { display: grid; gap: 14px; padding: 18px 20px; border-top: 1px solid var(--line); background: var(--bg); }
.m-decide-q { font-size: 15px; font-weight: 600; margin: 0; padding: 0; }
.m-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.m-decided {
  display: grid;
  gap: 4px;
  margin: 0 20px 18px;
  padding: 14px 16px;
  border-radius: 12px;
  background: var(--tint);
  font-size: 14px;
}
.m-decided .m-row-sub { color: var(--tint-muted); }
.m-decided q { overflow-wrap: anywhere; }

.m-run-when { font-size: 15px; font-weight: 600; }
.m-counts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin: 0; flex: 2 1 280px; }
.m-counts div { display: grid; gap: 2px; }
.m-counts dd { margin: 0; font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.m-counts dt { order: 2; font-size: 11.5px; color: var(--muted); }
.m-count--red dd { color: var(--red); }
.m-count--amber dd { color: var(--amber); }
.m-run-reason { flex: 1 1 100%; }

.m-panel {
  padding: 20px 22px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
}
.m-toggle { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 20px; }
.m-toggle-copy { display: grid; gap: 4px; flex: 1 1 260px; min-width: 0; font-size: 15px; }

.m-filter-form { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.m-filter-form .text-input { flex: 0 1 340px; padding: 9px 12px; font-size: 14px; }
.m-trail {
  gap: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
}
.m-trail-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--divider);
}
.m-trail-row:last-child { border-bottom: 0; }
.m-trail-time { flex: 0 0 120px; font: 500 12.5px var(--mono); color: var(--muted); }
.m-trail-what { flex: 1 1 220px; min-width: 0; font-size: 14px; overflow-wrap: anywhere; }
/* RECEIPT ADDRESS SET in ok, as Android draws it (design pass 15 § 6.3, batch 418.4): --accent-text on
   --surface, 5.39 light / 6.36 dark. The only coloured word on this page. */
.m-trail-word--ok { color: var(--accent-text); }
.m-source { font: 500 11.5px var(--mono); padding: 2px 7px; border-radius: 6px; background: var(--bg); color: var(--muted); }

/* Slice 3, Checkout. The swatch tiles are the link page's --mark-N tiles, whose ✓ is the initial's
   measured pairing; the danger button is --red on the surface, the failed chip's text colour. */

.m-section { display: grid; gap: 12px; }
.m-panel--dashed { border-style: dashed; }
.m-swatches { display: flex; flex-wrap: wrap; gap: 10px; }
.m-swatch {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px 8px 8px;
  font: 600 14px var(--sans);
  color: var(--text);
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: 12px;
  cursor: pointer;
}
.m-swatch[aria-pressed="true"] { border-color: var(--accent); }
.mark--small { width: 28px; height: 28px; border-radius: 8px; font-size: 15px; }
.m-logo-row { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }
.m-logo-row .m-row-note { flex: 1 1 220px; }
.m-logo-empty {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border: 1px dashed var(--input-line);
  border-radius: 14px;
  font-size: 24px;
  color: var(--muted);
}
.m-upload { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; min-width: 0; }
.m-upload input[type="file"] { max-width: 100%; font-size: 13px; color: var(--muted); }
.m-btn-danger { background: transparent; border-color: transparent; color: var(--red); }
/* The logo's Remove, asked first (design pass 15 § 6.1, batch 418.4): the apps' stop panel. Its title is
   --red on --surface, the danger button's own pair; the body is --muted on --surface, 5.58 / 6.61. */
.m-confirm { display: grid; gap: 8px; margin-top: 12px; padding: 12px 14px; border-left: 3px solid var(--red); }
.m-confirm-title { font-size: 14px; color: var(--red); }
.m-providers { list-style: none; margin: 0; padding: 0; display: grid; }
.m-provider {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  padding: 14px 0;
  border-top: 1px solid var(--divider);
}
.m-provider form { display: flex; align-items: center; gap: 10px; margin: 0; }
.m-prefix { font: 600 12.5px var(--mono); padding: 2px 8px; border-radius: 999px; background: var(--neutral); }
.m-prefix-input { max-width: 120px; font-family: var(--mono); text-transform: uppercase; letter-spacing: .1em; }
.m-link-url { display: block; font: 500 13px var(--mono); overflow-wrap: anywhere; margin-bottom: 4px; }

@media (prefers-reduced-motion: reduce) {
  .dot, .spinner, .row, .row-panel { animation: none; }
}

/* ---------------------------------------------------------------- the simulated acquirer (batch 340.5) */

/* SimulatedCard.dc.html's page, in this system's tokens. The simulated mark is the DASHED rule (§ 0o
   decision 4.2): dashed already means "not the real thing" here, and it is not amber, which is Demo
   mode. Every text colour below is a pair this file already uses — --text and --muted on --surface,
   --accent-text on --tint (4.75 light), --amber on --amber-row (5.73 / 10.69), --red as
   .message--error draws it — so no new pair owes a figure. */
.sim-band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 8px 16px;
  background: var(--surface);
  border-bottom: 1px dashed var(--input-line);
}
.sim-band-label {
  font: 500 11px var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  border: 1px dashed var(--input-line);
  border-radius: 3px;
  padding: 2px 6px;
}
.sim-band-line { font-size: 13px; color: var(--muted); }
.sim-page { text-align: left; }
.sim-grid {
  display: grid;
  gap: 28px;
  width: 100%;
  max-width: 880px;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
/* At width (PAY-KITS-CHECKOUT-AND-RETURN-AT-WIDTH-1, pass 11's M11-desktop-sim-* and
   M13-desktop-sim-declined): the card form keeps the list beside it, 460 + 380. Google Pay's view has no
   list, and the board centres its one column at 520, the return's width, rather than leaving it in the
   left track beside an empty right one. The boards also start the page 28px under the band, not 56. The
   phone is untouched: every rule here is inside this query. */
@media (min-width: 860px) {
  .sim-grid { grid-template-columns: minmax(0, 460px) minmax(0, 380px); justify-content: center; }
  .sim-grid--single { grid-template-columns: minmax(0, 520px); }
  .sim-page { padding-top: 28px; }
}
.sim-main { display: grid; gap: 12px; min-width: 0; }
.sim-main--narrow { width: 100%; max-width: 520px; }
.sim-order { display: flex; align-items: center; gap: 12px; }
.sim-order .mark { width: 36px; height: 36px; font-size: 14px; border-radius: 4px; }
.sim-order-copy { display: grid; gap: 2px; flex: 1; min-width: 0; }
.sim-order-name { font-weight: 600; }
.sim-order-item { font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.sim-order-amount { font: 500 20px var(--mono); }
/* 10.5px, as every pass 11 board sets these labels: at 11px the card form's head wrapped both sides to
   two lines at 390 (batch 440.8), where its 324px head holds about 312 at 10.5. */
.sim-kicker, .sim-label {
  font: 500 10.5px var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.sim-kicker, .sim-label--dim, .sim-dim { color: var(--muted); }
.sim-provider { background: var(--tint); border-color: var(--accent); cursor: default; }
.sim-provider-dot {
  width: 18px;
  height: 18px;
  flex: none;
  border-radius: 50%;
  border: 5px solid var(--brand);
  box-sizing: border-box;
}
.sim-switch {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1px solid var(--input-line);
  border-radius: 4px;
  overflow: hidden;
}
.sim-switch a {
  min-height: 44px;
  display: grid;
  place-items: center;
  font-weight: 600;
  text-decoration: none;
  color: var(--text);
}
.sim-switch a[aria-current="page"] { background: var(--brand); color: var(--on-brand); }
.sim-form {
  display: grid;
  gap: 10px;
  padding: 14px 12px;
  border: 1px dashed var(--input-line);
  border-radius: 6px;
  background: var(--surface);
}
.sim-form-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.sim-prose { font-size: 13.5px; line-height: 1.5; color: var(--muted); margin: 0; }
.sim-field { display: grid; gap: 5px; min-width: 0; }
.sim-input { font: 400 16px var(--mono); letter-spacing: .04em; min-width: 0; width: 100%; box-sizing: border-box; }
.sim-input--stop { border-color: var(--red); }
.sim-pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.sim-check { font-size: 12.5px; color: var(--red); }
.sim-note { text-align: left; }
.sim-panel {
  display: grid;
  gap: 6px;
  padding: 12px 14px;
  background: var(--surface);
  border-left: 3px solid var(--input-line);
}
.sim-panel-title { font: 500 14px/1.45 var(--mono); }
.sim-panel-body { font-size: 14px; line-height: 1.55; color: var(--text); }
.sim-panel--stop { border-left-color: var(--red); }
.sim-panel--stop .sim-panel-title, .sim-stop { color: var(--red); }
.sim-panel--ok { background: var(--tint); border-left-color: var(--accent); }
.sim-panel--ok .sim-panel-title, .sim-ok { color: var(--accent-text); }
.sim-panel--created { background: var(--amber-row); border-left-color: var(--amber-line); }
.sim-panel--created .sim-panel-title, .sim-created { color: var(--amber); }
.sim-panel--dim .sim-panel-title { color: var(--muted); }
.sim-ink { color: var(--text); }
.sim-gpay { display: grid; gap: 10px; }
.sim-gpay-button { min-height: 48px; }
.sim-gpay-summary {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 4px;
}
.sim-gpay-card { flex: 1; font: 500 14px var(--mono); }
.sim-list {
  display: grid;
  gap: 8px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  min-width: 0;
}
.sim-list summary {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  cursor: pointer;
  list-style: none;
}
.sim-list summary::-webkit-details-marker { display: none; }
.sim-toggle { margin-left: auto; font: 500 13px var(--mono); text-decoration: underline; }
.sim-list[open] .sim-toggle--show, .sim-list:not([open]) .sim-toggle--hide { display: none; }
.sim-list-lead { font-size: 13px; line-height: 1.5; color: var(--muted); margin: 0 0 4px; }
.sim-cards { list-style: none; margin: 0 0 6px; padding: 0; border-top: 1px solid var(--divider); }
.sim-card { display: flex; align-items: center; gap: 10px; min-height: 46px; border-bottom: 1px solid var(--divider); }
.sim-card-copy { display: grid; gap: 2px; flex: 1; min-width: 0; }
.sim-card-number { font: 500 13px var(--mono); white-space: nowrap; }
.sim-card-what { font-size: 12.5px; color: var(--muted); }
.sim-use {
  min-height: 44px;
  padding: 0 4px;
  font: 500 13px var(--mono);
  text-decoration: underline;
  background: none;
  border: 0;
  color: inherit;
  cursor: pointer;
}
.sim-expiries { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 14px; margin: 0 0 4px; }
.sim-expiries dt, .sim-expiries dd { margin: 0; font: 500 13px var(--mono); }
.sim-title { margin: 0; }
.sim-strong { font-weight: 600; color: var(--muted); margin: 0; }
.sim-rows { display: grid; margin: 0; border-top: 1px solid var(--divider); }
.sim-rows div { display: flex; justify-content: space-between; gap: 12px; padding: 10px 2px; border-bottom: 1px solid var(--divider); }
.sim-rows dt { font-size: 13px; color: var(--muted); }
.sim-rows dd { margin: 0; font: 500 13px var(--mono); }
.sim-code { display: grid; gap: 10px; }
.sim-code-shown {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  background: var(--surface);
  border-radius: 4px;
  font-size: 13px;
  color: var(--muted);
}
.sim-code-value { font: 500 24px var(--mono); letter-spacing: .18em; color: var(--text); }
.sim-cancel { display: grid; justify-items: center; }
/* The browser's own [hidden] rule loses to any author display, so .sim-panel, .btn and .sim-gpay-summary
   were drawn from the start: Google Pay's stop panel said "Google returned the card above" before Google
   was asked (batch 340, found with PAYDEMO-SIM-PAGE-GOOGLE-PAY-STOP-IS-A-DEAD-END-1). sim.js shows them. */
.sim-page [hidden] { display: none !important; }
.sim-outcome-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.sim-outcome-rows { display: grid; gap: 3px; margin: 6px 0 0; }
.sim-outcome-rows div { display: flex; gap: 12px; }
.sim-outcome-rows dt { width: 110px; flex: none; font: 500 13px var(--mono); color: var(--muted); }
.sim-outcome-rows dd { margin: 0; font: 500 13px var(--mono); overflow-wrap: anywhere; }
.sim-options { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
