/* ===================================================================
   Sahl — design tokens
   Petrol ink + pine, with magenta reserved for arrival moments only.
   =================================================================== */
:root{
  --ink:#0B1D24;
  --ink-2:#16333C;
  --pine:#0D6A56;
  --pine-dark:#095045;
  --pine-tint:#E4F0EB;
  --magenta:#C81E64;
  --magenta-tint:#FBE8EF;
  --surface:#F0F3F1;
  --card:#FFFFFF;
  --line:#DBE3E0;
  --muted:#64797E;
  --amber:#B26205;
  --amber-tint:#FDF1E0;
  --radius:14px;
  --radius-sm:9px;
  /* Pill. Status and trust cues are round-ended so they read as state
     rather than as another button; every one of them uses this, so the
     shape is a single decision. */
  --radius-pill:999px;
  --shadow:0 1px 2px rgba(11,29,36,.06), 0 12px 32px -18px rgba(11,29,36,.35);
  /* Vertical rhythm. One scale, used by every band and every stack,
     so section spacing is a decision made once rather than per page. */
  --s-1:.5rem; --s-2:.85rem; --s-3:1.25rem; --s-4:2rem;
  --s-5:3rem;  --s-6:4.5rem; --s-7:6.5rem;
  --band-y:clamp(3.5rem,7vw,6.5rem);
  --measure:65ch;          /* body copy line length */
  --measure-tight:52ch;    /* lede and section intro */

  /* Supporting type, fluid on the same principle as the headings above:
     one ramp, so a lede and a section intro cannot drift apart. The
     headings already clamp; these are what sat under them as fixed rem
     values and broke the ramp at both ends of the viewport. */
  --fs-lede:clamp(1.02rem,.55vw + .88rem,1.18rem);
  --fs-small:.86rem;
  --fs-micro:.7rem;

  /* Layered shadows. A single large blur reads as fog; three stops
     with tightening opacity read as an object above a surface. */
  --lift-1:0 1px 2px rgba(11,29,36,.05), 0 2px 6px -2px rgba(11,29,36,.10);
  --lift-2:0 2px 4px rgba(11,29,36,.05), 0 8px 18px -6px rgba(11,29,36,.14),
           0 24px 48px -24px rgba(11,29,36,.30);
  --lift-3:0 2px 4px rgba(11,29,36,.06), 0 12px 24px -8px rgba(11,29,36,.16),
           0 40px 72px -32px rgba(11,29,36,.38);

  /* "Noto Sans Arabic" and "Noto Sans Bengali" sit second in all three
     stacks and carry exactly one glyph each: ؋ (U+060B) and ৳ (U+09F3), the
     Afghani and taka signs. None of the three primaries covers the Arabic or
     Bengali block, so without these those two characters fall through to
     whatever the operating system offers and arrive at the wrong weight
     beside the digits. ₨ ₹ ₦ ₱ are in Plex's latin-ext subset and never had
     the problem.

     Both are loaded via Google's text= subset, which ships them with
     unicode-range: U+60b and U+9f3 respectively. Those ranges are the
     guarantee, not a hope: the browser will not reach for either font for
     any other character, so every other symbol and every digit still
     resolves exactly as it did before. That is also why it is safe to name
     them in --body and --display and not only in --mono — the symbol is set
     in body text on transfer.php and inside an h3 on track.php, and it needs
     the same glyph in all three. */
  --display:"Bricolage Grotesque","Noto Sans Arabic","Noto Sans Bengali","Instrument Sans",system-ui,sans-serif;
  --body:"Instrument Sans","Noto Sans Arabic","Noto Sans Bengali",system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"IBM Plex Mono","Noto Sans Arabic","Noto Sans Bengali",ui-monospace,"SF Mono",Menlo,monospace;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--surface);color:var(--ink);
  font-family:var(--body);font-size:16px;line-height:1.55;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
a{color:var(--pine-dark);text-decoration-thickness:1px;text-underline-offset:2px}
:focus-visible{outline:2.5px solid var(--magenta);outline-offset:2px;border-radius:4px}

h1,h2,h3,h4{font-family:var(--display);font-weight:700;line-height:1.08;letter-spacing:-.02em;margin:0}
h1{font-size:clamp(2.1rem,5.2vw,3.6rem)}
h2{font-size:clamp(1.55rem,3.2vw,2.35rem)}
h3{font-size:1.15rem;letter-spacing:-.01em}
p{margin:0 0 1rem}

.wrap{max-width:1140px;margin:0 auto;padding:0 22px}
.narrow{max-width:600px;margin:0 auto;padding:0 22px}
.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}
.muted{color:var(--muted)}
.small{font-size:var(--fs-small)}
.center{text-align:center}
.stack>*+*{margin-top:1rem}

/* ---------- eyebrow: used only where it names a real category ---------- */
.eyebrow{
  font-family:var(--mono);font-size:var(--fs-micro);letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);margin:0 0 .7rem
}

/* ---------------------------- header ---------------------------- */
.topbar{
  background:var(--ink);color:#fff;position:sticky;top:0;z-index:50;
  border-bottom:1px solid rgba(255,255,255,.08)
}
/* WRAPS WHENEVER IT MUST, AT ANY WIDTH — not below a chosen breakpoint.

   The wrap rule for this header lived at max-width:700px, sized for a
   360px phone with five nav items. Signed in as staff the nav carries
   NINE — Track, Rates, About, Contact, Transfers, Recipients, Console,
   Log out, Send money — measuring 724px, and with the logo and padding
   the header needs 962px. So from 701px all the way to about 960px the
   header pushed the whole document sideways: every tablet, and a good
   part of the laptop range. A signed-in operator at 768px got a
   storefront that scrolled horizontally on every page.

   Raising the breakpoint to 980px would fix the measurement and not the
   fault. The width the header needs is not a constant: it grows with
   the brand name in the logo, which is the licensee's, and with the nav
   items, which follow their plan. A licensee whose name is two words
   longer than "Northwind Remit" would reopen the gap somewhere nobody
   is testing.

   So the header wraps when its contents do not fit, whatever the
   viewport, and height becomes a MINIMUM rather than a fixed 66px —
   a fixed height with wrapped content clips the second row.
   min-width:0 on the nav lets it shrink below its content before
   wrapping rather than forcing the overflow it used to. */
.topbar .wrap{
  display:flex;align-items:center;gap:20px;
  min-height:66px;
  flex-wrap:wrap;row-gap:4px
}
.logo{
  font-family:var(--display);font-weight:800;font-size:1.24rem;letter-spacing:-.03em;white-space:nowrap;
  color:#fff;text-decoration:none;display:flex;align-items:center;gap:9px
}
.logo-mark{
  min-width:26px;height:26px;padding:0 6px;border-radius:7px;flex:none;
  background:linear-gradient(150deg,var(--pine) 40%,var(--magenta));
  display:grid;place-items:center;font-size:.72rem;font-weight:600;color:#fff;font-family:var(--mono)
}
.nav{display:flex;gap:6px;margin-left:auto;align-items:center;flex-wrap:wrap;min-width:0}
.nav a{
  color:rgba(255,255,255,.82);text-decoration:none;font-size:.92rem;
  padding:8px 13px;border-radius:8px
}
.nav a:hover{color:#fff;background:rgba(255,255,255,.09)}
.nav a.on{color:#fff;background:rgba(255,255,255,.13)}

/* ---------------------------- buttons ---------------------------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  font-family:var(--body);font-weight:600;font-size:.97rem;
  padding:13px 22px;border-radius:11px;border:1px solid transparent;
  cursor:pointer;text-decoration:none;transition:transform .08s,background .15s
}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--pine);color:#fff}
.btn-primary:hover{background:var(--pine-dark)}
.btn-dark{background:var(--ink);color:#fff}
.btn-dark:hover{background:var(--ink-2)}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--line)}
.btn-ghost:hover{background:#fff}
.btn-line{background:#fff;color:var(--ink);border-color:var(--line)}
.btn-line:hover{border-color:var(--ink)}
.btn-sm{padding:8px 14px;font-size:.87rem;border-radius:9px}
.btn-full{width:100%}
.btn[disabled]{opacity:.45;pointer-events:none}

/* ---------------------------- cards ---------------------------- */
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:26px}
.card-flat{background:var(--card);border:1px solid var(--line);border-radius:var(--radius)}

/* =====================================================================
   SIGNATURE: the receipt.
   Leads with what lands, not what leaves. Perforated foot, mono figures.
   ===================================================================== */
.receipt{
  background:var(--card);border-radius:var(--radius);box-shadow:var(--lift-3);
  position:relative;overflow:hidden;border:1px solid var(--line);
  transition:box-shadow .3s ease, transform .3s ease
}
/* Paper, not a rectangle: a hairline of the brand colour along the top
   edge, the way a printed receipt carries a header rule. */
.receipt::before{
  content:"";position:absolute;inset-inline:0;top:0;height:3px;z-index:2;
  background:linear-gradient(90deg,var(--pine),var(--magenta))
}
/* The head is the answer; the body is the question. Tinting the head
   and hardening the rule between them stops the eye reading the whole
   card as one undifferentiated form. */
/* The head is the answer, the body is the question. The tint alone was
   doing that work; a 2px rule under it and a little more air above the
   first field make the boundary something the eye lands on rather than
   something it has to look for. */
.receipt-head{
  padding:24px 24px 20px;border-bottom:2px solid var(--line);
  display:flex;justify-content:space-between;align-items:flex-start;gap:14px;
  background:linear-gradient(180deg,var(--pine-tint),transparent 140%)
}
.receipt-body{padding:24px 24px 20px}
.receipt-foot{
  position:relative;
  padding:22px 24px 30px;
  background:linear-gradient(180deg,#FAFCFB,#F4F8F6)
}
/* The tear line, where the stub parts from the receipt.

   It used to be `border-top:1px dashed var(--line)` — #DBE3E0 on an
   almost-white foot, which is a hairline somebody forgot to remove
   rather than a deliberate edge.

   Drawn INTO the card's own surface rather than punched through it.
   The receipt sits over the hero's animated wash, so a hole filled
   with a flat --surface would read as a flat blob against a moving
   gradient — which is the flaw the scallops along the bottom edge
   already have to live with, and not one worth repeating here. */
.receipt-foot::before{
  content:"";position:absolute;top:0;inset-inline:0;height:7px;
  background:
    radial-gradient(circle at 4px 3.5px,
      color-mix(in oklab, var(--ink) 26%, transparent) 1.7px, transparent 2.2px)
      0 0/10px 7px repeat-x,
    linear-gradient(180deg, color-mix(in oklab, var(--ink) 7%, transparent), transparent);
}
@supports not (background: color-mix(in oklab, red 20%, transparent)){
  .receipt-foot::before{
    background:
      radial-gradient(circle at 4px 3.5px, var(--muted) 1.7px, transparent 2.2px)
        0 0/10px 7px repeat-x
  }
}
/* Perforation. The old one was a 9px sliver at 6.5px radius — legible
   only if you knew to look. Deeper bite, larger scallops, and a hairline
   above them so the tear reads as intentional rather than as a
   rendering artefact. */
.receipt::after{
  content:"";position:absolute;inset-inline:0;bottom:0;height:14px;z-index:2;
  background:
    radial-gradient(circle at 9px 0,var(--surface) 8px,transparent 8.5px) 0 100%/18px 14px repeat-x,
    linear-gradient(var(--line),var(--line)) 0 0/100% 1px no-repeat
}
.arrives{
  font-family:var(--mono);font-weight:600;letter-spacing:-.03em;
  font-size:clamp(2rem,6vw,2.9rem);line-height:1;color:var(--ink);
  font-variant-numeric:tabular-nums;display:block
}
.arrives-ccy{font-size:.44em;color:var(--magenta);margin-inline-start:.3em;letter-spacing:0;direction:ltr;unicode-bidi:isolate}
.arrives-label{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--muted);display:block;margin-bottom:.5rem
}

/* =====================================================================
   MONEY AND BIDI

   An amount is a number in every locale. It never mirrors, and its
   currency symbol never swaps sides — not in Dari, not in Pashto, not
   in Urdu.

   "isolate" rather than "embed": isolation stops the symbol's strong
   RTL directionality (؋ U+060B is the one that actually misbehaves)
   from reaching out and reordering the digits beside it, AND stops the
   surrounding paragraph's direction from reaching in. Both halves
   matter — the first fixes the LTR page, the second keeps it fixed
   once the page is RTL.
   ===================================================================== */
.amt{
  direction:ltr;unicode-bidi:isolate;
  font-variant-numeric:tabular-nums;white-space:nowrap
}
.amt-sym{
  direction:ltr;unicode-bidi:isolate;
  /* The symbol needs air on its right, and the Afghani needs more of
     it than the pound: ؋ is a tall narrow glyph that otherwise reads
     as part of the first digit. Logical so it follows the flip. */
  margin-inline-end:.14em
}
/* Inside the big arrival figure the symbol is set slightly smaller —
   at 2.9rem a full-size ؋ overpowers the number it is labelling. */
.arrives .amt-sym{font-size:.82em;opacity:.85;vertical-align:.02em}

/* A three-letter ISO code is not a symbol and should not be set like
   one. It is a label ON the figure rather than part of it, so it goes
   smaller, tracked out, and in the accent colour — which is where the
   trailing AFN used to sit before the code moved to the front. The
   word space between code and digits is a text node in .amt, not
   margin here, so it survives a copy-paste. */
.amt-sym.is-code{
  font-size:.82em;letter-spacing:.03em;font-weight:600;
  color:var(--magenta);margin-inline-end:0
}
.arrives .amt-sym.is-code{
  font-size:.42em;opacity:1;vertical-align:.06em;letter-spacing:.06em
}

/* THE TRAILING ISO CODE, on every amount that leads with a glyph.

   Set like .amt-sym.is-code and for the same reason — it is a label on
   the figure, not part of it — but it lives INSIDE .amt now rather
   than beside it, so the code cannot be reordered away from its digits
   by an RTL paragraph. It replaces .arrives-ccy, which sat outside the
   isolation boundary and only ever appeared on the one big figure;
   this appears on every quoted amount, which is the point. */
.amt-ccy{
  font-size:.72em;letter-spacing:.04em;font-weight:600;
  color:var(--magenta);direction:ltr;unicode-bidi:isolate
}
.arrives .amt-ccy{font-size:.42em;letter-spacing:.06em;vertical-align:.06em}

/* THE AMBIGUOUS-DESTINATION CHOOSER. A storefront that will not guess
   a currency has to offer the choice somewhere, and it is the whole
   page in that state — see index.php. */
.corridor-choice{max-width:44rem;margin:0 auto;padding:3rem 1.25rem}
.corridor-choice h1{margin-bottom:.75rem}
.choice-list{list-style:none;padding:0;margin:1.5rem 0 0;display:grid;gap:.75rem}
.choice-list .btn{
  display:flex;align-items:center;gap:.75rem;width:100%;
  justify-content:flex-start;text-align:start
}
.choice-list .choice-ccy{margin-inline-start:auto;opacity:.8}

.line-row{
  display:flex;justify-content:space-between;gap:12px;
  padding:9px 0;font-size:.92rem;border-bottom:1px solid #EFF3F1
}
.line-row:last-child{border-bottom:0}
.line-row dt{color:var(--muted);margin:0}
.line-row dd{margin:0;font-family:var(--mono);font-variant-numeric:tabular-nums}
.line-total{font-weight:700;font-size:1.02rem;border-top:1px solid var(--line);margin-top:4px;padding-top:12px}

/* ---------------------------- inputs ---------------------------- */
label{display:block;font-size:.87rem;font-weight:600;margin-bottom:6px;color:var(--ink-2)}
.hint{font-size:.81rem;color:var(--muted);margin-top:5px}
input[type=text],input[type=email],input[type=password],input[type=tel],
input[type=number],input[type=date],select,textarea{
  width:100%;padding:12px 13px;font-size:1rem;font-family:var(--body);
  border:1px solid var(--line);border-radius:var(--radius-sm);background:#fff;color:var(--ink)
}
input:focus,select:focus,textarea:focus{border-color:var(--pine);outline:none;box-shadow:0 0 0 3px var(--pine-tint)}
.field{margin-bottom:16px}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:560px){.grid-2{grid-template-columns:1fr}}

.amount-input{position:relative}
.amount-input input{
  font-family:var(--mono);font-size:1.65rem;font-weight:600;
  padding-block:16px;padding-inline:42px 16px;
  font-variant-numeric:tabular-nums;
  /* The field holds a number. Keep it LTR even in an RTL layout, or
     the caret and the digits fight each other as you type. */
  direction:ltr;text-align:start
}
.amount-input .sym{
  position:absolute;inset-inline-start:16px;top:50%;transform:translateY(-50%);
  font-family:var(--mono);font-size:1.4rem;color:var(--muted);pointer-events:none;
  direction:ltr;unicode-bidi:isolate
}

/* choice tiles */
.choices{display:grid;gap:10px}
.choice{
  display:flex;gap:12px;align-items:flex-start;padding:14px;cursor:pointer;
  border:1.5px solid var(--line);border-radius:var(--radius-sm);background:#fff
}
.choice:hover{border-color:#B9C7C3}
.choice input{margin:3px 0 0;accent-color:var(--pine);flex:none}
.choice-body{flex:1;min-width:0}
.choice-title{font-weight:600;font-size:.95rem;display:flex;justify-content:space-between;gap:10px}
.choice input:checked~.choice-body .choice-title{color:var(--pine-dark)}
.choice:has(input:checked){border-color:var(--pine);background:var(--pine-tint)}

/* ---------------------------- badges ---------------------------- */
.badge{
  display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);
  font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;
  padding:5px 10px;border-radius:var(--radius-pill);background:var(--pine-tint);color:var(--pine-dark);font-weight:500
}
.badge-warn{background:var(--amber-tint);color:var(--amber)}
.badge-hot{background:var(--magenta-tint);color:var(--magenta)}
.badge-mute{background:#EAEFED;color:var(--muted)}
.dot{width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}

.sandbox-bar{
  background:var(--amber-tint);border-bottom:1px solid #F0DCBC;
  /* #B26205 on this tint measured 4.05:1 — under the 4.5 AA floor for
     small text. Darkened to clear it. */
  color:#8A4B04;
  font-size:.83rem;padding:8px 0;text-align:center
}
.sandbox-bar strong{font-family:var(--mono);font-weight:600}

/* THE QUOTES-ONLY BAR. Same shelf, different message and different
   weight: this is not a warning about a demonstration, it is a standing
   statement of what the site does. Neutral rather than amber, and the
   lead is set in the body face rather than the mono one because
   "SANDBOX" was a label and "Rates and quotes only." is a sentence. */
.sandbox-bar.quotes-bar{
  background:var(--paper, #F6F5F2);
  border-bottom:1px solid var(--line, #E3E0DA);
  color:var(--ink, #2B2A27);
  /* Wraps on a phone rather than shrinking: every clause here is one a
     customer is entitled to read before they act on a figure. */
  text-align:center;padding:9px 14px;line-height:1.45
}
.sandbox-bar.quotes-bar strong{font-family:inherit;font-weight:650}

/* AT THE FOOT, the border swaps ends. The bar now sits above the
   regulatory footer rather than below the header, so a bottom border
   would draw a line between it and the disclosure it introduces, and
   leave it hanging off the content above with nothing separating them.
   A top border does the opposite and is the whole of the change --
   the palette, the wrapping and the type are the bar's own and do not
   vary by position. */
.sandbox-bar.quotes-bar-foot{
  border-bottom:0;
  border-top:1px solid var(--line, #E3E0DA);
}
/* Second line of the sandbox bar: demo tenants only, and only ever a
   link — no licence figure lives on this site. Quieter than the warning
   above it, because the warning is the one a customer must read.

   #8B5A18 measures 5.27:1 on the tint. It reads a step lighter than the
   warning's #8A4B04 without going near the 4.5 floor — this line is
   smaller again at .78rem, so the margin matters more here, not less. */
.sandbox-licence{display:block;margin-top:2px;font-size:.78rem;color:#8B5A18}
/* currentColor, not the site link green: the bar sets its own ink
   against the amber tint and a link that opts out of it would be both
   louder than intended and unmeasured for contrast. */
.sandbox-licence a{color:inherit;text-decoration-thickness:1px}
.sandbox-licence a:hover{color:#8A4B04}

/* ---------------------------- hero ---------------------------- */
.hero{padding:clamp(40px,7vw,78px) 0 clamp(44px,6vw,72px)}
.hero-grid{display:grid;grid-template-columns:1.02fr .98fr;gap:clamp(28px,5vw,60px);align-items:center}
@media(max-width:900px){.hero-grid{grid-template-columns:1fr}}
.hero h1{margin-bottom:1rem}
.hero-lede{font-size:var(--fs-lede);color:var(--ink-2);max-width:44ch;margin-bottom:1.6rem}
.underline-mag{
  background:linear-gradient(transparent 62%,var(--magenta-tint) 62%);
  /* Padding on both sides sits on top of the normal word space and
     reads as a double space. Pull the trailing side back. */
  padding:0 .12em;margin-inline-end:-.1em;box-decoration-break:clone
}
.trust-row{display:flex;flex-wrap:wrap;gap:8px 18px;font-size:.87rem;color:var(--muted);margin-top:1.4rem}
.trust-row span{display:flex;align-items:center;gap:7px}

/* ---------------------------- sections ---------------------------- */
/* .band and .band-head padding/measure live in the RHYTHM section
   below, on the --band-y / --s-* scale. They were declared twice; the
   hardcoded pair here was dead, overridden by the scale further down,
   and left the rhythm looking like two decisions instead of one. */
.band-ink{background:var(--ink);color:#fff}
.band-ink h2,.band-ink h3{color:#fff}
.band-ink .muted{color:rgba(255,255,255,.62)}
.band-white{background:#fff;border-block:1px solid var(--line)}

.rate-table{width:100%;border-collapse:collapse;font-size:.94rem;background:#fff}
.rate-table th{
  text-align:left;font-family:var(--mono);font-size:.68rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--muted);font-weight:500;padding:12px 14px;border-bottom:1px solid var(--line)
}
.rate-table td{padding:14px;border-bottom:1px solid #EFF3F1;vertical-align:middle}
.rate-table tr:last-child td{border-bottom:0}
.rate-table .num{font-family:var(--mono);font-variant-numeric:tabular-nums;text-align:right}
.flag{font-size:1.25rem;margin-right:9px;vertical-align:-2px}
.table-scroll{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);background:#fff}

/* ---------------------------- progress ---------------------------- */
.progress{display:flex;gap:6px;margin-bottom:28px;list-style:none;padding:0}
.progress li{
  flex:1;font-family:var(--mono);font-size:.66rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);padding-top:9px;border-top:3px solid var(--line)
}
.progress li.on{color:var(--pine-dark);border-top-color:var(--pine)}
.progress li.done{color:var(--ink);border-top-color:var(--ink)}

/* ---------------------------- timeline ---------------------------- */
.timeline{list-style:none;padding:0;margin:0}
.timeline li{position:relative;padding:0 0 22px 30px;border-left:2px solid var(--line);margin-left:6px}
.timeline li:last-child{border-left-color:transparent;padding-bottom:0}
.timeline li::before{
  content:"";position:absolute;left:-7px;top:3px;width:12px;height:12px;
  border-radius:50%;background:var(--line);border:2.5px solid var(--surface)
}
.timeline li.done::before{background:var(--pine)}
.timeline li.now::before{background:var(--magenta);box-shadow:0 0 0 4px var(--magenta-tint)}
.tl-title{font-weight:600;font-size:.96rem}
.tl-time{font-family:var(--mono);font-size:.76rem;color:var(--muted)}

/* ---------------------------- tables/list ---------------------------- */
.tx-row{
  display:flex;align-items:center;gap:14px;padding:15px 18px;
  border-bottom:1px solid #EFF3F1;text-decoration:none;color:inherit
}
.tx-row:last-child{border-bottom:0}
.tx-row:hover{background:#FAFCFB}
.tx-main{flex:1;min-width:0}
.tx-name{font-weight:600;font-size:.97rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tx-amt{font-family:var(--mono);font-weight:600;text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}

.empty{padding:48px 24px;text-align:center;color:var(--muted)}
.empty h3{color:var(--ink);margin-bottom:.5rem}

.alert{padding:13px 16px;border-radius:var(--radius-sm);font-size:.92rem;margin-bottom:18px}
.alert-err{background:var(--magenta-tint);color:#8E1246;border:1px solid #F3CCDC}
.alert-ok{background:var(--pine-tint);color:var(--pine-dark);border:1px solid #C4DFD6}
.alert-warn{background:var(--amber-tint);color:var(--amber);border:1px solid #F0DCBC}

.page{padding:36px 0 64px}
.page-head{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;margin-bottom:24px;flex-wrap:wrap}

footer.foot{background:var(--ink);color:rgba(255,255,255,.66);padding:52px 0 34px;font-size:.9rem}
.foot-grid{display:grid;grid-template-columns:1.6fr 1fr 1fr;gap:32px;margin-bottom:34px}
@media(max-width:760px){.foot-grid{grid-template-columns:1fr}}
.foot h3.foot-h,.foot h4{font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.72);margin-bottom:14px;font-weight:500}
.foot a{color:rgba(255,255,255,.78);text-decoration:none;display:block;padding:4px 0}
.foot a:hover{color:#fff}
.foot-legal{border-top:1px solid rgba(255,255,255,.11);padding-top:22px;font-size:.8rem;color:rgba(255,255,255,.75);line-height:1.6}

@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

/* =====================================================================
   HERO DEPTH

   CSS only — no images, no libraries. Three layers behind the receipt:

     wash    two large, very soft radial tints, drifting slowly
     route   a dashed line between two points with a token travelling
             it, which is literally what the product does
     grain   a faint dot lattice giving the flat colour some tooth

   Every colour is a theme variable, so a licensee's palette drives
   this exactly as it drives everything else.
   ===================================================================== */
.hero{position:relative;overflow:hidden;isolation:isolate}

.hero-bg{
  position:absolute;inset:0;z-index:-1;pointer-events:none;
  /* Never announced: it carries no information a screen reader needs. */
}
.hero-bg::before{
  content:"";position:absolute;inset:-20%;
  background:
    radial-gradient(38% 44% at 18% 22%, color-mix(in oklab, var(--pine) 22%, transparent), transparent 70%),
    radial-gradient(34% 40% at 82% 68%, color-mix(in oklab, var(--magenta) 16%, transparent), transparent 70%);
  filter:blur(6px);
  animation:wash 34s ease-in-out infinite alternate
}
/* Browsers without color-mix still get a wash, just a flatter one. */
@supports not (background: color-mix(in oklab, red 20%, transparent)){
  .hero-bg::before{
    background:
      radial-gradient(38% 44% at 18% 22%, var(--pine-tint), transparent 70%),
      radial-gradient(34% 40% at 82% 68%, var(--magenta-tint), transparent 70%)
  }
}
.hero-bg::after{
  content:"";position:absolute;inset:0;
  background-image:radial-gradient(currentColor .5px, transparent .5px);
  background-size:22px 22px;color:var(--ink);opacity:.05
}
@keyframes wash{
  from{transform:translate3d(-1.5%,-1%,0) scale(1)}
  to  {transform:translate3d(1.5%,1.5%,0) scale(1.06)}
}

/* The route: two places, a dashed path, and a token crossing it. */
.hero-route{
  position:absolute;inset-inline:6%;top:22%;height:2px;z-index:-1;
  pointer-events:none;opacity:.5
}
.hero-route i{
  position:absolute;inset-inline:0;top:0;height:2px;display:block;
  background:repeating-linear-gradient(90deg,
    color-mix(in oklab, var(--ink) 34%, transparent) 0 6px, transparent 6px 14px)
}
.hero-route b, .hero-route s{
  position:absolute;top:50%;width:9px;height:9px;border-radius:50%;
  transform:translateY(-50%);background:var(--pine);
  box-shadow:0 0 0 5px color-mix(in oklab, var(--pine) 18%, transparent)
}
.hero-route b{inset-inline-start:0}
.hero-route s{inset-inline-end:0;background:var(--magenta);
  box-shadow:0 0 0 5px color-mix(in oklab, var(--magenta) 18%, transparent)}
.hero-route em{
  position:absolute;top:50%;inset-inline-start:0;width:7px;height:7px;border-radius:50%;
  background:var(--magenta);transform:translate(-50%,-50%);
  animation:travel 7s cubic-bezier(.65,0,.35,1) infinite
}
@keyframes travel{
  0%       {inset-inline-start:0;   opacity:0}
  12%      {opacity:1}
  88%      {opacity:1}
  100%     {inset-inline-start:100%; opacity:0}
}
@media(max-width:900px){ .hero-route{display:none} }

/* =====================================================================
   RHYTHM AND HEADINGS
   ===================================================================== */
.band{padding:var(--band-y) 0}
.band-head{max-width:var(--measure);margin-bottom:var(--s-5)}
.band-head h2{margin-bottom:var(--s-2);text-wrap:balance}
.band-head p{max-width:var(--measure-tight);color:var(--muted);font-size:var(--fs-lede)}
.band-head.center{margin-inline:auto;text-align:center}
.band-head.center p{margin-inline:auto}

/* Section headings earn more presence: a short rule above the eyebrow
   ties the heading to the band it opens. */
.band-head .eyebrow{display:inline-flex;align-items:center;gap:.6rem}
.band-head .eyebrow::before{
  content:"";width:26px;height:2px;background:var(--magenta);flex:none;border-radius:2px
}
.band-ink .band-head .eyebrow::before{background:var(--magenta)}
h2{font-size:clamp(1.7rem,3.6vw,2.7rem)}
.lede{font-size:1.06rem;color:var(--ink-2);max-width:var(--measure)}
p{max-width:var(--measure)}
.hero-lede{max-width:46ch}

/* =====================================================================
   CORRIDOR STRIP
   Scrolls horizontally on small screens rather than reflowing into a
   column — a row of destinations is a row, and swiping it is the
   gesture people already use for this shape of content.
   ===================================================================== */
.corridors{
  display:grid;grid-auto-flow:column;grid-auto-columns:min(78vw,268px);
  gap:14px;overflow-x:auto;padding:4px 4px 16px;
  scroll-snap-type:x proximity;
  scrollbar-width:thin;-webkit-overflow-scrolling:touch
}
.corridors::-webkit-scrollbar{height:6px}
.corridors::-webkit-scrollbar-thumb{background:var(--line);border-radius:99px}
@media(min-width:900px){
  .corridors{grid-auto-flow:row;grid-template-columns:repeat(3,1fr);overflow:visible}
}
.corridor{
  scroll-snap-align:start;
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:18px;text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:10px;
  box-shadow:var(--lift-1);
  transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease
}
.corridor:hover{transform:translateY(-3px);box-shadow:var(--lift-2);border-color:var(--pine)}
.corridor:focus-visible{transform:translateY(-3px);box-shadow:var(--lift-2)}
/* Wraps rather than clips: "Afghanistan" plus a delivery badge does
   not fit one 210px line, and a single long word cannot shrink. The
   badge drops to its own line and stays end-aligned. */
.corridor-top{display:flex;align-items:center;gap:8px;flex-wrap:wrap;row-gap:6px}
.corridor-flag{font-size:1.6rem;line-height:1}
.corridor-name{font-weight:700;font-family:var(--display);letter-spacing:-.01em;
  min-width:0;overflow-wrap:anywhere}
.corridor-eta{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--pine-dark);background:var(--pine-tint);padding:3px 9px;border-radius:var(--radius-pill);
  margin-inline-start:auto;white-space:nowrap
}
.corridor-amt{
  font-family:var(--mono);font-size:1.55rem;font-weight:600;letter-spacing:-.025em;
  color:var(--ink);line-height:1.05
}
/* The rate line is the evidence for the figure above it, so it is set
   as data — mono, tabular, one clear step down — rather than as a
   second line of prose the eye has to sort from the methods list. */
.corridor-rate{
  font-family:var(--mono);font-size:.76rem;color:var(--ink-2);
  font-variant-numeric:tabular-nums;letter-spacing:-.01em;margin-top:-4px
}
.corridor-sub{font-size:.78rem;color:var(--muted)}
/* The arrow leads on hover. Two pixels, and only where the pointer is. */
.corridor-go svg{transition:transform .18s ease}
.corridor:hover .corridor-go svg,
.corridor:focus-visible .corridor-go svg{transform:translateX(3px)}
.corridor-go{
  margin-top:auto;font-size:.85rem;font-weight:600;color:var(--pine-dark);
  display:flex;align-items:center;gap:6px
}
.corridor-go svg{transition:transform .18s ease}
.corridor:hover .corridor-go svg{transform:translateX(3px)}

/* =====================================================================
   STEPS — numbered, iconed, connected
   ===================================================================== */
.flow{list-style:none;padding:0;margin:0;display:grid;gap:var(--s-4);position:relative}
@media(min-width:820px){
  .flow{grid-template-columns:repeat(3,1fr);gap:var(--s-4)}
  /* The connector: one line behind the row, drawn only where there is
     a row to connect. */
  .flow::before{
    content:"";position:absolute;top:34px;inset-inline:16%;height:2px;
    background:repeating-linear-gradient(90deg,
      rgba(255,255,255,.28) 0 7px, transparent 7px 15px)
  }
}
.flow-step{position:relative;text-align:start}
.flow-mark{
  width:68px;height:68px;border-radius:20px;display:grid;place-items:center;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.16);
  position:relative;z-index:1;margin-bottom:var(--s-3);
  backdrop-filter:blur(2px)
}
.flow-mark svg{width:28px;height:28px;stroke:#fff;fill:none;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.flow-n{
  position:absolute;top:-7px;inset-inline-end:-7px;
  width:25px;height:25px;border-radius:50%;background:var(--magenta);color:#fff;
  font-family:var(--mono);font-size:.72rem;font-weight:600;display:grid;place-items:center;
  border:2px solid var(--ink)
}
.flow-step h3{margin-bottom:.45rem;font-size:1.18rem}
.flow-step p{font-size:.94rem;max-width:34ch;margin:0}

/* =====================================================================
   TRUST BAND
   ===================================================================== */
.trust-grid{display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(232px,1fr));align-items:stretch}
.trust-card{
  background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:24px;box-shadow:var(--lift-1);
  transition:transform .18s ease, box-shadow .18s ease
}
.trust-card:hover{transform:translateY(-2px);box-shadow:var(--lift-2)}
.trust-icon{
  width:40px;height:40px;border-radius:11px;display:grid;place-items:center;
  background:var(--pine-tint);margin-bottom:var(--s-3)
}
.trust-icon svg{width:20px;height:20px;stroke:var(--pine-dark);fill:none;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.trust-card h3{
  margin-bottom:.45rem;font-size:1.06rem;
  /* Four across is a narrow column; balance stops "held / apart"
     breaking one word onto its own line. */
  text-wrap:balance
}
.trust-card p{font-size:.9rem;color:var(--muted);margin:0;max-width:38ch}

/* A placeholder slot, labelled as one. Never a fabricated quote. */
.placeholder-quote{
  border:1.5px dashed var(--line);background:transparent;border-radius:var(--radius);
  padding:24px;display:flex;flex-direction:column;gap:10px
}
.placeholder-tag{
  font-family:var(--mono);font-size:.64rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);border:1px solid var(--line);border-radius:5px;padding:3px 7px;
  align-self:flex-start
}
.placeholder-quote p{color:var(--muted);font-size:.92rem;margin:0}

/* =====================================================================
   CLOSING CTA
   ===================================================================== */
.closer{
  position:relative;overflow:hidden;isolation:isolate;
  background:var(--ink);color:#fff;border-radius:calc(var(--radius) * 1.6);
  padding:clamp(2.2rem,5vw,3.6rem);text-align:center
}
.closer::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:
    radial-gradient(46% 60% at 12% 8%,  color-mix(in oklab, var(--pine) 46%, transparent), transparent 72%),
    radial-gradient(42% 56% at 88% 92%, color-mix(in oklab, var(--magenta) 32%, transparent), transparent 72%)
}
.closer h2{color:#fff;margin-bottom:var(--s-2)}
.closer p{color:rgba(255,255,255,.72);margin-inline:auto;margin-bottom:var(--s-4);max-width:48ch}
.closer .btn-primary{background:#fff;color:var(--ink)}
.closer .btn-primary:hover{background:rgba(255,255,255,.9)}
.closer .btn-ghost{color:#fff;border-color:rgba(255,255,255,.34)}
.closer .btn-ghost:hover{background:rgba(255,255,255,.10)}
.closer-actions{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}

/* =====================================================================
   QUOTE STATES — never show a stale figure unmarked
   ===================================================================== */
.quote-status{
  display:flex;align-items:center;gap:8px;margin:12px 0 0;
  font-size:.83rem;color:var(--muted)
}
/* display:flex would otherwise beat the hidden attribute's display:none
   and leave a spinner running under a settled quote. */
.quote-status[hidden]{display:none}
.quote-status::before{
  content:"";width:12px;height:12px;border-radius:50%;flex:none;
  border:2px solid var(--line);border-top-color:var(--pine);
  animation:spin .7s linear infinite
}
@keyframes spin{to{transform:rotate(360deg)}}
.receipt.is-error .quote-status{color:var(--magenta)}
.receipt.is-error .quote-status::before{
  border-color:var(--magenta);border-top-color:var(--magenta);animation:none
}
/* While pending, the figures are dimmed — the customer can still read
   them, but they are visibly not the current answer. */
.receipt.is-loading .arrives,
.receipt.is-loading .line-row dd{opacity:.42;transition:opacity .15s ease}
.receipt.is-loading .receipt-foot .btn{opacity:.55;pointer-events:none}

.arrives{transition:color .25s ease}
.just-changed{animation:figure-in .5s ease-out}
@keyframes figure-in{
  0%  {color:var(--magenta)}
  100%{color:var(--ink)}
}

/* =====================================================================
   REVEAL ON SCROLL — short, small, and off for reduced motion
   ===================================================================== */
/* Gated on .js, which is set by an inline script in <head> before
   first paint. Without JavaScript — or if the script fails — nothing
   is ever hidden, so the page reads in full. Hiding content that only
   JS can bring back is how a whole page ends up blank. */
.js [data-reveal]{opacity:0;transform:translateY(14px)}
[data-reveal].revealed{
  opacity:1;transform:none;
  transition:opacity .5s ease, transform .5s cubic-bezier(.22,1,.36,1)
}
[data-reveal][data-delay="1"].revealed{transition-delay:.06s}
[data-reveal][data-delay="2"].revealed{transition-delay:.12s}
[data-reveal][data-delay="3"].revealed{transition-delay:.18s}

/* =====================================================================
   HOVER / FOCUS
   ===================================================================== */
.btn{transition:transform .12s ease, background .18s ease, box-shadow .18s ease, border-color .18s ease}
.btn-primary{box-shadow:var(--lift-1)}
.btn-primary:hover{box-shadow:var(--lift-2);transform:translateY(-1px)}
.btn-dark:hover{transform:translateY(-1px);box-shadow:var(--lift-2)}
.btn-ghost:hover,.btn-line:hover{transform:translateY(-1px)}
.card{transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease}

/* Inputs: a wider, softer ring and a visible resting affordance. */
input[type=text],input[type=email],input[type=password],input[type=tel],
input[type=number],input[type=date],select,textarea{
  transition:border-color .16s ease, box-shadow .16s ease, background .16s ease
}
input:hover,select:hover,textarea:hover{border-color:#B9C7C3}
input:focus,select:focus,textarea:focus{
  border-color:var(--pine);outline:none;
  box-shadow:0 0 0 4px color-mix(in oklab, var(--pine) 16%, transparent)
}
@supports not (background: color-mix(in oklab, red 20%, transparent)){
  input:focus,select:focus,textarea:focus{box-shadow:0 0 0 4px var(--pine-tint)}
}
.amount-input:focus-within .sym{color:var(--pine-dark)}
.rate-table tbody tr{transition:background .15s ease}
.rate-table tbody tr:hover{background:var(--pine-tint)}

/* =====================================================================
   360px
   ===================================================================== */
/* The delivery badge and the arrival figure cannot share one row on a
   narrow screen: the figure is deliberately large and a single long
   number cannot shrink, so the badge was being clipped by the card
   edge. Below 480 the head becomes a two-row grid — label and badge on
   the first, the figure spanning the second. "display:contents" lets
   the label and figure become grid children without changing markup. */
@media(max-width:480px){
  .receipt-head{display:grid;grid-template-columns:1fr auto;align-items:center;gap:4px 10px}
  .receipt-head > div{display:contents}
  .arrives-label{grid-column:1;grid-row:1;margin-bottom:0}
  .receipt-head .badge{grid-column:2;grid-row:1;justify-self:end}
  .arrives{grid-column:1 / -1;grid-row:2}
}

@media(max-width:400px){
  .wrap{padding-inline:16px}
  .receipt-head,.receipt-body{padding-inline:18px}
  .receipt-foot{padding-inline:18px}
  .arrives{font-size:clamp(1.75rem,10vw,2.3rem)}
  .flow-mark{width:58px;height:58px;border-radius:17px}
  .corridors{margin-inline:-16px;padding-inline:16px}
  .closer{border-radius:var(--radius);padding:1.8rem 1.2rem}
  .trust-row{gap:6px 12px;font-size:.82rem}
}

/* Everything above is motion; none of it survives the media query the
   original build already respected. */
@media (prefers-reduced-motion:reduce){
  .hero-bg::before,.hero-route em{animation:none}
  .quote-status::before{animation:none}
  .js [data-reveal]{opacity:1;transform:none}
  .corridor:hover,.trust-card:hover,.btn:hover{transform:none}
  .corridor:hover .corridor-go svg,
  .corridor:focus-visible .corridor-go svg{transform:none}
}

/* ---------------------------------------------------------------------
   Footer logo.

   ".foot a{display:block}" (0-1-1) outranks ".logo{display:flex}"
   (0-1-0), so the footer's brand mark became a block-level grid box and
   stretched to the full column — a 26px badge rendered 459px wide.
   Restoring the flex row here rather than weakening the .foot a rule,
   which every other footer link still needs.
   --------------------------------------------------------------------- */
.foot .logo{display:inline-flex;width:auto;padding:0}
.foot .logo-mark{width:26px;min-width:26px;flex:none}

/* The closing CTA follows another band, so their padding stacks into a
   gap twice the intended rhythm. Halve the join rather than special-
   casing either band's own spacing. */
.band + .band-closer{padding-top:0}
.band-closer{padding-bottom:var(--band-y)}

/* =====================================================================
   PROSE — tenant-authored page bodies at /p/{slug}

   The body is HTML the licensee wrote, restricted to a small allowlist.
   Styling it here rather than letting authors carry style attributes is
   the point: the sanitiser strips style and class, so the only way a
   page can look right is if the stylesheet already knows what to do
   with the tags it is allowed to use.
   ===================================================================== */
.prose{max-width:68ch;color:var(--ink-2);font-size:1.02rem;line-height:1.72}
.prose > *:first-child{margin-top:0}
.prose h2{
  font-size:1.35rem;margin:2.4rem 0 .7rem;color:var(--ink);
  letter-spacing:-.015em;text-wrap:balance
}
.prose h3{font-size:1.1rem;margin:1.9rem 0 .5rem;color:var(--ink)}
.prose h4{font-size:.98rem;margin:1.5rem 0 .4rem;color:var(--ink)}
.prose p{margin:0 0 1.05rem;max-width:none}
.prose ul,.prose ol{margin:0 0 1.05rem;padding-inline-start:1.35rem}
.prose li{margin-bottom:.45rem}
.prose li::marker{color:var(--pine)}
.prose a{color:var(--pine-dark);text-underline-offset:2px}
.prose a:hover{color:var(--ink)}
.prose strong{color:var(--ink);font-weight:650}
.prose hr{border:0;border-top:1px solid var(--line);margin:2rem 0}
.prose blockquote{
  margin:1.4rem 0;padding:.2rem 0 .2rem 1.1rem;
  border-inline-start:3px solid var(--pine);color:var(--muted)
}
/* Tables in a policy document are usually a fee or retention schedule
   and are the part most likely to be read on a phone. */
.prose table{
  width:100%;border-collapse:collapse;margin:1.3rem 0;font-size:.94rem;
  display:block;overflow-x:auto;white-space:nowrap
}
@media(min-width:640px){.prose table{display:table;white-space:normal}}
.prose th{
  text-align:start;font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);font-weight:500;
  padding:10px 12px;border-bottom:1px solid var(--line)
}
.prose td{padding:11px 12px;border-bottom:1px solid #EFF3F1;vertical-align:top}
.prose tr:last-child td{border-bottom:0}

.foot-social{display:flex;flex-wrap:wrap;gap:6px 14px;margin-top:14px}
.foot-social a{display:inline;padding:0;font-size:.85rem}
.logo-img{height:30px;width:auto;display:block;border-radius:6px}

/* =====================================================================
   MOBILE — the send flow, the receipt and authored content

   The public site was already fluid; what it lacked was the handful of
   patterns a phone needs that a narrow desktop does not.
   ===================================================================== */

/* ---- progress: four segments on desktop, "Step 2 of 4" on a phone ----
   One list in the markup, restyled. Two separate indicators could drift
   apart and tell the customer different things. */
.progress-mobile { display: none; }

@media (max-width: 640px) {
    .progress { display: none; }
    .progress-mobile {
        display: flex; align-items: baseline; gap: 10px;
        margin: 0 0 20px; padding-bottom: 12px;
        border-bottom: 2px solid var(--line);
        position: relative;
    }
    /* The bar underneath fills in proportion to the step, so progress is
       visible as well as stated. */
    .progress-mobile::after {
        content: ""; position: absolute; inset-block-end: -2px; inset-inline-start: 0;
        height: 2px; background: var(--pine);
        width: calc(var(--step, 1) / var(--total, 4) * 100%);
        transition: width .3s ease;
    }
    .progress-mobile-step {
        font-family: var(--mono); font-size: .68rem; letter-spacing: .12em;
        text-transform: uppercase; color: var(--muted); white-space: nowrap;
    }
    .progress-mobile-name { font-weight: 650; font-size: 1.05rem; color: var(--ink); }
}

/* ---- the primary action stays reachable ----
   On a long step the Continue button sits below the fold; a thumb
   should not have to scroll to find the only thing it can do next. */
@media (max-width: 640px) {
    .send-cta {
        position: sticky; bottom: 0; z-index: 20;
        margin-inline: -22px; margin-block-start: 18px;
        padding: 12px 22px calc(12px + env(safe-area-inset-bottom, 0px));
        background: color-mix(in oklab, var(--surface) 92%, transparent);
        backdrop-filter: blur(8px);
        border-top: 1px solid var(--line);
    }
    @supports not (backdrop-filter: blur(4px)) {
        .send-cta { background: var(--surface); }
    }
    .send-cta .btn { min-height: 52px; font-size: 1.02rem; }
}

/* ---- receipt, one-handed ---- */
@media (max-width: 640px) {
    .receipt-body .field { margin-bottom: 18px; }
    .amount-input input { min-height: 60px; font-size: 1.75rem; }
    select, input[type=text], input[type=email], input[type=password],
    input[type=tel], input[type=number], input[type=date], textarea {
        min-height: 48px; font-size: 1rem;   /* 16px stops iOS zooming on focus */
    }
    .btn { min-height: 48px; }
    .btn-sm { min-height: 44px; }
    .nav a { min-height: 44px; display: inline-flex; align-items: center; }
    .logo { min-height: 44px; }
    .foot a { min-height: 44px; display: flex; align-items: center; }
    .foot-social a { min-height: 44px; }
}

/* ---- authored page content must not break the layout ----
   /p/{slug} bodies are HTML an admin wrote. A long URL or a wide table
   would otherwise push the whole page sideways. */
.prose { overflow-wrap: anywhere; }
.prose a { overflow-wrap: anywhere; }
.prose pre, .prose code { overflow-x: auto; max-width: 100%; }
@media (max-width: 640px) {
    .prose table { display: block; overflow-x: auto; white-space: nowrap; max-width: 100%; }
    .prose h2 { font-size: 1.2rem; }
}

/* ---- rate table: let it scroll rather than squeeze ---- */
@media (max-width: 640px) {
    .table-scroll { -webkit-overflow-scrolling: touch; }
    .rate-table { min-width: 34rem; }
}

/* ---- public header at phone width ----
   The wrapping itself is now unconditional — see .topbar .wrap above,
   which is where the 701-960px gap this block used to leave is
   explained. What is left here is the phone TREATMENT: the nav takes a
   full row of its own rather than trailing the logo, and everything
   tightens up. The header wraps to a second line rather than collapsing
   into a menu: these links are worth showing, and a hamburger for them
   is a tap nobody needs to make. */
@media (max-width: 700px) {
    .topbar .wrap {
        min-height: 56px;
        padding-block: 8px;
    }
    .nav {
        margin-inline-start: 0;
        width: 100%;
        gap: 2px 4px;
    }
    .nav a { padding: 9px 10px; font-size: .88rem; }
    .nav .btn { margin-inline-start: 0 !important; }
    .logo { font-size: 1.1rem; }
}
@media (max-width: 380px) {
    .nav a { padding: 9px 8px; font-size: .84rem; }
}


/* ---- contrast on the dark footer ----
   .muted is a light-background grey (#64797E). On the footer's dark
   panel it measured 3.76:1, under the AA floor. Inside the footer the
   same intent needs a light value instead. */
.foot h3.foot-h { font-size:.7rem; }
.foot .muted { color: rgba(255,255,255,.74); }
.foot-legal p { color: rgba(255,255,255,.75); }
.foot-legal a { color: rgba(255,255,255,.9); text-decoration: underline; }
/* An inline link distinguished only by colour fails AA; underline it. */
.foot-legal a[href], .foot p a { text-decoration: underline; }
/* .foot-powered was removed on 2026-09-01 along with the element it
   styled — the old "Powered by EH Remit from eCom Healer." line. Its
   note is kept here because the lesson outlived it: an inline
   opacity:.6 on that line dropped the computed colour to 4.45:1, just
   under the AA floor, and the fix was to express the de-emphasis as a
   colour that passes rather than as an opacity that compounds. The
   .foot-mark rule below is written that way for the same reason. */

/* ===================================================================
   CONTACT PAGE
   =================================================================== */

/* The details panel. A description list because that is what it is —
   a label and its value — rather than a table, which would announce
   rows and columns to a screen reader that has neither. */
.contact-details{
  margin:0 0 2rem;padding:18px 20px;
  border:1px solid var(--line);border-radius:var(--radius);
  background:var(--card);
}
.contact-row{display:flex;gap:16px;padding:9px 0;border-bottom:1px solid var(--line)}
.contact-row:last-child{border-bottom:0}
.contact-row:first-child{padding-top:0}
.contact-row:last-child{padding-bottom:0}
.contact-details dt{
  flex:0 0 9.5rem;margin:0;font-weight:650;color:var(--ink);font-size:.9rem;
}
.contact-details dd{margin:0;color:var(--ink-2);font-size:.95rem}

/* Stack below the point where a 9.5rem label column starts squeezing
   an address into one word per line. */
@media (max-width:560px){
  .contact-row{flex-direction:column;gap:2px}
  .contact-details dt{flex:none}
}

.contact-form{max-width:44rem}
.contact-form textarea{min-height:9rem;resize:vertical}

/* A validation message, not a hint. Same size and position as .hint so
   the field does not jump when one replaces the other. */
.hint.err{color:#8E1246;font-weight:600}
.contact-form [aria-invalid="true"]{border-color:#D98BAC}
.contact-form [aria-invalid="true"]:focus{outline-color:#D98BAC}

/* THE HONEYPOT.
   display:none rather than an off-screen position. Off-screen is the
   usual advice for hiding things from sight but not from assistive
   technology — here that is precisely backwards: this field must be
   hidden from PEOPLE, including screen reader users, and left visible
   only to something parsing the raw markup. A blind visitor who fills
   this in has their message silently discarded, so it must not be
   reachable by any means a person has. aria-hidden and tabindex="-1"
   in the markup are the other two layers. */
.hp-field{display:none !important}

/* The form's own heading. Sized DOWN from the global h2, which is a
   display size meant for a landing-page section and would otherwise be
   larger than the page's own h1 — the h1 here carries an inline 2rem,
   the same as every other /p/ page. A subheading bigger than the title
   above it reads as the page starting twice. */
.contact-h2{font-size:1.35rem;margin:2.4rem 0 1rem}

/* ===================================================================
   COOKIE CONSENT
   =================================================================== */

/* Fixed to the bottom rather than covering the page. A modal overlay
   that blocks the content until you answer is a consent taken under
   pressure, and pressure is the thing "freely given" excludes. The
   visitor can read the site, read the cookie policy and then decide. */
/* Positioned by .fixed-stack below, not by itself. It used to carry
   its own position:fixed; the wrapper took that over so the chat
   button can sit above it without anybody having to know how tall it
   is at a given width. align-self:stretch keeps it full-bleed while
   its sibling stays a small right-aligned button. */
.cookie-banner{
  align-self:stretch;
  background:var(--ink);color:#fff;
  border-top:3px solid var(--pine);
  box-shadow:0 -8px 28px rgba(11,29,36,.28);
}
.cookie-banner-inner{
  display:flex;gap:22px;align-items:center;justify-content:space-between;
  padding-block:16px;flex-wrap:wrap;
}
.cookie-banner-text{flex:1 1 30rem;min-width:0}
.cookie-banner h2{font-size:1.02rem;margin:0 0 4px;color:#fff}
.cookie-banner p{margin:0;font-size:.88rem;line-height:1.55;color:rgba(255,255,255,.82);max-width:70ch}
/* Scoped to the paragraph. An unscoped `.cookie-banner a` also caught
   the Manage preferences button, which is an <a> styled as a button —
   an underlined button reads as a link that has been made to look
   important, which is the opposite of the intent. */
.cookie-banner-text a{color:#fff;text-decoration:underline;text-underline-offset:2px}

.cookie-banner-actions{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:0}

/* ACCEPT AND REJECT ARE THE SAME BUTTON.
   Same class, same padding, same font, same weight, same background,
   side by side, neither one the coloured "primary" and neither one the
   ghost. This is a legal requirement rather than a taste: a reject
   that is smaller, greyer or one click further away is the pattern the
   ICO writes to people about. If a future change makes one of these
   stand out, it has to make the other stand out equally. */
.btn-consent{
  background:#fff;color:var(--ink);border:1px solid #fff;
  min-width:9.5rem;justify-content:center;text-align:center;font-weight:650
}
.btn-consent:hover{background:#EDF2F1;color:var(--ink);border-color:#EDF2F1}

/* Manage preferences is the only one that may look secondary — it
   makes no decision, it opens a page. */
.cookie-banner-actions .btn-consent-manage{
  background:transparent;color:#fff;border-color:rgba(255,255,255,.5);min-width:0
}
.cookie-banner-actions .btn-consent-manage:hover{
  background:rgba(255,255,255,.1);color:#fff;border-color:#fff
}

@media(max-width:760px){
  .cookie-banner-inner{align-items:stretch}
  .cookie-banner-actions{width:100%}
  /* Still equal to each other, and now both full width: on a phone the
     two decisions share a row and the third drops below, so neither
     decision is the one your thumb reaches first. */
  .cookie-banner-actions .btn-consent{flex:1 1 0;min-width:0}
  .cookie-banner-actions .btn-consent-manage{flex:1 1 100%}
}
@media(max-width:380px){
  .cookie-banner p{font-size:.84rem}
  .cookie-banner-actions .btn-consent{flex:1 1 100%}
}

/* ---------------- the preferences form ---------------- */

.cookie-prefs{max-width:44rem;margin-top:1.4rem}
.cookie-cat{
  border:1px solid var(--line);border-radius:var(--radius);
  padding:14px 16px;margin-bottom:12px;background:var(--card)
}
.cookie-cat.is-locked{background:var(--pine-tint);border-color:#C4DFD6}
.cookie-cat-head{display:flex;align-items:center;justify-content:space-between;gap:14px}
.cookie-cat-head label{margin:0;font-size:1rem;font-weight:650;color:var(--ink)}
.cookie-cat-head input[type=checkbox]{width:22px;height:22px;flex:0 0 22px;accent-color:var(--pine)}
.cookie-always{
  font-size:.76rem;font-weight:700;letter-spacing:.02em;
  color:var(--pine-dark);background:#fff;border:1px solid #C4DFD6;
  border-radius:20px;padding:3px 10px;white-space:nowrap
}
.cookie-cat-desc{margin:6px 0 0;font-size:.88rem;line-height:1.55;color:var(--ink-2);max-width:62ch}
.cookie-prefs-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:18px}

@media(max-width:380px){
  .cookie-prefs-actions .btn{flex:1 1 100%;justify-content:center;text-align:center}
}

/* The entry-tier attribution mark. Discreet by design: smaller than the
   footer's own small print and lower contrast than the copyright above
   it, so it reads as a maker's mark rather than as a second brand on
   the licensee's site.

   Still a real link with a real hover, and still legible — "discreet"
   is not a licence to hide it. A mark nobody can read is not
   attribution, and one that fails contrast outright would be a defect
   on a page that has to meet AA elsewhere. */
.foot-mark{
  margin:14px 0 0;
  font-size:.78rem;
  color:rgba(255,255,255,.42);
  letter-spacing:.01em;
}
.foot-mark a{
  /* `.foot a` sets display:block for the stacked link columns, and at
     (0-1-1) it outranks a bare `a` — the same specificity trap this
     stylesheet already records at the .logo rule below. Without this
     the mark breaks across two lines: "Designed & Developed by" then
     "eCom Healer" — a longer phrase since 2026-09-07, so this matters
     more than it did, not less.
     Declared here rather than as an inline style on the anchor — which
     is how the old foot-powered line used to work around the same rule,
     and one reason it was easy to miss. */
  display:inline;
  color:rgba(255,255,255,.58);
  text-decoration:underline;
  text-underline-offset:2px;
  padding:0;
}
.foot-mark a:hover{color:rgba(255,255,255,.85)}

/* ===================================================================
   FIXED BOTTOM STACK — chat button above, cookie banner below
   =================================================================== */

/* THE FIXED LAYER — four zones and the banner, no offsets anywhere.

   A column filling the viewport: the middle band takes what is left,
   the bottom band sits directly above the banner, and the banner is
   last. Two widgets in one corner are children of one flex column with
   a gap, so they stack; both bands move up by exactly the banner's
   height because the column reserves it. There is no number in here to
   be wrong at 380px, which is the whole reason it is built this way
   rather than with bottom: offsets.

   pointer-events:none covers the layer and the zones — this element
   spans the viewport and must not eat clicks or scrolling — and is
   restored on the widgets themselves. */
.fixed-stack{
  position:fixed;inset:0;z-index:60;
  display:flex;flex-direction:column;
  pointer-events:none;
}
.fixed-mid{
  flex:1 1 auto;min-height:0;
  display:flex;align-items:center;justify-content:space-between;
}
.fixed-bottom{
  flex:0 0 auto;
  display:flex;align-items:flex-end;justify-content:space-between;
}
/* Both bands always render both sides so justify-content keeps left on
   the left and right on the right even when only one side has a
   widget. An empty zone is zero-width and invisible. */
.fixed-mid:empty,.fixed-bottom:empty{display:none}

.fixed-zone{
  display:flex;flex-direction:column;align-items:flex-start;
  /* The gap is what stops two widgets in one corner overlapping. */
  gap:10px;
  pointer-events:none;
}
.fixed-zone > *{pointer-events:auto}
.fixed-zone-right{align-items:flex-end;margin-inline-start:auto}
.fixed-zone-left{align-items:flex-start;margin-inline-end:auto}
.fixed-stack > *{pointer-events:none}

/* AND THE BANNER GETS THE RESTORE TOO, which the rule above would
   otherwise take from it.

   The banner is a direct child of .fixed-stack rather than of a
   .fixed-zone, so `.fixed-zone > *` never reached it. pointer-events
   is inherited, so `none` flowed down through the form into every
   control: Accept, Reject and Manage preferences all rendered, looked
   correct, and could not be pressed. Consent could only be given or
   withdrawn from the footer link.

   THE DESCENDANT FORM IS LOAD-BEARING. `.cookie-banner` on its own is
   0-1-0, which ties `.fixed-stack > *` and loses to it on source
   order — putting pointer-events:auto in the .cookie-banner block
   further up this file does nothing whatsoever. This selector is
   0-2-0 and wins wherever it is placed. */
.fixed-stack > .cookie-banner{pointer-events:auto}

/* ---------------- the chat button ---------------- */

/* TENANT COLOURS, NOT WHATSAPP GREEN. #25D366 against an arbitrary
   licensee palette is a colour nobody chose, and this is the
   licensee's shopfront. The glyph carries the recognition.

   The bottom margin is what separates it from the banner when the
   banner is up, and from the viewport edge when it is not — one value,
   both cases, because they are the same gap. */
.wa-fab{
  display:inline-flex;align-items:center;gap:9px;
  margin:0 18px 18px;
  padding:12px 18px;
  background:var(--pine);color:#fff;
  border-radius:999px;
  font-weight:650;font-size:.92rem;line-height:1;
  text-decoration:none;
  box-shadow:0 6px 20px rgba(11,29,36,.28);
}
.wa-fab:hover{background:var(--pine-dark);color:#fff;text-decoration:none}
.wa-fab:focus-visible{outline:3px solid var(--magenta);outline-offset:3px}
.wa-fab-icon{width:22px;height:22px;flex:0 0 22px;display:block}

/* Below the width where a pill with a label starts crowding the
   viewport, it becomes a round icon button. The accessible name stays
   on the anchor either way, so nothing is lost to a screen reader. */
@media (max-width:560px){
  .wa-fab{padding:14px;border-radius:50%}
  .wa-fab-label{
    position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
  }
}

@media (prefers-reduced-motion:no-preference){
  .wa-fab{transition:background .15s ease, transform .15s ease}
  .wa-fab:hover{transform:translateY(-1px)}
}

/* .fixed-stack-shifted is gone. It used to move our buttons left when a
   third-party chat launcher loaded, because that launcher owns the
   bottom-right corner and cannot be reached from here. Position is now
   an explicit per-tenant setting, and silently overriding what a
   licensee chose is worse than the collision it avoided — so the
   console warns them in the Live chat panel instead. */

/* ---------------- the AI assistant ---------------- */

/* Same stack as the WhatsApp button and the cookie banner — it is a
   flex column, so a third element simply stacks and everything below
   it moves down. No offsets to keep in step.

   Deliberately quieter than the WhatsApp button: outlined rather than
   filled. On a money-transfer site the human channel should read as
   the primary one, and an automated assistant that shouts louder than
   the route to a person is the wrong hierarchy. */
.ai-fab{
  display:inline-flex;align-items:center;gap:8px;
  margin:0 18px 10px;padding:10px 16px;
  background:var(--card);color:var(--ink);
  border:1.5px solid var(--line);border-radius:999px;
  font-weight:600;font-size:.88rem;line-height:1;text-decoration:none;
  box-shadow:0 4px 14px rgba(11,29,36,.16);
}
.ai-fab:hover{border-color:var(--pine);color:var(--pine-dark);text-decoration:none}
.ai-fab:focus-visible{outline:3px solid var(--magenta);outline-offset:3px}
.ai-fab-dot{
  width:8px;height:8px;border-radius:50%;background:var(--pine);flex:0 0 8px;
}

@media (max-width:560px){
  .ai-fab{padding:11px 14px}
}

/* The label that goes on every reply. Not decoration — a visitor has
   to be able to tell they are not talking to a person. */
.ai-label{
  font-size:.8rem;color:var(--muted);margin:0 0 1rem;
  border-left:3px solid var(--line);padding-left:10px;
}
.ai-reply{
  background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);padding:18px 20px;margin:1.2rem 0;
}
.ai-reply p:first-child{margin-top:0;font-size:1.02rem;line-height:1.6}
.ai-reply .ai-label{margin:1rem 0 0;border-left:0;padding-left:0}
.ai-form{max-width:44rem;margin-top:1.4rem}

/* The currency beside a footer corridor link. Quieter than the country
   because the country is what a customer is looking for; the code is
   what tells two corridors to the same country apart. */
.foot-ccy{
  font-family:var(--mono);font-size:.76em;
  color:rgba(255,255,255,.55);margin-inline-start:2px;
}

/* ===================================================================
   ANNOUNCEMENT BANNER

   The licensee's own short notice, above the header on every page and
   every template. Drawn entirely from the theme tokens — there is no
   colour in this block that is not one of theirs, so it carries their
   brand rather than a house style laid over it.

   In normal flow. It pushes the header down by its own height and
   overlaps nothing; the sandbox notice above and the header below are
   untouched by it.
   =================================================================== */
.ann-bar{
  background:var(--pine-tint);
  border-bottom:1px solid color-mix(in srgb, var(--pine) 22%, transparent);
  color:var(--ink);
  font-size:.9rem;
}
.ann-in{
  display:flex; align-items:center; gap:12px;
  padding-top:9px; padding-bottom:9px;
}
.ann-text{ margin:0; min-width:0; flex:1 1 auto; line-height:1.45; }
.ann-head{ font-weight:650; }
/* The subtext runs on after the headline where there is room and drops
   to its own line where there is not, which is what keeps a two-part
   notice to two lines on a phone. */
.ann-sub{ color:var(--muted); }
.ann-sub::before{ content:" — "; color:var(--muted); }
.ann-link{
  flex:0 0 auto;
  color:var(--pine-dark);
  font-weight:600;
  text-decoration:none;
  white-space:nowrap;
}
.ann-link:hover{ text-decoration:underline; text-underline-offset:3px; }
.ann-x{
  flex:0 0 auto;
  display:grid; place-items:center;
  width:26px; height:26px;
  padding:0;
  border:0; border-radius:50%;
  background:transparent;
  color:var(--muted);
  cursor:pointer;
}
.ann-x:hover{ background:color-mix(in srgb, var(--pine) 14%, transparent); color:var(--ink); }
.ann-x:focus-visible{ outline:2px solid var(--pine); outline-offset:2px; }
/* Shown only where a script can act on it: without JavaScript there is
   nothing to remember a dismissal, and a button that does nothing is
   worse than no button. */
.js .ann-x{ display:grid; }
.js .ann-x[hidden]{ display:none; }
/* Hidden before first paint when this tab has already dismissed it. */
.ann-hidden .ann-bar{ display:none; }

@media (max-width: 620px){
  /* The row wraps rather than squeezing: text and the dismiss button
     on the first line, the link on its own beneath. An earlier version
     hid the link at this width, which took it away from exactly the
     visitors most likely to be reading on one. */
  .ann-in{ flex-wrap:wrap; align-items:flex-start; gap:6px 10px; }
  .ann-text{ font-size:.86rem; flex:1 1 70%; }
  .ann-x{ order:2; margin-left:auto; }
  .ann-link{ order:3; flex:1 1 100%; white-space:normal; }
  /* The subtext takes its own line so a two-part notice stays two
     lines rather than four. */
  .ann-sub{ display:block; }
  .ann-sub::before{ content:none; }
}

/* =====================================================================
   THE API REFERENCE                                        /docs.php

   .prose already carries the typography, because a rendered document is
   a rendered document whether a licensee wrote it in the CMS or it came
   out of docs/api.md. Only three things are genuinely different here and
   each earns its rule.

   Code blocks. The sanitiser's allowlist has no <pre> and no <code>, so
   a tenant-authored /p/ page cannot contain either and these selectors
   can only ever reach this page. Nothing below changes an existing one.
   ===================================================================== */

/* A reference is read against code samples, not as an essay: 68ch is
   the right measure for prose and too narrow for an HTTP exchange. */
.prose-doc{max-width:82ch}

/* The document supplies its own h1; .prose only styled h2 down. */
.prose h1{
  font-size:clamp(1.9rem,4vw,2.5rem);margin:0 0 .6rem;color:var(--ink);
  letter-spacing:-.02em;text-wrap:balance
}

/* Anchors land under the sticky header without this: .topbar is
   position:sticky at 66px, so #authentication would scroll its own
   heading out of sight. The contents list at the top of the document is
   made of those links, so this is the difference between a working
   table of contents and one that appears to do nothing. */
.prose h1[id],.prose h2[id],.prose h3[id],.prose h4[id]{scroll-margin-top:84px}

.prose pre{
  background:var(--ink);color:#E8EFED;
  border-radius:var(--radius-sm);padding:14px 16px;margin:1.1rem 0;
  font-size:.86rem;line-height:1.6;
  /* Samples are copied and pasted. A wrapped one is a broken one, so
     it scrolls instead. */
  overflow-x:auto;-webkit-overflow-scrolling:touch;white-space:pre
}
.prose pre code{
  background:none;color:inherit;border:0;padding:0;
  font-family:var(--mono);white-space:pre
}
/* Inline code, on the light background of the page rather than the
   dark of a block. */
.prose code{
  font-family:var(--mono);font-size:.88em;
  background:#EDF2F0;border:1px solid var(--line);border-radius:5px;
  padding:.08em .35em;color:var(--ink)
}
.prose a code{color:inherit}

.doc-meta{margin-bottom:1.6rem}
.doc-updated{font-size:var(--fs-small);color:var(--muted);margin:0}

@media (max-width:640px){
  /* The dark block runs to the edge of the reading column: 16px of
     padding either side of a code sample is 32px the sample does not
     get, on the screens with least of it. */
  .prose-doc pre{margin-inline:-16px;border-radius:0;padding-inline:16px}
}
