/* ============================================================================
   PlatinumEdge Admin - design v2 (approved "PE Panels v1")
   One accent: the blue to cyan brand gradient. Status colours only ever mean a
   status. Light theme only - no OS dark hook anywhere in this file.
   ============================================================================ */
@font-face{font-family:'Hanken Grotesk';font-weight:400;font-style:normal;font-display:swap;src:url('/public/fonts/HankenGrotesk-400.woff2') format('woff2')}
@font-face{font-family:'Hanken Grotesk';font-weight:500;font-style:normal;font-display:swap;src:url('/public/fonts/HankenGrotesk-500.woff2') format('woff2')}
@font-face{font-family:'Hanken Grotesk';font-weight:600;font-style:normal;font-display:swap;src:url('/public/fonts/HankenGrotesk-600.woff2') format('woff2')}
@font-face{font-family:'Hanken Grotesk';font-weight:700;font-style:normal;font-display:swap;src:url('/public/fonts/HankenGrotesk-700.woff2') format('woff2')}
@font-face{font-family:'Space Grotesk';font-weight:400;font-style:normal;font-display:swap;src:url('/public/fonts/SpaceGrotesk-400.woff2') format('woff2')}
@font-face{font-family:'Space Grotesk';font-weight:500;font-style:normal;font-display:swap;src:url('/public/fonts/SpaceGrotesk-500.woff2') format('woff2')}
@font-face{font-family:'Space Grotesk';font-weight:700;font-style:normal;font-display:swap;src:url('/public/fonts/SpaceGrotesk-700.woff2') format('woff2')}

:root{
  color-scheme:light;

  /* surfaces */
  --bg:#EEF1F8;            /* page background (canvas) */
  --bg-2:#FFFFFF;          /* card / panel background */
  --panel:#FFFFFF;
  --panel-2:#F5F7FC;       /* alt panel / table head */
  --panel-3:#E9EDF6;       /* hover / muted highlight (sunken) */
  --panel-4:#DFE5F1;       /* slightly deeper highlight */

  /* text */
  --ink:#0C1322;           /* primary heading + body */
  --ink-2:#222D42;         /* body emphasis */
  --t2:#48536A;            /* secondary */
  --t3:#606B84;            /* tertiary */
  --t4:#8A93A8;            /* placeholder / subtle */

  /* lines */
  --line:#E2E6EF;          /* borders */
  --line-2:#D2D8E4;        /* stronger border */
  --line-soft:#EEF1F7;     /* dividers */

  /* accents - the ONE brand accent, blue to cyan */
  --blue:#2E7CFF;
  --blue-ink:#0E56E6;
  --cyan:#19E3D0;
  --cyan-ink:#0B8F83;
  --teal:#0E56E6;          /* primary action (brand blue ink) */
  --teal-bright:#2E7CFF;
  --teal-soft:#D9E7FF;
  --teal-50:#F1F5FF;
  --gold:#0B8F83;          /* secondary accent (cyan ink) */
  --gold-bright:#19E3D0;
  --gold-soft:#DCF8F4;
  --amber:#A8690F;
  --amber-soft:#FCF1DC;
  --red:#C8463B;
  --red-soft:#FBE7E5;
  --green:#0E9C6F;
  --green-soft:#E4F7EE;
  --indigo:#0E56E6;
  --indigo-soft:#E8F0FF;
  --violet:#3D5BD6;
  --violet-soft:#E9EDFD;

  /* gradients */
  --grad:linear-gradient(118deg,#2E7CFF 0%,#19E3D0 100%);
  --grad-gold:linear-gradient(118deg,#2E7CFF 0%,#19E3D0 100%);
  --grad-soft:linear-gradient(180deg,rgba(46,124,255,.10),rgba(25,227,208,.03));
  --grad-page:radial-gradient(circle at 0% 0%, rgba(46,124,255,.05), transparent 50%),
              radial-gradient(circle at 100% 100%, rgba(25,227,208,.04), transparent 50%);

  /* type */
  --f:"Hanken Grotesk",system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
  --fm:"Space Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --fd:"Space Grotesk",system-ui,sans-serif;

  /* shape */
  --r:14px;
  --r-lg:18px;
  --r-sm:9px;
  --pill:999px;

  /* shadow */
  --sh-sm:0 1px 2px rgba(12,19,34,.04);
  --sh-md:0 1px 2px rgba(12,19,34,.04),0 8px 24px -14px rgba(18,32,78,.22);
  --sh-lg:0 10px 25px -8px rgba(12,19,34,.10), 0 4px 10px -4px rgba(12,19,34,.06);
  --sh-xl:0 25px 50px -15px rgba(12,19,34,.18);
  --sh-pop:0 0 0 4px rgba(46,124,255,.14);

  /* layout */
  --side-w:240px;
  --top-h:64px;

  /* motion */
  --ease:cubic-bezier(.16,1,.3,1);

  /* ---- aliases -------------------------------------------------------------
     Names used by views and older rules. Defined here so every reference
     resolves to a real value: a var() pointing at nothing renders invisible
     and passes every other check. */
  --card:#FFFFFF;
  --bg2:#F5F7FC;
  --bd:#E2E6EF;
  --t1:#0C1322;
  --ink2:#48536A;
  --muted:#606B84;
  --brand:#0E56E6;
  --pri:#0E56E6;
  --accent:linear-gradient(118deg,#2E7CFF 0%,#19E3D0 100%);
  --teal-ink:#0E56E6;
  --green-ink:#0A7A56;
  --good:#0E9C6F;
  --ok:#0E9C6F;
  --bad:#C8463B;
  --warn:#A8690F;
  --amber-50:#FCF1DC;
  --red-bg:#FBE7E5;
}
*,*::before,*::after{box-sizing:border-box;margin:0}
html,body{height:100%}
body{
  font-family:var(--f);
  background:var(--bg) var(--grad-page);
  color:var(--ink);
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
a{color:inherit;text-decoration:none}
button{font:inherit;cursor:pointer;background:none;border:none;color:inherit}
input,textarea,select{font:inherit;color:inherit}
.mono{font-family:var(--fm);letter-spacing:.01em}
.caps{font-family:var(--fm);font-size:11px;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--t3)}
::selection{background:rgba(46,124,255,.20);color:var(--ink)}

/* ================================================================== LOGIN */
.login-wrap{
  min-height:100dvh;display:grid;place-items:center;padding:20px;
  background:
    radial-gradient(circle at 25% 25%,rgba(46,124,255,.10),transparent 50%),
    radial-gradient(circle at 75% 75%,rgba(25,227,208,.07),transparent 50%),
    var(--bg);
}
.login{
  width:min(420px,100%);background:var(--bg-2);border:1px solid var(--line);
  border-radius:18px;padding:32px;box-shadow:var(--sh-xl);
}
.login .mark{display:flex;align-items:center;gap:.6rem;margin-bottom:1.4rem}
.login .mark svg{width:30px;height:30px}
.login .mark b{font-family:var(--fd);font-weight:700;font-size:1.04rem;letter-spacing:-.01em}
.login .mark .ad{
  font-family:var(--fd);font-weight:500;font-size:.6rem;letter-spacing:.24em;color:var(--t3);
  text-transform:uppercase;margin-top:3px;display:block;line-height:1;
}
.login h1{font-family:var(--fd);font-weight:700;font-size:1.6rem;letter-spacing:-.02em;margin:.4rem 0 1.6rem;color:var(--ink)}

/* ============================================================== FORM FIELDS */
.field{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1.2rem}
.field label{
  font-family:var(--fm);font-size:11px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--t3);font-weight:600;
}
.field input,.field textarea,.field select{
  background:var(--bg-2);border:1px solid var(--line-2);border-radius:10px;
  padding:.78rem 1rem;color:var(--ink);min-height:46px;width:100%;
  transition:border-color .15s,box-shadow .15s,background .15s;
}
.field input::placeholder,.field textarea::placeholder{color:var(--t4)}
.field input:hover,.field textarea:hover,.field select:hover{border-color:var(--t3)}
.field input:focus,.field textarea:focus,.field select:focus{
  outline:none;border-color:var(--teal);box-shadow:var(--sh-pop);background:#fff;
}
.field input:read-only{background:var(--panel-2);color:var(--t2);cursor:not-allowed}
.field textarea{min-height:100px;resize:vertical;line-height:1.5}

/* ===================================================================== BTN */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.5em;
  font-weight:600;font-size:.92rem;padding:.7em 1.3em;border-radius:var(--pill);
  border:1px solid transparent;white-space:nowrap;
  transition:transform .15s var(--ease),background .15s,box-shadow .2s,border-color .15s,color .15s;
}
.btn-primary{background:var(--teal);color:#fff;box-shadow:0 4px 14px -4px rgba(46,124,255,.4)}
.btn-primary:hover{background:var(--teal);transform:translateY(-1px);box-shadow:0 8px 18px -6px rgba(46,124,255,.5)}
.btn-primary:active{transform:translateY(0)}
.btn-primary:disabled{opacity:.55;cursor:not-allowed;transform:none;box-shadow:none}
.btn-ghost{background:transparent;border-color:var(--line-2);color:var(--ink-2)}
.btn-ghost:hover{background:var(--panel-3);border-color:var(--t4)}
.btn-danger{background:#fff;border-color:var(--red);color:var(--red)}
.btn-danger:hover{background:var(--red-soft)}
.btn-block{width:100%}
.err{color:var(--red);font-size:.88rem;margin-top:.6rem;text-align:center;min-height:1.2em}

/* =============================================================== APP SHELL */
.app{
  /* minmax(0,1fr), not 1fr: a 1fr track's minimum is its content, so one wide table
     (Merchants, Gateway routing rules) pushed .main past the window and the whole
     desktop page scrolled sideways, taking Sign out off-screen. Fixed for every width,
     not only phones. */
  display:grid;grid-template-columns:var(--side-w) minmax(0,1fr);
  grid-template-rows:var(--top-h) 1fr;
  grid-template-areas:"side top" "side main";
  min-height:100vh;
}
.app > .main,.app > header.top{min-width:0}
.side{
  grid-area:side;background:var(--bg-2);border-right:1px solid var(--line);
  padding:22px 14px;display:flex;flex-direction:column;gap:4px;
  position:sticky;top:0;height:100vh;overflow-y:auto;
}
.side .brand{display:flex;align-items:center;gap:.6rem;padding:6px 10px;margin-bottom:22px}
.side .brand svg{width:28px;height:28px;flex:none}
.side .brand b{font-family:var(--fd);font-weight:700;font-size:1.05rem;letter-spacing:-.01em;line-height:1.1;color:var(--ink)}
.side .brand .sub{
  font-family:var(--fm);font-size:.54rem;letter-spacing:.26em;color:var(--gold);
  text-transform:uppercase;display:block;line-height:1;margin-top:2px;
}
.nav-section{
  font-family:var(--fm);font-size:.6rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--t4);padding:14px 10px 6px;font-weight:600;
}
.nav-item{
  display:flex;align-items:center;gap:.7rem;padding:.6rem .8rem;border-radius:10px;
  font-size:.93rem;font-weight:500;color:var(--t2);transition:.15s;position:relative;
}
.nav-item svg{width:18px;height:18px;flex:none;opacity:.85;stroke-width:1.8}
.nav-item:hover{background:var(--panel-3);color:var(--ink)}
.nav-item.active{background:var(--teal-50);color:var(--teal);font-weight:600}
.nav-item.active svg{opacity:1}
.nav-item.active::before{
  content:"";position:absolute;left:-14px;top:8px;bottom:8px;width:3px;
  border-radius:0 3px 3px 0;background:var(--teal);
}
.nav-item .badge{
  margin-left:auto;font-family:var(--fm);font-size:.66rem;font-weight:700;
  background:var(--teal);color:#fff;border-radius:999px;padding:.2em .55em;
  min-width:1.4em;text-align:center;
}
.side .pull-bottom{margin-top:auto;padding-top:14px;border-top:1px solid var(--line-soft)}

.top{
  grid-area:top;background:var(--bg-2);border-bottom:1px solid var(--line);
  padding:0 28px;display:flex;align-items:center;gap:14px;position:sticky;top:0;z-index:20;
}
.top h1{font-family:var(--fd);font-weight:700;font-size:1.2rem;letter-spacing:-.01em;color:var(--ink);flex:1}
.top .spacer{flex:1}
.top .who{font-family:var(--fm);font-size:.72rem;color:var(--t3);letter-spacing:.04em}
.top .logout{
  font-family:var(--fm);font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;
  color:var(--t2);border:1px solid var(--line-2);border-radius:var(--pill);padding:.5em 1em;
  transition:.15s;
}
.top .logout:hover{color:var(--ink);border-color:var(--ink);background:var(--panel-3)}
.burger{display:none;width:38px;height:38px;border-radius:9px;border:1px solid var(--line-2);align-items:center;justify-content:center;background:#fff}
.burger span,.burger span::before,.burger span::after{content:"";display:block;width:16px;height:1.8px;background:var(--ink);border-radius:2px;position:relative}
.burger span::before{position:absolute;top:-5px}
.burger span::after{position:absolute;top:5px}

.main{grid-area:main;padding:28px}
/* Width alone is not enough to detect a phone.

   Igor's screenshot: Chrome on Android with "Desktop site" requested. The
   layout viewport reports 1350 CSS px, so every max-width query missed and the
   full desktop shell rendered on a handset - 240px sidebar, header search, and
   eight table columns squeezed into a palm.

   `pointer:coarse` and `hover:none` stay true in desktop-site mode, because
   they describe the INPUT DEVICE rather than the viewport. Pairing them with a
   generous width catches the phone without touching a real desktop, and a
   touch laptop at 1400px+ is unaffected. */
@media(max-width:880px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  .app{grid-template-columns:minmax(0,1fr);grid-template-areas:"top" "main"}
  /* A grid item's default min-width is auto, not 0, so any child wider than
     the track pushes the TRACK wider. That is why .app measured 390px while
     .main measured 520px and the whole document scrolled sideways on a phone.
     minmax(0,1fr) on the track plus min-width:0 on the items lets content
     shrink instead of the layout growing. Diagnosed on the dashboard earlier
     and left unfixed - same defect, now fixed at the source for every view. */
  .app > .main,.app > header.top{min-width:0;max-width:100%}
  /* The header packs six items onto one flex row. On a phone the command
     palette trigger and the operator name have no room, and they pushed the
     Sign out button to 434px - past the 390px viewport. The palette is still
     reachable via the search on each page; the identity label is not
     information an operator needs while scrolling a list. */
  .top{flex-wrap:nowrap;min-width:0;gap:6px}
  /* The title had no room because .spacer still claimed flex space. Give the
     title the flex instead so "Transactions" fits rather than truncating to
     "Transacti...". */
  .top #viewTitle{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:1.05rem}
  .top .spacer{display:none}
  .top .top-search,.top .who{display:none}
  .top .logout{flex:0 0 auto;white-space:nowrap}
  .side{
    position:fixed;top:0;left:0;height:100vh;width:var(--side-w);z-index:60;
    transform:translateX(-100%);transition:transform .3s var(--ease);box-shadow:var(--sh-lg);
  }
  body.nav-open .side{transform:none}
  .scrim{position:fixed;inset:0;background:rgba(15,23,42,.4);opacity:0;visibility:hidden;transition:.25s;z-index:55}
  body.nav-open .scrim{opacity:1;visibility:visible}
  .burger{display:flex}
  .main{padding:18px 16px 60px}
}

/* =========================================================== SHARED LAYOUT */
.view{display:none}
.view.on{display:block;animation:fadeIn .3s var(--ease)}
@keyframes fadeIn{from{opacity:0;transform:translateY(6px)} to{opacity:1;transform:none}}

.section-head{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-bottom:22px;flex-wrap:wrap}
.section-head h2{font-family:var(--fd);font-weight:700;font-size:1.65rem;letter-spacing:-.025em;margin-bottom:.3rem;color:var(--ink)}
.section-head .lead{color:var(--t2);font-size:.96rem;max-width:62ch}

.kpis{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;margin-bottom:24px}
@media(min-width:760px){.kpis{grid-template-columns:repeat(4,1fr)}}
.kpi{
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r);padding:20px;
  position:relative;overflow:hidden;box-shadow:var(--sh-sm);transition:.2s var(--ease);
}
.kpi:hover{box-shadow:var(--sh-md);transform:translateY(-1px)}
.kpi .l{
  font-family:var(--fm);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--t3);display:flex;align-items:center;gap:.5em;font-weight:600;
}
.kpi .l .dot{width:6px;height:6px;border-radius:50%;background:var(--teal)}
.kpi .v{font-family:var(--fd);font-weight:800;font-size:2rem;letter-spacing:-.03em;margin-top:8px;line-height:1;color:var(--ink)}
.kpi .sub{margin-top:8px;font-size:.8rem;color:var(--t2);display:flex;align-items:center;gap:.4em}
.kpi .sub .up{color:var(--green);font-weight:700;font-family:var(--fm);font-size:.74rem}
.kpi.gold{background:linear-gradient(180deg,var(--gold-soft),#fff);border-color:var(--gold-soft)}
.kpi.gold .v{background:var(--grad-gold);-webkit-background-clip:text;background-clip:text;color:transparent}
.kpi.teal{background:linear-gradient(180deg,var(--teal-50),#fff);border-color:var(--teal-soft)}
.kpi.teal .v{color:var(--teal)}
.kpi.teal .l .dot{background:var(--teal)}

.panel{
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r);
  padding:22px;margin-bottom:18px;box-shadow:var(--sh-sm);
}
.panel .head{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;gap:1rem}
.panel .head h3{font-family:var(--fd);font-weight:700;font-size:1.05rem;color:var(--ink)}
.panel .head .actions{display:flex;gap:.5rem}

.grid-2{display:grid;grid-template-columns:1fr;gap:18px}
@media(min-width:980px){.grid-2{grid-template-columns:1.4fr 1fr}}

.empty{padding:54px 24px;text-align:center;color:var(--t3);font-size:.92rem}
.loading{padding:36px;text-align:center;color:var(--t3);font-family:var(--fm);font-size:.78rem;letter-spacing:.08em;text-transform:uppercase}

/* ================================================================ TOOLBAR */
.toolbar{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px;
  padding:12px;background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--sh-sm);
}
.search{
  flex:1;min-width:220px;display:flex;align-items:center;gap:.5em;
  background:var(--panel-2);border:1px solid var(--line);border-radius:10px;padding:.55em .9em;
  transition:.15s;
}
.search:focus-within{border-color:var(--teal);box-shadow:var(--sh-pop);background:#fff}
.search svg{width:15px;height:15px;color:var(--t4);flex:none}
.search input{background:none;border:0;flex:1;outline:none;min-height:30px;color:var(--ink)}
.search input::placeholder{color:var(--t4)}
.chip{
  display:inline-flex;align-items:center;gap:.4em;
  font-family:var(--f);font-size:.83rem;font-weight:500;letter-spacing:0;text-transform:none;
  padding:.5em 1em;border-radius:var(--pill);border:1px solid var(--line-2);
  color:var(--t2);cursor:pointer;transition:.12s;background:#fff;
}
.chip:hover{border-color:var(--t3);color:var(--ink);background:var(--panel-3)}
.chip.on{background:var(--teal);border-color:var(--teal);color:#fff;font-weight:600}
.chip .n{margin-left:.5em;opacity:.7;font-family:var(--fm);font-size:.74em;font-weight:600}
.chip.on .n{opacity:.9}

/* ================================================================== TABLES */
.tbl{
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;box-shadow:var(--sh-sm);
}
.thead,.trow{display:grid;gap:12px;align-items:center;padding:14px 20px}
.thead{
  background:var(--panel-2);font-family:var(--fm);font-size:10px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--t3);border-bottom:1px solid var(--line);font-weight:600;
}
.trow{border-bottom:1px solid var(--line-soft);cursor:pointer;transition:background .12s;font-size:.93rem}
.trow:hover{background:var(--panel-3)}
.trow:last-child{border-bottom:0}
.t-leads .thead,.t-leads .trow{grid-template-columns:60px 1.3fr 1.3fr .8fr 1fr 120px 100px}
.t-orders .thead,.t-orders .trow{grid-template-columns:124px 104px 1.25fr 1.15fr .85fr 128px 116px 150px}
/* Amount leads and is right-aligned with tabular figures: it is the column an
   operator scans, and left-aligned mixed-currency amounts do not line up on the
   decimal. Reference moved last - the PSP research was explicit that an opaque
   identifier should not occupy the most prominent slot. */
.t-orders .t-amt{text-align:right;font-variant-numeric:tabular-nums;font-weight:750;color:var(--ink);letter-spacing:-.01em}
.t-orders .t-amt-neg{color:var(--red)}
.t-orders .t-ref{font-family:var(--fm,ui-monospace,monospace);font-size:.74rem;color:var(--t3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.t-orders .t-rail{display:block;font-size:.66rem;color:var(--t4);text-transform:uppercase;letter-spacing:.04em;margin-top:1px}
.t-orders .trow{cursor:pointer}
.t-orders .trow:focus-visible{outline:2px solid var(--teal);outline-offset:-2px;border-radius:6px}
.test-tag{font-size:.6rem;font-weight:800;letter-spacing:.05em;color:var(--amber);background:rgba(180,83,9,.1);border:1px solid rgba(180,83,9,.25);border-radius:4px;padding:1px 4px;margin-left:4px;vertical-align:middle}

/* ---- Transactions filter bar ----------------------------------------------
   Ten controls sat on one flex line and wrapped into SEVEN ragged rows at
   1440px, each at a different vertical offset because the elements had
   different heights. Now: one primary row that is always visible (search,
   quick ranges, Filters, Export), and a labelled grid that collapses. */
.tx-filters{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:12px;margin-top:14px}
.txf-row{display:flex;gap:10px;align-items:center}
.txf-primary{flex-wrap:wrap}
.txf-search{flex:1 1 260px;min-width:0}
.txf-quick{flex:0 0 auto}
.txf-more,.txf-export{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.txf-more.has-filters{border-color:rgba(46,124,255,.45);color:var(--teal-ink)}
.txf-count{display:inline-flex;align-items:center;justify-content:center;min-width:17px;height:17px;padding:0 5px;
  border-radius:9px;background:var(--teal);color:#fff;font-size:.64rem;font-weight:800}

/* Advanced panel: a real grid, so every control aligns on a baseline and each
   one says what it filters. Unlabelled date inputs were unreadable. */
.txf-advanced{display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));gap:12px;
  margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
.txf-advanced[hidden]{display:none}
.txf-group{display:flex;flex-direction:column;gap:5px;min-width:0}
.txf-legend{font-size:.64rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--t4)}
.txf-group select,.txf-group input:not([type=checkbox]){width:100%;background:var(--bg,#fff);border:1px solid var(--line);border-radius:8px;
  padding:8px 9px;font-size:.82rem;color:var(--ink);min-height:38px}
/* The toggle is a control, not a field: excluded above so it is not stretched
   to the full grid cell the way the selects are. */
.txf-group-check{justify-content:center}
.txf-group-check .db-toggle{display:inline-flex;align-items:center;gap:8px}
.txf-group-check input[type=checkbox]{width:17px;height:17px;flex:0 0 auto}
.txf-pair{display:flex;align-items:center;gap:6px}
.txf-pair input{min-width:0}
.txf-sep{font-size:.72rem;color:var(--t4);flex:0 0 auto}
.txf-group-check{justify-content:flex-end}

/* ---- Multi-select payment routes and MIDs --------------------------------
   One route at a time could not answer "how much on these three acquirers":
   it meant running the page three times and adding up by hand. The control is
   a button that reports the picks and a panel of checkboxes, routes with
   their MIDs nested underneath. */
.rpick{position:relative}
/* The filter card has to WIN the stacking order while the panel is open. Each
   direct child of a view carries an entrance animation with fill-mode `both`
   (pe-rise), and a filled animation leaves the element with its own stacking
   context - so the summary card, a LATER sibling, painted straight over the
   open panel and buried the MID checkboxes. Raised only while open, and kept
   below the sticky topbar (z-index 20) so a scroll cannot push it over the
   header. */
.tx-filters{position:relative}
.tx-filters.rpick-open{z-index:15}
.rpick-btn{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;
  background:var(--bg,#fff);border:1px solid var(--line);border-radius:8px;padding:8px 9px;
  font:inherit;font-size:.82rem;color:var(--ink);min-height:38px;cursor:pointer;text-align:left}
.rpick-btn:hover{border-color:var(--teal)}
.rpick-btn:focus-visible{outline:2px solid var(--teal);outline-offset:1px}
.rpick-btn.on{border-color:rgba(46,124,255,.45);color:var(--teal-ink);font-weight:650}
.rpick-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rpick-caret{flex:0 0 auto;color:var(--t4);font-size:.7rem}
.rpick-panel{position:absolute;z-index:40;top:calc(100% + 6px);left:0;width:320px;max-width:min(320px,92vw);
  background:var(--card,#fff);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 10px 30px rgba(14,26,51,.16);display:flex;flex-direction:column;overflow:hidden}
.rpick-panel[hidden]{display:none}
.rpick-head{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--line)}
.rpick-title{flex:1 1 auto;font-size:.64rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--t4)}
.rpick-list{max-height:44vh;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:4px 0}
.rpick-grp{padding:2px 0}
.rpick-grp + .rpick-grp{border-top:1px solid var(--line-soft)}
.rpick-opt{display:flex;align-items:center;gap:9px;padding:8px 12px;min-height:40px;cursor:pointer}
.rpick-opt:hover{background:var(--line-soft)}
.rpick-opt input[type=checkbox]{width:17px;height:17px;flex:0 0 auto;cursor:pointer}
.rpick-nm{flex:1 1 auto;min-width:0;font-size:.82rem;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rpick-n{flex:0 0 auto;font-size:.66rem;font-weight:700;letter-spacing:.03em;color:var(--t4);font-variant-numeric:tabular-nums}
.rpick-opt-rail .rpick-nm{font-weight:700}
.rpick-opt-mid{padding-left:30px}
.rpick-opt-mid .rpick-nm{color:var(--t2);font-size:.78rem}
.rpick-empty{padding:14px 12px;font-size:.8rem;color:var(--t3)}
.rpick-foot{display:flex;align-items:center;gap:8px;padding:10px 12px;border-top:1px solid var(--line);background:var(--bg-2)}
.rpick-foot .btn-primary{flex:1 1 auto;justify-content:center}

/* Status tone drives the badge colour from meaning, not from the raw DB word,
   so a new status cannot arrive with an accidental green. */
.stbadge.tone-ok{color:var(--green-ink);background:var(--green-soft);border-color:rgba(47,191,113,.3)}
.stbadge.tone-bad{color:#B42318;background:rgba(180,35,24,.09);border-color:rgba(180,35,24,.26)}
.stbadge.tone-warn{color:var(--amber);background:rgba(180,83,9,.1);border-color:rgba(180,83,9,.26)}
.stbadge.tone-muted{color:var(--t3);background:var(--line-soft);border-color:var(--line)}
.stbadge.tone-neutral{color:var(--t2);background:var(--line-soft);border-color:var(--line)}

/* Active filters must look active - a filtered view that resembles an
   unfiltered one produces wrong conclusions. */
.active-filters{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 0}
.active-filters:empty{display:none}
.fpill{display:inline-flex;align-items:center;gap:6px;font-size:.72rem;font-weight:650;color:var(--teal-ink);background:var(--teal-soft);border:1px solid rgba(46,124,255,.28);border-radius:20px;padding:4px 10px;cursor:pointer;min-height:28px}
.fpill:hover{background:rgba(46,124,255,.16)}
.fpill-x{font-size:.85rem;line-height:1;opacity:.65}
.fpill-all{color:var(--t3);background:transparent;border-style:dashed;border-color:var(--line)}
.chip-empty{opacity:.45}

/* Selection summary. Three zones on one card: the money kept, how it was
   reached, and how well the selection converted. Currencies are never summed;
   the primary is whichever holds the most approved money and the rest sit as
   chips, so a 7.9M figure and a 1,932 figure are not given equal weight. */
.orders-summary{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);gap:18px 26px;
  align-items:start;margin:12px 0 2px;padding:16px 18px;background:var(--card);
  border:1px solid var(--line);border-radius:12px}
.orders-summary:empty{display:none}
.osum-main{min-width:0}
.osum-head{font-size:.66rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--t4);
  display:flex;flex-wrap:wrap;align-items:baseline;gap:7px}
.osum-scope{font-weight:650;letter-spacing:.01em;text-transform:none;font-size:.72rem;color:var(--t3)}
.osum-big{font-family:var(--fd);font-weight:800;font-size:2rem;line-height:1.12;color:var(--ink);
  font-variant-numeric:tabular-nums;letter-spacing:-.02em;margin-top:4px}
.osum-calc{margin-top:5px;font-size:.76rem;color:var(--t3);font-variant-numeric:tabular-nums}
.osum-minus{color:var(--t4);padding:0 2px}

.osum-rate{min-width:0;align-self:center}
.osum-rate-top{font-size:.82rem;color:var(--t2)}
.osum-rate-top b{font-family:var(--fd);font-size:1.15rem;color:var(--ink);font-variant-numeric:tabular-nums}
.osum-bar{height:7px;border-radius:5px;background:var(--line-soft);overflow:hidden;margin:7px 0 5px}
.osum-bar span{display:block;height:100%;border-radius:5px;transition:width .35s var(--ease,ease)}
.osum-bar .tone-ok{background:var(--green)}
.osum-bar .tone-warn{background:#E0A03A}
.osum-bar .tone-bad{background:#D9614F}
.osum-rate-sub{font-size:.7rem;color:var(--t4);font-variant-numeric:tabular-nums}

.osum-others{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:8px;padding-top:12px;border-top:1px solid var(--line)}
.osum-chip{display:inline-flex;align-items:baseline;gap:7px;padding:5px 11px;border-radius:20px;
  background:var(--line-soft);border:1px solid var(--line)}
.osum-chip b{font-family:var(--fd);font-size:.86rem;color:var(--ink);font-variant-numeric:tabular-nums}
.osum-chip small{font-size:.66rem;font-weight:700;letter-spacing:.04em;color:var(--t4)}
.osum-chip-more{color:var(--t3);font-size:.72rem;font-weight:650;border-style:dashed}
/* Currency chips are filters: press to narrow the screen to one currency. Same
   feedback as the status chips - hover lifts, press sinks, the selected one fills blue. */
button.osum-chip{font:inherit;cursor:pointer;min-height:36px;
  transition:background-color .15s,border-color .15s,box-shadow .15s,transform .08s}
button.osum-chip:hover{border-color:var(--teal);background:#F1F5FF;box-shadow:0 1px 3px rgba(14,26,51,.10)}
button.osum-chip:active{transform:translateY(1px);box-shadow:none}
button.osum-chip:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
button.osum-chip.on{background:var(--teal);border-color:var(--teal)}
button.osum-chip.on b,button.osum-chip.on small{color:#fff}
.osum-chip-all{font-size:.76rem;font-weight:650;color:var(--t2)}

.orders-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 2px 0}
.orders-footer:empty{display:none}

/* ---- Per-pick totals -----------------------------------------------------
   The headline figure says how much the whole selection holds; this says how
   much each ticked route and MID holds, which is the question behind ticking
   them. Each currency keeps its own chip on every line and in the total:
   adding currencies together would invent an exchange rate. */
.orders-picktotals{margin:10px 0 2px;padding:14px 16px;background:var(--card);
  border:1px solid var(--line);border-radius:12px}
.orders-picktotals:empty{display:none}
.opick-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;font-size:.66rem;font-weight:800;
  letter-spacing:.06em;text-transform:uppercase;color:var(--t4);margin-bottom:10px}
.opick-note{font-weight:650;letter-spacing:.01em;text-transform:none;font-size:.72rem;color:var(--t3)}
.opick-tbl{display:flex;flex-direction:column}
.opick-thead,.opick-row{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1.5fr) 72px 82px 76px;
  gap:8px 12px;align-items:center;padding:8px 0}
.opick-thead{font-size:.62rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--t4);
  border-bottom:1px solid var(--line);padding-bottom:6px}
.opick-thead span:nth-child(n+3){text-align:right}
.opick-row{border-bottom:1px solid var(--line-soft)}
.opick-nm{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;min-width:0}
.opick-nm b{font-size:.86rem;color:var(--ink);overflow:hidden;text-overflow:ellipsis}
.opick-nm small{font-size:.68rem;color:var(--t3)}
.opick-kind{flex:0 0 auto;font-size:.58rem;font-weight:800;letter-spacing:.06em;color:var(--t4);
  background:var(--line-soft);border-radius:4px;padding:2px 5px}
.opick-money{display:flex;flex-wrap:wrap;gap:6px;min-width:0}
.opick-ccy{display:inline-flex;align-items:baseline;gap:5px;padding:3px 8px;border-radius:14px;
  background:var(--line-soft);border:1px solid var(--line)}
.opick-ccy b{font-family:var(--fd);font-size:.82rem;color:var(--ink);font-variant-numeric:tabular-nums}
.opick-ccy small{font-size:.62rem;font-weight:700;letter-spacing:.04em;color:var(--t4)}
.opick-none{font-size:.74rem;color:var(--t4)}
.opick-num{text-align:right;font-size:.82rem;color:var(--t2);font-variant-numeric:tabular-nums}
.opick-total{border-bottom:0;border-top:2px solid var(--line);margin-top:2px;padding-top:11px}
.opick-total .opick-nm b{font-weight:800}
.opick-total .opick-num{color:var(--ink);font-weight:700}
.opick-total .opick-ccy{background:var(--teal-soft);border-color:rgba(46,124,255,.28)}
.ofoot-count{font-size:.76rem;color:var(--t3)}
.ofoot-end{font-size:.72rem;color:var(--t4)}

/* ---- Mobile: transactions ------------------------------------------------
   At 390px the page scrolled to 520px and the row grid collapsed to two
   columns that dropped the AMOUNT entirely - the one field a payments page
   must never hide. Each row becomes a card, every cell labelled by the column
   it came from, amount and status on the top line. */
@media (max-width:900px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  .t-orders .thead{display:none}
  .t-orders .trow{display:grid;grid-template-columns:1fr auto;gap:6px 10px;padding:13px 14px;align-items:start}
  .t-orders .trow > span{min-width:0;display:flex;align-items:baseline;gap:8px;font-size:.82rem}
  .t-orders .trow > span::before{content:attr(data-label);flex:0 0 74px;font-size:.63rem;font-weight:800;
    letter-spacing:.05em;text-transform:uppercase;color:var(--t4)}
  /* Amount and status lead, side by side, with no label prefix - they are
     self-evident and they are what the eye needs first. */
  .t-orders .trow > .t-amt{grid-column:1;grid-row:1;font-size:1.06rem;font-weight:800}
  .t-orders .trow > .t-amt::before{content:none}
  .t-orders .trow > span[data-label="Status"]{grid-column:2;grid-row:1;justify-content:flex-end}
  .t-orders .trow > span[data-label="Status"]::before{content:none}
  .t-orders .trow > .t-nm{grid-column:1/-1}
  .t-orders .trow > .t-it,.t-orders .trow > .t-brand,.t-orders .trow > .t-method,
  .t-orders .trow > .t-dt,.t-orders .trow > .t-ref{grid-column:1/-1}
  .t-orders .trow .t-nm small{display:block;font-size:.72rem;color:var(--t3)}
  .t-orders .t-ref{font-size:.7rem}
  .t-orders .t-rail{display:inline;margin-left:6px}

  .tx-filters{padding:10px}
  .txf-primary{gap:8px}
  .txf-search{flex:1 1 100%}
  .txf-quick{flex:1 1 auto}
  .txf-quick button{flex:1}
  /* Filters and Export share one line rather than Export dropping alone. */
  .txf-more,.txf-export{flex:1 1 calc(50% - 4px);justify-content:center;min-height:40px}
  /* The checkbox was stretched to the full grid cell by align-items:stretch. */
  .txf-group-check{align-items:flex-start}
  .txf-group-check .db-toggle{display:flex;align-items:center;gap:8px;min-height:40px}
  .txf-group-check input[type=checkbox]{width:18px;height:18px;min-height:0;flex:0 0 auto}
  .txf-advanced{grid-template-columns:1fr;gap:10px}
  .orders-summary{grid-template-columns:minmax(0,1fr);gap:14px;padding:14px}
  .osum-big{font-size:1.6rem}
  .osum-rate{align-self:stretch}
  .osum-others{padding-top:10px}
  /* The picker becomes a full-width sheet under the button: a 320px panel
     anchored left overflowed a 390px phone, and 40px tap targets matter more
     than compactness on a screen used with a thumb. */
  .rpick-panel{position:static;width:auto;max-width:none;margin-top:6px;box-shadow:none}
  .rpick-list{max-height:52vh}
  .rpick-opt{min-height:46px;padding:10px 12px}
  .rpick-opt input[type=checkbox]{width:20px;height:20px}
  .rpick-opt-mid{padding-left:34px}
  .rpick-foot .btn-sm,.rpick-head .btn-sm{min-height:40px}
  /* Each pick becomes a card, every cell labelled: the five-column grid
     dropped to unreadable slivers at 390px. */
  .orders-picktotals{padding:12px}
  .opick-thead{display:none}
  .opick-row{grid-template-columns:1fr;gap:5px;padding:11px 0}
  .opick-row > span{display:flex;align-items:baseline;gap:8px;min-width:0}
  .opick-num::before,.opick-money::before{content:attr(data-label);flex:0 0 96px;font-size:.6rem;
    font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--t4)}
  /* Two currencies wrapped onto a second line and the second chip lost the
     label column, so it read as if it belonged to the row below. A grid keeps
     every chip in one column under the label. */
  .opick-row > .opick-money{display:grid;grid-template-columns:96px minmax(0,1fr);row-gap:5px;align-items:baseline;gap:5px 8px}
  .opick-row > .opick-money::before{grid-row:1}
  .opick-row > .opick-money > .opick-ccy,.opick-row > .opick-money > .opick-none{grid-column:2;justify-self:start}
  .opick-num{text-align:left}
  .opick-nm{padding-bottom:2px}
  .orders-footer{flex-direction:column;align-items:stretch;gap:8px}
  .orders-footer .btn-sm{width:100%;min-height:42px}
  /* Chips scroll horizontally instead of stacking into five rows. */
  #orderStatusChips{flex-wrap:nowrap;overflow-x:auto;padding-bottom:4px;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  #orderStatusChips::-webkit-scrollbar{display:none}
  #orderStatusChips .chip{flex:0 0 auto;min-height:34px}
}

@media (max-width:520px),(pointer:coarse) and (hover:none) and (max-width:820px){
  #v-orders .section-head h2{font-size:1.35rem}
  .t-orders .trow > span::before{flex-basis:66px}
}

.lnk{background:none;border:0;color:var(--teal);font-weight:650;cursor:pointer;text-decoration:underline}
.t-id{font-family:var(--fm);font-size:.74rem;color:var(--t3)}
.t-nm{font-weight:600;color:var(--ink)}
.t-nm small{display:block;font-weight:400;color:var(--t3);font-size:.78rem;margin-top:2px}
.t-em{font-family:var(--fm);font-size:.82rem;color:var(--t2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.t-co{color:var(--t2);font-size:.9rem}
.t-it{color:var(--t2);font-size:.84rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.t-dt{font-family:var(--fm);font-size:.72rem;color:var(--t3)}
.t-amt{font-family:var(--fm);font-weight:700;color:var(--ink)}
.t-ref{font-family:var(--fm);font-size:.72rem;color:var(--t2)}
.t-brand{font-size:.85rem;color:var(--ink)}
.t-brand .dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:6px;vertical-align:middle}

/* status badges with soft tinted backgrounds (light theme convention) */
.stbadge{
  display:inline-flex;align-items:center;gap:.4em;
  font-family:var(--f);font-size:.74rem;font-weight:600;letter-spacing:.01em;
  padding:.3em .7em;border-radius:var(--pill);border:1px solid transparent;
}
.stbadge .d{width:6px;height:6px;border-radius:50%}
/* new / in-flight / created - teal */
.stbadge.new,.stbadge.created,.stbadge.redirected,.stbadge.pending,.stbadge.preauth_ok{
  background:var(--teal-50);color:var(--teal);border-color:var(--teal-soft);
}
.stbadge.new .d,.stbadge.created .d,.stbadge.redirected .d,.stbadge.pending .d,.stbadge.preauth_ok .d{background:var(--teal)}
/* in_progress - amber */
.stbadge.in_progress{background:var(--amber-soft);color:var(--amber);border-color:#FDE68A}
.stbadge.in_progress .d{background:var(--amber)}
/* approved - green */
.stbadge.approved{background:var(--green-soft);color:var(--green);border-color:var(--teal-soft)}
.stbadge.approved .d{background:var(--green)}
/* closed / cancelled - gray */
.stbadge.closed,.stbadge.cancelled{background:var(--panel-3);color:var(--t2);border-color:var(--line-2)}
.stbadge.closed .d,.stbadge.cancelled .d{background:var(--t3)}
/* error / declined / spam - red */
.stbadge.spam,.stbadge.declined,.stbadge.error{background:var(--red-soft);color:var(--red);border-color:#FECACA}
.stbadge.spam .d,.stbadge.declined .d,.stbadge.error .d{background:var(--red)}

@media(max-width:920px){
  .t-leads .thead,.t-orders .thead{display:none}
  .t-leads .trow,.t-orders .trow{grid-template-columns:1fr auto;gap:6px;padding:14px}
  .t-id,.t-co,.t-it,.t-dt,.t-em,.t-amt,.t-brand{display:none}
  .t-nm,.t-ref{order:1}
  .stbadge{order:2;justify-self:end}
}

/* =================================================================== MODAL */
.modal-back{
  position:fixed;inset:0;background:rgba(15,23,42,.45);backdrop-filter:blur(4px);
  display:none;align-items:center;justify-content:center;padding:18px;z-index:90;
  animation:fadeIn .2s var(--ease);
}
.modal-back.on{display:flex}
.modal{
  background:var(--bg-2);border:1px solid var(--line);border-radius:18px;padding:28px;
  width:min(640px,100%);max-height:90vh;overflow:auto;box-shadow:var(--sh-xl);
  animation:popIn .25s var(--ease);
}
@keyframes popIn{from{opacity:0;transform:translateY(8px) scale(.98)} to{opacity:1;transform:none}}
.modal h2{font-family:var(--fd);font-weight:700;font-size:1.4rem;letter-spacing:-.02em;margin-bottom:.3rem;color:var(--ink)}
.modal .submeta{font-family:var(--fm);font-size:.74rem;color:var(--t3);margin-bottom:1.4rem}
.mrow{display:grid;grid-template-columns:auto 1fr;gap:.7em 1.4rem;font-size:.93rem;margin-bottom:1.4rem;padding-bottom:1.4rem;border-bottom:1px solid var(--line)}
.mrow b{color:var(--t3);font-family:var(--fm);font-size:.7rem;letter-spacing:.05em;text-transform:uppercase;font-weight:600;padding-top:2px}
.mrow span{color:var(--ink-2);word-break:break-word}
.mrow a{color:var(--teal);font-weight:500}
.mrow a:hover{text-decoration:underline}
.mrow .msg{
  grid-column:1/-1;color:var(--ink-2);background:var(--panel-2);border:1px solid var(--line);
  border-radius:10px;padding:14px;white-space:pre-wrap;font-size:.9rem;line-height:1.6;
}
.status-row{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1.2rem}
.notes{
  width:100%;min-height:90px;background:var(--panel-2);border:1px solid var(--line-2);
  border-radius:10px;padding:12px;color:var(--ink);resize:vertical;font:inherit;line-height:1.5;
  transition:.15s;
}
.notes:focus{outline:none;border-color:var(--teal);box-shadow:var(--sh-pop);background:#fff}
.actions-row{display:flex;gap:.6rem;justify-content:flex-end;margin-top:1.2rem;flex-wrap:wrap}

/* ========================================================== DASHBOARD WIDGETS */
.activity{display:flex;flex-direction:column;gap:8px;max-height:380px;overflow-y:auto;padding-right:6px}
.act-item{display:flex;gap:11px;align-items:flex-start;padding:11px 13px;background:var(--panel-2);border:1px solid var(--line);border-radius:11px;font-size:.86rem;transition:.15s}
.act-item:hover{border-color:var(--line-2);background:#fff}
.act-item .ic{width:34px;height:34px;border-radius:9px;flex:none;display:grid;place-items:center;background:var(--teal-soft);color:var(--teal)}
.act-item.order .ic{background:var(--gold-soft);color:var(--gold)}
.act-item .body{flex:1;min-width:0}
.act-item .body b{font-weight:600;color:var(--ink)}
.act-item .body p{color:var(--t2);font-size:.82rem;margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.act-item .body small{display:block;color:var(--t4);font-family:var(--fm);font-size:.66rem;margin-top:3px}

.bcards{display:grid;grid-template-columns:1fr;gap:10px}
@media(min-width:600px){.bcards{grid-template-columns:1fr 1fr}}
.bcard{background:var(--panel-2);border:1px solid var(--line);border-radius:11px;padding:14px 16px;transition:.15s}
.bcard:hover{border-color:var(--line-2);background:#fff;box-shadow:var(--sh-sm)}
.bcard .top{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.bcard .dot{width:10px;height:10px;border-radius:50%;flex:none}
.bcard .nm{font-weight:700;color:var(--ink)}
.bcard .stat{display:flex;justify-content:space-between;font-size:.78rem;color:var(--t2);margin-top:4px}
.bcard .stat b{color:var(--ink);font-family:var(--fm)}

.bars-inline{display:flex;flex-direction:column;gap:10px}
.bar-row-i{display:grid;grid-template-columns:1.3fr 3fr auto;gap:14px;align-items:center;font-size:.84rem}
.bar-row-i .nm{color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bar-row-i .trk{height:8px;background:var(--panel-3);border-radius:var(--pill);overflow:hidden}
.bar-row-i .fil{height:100%;background:var(--grad);border-radius:var(--pill);transition:width .6s var(--ease)}
.bar-row-i .vl{font-family:var(--fm);font-weight:700;font-size:.84rem;color:var(--ink)}

.spark{display:flex;align-items:flex-end;gap:3px;height:54px;margin-top:8px}
.spark span{flex:1;background:var(--teal);border-radius:2px 2px 0 0;min-height:2px;opacity:.85;transition:.2s}
.spark span:hover{opacity:1;transform:scaleY(1.05)}

/* ============================================================== BRAND GRID */
.brand-grid{display:grid;grid-template-columns:1fr;gap:14px}
@media(min-width:760px){.brand-grid{grid-template-columns:1fr 1fr}}
@media(min-width:1180px){.brand-grid{grid-template-columns:repeat(3,1fr)}}
.brand-card{
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r);
  padding:18px;display:flex;flex-direction:column;gap:12px;
  position:relative;overflow:hidden;transition:.2s var(--ease);cursor:pointer;
  box-shadow:var(--sh-sm);
}
.brand-card:hover{border-color:var(--line-2);transform:translateY(-2px);box-shadow:var(--sh-md)}
.brand-card::before{content:"";position:absolute;left:0;right:0;top:0;height:3px;background:var(--accent)}
.brand-card .head{display:flex;justify-content:space-between;align-items:flex-start;gap:8px}
.brand-card .head .nm{font-family:var(--fd);font-weight:700;font-size:1.15rem;letter-spacing:-.02em;color:var(--ink)}
.brand-card .head .slug{font-family:var(--fm);font-size:.7rem;color:var(--t3);margin-top:2px}
.brand-card .domain{font-family:var(--fm);font-size:.78rem;color:var(--teal)}
.brand-card .stats{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;padding-top:12px;border-top:1px solid var(--line-soft);margin-top:auto}
.brand-card .stats .s{display:flex;flex-direction:column;gap:1px}
.brand-card .stats .s .l{font-family:var(--fm);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;color:var(--t3);font-weight:600}
.brand-card .stats .s .v{font-family:var(--fd);font-weight:700;font-size:1.1rem;color:var(--ink)}
.brand-card .embed-box{
  background:var(--panel-2);border:1px solid var(--line);border-radius:9px;padding:9px 12px;
  font-family:var(--fm);font-size:.7rem;color:var(--t2);display:flex;align-items:center;gap:8px;
  cursor:text;overflow:hidden;
}
.brand-card .embed-box code{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.brand-card .embed-box button{
  font-family:var(--fm);font-size:.62rem;letter-spacing:.05em;text-transform:uppercase;
  padding:.32em .7em;border:1px solid var(--line-2);border-radius:6px;color:var(--t2);flex:none;background:#fff;
  transition:.12s;
}
.brand-card .embed-box button:hover{color:var(--ink);border-color:var(--t3);background:var(--panel-3)}
.brand-card .row-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:4px}
.brand-card .row-actions .btn{font-size:.8rem;padding:.5em 1.1em;font-weight:600}
.brand-card .row-actions .btn-edit{background:var(--teal-50);border:1px solid var(--teal-soft);color:var(--teal);border-radius:var(--pill)}
.brand-card .row-actions .btn-edit:hover{background:var(--teal-soft);border-color:var(--teal)}
.brand-add{
  background:transparent;border:2px dashed var(--line-2);color:var(--t3);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  min-height:160px;cursor:pointer;transition:.2s var(--ease);
}
.brand-add:hover{border-color:var(--teal);color:var(--teal);background:var(--teal-50)}
.brand-add svg{width:28px;height:28px}

/* ============================================================ CHIP-INPUT */
.chip-input{
  background:var(--bg-2);border:1px solid var(--line-2);border-radius:10px;padding:8px;
  min-height:46px;display:flex;flex-wrap:wrap;gap:6px;align-items:center;transition:.15s;
}
.chip-input:focus-within{border-color:var(--teal);box-shadow:var(--sh-pop)}
.chip-input input{background:none;border:0;outline:none;flex:1;min-width:140px;padding:4px 6px;color:var(--ink)}
.chip-input .item{
  display:inline-flex;align-items:center;gap:4px;background:var(--panel-3);color:var(--ink-2);
  font-size:.78rem;padding:.3em .7em;border-radius:var(--pill);font-family:var(--fm);font-weight:500;
}
.chip-input .item button{font-size:1.05rem;line-height:1;color:var(--t3);padding:0 0 0 2px}
.chip-input .item button:hover{color:var(--red)}

/* ================================================================ SWATCH */
.swatch{display:flex;align-items:center;gap:8px;background:var(--bg-2);border:1px solid var(--line-2);border-radius:10px;padding:5px 12px 5px 5px;min-height:46px;transition:.15s}
.swatch:focus-within{border-color:var(--teal);box-shadow:var(--sh-pop)}
.swatch input[type=color]{width:34px;height:34px;border:0;background:none;cursor:pointer;border-radius:6px;padding:0}
.swatch input[type=text]{flex:1;background:none;border:0;outline:none;font-family:var(--fm);color:var(--ink)}

/* ================================================================== FLASH */
.flash{
  position:fixed;bottom:24px;left:50%;transform:translateX(-50%);background:var(--ink);
  color:#fff;padding:.78em 1.4em;border-radius:var(--pill);
  font-size:.85rem;font-weight:500;box-shadow:var(--sh-xl);
  opacity:0;transition:opacity .25s,transform .25s;pointer-events:none;z-index:120;
  display:inline-flex;align-items:center;gap:.5em;
}
.flash.on{opacity:1;transform:translateX(-50%) translateY(-4px)}
.flash.err{background:var(--red)}
.flash::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--teal-bright)}
.flash.err::before{background:#FCA5A5}

/* ============================================================== DOMAINS */
.dom-info{
  background:var(--teal-50);border:1px solid var(--teal-soft);border-radius:var(--r);
  padding:18px 20px;margin-bottom:18px;font-size:.92rem;color:var(--ink-2);line-height:1.65;
}
.dom-info b{color:var(--ink);font-weight:700}
.dom-info code{
  background:#fff;border:1px solid var(--line);border-radius:6px;
  padding:.15em .55em;font-family:var(--fm);font-size:.85em;color:var(--teal);
}
.dom-add{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:18px}
.dom-add input{
  flex:1;min-width:240px;background:var(--bg-2);border:1px solid var(--line-2);border-radius:10px;
  padding:.78em 1em;color:var(--ink);font:inherit;transition:.15s;
}
.dom-add input:focus{outline:none;border-color:var(--teal);box-shadow:var(--sh-pop)}
.dom-list{display:flex;flex-direction:column;gap:10px}
.dom-row{
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r);
  padding:16px 20px;display:grid;grid-template-columns:1fr auto;gap:14px;align-items:center;
  box-shadow:var(--sh-sm);
}
.dom-row .name{font-family:var(--fd);font-weight:700;font-size:1.05rem;letter-spacing:-.01em;color:var(--ink);display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.dom-row .name .stbadge{font-size:.7rem}
.dom-row .sub{font-size:.82rem;color:var(--t2);margin-top:4px;display:flex;gap:14px;flex-wrap:wrap}
.dom-row .sub b{color:var(--t3);font-family:var(--fm);font-size:.66rem;letter-spacing:.06em;text-transform:uppercase;font-weight:600;margin-right:5px}
.dom-row .acts{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.dom-row .acts .btn{font-size:.78rem;padding:.5em 1em;font-weight:600}
.dom-row.orphan{border-style:dashed;border-color:var(--amber);background:#FFFBEB}
.dom-row.orphan .name::after{
  content:"orphaned - not on Vercel";font-family:var(--fm);font-size:.65rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--amber);background:#FEF3C7;border:1px solid #FDE68A;
  padding:.3em .6em;border-radius:var(--pill);font-weight:600;
}
@media(max-width:720px){
  .dom-row{grid-template-columns:1fr}
  .dom-row .acts{justify-content:flex-start}
}

.dns-table{width:100%;border-collapse:collapse;font-size:.85rem;margin-top:6px}
.dns-table th,.dns-table td{padding:9px 10px;text-align:left;border-bottom:1px solid var(--line-soft);font-family:var(--fm)}
.dns-table th{color:var(--t3);font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;font-weight:600;background:var(--panel-2)}
.dns-table td{color:var(--ink-2);word-break:break-all;font-size:.8rem}
.dns-table td button{
  font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;padding:.3em .65em;
  border:1px solid var(--line-2);border-radius:6px;color:var(--t2);background:#fff;
}
.dns-table td button:hover{color:var(--ink);border-color:var(--t3);background:var(--panel-3)}

/* ============================================================================
   GENERIC COMPONENTS - used across Player payouts, Merchant stats, Monitoring,
   Reports, Refunds, Resellers. These pages render `.card` / `.muted` / inline
   tables; without these rules they fell back to flat black-on-white.
   ============================================================================ */
.card{
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--sh-sm);padding:16px;
}
.card.primary,.card[style*="border-top"]{box-shadow:var(--sh-md)}
.muted{color:var(--t3)}
.lead{color:var(--t2);font-size:.96rem}
.amt{font-family:var(--fm);font-weight:600}

/* Friendlier data tables everywhere: tinted bold header, row hover, clear dividers.
   Additive only - inline padding/align on cells still wins. */
.main table{border-collapse:collapse;width:100%}
.main table th{
  background:var(--panel-2);color:var(--t3);font-family:var(--fm);font-weight:700;
  font-size:10px;letter-spacing:.09em;text-transform:uppercase;border-bottom:2px solid var(--line-2);
}
.main table tbody tr{transition:background .12s}
.main table tbody tr:hover{background:var(--teal-50)}
.main table a[onclick]{color:var(--teal);font-weight:600}
.main table a[onclick]:hover{text-decoration:underline}

/* Bolder section headers - a short accent rule under each page title. */
.section-head h2::after{content:"";display:block;width:46px;height:4px;border-radius:3px;background:var(--grad);margin-top:9px}

/* Panel header strip (the bold first row inside a flush card) reads as a section. */
.card > div:first-child[style*="border-bottom"]{
  background:linear-gradient(180deg,var(--panel-2),var(--bg-2));
}

/* A simple page-level chip used by some views (e.g. status pills built inline). */
.pill-soft{display:inline-flex;align-items:center;gap:.4em;font-size:.72rem;font-weight:700;border-radius:var(--pill);padding:.25em .7em}

/* ============================================================================
   MORE CONTRAST & COLOR - the light theme read as "faded". Darker text, stronger
   surfaces/shadows, and brand-teal tinted table headers + section strips so the
   eye can parse each page quickly. (Override block - defined last to win.)
   ============================================================================ */
:root{
  --t2:#48536A;            /* secondary text */
  --t3:#606B84;            /* tertiary text */
  --t4:#8A93A8;            /* placeholder / subtle */
  --line:rgba(12,19,34,.09);
  --line-2:rgba(12,19,34,.16);
  --sh-sm:0 1px 3px rgba(12,19,34,.05);
  --sh-md:0 1px 2px rgba(12,19,34,.04),0 8px 24px -14px rgba(18,32,78,.22);
}
body{color:var(--ink)}

/* Cards/panels get real definition */
.card,.panel,.kpi,.tbl,.toolbar,.brand-card,.dom-row{box-shadow:var(--sh-md)}
.card,.panel{border-color:var(--line-2)}

/* Section titles bolder + the page lead darker */
.section-head h2{font-size:1.7rem;color:var(--ink)}
.section-head .lead,.lead{color:var(--t2)}
.muted{color:var(--t3)}

/* Table headers: quiet Space Grotesk caps on the alt surface, per the design.
   Colour carries meaning; a column label is not a status. */
.main table th{
  background:var(--panel-2)!important;color:var(--t3)!important;
  font-family:var(--fd)!important;font-weight:500!important;letter-spacing:.14em!important;
  border-bottom:1px solid var(--line)!important;
}
.main table tbody td{color:var(--ink-2)}
.main table tbody tr:hover{background:var(--panel-2)}

/* The bold first row inside a flush card reads as a section header. */
.card > div:first-child[style*="border-bottom"]{
  background:linear-gradient(180deg,var(--panel-2),var(--bg-2));color:var(--ink);
}

/* Money / key figures shouldn't be gray. */
.amt,.mono{color:var(--ink)}

/* Nav: stronger active state */
.nav-item{font-weight:600;color:var(--t2)}
.nav-item.active{background:var(--teal-50);color:var(--teal)}
.nav-item .badge{background:var(--red);box-shadow:0 1px 4px rgba(220,38,38,.4)}

/* Toolbar selects/inputs a touch crisper */
.toolbar select,.toolbar input{border-color:var(--line-2)}

/* ============================================================================
   PER-METRIC COLOUR - coloured stat cards (.kard) + accent section panels
   (.spanel). Each metric gets its own hue so the page is parseable at a glance.
   ============================================================================ */
.kard{position:relative;background:var(--bg-2);border:1px solid var(--line-2);border-radius:var(--r);padding:15px 17px;box-shadow:var(--sh-md);overflow:hidden;flex:1;min-width:158px}
.kard::before{content:"";position:absolute;left:0;top:0;bottom:0;width:5px;background:var(--c,var(--teal))}
.kard .kl{font-family:var(--fm);font-size:10px;letter-spacing:.11em;text-transform:uppercase;color:var(--t3);font-weight:700;display:flex;align-items:center;gap:6px}
.kard .kv{font-family:var(--fd);font-weight:800;font-size:1.5rem;letter-spacing:-.02em;color:var(--c,var(--ink));margin-top:5px;line-height:1.2;padding-bottom:1px}
.kard .ks{font-size:.73rem;color:var(--t3);margin-top:5px;line-height:1.45}
.kard.teal  {--c:var(--teal);  background:linear-gradient(180deg,var(--teal-50),var(--bg-2));border-color:var(--teal-soft)}
.kard.green {--c:var(--green); background:linear-gradient(180deg,var(--green-soft),var(--bg-2));border-color:var(--teal-soft)}
.kard.gold  {--c:var(--gold);  background:linear-gradient(180deg,var(--gold-soft),var(--bg-2));border-color:var(--gold-soft)}
.kard.red   {--c:var(--red);   background:linear-gradient(180deg,#FEF2F2,var(--bg-2));border-color:#FECACA}
.kard.indigo{--c:var(--indigo);background:linear-gradient(180deg,#EEF1FE,var(--bg-2));border-color:#C7D2FE}
.kard.violet{--c:var(--violet);background:linear-gradient(180deg,#F5F3FF,var(--bg-2));border-color:#DDD6FE}
.kard.amber {--c:var(--amber); background:linear-gradient(180deg,#FFFBEB,var(--bg-2));border-color:#FDE68A}

.spanel{background:var(--bg-2);border:1px solid var(--line-2);border-radius:var(--r);box-shadow:var(--sh-md);overflow:hidden;margin-bottom:16px}
.spanel > .sh{padding:13px 16px;font-family:var(--fd);font-weight:800;font-size:1.02rem;color:var(--ink);border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px;background:linear-gradient(180deg,var(--panel-2),var(--bg-2))}
.spanel > .sh::before{content:"";width:5px;height:19px;border-radius:3px;background:var(--c,var(--teal))}
.spanel > .sh .sub{font-family:var(--f);font-weight:400;font-size:.77rem;color:var(--t3)}
.spanel.teal{--c:var(--teal)} .spanel.gold{--c:var(--gold-bright)} .spanel.indigo{--c:var(--indigo)} .spanel.violet{--c:var(--violet)} .spanel.green{--c:var(--green)} .spanel.amber{--c:var(--amber)}

/* ============================================================================
   PREMIUM v2 - high-class gateway look. Dark rich sidebar, real depth on the
   light content area, bolder type, refined components. Appended last to win;
   no markup or JS changes. Tune freely.
   ============================================================================ */
:root{
  --pe-shadow-card:0 1px 2px rgba(12,19,34,.04), 0 8px 24px -14px rgba(18,32,78,.22);
  --pe-shadow-hover:0 2px 6px rgba(12,19,34,.06), 0 18px 40px -18px rgba(18,32,78,.30);
}

/* ---- Page: the flat canvas from the approved design ---- */
body{
  background:var(--bg);
  background-attachment:fixed;
}

/* ---- Dark sidebar with the 168deg blue wash (approved design) ---- */
.side{
  background:#0A101C;
  background-image:linear-gradient(168deg,rgba(46,124,255,.16) 0%,rgba(46,124,255,0) 42%);
  border-right:1px solid rgba(255,255,255,.07);
  box-shadow:1px 0 0 rgba(255,255,255,.03) inset, 6px 0 30px -18px rgba(10,16,28,.55);
}
.side .brand{padding-bottom:16px;margin-bottom:14px;border-bottom:1px solid rgba(255,255,255,.07)}
.side .brand b{color:#fff;font-family:var(--fd);font-weight:700;letter-spacing:-.01em}
.side .brand .sub{font-family:var(--fd);color:#93A6C8;letter-spacing:.24em;font-weight:500}
.nav-section{font-family:var(--fd);color:#5E7196;letter-spacing:.2em;font-weight:500;font-size:.64rem}
.nav-item{color:#93A6C8;border-radius:10px;font-weight:500;border:1px solid transparent}
.nav-item svg{opacity:.9;stroke-width:1.7}
.nav-item:hover{background:rgba(255,255,255,.04);color:#DCE5F5}
.nav-item:hover svg{opacity:1}
/* Active: soft blue fill. The border is transparent in EVERY state above, so
   turning it blue here cannot shift the label by a pixel. */
.nav-item.active{
  background:rgba(46,124,255,.12);
  border-color:rgba(46,124,255,.22);
  color:#fff;font-weight:600;box-shadow:none;
}
.nav-item.active svg{opacity:1;stroke:url(#peNavGrad);color:inherit}
/* No left rail on the active item - the fill is the signal. */
.nav-item.active::before{content:none}
.nav-item .badge{
  background:rgba(255,255,255,.08);color:#DCE5F5;font-family:var(--fd);font-weight:600;
  box-shadow:none;
}
.nav-item .badge.hot{background:rgba(224,72,59,.2);color:#FFB4AC}
/* Sub-menu under a sidebar item (Evervault sections). Same colours and
   radius as .nav-item, indented under the parent's label with a thin guide
   line; folded away unless that section is showing. */
.nav-sub{display:none;margin:2px 0 6px 21px;padding-left:12px;border-left:1px solid rgba(255,255,255,.09)}
.nav-sub.open{display:block}
.nav-subitem{
  display:block;padding:.38rem .7rem;margin:1px 0;border-radius:8px;
  font-size:.84rem;font-weight:500;color:#93A6C8;border:1px solid transparent;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.nav-subitem:hover{background:rgba(255,255,255,.04);color:#DCE5F5}
.nav-subitem.active{background:rgba(46,124,255,.12);border-color:rgba(46,124,255,.22);color:#fff;font-weight:600}
@media (max-width:900px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  .nav-subitem{padding:.55rem .75rem;font-size:.9rem}
}
.side .pull-bottom{border-top:1px solid rgba(255,255,255,.07)}
/* sidebar scrollbar */
.side::-webkit-scrollbar{width:8px}
.side::-webkit-scrollbar-thumb{background:rgba(255,255,255,.14);border-radius:8px}

/* ---- Top bar: the canvas, blurred, per the design ---- */
.top{
  background:rgba(238,241,248,.84);backdrop-filter:saturate(1.4) blur(10px);
  border-bottom:1px solid var(--line);
  box-shadow:none;
}
.top h1{font-family:var(--fd);font-weight:700;font-size:1.45rem;letter-spacing:-.02em;color:var(--ink)}
.top .logout{background:var(--bg-2);font-family:var(--f);text-transform:none;letter-spacing:0;font-weight:600;font-size:.82rem;border-radius:10px}

/* ---- Headings ---- */
.section-head{margin-bottom:26px}
.section-head h2{font-family:var(--fd);font-weight:700;font-size:1.75rem;letter-spacing:-.03em;line-height:1.15;padding-bottom:2px}
.section-head h2::after{content:none}
.section-head .lead{color:var(--t2);font-size:1rem}

/* ---- Cards & surfaces: real depth + hover lift ---- */
.card,.panel,.kpi,.tbl,.toolbar,.brand-card,.dom-row,.spanel,.kard{
  border:1px solid var(--line-2);box-shadow:var(--pe-shadow-card);
}
.card:hover,.brand-card:hover,.kard:hover{box-shadow:var(--pe-shadow-hover);transform:translateY(-1px)}
.card,.kard{transition:box-shadow .2s var(--ease),transform .2s var(--ease)}
.spanel{border-radius:var(--r-lg)}
.kpi .v{font-size:2.15rem}

/* ---- Buttons: solid ink primary, crisp ghost ---- */
.btn{font-weight:600;letter-spacing:0;border-radius:10px}
.btn-primary{
  background:var(--ink);border-color:var(--ink);
  box-shadow:0 8px 18px -10px rgba(12,19,34,.5);
}
.btn-primary:hover{background:#1A2439;border-color:#1A2439;box-shadow:0 12px 24px -12px rgba(12,19,34,.55)}
.btn-ghost{background:#fff;box-shadow:var(--sh-sm)}
.btn-ghost:hover{background:var(--panel-2);border-color:var(--line-2)}

/* ---- Form controls in content: consistent + crisp ---- */
.main select,.toolbar select,.toolbar input,
.main input[type=text],.main input[type=date],.main input[type=search],.main input[type=email],.main input[type=number]{
  background:#fff;border:1px solid var(--line-2);border-radius:10px;
  padding:.55em .85em;min-height:40px;color:var(--ink);transition:border-color .15s,box-shadow .15s;
}
.main select:focus,.toolbar select:focus,.toolbar input:focus,
.main input[type=text]:focus,.main input[type=date]:focus,.main input[type=search]:focus,.main input[type=email]:focus,.main input[type=number]:focus{
  outline:none;border-color:var(--teal);box-shadow:var(--sh-pop);
}

/* ---- Tables: premium header + zebra-on-hover ---- */
.main table th{font-size:10.5px;padding-top:12px;padding-bottom:12px}
.main table tbody tr:hover{background:var(--panel-2)}

/* ---- Modals: a touch more premium ---- */
.modal{border-radius:20px;box-shadow:0 40px 80px -24px rgba(2,6,23,.45)}
.modal-back{background:rgba(10,16,28,.55)}

/* ---- Page content scrollbar ---- */
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-thumb{background:rgba(100,116,139,.32);border-radius:10px;border:3px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:rgba(100,116,139,.5);background-clip:content-box}

/* ============================================================================
   DTABLE - one premium data-table component to replace the inline <table style>
   pattern across Player payouts, Merchant stats, Reports, Monitoring, etc.
   Usage: <div class="dtable-wrap"><table class="dtable"> ... add class="num" to
   right-aligned numeric th/td.
   ============================================================================ */
.dtable-wrap{overflow-x:auto}
.dtable{width:100%;border-collapse:separate;border-spacing:0;font-size:.9rem}
.dtable thead th{
  position:sticky;top:0;z-index:1;background:var(--panel-2);color:var(--t2);
  font-family:var(--fm);font-weight:800;font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  text-align:left;padding:12px 16px;border-bottom:2px solid var(--line-2);white-space:nowrap;
}
.dtable thead th.num{text-align:right}
.dtable tbody td{padding:13px 16px;border-bottom:1px solid var(--line-soft);color:var(--ink-2);vertical-align:middle}
.dtable tbody td.num{text-align:right;font-family:var(--fm);font-weight:600;color:var(--ink)}
.dtable tbody td .sub{display:block;color:var(--t3);font-size:.77rem;margin-top:2px}
.dtable tbody tr{transition:background .12s}
.dtable tbody tr:hover td{background:var(--panel-2)}
.dtable tbody tr:last-child td{border-bottom:0}
.dtable tbody tr.warn td{background:#FFF6F5}
.dtable .empty-row td{padding:26px 16px;text-align:center;color:var(--t3)}

/* A row of colour-coded KPI cards at the top of a page (uses .kard variants). */
.kard-row{display:flex;gap:14px;flex-wrap:wrap;margin-bottom:18px}

/* Numeric helper for inline use */
.num{text-align:right;font-family:var(--fm);font-weight:600;color:var(--ink)}

/* ============================================================================
   MERCHANT IDENTITY - initials avatar in the merchant's accent colour, used
   everywhere a merchant appears so they're recognisable at a glance.
   ============================================================================ */
.mav{display:inline-flex;align-items:center;justify-content:center;border-radius:9px;color:#fff;
  font-family:var(--fd);font-weight:800;letter-spacing:-.02em;flex:none;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.22), 0 2px 7px -2px rgba(15,23,42,.35);text-transform:uppercase}
.mav.sm{width:26px;height:26px;font-size:.64rem;border-radius:7px}
.mav.md{width:36px;height:36px;font-size:.82rem}
.mav.lg{width:48px;height:48px;font-size:1.05rem;border-radius:13px}
.mname{display:inline-flex;align-items:center;gap:9px}

/* ============================================================================
   STATUS STEPPER - horizontal transaction lifecycle (Created → ... → Settled).
   ============================================================================ */
/* One track behind four evenly spaced points (centres at 12.5/37.5/62.5/87.5%).
   Ordinary steps are quiet; the OUTCOME step stands out: Approved in the
   PlatinumEdge blue-green gradient, Declined in red, both one size larger. */
.stepper{position:relative;display:flex;margin:4px 0 22px;padding:14px 8px 14px;border:1px solid var(--line);border-radius:14px;background:var(--grad-soft)}
.stepper::before,.stepper::after{content:"";position:absolute;top:33px;left:12.5%;height:3px;border-radius:3px}
.stepper::before{right:12.5%;background:var(--line-2)}
.stepper::after{width:calc(75% * var(--p,0));background:rgba(46,124,255,.35)}
.stepper .stp{flex:1;text-align:center;position:relative;z-index:1;min-width:0}
.stepper .stp .dot{box-sizing:border-box;width:30px;height:30px;border-radius:50%;margin:5px auto 0;display:flex;align-items:center;justify-content:center;
  font-family:var(--fm);font-size:.74rem;font-weight:800;line-height:1;background:#fff;border:2px solid var(--line-2);color:var(--t3)}
.stepper .stp .dot svg{width:14px;height:14px;display:block;flex:none}
.stepper .stp.done .dot{background:#E8F0FE;border:0;color:#2E7CFF}
.stepper .stp.cur .dot{border-color:#2E7CFF;color:#2E7CFF}
.stepper .stp.ok .dot,.stepper .stp.bad .dot{width:40px;height:40px;margin-top:0;border:0;color:#fff}
.stepper .stp.ok .dot svg,.stepper .stp.bad .dot svg{width:18px;height:18px}
.stepper .stp.ok .dot{background:linear-gradient(135deg,#2E7CFF 0%,#19E3D0 100%);box-shadow:0 0 0 5px rgba(25,200,220,.16),0 4px 12px rgba(25,160,220,.32)}
.stepper .stp.bad .dot{background:var(--red);box-shadow:0 0 0 5px rgba(220,38,38,.12),0 4px 12px rgba(220,38,38,.25)}
.stepper .stp .lbl{font-size:.74rem;color:var(--t3);margin-top:8px;font-weight:600;white-space:nowrap}
.stepper .stp.ok .dot + .lbl,.stepper .stp.bad .dot + .lbl{margin-top:3px}
.stepper .stp.done .lbl,.stepper .stp.cur .lbl{color:var(--ink)}
.stepper .stp.ok .lbl{font-weight:800;background:linear-gradient(90deg,#2E7CFF,#12B8AC);-webkit-background-clip:text;background-clip:text;color:transparent}
.stepper .stp.bad .lbl{color:var(--red);font-weight:800}
.stepper.is-bad::after{background:rgba(46,124,255,.35)}
.od-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.od-head h2{margin:0}
.od-head + .submeta{margin:4px 0 14px}
.stepper .stp .sub{font-size:.66rem;color:var(--t3);margin-top:2px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media (max-width:480px){.stepper{padding:14px 2px 12px}.stepper .stp .lbl{font-size:.7rem}.stepper .stp .sub{display:none}}

/* ============================================================================
   COMMAND PALETTE (⌘K) + top-bar search trigger
   ============================================================================ */
.top-search{display:flex;align-items:center;gap:9px;background:var(--panel-2);border:1px solid var(--line-2);
  border-radius:10px;padding:.5em .85em;color:var(--t3);cursor:text;min-width:240px;font-size:.88rem;transition:.15s}
.top-search:hover{border-color:var(--teal);background:#fff;color:var(--t2)}
.top-search svg{width:15px;height:15px;flex:none}
.top-search .kbd{margin-left:auto;font-family:var(--fm);font-size:.64rem;border:1px solid var(--line-2);
  border-radius:5px;padding:1px 6px;color:var(--t4);background:#fff}
@media(max-width:680px){.top-search{min-width:0}.top-search span.lbl{display:none}}

.cmdk-back{position:fixed;inset:0;background:rgba(10,16,28,.5);backdrop-filter:blur(4px);
  display:none;align-items:flex-start;justify-content:center;padding-top:11vh;z-index:200;animation:fadeIn .15s var(--ease)}
.cmdk-back.on{display:flex}
.cmdk{width:min(620px,94vw);background:var(--bg-2);border:1px solid var(--line-2);border-radius:18px;
  box-shadow:0 44px 96px -22px rgba(2,6,23,.55);overflow:hidden;animation:popIn .18s var(--ease)}
.cmdk-top{display:flex;align-items:center;gap:11px;padding:15px 18px;border-bottom:1px solid var(--line)}
.cmdk-top svg{width:19px;height:19px;color:var(--t3);flex:none}
.cmdk-input{flex:1;border:0;outline:none;background:none;font-size:1.05rem;color:var(--ink)}
.cmdk-input::placeholder{color:var(--t4)}
.cmdk-list{max-height:58vh;overflow-y:auto;padding:8px}
.cmdk-group{font-family:var(--fm);font-size:10px;letter-spacing:.11em;text-transform:uppercase;color:var(--t4);padding:11px 12px 5px}
.cmdk-item{display:flex;align-items:center;gap:12px;padding:9px 12px;border-radius:11px;cursor:pointer;color:var(--ink-2)}
.cmdk-item .ic{width:32px;height:32px;border-radius:9px;background:var(--panel-3);color:var(--t2);display:grid;place-items:center;flex:none}
.cmdk-item .ic svg{width:17px;height:17px;stroke-width:1.9}
.cmdk-item .t{flex:1;min-width:0}
.cmdk-item .t b{display:block;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cmdk-item .t small{color:var(--t3);font-size:.78rem}
.cmdk-item.sel{background:var(--teal-50);box-shadow:inset 0 0 0 1px rgba(46,124,255,.25)}
.cmdk-empty{padding:34px;text-align:center;color:var(--t3)}

/* Segmented toggle (e.g. EUR/GBP on the volume chart) */
.seg{display:inline-flex;background:var(--panel-2);border:1px solid var(--line-2);border-radius:9px;padding:2px;gap:2px}
.seg button{font:inherit;font-weight:700;font-size:.78rem;border:0;background:none;color:var(--t3);padding:4px 12px;border-radius:7px;cursor:pointer;transition:.12s}
.seg button.on{background:#fff;color:var(--ink);box-shadow:var(--sh-sm)}

/* ---- Add-merchant modal: sections, fee cards, access options ---- */
.mc-sec{font-size:.66rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:var(--teal);margin:18px 0 9px;padding-bottom:6px;border-bottom:1px solid var(--line)}
.mc-feecards{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:12px}
.mc-feecard{border:1px solid var(--line);border-radius:12px;padding:12px 14px;background:var(--bg-2)}
.mc-feecard-h{font-weight:800;font-size:.92rem;color:var(--ink)}
.mc-feecard-sub{font-size:.74rem;color:var(--t3);margin-top:2px}
.mc-opts{display:flex;flex-direction:column;gap:9px}
.mc-opt{display:flex;align-items:flex-start;gap:11px;border:1px solid var(--line);border-radius:12px;padding:12px 14px;cursor:pointer;transition:border-color .14s,background .14s}
.mc-opt:hover{border-color:var(--teal)}
.mc-opt:has(input:checked){border-color:var(--teal);background:rgba(46,124,255,.07)}
.mc-opt > input{margin-top:2px;accent-color:var(--teal);width:16px;height:16px;flex:0 0 auto;cursor:pointer}
.mc-opt-b{display:flex;flex-direction:column;gap:1px}
.mc-opt-b b{font-weight:700;font-size:.9rem;color:var(--ink)}
.mc-opt-sub{font-size:.76rem;color:var(--t3)}

/* ---- Providers: grouped provider card (Open banking nests Sepagon + PayDo) ---- */
.prov-group .prov-items{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.prov-item{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:var(--bg-2)}
.prov-item-main{min-width:0}
.prov-item-nm{font-weight:700;font-size:.88rem;color:var(--ink)}
.prov-item-meta{font-size:.76rem;color:var(--t3);margin-top:1px;word-break:break-word}
.prov-item-note{font-size:.76rem;color:var(--t2);margin-top:4px}
.prov-item-act{display:flex;align-items:center;gap:8px;flex:0 0 auto}
.prov-item-act .btn{padding:4px 10px;font-size:.78rem}

/* ===== Merchants table (scales to 100s) ===== */
#brandGrid{display:block}
.mtbl-toolbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:16px}
.mtbl-search{position:relative;flex:1;min-width:240px}
.mtbl-search svg{position:absolute;left:12px;top:50%;transform:translateY(-50%);width:16px;height:16px;color:var(--t3);pointer-events:none}
.mtbl-search input{width:100%;padding:10px 14px 10px 36px;border:1px solid var(--line);border-radius:10px;background:var(--panel);color:var(--ink);font-size:.9rem;font-family:inherit}
.mtbl-search input:focus{outline:none;border-color:var(--teal);box-shadow:0 0 0 3px var(--teal-50)}
.mtbl-sel{padding:10px 14px;border:1px solid var(--line);border-radius:10px;background:var(--panel);color:var(--ink);font-size:.88rem;font-family:inherit;cursor:pointer}
.mtbl-sel:focus{outline:none;border-color:var(--teal)}
.mtbl-dir{width:40px;height:40px;flex:none;border:1px solid var(--line);border-radius:10px;background:var(--panel);color:var(--ink);font-size:1.05rem;cursor:pointer;display:flex;align-items:center;justify-content:center}
.mtbl-dir:hover{background:var(--panel-2);border-color:var(--t4)}
.mtbl-summary{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:16px}
.mtbl-chip{flex:1;min-width:140px;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:12px 16px}
.mtbl-chip-l{font-family:var(--fm);font-size:.62rem;letter-spacing:.08em;text-transform:uppercase;color:var(--t3);font-weight:600;margin-bottom:5px}
.mtbl-chip-v{font-size:1.15rem;font-weight:700;color:var(--ink);font-family:var(--fm)}
.mtbl-sub{font-size:.72rem;font-weight:600;color:var(--green);margin-left:4px}
.dtable tbody tr.mtbl-row{cursor:pointer}
.mtbl-merch{display:flex;align-items:center;gap:11px;min-width:0}
.mtbl-merch-t{min-width:0}
.mtbl-merch-nm{font-weight:700;color:var(--ink);font-size:.92rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}
.mtbl-merch-sub{font-size:.74rem;color:var(--t3);font-family:var(--fm);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}
.mtbl-prov{display:inline-block;padding:3px 10px;border-radius:999px;background:var(--panel-3);color:var(--t2);font-size:.78rem;font-weight:600}

/* ---- merchants list, restructured ------------------------------------------
   The live table had a status column that could only ever read "active", every
   currency printed inline (three-line rows for the 3 of 17 merchants that are
   multi-currency), and five buttons on every row. These rules support the
   replacement: quick filters, a collapsed money cell, and a hover menu. */

/* Quick filters. They key off something that actually differs between
   merchants, unlike the status dropdown they replace. */

/* ---- merchant profile: left rail -------------------------------------------
   Six top tabs put every section behind a horizontal strip, and the widest of
   them rendered 10,572px - 11.7 screens at a 900px viewport. The rail stays on
   screen, so the section list is always visible and jumping between them costs
   no scrolling. */
.mp-layout{display:grid;grid-template-columns:224px minmax(0,1fr);gap:16px;align-items:start}
.mp-rail{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:8px;box-shadow:var(--sh-sm);position:sticky;top:16px}
.mp-rail-g{font-size:.66rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--t4);padding:10px 10px 5px}
.mp-rl{display:flex;align-items:center;gap:9px;width:100%;padding:8px 10px;border:none;
  background:transparent;border-radius:var(--r-sm);color:var(--t2);font-family:inherit;
  font-size:.86rem;font-weight:500;cursor:pointer;text-align:left;margin-bottom:1px}
@media (hover:hover){.mp-rl:hover{background:var(--panel-3);color:var(--ink)}}
.mp-rl.on{background:var(--teal-50);color:var(--teal);font-weight:600}
.mp-rl.on .mp-rl-ic{background:var(--teal);color:#fff}
.mp-rl-ic{width:22px;height:22px;border-radius:6px;background:var(--panel-3);color:var(--t3);
  display:grid;place-items:center;font-size:.72rem;flex:none}
.mp-rl-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mp-rl-n{font-family:var(--fm);font-size:.7rem;color:var(--t4);flex:none}
.mp-rl-n.warn{color:var(--amber);font-weight:700}
/* Money tabs carry no permanent side mark: only the selected tab shows the marker. */
.mp-pane{min-width:0}

/* Overview KPIs */
.mp-kpis{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:11px;margin-bottom:14px}
.mp-kpi{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);padding:12px 15px}
.mp-kpi .k{font-size:.68rem;color:var(--t4);text-transform:uppercase;letter-spacing:.05em;font-weight:600}
.mp-kpi .v{font-size:1.3rem;font-weight:700;letter-spacing:-.02em;margin-top:3px;font-family:var(--fm)}

/* ---- REVENUE IN EVERY CURRENCY -----------------------------------------
   The tile used to hold one figure, because it only ever stated one currency.
   It now holds one row per currency (moneyAllCcyRows in core.js), so the type
   drops to a size four or five rows fit at 390px without the tile swallowing
   the screen, and the code stays aligned in a column by using the mono face
   for the amount only. */
.mp-kpi .v.mccy{font-size:.85rem;line-height:1.35;margin-top:4px}
.mccy-row{display:flex;align-items:baseline;justify-content:space-between;gap:6px;min-width:0}
.mccy-row + .mccy-row{margin-top:1px}
.mccy-c{font-size:.64rem;font-weight:700;color:var(--t4);letter-spacing:.05em;flex:none}
/* NEVER BREAK A FIGURE ACROSS TWO LINES. `overflow-wrap:anywhere` split
   "IDR 1,199,148.00" after the comma group at 390px, which reads as a
   different, smaller number at a glance - the exact misreading this whole
   change exists to stop. The amount stays whole and the type shrinks instead,
   because a wrong number is worse than a small one. min-width:0 on both the
   row and the value is what lets the flex item shrink rather than push the
   tile wider than its card. */
.mccy-v{font-family:var(--fm);font-weight:700;white-space:nowrap;text-align:right;
  min-width:0;font-size:clamp(.62rem,2.6vw,.8rem)}
/* The revenue tile is the tall one; letting it stretch would drag three short
   tiles to the same height and leave a band of empty card. */
.mp-kpi-ccy{align-self:start}

/* ---- PAYMENT RAILS TABLE ------------------------------------------------
   Four columns on a desktop, stacked labelled rows on a phone: a rail list
   that needs a horizontal scrollbar is a rail list an operator does not read.
   Named mprw-*, NOT mp-rail-*: .mp-rail-g is already the left navigation's
   group heading, and reusing it would restyle the nav. */
.mprw-head{display:grid;grid-template-columns:1.5fr 1.6fr 1.2fr .9fr;gap:10px;padding:6px 2px;
  font-size:.66rem;text-transform:uppercase;letter-spacing:.05em;color:var(--t4);font-weight:700;
  border-bottom:1px solid var(--line)}
.mprw{display:grid;grid-template-columns:1.5fr 1.6fr 1.2fr .9fr;gap:10px;padding:9px 2px;
  border-bottom:1px solid var(--line);font-size:.8rem;align-items:baseline}
.mprw:last-child{border-bottom:0}
.mprw-n{min-width:0;overflow-wrap:anywhere}
.mprw-w,.mprw-c,.mprw-g{min-width:0;overflow-wrap:anywhere;color:var(--t2);font-family:var(--fm);font-size:.74rem}
@media (pointer:coarse) and (hover:none) and (max-width:1100px),(max-width:760px){
  .mprw-head{display:none}
  .mprw{grid-template-columns:1fr;gap:3px;padding:11px 2px}
  .mprw-w::before{content:"cleared by: ";color:var(--t4);font-family:var(--fs,inherit)}
  .mprw-c::before{content:"currencies: ";color:var(--t4)}
  .mprw-g::before{content:"countries: ";color:var(--t4)}
}

/* Currencies stated per rail under the union, so "EUR, GBP, USD, INR, IDR"
   cannot be misread as "all of these on cards". */
.mp-ccy-rails{margin-top:5px;font-size:.7rem;color:var(--t3);line-height:1.45}
.mp-ccy-rails span{color:var(--t4);font-weight:600}

/* A check that names a problem must take you to it. */
.mp-golink{color:var(--teal);font-weight:600;cursor:pointer;white-space:nowrap}
.mp-golink:hover{text-decoration:underline}

/* Width alone is not the test: a phone in desktop-site mode reports a wide
   viewport while still being a touch device, and would get the sticky rail it
   cannot use. pointer:coarse + hover:none stay true in that mode - the same
   condition the rest of this stylesheet already uses. */
@media (max-width:900px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  .mp-layout{grid-template-columns:1fr}
  .mp-rail{position:static;display:flex;gap:4px;overflow-x:auto;padding:6px}
  .mp-rail-g{display:none}
  .mp-rl{width:auto;white-space:nowrap}
}



/* ---- geo picker (modal) ----------------------------------------------------
   Replaces a window.prompt() that demanded comma-separated ISO codes. Selection
   is a SELECTION: the chosen countries are visible and removable, regions are
   one click, and search handles the long tail. */
.geo-chosen{display:flex;flex-wrap:wrap;gap:6px;align-items:center;min-height:34px;
  padding:8px 10px;background:var(--panel-2);border:1px solid var(--line);
  border-radius:10px;margin-bottom:12px}
.geo-sel{display:inline-flex;align-items:center;gap:5px;background:var(--teal-50);
  border:1px solid var(--teal);color:var(--teal);border-radius:999px;padding:3px 9px;
  font-family:var(--fm);font-size:.74rem;font-weight:700;cursor:pointer}
.geo-sel:hover{background:var(--red-soft,#FEE);border-color:var(--red);color:var(--red)}
.geo-sel span{opacity:.7;font-size:.9em}

.geo-presets{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
.geo-preset{background:var(--panel-2);border:1px solid var(--line);color:var(--t2);
  border-radius:8px;padding:5px 10px;font-size:.76rem;font-weight:600;cursor:pointer}
.geo-preset:hover{border-color:var(--teal);color:var(--teal)}
.geo-preset.danger:hover{border-color:var(--red);color:var(--red)}

.geo-search{width:100%;margin-bottom:10px}
.geo-list{max-height:min(46vh,340px);overflow-y:auto;border:1px solid var(--line);
  border-radius:10px;background:var(--panel)}
.geo-opt{display:grid;grid-template-columns:44px 1fr 22px;align-items:center;gap:8px;
  width:100%;padding:8px 12px;background:transparent;border:0;
  border-bottom:1px solid var(--line);cursor:pointer;text-align:left;font-size:.86rem;
  color:var(--t2);font-family:inherit}
.geo-opt:last-child{border-bottom:0}
.geo-opt:hover{background:var(--panel-3)}
.geo-opt.on{background:var(--teal-50);color:var(--teal);font-weight:600}
.geo-code{font-family:var(--fm);font-size:.76rem;font-weight:700;color:var(--t3)}
.geo-opt.on .geo-code{color:var(--teal)}
.geo-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.geo-tick{color:var(--teal);font-weight:700;text-align:right}
/* ---- per-solution settings: chip + inline editor ---------------------------
   Deliberately reuses the MID card's controls (.gw-chip, .mpf-*) rather than a
   parallel vocabulary: an operator who has learned the MID card is editing the
   same four settings here. */
.mp-solchip{border:1px solid var(--line);background:var(--panel-2);color:var(--t3);
  border-radius:999px;padding:3px 9px;font-size:.72rem;font-weight:600;cursor:pointer;
  font-family:var(--fm);white-space:nowrap;margin-right:8px;line-height:1.6}
.mp-solchip:hover{border-color:var(--teal);color:var(--teal)}
.mp-solchip.on{background:var(--teal-50);border-color:var(--teal);color:var(--teal)}
.mp-soledit{background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;margin:2px 0 10px}
.mp-soledit .mid-sub{font-size:.72rem;font-weight:600;color:var(--t3);margin:10px 0 5px}
.mp-soledit .mid-sub:first-child{margin-top:0}
.mp-soledit-foot{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:12px;
  padding-top:10px;border-top:1px solid var(--line)}
/* ---- geo chip: which countries may SEE a solution --------------------------
   States its own value at rest ("All countries" / "PE CL +2"), so an operator
   reads the rule without opening anything. Amber when restricted: it is a
   deliberate narrowing of who can pay, not a neutral setting. */
.mp-geochip{border:1px solid var(--line);background:var(--panel-2);color:var(--t3);
  border-radius:999px;padding:3px 9px;font-size:.72rem;font-weight:600;cursor:pointer;
  font-family:var(--fm);white-space:nowrap;margin-right:8px;line-height:1.6}
.mp-geochip:hover{border-color:var(--teal);color:var(--teal)}
.mp-geochip.on{background:var(--amber-50);border-color:var(--amber);color:#8A5A00}
.mtbl-quick{display:flex;gap:6px;flex-wrap:wrap}
.mtbl-qf{font-family:inherit;font-size:.78rem;font-weight:600;padding:6px 11px;border-radius:999px;
  border:1px solid var(--line-2);background:var(--panel);color:var(--t2);cursor:pointer;white-space:nowrap}
.mtbl-qf:hover{background:var(--panel-2)}
.mtbl-qf.on{background:var(--ink);border-color:var(--ink);color:#fff}
.mtbl-qf .n{opacity:.6;margin-left:5px;font-family:var(--fm);font-size:.72rem}

.mtbl-chip-s{font-size:.72rem;color:var(--t3);margin-top:3px}
/* Secondary currencies in a summary chip: small, wrapped, and clearly not the
   headline figure. Printing all seven at chip size made Revenue six lines tall. */
.mtbl-chip-x{display:block;font-family:var(--fm);font-size:.7rem;font-weight:500;color:var(--t3);
  margin-top:4px;line-height:1.45}

/* Sortable headers replace a "Sort:" select plus a direction button. */
.mtbl thead th[data-sort]{cursor:pointer;user-select:none}
.mtbl thead th[data-sort]:hover{color:var(--t2)}
.mtbl thead th .ar{opacity:.35;margin-left:3px;font-size:.8em}
.mtbl thead th.sorted .ar{opacity:1;color:var(--teal)}

/* EVERY currency, largest first, the rest stacked underneath in smaller type.
   The hover tip that used to hold them does not exist on a phone, so on touch
   the other currencies were invisible - the same defect the merchant Overview
   Revenue tile had. Kept small and tight so a five-currency merchant does not
   set the row height for the whole table. */
.mtbl-zero{color:var(--t4)}
.mtbl-ccys{margin-top:2px}
.mtbl-ccy{font-size:.72rem;font-weight:500;color:var(--t3);line-height:1.4}
.mtbl-more{display:inline-block;margin-left:5px;font-size:.72rem;color:var(--t4);cursor:help;position:relative}
.mtbl-more:hover{color:var(--t2)}
.mtbl-tip{display:none;position:absolute;right:0;bottom:135%;background:var(--ink);color:#E2E8F0;
  font-family:var(--fm);font-size:.74rem;font-weight:400;padding:7px 10px;border-radius:8px;
  white-space:nowrap;text-align:right;z-index:60;box-shadow:0 4px 14px rgba(15,23,42,.18)}
.mtbl-more:hover .mtbl-tip{display:block}

/* Actions: the row opens the merchant, everything else lives behind the dots.
   Revealed on hover so 17 rows do not present 85 controls at once. */
.mtbl-act .btn{opacity:0;transition:opacity .12s}
.mtbl-row:hover .mtbl-act .btn,.mtbl-menu.open .btn{opacity:1}
.mtbl-dots{padding:5px 9px !important;font-size:.95rem !important;line-height:1}
.mtbl-menu{position:relative;display:inline-block}
.mtbl-pop{display:none;position:absolute;right:0;top:calc(100% + 4px);background:var(--panel);
  border:1px solid var(--line);border-radius:10px;box-shadow:0 4px 14px rgba(15,23,42,.14);
  z-index:70;min-width:172px;padding:4px;text-align:left}
.mtbl-menu.open .mtbl-pop{display:block}
.mtbl-pop a{display:block;padding:7px 11px;font-size:.82rem;color:var(--t2);border-radius:7px;
  text-decoration:none;cursor:pointer;white-space:nowrap}
.mtbl-pop a:hover{background:var(--panel-3);color:var(--ink)}
.mtbl-act{white-space:nowrap;text-align:right}
.mtbl-act .btn{padding:5px 10px;font-size:.78rem;margin-left:5px;border-radius:8px}
.mtbl-act .btn-edit{background:var(--teal-50);border:1px solid var(--teal-soft);color:var(--teal)}
.mtbl-act .btn-edit:hover{background:var(--teal-soft)}
.pager{display:flex;align-items:center;justify-content:space-between;margin-top:16px;flex-wrap:wrap;gap:10px}
.pager .pg-info{font-size:.82rem;color:var(--t3);font-family:var(--fm)}
.pager .pg-nav{display:flex;align-items:center;gap:8px}
.pager .pgbtn{padding:7px 14px;border:1px solid var(--line);border-radius:8px;background:var(--panel);color:var(--ink);font-size:.84rem;cursor:pointer;font-family:inherit}
.pager .pgbtn:hover:not(:disabled){background:var(--panel-2);border-color:var(--t4)}
.pager .pgbtn:disabled{opacity:.4;cursor:default}
.pager .pg-cur{font-size:.82rem;color:var(--t2);font-family:var(--fm);padding:0 4px}
@media(max-width:720px){.mtbl-act .btn{margin:2px 0 2px 4px}.mtbl-merch-nm,.mtbl-merch-sub{max-width:140px}}

/* ===== Edit-merchant modal: bordered sections ===== */
.bf-sec{border:1px solid var(--line);border-radius:12px;padding:16px 18px;margin-bottom:14px;background:var(--panel)}
.bf-sec-h{font-size:.7rem;letter-spacing:.07em;text-transform:uppercase;color:var(--t2);font-weight:700;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid var(--line)}
.bf-sec .submeta{margin-top:2px}
.bf-pod-fields{grid-template-columns:1fr 1fr;gap:14px;margin-bottom:12px}
.bf-pod-fields.bf-pod-crypto{grid-template-columns:1fr 1fr 2fr}
.bf-logo{display:flex;gap:16px;align-items:flex-start}
.bf-logo-prev{width:84px;height:84px;flex:none;border:1px dashed var(--line-2);border-radius:12px;display:flex;align-items:center;justify-content:center;background:var(--panel-2);overflow:hidden;color:var(--t3);font-size:.72rem;text-align:center;padding:6px}
.bf-logo-prev img{max-width:100%;max-height:100%;object-fit:contain}
.bf-logo-ctl{flex:1;display:flex;flex-direction:column;gap:8px;min-width:0}
.bf-logo-ctl input[type=url]{width:100%}
@media(max-width:640px){.bf-logo{flex-direction:column}}

/* ============================================================
   DoPay control panel
   ============================================================ */
.prov-dopay{cursor:pointer;transition:border-color .15s,box-shadow .15s}
.prov-dopay:hover{border-color:var(--teal);box-shadow:0 6px 22px -10px rgba(46,124,255,.35)}
.dp-overlay{position:fixed;inset:0;z-index:1200;background:rgba(15,23,42,.45);display:none;overflow-y:auto;padding:24px}
.dp-overlay.on{display:block}
.dp-sheet{max-width:1080px;margin:0 auto;background:var(--bg);border:1px solid var(--line);border-radius:16px;box-shadow:0 24px 70px -20px rgba(15,23,42,.5);overflow:hidden}
.dp-loading{padding:40px}
.dp-head{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;padding:18px 22px;background:var(--bg-2);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:2}
.dp-head h2{font-size:1.25rem}
.dp-sub{margin-top:7px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:.82rem;color:var(--t2)}
.dp-warn{color:var(--amber);background:#FEF3C7;border:1px solid #FDE68A;border-radius:6px;padding:1px 8px;font-size:.76rem}
.dp-body{padding:18px 22px;display:flex;flex-direction:column;gap:16px}
.dp-card{background:var(--bg-2);border:1px solid var(--line);border-radius:14px;overflow:hidden}
.dp-card-h{padding:14px 16px 10px}
.dp-card-h h3{font-size:1rem;margin:0}
.dp-card-h p{margin:5px 0 0;font-size:.82rem;color:var(--t2);max-width:80ch}
.dp-card-b{padding:6px 16px 16px}
.dp-tablewrap{overflow-x:auto;border:1px solid var(--line);border-radius:10px}
.dp-table{width:100%;border-collapse:collapse;font-size:.86rem}
.dp-table th{text-align:left;padding:9px 11px;font-size:.7rem;text-transform:uppercase;letter-spacing:.04em;color:var(--t3);background:var(--panel-2);border-bottom:1px solid var(--line);white-space:nowrap}
.dp-table td{padding:9px 11px;border-top:1px solid var(--line-soft);vertical-align:middle}
.dp-cellmeta{font-size:.7rem;color:var(--t4);font-family:ui-monospace,monospace;margin-top:2px}
.dp-fields{font-size:.78rem;color:var(--t2);max-width:220px}
.dp-sm{padding:.32em .8em;font-size:.8rem}
.dp-in{width:88px;padding:.4em .55em;border:1px solid var(--line-2);border-radius:8px;background:var(--bg-2);color:var(--ink);font-size:.84rem}
.dp-in-wide{width:160px}
.dp-link{color:var(--teal);font-weight:600;text-decoration:none}
.dp-link:hover{text-decoration:underline}
.dp-err{color:#DC2626;font-size:.8rem}
.dp-ts{color:var(--t4);font-size:.72rem;font-family:ui-monospace,monospace}
.dp-toggle{position:relative;width:40px;height:22px;border-radius:11px;border:1px solid var(--line-2);background:var(--panel-3);cursor:pointer;transition:.15s;padding:0;flex:none}
.dp-toggle.on{background:var(--teal);border-color:var(--teal)}
.dp-knob{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);transition:.15s}
.dp-toggle.on .dp-knob{left:20px}
.dp-spin{display:inline-block;width:13px;height:13px;border:2px solid var(--line-2);border-top-color:var(--teal);border-radius:50%;animation:dp-spin .7s linear infinite;vertical-align:middle}
@keyframes dp-spin{to{transform:rotate(360deg)}}
.dp-payrow{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.dp-kv{display:flex;justify-content:space-between;gap:14px;padding:7px 0;border-bottom:1px solid var(--line-soft);font-size:.86rem}
.dp-kv span:first-child{color:var(--t2)}
.dp-recent{margin-top:12px}
.dp-recent-h{font-size:.72rem;text-transform:uppercase;letter-spacing:.04em;color:var(--t3);margin-bottom:6px}
.dp-recent-row{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:.84rem;flex-wrap:wrap}
.dp-segwrap{display:inline-flex;border:1px solid var(--line-2);border-radius:9px;overflow:hidden}
.dp-seg{padding:.42em 1.1em;border:0;background:var(--bg-2);color:var(--t2);cursor:pointer;font-size:.84rem;text-transform:capitalize}
.dp-seg.on{background:var(--teal);color:#fff;font-weight:600}
@media(max-width:640px){.dp-overlay{padding:0}.dp-sheet{border-radius:0;min-height:100vh}}


/* ============================================================
   SETTLEMENTS + GLOBAL MOBILE TABLES
   Measured before writing: 15 of 22 views overflowed 390px, and
   the worst was settlements (464 elements wider than the viewport,
   2 tables). Transactions was the only clean view because it had
   already been converted to card rows. This does the same thing
   once, globally, instead of per view.
   ============================================================ */

/* -- settlements: exposure block -- */
.po-exposure{padding:0;overflow:hidden;margin-bottom:14px}
.po-sec-h{padding:12px 14px;border-bottom:1px solid var(--line);
  font-weight:800;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.po-sec-sub{font-weight:400;font-size:.76rem;color:var(--t3)}
.po-sec-b{padding:14px}
.po-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-bottom:14px}
.po-agebar{display:flex;gap:2px;height:10px;border-radius:5px;overflow:hidden;
  background:var(--line);margin-bottom:8px}
.po-agebar i{display:block;height:100%}
.po-legend{display:flex;gap:14px;flex-wrap:wrap;font-size:.72rem;color:var(--t2)}
.po-legend span{display:flex;align-items:center;gap:5px}
.po-legend b{width:8px;height:8px;border-radius:2px;display:block}
.po-legend em{font-style:normal;font-weight:700;color:var(--t1)}

/* -- settlements: filters -- */
.po-filters{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.po-filters input,.po-filters select{padding:9px 12px;border-radius:8px;font-size:.84rem;
  border:1px solid var(--line);background:var(--card,#fff);color:inherit;min-width:0}
.po-filters input{flex:1 1 240px;max-width:340px}
.po-filters select{flex:0 1 220px}
.po-clear{padding:9px 14px;border-radius:8px;border:1px solid var(--line);
  background:transparent;color:inherit;font-weight:700;font-size:.82rem;cursor:pointer}

/* -- settlements: age chips -- */
.po-age{display:inline-block;padding:2px 8px;border-radius:6px;font-size:.72rem;font-weight:700;white-space:nowrap}
.po-age-ok{background:#E6F8EE;color:#0E9C6F}
.po-age-warn{background:var(--amber-soft);color:var(--amber)}
.po-age-bad{background:#FBE7E5;color:#C8463B}
.po-age-none{background:rgba(128,128,128,.12);color:var(--t3)}
.po-due{color:#0E9C6F;font-weight:700}
.po-dim{color:var(--t3)}
.po-auto{font-size:.7rem;color:#2563EB}
.po-merch{font-weight:600}
.po-more{padding:12px 14px;border-top:1px solid var(--line);text-align:center}
.po-more button{padding:9px 18px;border-radius:8px;border:1px solid var(--line);
  background:transparent;color:inherit;font-weight:700;font-size:.84rem;cursor:pointer}
.po-more button:disabled{opacity:.6;cursor:default}

.po-table{width:100%;border-collapse:collapse;font-size:.88rem}
.po-table thead tr{text-align:left;opacity:.55;font-size:.72rem;text-transform:uppercase;letter-spacing:.04em}
.po-table th{padding:10px 12px;font-weight:700;white-space:nowrap}
.po-table td{padding:11px 12px}
.po-table tbody tr{border-top:1px solid var(--line)}
.po-table .num{text-align:right;font-variant-numeric:tabular-nums}
.po-batches tbody tr{cursor:pointer}
.po-batches tbody tr:hover{background:rgba(46,124,255,.05)}
/* PRESSED feedback. On a phone there is no hover, so a tap on a row gave no acknowledgement
   at all while the detail loaded - which is half of "nothing happens". */
.po-batches tbody tr:active{background:var(--teal-50)}

/* ============================================================
   SETTLEMENTS AS AN OPERATOR TO-DO LIST
   Due now / Needs fixing / Waiting for bank / Scheduled / Paid /
   Closed unpaid. One card per section, each with its own count and
   its own PER-CURRENCY totals. The sections are deliberately far
   apart: two money sections that touch read as one list, which is
   the thing this layout exists to stop.
   ============================================================ */

/* -- the jump strip: every section, its count, and a link that scopes the page -- */
.po-jumps{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 18px}
.po-jump{
  display:inline-flex;align-items:center;gap:8px;text-decoration:none;
  padding:9px 14px;border-radius:999px;border:1px solid var(--line-2);
  background:var(--panel);color:var(--ink-2);font-weight:700;font-size:.82rem;
  min-height:38px;transition:background .14s,border-color .14s,color .14s,transform .05s;
}
.po-jump b{font-size:.78rem;font-weight:800;color:var(--t3);font-variant-numeric:tabular-nums}
.po-jump:hover{background:var(--panel-3);border-color:var(--t4)}
.po-jump:active{transform:translateY(1px)}
.po-jump:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.po-jump.on{background:var(--blue-ink);border-color:var(--blue-ink);color:#fff}
.po-jump.on b{color:rgba(255,255,255,.82)}

/* -- the section cards. 26px between them, so two money sections never read as one -- */
.po-sects{display:flex;flex-direction:column;gap:26px;margin-bottom:26px}
.po-sect{padding:0;overflow:hidden}
.po-sect-h{align-items:center;gap:10px;row-gap:6px;padding:14px 16px}
/* The heading IS the toggle, full height, so a thumb hits it on a phone. */
.po-sect-t{
  appearance:none;background:transparent;border:0;font:inherit;cursor:pointer;
  display:inline-flex;align-items:center;gap:9px;padding:6px 8px;margin:-6px -8px;
  border-radius:9px;color:var(--ink);min-height:40px;
}
.po-sect-t:hover{background:var(--panel-3)}
.po-sect-t:focus-visible{outline:2px solid var(--blue);outline-offset:1px}
/* The caret is a rotated CSS border triangle, so no glyph appears in the markup and the
   open/closed state follows aria-expanded rather than a second source of truth. */
.po-sect-caret{width:0;height:0;flex:none;
  border-left:5px solid var(--t3);border-top:4px solid transparent;border-bottom:4px solid transparent;
  transition:transform .15s ease}
.po-sect-t[aria-expanded="true"] .po-sect-caret{transform:rotate(90deg)}
.po-sect-n{font-family:var(--fd);font-weight:800;font-size:1.02rem;letter-spacing:-.01em}
.po-sect-c{
  display:inline-block;min-width:24px;text-align:center;padding:2px 8px;border-radius:999px;
  background:var(--panel-3);color:var(--t2);font-size:.76rem;font-weight:800;
  font-variant-numeric:tabular-nums;
}
/* Per-currency totals, never summed across currencies. */
.po-sect-tots{display:flex;gap:16px;flex-wrap:wrap;margin-left:auto;align-items:baseline}
.po-sect-tot{display:inline-flex;align-items:baseline;gap:6px}
.po-sect-tot b{font-family:var(--fd);font-weight:800;font-size:.92rem;color:var(--ink);
  font-variant-numeric:tabular-nums}
.po-sect-tot em{font-style:normal;font-size:.74rem;color:var(--t3)}
.po-sect-none{padding:16px;color:var(--t3);font-size:.85rem}

/* The one section that is a job rather than a state gets the accent; the finished ones
   stay quiet, so the eye lands on what is actionable. */
.po-sect-due .po-sect-h{border-left:3px solid var(--blue-ink)}
.po-sect-fix .po-sect-h{border-left:3px solid var(--red)}
.po-sect-bank .po-sect-h{border-left:3px solid var(--amber)}
.po-sect-due .po-sect-c{background:rgba(14,86,230,.12);color:var(--blue-ink)}
.po-sect-fix .po-sect-c{background:var(--red-soft);color:var(--red)}
.po-sect.empty-sect .po-sect-n{color:var(--t3)}

/* ============================================================
   ONE ROW PER MERCHANT, CURRENCIES INSIDE IT.

   A section is now a list of MERCHANT lines, and a merchant line expands to that merchant's
   own batch table. The line has to work as a control on a phone - the width this screen is
   actually worked on - so it is a real button, full width, 52px tall, and its money stays
   on its own row rather than being squeezed beside a name.
   ============================================================ */
.po-mgrps{display:flex;flex-direction:column}
.po-mgrp{border-top:1px solid var(--line)}
.po-mgrp:first-child{border-top:0}
.po-mgrp.on{background:var(--panel-2)}
.po-mgrp-h{
  appearance:none;background:transparent;border:0;font:inherit;cursor:pointer;text-align:left;
  width:100%;display:flex;align-items:center;gap:12px;padding:13px 16px;min-height:52px;
  color:var(--ink);transition:background .12s;
}
.po-mgrp-h:hover{background:var(--panel-3)}
.po-mgrp-h:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}
/* Drawn, never typed: a glyph here would be a bullet character in the markup and would be
   read aloud on a control that already announces aria-expanded. */
.po-mgrp-caret{width:0;height:0;flex:none;
  border-left:5px solid var(--t3);border-top:4px solid transparent;border-bottom:4px solid transparent;
  transition:transform .15s ease}
.po-mgrp-h[aria-expanded="true"] .po-mgrp-caret{transform:rotate(90deg)}
.po-mgrp-id{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}
.po-mgrp-nm{font-family:var(--fd);font-weight:800;font-size:.95rem;letter-spacing:-.01em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.po-mgrp-sub{font-size:.76rem;color:var(--t3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Per-currency, never one number. tabular-nums so two currencies line up. */
.po-mgrp-tots{display:flex;gap:14px;flex-wrap:wrap;justify-content:flex-end;align-items:baseline;flex:none}
.po-mgrp-tot{display:inline-flex;align-items:baseline;gap:5px;white-space:nowrap}
.po-mgrp-tot b{font-family:var(--fd);font-weight:800;font-size:.9rem;color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.po-mgrp-tot em{font-style:normal;font-size:.72rem;color:var(--t3)}
/* The overall readiness of a merchant's settlements in this section, in one chip. */
.po-mchip{display:inline-block;flex:none;padding:3px 10px;border-radius:999px;
  font-size:.72rem;font-weight:800;white-space:nowrap}
.po-mchip.ok{background:var(--green-soft);color:var(--green)}
.po-mchip.warn{background:var(--amber-soft);color:var(--amber)}
.po-mchip.bad{background:var(--red-soft);color:var(--red)}
/* The reason that belongs to the MERCHANT, stated once instead of under every currency. */
/* The merchant's shared reason needs air above it: butted straight against the header
   button it reads as part of the name rather than as a statement about it. */
/* The reason block is measured against the header BUTTON above it, and padding inside
   this wrapper leaves the two boxes still touching. The gap has to be real, so it is a
   margin on the box that is actually compared. */
.po-mgrp-why{padding:0 16px 13px;margin-top:10px}
.po-mgrp-why .po-fixline{background:var(--red-soft);border-radius:10px;padding:10px 12px}
.po-mgrp .tbl-wrap{padding:0 0 6px}
/* The row a settlement link came back to, so the eye lands on it rather than hunting. */
tr.po-focus > td{background:rgba(14,86,230,.10)}
/* The merchant has a newer destination than this batch carries. Display only. */
.po-stale{color:var(--amber);font-weight:700}

/* -- PARTNER COMMISSION, same shape as a merchant section -- */
.po-whotabs{margin-bottom:14px}
.po-tab-n{display:inline-block;margin-left:6px;padding:1px 7px;border-radius:999px;
  background:var(--panel-3);color:var(--t2);font-size:.72rem;font-weight:800;
  font-variant-numeric:tabular-nums}
.po-tab.on .po-tab-n{background:rgba(255,255,255,.2);color:#fff}
.po-sect-partners .po-sect-h{border-left:3px solid var(--blue-ink)}
.po-pact{text-align:right;white-space:nowrap}

/* ============================================================
   COMING UP - the settlements the generator has not created yet.

   Same card, same heading, same merchant lines as every other section, so an operator
   reads it without learning a new shape. What differs is the BODY of an expanded merchant:
   there is no batch to put in a table, so each settlement is a small block of named money
   items. That also makes 390px work without a sideways scroll, which a nine-column table
   at this width cannot.

   The accent is the house blue-to-green line rather than a flat colour: Coming up is not a
   job yet and must not read as loud as Due now, but it is money and must not read as dead.
   ============================================================ */
.po-sect-coming .po-sect-h{border-left:3px solid transparent;
  border-image:var(--grad) 1}
.po-sect-coming .po-sect-c{background:var(--teal-50);color:var(--teal-ink)}

.po-cu-rows{display:flex;flex-direction:column;gap:var(--po-s2);padding:0 var(--po-s3) var(--po-s3)}
.po-cu-row{background:var(--panel);border:1px solid var(--line);border-radius:12px;
  padding:var(--po-s2) var(--po-s3)}
/* A closed period gets the accent edge: its figure is the final one. */
.po-cu-row.final{border-left:3px solid transparent;
  border-image:var(--grad) 1}
.po-cu-row.held{background:var(--amber-soft);border-color:var(--amber-50)}
.po-cu-h{display:flex;align-items:center;gap:var(--po-s2);flex-wrap:wrap}
/* The neutral chip. "Still collecting" is a real state, not an absence of one, so it reads
   as a chip like Final and Held rather than as loose text beside them. */
.po-cu-h .po-mchip:not(.ok):not(.warn):not(.bad){background:var(--panel-2);color:var(--t2);
  border:1px solid var(--line)}
/* The held chip sits ON the amber row, so the default amber-on-amber-soft chip disappears
   into its own background. Give it the panel behind it back. */
.po-cu-row.held .po-mchip.warn{background:#fff;border:1px solid var(--amber-50)}
.po-cu-d{display:flex;flex-direction:column;gap:2px;min-width:0}
.po-cu-d b{font-family:var(--fd);font-weight:800;font-size:.92rem;color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.po-cu-d em{font-style:normal;font-size:.74rem;color:var(--t3)}
.po-cu-meta{font-size:.74rem;color:var(--t3);margin-left:auto;white-space:nowrap}
.po-cu-when{font-size:.76rem;color:var(--t3);margin-top:6px}
/* The named parts of the figure. A grid rather than a table so it reflows to one column
   on a phone instead of scrolling sideways. */
.po-cu-items{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:6px var(--po-s3);margin-top:var(--po-s2);
  border-top:1px solid var(--line);padding-top:var(--po-s2)}
.po-cu-i{display:flex;align-items:baseline;justify-content:space-between;gap:10px;min-width:0}
.po-cu-k{font-size:.76rem;color:var(--t3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.po-cu-v{font-size:.82rem;color:var(--ink-2);font-variant-numeric:tabular-nums;white-space:nowrap}
.po-cu-i.tot{grid-column:1/-1;border-top:1px solid var(--line);padding-top:8px;margin-top:2px}
.po-cu-i.tot .po-cu-k{color:var(--ink);font-weight:700;overflow:visible}
.po-cu-i.tot .po-cu-v{font-family:var(--fd);font-weight:800;font-size:.92rem;color:var(--ink)}
.po-cu-est{margin-top:8px;font-size:.76rem;color:var(--amber);line-height:1.5}
.po-cu-note{padding:0 var(--po-s3) var(--po-s3);font-size:.78rem;color:var(--t3);line-height:1.55}

@media (max-width:760px){
  .po-cu-rows{padding:0 var(--po-s2) var(--po-s2)}
  .po-cu-row{padding:var(--po-s2)}
  .po-cu-meta{margin-left:0;flex:1 1 100%}
  /* One column at phone width: two money columns in 390px either overflow or crush the
     label to three characters. */
  .po-cu-items{grid-template-columns:1fr}
  .po-cu-note{padding:0 var(--po-s2) var(--po-s2)}
}

/* -- why a Needs-fixing batch is stuck, and the screen that fixes it -- */
.po-fixrow td{padding:0 12px 12px}
.po-fixnote{background:var(--red-soft);border-radius:10px;padding:10px 12px;
  display:flex;flex-direction:column;gap:8px}
.po-fixline{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  font-size:.84rem;color:var(--ink-2);line-height:1.5}
.po-fixgo{
  display:inline-block;text-decoration:none;background:var(--panel);border:1px solid var(--red);
  color:var(--red);font-weight:700;font-size:.78rem;padding:7px 13px;border-radius:8px;
  min-height:34px;line-height:20px;transition:background .14s,color .14s,transform .05s;
}
.po-fixgo:hover{background:var(--red);color:#fff}
.po-fixgo:active{transform:translateY(1px)}
.po-fixgo:focus-visible{outline:2px solid var(--red);outline-offset:2px}

/* -- the phone, which is where this screen is actually worked -- */
@media (max-width:760px){
  /* The jump chips WRAP onto several rows at this width, so the gap is doing two jobs:
     the space between chips on a row, and the space between rows. 7px between rows reads
     as one crowded block and the UI QA agent flags it as cramped. Row gap is set
     separately and larger so two rows of chips stay two rows. */
  .po-jumps{gap:7px;row-gap:12px;margin-bottom:16px}
  .po-jump{padding:9px 12px;font-size:.8rem;min-height:40px}
  .po-sects{gap:22px}
  .po-sect-h{flex-direction:column;align-items:flex-start;gap:8px}
  .po-sect-tots{margin-left:0;gap:14px}
  /* A MERCHANT LINE ON A PHONE. Name and chip on one row, money on its own row underneath:
     at 390 a name, a chip and two currency figures on one line either overflow sideways or
     crush the name to three characters. The control stays one tap target either way. */
  .po-mgrp-h{flex-wrap:wrap;row-gap:9px;padding:13px 14px;min-height:56px}
  .po-mgrp-id{flex:1 1 60%}
  .po-mgrp-tots{flex:1 1 100%;justify-content:flex-start;margin-left:17px;gap:16px}
  .po-mgrp-nm{white-space:normal}
  .po-mgrp-why{padding:0 14px 13px;margin-top:9px}
  .po-whotabs{margin-bottom:12px}
  .po-fixline{align-items:flex-start;flex-direction:column;gap:9px}
  .po-fixgo{width:100%;text-align:center}
}

/* ============================================================
   SETTLEMENTS SPACING, ON A SCALE

   The owner, on the live page: "the UI UX here is not so good everything too close to each
   other (section buttons and etc)". Statement and CSV were jammed under the row, the reason
   banner touched the row above it, the tabs and the filter row were crowded, and the jump
   strip sat on top of the first section.

   One scale, used everywhere below: 8 / 12 / 16 / 24. Nothing on this screen picks a
   number that is not on it, so the rhythm holds when a block is added later.

   The merchant group becomes a CARD: 16-20px of padding, 12px between groups, its own
   surface and border. Grouping by hairline alone made a list of rows; a merchant is a unit
   of work here, and it reads as one.
   ============================================================ */
:root{
  /* Named so the values below cannot drift apart one edit at a time. */
  --po-s1:8px; --po-s2:12px; --po-s3:16px; --po-s4:24px;
}

/* -- the page rhythm: tabs, filters, jump strip, sections -- */
.po-tabs{gap:var(--po-s1);margin:0 0 var(--po-s3)}
.po-tabs .po-tab{padding:10px 16px;min-height:42px}
.po-whotabs{margin:0 0 var(--po-s3)}
.po-filters{gap:var(--po-s2);margin-bottom:var(--po-s4)}
.po-jumps{gap:var(--po-s1);row-gap:var(--po-s2);margin:0 0 var(--po-s4)}
.po-runfilter{margin:0 0 var(--po-s3)}

/* 24px of air above a section heading, which is the top of a new block of work. */
.po-sects{gap:var(--po-s4);margin-bottom:var(--po-s4)}
.po-sect-h{padding:var(--po-s3) 20px;gap:var(--po-s2)}
.po-sect-b, .po-sect .po-mgrps{padding:var(--po-s2) var(--po-s2) var(--po-s3)}

/* -- A MERCHANT GROUP IS A CARD -- */
.po-mgrps{gap:var(--po-s2)}
.po-mgrp{
  border-top:0;
  border:1px solid var(--line);border-radius:12px;background:var(--bg-2);
  padding:var(--po-s1) 0 var(--po-s2);
  transition:border-color .14s,box-shadow .14s;
}
.po-mgrp:first-child{border-top:1px solid var(--line)}
.po-mgrp:hover{border-color:var(--line-2)}
.po-mgrp.on{background:var(--panel-2);border-color:var(--line-2);box-shadow:var(--sh-sm)}
.po-mgrp-h{padding:var(--po-s2) 20px;gap:var(--po-s2);border-radius:12px 12px 0 0}

/* -- THE REASON IS A LINE INSIDE THE CARD, not a full-width slab --
   A pink block running edge to edge read as an alert about the page rather than a note
   about one merchant, and it sat hard against the row above it. Inline, indented to the
   card's padding, with real air above. */
.po-mgrp-why{padding:0 20px;margin-top:var(--po-s2)}
.po-mgrp-why .po-fixnote, .po-mgrp-why.po-fixnote{
  background:transparent;border-radius:0;padding:0;gap:var(--po-s1);
}
.po-mgrp-why .po-fixline{
  background:transparent;border-left:3px solid var(--red);border-radius:0;
  padding:2px 0 2px var(--po-s2);gap:var(--po-s2);
}

/* -- THE ACTIONS, RIGHT-ALIGNED IN THE CARD ON DESKTOP --
   They were jammed under the row with 2px above them. On a wide screen they belong on the
   right, where the eye already is after the money figures. */
.po-mgrp-acts{gap:var(--po-s1);padding:0 20px;margin-top:var(--po-s2);justify-content:flex-end}
.po-mgrp .po-mgrp-why + .po-mgrp-acts{margin-top:var(--po-s2)}
.po-mgrp .tbl-wrap{padding:var(--po-s2) 0 0}

/* -- THE EXPOSURE KPI LABELS use the panel's small-caps sans, not a mono track --
   "OWED - VND" was set in the mono face with .11em of letter spacing, which reads as a
   code fragment beside money. Scoped to this block so the shared .kard is untouched
   elsewhere. */
.po-cards .kard .kl{
  font-family:var(--fd);font-size:.72rem;letter-spacing:.02em;font-weight:800;
  text-transform:uppercase;color:var(--t3);
}
.po-cards{gap:var(--po-s2);margin-bottom:var(--po-s3)}
.po-sec-h{padding:var(--po-s2) 20px;gap:var(--po-s1)}
.po-sec-b{padding:var(--po-s3) 20px}
.po-exposure{margin-bottom:var(--po-s4)}

@media (max-width:760px){
  /* ON A PHONE the actions go under the name in ONE row with 8px gaps, because there is no
     right-hand column to align to and a button that is 40px tall is the tap target. */
  .po-mgrp-acts{justify-content:flex-start;padding:0 var(--po-s3);gap:var(--po-s1)}
  .po-mgrp-h{padding:var(--po-s2) var(--po-s3)}
  .po-mgrp-why{padding:0 var(--po-s3);margin-top:var(--po-s2)}
  .po-sect-h{padding:var(--po-s2) var(--po-s3);gap:var(--po-s1)}
  .po-sect-b, .po-sect .po-mgrps{padding:var(--po-s1) var(--po-s1) var(--po-s2)}
  .po-sects{gap:20px}
  .po-tabs{margin-bottom:var(--po-s2)}
  .po-whotabs{margin-bottom:var(--po-s2)}
  .po-filters{margin-bottom:var(--po-s3)}
  .po-jumps{margin-bottom:20px}
  .po-sec-h,.po-sec-b{padding-left:var(--po-s3);padding-right:var(--po-s3)}
}

/* -- GLOBAL: any wide table scrolls inside its own box instead of stretching
   the page. .tbl-wrap is applied to new markup; the bare-table rules catch the
   views that were never wrapped. -- */
.tbl-wrap{width:100%;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}

@media (max-width:900px), (pointer:coarse) and (hover:none) and (max-width:1400px){
  /* Every view's own container must be allowed to shrink. Grid and flex children
     default to min-width:auto, so one wide table pushes the whole page wider -
     this is what made 15 views overflow. */
  .view, .view > *, .card, .panel{min-width:0;max-width:100%}
  .view table{max-width:100%}

  /* Tables that were not wrapped still must not widen the document. */
  .view .card > table, .view > table, .panel > table{display:block;overflow-x:auto;
    -webkit-overflow-scrolling:touch;white-space:nowrap}

  /* Settlements becomes card rows: label each cell, amount and age lead. */
  .po-table{display:block;font-size:.9rem}
  .po-table thead{display:none}
  .po-table tbody,.po-table tr,.po-table td{display:block;width:auto}
  .po-table tbody tr{border:1px solid var(--line);border-radius:10px;
    padding:10px 12px;margin-bottom:8px;background:var(--card)}
  .po-table td{padding:3px 0;display:flex;justify-content:space-between;gap:12px;align-items:baseline}
  .po-table td::before{content:attr(data-l);font-size:.7rem;text-transform:uppercase;
    letter-spacing:.05em;color:var(--t3);font-weight:700;flex:0 0 auto}
  .po-table td.num{text-align:right}
  /* amount first and largest - it is the number the operator is scanning for */
  .po-table td[data-l="Amount"]{order:-2;font-size:1.05rem;font-weight:800;padding-bottom:6px}
  .po-table td[data-l="Age"]{order:-1;padding-bottom:8px}
  .po-table td[data-l="Amount"]::before{align-self:center}

  .po-filters input,.po-filters select{flex:1 1 100%;max-width:none}
  .po-cards{grid-template-columns:1fr 1fr}
  .po-legend{gap:8px 12px;font-size:.68rem}

  /* The settlement TOTAL is a two-column statement, not a list of records: the card-row
     layout above turned every line into its own boxed card, right-aligned the label and
     clipped the reserve line ("10% until Sat, 27 Mar 2") at the edge. Label left and
     allowed to wrap, amount right and never wrapped. */
  .po-table.sd-totals{display:table;width:100%;font-size:.9rem}
  .po-table.sd-totals tbody{display:table-row-group}
  .po-table.sd-totals tbody tr{display:table-row;border:0;border-radius:0;padding:0;margin:0;background:none}
  .po-table.sd-totals td{display:table-cell;padding:9px 0;white-space:normal;vertical-align:baseline;
    border-bottom:1px solid var(--line)}
  .po-table.sd-totals td::before{content:none}
  .po-table.sd-totals td:first-child{padding-right:12px;color:var(--t2);text-align:left}
  .po-table.sd-totals td.num{white-space:nowrap;text-align:right}
  .po-table.sd-totals .sd-strong td{border-bottom:0;color:var(--ink);font-size:1rem}
}

@media (max-width:520px), (pointer:coarse) and (hover:none) and (max-width:560px){
  .po-cards{grid-template-columns:1fr}
}

/* -- Segmented control rows and button groups.
   Measured at 390px after the settlements pass: routing (418), risk (413) and
   settings (431) still pushed the document wider. None of it was tables - it
   was flex rows of buttons that could not wrap, so the last button's right edge
   landed past the viewport. Fixed generically: any inline control row wraps and
   its children may shrink. -- */
@media (max-width:900px), (pointer:coarse) and (hover:none) and (max-width:1400px){
  .view .rt-seg, .view .rk-modes, .view .seg, .view .segmented, .view .btn-row,
  .view .toolbar, .view .filters, .view .tabs{
    flex-wrap:wrap;max-width:100%;min-width:0}
  .view .rt-seg > *, .view .rk-modes > *, .view .seg > *, .view .segmented > *,
  .view .btn-row > *, .view .toolbar > *, .view .filters > *, .view .tabs > *{
    min-width:0;max-width:100%}

  /* Any flex row inside a view may wrap rather than force the page wider.
     The earlier rule only matched `.card > div[style*=flex]`, which missed the
     inline-styled rows inside .rt-banner (routing) and the .rk-mode button row
     (risk) - both measured still overflowing after that pass.

     wrap alone is NOT enough, and assuming it was made providers WORSE (390 ->
     572): a wrapped flex row still cannot shrink below its content, because flex
     items default to min-width:auto. Both the row and its items need min-width:0.
     Rows that must stay on one line opt out with .nowrap. */
  .view div[style*="display:flex"]:not(.nowrap),
  .view .rt-banner, .view .rt-banner > div,
  /* .rk-banner (risk) is a class-styled flex row with wrap:nowrap - not inline
     styled and no -mode suffix, so none of the selectors above reached it. It
     held .rk-modes at x=180 and left the view at 413px through three attempts. */
  .view [class$="-banner"], .view [class*="-banner "]{flex-wrap:wrap;min-width:0;max-width:100%}
  .view [class$="-banner"] > *, .view [class*="-banner "] > *{min-width:0;max-width:100%}
  .view div[style*="display:flex"]:not(.nowrap) > *{min-width:0;max-width:100%}
  .view .rt-banner > div > *, .view [class*="-mode"], .view [class*="-modes"] > *{
    min-width:0;max-width:100%}
  .view [class*="-modes"]{flex-wrap:wrap;min-width:0;max-width:100%}

  /* Long unbroken strings (references, hashes, URLs, emails) are a common
     silent widener - they cannot break without help. */
  .view td, .view th, .view .mono, .view code{overflow-wrap:anywhere}

  /* Inputs and selects default to a size attribute width that ignores the
     container; settings was 431px because of exactly this. */
  .view input, .view select, .view textarea{max-width:100%;min-width:0}
}

/* ===== Settlements: tabs + settlement detail =====
   The page was one flat list of batches with no way into a single settlement. Tabs put
   the settlement-level view first (what we owe, to whom, for which period) and keep the
   per-transaction list one click away. Tokens only - no new colours. */
.po-tabs{display:flex;gap:6px;margin:0 0 14px;border-bottom:1px solid var(--line-2);padding-bottom:0}
.po-tabs .po-tab{appearance:none;background:transparent;border:0;border-bottom:2px solid transparent;
  padding:9px 14px;font:inherit;font-weight:600;font-size:.86rem;color:var(--ink-2);cursor:pointer;
  border-radius:8px 8px 0 0;transition:color .15s,border-color .15s,background .15s}
.po-tabs .po-tab:hover{color:var(--ink);background:var(--panel-3)}
.po-tabs .po-tab.on{color:var(--teal);border-bottom-color:var(--teal)}

.sd-head{display:flex;align-items:flex-start;gap:14px;margin-bottom:16px;flex-wrap:wrap}
.sd-head .po-back{appearance:none;background:transparent;border:1px solid var(--line-2);color:var(--ink-2);
  padding:7px 12px;border-radius:9px;font:inherit;font-size:.82rem;font-weight:600;cursor:pointer}
.sd-head .po-back:hover{background:var(--panel-3);color:var(--ink)}
.sd-title h3{margin:0;font-size:1.12rem;line-height:1.3}
.sd-title .sd-sub{display:block;margin-top:3px;color:var(--ink-2);font-size:.8rem}
.sd-card{margin-bottom:14px}
.sd-totals td{padding:10px 14px}
.sd-totals .sd-strong td{font-weight:800;font-size:1.02rem;border-top:2px solid var(--line-2)}
.sd-meta{display:flex;flex-wrap:wrap;gap:18px;padding:14px}
.sd-meta>div{min-width:150px;display:flex;flex-direction:column;gap:3px}
.sd-meta .k{font-size:.66rem;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-2)}
.sd-meta .v{font-weight:600;font-size:.86rem}
.sd-actions{display:flex;flex-wrap:wrap;gap:9px;align-items:center;padding:14px}
.sd-note{width:100%;font-size:.8rem;color:var(--ink-2);min-height:1em}
.sd-note.ok{color:var(--teal);font-weight:600}
.sd-note.err{color:#B91C1C;font-weight:600}
.po-link{appearance:none;background:transparent;border:0;padding:0;font:inherit;font-weight:600;
  color:var(--teal);cursor:pointer;text-decoration:underline}

/* ---- controls that became real links ------------------------------------
   Every screen these open has its own URL now, so the controls are <a href>
   rather than <button>: that is what makes long-press and open-in-new-tab work
   on a phone. They must keep looking exactly as they did, so the anchor
   defaults (underline, visited colour, inline layout) are cancelled here
   rather than by restyling each one. */
a.po-rowpay,a.po-back,a.po-rowlink,a.mp-rl,a.pf-link,.mtbl-act a.btn-edit{text-decoration:none}
a.po-rowpay,a.po-back,.mtbl-act a.btn-edit{display:inline-block;text-align:center}
a.po-rowlink,a.pf-link{color:inherit}
a.po-rowlink:hover,a.pf-link:hover{text-decoration:underline}
a.mp-rl{box-sizing:border-box;text-decoration:none}

/* ============================================================================
   THE SETTLE ACTION AREA (.sd-settle) and THE PAY SHEET (.pay-*)

   A settlement detail used to be read only, so an operator could open a batch and find
   nothing to press. This is the primary action area: it sits directly under the header,
   states the one figure, and offers the one action that status and readiness allow.

   Phone first. At 390px the buttons are full width and stacked, nothing is under 11px, and
   the sheet is the full-screen .oz-sheet the onboarding windows already use, so its footer
   buttons stay reachable without scrolling a long form.
   ============================================================================ */
.sd-settle{padding:0;overflow:hidden;border-left:3px solid var(--line-2)}
.sd-settle.ready{border-left-color:var(--teal)}
.sd-settle.blocked{border-left-color:var(--amber)}
.sd-settle.done{border-left-color:var(--green)}
.sd-settle.bad{border-left-color:var(--red)}
.sd-st-h{
  font-family:var(--fd);font-size:.72rem;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;color:var(--ink-2);padding:12px 16px 0;
}
.sd-settle.ready .sd-st-h{color:var(--teal)}
.sd-settle.blocked .sd-st-h{color:var(--amber)}
.sd-settle.done .sd-st-h{color:var(--green)}
.sd-settle.bad .sd-st-h{color:var(--red)}
.sd-st-b{padding:8px 16px 16px}
.sd-st-amt{font-family:var(--fd);font-size:1.7rem;font-weight:800;letter-spacing:-.02em;color:var(--ink);line-height:1.15}
.sd-st-say{margin:6px 0 0;font-size:.88rem;line-height:1.5;color:var(--ink-2)}
.sd-st-say .mono{font-family:var(--fm);font-size:.82rem}
.sd-st-note{margin:10px 0 0;font-size:.8rem;line-height:1.5;color:var(--t3)}
.sd-st-why{margin:8px 0 0;padding-left:18px;font-size:.88rem;line-height:1.6;color:var(--ink-2)}
.sd-st-why li{margin-bottom:6px}
.sd-fix{
  appearance:none;background:var(--teal-50);border:1px solid var(--teal-soft);color:var(--teal);
  font:inherit;font-size:.78rem;font-weight:700;padding:3px 9px;border-radius:8px;cursor:pointer;
  transition:background .14s,border-color .14s;
}
.sd-fix:hover{background:var(--teal-soft)}
.sd-fix:active{background:var(--teal-soft);transform:translateY(1px)}
.sd-fix:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
.sd-st-row{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-top:14px}
.sd-more{position:relative;margin-left:auto}
/* The menu sits IN the flow, not absolutely: the settle card clips its overflow (for the
   coloured left rail), so an absolute menu opened below the last row was cut off and the
   More press looked dead. In flow, the card grows to show it. */
.sd-more-m{
  position:static;margin-top:6px;min-width:200px;
  background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:6px;
  box-shadow:0 10px 26px -12px rgba(12,19,34,.4);
}
.sd-more-i{
  display:block;width:100%;text-align:left;appearance:none;background:transparent;border:0;
  font:inherit;font-size:.86rem;font-weight:600;color:var(--red);padding:9px 10px;border-radius:8px;cursor:pointer;
}
.sd-more-i:hover{background:var(--red-soft)}
.sd-more-i:focus-visible{outline:2px solid var(--red);outline-offset:-2px}

/* ---- the Pay button on a list row ---- */
.po-rowpay{
  display:inline-block;appearance:none;background:var(--teal);border:1px solid var(--teal);
  color:#fff;font:inherit;font-size:.76rem;font-weight:700;padding:4px 11px;border-radius:8px;cursor:pointer;
  transition:background .14s,box-shadow .14s,transform .05s;
}
/* The chip and the money action share the status cell and WRAP onto two lines in a narrow
   column, so the gap has to come from the cell rather than from a left margin on the
   button: a horizontal margin leaves them touching vertically. The row gap is deliberately
   larger than the column gap - when they wrap, the button sits under the chip and the two
   need to read as separate controls rather than one stacked block. */
.po-status-cell{display:flex;flex-wrap:wrap;align-items:center;gap:12px 8px}
.po-rowpay:hover{background:var(--blue-ink,#0B45B8);border-color:var(--blue-ink,#0B45B8)}
.po-rowpay:active{transform:translateY(1px)}
.po-rowpay:focus-visible{outline:2px solid var(--teal);outline-offset:2px}

/* ---- the sheet ---- */
.pay-grp{margin-bottom:16px}
.pay-grp:last-child{margin-bottom:0}
.pay-grp-h{
  font-family:var(--fd);font-size:.74rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
  color:var(--t3);margin-bottom:8px;
}
.pay-amt{font-family:var(--fd);font-size:2.1rem;font-weight:800;letter-spacing:-.025em;color:var(--ink);line-height:1.1}
.pay-amt-s{font-size:.86rem;color:var(--ink-2);margin-top:2px}
/* The arithmetic line under the big figure. Tabular numerals so the terms line up, and it
   wraps rather than overflowing the sheet on a phone. */
.pay-amt-b{font-size:.78rem;color:var(--ink-2);margin-top:6px;line-height:1.5;
  font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.pay-say{margin:0;font-size:.88rem;line-height:1.55;color:var(--ink-2)}
.pay-say.strong{font-weight:600;color:var(--ink);background:var(--teal-50);border:1px solid var(--teal-soft);
  border-radius:10px;padding:11px 13px}
.pay-dim{margin:6px 0 0;font-size:.82rem;color:var(--t3)}
.pay-dl{display:grid;grid-template-columns:minmax(0,9rem) minmax(0,1fr);gap:8px 14px;margin:10px 0 0;font-size:.86rem}
.pay-dl dt{color:var(--t3);font-weight:500;min-width:0;word-break:break-word}
.pay-dl dd{margin:0;display:flex;align-items:center;gap:8px;min-width:0;color:var(--ink);font-weight:600}
.pay-dl dd .mono{font-family:var(--fm);font-size:.82rem;word-break:break-all;min-width:0}
.pay-copy{
  flex:0 0 auto;appearance:none;background:var(--panel-3);border:1px solid var(--line);color:var(--ink-2);
  font:inherit;font-size:.74rem;font-weight:700;padding:3px 9px;border-radius:7px;cursor:pointer;transition:.14s;
}
.pay-copy:hover{background:var(--teal-50);border-color:var(--teal-soft);color:var(--teal)}
.pay-copy:active{transform:translateY(1px)}
.pay-copy:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
.pay-copy.wide{display:block;margin-top:10px;width:100%;padding:8px 10px;font-size:.8rem}
/* ---- THE FULL DESTINATION, ON THE CHECK AND CONFIRM STEPS ----
   The owner's report: the masked "...88B0" is not something anyone can check an address
   against or retype, and the wallet has to be on the step the PIN is entered on too. A
   wallet address is 42 characters of hex and an IBAN can be 34, so the value wraps rather
   than widening the sheet: anywhere, not just at spaces, because a hex string has none.
   The rail is 390px on a phone and the sheet must never scroll sideways on a money screen. */
.pay-dl-full dd.long{display:block}
.pay-dl-full dd.long .mono{display:block;word-break:break-all;overflow-wrap:anywhere;
  background:var(--panel-3);border:1px solid var(--line);border-radius:8px;
  padding:7px 9px;line-height:1.5;max-width:100%}
.pay-dl-full dd.long .pay-copy{margin-top:6px}
/* The last four characters, kept highlighted so the string an operator already recognises
   from every other screen is still findable inside the full one. It adds no characters:
   reading the element's text back gives the stored address exactly. */
.pay-dest-4{font-weight:800;color:var(--teal);background:var(--teal-50);border-radius:4px;padding:0 2px}
.pay-dest-grp .pay-say{word-break:break-word;overflow-wrap:anywhere}
.pay-blocked{
  font-size:.88rem;line-height:1.55;color:#6E4708;background:var(--amber-soft);
  border:1px solid #F0DCB4;border-radius:10px;padding:12px 14px;
}
.pay-blocked b{display:block;margin-bottom:4px;color:#6E4708}
/* The API's own words, INSIDE the sheet and above the footer, so a refused settlement is
   read where the decision was made rather than behind a modal that closed. */
.pay-err{
  flex:none;margin:0;padding:12px 20px;font-size:.86rem;font-weight:600;line-height:1.5;
  color:#8E1B14;background:var(--red-soft);border-top:1px solid #F2C9C4;
}

/* ---- STATUS CHIPS, one vocabulary ----
   Due now / Sent / Paid / Rejected / Needs fixing. The colour carries the same meaning the
   word does, so the chip is readable without relying on colour alone. */
.po-chip{
  display:inline-block;padding:3px 10px;border-radius:999px;white-space:nowrap;
  font-family:var(--fd);font-size:.72rem;font-weight:700;letter-spacing:.01em;
  border:1px solid transparent;
}
.po-chip-new{background:#E8F0FE;color:var(--blue,#0E56E6);border-color:#CBDCFB}
.po-chip-processing{background:var(--teal-50);color:#0B8C81;border-color:var(--teal-soft)}
.po-chip-paid{background:#E6F8EE;color:#0E9C6F;border-color:#BEEBD5}
.po-chip-rejected{background:#FBE7E5;color:#C8463B;border-color:#F2C9C4}
.po-chip-failed{background:var(--amber-soft);color:#6E4708;border-color:#F0DCB4}
.po-chip-unknown{background:var(--panel-3);color:var(--t3);border-color:var(--line)}

/* ---- THE SUMMARY AN OPERATOR SIGNS AGAINST ----
   Short labelled rows instead of three paragraphs. The label column is fixed so the eye
   reads straight down the values, and the values are tabular so two amounts line up. */
/* The key column sizes to the LONGEST label rather than to a guessed rem width: at 8.5rem
   "CONVERSION REF" and "BANK REFERENCE" broke over two lines on a phone, and a fixed wider
   guess just steals room from the values. max-content measures them. */
/* The key column is sized by its own longest label, with no zero floor: minmax(0,...)
   let the grid shrink it again and "CONVERSION REF" went back to two lines on a phone.
   The labels are also allowed to lose their tracking here rather than their line. */
.pay-kv{display:grid;grid-template-columns:max-content minmax(0,1fr);
  gap:0 12px;margin:0;font-size:.87rem}
/* Each pair is its own ruled line, label left in small muted uppercase, value hard right -
   the same statement rhythm the settlement card uses, so an operator reading the confirm
   list is reading a familiar shape rather than a second style of key/value block. */
.pay-kv dt{color:var(--t3);font-weight:700;font-size:.72rem;letter-spacing:.02em;
  white-space:nowrap;
  text-transform:uppercase;min-width:0;overflow-wrap:anywhere;align-self:center;
  padding:9px 0;border-bottom:1px solid var(--line)}
.pay-kv dd{margin:0;min-width:0;color:var(--ink);font-weight:600;overflow-wrap:anywhere;
  font-variant-numeric:tabular-nums;text-align:right;padding:9px 0;
  border-bottom:1px solid var(--line)}
.pay-kv dt:last-of-type,.pay-kv dd:last-of-type{border-bottom:0}
.pay-kv dd.strong{font-weight:800;color:var(--ink)}
/* The full sentence still renders under the summary, quieter, so nothing that was stated
   before is lost and a reader who wants the prose has it. */
.pay-fine{margin-top:11px;font-size:.79rem;color:var(--t3);line-height:1.55}

/* ---- THE CONVERSION STEP ---- */
.pay-seg-row{display:flex;gap:8px;margin:10px 0 12px;flex-wrap:wrap}
.pay-seg{
  appearance:none;flex:1 1 auto;background:var(--panel-3);border:1px solid var(--line);color:var(--ink-2);
  font:inherit;font-size:.78rem;font-weight:700;padding:8px 11px;border-radius:9px;cursor:pointer;
  transition:background .14s,border-color .14s,color .14s;
}
@media(hover:hover){.pay-seg:not(.on):hover{background:var(--teal-50);border-color:var(--teal-soft)}}
.pay-seg.on{background:var(--blue,#0E56E6);border-color:var(--blue,#0E56E6);color:#fff}
.pay-seg:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
/* The input with its units attached, so the field reads as one statement: 1 EUR = [ ] USDT */
.pay-fx-in{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pay-fx-in input{flex:1 1 8rem;min-width:0}
.pay-fx-pre,.pay-fx-post{font-size:.82rem;font-weight:700;color:var(--t3);white-space:nowrap}
/* The derived side, live. This is the line the confirmation, the row, the statement and
   the merchant email all carry, so it is shown at full weight before anything is signed. */
.pay-fx-out{margin-top:12px;background:var(--teal-50);border:1px solid var(--teal-soft);
  border-radius:10px;padding:14px 15px}
/* The asset figure leads at display size - it is the number being signed for; the full
   conversion sentence sits under it as the supporting line, not above it as the headline. */
.pay-fx-k{font-size:.7rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--teal)}
.pay-fx-big{margin-top:3px;font-family:var(--fd);font-size:1.6rem;font-weight:800;
  letter-spacing:-.025em;color:var(--ink);line-height:1.12;font-variant-numeric:tabular-nums}
.pay-fx-big em{font-style:normal;font-size:.82rem;font-weight:700;color:var(--ink-2);margin-left:5px}
.pay-fx-line{margin-top:5px;font-size:.82rem;font-weight:600;color:var(--ink-2);
  line-height:1.4;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.pay-fx-line.dim{margin-top:0;font-weight:600;font-size:.85rem;color:var(--t3)}
.pay-fx-sub{margin-top:4px;font-size:.76rem;color:var(--ink-2);overflow-wrap:anywhere;
  font-variant-numeric:tabular-nums}
.pay-fx-ref{margin-top:8px;font-size:.76rem;color:var(--t3);font-variant-numeric:tabular-nums}
.pay-fx-ref.dim{color:var(--t3);opacity:.85}
/* WARN, never block: amber, not red, and the Next button stays enabled behind it. */
.pay-fx-warn{margin-top:8px;font-size:.8rem;line-height:1.5;color:#6E4708;
  background:var(--amber-soft);border:1px solid #F0DCB4;border-radius:9px;padding:9px 11px}
.pay-fx-bad{margin-top:8px;font-size:.8rem;line-height:1.5;color:#8E1B14;
  background:var(--red-soft);border:1px solid #F2C9C4;border-radius:9px;padding:9px 11px}

/* ---- WHAT ACTUALLY LEFT, on a row and in the detail ---- */
.po-fx{color:var(--teal);font-weight:700;font-variant-numeric:tabular-nums}
.po-fx .po-fx-r{color:var(--t3);font-weight:400}
.po-mgrp-fx b{color:var(--teal)}

/* ===== THE SETTLEMENT STATEMENT CARD =====
   One card, the panel sans face throughout, money in tabular figures. It replaces a
   two-column monospace table whose letter-spaced labels, mono amounts and mono notes
   floating beside the figures read as a debug dump rather than a statement. */
.sdc{padding:0;overflow:hidden}
.sdc-h{padding:16px 18px 14px;border-bottom:1px solid var(--line)}
.sdc-h-t{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.sdc-nm{font-family:var(--fd);font-weight:800;font-size:1.12rem;letter-spacing:-.015em;color:var(--ink)}
.sdc-per{margin-top:5px;font-size:.86rem;color:var(--ink-2);font-variant-numeric:tabular-nums}
.sdc-ccy{color:var(--t3);font-weight:600;margin-left:4px}
.sdc-when{margin-top:7px;font-size:.78rem;color:var(--t3);display:flex;align-items:center;
  gap:7px;flex-wrap:wrap}
.sdc-lines{padding:6px 18px}
/* REFUNDS THIS CYCLE, itemised under the group line. Each entry names the order and the sale
   date, because a refund is deducted in the cycle it happens in and its sale usually belongs
   to an earlier settlement. docs/settlement-refund-cycle-rule.md */
.sdc-rf{padding:2px 0 8px 0;border-left:2px solid var(--amber,#F59E0B);margin:0 0 6px 10px;padding-left:10px}
.sdc-rf-l{margin:4px 0}
.sdc-rf-k{font-size:.78rem;color:var(--ink,#0E1A33)}
.sdc-rf-v{float:right;font-size:.78rem;font-variant-numeric:tabular-nums}
.sdc-rf-s{clear:both;font-size:.68rem;color:var(--muted,#64748B);line-height:1.5}
.sdc-line{display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  padding:11px 0;border-bottom:1px solid var(--line)}
.sdc-line:last-child{border-bottom:0}
.sdc-k{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--t3);flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
/* The value stack takes exactly the width its number needs and never squeezes the label:
   at 390 a flexible value column clipped "ADJUSTMENTS" to "ADJUSTMENT". */
.sdc-vs{display:flex;flex-direction:column;align-items:flex-end;gap:2px;text-align:right;
  flex:0 0 auto;max-width:62%;min-width:0}
.sdc-v{font-size:.98rem;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;
  white-space:nowrap}
.sdc-line-neg .sdc-v{color:var(--red)}
.sdc-sub{font-size:.72rem;color:var(--t3);line-height:1.4;font-weight:400}
.sdc-total{display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  padding:15px 18px;border-top:2px solid var(--line-2);background:var(--panel-2)}
.sdc-total-k{font-size:.78rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-2)}
.sdc-total-v{font-family:var(--fd);font-size:1.32rem;font-weight:800;letter-spacing:-.02em;
  color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.sdc-total-v em{font-style:normal;font-size:.72rem;font-weight:600;color:var(--t3);margin-left:3px}
/* The converted payout is the figure a merchant matches against their wallet, so it gets
   its own highlighted block rather than a grey sub-line under a table row. */
.sdc-paid{padding:14px 18px;background:var(--teal-soft);border-top:1px solid var(--line)}
.sdc-paid-k{font-size:.7rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--teal)}
.sdc-paid-v{margin-top:4px;font-family:var(--fd);font-size:1.5rem;font-weight:800;
  letter-spacing:-.02em;color:var(--ink);font-variant-numeric:tabular-nums;line-height:1.15}
.sdc-paid-v em{font-style:normal;font-size:.8rem;font-weight:700;color:var(--ink-2);margin-left:4px}
.sdc-paid-r{margin-top:3px;font-size:.78rem;color:var(--ink-2);font-variant-numeric:tabular-nums}
.sdc-paid-s{margin-top:3px;font-size:.74rem;color:var(--t3)}
.sdc-row{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:13px 18px;border-top:1px solid var(--line)}
.sdc-row-k{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--t3)}
.sdc-row-v{font-size:.9rem;font-weight:600;color:var(--ink);text-align:right;min-width:0}

/* The destination, as a value plus a network chip - never "Bank -". */
.po-dest{display:inline-flex;align-items:center;gap:7px;flex-wrap:wrap;justify-content:flex-end}
.po-dest-a{font-variant-numeric:tabular-nums;color:var(--ink-2);font-weight:600}
.po-dest-none{color:var(--t3);font-weight:400;font-style:normal}
.po-net{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;
  background:var(--panel-2);border:1px solid var(--line-2);color:var(--t2);
  font-size:.7rem;font-weight:700;letter-spacing:.04em}
/* An empty money cell reads 0.00, quietly - never a lone dash pretending to be a value. */
.po-zero{color:var(--t3);font-weight:500}
/* The range may wrap between its two dates; neither date may break inside itself. */
.po-dates{white-space:normal}
.po-dates > span{white-space:nowrap}

@media(max-width:640px){
  .sdc-h,.sdc-lines,.sdc-total,.sdc-paid,.sdc-row{padding-left:14px;padding-right:14px}
  .sdc-nm{font-size:1.02rem}
  .sdc-total-v{font-size:1.18rem}
  .sdc-paid-v{font-size:1.34rem}
}

@media(max-width:640px){
  .sd-actions .btn{flex:1 1 auto;justify-content:center}
  .sd-meta{gap:12px}
  .sd-st-amt{font-size:1.5rem}
  .sd-st-row{gap:9px}
  .sd-st-row .btn{flex:1 1 100%;justify-content:center}
  .sd-more{margin-left:0;flex:1 1 100%}
  .sd-more .btn{width:100%}
  .sd-more-m{min-width:0}
  .sd-st-say,.sd-st-why{font-size:.82rem}
  .sd-st-note,.sd-st-h{font-size:.7rem}
  .pay-amt{font-size:1.8rem}
  .pay-say,.pay-dl{font-size:.82rem}
  .pay-dim,.pay-grp-h,.pay-copy{font-size:.7rem}
  .pay-dl{grid-template-columns:1fr;gap:2px}
  .pay-dl dd{margin-bottom:8px}
  /* The key/value summary keeps its two columns on a phone but narrows the label: a
     stacked label/value pair doubles the height of the one block an operator reads before
     signing, and the labels here are one or two short words. */
  .pay-kv{grid-template-columns:minmax(0,5.6rem) minmax(0,1fr);gap:6px 10px;font-size:.81rem}
  .pay-fine{font-size:.75rem}
  .pay-seg{font-size:.74rem;padding:8px 9px}
  .pay-fx-line{font-size:.88rem}
  .pay-fx-sub,.pay-fx-ref,.pay-fx-warn,.pay-fx-bad{font-size:.74rem}
  .pay-err{padding:11px 15px;font-size:.78rem}
}


/* ---- Settlement runs: what leaves the bank on one date, across all merchants ---- */
.po-runs tbody tr{cursor:pointer}
.po-runs tbody tr:hover{background:var(--teal-50)}
.po-prog{height:6px;border-radius:999px;background:var(--line-soft);overflow:hidden;min-width:90px}
.po-prog>span{display:block;height:100%;background:var(--teal);border-radius:999px}
.po-prog-t{font-size:11px;color:var(--t3);margin-top:3px;display:inline-block}
.po-chip{display:inline-block;font-size:11px;font-weight:600;padding:.12em .5em;border-radius:999px;
  background:var(--line-soft);color:var(--t2)}
.po-chip.bad{background:var(--red-soft);color:var(--red)}
.po-muted{color:var(--t3)}
/* ---- THE ACTION ON A MERCHANT OR PARTNER LINE ----------------------------------------
   The owner could not find the settle button because grouping put every Pay inside the
   expanded currency rows. This strip sits between the group header and its (collapsible)
   table, so the money action is on screen at 390 without expanding anything. It is OUTSIDE
   the header button on purpose: a button inside a button is not a control. */
.po-mgrp-acts{display:flex;flex-wrap:wrap;align-items:center;gap:9px;
  padding:0 16px 13px;margin-top:2px}
.po-mgrp .po-mgrp-why + .po-mgrp-acts{margin-top:0}
/* The money button. Blue and solid, because on this screen it is THE action, and wide enough
   that the amount it names is legible rather than an abbreviation. */
.po-mpay{
  appearance:none;background:var(--blue);border:1px solid var(--blue);color:#fff;
  font:inherit;font-family:var(--fd);font-size:.84rem;font-weight:800;letter-spacing:-.01em;
  padding:9px 15px;border-radius:9px;cursor:pointer;min-height:40px;
  display:inline-flex;align-items:center;gap:8px;white-space:nowrap;
  font-variant-numeric:tabular-nums;
  transition:background .14s,border-color .14s,transform .05s;
}
.po-mpay:hover{background:var(--blue-ink,#0B45B8);border-color:var(--blue-ink,#0B45B8)}
.po-mpay:active{transform:translateY(1px)}
.po-mpay:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.po-mpay[disabled]{opacity:.55;cursor:default}
/* "1 of 3": which batch this press pays, so a currency with several ready settlements is
   never read as done after one transfer. */
.po-mpay-n{display:inline-block;padding:1px 7px;border-radius:999px;
  background:rgba(255,255,255,.22);font-size:.7rem;font-weight:700;letter-spacing:0}
/* The reports beside it: secondary, same height, so the row reads as one strip. */
.po-mstmt{
  display:inline-flex;align-items:center;text-decoration:none;
  background:var(--panel);border:1px solid var(--line);color:var(--t2);
  font:inherit;font-size:.8rem;font-weight:700;padding:8px 13px;border-radius:9px;
  min-height:40px;cursor:pointer;white-space:nowrap;
  transition:background .14s,color .14s,border-color .14s,transform .05s;
}
.po-mstmt:hover{background:var(--panel-3);color:var(--ink);border-color:var(--blue)}
.po-mstmt:active{transform:translateY(1px)}
.po-mstmt:focus-visible{outline:2px solid var(--blue);outline-offset:2px}

/* ---- PAY ALL: the one-transfer button, and the sheet behind it ----------------------
   Nine in ten settlements leave as USDT or USDC and one merchant routinely has ready
   batches in several order currencies bound for the SAME wallet, which is ONE transfer.
   The button leads the action strip because it is the one press that clears the merchant;
   the per-currency Pay buttons stay beside it for a partial payment. */
.po-mpayall{background:var(--ink);border-color:var(--ink)}
.po-mpayall:hover{background:var(--ink-2);border-color:var(--ink-2)}
.po-mpayall:focus-visible{outline-color:var(--ink)}
/* Offered but not possible: the button stays visible so a merchant with four ready
   settlements never looks like a screen with a missing action, and the reason is stated
   beside it rather than hidden behind a hover. */
.po-mpayall-off{display:inline-flex;align-items:center;gap:9px;flex-wrap:wrap}
.po-mpayall-off em{font-style:normal;font-size:.76rem;line-height:1.35;color:var(--t3);max-width:34ch}

/* THE SHEET. Same frame, spacing and type as the single Pay sheet - it is the same job at
   a different scale, and a second visual language for one of them would make the pair read
   as two different products. */
.pay-all-list{display:flex;flex-direction:column;gap:6px;margin-top:10px}
/* One settlement, tickable. The id leads because that is what a refusal names. */
.pay-all-b{display:flex;align-items:center;gap:10px;padding:10px 12px;
  background:var(--panel);border:1px solid var(--line);border-radius:10px;cursor:pointer}
.pay-all-b:hover{border-color:var(--blue)}
.pay-all-b.off{opacity:.5}
.pay-all-b input{margin:0;width:18px;height:18px;accent-color:var(--blue);flex:0 0 auto}
.pay-all-b-id{font-family:var(--fd);font-size:.8rem;font-weight:800;color:var(--t3);
  font-variant-numeric:tabular-nums;flex:0 0 auto}
.pay-all-b-p{font-size:.78rem;color:var(--t2);flex:1 1 auto;min-width:0;
  display:flex;flex-direction:column;gap:1px;overflow:hidden}
/* THE SETTLEMENT DAY, the lead fact of the line: the owner's report was that the sheet
   showed the transaction dates and not the day the money is due. It is the stronger of the
   two, with the transaction window beneath it as the supporting line. */
.pay-all-b-sd{font-weight:700;color:var(--ink);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.pay-all-b-per{font-size:.72rem;color:var(--t3);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.pay-all-b-a{display:flex;align-items:baseline;gap:5px;flex:0 0 auto;
  font-variant-numeric:tabular-nums}
.pay-all-b-a b{font-family:var(--fd);font-size:.9rem;font-weight:800;color:var(--ink)}
.pay-all-b-a em{font-style:normal;font-size:.7rem;font-weight:700;color:var(--t3)}
/* The same settlements restated on the Confirm step, each with its own due day, so the
   operator entering the PIN signs against dates rather than against a count. */
.pay-all-clines{display:flex;flex-direction:column;gap:5px;margin-top:10px}
.pay-all-cline{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  padding:8px 11px;background:var(--panel);border:1px solid var(--line);border-radius:9px;
  font-size:.78rem;color:var(--t2)}
.pay-all-cline-id{font-family:var(--fd);font-size:.78rem;font-weight:800;color:var(--t3);
  font-variant-numeric:tabular-nums;flex:0 0 auto}
.pay-all-cline-sd{font-weight:700;color:var(--ink);flex:0 0 auto}
.pay-all-cline-per{font-size:.72rem;color:var(--t3);flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
.pay-all-cline-a{font-family:var(--fd);font-weight:800;color:var(--ink);flex:0 0 auto;
  font-variant-numeric:tabular-nums}
/* Per-currency subtotals of what is still ticked. Never one number across currencies. */
.pay-all-tots{display:flex;flex-wrap:wrap;gap:14px;margin-top:12px;
  padding-top:10px;border-top:1px solid var(--line-soft)}

/* One currency's conversion, as its own block: the rate is a money decision per currency
   and stacking them in one undivided form is how one of them gets signed unread. */
.pay-all-ccy{margin-top:14px;padding:13px 14px;background:var(--panel);
  border:1px solid var(--line);border-radius:12px}
.pay-all-ccy:first-of-type{margin-top:10px}
.pay-all-ccy-h{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;margin-bottom:9px}
.pay-all-ccy-h b{font-family:var(--fd);font-size:1rem;font-weight:800;letter-spacing:-.02em;
  color:var(--ink);font-variant-numeric:tabular-nums}
.pay-all-ccy-h em{font-style:normal;font-size:.74rem;font-weight:700;color:var(--t3)}
.pay-all-ccy-out{margin-top:10px;font-size:.82rem;font-weight:700;color:var(--teal);
  font-variant-numeric:tabular-nums;overflow-wrap:anywhere}

/* THE TOTAL IS THE POINT OF THIS SHEET, so it is the biggest thing on it: what the merchant
   actually receives, in the coin, in display type, with the per-currency lines beneath as
   the supporting detail. It reuses .pay-fx-big so the single sheet and this one state the
   same kind of number at the same size. */
.pay-all-total{background:var(--teal-50);border:1px solid var(--teal-soft);
  border-radius:12px;padding:16px 16px 14px}
.pay-all-total .pay-fx-big{font-size:2rem}
.pay-all-lines{margin-top:9px;display:flex;flex-direction:column;gap:4px;
  padding-top:9px;border-top:1px solid var(--teal-soft)}
.pay-all-line{font-size:.8rem;font-weight:600;color:var(--ink-2);
  font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.pay-all-n{display:inline-block;margin-left:6px;padding:1px 7px;border-radius:999px;
  background:var(--panel-3);font-size:.7rem;font-weight:700;color:var(--t3)}

@media (max-width:760px){
  .po-mpayall-off{width:100%}
  .po-mpayall-off em{max-width:none}
  .pay-all-b{flex-wrap:wrap;row-gap:4px}
  .pay-all-b-p{flex:1 1 100%;order:3}
  .pay-all-b-sd,.pay-all-b-per{white-space:normal}
  .pay-all-cline{row-gap:3px}
  .pay-all-cline-per{flex:1 1 100%;order:4}
  .pay-all-total .pay-fx-big{font-size:1.7rem}
  /* THREE STEPS ON A 390 RAIL. The shared .oz-prog scrolls when its steps overflow, which
     leaves the step you are on half off the edge - the one thing the rail exists to show.
     Tightened here only, so the other sheets are untouched. */
  .pay-all-sheet .oz-prog{gap:4px;padding-left:10px;padding-right:10px}
  .pay-all-sheet .oz-step{padding-left:7px;padding-right:7px;min-width:0}
  .pay-all-sheet .oz-step-l{font-size:.68rem}
}

/* THE STALE-DESTINATION NOTE is not a failure: the operator already did the work and only
   the snapshot on older batches is behind. Amber, not red, and its action is the normal
   blue one rather than the red "go and fix something" button. */
.po-mgrp-why.po-stalenote .po-fixline{background:var(--amber-soft)}
.po-stalenote .po-refreshdest{
  background:var(--blue);border-color:var(--blue);color:#fff;
}
.po-stalenote .po-refreshdest:hover{background:var(--blue-ink,#0B45B8);border-color:var(--blue-ink,#0B45B8)}
.po-stalenote .po-refreshdest:focus-visible{outline-color:var(--blue)}

/* WHAT WE HAVE PAID A PARTNER, under their currencies. A record, so it is quieter than the
   owed table above it and separated by a rule rather than by a card of its own. */
.po-phist{padding:4px 16px 14px;border-top:1px solid var(--line-soft);margin-top:4px}
.po-phist .po-sec-h{padding:12px 0 8px;background:transparent;border:0}
.po-chip.ok{background:var(--green-soft);color:var(--green)}

/* The address a statement will be emailed to, stated before the button is pressed. */
.sd-mailto{font-size:.82rem;color:var(--t2);flex:1 1 100%}
.sd-mailto.bad{color:var(--red)}

@media (max-width:760px){
  /* ONE ACTION PER ROW ON A PHONE. Two buttons side by side at 390 either overflow or shrink
     the amount into an ellipsis, and the amount is the whole point of the button. */
  .po-mgrp-acts{padding:0 14px 13px;gap:8px}
  .po-mgrp-acts>*{flex:1 1 100%;justify-content:center;text-align:center}
  .po-phist{padding:4px 14px 14px}
}

.po-runfilter{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:12px 0;
  padding:10px 14px;border:1px solid var(--teal);background:var(--teal-50);
  border-radius:10px;font-size:13px;color:var(--t2)}
.po-runfilter .btn-ghost{margin-left:auto;padding:.3em .7em;font-size:12px}
@media (max-width:760px){
  .po-runfilter .btn-ghost{margin-left:0}
  .po-prog{min-width:60px}
}


/* ---- Detailed settlement rows: the money behind each batch ---- */
.po-sub{display:block;font-size:11px;color:var(--t3);font-weight:400;margin-top:2px;line-height:1.35}
.po-names{font-weight:600}
/* A money figure must never break across lines. "-GBP 60.00" split over two rows reads as
   two different numbers, and on a settlements screen that is the one misreading that costs
   real money. The cell refuses to wrap and the column is allowed the width it needs. */
.po-neg{color:var(--red)}
/* Money coming BACK to the merchant (a released reserve), so a + item is never read as
   another deduction sitting in the same column. */
.po-pos{color:var(--green,#146C2E)}

/* THE FAIL-CLOSED STATE ON A SETTLEMENT ROW, CARD AND PAY SHEET.

   A settlement whose named lines do not add up to what it would pay, or which shows a refund
   that is not inside that amount, is not a rounding curiosity: paying it sends the wrong
   amount. It used to be invisible, because the Adjustments column carried a derived residual
   that closed the arithmetic whatever the cause. The row now says so in red and the Pay button
   is withdrawn. docs/settlement-refund-cycle-rule.md */
.po-donotpay{color:var(--red);font-weight:700}
tr.po-unrec>td{background:#FEF2F2}
tr.po-unrec>td:first-child{box-shadow:inset 3px 0 0 var(--red)}
.sdc-donotpay{margin-top:10px;padding:10px 12px;border:1px solid var(--red);
  border-left-width:3px;border-radius:8px;background:#FEF2F2;color:#7F1D1D;font-size:13px}
.sdc-donotpay b{display:block;margin-bottom:4px;color:var(--red)}
.sdc-donotpay div+div{margin-top:4px}
.sdc-line-pos .sdc-v{color:var(--green,#146C2E)}
.pay-donotpay{margin-top:8px;padding:8px 10px;border:1px solid var(--red);border-radius:8px;
  background:#FEF2F2;color:#7F1D1D;text-align:left}
.pay-donotpay b{color:var(--red)}

/* THE DESKTOP SETTLEMENT TABLE, readable.

   It shipped at .88rem in the global monospace .num face with 11px sub-lines, and the
   merchant cell wrapped "QA Crypto INR Co" plus four facts into five lines - a row taller
   than the numbers in it and harder to read than the phone card. Now: the panel sans face
   with tabular figures (no monospace anywhere), 14px body text, 12px sub-lines, room to
   breathe vertically, and a merchant cell held to two lines by its own minimum width. */
.po-batches{font-size:14px}
.po-batches td{padding:14px 14px;vertical-align:top}
.po-batches th{padding:10px 14px}
.po-batches td.num,.po-batches th.num{white-space:nowrap}
/* The global .num rule sets the monospace face; on this table money is the panel's own
   sans with tabular figures, which lines up just as well and stops the row reading as a
   terminal dump. */
.po-batches td.num{font-family:var(--f);font-weight:700;font-variant-numeric:tabular-nums}
.po-batches td.num span{white-space:nowrap}
.po-batches .po-sub{font-size:12px;margin-top:3px}
/* ...but the explanatory note UNDER a figure is prose, not a number. Holding it on one
   line pushed the widest section 16px past its card and put a sideways scroll on a
   desktop table. It wraps; the figure above it still does not. */
.po-batches td.num .po-sub{white-space:normal}
.po-batches .num .po-sub{font-weight:400}
/* Two lines at most: the name, then one line of context. Enough width that the name does
   not break mid-word, and the sub line is clipped rather than allowed to stack. */
.po-batches td.po-merch{min-width:172px;max-width:230px}
.po-batches td.po-merch .po-rowlink{display:block;line-height:1.3}
.po-batches td.po-merch .po-sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.po-batches td[data-l="Period"]{min-width:128px}
/* The fee arrangement is a formula, not prose: "4% + 0.50" broken over two lines reads as
   two unrelated terms. It is short, so it holds its line and the column widens for it. */
.po-batches .po-terms{white-space:nowrap}
.po-batches td[data-l="Destination"]{min-width:120px}
/* The 14px body plus the new column minimums pushed the nine-column table 214px past its
   card at 1280 and put a sideways scroll on a desktop. Tighten the horizontal padding
   rather than shrinking the type back: the readable size is the point of the change. */
/* Measured across every seeded merchant group, not just the first: the widest one still
   ran 13px past its card at 10px of side padding. 8px clears it with room to spare and is
   still a readable gutter at 14px type. */
.po-batches td{padding-left:8px;padding-right:8px}
.po-batches th{padding-left:8px;padding-right:8px}
@media (max-width:980px){
  /* The detail columns stack rather than scroll off: this panel is used on a phone. */
  .po-batches thead{display:none}
  /* The desktop column minimums must not survive into the card layout, where every cell is
     a full-width flex row - a 186px minimum on a 358px card pushes the value off the edge. */
  .po-batches td.po-merch,.po-batches td[data-l="Period"],.po-batches td[data-l="Destination"]{
    min-width:0;max-width:none}
  .po-batches td.po-merch .po-sub{white-space:normal;text-overflow:clip}
  .po-batches tr{display:block;border-bottom:1px solid var(--line);padding:10px 4px}
  .po-batches td{display:flex;justify-content:space-between;gap:12px;border:0;padding:3px 8px;text-align:right}
  .po-batches td::before{content:attr(data-l);color:var(--t3);font-size:11px;
    text-transform:uppercase;letter-spacing:.04em;text-align:left}
  .po-batches td .po-sub{text-align:right;white-space:normal;min-width:0}
  /* Each cell is a flex row of label and value; a value carrying two sub-lines has to be
     allowed to take the width it needs, or the date crushes to one character per line. */
  .po-batches td{align-items:baseline}
  .po-batches td::before{flex:0 0 auto;white-space:nowrap}
  .po-batches td[data-l="Period"]{flex-wrap:wrap}
  .po-batches td[data-l="Period"] .po-dates,
  .po-batches td[data-l="Period"] .po-sub{flex:1 1 auto;min-width:9rem}
  /* Stacked on a phone the merchant cell is label-left value-right like every other row,
     so the name must not wrap mid-word against a 5rem label. The name takes the line it
     needs and the transaction count sits under it. */
  .po-batches td.po-merch{max-width:none;min-width:0;flex-wrap:wrap}
  .po-batches td.po-merch .po-names{flex:1 1 auto;text-align:right;min-width:10rem}
  .po-batches td.po-merch .po-sub{flex:1 1 100%;text-align:right}
  /* The fix note is a full-width explanation, not a labelled cell: without this it
     inherits the card-row flex and the label pseudo-element, and reads as an empty field. */
  .po-batches tr.po-fixrow{padding:0 4px 10px}
  .po-batches tr.po-fixrow td{display:block;text-align:left;padding:0}
  .po-batches tr.po-fixrow td::before{content:none}
}

/* Settlement by partner: same book, grouped by who is owed. */
.po-bypartner{margin-bottom:14px}
.po-bypartner tr.po-pt{cursor:pointer}
.po-bypartner tr.po-pt:hover{background:var(--panel-3)}


/* ============================================================================
   DESIGN V2 - phone tab bar, table containment, motion.
   Appended last so it wins over the older blocks above.
   ============================================================================ */

/* ---- Phone bottom tab bar -------------------------------------------------
   Built in core.js by cloning the sidebar's own <a> nodes. Hidden on desktop:
   the sidebar is the nav there. The .tabbar is position:fixed, so a
   full_page=True screenshot paints it once per screenful - that is the capture
   mode, not a defect. */
.tabbar{display:none}
@media(max-width:820px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  .tabbar{
    display:grid;grid-template-columns:repeat(5,1fr);position:fixed;left:0;right:0;bottom:0;z-index:70;
    background:rgba(10,16,28,.96);backdrop-filter:blur(10px);
    padding:8px 6px calc(8px + env(safe-area-inset-bottom));border-top:1px solid rgba(255,255,255,.07);
  }
  .tabbar a,.tabbar .tb-more{
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
    color:#93A6C8;text-decoration:none;font-size:.66rem;font-weight:600;font-family:var(--f);
    padding:4px 2px;min-height:44px;background:none;border:0;cursor:pointer;
  }
  .tabbar svg{width:21px;height:21px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;flex:none}
  .tabbar .tb-l{line-height:1.1;text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}
  .tabbar a.on{color:#fff}
  .tabbar a.on svg{stroke:url(#peNavGrad)}
  .tabbar .badge{display:none}
  /* Clear the bar so the last row of every page stays readable. */
  .main{padding-bottom:96px}
  /* The flash toast is bottom-fixed at 24px, which puts it behind the tab bar.
     Lift it clear, or a confirmation an operator needs is half-hidden. */
  .flash{bottom:calc(84px + env(safe-area-inset-bottom));max-width:calc(100vw - 32px);text-align:center}
  /* The burger stays: it is the same drawer the More tab opens. */
}

/* ---- Phone: a table scrolls INSIDE its card, never sideways across the page
   A table wider than the viewport used to widen the document itself, so the
   whole page slid under the thumb and the sidebar edge came with it. Every
   table wrapper gets its own scroll box and the shell is pinned to 100%. */
@media(max-width:820px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  html,body{max-width:100%;overflow-x:hidden}
  .app,.app > .main{max-width:100%;min-width:0;overflow-x:clip}
  .main .dtable-wrap,.main .tbl-wrap,.main .tw,.main .table-wrap{
    max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;
  }
  /* A bare <table> with no wrapper: give it the scroll box via its card. */
  .main .card,.main .panel,.main .spanel,.main .tbl{max-width:100%;overflow-x:auto}
  .main table{max-width:100%}
  .main pre,.main code{max-width:100%;overflow-x:auto;white-space:pre-wrap;word-break:break-word}
  /* Long unbroken identifiers (refs, hashes, URLs) are the other page-widener. */
  .main .mono,.main .t-ref,.main .t-em{overflow-wrap:anywhere}
}

/* ---- Inputs: the focus ring is brand blue everywhere ---- */
.field input:focus,.field textarea:focus,.field select:focus,
.main select:focus,.toolbar select:focus,.toolbar input:focus,
.main input:focus,.main textarea:focus{
  outline:none;border-color:var(--blue);box-shadow:var(--sh-pop);
}
.btn:focus-visible,.seg button:focus-visible,.chip:focus-visible,
.nav-item:focus-visible,.tabbar a:focus-visible,.tabbar .tb-more:focus-visible{
  outline:2px solid var(--blue);outline-offset:2px;
}

/* ---- KPI cards: no coloured left rail, tinted variants become the brand wash */
.kard::before{content:none}
.kard{padding-left:17px}
.kpi.gold,.kpi.teal{background:var(--grad-soft);border-color:var(--line-2)}
.kpi.gold .v{background:none;-webkit-background-clip:border-box;background-clip:border-box;color:var(--ink)}
.kpi.teal .v{color:var(--ink)}
.kard.teal,.kard.gold,.kard.green,.kard.indigo,.kard.violet,.kard.amber,.kard.red{
  background:var(--bg-2);border-color:var(--line-2);
}
.kard .kv{color:var(--ink)}

/* ---- Tabs: the active tab carries the brand gradient on its underline ---- */
.co-tab.on,.gw-tab.on{background:var(--ink);color:#fff}

/* ---- Motion: entrance only, 120-320ms, eased out ---- */
@keyframes pe-rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.view.on{animation:pe-rise .28s var(--ease) both}
.view.on > *:nth-child(1){animation:pe-rise .26s var(--ease) both}
.view.on > *:nth-child(2){animation:pe-rise .26s var(--ease) both;animation-delay:.04s}
.view.on > *:nth-child(3){animation:pe-rise .26s var(--ease) both;animation-delay:.08s}
.view.on > *:nth-child(4){animation:pe-rise .26s var(--ease) both;animation-delay:.12s}

/* prefers-reduced-motion is not a courtesy: transform animation is genuinely
   unpleasant with a vestibular disorder, and this is somebody's job. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important;animation-iteration-count:1!important}
}

/* ============================================================================
   DESIGN V2 - narrow-screen containment, round 2.
   Measured with the UI QA agent at 360/390/430/768/1280. Two failure shapes
   kept recurring and both are fixed here by principle, not per view:

     1. a row of "text plus controls" that cannot wrap, so the text column is
        squeezed to a few pixels while the buttons keep their width. The fix is
        to stack (column / one grid track) on a phone, never to shrink the text.
     2. a wide table told to be width:100% inside a scroll box, so it squeezes
        its first column into one character per line instead of scrolling. The
        fix is a min-width on the table plus nowrap headers, so the scroll box
        it already sits in actually scrolls.

   Nothing is hidden and no element is removed.
   ============================================================================ */

/* ---- Dashboard hero KPIs -------------------------------------------------
   .hkpi had overflow:hidden, so the delta pill and the denominator line were
   simply cut off (35px at 360, still 2px at 1280). The pill is one unbreakable
   nowrap run; let the sub-line wrap and let the pill break instead of clipping
   the sentence an operator needs. */
/* Specificity note: public/css/dashboard.css loads AFTER this file and its rules
   are written as "#v-dashboard .hkpi" / "#v-dashboard .db-merchants". An equal
   selector here would lose, so these carry one extra class to win outright. */
.main #v-dashboard .hkpi{overflow:hidden}
.main #v-dashboard .hkpi .hk-sub{flex-wrap:wrap;min-width:0}
.main #v-dashboard .hkpi .hk-delta{white-space:normal;min-width:0;max-width:100%;line-height:1.35;
  overflow-wrap:anywhere}
.main #v-dashboard .hkpi .hk-delta span{white-space:normal}
.main #v-dashboard .hkpi .hk-v{white-space:normal;overflow-wrap:anywhere}
.main #v-dashboard .hkpi .hk-den{overflow-wrap:anywhere;max-width:100%}

/* ---- Dashboard: top merchants table -------------------------------------
   At 360 the four columns shared 328px and the merchant name became 11 lines
   in 50px. The table keeps a readable minimum and scrolls inside its own card. */
.main #v-dashboard .db-merchants{overflow-x:auto;overflow-y:visible;-webkit-overflow-scrolling:touch}
.main #v-dashboard .merch-tbl{min-width:520px}
.main #v-dashboard .merch-tbl th{white-space:nowrap}
.main #v-dashboard .merch-tbl td:first-child{min-width:170px}

/* ---- Dashboard: activity feed rows on a phone ---------------------------
   Time, icon and status badge are fixed-size siblings of a flexible body; on a
   narrow card the badge is what gets pushed out. Allow the row to wrap. */
@media (max-width:560px){
  #v-dashboard .act2-item{flex-wrap:wrap}
  #v-dashboard .act2-item .a2-body{flex:1 1 auto}
  #v-dashboard .act2-item .a2-badge{align-self:flex-start}
}

/* ---- Merchant / partner page: the tab rail is a scrolling strip ----------
   The rail is a sticky column on desktop and a horizontal strip on a phone.
   #v-merchant-page .mp-rail / #v-partner-page .mp-rail (id + class) set
   overflow:hidden for the MID cards that share the class name, and that beat
   the strip's own overflow-x:auto - so the tabs past "Countries & currencies"
   were cut by the screen edge with no way to reach them. The nav element is
   addressed directly, which leaves the MID cards untouched. */
@media (max-width:900px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  .mp-layout{grid-template-columns:minmax(0,1fr)}
  #v-merchant-page nav.mp-rail,#v-partner-page nav.mp-rail,nav.mp-rail{
    position:static;display:flex;flex-wrap:nowrap;gap:4px;padding:6px;margin-bottom:11px;
    min-width:0;max-width:100%;overflow-x:auto;overflow-y:hidden;
    -webkit-overflow-scrolling:touch;scrollbar-width:thin;
  }
  nav.mp-rail .mp-rl{width:auto;flex:0 0 auto;white-space:nowrap}
  nav.mp-rail .mp-rl-l{overflow:visible;text-overflow:clip}
}

/* ---- Merchant / partner page KPIs ---------------------------------------
   Four monospace money values in 360px overlapped each other. Two columns on a
   phone, and a value may break rather than paint over its neighbour. */
.mp-kpi .v{overflow-wrap:anywhere;min-width:0}
@media (max-width:900px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  #v-merchant-page .mp-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:430px){
  #v-merchant-page .mp-kpis,#v-partner-page .mp-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* ---- Risk + routing state banners: stack on a phone ---------------------
   Both are "icon, sentence, mode buttons" in one flex row. The buttons are
   flex:none, so the sentence absorbed every pixel of the shortfall and ended
   up 4px wide (21 lines of one letter). On a phone the sentence takes the full
   width and the controls sit underneath it, full width and easy to hit. */
@media (max-width:720px){
  #v-risk .rk-banner,#v-routing .rt-banner,#v-routing-map .rm-engine{
    flex-direction:column;align-items:stretch;gap:11px}
  #v-risk .rk-banner > div,#v-routing .rt-banner > div{min-width:0;max-width:100%}
  #v-risk .rk-dot,#v-routing .rt-dot{align-self:flex-start}
  #v-risk .rk-modes,#v-routing .rt-seg{width:100%}
  #v-risk .rk-modes .rk-mode{flex:1 1 0;min-width:0;text-align:center}
  #v-routing .rt-seg{display:flex}
  #v-routing .rt-seg button{flex:1 1 0;min-width:0}
  /* the routing banner's right-hand column is inline-styled align:flex-end */
  #v-routing .rt-banner > div:last-child{align-items:stretch!important;width:100%}
}

/* ---- Wide tables: scroll, never squeeze --------------------------------
   Each of these tables already sits in a box with overflow-x:auto; they were
   width:100% with no minimum, so they squeezed instead of scrolling. A minimum
   width plus nowrap headers turns the existing box into a real scroll strip. */
@media (max-width:900px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  #v-risk .rk-cb > table,#v-risk .rk-cb table{min-width:560px}
  #v-risk th{white-space:nowrap}
  #v-risk td:first-child{min-width:150px}
  #v-risk .rk-sigtoggle{white-space:nowrap}

  #v-monitoring table{min-width:620px}
  #v-monitoring th{white-space:nowrap}

  #v-reports table{min-width:700px}
  #v-reports th{white-space:nowrap}
  #v-reports tr.res-row > td:first-child,#v-reports tr.rep-merchant-row > td:first-child{min-width:150px}
  /* the cost editor is four columns with two number inputs; it needs far less */
  #v-reports table.rep-cost{min-width:560px}

  #v-recon table,#v-audit table,#v-integrations table{min-width:620px}
  #v-recon th,#v-audit th,#v-integrations th{white-space:nowrap}
}
/* The By-merchant statement carries ten money columns; 700px still crushed the
   merchant name at 430. It is a spreadsheet, and it scrolls like one.
   Keyed on the input device as well as width: a phone in desktop-site mode
   reports ~1350 CSS px and would otherwise get the squeezed desktop table. */
@media (max-width:900px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  #v-reports table.rep-wide{min-width:980px}
  /* A MONEY FIGURE IS NEVER BROKEN ACROSS TWO LINES. An INR total is the longest thing on
     this table and a 92px column was wrapping "221,484.35" mid-number, which is a figure
     an operator can misread. The table already scrolls sideways here, so a cell that
     refuses to wrap costs a swipe rather than a mistake. */
  #v-reports .rep-wide td.num,#v-reports .rep-wide th.num,
  #v-reports .rep-wide td.ccy,#v-reports .rep-wide .money{white-space:nowrap}
  /* The merchant name is prose and may wrap, but it gets enough room to do it in two or
     three lines rather than five. */
  #v-reports .rep-wide td:first-child{min-width:140px;overflow-wrap:break-word}
}

/* ---- API docs tables ----------------------------------------------------
   The global "bare table in a panel becomes display:block" rule turned these
   into a block box whose anonymous table still wrapped every cell. They stay
   real tables with a readable minimum and scroll inside the panel. */
@media (max-width:900px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  #v-docs .panel > table{display:table;white-space:normal;min-width:480px}
  #v-docs .panel > table th{white-space:nowrap}
  #v-docs .panel > table td:first-child{min-width:170px}
}

/* ---- Settings: a description never shares a line with its control -------
   .op-row is the row built in views/settings.js. Label plus help text on the
   left, the input and Save on the right; on a phone the two stack, because at
   360px the help text was 18 lines in 74px next to the toggle. */
.op-row{display:grid;grid-template-columns:1fr auto;gap:6px 14px;align-items:center;
  padding:11px 0;border-top:1px solid var(--line)}
.op-row-t{font-weight:600}
.op-row-k{opacity:.5;font-weight:400;font-size:.76rem}
.op-row-h{margin:2px 0 0;font-size:.8rem}
.op-row-when{opacity:.5}
.op-row-c{display:flex;gap:8px;align-items:center}
.op-group{font-weight:800;margin:16px 0 4px;font-size:.9rem}
@media (max-width:560px){
  .op-row{grid-template-columns:minmax(0,1fr);align-items:start}
  .op-row-c{width:100%}
  .op-row-c .op-input{flex:1 1 auto;min-width:0}
}

/* ---- Readable floor: no label below 11px ----
   The UI QA agent measured 532 labels at 8.6-10.2px (Admin tag, nav sections, KPI
   labels, table headers, pills, chart axis). Uppercase tracking makes them read even
   smaller on a phone. Every one gets an 11px floor; sizes above that are untouched. */
.brand .sub,.side .nav-section,.hk-label,.hk-label > span,.a2-time,#sparkAxis > span,
#ordersLive,.test-tag,.ph-window,.txf-legend,.kard .kl,.mtbl-chip-l,.po-unpayable,
.thead > span,.gw-advgrid > label,.ad,.mp-pill,.rk-blind,.rm-pill,.rt-soon,
.merch-tbl th,.dtable th,.rm-table th{font-size:11px!important}

/* Merchant page, Latest transactions: the Amount cell carries amount + status pill + TEST
   tag. On a 768px tablet the fixed 24% column could not hold all three on one line and the
   TEST tag ran past the screen edge. Let that cell wrap; tags drop under the amount. */
#v-merchant-page .mp-ttable td.num{white-space:normal;overflow:visible;line-height:1.7}
#v-merchant-page .mp-ttable td.num .mp-pill,#v-merchant-page .mp-ttable td.num .test-tag{display:inline-block;white-space:nowrap}
#v-merchant-page .mp-ttable th,.main table > thead > tr > th{font-size:11px!important}

/* ---- Money and codes never break mid-value ----
   The phone rule ".view td{overflow-wrap:anywhere}" (there before design v2, also live)
   let a squeezed column split "EUR" into "EU / R" and "€864.31" into "€864 / .31" on
   Merchant statistics and elsewhere. Long references/emails/hashes may still break (that
   is what the rule is for); amounts, currency codes, counts and headings are kept whole,
   and their table scrolls inside its card instead. */
@media(max-width:880px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  .view td.num,.view th,.view td.ccy,.view .stbadge,.view .mp-pill,.view .test-tag{overflow-wrap:normal;white-space:nowrap}
  .view .recon-table td:nth-child(-n+5){white-space:nowrap}
  .view .recon-table{min-width:max-content}
  .view .dtable,.view .rm-table,.view .merch-tbl{min-width:max-content}
  .view .dtable td:not(.num),.view .rm-table td:not(.num){overflow-wrap:break-word}
  .view .dtable-wrap,.view .mp-cb,.view .card:has(> table),.view .card:has(> .dtable){overflow-x:auto;-webkit-overflow-scrolling:touch}
}

/* ---- Providers: the "system config" marker beside a provider name ----
   It had no rule at all, so it wrapped word by word into the name above it and a provider
   called "QA Gateway Merchants" came out as five crushed lines at 390. It is a chip: it
   stays on one line and sits on its own line under a long name rather than inside it. */
.pv-syschip{display:inline-block;white-space:nowrap;vertical-align:middle;
  margin-left:6px;padding:2px 8px;border-radius:999px;
  background:var(--panel-2);color:var(--t3);border:1px solid var(--line-soft);
  font-size:.66rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
@media(max-width:560px){
  .pv-syschip{margin-left:0;margin-top:4px}
}

/* ---- Desktop: list tables fit the card without a sideways swipe ----
   Merchants (92px) and Partners (44px) overflowed a 1280 laptop, hiding the action
   column; same on live. Tighter cell padding on wide screens, and headings may wrap. */
@media(min-width:1100px){
  #v-brands .dtable th,#v-brands .dtable td,#v-partners .dtable th,#v-partners .dtable td{padding-left:11px;padding-right:11px}
  #v-brands .dtable th,#v-partners .dtable th{white-space:normal}
  #v-brands .dtable td:first-child{max-width:240px}
  /* THE MERCHANTS TABLE MUST FIT A 1280 LAPTOP. Under multi-currency seed data it still
     needed a 64px sideways scroll, which hides the right-hand action column - on the
     brands screen and on every create/edit pop-up rendered over it. Three changes, none
     of which shrink a number:
       - money and counts never wrap, so a figure is never broken across two lines;
       - the merchant name and the Methods list may wrap, because prose can;
       - the name column gives back width instead of the action column losing it. */
  #v-brands .dtable{table-layout:auto}
  #v-brands .dtable td.num,#v-brands .dtable th.num{white-space:nowrap}
  #v-brands .dtable td:first-child{max-width:190px;overflow-wrap:break-word}
  #v-brands .dtable td:first-child .sub{overflow-wrap:anywhere}
  #v-brands .dtable th,#v-brands .dtable td{padding-left:9px;padding-right:9px}
  /* The methods cell is a list of short tokens and is the widest thing that can give. */
  #v-brands .dtable td:nth-child(3){max-width:170px;overflow-wrap:break-word}
  /* THE REPORTS TABLE. Twelve columns of money is a spreadsheet, and forcing every one of
     them onto a single line does not make it fit a 1280 laptop - it made the overflow
     worse (43px became 305px). So the number columns are left able to wrap at desktop
     width and the table keeps its scroll; what is fixed is the merchant NAME column, which
     was being broken into five lines because it had no width of its own. */
  #v-reports .rep-wide{font-size:.82rem!important}
  #v-reports .rep-wide th,#v-reports .rep-wide td{padding-left:6px!important;padding-right:6px!important}
  /* By class, not :first-child: the name cell spans a merchant's rows, so on every row after
     the first the first cell is the CURRENCY, and :first-child made that column 150px wide. */
  #v-reports .rep-wide td.rep-name{min-width:110px;max-width:200px;overflow-wrap:break-word}
  /* Gateway routing rules: each row is a form (inputs per column). 1120px was the floor
     so the inputs stay usable; 940px of room fits them when padding is trimmed. */
  #v-gateway table.gw-rules{min-width:900px!important}
  #v-gateway .gw-rules th,#v-gateway .gw-rules td{padding-left:5px;padding-right:5px}
}

/* ================= DESIGN V2 - INTERACTION LAYER =================
   Every control reacts: pointer cursor, hover lift/tint, press-down, a visible keyboard
   focus ring and a clear selected state, all in the brand blue -> cyan line. One layer
   for the whole panel so a control added later behaves the same. Colours only through
   tokens; no layout change (transform + shadow + background only). */
:where(button,[role=button],[role=tab],a.btn,.btn,.seg > *,[data-tab],button.chip,a.chip,label.chip,[role=button].chip,.chips label,.mp-rl,.po-tab,.hub-tab,.gw-tab,.mp-tab,.mp-subtab,.tab-btn,.geo-opt,.mp-solchip,.filter-chip,.preset,.pill-btn):not(:disabled):not([aria-disabled=true]){
  cursor:pointer;
  transition:background-color .16s ease,color .16s ease,border-color .16s ease,box-shadow .16s ease,transform .12s ease,filter .16s ease;
  -webkit-tap-highlight-color:rgba(46,124,255,.14);
}
/* hover (real pointers only - no sticky hover on phones) */
@media (hover:hover){
  :where(.btn,a.btn,button.btn):not(:disabled):hover{transform:translateY(-1px);box-shadow:0 6px 16px -8px rgba(14,86,230,.45)}
  :where(.btn-primary,.btn.primary,button.primary):not(:disabled):hover{filter:brightness(1.07) saturate(1.05)}
  :where(.btn-ghost,.btn-secondary,.btn.ghost,.btn-outline):not(:disabled):hover{background-color:#E8F0FF;border-color:#2E7CFF;color:#0A47C4}
  :where([role=tab],.seg > *,[data-tab],.po-tab,.hub-tab,.gw-tab,.mp-tab,.mp-subtab,.tab-btn,button.chip,a.chip,label.chip,[role=button].chip,.chips label,.geo-opt,.mp-solchip,.filter-chip,.preset,.pill-btn):not(.on):not(.active):not([aria-selected=true]):hover{
    background-color:#EEF4FF;color:#0A47C4;border-color:#9DBEFF}
  .mp-rl:not(.on):hover{background:#EEF4FF;color:#0A47C4}
  .mp-rl:not(.on):hover .mp-rl-ic{background:#DCE8FF;color:#0E56E6}
  :where(.side a,.side [data-nav],nav#nav a):not(.on):not(.active):hover{background-color:rgba(46,124,255,.12);color:#fff}
  :where(button:not(.btn):not([role=tab]):not(.mp-rl)):not(:disabled):not(.on):not(.active):hover{filter:brightness(1.06)}
}
/* press */
:where(button,[role=button],[role=tab],a.btn,.btn,.seg > *,[data-tab],button.chip,a.chip,label.chip,[role=button].chip,.chips label,.mp-rl,.po-tab,.hub-tab,.gw-tab,.mp-tab,.mp-subtab,.tab-btn,.geo-opt,.mp-solchip,.filter-chip,.preset,.pill-btn):not(:disabled):active{
  transform:translateY(0) scale(.97);box-shadow:none;filter:brightness(.96)}
/* keyboard focus: always visible, never on mouse click */
:where(button,[role=button],[role=tab],a,.btn,.seg > *,[data-tab],button.chip,a.chip,label.chip,[role=button].chip,.chips label,.mp-rl,.po-tab,.hub-tab,.gw-tab,.mp-tab,.mp-subtab,.tab-btn,.geo-opt,.mp-solchip,summary,select,input,textarea):focus-visible{
  outline:2px solid #2E7CFF;outline-offset:2px;box-shadow:0 0 0 5px rgba(46,124,255,.18)}
/* selected: brand tint + blue ink + gradient marker */
.mp-rl.on{background:linear-gradient(90deg,#E8F0FF,#EEFBFA);color:#0A47C4;font-weight:600;box-shadow:inset 3px 0 0 #2E7CFF}
.mp-rl.on .mp-rl-ic{background:linear-gradient(135deg,#0E56E6,#19E3D0);color:#fff}
.mp-rl.on .mp-rl-n:not(.warn){color:#0A47C4}
:where([role=tab],.po-tab,.hub-tab,.gw-tab,.mp-tab,.mp-subtab,.tab-btn,.geo-opt,.mp-solchip,button.chip,a.chip,.filter-chip,.preset):is(.on,.active,[aria-selected=true]){color:#0A47C4;border-color:#2E7CFF}
:where(button,.btn,[role=button]):disabled,:where(button,.btn,[role=button])[aria-disabled=true]{cursor:not-allowed;opacity:.55;transform:none;box-shadow:none;filter:none}
@media (prefers-reduced-motion:reduce){*{transition:none!important}:where(.btn,button):hover,:where(.btn,button):active{transform:none!important}}

/* interaction layer - controls that are not <button> but act like one */
:where(.top-search,#cmdkTrigger,.bell,.df-cal,.pgbtn,.gw-chip,.gw-add,.txf-export,.txf-more,.nav a,.nav-sub,nav a,[role=button][tabindex]){cursor:pointer}
:where(.top-search,#cmdkTrigger) *{cursor:pointer}
@media (hover:hover){
  :where(.top-search,#cmdkTrigger):hover{border-color:#2E7CFF;box-shadow:0 0 0 3px rgba(46,124,255,.14);background-color:#fff}
  :where(.bell,.df-cal,.pgbtn,.gw-chip,.gw-add,.txf-export,.txf-more,.seg > button):not(.on):not(:disabled):hover{background-color:#EEF4FF;color:#0A47C4;border-color:#9DBEFF}
  :where(.nav a,.nav-sub,nav#nav a,.side nav a):not(.on):not(.active):hover{background-color:rgba(46,124,255,.14);color:#fff}
}
:where(.nav a,.nav-sub,nav a,.top-search,#cmdkTrigger,.bell,.df-cal,.pgbtn,a.btn,.btn,.gw-chip,.gw-add,.txf-export,.txf-more):focus-visible{outline:2px solid #2E7CFF;outline-offset:2px;box-shadow:0 0 0 5px rgba(46,124,255,.18)}

/* clickable list rows (admin orders .trow, drill-in rows): show they open something */
:where(.trow[data-id],.trow[onclick],tr.clickable,tr[data-id],.recon-row,.res-row,.mtbl-row){cursor:pointer}
@media (hover:hover){:where(.trow[data-id],.trow[onclick],tr.clickable,tr[data-id],.recon-row,.res-row,.mtbl-row):hover{background-color:#F3F7FF}
  .chips label:not(:has(input:checked)):hover{border-color:#9DBEFF;background-color:#F3F7FF;color:#0A47C4}}

/* ---- Admin sign-in matches the merchant and partner sign-in pages ----
   Same navy backdrop, white card with the blue-to-cyan top bar, full-width blue button.
   Styling only: the form, its fields and the sign-in script are unchanged. */
.login-wrap{background:radial-gradient(1100px 560px at 85% -12%,#123a86 0%,#0B1428 36%,#0a1020 100%);min-height:100dvh}
.login{position:relative;overflow:hidden;background:#fff;max-width:404px;border-radius:20px;border:1px solid #E4E9F2;
  box-shadow:0 40px 90px -40px rgba(0,0,0,.7);padding:36px 30px 30px}
.login::before{content:"";position:absolute;left:0;right:0;top:0;height:4px;background:linear-gradient(90deg,#0E56E6,#19E3D0)}
.login .mark b{font-weight:800;font-size:1.18rem;letter-spacing:-.02em;color:#0B1220}
.login h1{font-weight:800;font-size:1.35rem;margin:.2rem 0 1.2rem;color:#0B1220}
.login .field label{font-family:inherit;font-size:.8rem;letter-spacing:0;text-transform:none;font-weight:700;color:#334155}
.login .field input{border-color:#E4E9F2;border-radius:10px}
.login .field input:focus{border-color:#0E56E6;box-shadow:0 0 0 3px rgba(46,124,255,.16)}
.login #loginBtn{width:100%;margin-top:10px;justify-content:center;border:none;border-radius:11px;padding:12px;font-size:.98rem;font-weight:700;
  color:#fff;background:linear-gradient(180deg,#0E56E6,#0A47C4);box-shadow:0 4px 14px rgba(46,124,255,.32)}
.login .err{color:#C8463B;font-size:.88rem;margin-top:12px;min-height:1.1em}
@media (max-width:420px){.login{padding:32px 22px 24px}}

/* ================= DESIGN V2 - SPACING RHYTHM =================
   Owner: sections sat too close to each other. One rhythm for the whole admin:
   cards stacked in a page 16px apart, controls in a row 8px apart (10px when a row wraps),
   page headers 20px above their content. Joined controls (segmented toggles, date presets,
   pagers) keep their own tight spacing on purpose. */
#payoutsBody > * + *,#routingBody > * + *,#riskBody > * + *,.view > .card + .card,.view > .card + div,.view > div + .card,
.mp-pane .mp-panel.on > * + *,.gw-tabpane.on > * + *{margin-top:16px}
#payoutsBody > .card{margin-bottom:0}
.toolbar{row-gap:10px;column-gap:10px;flex-wrap:wrap}
.mtbl-quick{gap:8px}
.gw-chips{gap:8px!important}
.rk-cb > div > .btn + .btn,.rk-cb .btn + .btn,.sd-actions .btn + .btn{margin-left:8px}
.sd-actions{display:flex;flex-wrap:wrap;gap:8px}.sd-actions .btn + .btn{margin-left:0}
.rm-attach{gap:8px!important;flex-wrap:wrap}
#rtDecFrom,#rtDecTo{margin:4px 0}
.rt-cb > div[style*="display:flex"]{gap:8px!important;row-gap:10px!important}
/* merchant + partner page header: back link, avatar, name, status and actions, evenly spaced */
#v-merchant-page .mp-top,#v-partner-page .mp-top{display:flex;align-items:center;column-gap:14px;row-gap:12px;flex-wrap:wrap;margin-bottom:20px}
#v-merchant-page .mp-top .mp-spacer,#v-partner-page .mp-top .mp-spacer{flex:1 1 0;min-width:0}
#v-merchant-page .mp-top .mp-who,#v-partner-page .mp-top .mp-who{min-width:0;flex:1 1 220px}
#v-merchant-page .mp-top > .btn + .btn,#v-partner-page .mp-top > .btn + .btn{margin-left:0}
@media (max-width:640px){
  #v-merchant-page .mp-top,#v-partner-page .mp-top{column-gap:12px}
  /* back link alone on the first row, then avatar + name side by side, then status + actions */
  #v-merchant-page .mp-top > .btn:first-child,#v-partner-page .mp-top > .btn:first-child{margin-right:100%}
  #v-merchant-page .mp-top .mp-who,#v-partner-page .mp-top .mp-who{flex:1 1 calc(100% - 64px)}
  #v-merchant-page .mp-top .mp-spacer,#v-partner-page .mp-top .mp-spacer{display:none}
}
/* status tags that sit on top of each other in a cell */
.mtbl-row td .stbadge + .pn-nopay,.mtbl-row td .pn-nopay{margin-top:6px}
td.num .mp-pill + .test-tag,td.num .test-tag{margin-left:6px}
td .mp-pill + .test-tag{display:inline-block;margin-top:4px}
.mp-panel.on > .mp-ready + .mp-card,.mp-ready{margin-bottom:0}

/* Reports: date presets row (wraps on phones) gets the standard gaps and room above the table */
#v-reports > div:has(> .rep-preset){gap:8px!important;row-gap:10px!important;margin:12px 0 16px!important}
/* partner list: status badge and the CANNOT BE PAID warning stacked in one cell */
#v-partners .pn-nopay,.ptl .pn-nopay{display:block!important;width:max-content;margin-top:8px!important;margin-left:0!important}
/* merchant page latest transactions: APPROVED + TEST tags stacked in the amount cell */
#mpOvTxBody td.num .test-tag{margin-top:8px;margin-left:6px}
#mpOvTxBody td.num .mp-pill{margin-bottom:2px}


/* ============================================================================
   ONBOARDING SHELL (.oz-*) - the stepped create wizard and the sectioned editor.

   PHONE FIRST. The old create/edit windows were a single scrolling modal with
   two-column inputs; at 390px a merchant name and its slug were cut off inside
   their own boxes and the monospace labels wrapped mid-phrase. Here the grid is
   ONE column until 640px, every control is full width, no text below 11px, and
   the Back/Next/Save footer is sticky so it is reachable without scrolling to
   the bottom of a long section. On a phone the whole thing is a full-screen
   sheet, which is what a form of this length has to be on a 390px screen.

   Design v2 tokens only: --teal (#0E56E6), --blue, --cyan, --ink, --line, the
   Space Grotesk display face for headings and Hanken Grotesk for body. Helper
   text is body font, NOT the letter-spaced monospace the old form used.
   ============================================================================ */

/* The sheet takes over .modal's box, so the header and footer can stick. */
.modal:has(.oz-sheet){padding:0;width:min(760px,100%);max-height:92vh;overflow:hidden;display:flex}
.oz-sheet{display:flex;flex-direction:column;width:100%;max-height:92vh;overflow:auto;background:var(--bg-2)}

.oz-head{
  position:sticky;top:0;z-index:3;display:flex;align-items:flex-start;gap:12px;
  padding:18px 20px 14px;background:var(--bg-2);border-bottom:1px solid var(--line);
}
.oz-head-t{min-width:0;flex:1}
.oz-head h2{font-family:var(--fd);font-weight:700;font-size:1.25rem;letter-spacing:-.02em;margin:0;color:var(--ink);word-break:break-word}
.oz-sub{font-size:.85rem;line-height:1.45;color:var(--t2);margin-top:4px}
.oz-sub .mono{font-family:var(--fm);font-size:.82rem;color:var(--teal);word-break:break-all}
.oz-x{
  flex:0 0 auto;width:34px;height:34px;border-radius:9px;border:1px solid var(--line);
  background:var(--panel);color:var(--t2);font-size:1.3rem;line-height:1;cursor:pointer;
}
.oz-x:hover{background:var(--panel-3);border-color:var(--line-2);color:var(--ink)}

/* ---- progress indicator (create) ---- */
.oz-prog{
  /* flex:none - inside the column sheet this row otherwise shrinks to ~20px and clips its pills */
  flex:none;display:flex;gap:8px;padding:12px 20px;overflow-x:auto;overflow-y:hidden;background:var(--panel-2);
  border-bottom:1px solid var(--line);scrollbar-width:none;
}
.oz-prog::-webkit-scrollbar{display:none}
.oz-step{
  display:flex;align-items:center;gap:7px;flex:0 0 auto;border:1px solid var(--line);
  background:var(--panel);border-radius:999px;padding:6px 13px 6px 7px;cursor:pointer;
  font:inherit;font-size:.8rem;font-weight:600;color:var(--t3);transition:.14s;
}
.oz-step-n{
  width:20px;height:20px;flex:0 0 auto;border-radius:50%;background:var(--panel-3);color:var(--t3);
  display:flex;align-items:center;justify-content:center;font-size:.72rem;font-weight:700;
}
.oz-step.on{border-color:var(--teal);color:var(--teal);background:var(--teal-50)}
.oz-step.on .oz-step-n{background:var(--teal);color:#fff}
.oz-step.done{color:var(--green);border-color:var(--green-soft)}
.oz-step.done .oz-step-n{background:var(--green-soft);color:var(--green)}

/* ---- section switcher (edit) ---- */
.oz-tabs{
  /* flex:none for the same reason as .oz-prog: the sheet is a flex column with a
     max-height, so without it this row shrinks to ~20px and clips every tab label. */
  flex:none;display:flex;gap:8px;padding:12px 20px;overflow-x:auto;overflow-y:hidden;background:var(--panel-2);
  border-bottom:1px solid var(--line);scrollbar-width:none;
}
.oz-tabs::-webkit-scrollbar{display:none}
.oz-tab{
  flex:0 0 auto;border:1px solid var(--line);background:var(--panel);border-radius:999px;
  padding:7px 14px;cursor:pointer;font:inherit;font-size:.82rem;font-weight:600;color:var(--t3);transition:.14s;
}
.oz-tab.on{border-color:var(--teal);background:var(--teal);color:#fff}
.oz-pane{display:none}
.oz-pane.on{display:block}

/* ---- body ---- */
.oz-body{padding:18px 20px 22px;flex:1}

.oz-grp{margin-bottom:16px}
.oz-grp:last-child{margin-bottom:0}
.oz-grp-h{
  font-family:var(--fd);font-size:.95rem;font-weight:700;color:var(--ink);
  margin:0 0 10px;padding-bottom:8px;border-bottom:1px solid var(--line);
}
.oz-note{font-size:.85rem;line-height:1.5;color:var(--t2);margin:0 0 12px}
.oz-note b{color:var(--ink-2)}

/* ONE COLUMN by default. Two columns are an enhancement for real screens, not
   the baseline - the baseline is the phone this panel is used on. */
.oz-grid{display:grid;grid-template-columns:1fr;gap:14px}
@media (min-width:640px){
  .oz-grid{grid-template-columns:1fr 1fr}
  .oz-f-wide{grid-column:1/-1}
}

.oz-f{display:flex;flex-direction:column;gap:6px;min-width:0}
.oz-f label{
  font-family:var(--f);font-size:.82rem;font-weight:600;color:var(--ink-2);
  letter-spacing:0;text-transform:none;
}
.oz-req{color:var(--teal);margin-left:3px}
.oz-f input,.oz-f select,.oz-f textarea{
  width:100%;box-sizing:border-box;min-width:0;font:inherit;font-size:.92rem;
  padding:10px 12px;border:1px solid var(--line-2);border-radius:10px;
  background:var(--panel);color:var(--ink);transition:.14s;
}
.oz-f textarea{min-height:76px;resize:vertical;line-height:1.5}
.oz-f input::placeholder,.oz-f textarea::placeholder{color:var(--t4)}
.oz-f input:hover,.oz-f select:hover,.oz-f textarea:hover{border-color:var(--t4)}
.oz-f input:focus,.oz-f select:focus,.oz-f textarea:focus{
  outline:none;border-color:var(--teal);box-shadow:0 0 0 3px var(--teal-50);background:#fff;
}
.oz-f.bad input,.oz-f.bad select,.oz-f.bad textarea{border-color:var(--red);background:var(--red-soft)}
.oz-help{font-family:var(--f);font-size:.78rem;line-height:1.45;color:var(--t3)}
.oz-help b{color:var(--t2)}
/* overflow-wrap:anywhere breaks a long URL only when it cannot fit; break-all split short
   examples like "example.com" mid-word on a phone. */
.oz-help .mono{font-family:var(--fm);font-size:.76rem;color:var(--teal);overflow-wrap:anywhere}
.oz-err{display:none;font-size:.78rem;line-height:1.4;color:var(--red);font-weight:600}
.oz-err.on{display:block}

/* ---- toggle ---- */
.oz-tgw{
  display:flex;align-items:center;gap:12px;grid-column:1/-1;
  border:1px solid var(--line);border-radius:12px;padding:12px 14px;background:var(--panel);
}
.oz-tgw.bad{border-color:var(--red)}
.oz-tgt{flex:1;min-width:0}
.oz-tgl{font-size:.88rem;font-weight:600;color:var(--ink)}
.oz-tgc{display:flex;align-items:center;gap:9px;flex:0 0 auto}
.oz-tgs{font-size:.78rem;font-weight:700;color:var(--t3)}
.oz-tog{
  width:44px;height:25px;flex:0 0 auto;border-radius:999px;border:1px solid var(--line-2);
  background:var(--panel-3);cursor:pointer;position:relative;padding:0;transition:.16s;
}
.oz-tog span{
  position:absolute;top:2px;left:2px;width:19px;height:19px;border-radius:50%;
  background:#fff;box-shadow:0 1px 3px rgba(12,19,34,.3);transition:.16s;
}
.oz-tog.on{background:var(--teal);border-color:var(--teal)}
.oz-tog.on span{left:21px}
.oz-tgc .oz-tog.on + .oz-tgs,.oz-tgw:has(.oz-tog.on) .oz-tgs{color:var(--teal)}

/* ---- live restatement (fee examples, cycle explainer, masked account) ---- */
.oz-live{
  grid-column:1/-1;font-size:.83rem;line-height:1.5;color:var(--t2);
  background:var(--teal-50);border:1px solid var(--teal-soft);border-radius:10px;padding:10px 12px;
}
.oz-live b{color:var(--teal);font-weight:700}
.oz-live.warn{background:var(--amber-soft);border-color:#F0DCB4;color:#6E4708}
.oz-live.warn b{color:#6E4708}
.oz-live .mono{font-family:var(--fm);font-size:.8rem;word-break:break-all}

/* ---- review ---- */
.oz-rev{border:1px solid var(--line);border-radius:12px;padding:14px 16px;margin-bottom:16px;background:var(--panel)}
.oz-rev:last-child{margin-bottom:0}
.oz-rev-h{
  display:flex;align-items:center;gap:10px;font-family:var(--fd);font-size:.92rem;font-weight:700;
  color:var(--ink);margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--line);
}
.oz-rev-e{
  margin-left:auto;font:inherit;font-size:.78rem;font-weight:600;color:var(--teal);
  background:none;border:0;cursor:pointer;padding:2px 4px;border-radius:6px;
}
.oz-rev-e:hover{background:var(--teal-50);text-decoration:underline}
.oz-rev-l{display:grid;grid-template-columns:minmax(0,11rem) minmax(0,1fr);gap:7px 14px;margin:0;font-size:.86rem}
.oz-rev-l dt{color:var(--t3);font-weight:500;min-width:0;word-break:break-word}
.oz-rev-l dd{margin:0;color:var(--ink-2);font-weight:600;min-width:0;word-break:break-word}
.oz-rev-l dd.mono{font-family:var(--fm);font-size:.8rem}
.oz-dim{color:var(--t4);font-weight:400}

/* ---- sticky footer ---- */
.oz-foot{
  position:sticky;bottom:0;z-index:3;display:flex;align-items:center;gap:10px;
  padding:13px 20px;background:var(--bg-2);border-top:1px solid var(--line);
  box-shadow:0 -6px 18px -14px rgba(12,19,34,.45);
}
.oz-foot .btn{flex:0 0 auto}
.oz-foot-mid{flex:1;text-align:center;font-size:.78rem;font-weight:600;color:var(--t3);min-width:0}
.oz-foot .btn:last-child{margin-left:auto}
.oz-foot .oz-foot-mid + .btn{margin-left:0}

/* ---- phone: full-screen sheet ---- */
@media (max-width:640px){
  .modal-back:has(.oz-sheet){padding:0;align-items:stretch}
  .modal:has(.oz-sheet){width:100%;max-width:100%;max-height:100vh;height:100dvh;border-radius:0;border:0}
  .oz-sheet{max-height:100dvh;height:100dvh}
  .oz-head{padding:14px 15px 12px}
  .oz-head h2{font-size:1.1rem}
  .oz-prog,.oz-tabs{padding:10px 15px}
  .oz-body{padding:15px 15px 20px}
  .oz-foot{padding:11px 15px;gap:9px}
  .oz-foot .btn{padding:.62em 1.05em;font-size:.86rem}
  .oz-foot-mid{font-size:.72rem}
  .oz-step-l{max-width:9rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* 11px floor: nothing on this form may be smaller than this on a phone. */
  .oz-help,.oz-err,.oz-note,.oz-live,.oz-tgs{font-size:.7rem}
  .oz-f label{font-size:.8rem}
  .oz-f input,.oz-f select,.oz-f textarea{font-size:16px}
  /* Review rows stack: a label + value grid at 390px leaves neither column room. */
  .oz-rev-l{grid-template-columns:1fr;gap:2px}
  .oz-rev-l dd{margin-bottom:8px}
}


/* ============================================================================
   PERFORMANCE TAB (public/js/views/performance.js)

   One stylesheet for BOTH the merchant page and the partner page, because they
   mount the same renderer: a fork here would drift the way the markup would.

   Everything below is token-only. No literal brand hex: var(--teal) IS the
   product blue in this codebase and the palette lock test asserts that the
   retired teal and gold ramps never reappear.
   ============================================================================ */
.pf-wrap{display:flex;flex-direction:column;gap:16px}
.pf-card{margin:0}

/* ---- the control bar: range presets, currency chips, export ---------------
   8-10px between controls, which is tighter than the 16px between cards: the
   controls are one group and the cards are separate objects. */
.pf-bar-top{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:2px}
.pf-spacer{flex:1;min-width:0}
.pf-chips{display:flex;flex-wrap:wrap;gap:8px;min-width:0}
.pf-chip{appearance:none;border:1px solid var(--line-2);background:var(--panel);color:var(--t2);
  border-radius:999px;padding:6px 13px;font:inherit;font-size:.8rem;font-weight:600;
  cursor:pointer;white-space:nowrap;transition:background .12s,border-color .12s,color .12s}
@media (hover:hover){.pf-chip:hover{border-color:var(--teal);color:var(--teal);background:var(--teal-50)}}
.pf-chip:active{transform:translateY(1px)}
.pf-chip:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
/* Filled blue ONLY when selected. A chip that is blue at rest says nothing. */
.pf-chip.on{background:var(--teal);border-color:var(--teal);color:#fff}
@media (hover:hover){.pf-chip.on:hover{background:var(--teal);border-color:var(--teal);color:#fff}}

.pf-custom{display:flex;flex-wrap:wrap;align-items:flex-end;gap:10px;margin:2px 0 0}
.pf-custom label{display:flex;flex-direction:column;gap:4px;font-size:.74rem;font-weight:600;color:var(--t3)}
.pf-in{border:1px solid var(--line-2);background:var(--panel);color:var(--ink);
  border-radius:9px;padding:7px 10px;font:inherit;font-size:.85rem}
.pf-in:focus-visible{outline:2px solid var(--teal);outline-offset:1px;border-color:var(--teal)}
.pf-apply{padding:.5em 1.1em}
.pf-range{font-size:.78rem;color:var(--t3)}
.pf-sub2{font-size:.72rem;color:var(--t4,var(--t3));font-weight:500}
.pf-none{padding:18px 4px;color:var(--t3);font-size:.88rem}

/* ---- headline KPIs and their deltas --------------------------------------- */
.pf-kpis{margin-bottom:0}
/* The shared .mp-kpi label is .68rem = 10.9px, which is under the 11px floor this screen
   holds itself to. Overridden rather than changed at source: the merchant page's own KPI
   strips are a different density and are not this card's to re-space. */
.pf-kpi .k{font-size:.7rem}
.pf-kpi .s{font-size:.7rem;color:var(--t3);margin-top:3px;line-height:1.35}
.pf-d{display:inline-block;font-size:.7rem;font-weight:700;border-radius:999px;padding:1px 7px;white-space:nowrap}
.pf-d.up{background:var(--green-soft);color:var(--green)}
.pf-d.down{background:var(--red-soft);color:var(--red)}
.pf-d.flat{background:var(--panel-3);color:var(--t3)}

/* ---- trend chart ----------------------------------------------------------
   preserveAspectRatio:none on the svg, so the height is set here and the bars
   stretch to the card. A fixed-ratio chart on a phone is 60px tall. */
.pf-chart{display:block;width:100%;height:190px}
.pf-bar{fill:var(--teal-soft)}
.pf-line{stroke-width:2;vector-effect:non-scaling-stroke}
.pf-line.attempts{stroke:var(--t4,var(--t3));stroke-dasharray:4 3}
.pf-line.approved{stroke:var(--teal)}
.pf-ax{fill:var(--t3);font-size:11px;font-family:var(--fm)}
.pf-legend{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin-top:9px;font-size:.74rem;color:var(--t3)}
.pf-lg{display:inline-block;width:14px;height:10px;border-radius:2px;margin-left:8px}
.pf-lg:first-child{margin-left:0}
.pf-lg.bar{background:var(--teal-soft)}
.pf-lg.ln{height:0;border-top:2px solid var(--teal)}
.pf-lg.ln.attempts{border-top-style:dashed;border-top-color:var(--t3)}

/* ---- tables: scroll inside the card, never squeeze ------------------------
   The settlement table is wider than a 390px phone. Without its own scroll box
   it pushes the whole page sideways and takes the rail and header with it. */
.pf-tw{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 -4px;padding:0 4px}
/* NO min-width at desktop size. The obvious version put a 520px floor on every table so
   columns would not crush, but the method and status tables sit two-up in a half-width
   card, and the floor forced a sideways scroll on a table whose content fits - a scroll
   an operator has to discover to read a column that was never too wide. The floor is a
   PHONE rule, applied in the phone block below where the columns genuinely do not fit. */
.pf-t{width:100%;border-collapse:collapse;font-size:.84rem}
.pf-t th{text-align:left;font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;
  font-weight:700;color:var(--t3);padding:0 8px 7px;white-space:nowrap}
.pf-t td{padding:9px 8px;border-top:1px solid var(--line-soft);color:var(--ink-2);vertical-align:top}
/* The settlement table carries eight columns (nine on a partner, which also names the
   merchant), all of them nowrap money or dates. At the standard cell padding it ran 33px
   past a full-width card on the merchant page and 161px on the partner page, forcing a
   sideways scroll on a desktop screen wide enough to show the whole thing. Tightened here
   rather than by dropping a column: every column on it answers a question an operator
   asked, and hiding one to fit is how "why is this smaller than my sales" came back. */
.pf-t.pf-settle th,.pf-t.pf-settle td{padding-left:6px;padding-right:6px}
.pf-t.pf-settle td{font-size:.82rem}
/* The merchant name on a partner's settlement row is the one cell allowed to ellipsis: it
   is a label, not a value, and the row opens the full settlement anyway. Money and dates
   never truncate - a clipped amount is a wrong amount. */
.pf-t.pf-settle td.pf-brand{max-width:110px;overflow:hidden;text-overflow:ellipsis}
.pf-t td.num,.pf-t th.num{text-align:right}
/* A money value never breaks mid-value: "EUR 1,2" over "34.00" is unreadable. */
.pf-t .nowrap,.pf-t td.num{white-space:nowrap}
.pf-t tr.pf-tot td{border-top:2px solid var(--line-2);font-weight:700;background:var(--panel-2)}

.pf-clickable tbody tr{cursor:pointer}
@media (hover:hover){.pf-clickable tbody tr:hover td{background:var(--teal-50)}}
.pf-clickable tbody tr:focus-visible{outline:2px solid var(--teal);outline-offset:-2px}
.pf-clickable tbody tr:active td{background:var(--teal-soft)}
.pf-empty{padding:16px 10px;color:var(--t3)}

/* ---- settlement status, in words ------------------------------------------ */
.pf-st{display:inline-block;font-size:.72rem;font-weight:700;border-radius:999px;
  padding:2px 9px;white-space:normal}
/* The status cell is the only one allowed to wrap, because an unpayable reason is a
   sentence. A floor width on a PHONE, so the reason breaks between words rather than being
   squeezed into a two-character column by the money columns beside it. At desktop size it
   has no floor: the settlement table has eight columns there, and a floor on one of them
   was enough to push the whole table past a full-width card and force a sideways scroll. */
@media (max-width:640px){
  .pf-t td:has(> .pf-st){min-width:150px}
}
.pf-st.ok{background:var(--green-soft);color:var(--green)}
.pf-st.warn{background:var(--amber-soft);color:var(--amber)}
.pf-st.bad{background:var(--red-soft);color:var(--red)}
.pf-st.muted{background:var(--panel-3);color:var(--t3)}

/* ---- structure card: label / value pairs ---------------------------------- */
.pf-defs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 18px}
.pf-def{display:flex;flex-direction:column;gap:2px;min-width:0}
.pf-def .k{font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;font-weight:700;color:var(--t3)}
.pf-def .v{font-size:.88rem;color:var(--ink);font-weight:600;overflow-wrap:anywhere}

.pf-grid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
.pf-grid2 > .pf-card{margin:0}

/* ---- phone --------------------------------------------------------------
   11px is the floor for anything on this screen. Below that the numbers are
   not readable on the device an operator actually checks settlements on. */
/* Width alone is not the test: a phone in desktop-site mode reports a wide
   viewport while still being a touch device. pointer:coarse + hover:none stay
   true there, which is the condition the rest of this stylesheet already uses. */
@media (max-width:900px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  .pf-grid2{grid-template-columns:1fr}
}
@media (max-width:640px){
  .pf-defs{grid-template-columns:1fr}
  .pf-chart{height:160px}
  .pf-bar-top{gap:8px}
  .pf-chip{padding:6px 11px;font-size:.78rem}
  .pf-t{font-size:.8rem;min-width:430px}
  /* Tighter cells on a phone so the settlement table's first three columns - the date, the
     amount and the status - fit inside 390px. The breakdown columns after them are what the
     sideways scroll is for; "is it paid" must not be. */
  .pf-t th{font-size:.7rem;padding:0 7px 6px}
  .pf-t td{padding:8px 7px}
  .pf-sub2,.pf-range,.pf-legend,.pf-kpi .s{font-size:.7rem}
  .pf-d,.pf-st{font-size:.7rem}
  /* Date inputs below 16px make iOS zoom the whole page on focus. */
  .pf-in{font-size:16px}
  .pf-custom label{flex:1 1 44%}
  .pf-custom .pf-in{width:100%}
}
@media (max-width:430px){
  #v-merchant-page .pf-kpis,#v-partner-page .pf-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* A MONEY FIGURE NEVER BREAKS ACROSS LINES, on any screen.

   Measured at 1280 by the QA crawler: "-EUR 1,181.73" split over two rows in a 72px column
   on Reports, and "-INR 68,212.03" over two rows in a 131px column on Player payouts. A
   split amount reads as two different numbers, and these are the screens where that costs
   money. Both tables already scroll inside their own wrapper, so refusing the wrap widens
   the table rather than the page.

   Applied by class, never by bare element, so an embedded third-party table is untouched. */
.dtable td.num,.dtable td.num b,.dtable td.num span,
#v-reports td.num,#v-reports td.num b,#v-reports td.num span{white-space:nowrap}


/* ============================================================================
   REFUNDS HUB (#/refunds)

   Cards, not a table. A refund request is a DECISION with about ten facts behind it
   (the sale, what is already refunded, what is left, who asked and through which
   panel, the reason, the age) and a row of a table either hides most of them or
   slides sideways under a thumb. The operator is often on a phone when a merchant
   messages them about a refund, so 390px is the design width, not an afterthought.
   Same palette as Settlements: navy ink, brand blue action, one card surface.
   ============================================================================ */

.rf-tabs{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 14px}
.rf-tab{
  display:inline-flex;align-items:center;gap:7px;background:var(--bg-2);
  border:1px solid var(--line);border-radius:999px;padding:.5em 1em;cursor:pointer;
  font:inherit;font-size:.84rem;font-weight:700;color:var(--t2);
}
.rf-tab:hover{border-color:var(--line-2);color:var(--ink)}
.rf-tab.on{background:var(--teal);border-color:var(--teal);color:#fff}
.rf-tab-n{
  display:inline-flex;align-items:center;justify-content:center;min-width:1.4em;
  padding:0 .35em;border-radius:999px;background:var(--panel-3);color:var(--t2);
  font-size:.72rem;font-weight:800;
}
.rf-tab.on .rf-tab-n{background:rgba(255,255,255,.22);color:#fff}

.rf-filters{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 16px}
.rf-filters select,.rf-filters input{
  font:inherit;font-size:.85rem;padding:.5em .7em;border:1px solid var(--line);
  border-radius:10px;background:var(--bg-2);color:var(--ink);min-width:0;max-width:100%;
}

/* One column on a phone, two from tablet up. auto-fit rather than a fixed count so a
   single pending request does not sit in a half-width column looking broken. */
.rf-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr));gap:14px}

.rf-card{padding:15px 16px;display:flex;flex-direction:column;gap:9px;min-width:0}
/* A pending request is the only one that still needs something from the operator, so
   it is the only one the eye is pulled to. */
.rf-card-pending{border-top:3px solid var(--teal)}
.rf-card-h{display:flex;align-items:center;gap:10px;justify-content:space-between;flex-wrap:wrap}
.rf-card-m{min-width:0;font-weight:800;overflow-wrap:anywhere}
.rf-card-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.rf-card-f{display:flex;gap:8px;flex-wrap:wrap;margin-top:2px}
.rf-card-f .btn{flex:1 1 auto}

.rf-chip{
  display:inline-block;font-size:.72rem;font-weight:700;border-radius:999px;padding:3px 10px;
  background:var(--panel-3);color:var(--t2);
}
/* A partner asking on behalf of a merchant is NOT the merchant asking, and the colour
   says so before the words are read. */
.rf-chip-partner{background:#EDE9FE;color:#5B21B6}
.rf-chip-merchant{background:var(--teal-soft);color:var(--blue-ink)}
.rf-chip-admin{background:var(--panel-3);color:var(--t2)}

.rf-amt{font-family:var(--fd);font-size:1.5rem;font-weight:800;letter-spacing:-.02em;color:var(--ink);
  display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.rf-amt-tag{font-family:var(--f);font-size:.7rem;font-weight:700;text-transform:uppercase;
  letter-spacing:.04em;color:var(--t3)}
.rf-dim{color:var(--t3);font-size:.78rem}
.rf-age{font-size:.74rem;font-weight:700;color:var(--amber)}
.rf-ok{color:#0E9C6F}
.rf-warn{color:#C8463B}
.rf-ref{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.82rem;overflow-wrap:anywhere}

.rf-kv{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:5px 12px;margin:0;font-size:.85rem}
.rf-kv dt{color:var(--t3);font-weight:700;font-size:.72rem;letter-spacing:.02em;text-transform:uppercase;
  padding-top:2px}
.rf-kv dd{margin:0;min-width:0;color:var(--ink);font-weight:600;overflow-wrap:anywhere}

.rf-empty{padding:22px 18px;text-align:center}

/* The decision sheet reuses the settlement Pay sheet's chrome (.oz-sheet, .pay-grp,
   .pay-kv) so a money decision looks and behaves the same wherever it is taken. */
/* Three buttons in the refund sheet footer leave no room for the caption on a phone:
   it was squeezed into a one-word column between Cancel request and Approve. */
@media (max-width:560px){.rf-sheet .oz-foot-mid{display:none}}
.rf-sheet .rf-effect{
  background:var(--teal-soft);border:1px solid var(--line);border-radius:12px;padding:13px 14px;
}
.rf-sheet .rf-effect .pay-grp-h{color:var(--blue-ink)}
/* The sentence under the deduction: the buyer got the whole payment back, and the fee on the
   sale is not returned. Secondary weight, because it explains the figure above it rather than
   being a second figure. It must wrap: it is a full clause, not a label. */
.rf-sheet .rf-effect .rf-sub{
  font-weight:500;font-size:.78rem;color:var(--t3);margin-top:3px;line-height:1.45;
  max-width:44ch;white-space:normal;overflow-wrap:anywhere;
}
/* THE LABEL MUST GIVE WAY, NOT OVERFLOW. .pay-kv dt is white-space:nowrap, which is right
   for the settlement sheet's one-word labels but not here: "Deducted from the merchant" is
   four words, and on a phone the label column is 5.6rem, so the nowrap label ran straight
   out of its cell and painted on top of the sub-line under the figure - the operator read
   the deduction wording through the label sitting on it. These labels wrap instead, and the
   pair is aligned to the top so a two-line label and a two-line value start together. */
.rf-sheet .rf-effect .pay-kv dt{
  white-space:normal;align-self:start;line-height:1.3;
}
.rf-sheet .rf-effect .pay-kv dd{align-self:start}
/* ON A PHONE THE PAIR STACKS. The shared .pay-kv gives the label a 5.6rem column because
   its own labels are one or two short words; these are up to four, and wrapping them into
   that column turned "Deducted from the merchant" into four lines in 90px - a label taller
   than the figure it names. Label over value uses the width that is actually there, and
   this block is short enough that the extra height costs nothing an operator scrolls past. */
@media(max-width:640px){
  .rf-sheet .rf-effect .pay-kv{grid-template-columns:1fr;gap:0}
  .rf-sheet .rf-effect .pay-kv dt{
    padding:10px 0 0;border-bottom:0;white-space:normal;
  }
  .rf-sheet .rf-effect .pay-kv dd{
    text-align:left;padding:2px 0 10px;
  }
  .rf-sheet .rf-effect .pay-kv dd .rf-sub{text-align:left;max-width:none}
}

@media(max-width:640px){
  .rf-grid{grid-template-columns:1fr;gap:12px}
  .rf-card{padding:13px 14px}
  .rf-amt{font-size:1.3rem}
  .rf-kv{grid-template-columns:minmax(0,6.2rem) minmax(0,1fr);gap:5px 10px;font-size:.82rem}
  .rf-filters select,.rf-filters input{flex:1 1 44%}
  .rf-tab{padding:.45em .85em;font-size:.8rem}
}

/* The count of anything waiting behind the phone "More" tab. Without it a refund request
   needing a decision was invisible on a handset until the drawer was opened for some
   other reason - the sidebar badge lives inside that drawer. */
.tabbar .tb-more{position:relative}
.tabbar .tb-dot{
  position:absolute;top:1px;left:calc(50% + 6px);min-width:17px;height:17px;padding:0 4px;
  border-radius:999px;background:#C8463B;color:#fff;font-size:.7rem;font-weight:800;
  display:flex;align-items:center;justify-content:center;line-height:1;
}

/* THE ONE-TIME REFUND CORRECTION. Its own small block, reusing the refund sheet's chrome,
   because it is the same kind of decision: a named signature over a money figure.

   The flag on the card is amber rather than red: the state is wrong on the books but nothing
   is broken for the operator right now, and a red banner on a settled refund reads as an
   incident. */
.rc-flag{
  font-size:.78rem;font-weight:600;line-height:1.45;color:#8A5A00;
  background:var(--amber-soft,#FFF6E5);border:1px solid #F0D9A8;border-radius:9px;
  padding:8px 10px;overflow-wrap:anywhere;
}
.rc-sheet .rc-why p{margin:0;font-size:.85rem;line-height:1.55;color:var(--t2)}
/* EVERY SETTLEMENT, BEFORE AND AFTER, as a table because that is what it is: one row per
   settlement, three comparable figures per row. Tabular numerals so the columns line up and
   a changed figure is visible without reading it. */
.rc-table{width:100%;border-collapse:collapse;font-size:.8rem;margin:0 0 10px}
.rc-table th{
  text-align:left;font-size:.7rem;text-transform:uppercase;letter-spacing:.03em;
  color:var(--t3);font-weight:700;padding:0 8px 6px 0;border-bottom:1px solid var(--line);
}
.rc-table th:not(:first-child):not(:nth-child(2)){text-align:right}
.rc-table td{padding:7px 8px 7px 0;border-bottom:1px solid var(--line);vertical-align:top}
.rc-table .rc-n{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.rc-table tr.rc-sale td{background:var(--panel-3,#F6F8FC)}
.rc-table tr.rc-land td{background:var(--teal-soft);font-weight:700}
.rc-table .rf-sub{font-weight:500;font-size:.72rem;color:var(--t3);margin-top:2px;max-width:12rem}
.rc-ok{
  margin:0;font-size:.78rem;line-height:1.5;color:#0B6B4F;background:#E6F8EE;
  border:1px solid #BFE8D4;border-radius:9px;padding:8px 10px;
}
/* ON A PHONE THE TABLE STACKS. Five columns in 390px is 60px a column, which turns every
   money figure into two lines and makes the comparison unreadable. Each settlement becomes
   its own labelled block instead: the label comes from the header via data-l, so there is one
   source for the wording. */
@media(max-width:640px){
  .rc-table,.rc-table tbody,.rc-table tr,.rc-table td{display:block;width:100%}
  .rc-table thead{display:none}
  .rc-table tr{
    border:1px solid var(--line);border-radius:10px;padding:9px 11px;margin:0 0 9px;
  }
  .rc-table tr.rc-sale,.rc-table tr.rc-land{border-color:var(--teal)}
  .rc-table td{border:0;padding:3px 0;display:flex;justify-content:space-between;gap:10px}
  .rc-table td.rc-n::before{
    content:attr(data-l);font-size:.7rem;text-transform:uppercase;letter-spacing:.02em;
    color:var(--t3);font-weight:700;
  }
  .rc-table td:first-child{font-weight:800;display:block}
  .rc-table .rf-sub{max-width:none}
}

/* KuCoin 3b (receiving wallets & routing): on a phone each row becomes a card.
   A sideways-scrolling table hid the coin chips and the "right now" status -
   the two columns that say where a buyer's money is going. */
@media (max-width:640px){
  .kc-stack{border:0;overflow:visible}
  .kc-stack .dp-table thead{display:none}
  .kc-stack .dp-table,.kc-stack .dp-table tbody,.kc-stack .dp-table tr,.kc-stack .dp-table td{display:block;width:100%}
  .kc-stack .dp-table tr{border:1px solid var(--line);border-radius:10px;margin-bottom:10px;padding:4px 0}
  .kc-stack .dp-table td{border-top:0;padding:6px 12px}
  .kc-stack .dp-table td[data-label]::before{content:attr(data-label);display:block;font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--t3);margin-bottom:4px}
  .kc-stack .dp-table td.kc-empty{display:none}
  .kc-stack .dp-table select.dp-in{width:100%}
}

/* ---- Settle partner (public/js/partner-settle.js) ---- */
.po-pwallet{display:flex;align-items:baseline;gap:8px;padding:0 20px;margin-top:6px;font-size:.78rem;color:var(--t2);flex-wrap:wrap}
.po-pwallet-k{font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--t3)}
.po-pwallet .mono{font-weight:700;color:var(--ink);overflow-wrap:anywhere}
.po-pstack{display:block;min-width:0;overflow-wrap:anywhere}
.po-pcov{display:block;font-size:.76rem;color:var(--ink-2);white-space:nowrap}
.po-pcov b{font-family:var(--fd);font-weight:800;color:var(--t3);margin-right:2px}
.po-pcov em{display:block;font-style:normal;font-size:.7rem;color:var(--t3)}
.pset-ccy{display:flex;flex-direction:column;gap:8px;padding:0 0 12px;border-bottom:1px solid var(--line)}
.pset-ccy:last-child{border-bottom:0}
.pset-ccy.off .pset-cyc{opacity:.45}
.pset-cyc{padding:0 4px 0 12px;border-left:3px solid var(--teal-soft);margin-left:6px}
.pset-k{font-size:.7rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--teal);margin:4px 0 2px}
.pset-txbtn{margin-top:8px;background:none;border:1px solid var(--line);border-radius:999px;padding:5px 12px;
  font-size:.76rem;font-weight:700;color:var(--blue);cursor:pointer}
.pset-txbtn:hover{border-color:var(--blue)}
.pset-tx{margin-top:8px;max-height:280px;overflow:auto}
.pset-tx .po-table td,.pset-tx .po-table th{font-size:.76rem;padding:7px 9px}
@media (max-width:640px){
  .po-pwallet{padding:0 var(--po-s3,14px)}
  .po-pcov{white-space:normal;margin-bottom:4px}
  .po-pstack{text-align:right;max-width:62%}
  .pset-cyc{padding-left:9px;margin-left:2px}
}

/* ===========================================================================
   WHAT THE CHECKOUT SHOWS (co-xpl*, sl-*)

   Amber, because this is a WARNING and not a failure: the row is configured
   correctly, something downstream hides it. Red would read as "this is broken",
   green-only would let it disappear into the page - the whole point is that the
   operator could not see the gate.

   Phone first: the line sits UNDER the row it explains and wraps, so a long
   reason never pushes the toggle off a 390px screen (the earlier version put
   the reason beside the switch and did exactly that).
   =========================================================================== */
.co-xpl{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin:4px 0 8px;padding:6px 10px;border-radius:8px;font-size:.78rem;line-height:1.45}
.co-xpl-off{background:var(--amber-soft);border:1px solid #F0DCB4;color:#6E4708;font-weight:600}
.co-xpl-on{background:var(--green-soft,#E6F8EE);border:1px solid #BEEBD5;color:#0E9C6F;
  font-weight:600;font-size:.72rem;padding:3px 9px;opacity:.9}
.co-xpl-btn{background:var(--amber);border:0;border-radius:7px;color:#fff;
  font-size:.74rem;font-weight:700;padding:4px 11px;cursor:pointer;white-space:nowrap}
.co-xpl-btn:hover{filter:brightness(1.08)}
.co-xpl-btn:disabled{opacity:.6;cursor:default}
.co-xpl-soft{font-size:.76rem;color:var(--t3);margin:0 0 10px;font-style:normal}

/* Live on checkout list (Providers area) */
.sl-wrap{display:flex;flex-direction:column;gap:14px}
.sl-fam{border:1px solid var(--bd);border-radius:10px;background:var(--card);overflow:hidden}
.sl-fam-h{font-size:.72rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
  color:var(--t3);padding:9px 13px;border-bottom:1px solid var(--line);background:var(--panel-3)}
.sl-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:10px 13px;
  border-bottom:1px solid var(--line)}
.sl-row:last-child{border-bottom:0}
.sl-main{flex:1;min-width:0}
.sl-name{font-weight:650;font-size:.9rem}
.sl-meta{font-size:.74rem;color:var(--t3);margin-top:2px;overflow-wrap:anywhere}
.sl-chip{display:inline-block;font-size:.7rem;font-weight:700;padding:.16em .62em;border-radius:999px;
  border:1px solid var(--line)}
.sl-chip-live{background:var(--green-soft,#E6F8EE);color:#0E9C6F;border-color:#BEEBD5}
.sl-chip-not{background:var(--amber-soft);color:#6E4708;border-color:#F0DCB4}
.sl-chip-planned{background:var(--panel-3);color:var(--t3)}
.sl-act{display:flex;align-items:center;gap:8px;flex-shrink:0}
.sl-note{font-size:.76rem;color:var(--t3);margin:0 0 10px}
/* Our cost per solution (Providers area) */
.sc-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 8px}
.sc-sum{font-size:.82rem;color:var(--t2)}
.sc-red{color:#C2410C}
.sc-chip-miss{background:#FDECEC;color:#B42318;border-color:#F5C2C0}
.sc-src{font-size:.7rem;color:var(--t3);margin-top:2px}
.sc-in{display:flex;align-items:center;gap:6px;font-size:.8rem;color:var(--t3)}
.sc-in label{display:flex;align-items:center;gap:4px;white-space:nowrap}
.sc-in input{border:1px solid var(--bd);border-radius:7px;padding:5px 7px;font:inherit;font-size:.82rem;
  background:var(--card);color:var(--t1)}
.sc-pct{width:72px}.sc-fix{width:78px}.sc-ccy{width:52px;text-transform:uppercase}
/* By provider terminal: one cost line per (terminal, method) */
.sc-sec-h{font-size:.9rem;font-weight:650;color:var(--t1);margin:4px 0 6px}
.sc-term{margin-bottom:12px}
.sc-term .sl-fam-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.sc-tid{font-size:.72rem;color:var(--t3);word-break:normal;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.sc-tmeta{font-size:.72rem;color:var(--t3);font-weight:400}
.sc-unset{font-size:.72rem;color:#B42318;margin-top:2px}
.sc-wait{color:#6E4708}
@media (max-width:640px){
  .sl-row{align-items:flex-start}
  .sl-act{width:100%}
  .sl-act .btn{flex:1}
  .sc-in{flex-wrap:wrap}
  .co-xpl{font-size:.76rem}
  .sc-trow{flex-wrap:wrap}
  .sc-trow .sl-main{flex:1 1 100%;min-width:0}
}

/* Price per solution (Merchant > Fees & pricing) */
#mpSpBody .sc-in input::placeholder{color:var(--t3);opacity:.5}
#mpSpBody .sl-chip{white-space:nowrap}
@media (max-width:640px){
  #mpSpBody .sl-act{flex-wrap:wrap;gap:8px}
  #mpSpBody .sl-act > .sl-chip{flex:0 0 auto}
  #mpSpBody .sl-act > .sc-in{flex:1 1 100%;flex-wrap:nowrap}
  #mpSpBody .sc-in .btn{white-space:nowrap}
}

/* Support groups (Settings) */
.sup-add{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.sup-in{flex:1;min-width:150px;padding:8px 10px;border-radius:8px;border:1px solid var(--line,rgba(128,128,128,.35));background:transparent;color:inherit;font:inherit}
.sup-list{display:flex;flex-direction:column;gap:8px}
.sup-row{display:flex;align-items:center;gap:12px;padding:11px 13px;border:1px solid var(--line,rgba(128,128,128,.25));border-radius:12px}
.sup-main{flex:1;min-width:0}
.sup-t{font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sup-s{font-size:.8rem;color:var(--t3)}
.sup-c{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.sup-tg{display:flex;align-items:center;gap:5px;font-size:.84rem;white-space:nowrap}
@media (max-width:600px){.sup-add{flex-direction:column}.sup-add .sup-in,.sup-add .btn{flex:none;width:100%;min-width:0}.sup-row{flex-direction:column;align-items:stretch}.sup-c{justify-content:space-between}}


/* ===========================================================================
   AGENTS (#/agents, #/agents/<name>)

   THE DEFECT THIS FIXES, measured at 390px on the QA stage:

     roster       .tbl-wrap.ag-tbl   scrollWidth 455 / clientWidth 358   +97
     payout queue .tbl-wrap          scrollWidth 437 / clientWidth 358   +79
     applications .tbl-wrap          scrollWidth 369 / clientWidth 358   +11

   The wrapper does scroll, so the PAGE never moved sideways - but a scroll box
   nobody can see is not a fix. The seven-column roster was told width:100%, so
   rather than scrolling it squeezed "QA Agent X" into one character per line and
   cut "US$246.40 owed" off at the card edge: a money figure the operator cannot
   read, which is the one thing this screen exists to show.

   The house answer on every other money screen - Settlements (.po-table), Risk
   centre (.rc-table), receiving wallets (.kc-stack) - is ONE CARD PER ROW with
   each cell labelled, and that is what is reused here. Nothing is hidden, nothing
   is truncated, and there is nothing to swipe for. Labels come from each table's
   own <thead> at paint time (agLabelTables in views/agents.js), so a new column
   cannot ship unlabelled.

   Desktop is untouched: these rules live inside the phone query only.
   =========================================================================== */

/* Money and rates never break mid-value, at any width. "US$246.40" split over two
   lines reads as two numbers, and this is a screen where that costs money. */
/* Each half of a balance is one unbreakable run: "US$246.40 owed" must never split
   across two lines, or it stops reading as one figure. The space BETWEEN the two runs
   is an ordinary break opportunity, which is what lets the cell stack on a phone. */
.ag-bal-v,.ag-bal-a{white-space:nowrap;display:inline-block}
.ag-tbl td.r,.ag-tbl td.r b,.ag-tbl td.r span,
#v-agents td.r,#v-agents td.r b,#v-agents td.r span,
#v-agent-page td.r,#v-agent-page td.r b,#v-agent-page td.r span{white-space:nowrap}

@media (max-width:820px),(pointer:coarse) and (hover:none) and (max-width:1400px){
  /* The wrapper stops being a scroll box: there is nothing left to scroll. */
  #v-agents .tbl-wrap,#v-agent-page .tbl-wrap{overflow-x:visible}
  #v-agents .ag-cards,#v-agent-page .ag-cards{
    display:block;background:none;border:0;box-shadow:none;border-radius:0;overflow:visible;
  }
  #v-agents .ag-cards thead,#v-agent-page .ag-cards thead{display:none}
  #v-agents .ag-cards tbody,#v-agent-page .ag-cards tbody,
  #v-agents .ag-cards tr,#v-agent-page .ag-cards tr{display:block;width:auto}
  #v-agents .ag-cards tbody tr,#v-agent-page .ag-cards tbody tr{
    border:1px solid var(--line);border-radius:10px;background:var(--bg-2);
    padding:8px 12px;margin-bottom:10px;box-shadow:var(--sh-sm);
  }
  #v-agents .ag-cards td,#v-agent-page .ag-cards td{
    display:flex;justify-content:space-between;align-items:baseline;gap:12px;
    border:0;padding:5px 0;text-align:right;min-width:0;
  }
  #v-agents .ag-cards td::before,#v-agent-page .ag-cards td::before{
    content:attr(data-l);flex:0 0 auto;text-align:left;white-space:nowrap;
    font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--t3);
  }
  /* A cell with no header (an action column) is a full-width row, not a labelled
     field: without this it reads as an empty entry with a button floating in it. */
  #v-agents .ag-cards td:not([data-l]),#v-agent-page .ag-cards td:not([data-l]){
    display:block;text-align:left;padding-top:8px;
  }
  /* The first cell is the row's identity (the agent, the client, the applicant),
     so it leads the card as a heading rather than sitting in a label/value pair. */
  #v-agents .ag-cards td:first-child,#v-agent-page .ag-cards td:first-child{
    display:block;text-align:left;font-size:1rem;padding-bottom:7px;margin-bottom:3px;
    border-bottom:1px solid var(--line-soft);
  }
  #v-agents .ag-cards td:first-child::before,#v-agent-page .ag-cards td:first-child::before{content:none}
  /* The value side may wrap (a long email, a wallet address); the LABEL never does,
     and a money figure never does - that is the rule above. */
  #v-agents .ag-cards td > .muted,#v-agent-page .ag-cards td > .muted,
  #v-agents .ag-cards td .mono,#v-agent-page .ag-cards td .mono{overflow-wrap:anywhere}
  /* Several balances stack inside one cell. Each FIGURE stays whole (the runs are
     nowrap below), but the line may break between "owed" and "accrued", so a
     three-currency cell stacks inside the card instead of running past it. */
  #v-agents .ag-cards .ag-bal{display:block;white-space:normal}
  /* A cell holding a STACK of balances is not a one-line label/value pair: the label
     "Owed / accrued" and a three-currency stack cannot share 332px, which left the
     widest row 39px past the card. The label takes its own line and the figures use
     the full card width under it. Only cells that actually carry a stack are affected;
     every other field keeps the compact label-left value-right row. */
  #v-agents .ag-cards td:has(.ag-bal){display:block;text-align:left}
  #v-agents .ag-cards td:has(.ag-bal)::before{display:block;margin-bottom:3px}
  #v-agents .ag-cards td:has(.ag-bal) .ag-bal{text-align:right}
  /* Action buttons sit side by side and reach the 44px touch target. */
  #v-agents .ag-cards td .btn,#v-agent-page .ag-cards td .btn{margin:3px 6px 3px 0}
}

/* Blocked countries card (merchants.js mpCountryBlock) */
.mp-cb-chips{display:flex;flex-wrap:wrap;gap:6px}
.mp-cb-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;background:var(--line-soft,#F1F5F9);border:1px solid var(--line,#E2E8F0);font-size:.85rem;color:var(--t1,#0F172A)}
.mp-cb-chip b{font-weight:700;letter-spacing:.02em}
.mp-cb-x{border:0;background:none;cursor:pointer;font-size:1rem;line-height:1;color:var(--t3,#64748B);padding:0 0 0 2px}
.mp-cb-x:hover{color:var(--warn,#c67)}
.mp-cb-in{text-transform:uppercase}
.mp-cb-in::placeholder{text-transform:none}
