/* accounts.moula.world control panel
 *
 * The design arrives as one page of inline styles. Pulled apart into classes
 * here so the templates stay readable, a colour changes in one place, and the
 * hover and responsive rules that inline styles cannot express have somewhere
 * to live.
 *
 * Square corners throughout, 2px at most. That is the house look across
 * moula.world and it is what separates this from the rounded product panels:
 * this is the ledger, and it should feel like one.
 */

/* Fonts, served from this origin.
 *
 * Never from Google. A <link> to fonts.googleapis.com makes every customer's
 * browser announce itself to Google — address, user agent, the page they are
 * on — on every visit to their own control panel. This is a product sold on
 * not knowing much about the customer: no KYC, paid in crypto, reachable over
 * a hidden service. Handing a third party the visitor log contradicts the
 * whole proposition.
 *
 * It is also faster. A stylesheet on another origin blocks the first paint
 * until it arrives, which is a DNS lookup, a TLS handshake and a round trip
 * before anything is on screen.
 *
 * Archivo is a variable font and Google serves the same file for 400, 500 and
 * 600, so it is stored once and declared across the range.
 */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/archivo-variable-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/archivo-variable-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('/assets/fonts/barlow-300-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('/assets/fonts/barlow-300-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/barlow-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/barlow-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/barlow-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/barlow-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/ibm-plex-mono-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --bg: #050505;
  --panel: #0A0A0A;
  --panel-2: #0E0E0E;
  --ink: #EDEAE6;
  --ink-bright: #FFFFFF;
  --muted: #A5A099;
  /* Lifted from #6E6A64 and #5F5B55.
     
     Both are used at 12–13px — the date under an invoice number, the uppercase
     field labels — and at that size they measured 3.68:1 and 2.94:1 against the
     panel, under the 4.5:1 that small text needs to be comfortably legible.
     They now sit at 5.6:1 and 4.6:1, still clearly quieter than --muted above
     them, so the hierarchy is intact and only the floor moved. */
  --dim: #8D8880;
  --dimmer: #7F7971;
  --accent: #F0912D;
  --accent-hi: #FFB25E;
  --good: #8FD1A9;
  --bad: #D9534F;
  --line: rgba(255, 255, 255, .07);
  --line-2: rgba(255, 255, 255, .10);

  --head: Archivo, Helvetica, Arial, sans-serif;
  --body: Barlow, Helvetica, Arial, sans-serif;
  /* The switcher is shared with my.buckets.ninja and wears its type, so the
     same component reads the same on both sites. */
  --mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, monospace;
}

* { box-sizing: border-box }
html, body { margin: 0; padding: 0; background: var(--bg) }
body { color: var(--ink); font-family: var(--body); -webkit-font-smoothing: antialiased }
a { color: var(--accent); text-decoration: none; transition: color .15s }
a:hover { color: var(--accent-hi) }
::selection { background: var(--accent); color: #0A0A0A }
input, textarea, select { font-family: var(--body) }
input::placeholder, textarea::placeholder { color: var(--dimmer) }

/* ---- shell ---- */

.pa-shell { min-height: 100vh; display: grid; grid-template-columns: 242px 1fr }

.pa-side {
  background: var(--panel);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
  padding: 22px 14px; gap: 26px;
  position: sticky; top: 0; height: 100vh;
}
.pa-side-logo { padding: 4px 10px 0 }
.pa-side-logo img { height: 34px; width: auto; display: block }

.pa-nav { display: flex; flex-direction: column; gap: 2px }
.pa-nav > a {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 12px;
  border-radius: 2px;
  font-size: 16px; font-weight: 400;
  color: var(--muted);
  border-left: 2px solid transparent;
}
.pa-nav > a:hover { background: rgba(255, 255, 255, .04); color: var(--ink) }
.pa-nav > a.on { background: rgba(240, 145, 45, .10); color: var(--accent); border-left-color: var(--accent) }
.pa-nav > a svg { width: 17px; height: 17px; flex: none }
/* The badge is the one thing in the sidebar allowed to shout. */
.pa-badge {
  margin-left: auto; min-width: 19px; height: 19px; padding: 0 6px;
  border-radius: 2px; background: var(--accent); color: #0A0A0A;
  font-size: 13px; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}

/* Second level, for the wallet's tabs. Indented under their parent rather than
   promoted to the top level, so the sidebar keeps five entries however many
   sub-pages exist. */
.pa-subnav { display: none; flex-direction: column; gap: 2px; padding: 0 0 4px 31px }
.pa-subnav[data-open="true"] { display: flex }
.pa-subnav a {
  padding: 8px 12px; border-radius: 2px;
  font-size: 15px; font-weight: 300; color: var(--muted);
  border-left: 1px solid rgba(255, 255, 255, .10);
}
.pa-subnav a:hover { color: var(--ink) }
.pa-subnav a.on { color: var(--accent); border-left-color: var(--accent) }

.pa-products { display: flex; flex-direction: column; gap: 2px }
.pa-products-h {
  font-size: 11px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--dimmer); padding: 0 12px 10px;
}
.pa-products a {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 12px; border-radius: 2px;
  font-size: 15px; font-weight: 300; color: var(--muted);
}
.pa-products a:hover { background: rgba(255, 255, 255, .04); color: var(--ink) }
.pa-dot { width: 6px; height: 6px; flex: none }
.pa-out { margin-left: auto; color: var(--dimmer) }

/* The balance sits at the foot of the sidebar on every page. It is the number
   a customer opens this panel to check, and putting it here means they never
   have to navigate to see it. */
.pa-side-foot {
  margin-top: auto; border-top: 1px solid var(--line);
  padding-top: 16px; display: flex; flex-direction: column; gap: 10px;
}
.pa-side-wallet { padding: 0 12px }
.pa-side-foot .pa-btn { padding: 11px; font-size: 14px }
.pa-side-out { padding: 9px 12px; font-size: 15px; font-weight: 300; color: var(--dim) }
.pa-side-out:hover { color: var(--ink) }
/* Sign out is a POST now (a GET logout is forgeable), so the control is a button
   in a tiny form. Make that button wear the link's clothes: no chrome, inherit
   the type, fill the row. The form itself adds no box. */
.pa-out-form { margin: 0; display: block; width: 100% }
button.pa-side-out, button.pa-menu-out {
  background: none; border: 0; cursor: pointer; font: inherit; width: 100%;
  text-align: left; display: block;
}
.pa-who { padding: 0 12px; min-width: 0 }
.pa-who-name { font-size: 15px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
.pa-who-mail { font-size: 14px; color: var(--dimmer); overflow: hidden; text-overflow: ellipsis; white-space: nowrap }

.pa-caret { margin-left: auto; font-size: 11px; color: inherit; opacity: .8 }

.pa-main { min-width: 0; display: flex; flex-direction: column }

/* ---- top bar ---- */

.pa-top {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 0 34px; height: 60px;
  border-bottom: 1px solid var(--line); background: var(--panel);
  position: sticky; top: 0; z-index: 15;
}
.pa-top-title { font-size: 13px; letter-spacing: .2em; text-transform: uppercase; color: var(--muted) }
.pa-top-right { display: flex; align-items: center; gap: 20px }
.pa-status {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; letter-spacing: .12em; text-transform: uppercase; color: #4A9E6A;
  text-decoration: none;
}
.pa-status:hover { opacity: .8 }
.pa-status-dot { width: 6px; height: 6px; border-radius: 50%; background: #4A9E6A }
/* Something on the status page is down: amber text and dot, plus a soft glow so
   it draws the eye without shouting. */
.pa-status.degraded { color: #E0A030 }
.pa-status.degraded .pa-status-dot { background: #E0A030; box-shadow: 0 0 6px #E0A030 }

/* A button and the menu it opens. Positioned relative so the menu hangs off
   the button rather than off the page. */
.pa-pop { position: relative }
.pa-pop-btn {
  width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: 2px;
  background: none; color: var(--muted); cursor: pointer;
}
.pa-pop-btn:hover { color: var(--ink); border-color: var(--line-2) }
.pa-pop-btn svg { width: 17px; height: 17px }
.pa-avatar {
  width: 30px; height: 30px; border-radius: 50%; border: 0; cursor: pointer;
  background: linear-gradient(135deg, #F5A73F, #E07C12); color: #0A0A0A;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--head); font-size: 15px;
}

.pa-menu {
  display: none; position: absolute; right: 0; top: calc(100% + 10px);
  min-width: 280px;
  background: var(--panel); border: 1px solid var(--line-2); border-radius: 2px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .5);
  z-index: 60; overflow: hidden;
}
.pa-menu[data-open="true"] { display: block }
.pa-menu-apps { min-width: 270px }
.pa-menu-h {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 13px 16px; border-bottom: 1px solid var(--line);
  font-size: 15px; font-weight: 600; color: var(--ink);
}
.pa-menu-who { padding: 13px 16px; border-bottom: 1px solid var(--line); min-width: 0 }
.pa-menu-item {
  display: block; padding: 11px 16px; font-size: 15px; color: var(--ink);
  border-bottom: 1px solid var(--line);
}
.pa-menu-item:last-child { border-bottom: 0 }
.pa-menu-item:hover { background: rgba(255, 255, 255, .04); color: var(--ink) }
.pa-menu-out { color: var(--dim) }

/* One product in the switcher. */
.pa-app {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 14px; border-bottom: 1px solid var(--line); color: var(--muted);
}
.pa-app:last-child { border-bottom: 0 }
.pa-app:hover { background: rgba(255, 255, 255, .04) }
.pa-app-mark {
  width: 30px; height: 30px; flex: none; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  font: 600 15px var(--mono);
}
.pa-app-n { display: block; font-size: 15px; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.pa-app-t { display: block; font-size: 13px; color: var(--dimmer); white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.pa-app-cur {
  margin-left: auto; font: 600 10px var(--mono); letter-spacing: .08em;
  color: var(--dimmer); flex: none;
}

/* Mobile header, replacing the sidebar below 1000px.
   Fixed rather than sticky: sticky is constrained by its parent's box, and in
   this grid-inside-flex shell it scrolled away entirely, so the only way back
   to the menu was to scroll to the top of the page. */
.pa-mhead {
  display: none;
  position: fixed; top: 0; left: 0; right: 0; z-index: 40;
  align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 20px; height: 70px;
  background: rgba(5, 5, 5, .94); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.pa-mhead img { height: 28px; display: block }
.pa-burger {
  width: 40px; height: 40px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 5px;
  border: 1px solid rgba(255, 255, 255, .14); border-radius: 2px;
  background: none; cursor: pointer;
}
.pa-burger span { width: 16px; height: 1.5px; background: var(--ink); display: block }

/* The drawer covers the page rather than pushing it down, and scrolls inside
   itself. overscroll-behavior stops a flick at its end from carrying on into
   the page behind it. */
.pa-drawer {
  display: none;
  position: fixed; top: 70px; left: 0; right: 0; bottom: 0; z-index: 39;
  background: var(--bg); border-top: 1px solid var(--line);
  padding: 16px 20px 32px;
  overflow-y: auto; overscroll-behavior: contain;
}
.pa-drawer[data-open="true"] { display: flex; flex-direction: column; gap: 18px }
.pa-drawer-foot { display: flex; flex-direction: column; gap: 8px; border-top: 1px solid var(--line); padding-top: 14px }
/* While it is open the page underneath must not move. */
body.pa-locked { overflow: hidden }

.pa-body {
  padding: 34px; max-width: 1280px; width: 100%;
  display: flex; flex-direction: column; gap: 16px;
}
/* The heading and its line are one block, 7px apart, so the 16px gap above
   applies between the block and the content rather than between the two. */
.pa-head { display: flex; flex-direction: column }
.pa-h1 { margin: 0 0 7px; font: 400 33px var(--head); letter-spacing: -.02em; color: var(--ink-bright) }
.pa-sub { margin: 0; font-size: 16px; font-weight: 300; color: var(--muted) }

/* ---- surfaces ---- */

.pa-card { background: var(--panel); border: 1px solid var(--line); border-radius: 2px }
.pa-card-pad { padding: 24px }
/* Card headers are the design's eyebrow: small, tracked, upper. Every card
   wears the same one, so a heading never has to be styled at the call site. */
.pa-card-h {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 17px 22px; border-bottom: 1px solid var(--line);
  font-size: 13px; letter-spacing: .2em; text-transform: uppercase; color: var(--muted);
}
/* Links and counts inside a header opt out of the tracking. */
.pa-card-h a, .pa-card-h .pa-dim { letter-spacing: 0; text-transform: none }

/* Column ratios come in as a --cols custom property rather than as an inline
   grid-template-columns, because an inline value beats a media query and left
   every two-column row uncollapsed on a phone. */
.pa-g4 { display: grid; grid-template-columns: var(--cols, repeat(4, 1fr)); gap: 14px }
.pa-g3 { display: grid; grid-template-columns: var(--cols, repeat(3, 1fr)); gap: 14px }
.pa-g2 { display: grid; grid-template-columns: var(--cols, 1fr 1fr); gap: 14px }
/* A grid item will not shrink below its content by default, so one long word or
   a row of chips that cannot wrap pushes the whole page sideways. Raising the
   type 10% was enough to do it on a 390px screen. */
.pa-g2 > *, .pa-g3 > *, .pa-g4 > *, .pa-split > * { min-width: 0 }
.pa-split { display: grid; grid-template-columns: var(--cols, 1.5fr 1fr); gap: 14px; align-items: start }
.pa-stack { display: flex; flex-direction: column; gap: 14px }

/* A card whose contents stack with even spacing, and whose last element can be
   pushed to the bottom so buttons line up across a row of unequal cards. */
.pa-col { display: flex; flex-direction: column; gap: 14px; align-items: start }
.pa-col > * { width: 100% }
/* Direct children only. A button that is the card's own action fills it; one
   inside a form is sized by that form's own layout. */
.pa-col > .pa-btn, .pa-col > .pa-btn-ghost { width: 100% }

/* A page heading with an action beside it. */
.pa-head-row {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 24px; flex-wrap: wrap;
}
.pa-back { display: inline-block; margin-bottom: 18px; font-size: 14px; color: var(--muted) }
.pa-back:hover { color: var(--ink) }

.pa-stat-l { font-size: 13px; letter-spacing: .2em; text-transform: uppercase; color: var(--muted) }
.pa-stat-v { font: 400 33px var(--head); color: var(--ink-bright); letter-spacing: -.01em; margin: 10px 0 8px }
.pa-stat-f { font-size: 15px; line-height: 1.6; font-weight: 300; color: var(--muted) }

/* The four figures under the balance. Their own scale, which is smaller and
   more tracked than a card eyebrow. */
.pa-stat { padding: 20px }
.pa-stat-k { font-size: 12px; letter-spacing: .2em; text-transform: uppercase; color: var(--muted); margin-bottom: 12px }
.pa-stat-row { display: flex; align-items: baseline; gap: 7px; margin-bottom: 8px }
.pa-stat-n { font-size: 29px; color: var(--ink-bright); letter-spacing: -.02em }
.pa-stat-u { font-size: 14px; color: var(--dimmer) }
.pa-stat-foot { font-size: 14px; font-weight: 300; color: var(--dimmer) }

/* ---- type ---- */

.pa-eyebrow { font-size: 13px; letter-spacing: .2em; text-transform: uppercase; color: var(--accent) }
.pa-num { font-family: var(--head); font-variant-numeric: tabular-nums }
.pa-bignum { font: 400 47px/1 var(--head); color: var(--ink-bright); letter-spacing: -.02em }
/* The balance colours itself when it will not cover what is coming. It is the
   only number in the panel allowed to do that. */
.pa-bignum.warn { color: #F0B672 }
.pa-bignum.bad { color: #E8837F }
/* A line of guidance inside a card, rather than the page-level pa-note. */
.pa-notice {
  background: rgba(255, 255, 255, .03); border-left: 2px solid var(--line-2);
  border-radius: 2px; padding: 13px 15px;
  font-size: 15px; line-height: 1.55; font-weight: 300; color: var(--muted);
}
.pa-notice.bad { border-left-color: rgba(217, 83, 79, .6); color: #E8837F }
.pa-midnum { font: 400 33px var(--head); color: var(--ink); letter-spacing: -.01em }
.pa-muted { color: var(--muted); font-weight: 300 }
.pa-dim { color: var(--dimmer) }

/* ---- controls ---- */

.pa-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 22px;
  background: linear-gradient(135deg, #F5A73F, #E07C12);
  color: #0A0A0A; font-size: 15px; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  border: 0; border-radius: 2px; cursor: pointer;
  transition: filter .15s;
}
/* A button that fills its card carries slightly wider tracking, as the design
   has it on Add funds and Top up. */
.pa-col > .pa-btn, .pa-side-foot .pa-btn { letter-spacing: .08em; padding: 13px }
.pa-btn:hover { filter: brightness(1.1); color: #0A0A0A }
.pa-btn-ghost {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 20px;
  border: 1px solid rgba(255, 255, 255, .18); background: none;
  color: var(--ink); font-size: 15px; font-weight: 500;
  letter-spacing: .06em; text-transform: uppercase;
  border-radius: 2px; cursor: pointer;
  transition: border-color .15s;
}
.pa-btn-ghost:hover { border-color: rgba(255, 255, 255, .45); color: var(--ink) }
.pa-btn-danger { border-color: rgba(217, 83, 79, .5); color: var(--bad) }
.pa-btn-danger:hover { border-color: var(--bad); color: var(--bad) }
.pa-btn[disabled], .pa-btn-ghost[disabled] { opacity: .45; cursor: not-allowed; filter: none }

.pa-in {
  width: 100%; padding: 12px 14px;
  background: var(--bg); border: 1px solid var(--line-2); border-radius: 2px;
  color: var(--ink); font-size: 16px;
}
.pa-in:focus { outline: none; border-color: rgba(240, 145, 45, .55) }
/* A field the form is waiting on. Border only — the message naming it sits
   under the group, so colour is not carrying the meaning on its own. */
.pa-in.bad { border-color: var(--bad) }
/* The amount field is not a .pa-in — it sits inside its own bordered row — so
   the invalid state has to be put on that row instead. */
.pa-amount-field:has(input.bad), .pa-amount-field.bad { border-color: var(--bad) }
#amount.bad { color: var(--bad) }
.pa-in.bad:focus { border-color: var(--bad) }
/* A field that cannot be edited has to look like one, or a customer types into
   it and wonders why nothing saved. */
.pa-in[disabled], .pa-in[readonly] { color: var(--muted); border-style: dashed; cursor: not-allowed }
/* Chromium (and Samsung Internet, Safari) paints an autofilled field with its
   own pale-yellow background that ignores the field's colours. The inset
   box-shadow repaints it in the panel's dark ground and text-fill-color restores
   the ink; the long transition stops the yellow flashing back on focus. */
.pa-in:-webkit-autofill,
.pa-in:-webkit-autofill:hover,
.pa-in:-webkit-autofill:focus,
.pa-in:-webkit-autofill:active {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 100px var(--bg) inset;
  caret-color: var(--ink);
  transition: background-color 6000s ease-in-out 0s;
}
.pa-label { display: block; font-size: 14px; letter-spacing: .1em; text-transform: uppercase; color: var(--dimmer); margin-bottom: 8px }

/* Filter chips, used above every list. */
.pa-chips { display: flex; gap: 8px; flex-wrap: wrap }
.pa-chip {
  padding: 9px 15px; border: 1px solid rgba(255, 255, 255, .12); border-radius: 2px;
  font-size: 14px; letter-spacing: .08em; text-transform: uppercase;
  white-space: nowrap; color: var(--muted); background: none; cursor: pointer;
}
.pa-chip:hover { color: var(--ink) }
.pa-chip.on { border-color: var(--accent); color: var(--accent); background: rgba(240, 145, 45, .08) }

/* Tabs within a section. Real links, so each view is bookmarkable. */
.pa-tabs {
  display: flex; gap: 0; border-bottom: 1px solid var(--line-2);
  /* Scrolls on a narrow screen, but without drawing a scrollbar across the
     underline, which reads as a stray mark at the end of the tab row. */
  overflow-x: auto; scrollbar-width: none;
}
.pa-tabs::-webkit-scrollbar { display: none }
.pa-tabs a {
  padding: 13px 20px; white-space: nowrap;
  font-size: 15px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.pa-tabs a:hover { color: var(--ink) }
.pa-tabs a.on { color: var(--accent); border-bottom-color: var(--accent) }

/* The filter bar above a list: chips, a search box and its button on one line
   that wraps rather than overflowing. */
.pa-filters { display: flex; gap: 12px; flex-wrap: wrap; align-items: center }
.pa-filters .pa-chips { flex: 1 }
.pa-search { width: auto; min-width: 220px; max-width: 340px; flex: 1; padding: 9px 14px; font-size: 15px }
/* A submit that belongs to the filter row, not to the page. Same height and
   tracking as the chips beside it. */
.pa-filters .pa-btn-ghost {
  padding: 9px 15px; font-size: 14px; letter-spacing: .08em;
  color: var(--muted); border-color: rgba(255, 255, 255, .12);
}
.pa-filters .pa-btn-ghost:hover { color: var(--ink); border-color: rgba(255, 255, 255, .3) }

textarea.pa-ta { line-height: 1.6; resize: vertical; font-weight: 300 }
select.pa-in { appearance: none; cursor: pointer }

/* ---- tables ---- */

.pa-row {
  display: grid; align-items: center; gap: 14px;
  grid-template-columns: var(--cols, 1fr auto);
  padding: 15px 22px; border-bottom: 1px solid rgba(255, 255, 255, .05);
}
.pa-row:last-child { border-bottom: 0 }
.pa-row:hover { background: rgba(255, 255, 255, .02) }
.pa-thead {
  font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--dimmer); background: var(--panel-2);
}
.pa-thead:hover { background: var(--panel-2) }
.pa-right { text-align: right }

/* Column layouts, named per table so the header and its rows can never drift
   out of alignment: both carry the same class. */
.pa-tx      { grid-template-columns: 1fr 110px 130px 120px 110px }
/* The dashboard's shorter version of the same row. */
.pa-tx-lite { grid-template-columns: 1fr 130px 110px }
.pa-inv  { grid-template-columns: 1fr 150px 130px 120px 90px }
.pa-tk   { grid-template-columns: 1fr 130px 96px 116px 104px }
.pa-line { grid-template-columns: 1fr 90px 110px 110px }

.pa-pager {
  display: flex; justify-content: space-between; align-items: center;
  gap: 14px; flex-wrap: wrap; padding: 15px 22px;
}
.pa-pager .pa-btn-ghost { padding: 8px 14px; font-size: 14px }

/* Invoice totals, right-aligned under the lines. */
.pa-totals { padding: 20px 22px; display: flex; flex-direction: column; gap: 11px; align-items: flex-end }
.pa-totals > div { display: flex; justify-content: space-between; gap: 40px; min-width: 260px; font-size: 15px }
.pa-totals-final { border-top: 1px solid var(--line); padding-top: 11px; color: var(--ink); font-size: 16px }
.pa-totals-final .pa-num { font-size: 25px; color: var(--ink) }

/* A key and its value on one line, used in every detail sidebar. */
.pa-kv { display: flex; justify-content: space-between; gap: 14px; align-items: baseline }
.pa-kv > span:first-child { font-size: 15px; font-weight: 300; color: var(--dimmer) }
.pa-kv > span:last-child { font-size: 15px; color: var(--ink); text-align: right }

/* ---- top up ---- */

.pa-amount {
  padding: 13px 22px; border: 1px solid var(--line-2); border-radius: 2px;
  background: none; color: var(--ink); font-family: var(--head); font-size: 17px;
  cursor: pointer;
}
.pa-amount:hover { border-color: rgba(255, 255, 255, .3) }
.pa-amount.on { border-color: var(--accent); background: rgba(240, 145, 45, .12); color: var(--accent) }

.pa-amount-field {
  display: flex; align-items: center; gap: 10px; padding: 0 15px;
  background: var(--bg); border: 1px solid var(--line-2); border-radius: 2px;
}
.pa-amount-field:focus-within { border-color: rgba(240, 145, 45, .55) }
.pa-amount-cur { font-family: var(--head); font-size: 19px; color: var(--dim) }
.pa-amount-field input {
  flex: 1; min-width: 0; background: none; border: 0; outline: none;
  padding: 14px 0; font-family: var(--head); font-size: 19px; color: var(--ink);
}

/* One payment method. The radio is kept for the keyboard and replaced visually. */
.pa-method {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 16px 18px; border: 1px solid var(--line-2); border-radius: 2px;
  cursor: pointer;
}
.pa-method:hover { border-color: rgba(255, 255, 255, .22) }
.pa-method.on { border-color: var(--accent); background: rgba(240, 145, 45, .07) }
.pa-method input { position: absolute; opacity: 0; width: 0; height: 0 }
.pa-method.off { cursor: not-allowed; border-style: dashed; opacity: .55 }
.pa-radio {
  width: 16px; height: 16px; border-radius: 50%; flex: none;
  border: 1px solid rgba(255, 255, 255, .28); position: relative;
}
.pa-method.on .pa-radio { border-color: var(--accent) }
.pa-method.on .pa-radio::after {
  content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--accent);
}
.pa-method-n { display: block; font-size: 16px; color: var(--ink) }
.pa-method-t { display: block; font-size: 14px; font-weight: 300; color: var(--dimmer) }
/* The marks, served from our own assets rather than a CDN. Same files the
   design names, vendored: a no-KYC product should not tell a third party who
   is looking at a payment page. */
.pa-marks { display: flex; align-items: center; gap: 7px; flex-wrap: wrap }
.pa-coin { position: relative; display: block; width: 22px; height: 22px }
.pa-coin img { width: 22px; height: 22px; display: block; opacity: .55; transition: opacity .15s }
.pa-method.on .pa-coin img { opacity: 1 }
.pa-coin:hover { z-index: 5 }
.pa-coin:hover .pa-tip { opacity: 1 }
.pa-tip {
  position: absolute; bottom: calc(100% + 7px); left: 50%; transform: translateX(-50%);
  white-space: nowrap; background: #141414; border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 2px; padding: 5px 9px; font-size: 13px; color: var(--ink);
  opacity: 0; pointer-events: none; transition: opacity .12s ease;
}
/* Card and wallet marks, inlined so the design's colour is the fill. */
.pa-brand { height: 20px; display: block; opacity: .55; transition: opacity .15s }
.pa-brand svg { width: 100%; height: 100%; display: block }
.pa-method.on .pa-brand { opacity: 1 }

/* The bonus notice, which changes state as the amount crosses the threshold. */
.pa-bonus {
  display: flex; align-items: center; gap: 14px;
  background: rgba(255, 255, 255, .03); border: 1px solid var(--line-2);
  border-radius: 2px; padding: 14px 16px;
}
.pa-bonus.on { background: rgba(74, 158, 106, .09); border-color: rgba(74, 158, 106, .4) }
.pa-bonus-v { font-family: var(--head); font-size: 17px; flex: none; color: var(--muted) }
.pa-bonus-t { font-size: 15px; line-height: 1.55; font-weight: 300; color: var(--muted) }
.pa-bonus.on .pa-bonus-v, .pa-bonus.on .pa-bonus-t { color: var(--good) }

.pa-good { color: var(--good) }

.pa-summary { position: sticky; top: 80px }
.pa-summary-total {
  display: flex; justify-content: space-between; align-items: baseline;
  border-top: 1px solid var(--line); padding-top: 16px;
  font-size: 15px; color: var(--ink);
}
.pa-summary-total .pa-num { font-size: 27px; color: var(--accent) }

/* What the balance becomes, under what it costs. Deliberately quiet: it is
   worth knowing and it is not the figure being agreed to. */
.pa-summary-after {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-top: -4px; font-size: 15px; color: var(--dim);
}
.pa-summary-after .pa-num { font-size: 16px; color: var(--muted) }

/* ---- profile ---- */

/* A card whose border says something: green while two-factor is on, red for
   the one card that can end the account. */
.pa-card-good { border-color: rgba(74, 158, 106, .3) }
.pa-card-danger { border-color: rgba(217, 83, 79, .3) }

.pa-setup {
  display: grid; grid-template-columns: auto 1fr; gap: 22px; align-items: start;
  background: var(--bg); border: 1px solid var(--line); border-radius: 2px; padding: 22px;
}
.pa-qr {
  width: 150px; height: 150px; flex: none;
  background: #FFFFFF; padding: 6px; border-radius: 2px;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: #5F5B55;
}
.pa-qr img { width: 100%; height: 100%; display: block }
/* The secret and the recovery codes: monospaced by tracking rather than by
   font, so they stay in the panel's own type. */
.pa-key {
  background: var(--panel); border: 1px solid var(--line-2); border-radius: 2px;
  padding: 12px 14px; font-family: var(--head); font-size: 16px;
  color: var(--ink); letter-spacing: .1em; word-break: break-all;
}
/* Grouped in fours by margin rather than by spaces in the text, so the key
   reads in chunks and still copies as one string. */
.pa-key-grouped { letter-spacing: .1em; word-break: normal }
.pa-key-grouped span { display: inline-block; margin-right: .55em }
.pa-key-grouped span:last-child { margin-right: 0 }

.pa-copy { font-size: 14px; padding: 7px 12px }
.pa-copy[data-done="true"] { border-color: var(--ok, #4A9E6A); color: var(--ok, #4A9E6A) }

.pa-codes {
  background: var(--bg); border: 1px solid var(--line); border-radius: 2px;
  padding: 22px; display: flex; flex-direction: column; gap: 14px;
}
.pa-codes-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px }

/* One method to pick, as a whole target rather than a radio and a label.
   A dialog that asks a single question is easier to answer with a thumb when
   the answer is the size of the sentence describing it. */
.pa-choice {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 14px 16px; border: 1px solid var(--line-2); border-radius: 2px;
  background: none; color: inherit; font: inherit;
}
.pa-choice:hover { border-color: var(--accent); background: rgba(255, 255, 255, .03) }
.pa-choice-t { display: block; font-size: 16px; font-weight: 600; color: var(--ink) }
.pa-choice-b { display: block; margin-top: 4px; font-size: 14px; font-weight: 300; line-height: 1.55; color: var(--muted) }

/* A checkbox drawn as a switch. The input stays in the DOM and keeps working
   with the keyboard; only its appearance is replaced. */
.pa-toggle {
  display: flex; justify-content: space-between; align-items: center; gap: 14px;
  font-size: 15px; font-weight: 300; color: #C9C4BD; cursor: pointer;
}
.pa-toggle input { position: absolute; opacity: 0; width: 0; height: 0 }
.pa-toggle-track {
  width: 38px; height: 21px; border-radius: 11px; flex: none; position: relative;
  background: rgba(255, 255, 255, .14); transition: background .15s;
}
.pa-toggle-knob {
  position: absolute; top: 3px; left: 3px; width: 15px; height: 15px;
  border-radius: 50%; background: var(--panel); transition: left .15s;
}
.pa-toggle input:checked + .pa-toggle-track { background: var(--accent) }
.pa-toggle input:checked + .pa-toggle-track .pa-toggle-knob { left: 20px }
.pa-toggle input:focus-visible + .pa-toggle-track { outline: 2px solid var(--accent-hi); outline-offset: 2px }

/* ---- support ---- */

.pa-tick { width: 6px; height: 6px; flex: none; background: rgba(255, 255, 255, .18) }
.pa-tick.on { background: var(--accent) }

.pa-msg { background: var(--panel); border: 1px solid var(--line); border-radius: 2px; padding: 20px 22px }
/* The customer's own messages carry the accent edge, so a thread can be
   skimmed for who said what without reading the names. */
.pa-msg.mine { background: var(--panel-2); border-left: 2px solid var(--accent) }
.pa-msg-h {
  display: flex; justify-content: space-between; gap: 14px;
  align-items: baseline; margin-bottom: 12px; flex-wrap: wrap;
}
/* pre-wrap rather than a template filter: the body is plain text and its own
   newlines are the formatting, so nothing has to be marked safe to display it. */
.pa-msg-b {
  font-size: 16px; line-height: 1.7; font-weight: 300; color: #C9C4BD;
  overflow-wrap: anywhere;
}
.pa-msg-b p { margin: 0 0 10px }
.pa-msg-b p:last-child { margin-bottom: 0 }
.pa-msg-b blockquote {
  margin: 10px 0; padding-left: 14px; border-left: 2px solid var(--line-2);
  color: var(--muted);
}
.pa-msg-b ul, .pa-msg-b ol { margin: 10px 0; padding-left: 22px }
.pa-msg-b code { font-family: var(--mono); font-size: 15px }
.pa-msg-b pre { background: var(--bg); padding: 12px 14px; overflow-x: auto; border-radius: 2px }
.pa-msg-avatar {
  width: 24px; height: 24px; border-radius: 50%; flex: none;
  background: rgba(240, 145, 45, .16); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--head); font-size: 13px;
}
.pa-attach {
  margin-top: 14px; display: inline-flex; align-items: center; gap: 10px;
  border: 1px solid var(--line-2); border-radius: 2px; padding: 9px 14px;
  font-size: 14px; color: var(--muted);
}
/* The file input is kept for the keyboard and hidden behind its label. */
.pa-attach-add { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: 14px; font-weight: 300; color: var(--dim) }
.pa-attach-add:hover { color: var(--ink) }
.pa-attach-add input { position: absolute; opacity: 0; width: 0; height: 0 }
.pa-attach-add:focus-within > span:first-of-type { outline: 2px solid var(--accent-hi); outline-offset: 3px }
.pa-attach-n { color: var(--muted) }
.pa-uploads { display: flex; flex-wrap: wrap; gap: 8px }
.pa-uploads .pa-attach { margin-top: 0 }
.pa-attach-x {
  background: none; border: 0; cursor: pointer; padding: 0 0 0 4px;
  color: var(--dim); font-size: 17px; line-height: 1;
}
.pa-attach-x:hover { color: var(--bad) }
a.pa-attach:hover { border-color: rgba(255, 255, 255, .3); color: var(--ink) }

/* CKEditor sits inside the card, so it wears the panel rather than its own
   white default. */
/* A floor, not the height: the script sizes each editable from the rows of the
   textarea it replaced, so the template stays the one place that says how tall
   the box is. This is what shows in the moment before that runs. 120px came out
   at about three lines, which is not room enough to describe a problem. */
.ck.ck-editor__editable { background: var(--bg) !important; color: var(--ink) !important; min-height: 176px }
.ck.ck-editor__editable.ck-focused { border-color: rgba(240, 145, 45, .55) !important; box-shadow: none !important }
.ck.ck-toolbar { background: var(--panel-2) !important; border-color: var(--line-2) !important }
.ck.ck-button { color: var(--muted) !important }
.ck.ck-button.ck-on, .ck.ck-button:hover { background: rgba(255, 255, 255, .06) !important; color: var(--ink) !important }
.ck.ck-editor__main > .ck-editor__editable { border-color: var(--line-2) !important; border-radius: 0 0 2px 2px }
.ck.ck-toolbar { border-radius: 2px 2px 0 0 }

/* ---- status pills ---- */

.pa-pill {
  display: inline-block; padding: 4px 10px; border-radius: 2px;
  font-size: 13px; letter-spacing: .08em; text-transform: uppercase;
  border: 1px solid;
}
.pa-pill-paid   { border-color: rgba(74, 158, 106, .4); background: rgba(74, 158, 106, .10); color: var(--good) }
.pa-pill-unpaid { border-color: rgba(240, 145, 45, .45); background: rgba(240, 145, 45, .10); color: #F0B672 }
.pa-pill-bad    { border-color: rgba(217, 83, 79, .45); background: rgba(217, 83, 79, .10); color: #E8837F }
.pa-pill-off    { border-color: rgba(255, 255, 255, .14); color: var(--dim) }

/* A crypto payment that has been seen and is waiting on the chain. Its own
   colour rather than "unpaid" in orange: the customer has sent the money, and
   the difference between "we are waiting for you" and "we are waiting for the
   network" is the whole reason the state exists. Blue reads as in-progress
   without claiming success — green is kept for money that has actually landed. */
.pa-pill-wait   { border-color: rgba(122, 162, 214, .45); background: rgba(122, 162, 214, .10); color: #9DBCE4 }

/* The dot beside it, which is what says the page is still watching. */
.pa-pill-wait::before {
  content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; margin-right: 7px; vertical-align: 1px;
  animation: pa-pulse 1.6s ease-in-out infinite;
}
@keyframes pa-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .25 } }
@media (prefers-reduced-motion: reduce) {
  .pa-pill-wait::before { animation: none }
}

/* ---- chart ---- */

.pa-bars { display: flex; align-items: flex-end; gap: 12px; height: 150px }
.pa-bar { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; gap: 9px; height: 100% }
.pa-bar-fill { width: 100%; background: rgba(255, 255, 255, .14); border-radius: 1px }
.pa-bar.on .pa-bar-fill { background: linear-gradient(180deg, #F5A73F, #E07C12) }
.pa-bar-l { font-size: 12px; letter-spacing: .14em; text-transform: uppercase; color: var(--dimmer); text-align: center }
.pa-bar-v { font-size: 14px; color: var(--muted); text-align: center; font-family: var(--head) }

/* ---- messages ---- */

.pa-note { padding: 14px 18px; border-left: 2px solid var(--accent); background: rgba(240, 145, 45, .07); font-size: 15px; font-weight: 300; color: var(--muted) }
.pa-note-bad { border-left-color: var(--bad); background: rgba(217, 83, 79, .08); color: #E8837F }
.pa-note-good { border-left-color: #4A9E6A; background: rgba(74, 158, 106, .08); color: var(--good) }
.pa-empty { padding: 44px 22px; text-align: center; font-size: 15px; font-weight: 300; color: var(--dim); line-height: 1.7 }

/* ---- signed-out screens ----
   Brand on the left, form on the right. The doorway is the only decoration in
   the whole panel and it carries the logo, so it stays on narrow screens as a
   banner rather than vanishing; only the headline block drops out there. */

.pa-auth { min-height: 100vh; display: grid; grid-template-columns: 1.05fr 1fr }

.pa-auth-brand {
  position: relative; overflow: hidden; background: var(--panel);
  display: flex; flex-direction: column; justify-content: space-between;
  padding: 40px 48px; border-right: 1px solid var(--line);
}
/* Framed near the right edge: the doorway is the only lit thing in the
   photograph and cover-cropping from the centre pushes it out of the pane. */
.pa-auth-photo { position: absolute; inset: 0; background: url('/assets/hero-doorway.jpg') 92% center/cover no-repeat }
/* Two layers rather than one: the photograph keeps its own framing while the
   gradient does the darkening, so either can be tuned without the other. It
   falls away to the right so the headline reads against black while the
   doorway is still visible. */
.pa-auth-scrim { position: absolute; inset: 0; background: linear-gradient(100deg, rgba(5,5,5,.93) 0%, rgba(5,5,5,.66) 42%, rgba(5,5,5,.20) 100%); pointer-events: none }
.pa-auth-brand > *:not(.pa-auth-photo):not(.pa-auth-scrim) { position: relative }
.pa-auth-logo img { height: 32px; width: auto; display: block }
.pa-auth-say { max-width: 460px }
.pa-auth-rule { display: flex; align-items: center; gap: 12px; margin-bottom: 26px }
.pa-auth-rule span:first-child { width: 26px; height: 1px; background: var(--accent) }
.pa-auth-say h1 { margin: 0 0 16px; font: 400 44px/1.08 var(--head); letter-spacing: -.02em; color: var(--ink-bright) }
.pa-auth-say p { margin: 0; font-size: 18px; line-height: 1.65; font-weight: 300; color: var(--muted) }
.pa-auth-tags { display: flex; gap: 26px; flex-wrap: wrap; font-size: 13px; letter-spacing: .18em; text-transform: uppercase; color: var(--dim) }

.pa-auth-form { display: flex; align-items: center; justify-content: center; padding: 56px 40px }
.pa-auth-in { width: 100%; max-width: 380px }
.pa-auth-h { margin: 0 0 8px; font: 400 33px var(--head); letter-spacing: -.02em; color: var(--ink-bright) }
.pa-auth-p { margin: 0 0 34px; font-size: 17px; line-height: 1.6; font-weight: 300; color: var(--muted) }
.pa-field { margin-bottom: 18px }
/* The label row carries a link on the right for "Forgot?", so it is a flex row
   rather than the plain block label used elsewhere. */
.pa-label-row { display: flex; justify-content: space-between; align-items: baseline }
.pa-label-row .pa-label { margin-bottom: 8px }
.pa-label-row a { font-size: 14px }
.pa-auth-alt { margin: 18px 0 0; font-size: 15px; font-weight: 300; color: var(--muted); text-align: center; line-height: 1.7 }
/* Six cells, one per digit.
   Real inputs rather than a single field dressed up, so the caret lands where
   the eye is. They work without scripting — tab across them — and the script
   only adds the advancing and the paste. */
.pa-code-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px }
.pa-code-cell {
  width: 100%; aspect-ratio: 1 / 1.15; padding: 0;
  background: var(--panel); border: 1px solid var(--line-2); border-radius: 2px;
  font-family: var(--head); font-size: 25px; color: var(--ink-bright);
  text-align: center;
  /* Chrome and Safari draw a spinner on a numeric input, which would sit on
     top of the digit in a cell this small. */
  appearance: textfield;
}
.pa-code-cell::-webkit-outer-spin-button,
.pa-code-cell::-webkit-inner-spin-button { appearance: none; margin: 0 }
.pa-code-cell:focus { outline: none; border-color: var(--accent) }
/* A cell that has a digit in it, so progress through the code is visible. */
.pa-code-cell:not(:placeholder-shown) { border-color: rgba(255, 255, 255, .3) }

/* The recovery code is one long string, not six digits, so it gets a field of
   its own rather than being forced through the cells. */
.pa-code-long {
  font-family: var(--head); font-size: 19px; letter-spacing: .08em;
  text-align: center; padding: 15px 14px;
}
/* A checkbox with a label beside it, for the terms box on sign-up. */
.pa-check {
  display: flex; gap: 11px; align-items: flex-start; cursor: pointer;
  font-size: 15px; line-height: 1.55; font-weight: 300; color: var(--muted);
}
.pa-check input { position: absolute; opacity: 0; width: 0; height: 0 }
.pa-check-box {
  width: 18px; height: 18px; flex: none; margin-top: 2px;
  border: 1.5px solid rgba(255, 255, 255, .25); border-radius: 2px;
  position: relative;
}
.pa-check input:checked + .pa-check-box { border-color: var(--accent); background: rgba(240, 145, 45, .18) }
.pa-check input:checked + .pa-check-box::after {
  content: ""; position: absolute; left: 5px; top: 1px;
  width: 4px; height: 9px; border: solid var(--accent);
  border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
}
.pa-check input:focus-visible + .pa-check-box { outline: 2px solid var(--accent-hi); outline-offset: 2px }

/* The password strength meter. Advice, not a gate: the server enforces the
   length whatever this shows. */
.pa-strength { display: flex; gap: 5px; margin-top: 9px }
.pa-strength span { height: 3px; flex: 1; background: var(--line-2); transition: background .15s }
.pa-strength span.on { background: #4A9E6A }

/* A button that has to be a form post but should read as a link. */
.pa-linkish {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--body); font-size: 15px; color: var(--accent);
}
.pa-linkish:hover { color: var(--accent-hi) }

/* ---- responsive ----
   The two breakpoints the design uses, and the same rules at each. Everything
   here overrides a --cols default rather than fighting an inline style, which
   is what makes a media query able to win at all. */

@media (max-width: 1000px) {
  .pa-shell { grid-template-columns: 1fr }
  .pa-side { display: none }
  .pa-mhead { display: flex }
  /* The switcher lives in the mobile header now: below this width the top bar
     it normally sits in is gone, and with it went the only way to reach
     another product without typing its address.

     Anchored to the header rather than to the button. Hanging off a button
     that sits 72px from the right edge put a 300px menu 12px off the left of
     a 360px screen; against the header it lines up with the padding and is
     sized to the viewport. */
  .pa-mhead .pa-pop { position: static }
  .pa-mhead .pa-menu { right: 20px; left: auto; min-width: 0; width: min(300px, calc(100vw - 40px)) }
  /* Room for the fixed header. */
  .pa-main { padding-top: 70px }
  /* The top bar's job — where you are, and the switcher — is done by the
     mobile header and the drawer at this width. */
  .pa-top { display: none }
  .pa-body { padding: 22px 20px 48px }

  .pa-g4 { grid-template-columns: repeat(2, 1fr) }
  .pa-g3, .pa-g2, .pa-split { grid-template-columns: 1fr }
  .pa-setup { grid-template-columns: 1fr }

  /* The brand pane becomes a full-page backdrop rather than a banner strip with
     the form stacked beneath it — the same treatment the buckets panel uses. The
     doorway fills the viewport behind everything, the logo sits top-left, and the
     form floats centred over it, the whole thing one screen tall and no scroll. */
  .pa-auth { display: block; min-height: 100vh; min-height: 100dvh }
  .pa-auth-brand {
    position: fixed; inset: 0; min-height: 0; padding: 24px;
    border-right: none; justify-content: flex-start;
    z-index: 0; pointer-events: none;
  }
  /* Bring the doorway into the phone's crop — the desktop 92% frame sits it off
     the right edge of a portrait viewport. */
  .pa-auth-photo { background-position: 78% center }
  /* Dark image, bright doorway: a top-light, bottom-dark wash lets the upper
     doorway read while keeping the form legible over the lower half. */
  .pa-auth-scrim { background: linear-gradient(180deg, rgba(5,5,5,.62) 0%, rgba(5,5,5,.82) 52%, rgba(5,5,5,.93) 100%) }
  .pa-auth-say, .pa-auth-tags { display: none }
  .pa-auth-form {
    position: relative; z-index: 1; box-sizing: border-box;
    min-height: 100dvh; padding: 30px 24px;
  }

  .pa-search { max-width: none }
  .pa-hide-md { display: none }
}

@media (max-width: 720px) {
  .pa-g4 { grid-template-columns: 1fr }
  .pa-h1 { font-size: 29px }
  .pa-bignum { font-size: 38px }

  /* Every table becomes description-and-amount. The columns that go are the
     ones whose absence changes nothing about what the row means, and the
     header goes with them because it would be labelling nothing. */
  .pa-row, .pa-tx, .pa-tx-lite, .pa-inv, .pa-tk, .pa-line {
    grid-template-columns: 1fr auto; row-gap: 6px;
  }
  .pa-thead { display: none }
  .pa-hide-sm { display: none }

  /* Chips get the full width and scroll sideways within it, rather than being
     squeezed into whatever the search box leaves — which crushed them to one
     visible chip and a scrollbar. */
  .pa-filters .pa-chips { flex: 1 1 100%; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none }
  .pa-filters .pa-chips::-webkit-scrollbar { display: none }
  .pa-filters .pa-search { flex: 1 1 auto }

  .pa-codes-grid { grid-template-columns: 1fr }
  .pa-summary { position: static }
  .pa-amount { flex: 1 0 auto; padding: 13px 16px }
  .pa-code-cell { font-size: 20px }
}

/* ---- Not found ---------------------------------------------------------- */
/* Centred in the content area rather than stacked at the top of it. The panel
   body is a flex column, so a lone anchor stretches to the full width of the
   page — which is how the old one came out as a 1200px orange bar under two
   lines of text. */
.pa-404 {
  flex: 1; min-height: 60vh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 16px; padding: 48px 22px;
}
.pa-404-mark {
  font: 300 84px/1 var(--mono); letter-spacing: .08em;
  color: var(--dim); opacity: .3; user-select: none;
}
.pa-404 h1 {
  margin: 0; font: 400 29px var(--head);
  letter-spacing: -.02em; color: var(--ink-bright);
}
.pa-404 p {
  margin: 0; max-width: 44ch;
  font-size: 16px; font-weight: 300; line-height: 1.7; color: var(--muted);
}
.pa-404-acts { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; margin-top: 6px }
/* The actions sit inside a flex row, so they are not stretched by the column. */
.pa-404-acts .pa-btn, .pa-404-acts .pa-btn-ghost { flex: 0 0 auto }
.pa-404-links {
  display: flex; gap: 8px 18px; flex-wrap: wrap; justify-content: center;
  margin-top: 10px; font-size: 15px; font-weight: 300;
}
.pa-404-links a { color: var(--dim); transition: color .15s }
.pa-404-links a:hover { color: var(--accent) }

@media (max-width: 600px) {
  .pa-404-mark { font-size: 64px }
  .pa-404 h1 { font-size: 25px }
  .pa-404-acts { width: 100%; flex-direction: column }
  .pa-404-acts .pa-btn, .pa-404-acts .pa-btn-ghost { width: 100% }
}

/* ---- the conversation pane --------------------------------------------- */
/* The thread scrolls inside a fixed pane so the reply box keeps its place at
   the bottom of the card rather than being pushed off the screen by a long
   history. Sized in vh so a tall window shows more of the conversation and a
   short one still leaves the reply box in view. */
.pa-thread {
  display: flex; flex-direction: column; gap: 12px;
  max-height: 68vh; min-height: 340px;
  overflow-y: auto; overscroll-behavior: contain;
  padding-right: 8px;
  /* Room for the scrollbar so a message's right edge is not sat on. */
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, .18) transparent;
}
.pa-thread::-webkit-scrollbar { width: 8px }
.pa-thread::-webkit-scrollbar-track { background: transparent }
.pa-thread::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .18); border-radius: 4px;
}
.pa-thread::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, .3) }
/* A pane that scrolls should say so at its edge rather than cutting a message
   off mid-sentence with no hint there is more. */
.pa-thread > .pa-msg:last-child { margin-bottom: 2px }

@media (max-width: 900px) {
  /* On a phone the page scrolls anyway; a second scrolling region inside it is
     a trap for a thumb. */
  .pa-thread { max-height: none; overflow-y: visible; padding-right: 0 }
}

/* ---- ticket priority --------------------------------------------------- */
/* A dot and a word. Only High carries colour: if every priority shouts, the
   one that matters stops being visible in a list of twenty. */
.pa-prio {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 14px; font-weight: 300; color: var(--muted);
}
.pa-prio::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex: none;
}
.pa-prio-low  { color: var(--dim) }
.pa-prio-med  { color: var(--muted) }
.pa-prio-high { color: var(--accent); font-weight: 400 }

/* ---- modal -------------------------------------------------------------- */
/* Square corners and the panel's own surfaces, so a dialog reads as part of
   the page rather than as something a framework dropped on top of it. */
.pa-modal { display: none; position: fixed; inset: 0; z-index: 200 }
.pa-modal[data-open="true"] { display: block }
.pa-modal-back {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, .72);
  backdrop-filter: blur(2px);
}
.pa-modal-box {
  position: relative; margin: 8vh auto 0;
  width: min(460px, calc(100% - 32px));
  max-height: 84vh; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--line-2); border-radius: 2px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .6);
  padding: 24px;
}
/* A payment needs more room than a confirmation does.
   
   Stacked in one column it came to 1384px of form in an 838px window: the
   billing address scrolled off the top, and a customer who opened it saw an
   email field and a card number and reasonably concluded no address was being
   asked for. Side by side, both halves are on screen at once. */
.pa-modal-wide .pa-modal-box { width: min(880px, calc(100% - 32px)) }

/* Waiting for a payment window to open.
   
   Opening a crypto invoice takes a second or two — our side, then Bitcart's —
   and a button that says "Working…" against an unchanged page reads as one that
   did nothing. This stands in until Bitcart's own frame reports itself loaded. */
/* Centred, the way the window it stands in for is. The ordinary modal sits
   near the top because it is a form you read downward; this is one line and a
   spinner, and anywhere but the middle reads as a mistake. */
.pa-modal.pa-modal-wait[data-open="true"] { display: flex; align-items: center; justify-content: center }
.pa-modal-wait .pa-modal-box {
  width: min(360px, calc(100% - 32px)); margin: 0; text-align: center;
}
.pa-spin {
  width: 30px; height: 30px; margin: 6px auto 16px;
  border: 2px solid var(--line-2); border-top-color: var(--accent); border-radius: 50%;
  animation: pa-spin 0.7s linear infinite;
}

/* A processor's checkout, framed.

   Bitcart ships a script that drives its own iframe; Plisio's checkout is an
   ordinary page, so this is the frame for it. Sized to the taller of the two
   layouts it renders — the coin picker and the address view — because an
   iframe cannot tell us how tall its content is across origins, and a frame
   that is short scrolls the payment address out of sight. */
.pa-modal.pa-modal-frame[data-open="true"] { display: flex; align-items: center; justify-content: center }
.pa-modal-frame .pa-modal-box {
  width: min(560px, calc(100% - 24px));
  height: min(760px, calc(100vh - 48px));
  max-height: none; margin: 0; padding: 0; overflow: hidden;
}
.pa-modal-frame iframe {
  display: block; width: 100%; height: 100%; border: 0; background: #FFF;
}
/* Over the frame rather than above it: the box is all iframe, and a header bar
   would take height the checkout needs. */
.pa-modal-frame .pa-modal-x {
  position: absolute; top: 6px; right: 10px; z-index: 1;
  width: 30px; height: 30px; border-radius: 2px;
  background: rgba(5, 5, 5, .72); color: #FFF;
}
.pa-modal-frame .pa-modal-x:hover { background: rgba(5, 5, 5, .9) }
@keyframes pa-spin { to { transform: rotate(360deg) } }
/* Someone who has asked not to see motion gets a still ring rather than none:
   the point is that something is happening, not that it spins. */
@media (prefers-reduced-motion: reduce) { .pa-spin { animation: none } }
.pa-pay-cols { display: grid; grid-template-columns: var(--cols, 1fr 1fr); gap: 26px; align-items: start }

@media (max-width: 760px) {
  /* One column again, in the same order as the wide layout: billing first.
     The card was first here for a while, on the reasoning that it is the part
     you came for -- but the billing fields are required and often empty, and
     putting them below the card is how they went unnoticed in the first place. */
  .pa-pay-cols { grid-template-columns: 1fr; gap: 22px }
}

.pa-modal-h {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin-bottom: 20px;
}
.pa-modal-h h2 {
  margin: 0; font: 400 21px var(--head);
  letter-spacing: -.01em; color: var(--ink-bright);
}
.pa-modal-x {
  background: none; border: 0; cursor: pointer; padding: 0;
  font-size: 27px; line-height: 1; color: var(--dim);
}
.pa-modal-x:hover { color: var(--ink) }
.pa-modal-f {
  display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap;
  margin-top: 4px;
}

@media (max-width: 560px) {
  .pa-modal-box { margin-top: 4vh; padding: 20px }
  /* Full-width, stacked, so neither button is a thumb-sized target next to a
     bigger one. Cancel below, since it is the one you press by accident. */
  .pa-modal-f { flex-direction: column-reverse }
  .pa-modal-f .pa-btn, .pa-modal-f .pa-btn-ghost { width: 100% }
}
