/* Seller surfaces on the brand domain.
 *
 * Same tokens as pay.css and the landing page — black/white brand, sea green
 * as the only accent. This is a third surface in one product, not a third
 * product, so it inherits rather than restates.
 */

@font-face { font-family: "Inter"; font-style: normal; font-weight: 100 900;
  font-display: optional; src: url("/static/fonts/inter-latin-var.woff2") format("woff2"); }
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 300 700;
  font-display: optional; src: url("/static/fonts/space-grotesk-latin-var.woff2") format("woff2"); }

:root {
  color-scheme: dark;
  --bg: #0a0a0b; --surface: #101012; --surface-2: #16161a;
  --border: #262630; --border-strong: #36363f;
  --text: #ffffff; --text-secondary: #8e9ba0; --text-dim: #6b7378;
  --brand: #ffffff; --brand-hover: #e8e8ea; --on-brand: #0a0a0b;
  --accent: #2dd4bf; --accent-hover: #5eead4; --accent-bg: rgba(45,212,191,.12);
  --burn: #f0714a; --burn-bg: rgba(240,113,74,.12);   /* spending wallets: money out, a burner */
  --recv: #5b9dff; --recv-bg: rgba(91,157,255,.12);    /* receiving wallets: money in, yours; blue, because the accent is already green */
  --error: #ff5d6c; --error-bg: rgba(255,93,108,.1);
  --radius: 10px;
}
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #ffffff; --surface: #f6f7f9; --surface-2: #eef0f4;
  --border: #e2e5ea; --border-strong: #cbd0d8;
  --text: #0a0a0b; --text-secondary: #5b6469; --text-dim: #858e93;
  --brand: #0a0a0b; --brand-hover: #262630; --on-brand: #ffffff;
  --accent: #0d9488; --accent-hover: #14b8a6; --accent-bg: rgba(13,148,136,.1);
  --burn: #c4471f; --burn-bg: rgba(196,71,31,.1);
  --recv: #1d4ed8; --recv-bg: rgba(29,78,216,.1);
}

* { box-sizing: border-box; }
/* `hidden` is only `display:none` at UA-stylesheet strength, so ANY later
   display rule silently defeats it — .first-run{display:flex} did exactly
   that and the first-run stepper showed to sellers who already had
   checkouts. Global, so no component has to remember. */
[hidden] { display: none !important; }
body { margin: 0; background: var(--bg); color: var(--text);
  font-family: "Inter", system-ui, sans-serif; line-height: 1.55;
  -webkit-font-smoothing: antialiased; }
a { color: var(--text); }
h1 { font-family: "Space Grotesk", sans-serif; font-size: 30px;
  letter-spacing: -0.025em; margin: 0 0 8px; line-height: 1.15; }
h2 { font-family: "Space Grotesk", sans-serif; font-size: 17px;
  letter-spacing: -0.01em; margin: 32px 0 12px; }
.lead { color: var(--text-secondary); font-size: 15px; margin: 0 0 26px; }
.muted { color: var(--text-secondary); font-size: 13.5px; }
.wordmark { font-family: "Space Grotesk", sans-serif; font-weight: 700;
  font-size: 19px; letter-spacing: -0.03em; text-decoration: none; color: var(--text); }
.caret { color: var(--accent); }

/* ── app shell ────────────────────────────────────────────────────────── */
.topbar { border-bottom: 1px solid var(--border); background: var(--bg);
  position: sticky; top: 0; z-index: 10; }
.topbar-in { max-width: 940px; margin: 0 auto; padding: 14px 20px;
  display: flex; align-items: center; gap: 22px; }
.topbar nav { display: flex; gap: 18px; font-size: 14px; margin-left: 6px; }
.topbar nav a { color: var(--text-secondary); text-decoration: none; }
.topbar nav a:hover { color: var(--text); }
.topbar nav a.on { color: var(--text); font-weight: 500; }
.topbar .right { margin-left: auto; display: flex; align-items: center;
  gap: 14px; font-size: 13px; color: var(--text-secondary); }
.wrap { max-width: 940px; margin: 0 auto; padding: 34px 20px 80px; }
.wrap.narrow { max-width: 620px; }

/* ── auth ─────────────────────────────────────────────────────────────── */
.auth { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.auth-card { width: 100%; max-width: 400px; }
.auth-card .wordmark { display: inline-block; margin-bottom: 34px; }
.auth-card h1 { font-size: 26px; }
.tick { width: 42px; height: 42px; border-radius: 50%; display: grid;
  place-items: center; background: var(--accent-bg); color: var(--accent);
  font-size: 20px; margin-bottom: 16px; }

/* ── forms ────────────────────────────────────────────────────────────── */
label { display: block; font-size: 11.5px; font-weight: 600; letter-spacing: .05em;
  text-transform: uppercase; color: var(--text-secondary); margin: 18px 0 6px; }
/* Match by exclusion, not enumeration. `input[type=text]` misses a bare
   <input> (no type attribute at all, which defaults to text) and misses every
   future type — usdreceipt's stylesheet omitted `select` the same way and the
   app grew inline style attributes to compensate. */
input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=submit]),
textarea, select {
  width: 100%; background: var(--surface); border: 1px solid var(--border);
  color: var(--text); border-radius: 8px; padding: 11px 13px; font: inherit;
  font-size: 14.5px; transition: border-color .12s, box-shadow .12s; }
input:focus, textarea:focus, select:focus { outline: none;
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-bg); }
textarea { min-height: 90px; resize: vertical;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }
.hint { color: var(--text-dim); font-size: 12.5px; margin: 6px 0 0; }
.field-error { color: var(--error); font-size: 12.5px; margin: 6px 0 0; }

/* SIZE LIVES HERE AND NOWHERE ELSE.
   Every colour variant below sets colour only. It used to set padding too, so
   picking a colour silently picked a size: `.btn-ghost` was 14px of horizontal
   padding and `.btn-solid` 16px, which meant a Cancel sitting beside a Save
   came out 4px narrower for the same length of label. Multiply that across a
   page of rows and it reads as buttons of assorted sizes rather than a set.
   If you need a different size, add a size class — do not put padding on a
   colour. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1px solid transparent; border-radius: 8px; padding: 8px 16px;
  /* A row mixes <button> and <a>. Without a min-height the anchors come out a
     pixel or two shorter than the buttons, which is exactly the kind of
     difference you see without being able to name. */
  min-height: 36px;
  font: inherit; font-size: 13.5px; font-weight: 500; cursor: pointer;
  text-decoration: none; transition: background .12s, border-color .12s,
  color .12s, opacity .12s, transform .06s; }
.btn:disabled { opacity: .55; cursor: default; }
/* Pressed. Nothing acknowledged a click before the network answered, so a slow
   save felt like a button that had not registered. */
.btn:active:not(:disabled) { transform: translateY(1px); }

/* THERE WAS NO FOCUS STYLE ON ANY BUTTON. Inputs had one; buttons, chips and
   link-buttons had nothing, so tabbing through the dashboard moved an invisible
   cursor — the whole interface was unusable from a keyboard and it is the sort
   of thing that never shows up in a screenshot.
   `:focus-visible` rather than `:focus`, so a mouse click does not leave a ring
   behind on the button you just pressed. */
.btn:focus-visible, .chip:focus-visible, .linkish:focus-visible,
summary:focus-visible, .m-tab:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }

/* The full-width button that ENDS a form, and the one place a larger size is
   the point — it is the only control on its line. Size is stated here rather
   than inherited from `.btn` so that the base can stay the row size, which is
   what almost every button in the product actually is. */
.btn-primary { background: var(--brand); color: var(--on-brand); width: 100%;
  margin-top: 22px; padding: 11px 18px; font-size: 14.5px; }
.btn-primary:hover:not(:disabled) { background: var(--brand-hover); }

.btn-ghost { background: transparent; border-color: var(--border-strong);
  color: var(--text); }
.btn-ghost:hover:not(:disabled) { border-color: var(--text-secondary);
  background: var(--surface-2); }

/* The third weight, and the reason it exists: a panel with Save, two "open in a
   new tab" links and Retire on one row rendered four bordered buttons of equal
   size, so nothing said which one you had come to press. Quiet has no border
   and no fill — it reads as a link that happens to be button-shaped, which is
   what "open this in a new tab" actually is. */
.btn-quiet { background: transparent; border-color: transparent;
  color: var(--text-secondary); padding-left: 10px; padding-right: 10px; }
.btn-quiet:hover:not(:disabled) { color: var(--text); background: var(--surface-2); }

/* Destructive, at rest. `.btn-danger` is filled and belongs on the button that
   ACTUALLY does the thing, inside the confirmation — a filled red sitting in a
   row next to Save invites the click it is trying to make you think about. */
.btn-danger-ghost { background: transparent; border-color: transparent;
  color: var(--text-secondary); }
.btn-danger-ghost:hover:not(:disabled) { color: var(--error);
  border-color: color-mix(in srgb, var(--error) 45%, transparent);
  background: color-mix(in srgb, var(--error) 8%, transparent); }

/* Pushes the destructive action away from the constructive ones. Same row, so
   it stays findable; opposite end, so it is not adjacent to Save. */
.row-actions .spacer { margin-left: auto; }

/* The filled button for an action inside a row. `.btn-primary` is the
   full-width one that ends the create form; using it for "Save wallets" would
   stretch it across the panel, and using nothing at all is what left these
   rendering as the browser's default grey. */
.btn-solid { background: var(--brand); color: var(--on-brand); }
.btn-solid:hover:not(:disabled) { background: var(--brand-hover); }

/* The one that spends money or reveals a key gets the accent, so the
   consequential button in a row is never the same weight as Cancel. */
.btn-accent { background: var(--accent); color: #042f2a; }
.btn-accent:hover:not(:disabled) { filter: brightness(1.07); }
.linkish { background: none; border: none; padding: 0; font: inherit;
  color: var(--accent); cursor: pointer; text-decoration: underline; }

.spinner { width: 14px; height: 14px; border: 2px solid currentColor;
  border-right-color: transparent; border-radius: 50%; animation: spin .6s linear infinite; }
.spinner.big { width: 30px; height: 30px; border-width: 3px; color: var(--accent);
  margin-bottom: 18px; }
@keyframes spin { to { transform: rotate(360deg); } }

.notice { margin-top: 18px; padding: 11px 13px; border-radius: 8px; font-size: 13.5px;
  background: var(--surface); border: 1px solid var(--border); }
.notice.error { background: var(--error-bg); border-color: var(--error); color: var(--error); }

/* ── dashboard ────────────────────────────────────────────────────────── */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px; margin: 4px 0 8px; }
.stat { background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 16px 18px; }
.stat .n { font-family: "Space Grotesk", sans-serif; font-size: 25px;
  letter-spacing: -0.02em; display: block; }
.stat .k { font-size: 11px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-secondary); margin-top: 3px; display: block; }

.list { list-style: none; padding: 0; margin: 0; }
/* `wrap` matters: the Manage panel is appended as a third child, and without
   it the panel sits BESIDE the title and price as a flex sibling, crushing
   `.grow` to zero width — the title and the price then render on top of each
   other. Measured before the fix: title width 0px, panel at x=262. */
.row { border: 1px solid var(--border); border-radius: var(--radius);
  padding: 15px 17px; margin-bottom: 10px; background: var(--surface);
  display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start; }
.row .grow { flex: 1; min-width: 0; }
.row .t { font-weight: 500; font-size: 15px; }
.row .u { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; color: var(--text-secondary); margin-top: 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The second line of a row is prose now — sales — not a URL. Monospace was
   right when it held `…/c/chk_UdPs-BBRSi3SjPG8` and reads as a code fragment
   for anything else. */
/* The kind tag is information, not a warning — quieter than `test`. */
.row .tag.kind { opacity: .72; }
.row .meta-line { font-size: 12.5px; color: var(--text-secondary);
  margin-top: 4px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.row .price { font-family: "Space Grotesk", sans-serif; font-size: 16px;
  white-space: nowrap; }
/* Transparent on desktop: price and Copy stay direct flex children of .row, so
   the wide layout is untouched. The mobile rule turns it into a real box. */
.row .foot { display: contents; }

/* ── checkouts grouped by what the buyer receives ───────────────────────
   A flat list made an API wrapper, a fixed payload and a file download look
   like one kind of object. They are three products with different rules. */
.list .group { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin: 22px 0 10px; padding: 0; border: 0; background: none; }
.list .group:first-child { margin-top: 4px; }
.g-name { font-family: "Space Grotesk", sans-serif; font-size: 14px;
  font-weight: 600; display: inline-flex; align-items: center; gap: 8px; }
.g-n { font-family: "Inter", sans-serif; font-size: 11.5px; font-weight: 500;
  color: var(--text-secondary); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 8px; }
.g-why { font-size: 12.5px; color: var(--text-dim); }

/* ── one checkout, managed in place ─────────────────────────────────────
   Editing and per-checkout revenue both existed on the API and the CLI. The
   dashboard had neither, so the surface most sellers use was the only one
   that could not answer "how is this one doing". Inline rather than a
   separate page: you are looking at the list because you are comparing them,
   and navigating away loses that. */
/* Full width, on its own line under the row. `grid-column: 1 / -1` was doing
   nothing here — .row is a flex container, not a grid, so the declaration was
   silently ignored and the panel laid out inline. */
.manage { flex: 1 0 100%; width: 100%; margin-top: 14px; padding-top: 14px;
  border-top: 1px solid var(--border); }
.m-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
  margin-bottom: 6px; }
.m-stats div { background: var(--bg); border: 1px solid var(--border);
  border-radius: 8px; padding: 10px 12px; }
.m-stats b { display: block; font-family: "Space Grotesk", sans-serif;
  font-size: 17px; font-weight: 600; }
.m-stats span { font-size: 11px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-dim); }
.manage label { margin-top: 14px; }
.m-msg { font-size: 13px; margin-top: 10px; }
.m-msg.ok { color: var(--accent); }
.m-msg.bad { color: var(--error); }

@media (max-width: 560px) {
  .m-stats { grid-template-columns: 1fr 1fr; }
  .list .group { gap: 6px; }
  .g-why { width: 100%; }
}
.tag { display: inline-block; font-size: 10.5px; letter-spacing: .06em;
  text-transform: uppercase; padding: 2px 7px; border-radius: 5px;
  border: 1px solid var(--border-strong); color: var(--text-secondary);
  margin-left: 8px; vertical-align: 1px; }
.tag.accent { color: var(--accent); border-color: var(--accent); }

.empty { border: 1px dashed var(--border-strong); border-radius: var(--radius);
  padding: 40px 24px; text-align: center; color: var(--text-secondary); }
.empty h2 { margin: 0 0 6px; }

/* ── copy affordance ──────────────────────────────────────────────────── */
.copy { background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 10px 12px; display: flex; gap: 10px;
  align-items: center; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px; }
.copy code { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
/* The anchor too — "Add to Claude ↗" is an <a>, and without this it collapses
   to a couple of characters next to a long URL.
   The font reset matters: `.copy` is monospace so the URL lines up, and `.btn`
   is `font: inherit`, so the button labels were coming out monospace too. */
.copy button, .copy a { flex-shrink: 0;
  font-family: "Inter", system-ui, sans-serif; }

@media (max-width: 560px) {
  .topbar nav { display: none; }
  /* URL on its own line, the two actions sharing the next one. Three items in
     one row at 375px leaves the URL about eight characters wide. */
  .copy { flex-wrap: wrap; }
  .copy code { flex: 1 0 100%; }
  .copy button, .copy a { flex: 1 1 auto; justify-content: center; min-height: 40px; }
}

.result { border: 1px solid var(--accent); background: var(--accent-bg);
  border-radius: var(--radius); padding: 20px; margin-top: 26px; }
.result h2 { margin: 0 0 4px; }

details.adv { margin-top: 22px; border-top: 1px solid var(--border); padding-top: 6px; }
details.adv summary { cursor: pointer; font-size: 13.5px; color: var(--text-secondary);
  padding: 10px 0; list-style: none; }
details.adv summary::-webkit-details-marker { display: none; }
details.adv summary::before { content: "▸ "; color: var(--text-dim); }
details.adv[open] summary::before { content: "▾ "; }

@media (max-width: 560px) {
  /* The row goes vertical, and in a COLUMN flex container `min-width: 0` on
     the child no longer constrains it — the checkout URL grew past the card
     edge and pushed the page into horizontal scroll. An explicit 100% width
     plus the ellipsis rule is what actually truncates it. */
  /* Two rows, not four. Stacking title / URL / price / full-width Copy made
     one checkout 350px tall, so four of them filled a phone screen and the
     list stopped being scannable — the thing a list is for. Title and URL take
     the top; price and Copy share the bottom, where the price is the value
     you scan and Copy is the action you take. */
  .row { flex-direction: column; align-items: stretch; gap: 10px;
    padding: 14px 15px; }
  .row .grow, .row .u, .row .meta-line { width: 100%; max-width: 100%; min-width: 0; }
  .row .foot { display: flex; align-items: center; justify-content: space-between;
    gap: 12px; }
  .row .price { font-size: 17px; }
  /* `flex: none` only. This used to also set `padding: 7px 16px`, one pixel off
     the base — a difference invisible in isolation and clearly wrong beside a
     button that did not have it. Size on mobile comes from the single
     min-height rule below. */
  .row .foot .btn { flex: none; }

  /* One row, always. The row needs 356px and a phone gives 343, so wrapping
     dropped "Sign out" onto a line of its own — floating right under the nav,
     which reads as a mistake — and doubled the header height, which is what
     put the section rail behind it. Nothing wraps now: the email goes (you
     know who you are), the nav scrolls if it must, and Sign out holds its
     place at the end of the row. */
  .topbar-in { gap: 12px; flex-wrap: nowrap; padding: 11px 16px; }
  .wordmark { font-size: 17px; flex: none; }
  .topbar nav { gap: 15px; margin-left: 0; min-width: 0;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .topbar nav::-webkit-scrollbar { display: none; }
  /* 40px of tappable height, measured. These were 22px — a text link with no
     padding — which on a phone is a coin-flip whether you hit "Checkouts" or
     the row beneath it. The label stays the same size; only the target grows. */
  .topbar nav a { white-space: nowrap; display: inline-flex; align-items: center;
    min-height: 40px; }
  .topbar nav { align-items: stretch; }
  /* The right side shrinks with the screen: a long account name in the
     switcher used to push the page to 600px wide, and the phone zoomed the
     whole dashboard out to fit it. */
  .topbar .right { margin-left: auto; flex: 1 1 auto; min-width: 0; justify-content: flex-end; gap: 10px; }
  .acct-switch { min-width: 0; flex: 0 1 auto; margin-right: 0; }
  .acct-switch .acct-k { display: none; }
  .acct-switch select { max-width: min(46vw, 220px); min-width: 0; width: auto; text-overflow: ellipsis; }
  #signout { white-space: nowrap; }
  #who { display: none; }
  /* A real target, not a 13px word. 33px measured before this. */
  #signout { padding: 6px 0; font-size: 13.5px; display: inline-flex;
    align-items: center; min-height: 40px; }

  /* Drop "Create" from the header: the row still overflows by 28px with it,
     and a half-visible "D" where "Docs" should be is the kind of detail that
     makes people distrust the rest. It is not lost — the section rail
     directly below has a Create chip pointing at the same anchor. */
  .topbar nav a[href$="#s-create"] { display: none; }

  .wrap { padding: 24px 16px 60px; }
  h1 { font-size: 25px; }
  .first-run { gap: 12px; }
  .fr-link { margin-left: 0; }
}

/* ── skeletons ─────────────────────────────────────────────────────────
   Never the string "Loading…". A skeleton keeps the layout stable so the
   page does not jump, and a re-fetch does not look like an error. */
.skel { display: inline-block; height: .85em; width: 100%; border-radius: 5px;
  vertical-align: -1px;
  background: linear-gradient(90deg, var(--surface) 25%, var(--surface-2) 50%, var(--surface) 75%);
  background-size: 200% 100%; animation: skel 1.3s ease-in-out infinite; }
@keyframes skel { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }
.stat .n .skel { width: 60%; height: 22px; }

/* ── first run ─────────────────────────────────────────────────────────
   One row, gone the moment a checkout exists. A stepper that never leaves
   becomes furniture nobody reads. */
.first-run { display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); padding: 14px 18px; margin-bottom: 20px; }
.fr-title { font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-secondary); font-weight: 600; }
.fr-steps { list-style: none; display: flex; gap: 20px; margin: 0; padding: 0;
  flex-wrap: wrap; font-size: 13.5px; color: var(--text-secondary); }
.fr-steps li { display: flex; align-items: center; gap: 7px; }
.fr-num { width: 20px; height: 20px; border-radius: 50%; display: grid;
  place-items: center; background: var(--accent-bg); color: var(--accent);
  font-size: 11px; font-weight: 600; }
.fr-link { margin-left: auto; font-size: 13.5px; color: var(--accent);
  text-decoration: none; white-space: nowrap; }

/* ── layout helpers ────────────────────────────────────────────────────── */
.page-head { margin-bottom: 22px; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 560px) { .grid2 { grid-template-columns: 1fr; gap: 0; } }
label.check { display: flex; align-items: center; gap: 9px; text-transform: none;
  letter-spacing: 0; font-size: 14px; font-weight: 400; color: var(--text);
  margin: 14px 0 0; cursor: pointer; }
label.check input { width: auto; }

/* Empty state names the next action — a dead end is worse than no list. */
.empty { display: block; border: 1px dashed var(--border-strong);
  border-radius: var(--radius); padding: 30px 22px; text-align: center; }
.empty strong { display: block; margin-bottom: 4px; }
.empty .hint { color: var(--text-secondary); font-size: 13.5px; }

.notice.ok { border-color: var(--accent); background: var(--accent-bg); }
.notice code { font-size: 12.5px; word-break: break-all; }
#msg:empty { display: none; }
#msg .notice { margin-top: 16px; }


/* ── dashboard layout: sticky section rail ─────────────────────────────────
   One authenticated page with an outline, not tabs. The rail is a scroll-spy
   over anchors — no router, no state to get out of sync with the URL, and
   Back still leaves the page rather than cycling tabs. */
.dash { display: grid; grid-template-columns: 180px 1fr; gap: 34px;
  align-items: start; max-width: 1060px; margin: 0 auto; padding: 30px 20px 90px; }
/* Offsets come from --topbar-h, published by the header itself (see
   _topbar.html). Every one of these used to be a hard-coded guess. */
.rail { position: sticky; top: calc(var(--topbar-h, 57px) + 17px); min-width: 0; }
.rail li.rail-group { margin-top: 22px; list-style: none; display: flex; align-items: center; gap: 7px; }
.rail li.rail-group:first-child { margin-top: 0; }
/* Two sections, two colours: buying is money out (orange), selling is money
   in (blue). The title carries a swatch and the active link in each group
   takes the group's colour. */
.rail li.rail-group::before { content: ""; width: 9px; height: 9px; border-radius: 2px; background: var(--border-strong); }
.rail li.rail-buying::before { background: var(--burn); }
.rail li.rail-wallets::before { background: var(--burn); }
.rail li.rail-account::before { background: var(--accent); }
.rail li.rail-analytics::before, .rail li.rail-archive::before { background: var(--border-strong); }
.rail li.rail-wallets ~ li a.on { border-left-color: var(--burn); }
.rail li.rail-account ~ li a.on { border-left-color: var(--accent); }
.rail-ico { display: inline-block; width: 12px; height: 12px; margin-right: 8px; vertical-align: -1px; opacity: .8; }
.rail a.on .rail-ico { opacity: 1; }
.parity { margin: 10px 0 0; }
.parity summary { font-size: 12px; color: var(--text-dim); cursor: pointer; }
.parity pre { margin: 6px 0; font-size: 12px; white-space: pre-wrap; word-break: break-all; }
.cost-line { font-size: 12.5px; color: var(--text-dim); margin: 4px 0 0; }
.stat-table td, .stat-table th { padding: 6px 8px; text-align: left; font-size: 13px; }
.rail li.rail-selling::before { background: var(--recv); }
.rail li.rail-buying ~ li a.on { border-left-color: var(--burn); }
.rail li.rail-selling ~ li a.on { border-left-color: var(--recv); }
.rail-title { font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-dim); margin-bottom: 10px; }
.rail ul { list-style: none; margin: 0; padding: 0; }
.rail a { display: block; padding: 6px 0 6px 11px; font-size: 13.5px;
  color: var(--text-secondary); text-decoration: none;
  border-left: 2px solid var(--border); transition: color .12s, border-color .12s; }
.rail a:hover { color: var(--text); }
.rail a.on { color: var(--text); border-left-color: var(--accent); font-weight: 500; }
.dash-main { min-width: 0; }

/* Mobile: the rail becomes a horizontal chip strip under the header. */
@media (max-width: 820px) {
  .dash { grid-template-columns: 1fr; gap: 18px; padding: 20px 16px 70px; }
  .rail { position: sticky; top: var(--topbar-h, 57px); background: var(--bg);
    z-index: 5; margin: 0 -16px; padding: 10px 16px;
    border-bottom: 1px solid var(--border); }
  .rail-title { display: none; }
  .rail ul { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; }
  .rail ul::-webkit-scrollbar { display: none; }
  /* 40px tall, measured — these were 31px. This is the primary navigation on
     a phone, tapped more than anything else on the page, and 5px of vertical
     padding made it the smallest target in the product. The pill looks the
     same; the padding does the work. */
  .rail a { white-space: nowrap; border-left: none; border: 1px solid var(--border);
    border-radius: 999px; padding: 0 14px; font-size: 12.5px;
    display: inline-flex; align-items: center; min-height: 40px; }
  .rail a.on { border-color: var(--accent); color: var(--accent); }
}

/* Sections get scroll-margin so the sticky header never covers a heading. */
/* Clear BOTH sticky bars, or an anchor lands on a heading hidden behind them. */
section[id] { scroll-margin-top: calc(var(--sticky-h, 84px) + 12px); }
section[id] + section[id] { margin-top: 44px; }
section > h2:first-child { margin-top: 0; }

/* ── receipts ─────────────────────────────────────────────────────────── */
.rcpt { display: grid; grid-template-columns: auto 1fr auto; gap: 4px 14px;
  align-items: baseline; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); padding: 13px 16px; margin-bottom: 8px; }
.rcpt .when { font-size: 12.5px; color: var(--text-secondary);
  font-variant-numeric: tabular-nums; }
.rcpt .what { font-size: 14px; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.rcpt .amt { font-family: "Space Grotesk", sans-serif; font-size: 15px;
  font-variant-numeric: tabular-nums; }
.rcpt .meta { grid-column: 1 / -1; font-size: 12px; color: var(--text-dim);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rcpt.undelivered { border-color: var(--error); }
.rcpt .warn { grid-column: 1 / -1; color: var(--error); font-size: 12.5px; }
/* Key rows wrap instead of truncating: the mode tag and a platform key's
   CUT chip are the facts the list exists to show, and on a phone the
   receipts-style ellipsis was eating exactly them. Scoped to #keys so
   receipt rows keep their one-line shape. */
#keys .rcpt .what { white-space: normal; overflow: visible; text-overflow: clip; }
#keys .rcpt .what .tag { white-space: nowrap; }

/* Key rows carry a trailing action (Revoke) or a dead-tag, so they widen the
   grid by one cell. A revoked key stays listed but reads as spent: dimmed,
   struck, its prefix greyed — present as a record, plainly not usable. */
#keys .rcpt { grid-template-columns: auto 1fr auto auto; }
#keys .rcpt .hint { grid-column: 1 / -1; margin: 2px 0 0; }
.rcpt.is-revoked { opacity: .55; }
.rcpt.is-revoked .what, .rcpt.is-revoked .amt { text-decoration: line-through; }
.tag.tag-off { color: var(--text-secondary); border-color: var(--border); }
.btn-revoke { font-size: 12px; font-weight: 600; padding: 5px 12px;
  border-radius: var(--radius); border: 1px solid var(--border);
  background: transparent; color: var(--text-secondary); cursor: pointer;
  white-space: nowrap; transition: color .12s, border-color .12s; }
.btn-revoke:hover:not(:disabled) { color: var(--error); border-color: var(--error); }
.btn-revoke:disabled { opacity: .6; cursor: default; }

/* Per-checkout revenue. Deliberately a table and not more .rcpt cards: these
   are figures to compare down a column, and cards defeat that. */
.perf { width: 100%; border-collapse: collapse; margin-top: 6px; }
.perf td { border-bottom: 1px solid var(--border); padding: 11px 4px; font-size: 14px; }
.perf tr:last-child td { border-bottom: 0; }
.perf td.grow { width: 100%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; max-width: 0; }
.perf td:not(.grow) { white-space: nowrap; text-align: right; padding-left: 18px;
  color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.perf td.amt { font-family: "Space Grotesk", sans-serif; color: var(--text); }
.perf td.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; color: var(--text); }

/* ── Payout wallet generator ─────────────────────────────────────────────
   Everything here shows key material, so it is styled to be read carefully
   rather than skimmed past. */
.row-actions { display: flex; gap: 12px 14px; flex-wrap: wrap; margin-top: 6px; }
/* A row of buttons wraps on a phone: the gap keeps them apart in both
   directions, and each one is easy to hit. */
@media (max-width: 560px) { .row-actions .btn { min-height: 44px; } }
.field + .row-actions { margin-top: 14px; }
.genwrap { margin-top: 18px; border: 1px solid var(--border-strong);
  border-radius: var(--radius); padding: 18px; background: var(--surface); }
.notice.warn { border-color: var(--warn, #d97706); color: var(--text);
  background: rgba(217, 119, 6, .1); }

/* One chip per word. A phrase set as prose is the easiest thing in the world
   to transcribe wrongly, and the mistake only surfaces when a restore fails. */
.phrase { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 8px; margin: 16px 0; }
.phrase .word { display: flex; align-items: baseline; gap: 8px;
  border: 1px solid var(--border); border-radius: 7px; padding: 8px 11px;
  background: var(--bg); font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13.5px; user-select: all; }
.phrase .word i { font-style: normal; color: var(--text-dim); font-size: 11px;
  min-width: 14px; text-align: right; }

/* One-shot copy. Deliberately the largest control in the panel: it is the
   action that prevents the failure mode, which is saving the phrase and
   losing the keys. */
/* A button and a caption, not one full-width slab with two lines in it — that
   read as a banner, which is the one thing a button must not look like. The
   description sits OUTSIDE the control so the clickable area is button-shaped. */
.grab { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 16px 0 20px; }
.grab .grab-note { font-size: 12.5px; color: var(--text-secondary); }
/* Already accent via .btn-accent, so "copied" reads as a brief dim rather than
   a colour change that would look like a different button. */
.grab .btn.done { opacity: .8; }

.genrow { margin: 18px 0; }
.genrow-head { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 9px; }
.genrow-head h3 { margin: 0; font-size: 12px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-dim); font-weight: 600; }

/* Small inline copy. `flex: none` so it never shrinks under a long address. */
.chip { flex: none; padding: 5px 11px; font-size: 12px; border-radius: 6px;
  background: transparent; border: 1px solid var(--border-strong);
  color: var(--text-secondary); cursor: pointer; white-space: nowrap; }
.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip.done { border-color: var(--accent); color: var(--accent); }

/* label / value / copy. `minmax(0,1fr)` on the value is what actually lets it
   shrink — a grid track defaults to min-content, so a 44-character address
   would push the copy button off the side of a phone instead of wrapping. */
.val { display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 10px; align-items: center; padding: 9px 0;
  border-bottom: 1px solid var(--border); }
.val:last-child { border-bottom: 0; }
.val-k { font-size: 12.5px; color: var(--text-dim); white-space: nowrap; }
.val-v { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; min-width: 0; overflow-wrap: anywhere; user-select: all;
  color: var(--text); }

.reveal { margin: 18px 0; }
.reveal summary { cursor: pointer; font-size: 13px; color: var(--text-secondary);
  letter-spacing: .04em; text-transform: uppercase; font-weight: 600;
  padding: 6px 0; }
.reveal summary:hover { color: var(--accent); }
.reveal > .muted { font-size: 13px; margin: 4px 0 10px; }

/* `label` is uppercased for form fields; this one is a sentence the seller has
   to actually read, and shouting it makes it read as boilerplate to skip. */
.ack { display: flex; gap: 9px; align-items: flex-start; margin: 16px 0 12px;
  font-size: 14px; cursor: pointer; text-transform: none; letter-spacing: normal;
  color: var(--text); font-weight: 400; }
.ack input { width: auto; margin: 2px 0 0; flex: none; }

/* Two products, chosen explicitly. A number box with placeholder "1" asked the
   seller to infer that a single call and a package are different things with
   different rules; this states it. */
.seg { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }
.seg button { display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  text-align: left; padding: 12px 14px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius); cursor: pointer;
  color: var(--text-secondary); font: inherit; }
.seg button b { font-size: 14px; font-weight: 600; color: var(--text); }
.seg button span { font-size: 12.5px; line-height: 1.4; }
.seg button:hover { border-color: var(--border-strong); }
.seg button.on { border-color: var(--accent); background: var(--accent-bg); }
.seg button.on b { color: var(--accent); }

.hint.error { color: var(--error); }

/* Off-screen but still a real form control: the cards write to a <select> that
   every other script already reads, and `display:none` would drop it from the
   accessibility tree AND from HTML5 validation. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.btn-sm { padding: 7px 12px; font-size: 13px; width: auto; }

/* ── the create cascade ───────────────────────────────────────────────────
   One question per screen. The rail is the only thing that tells a seller how
   much is left, so it hides the steps that don't apply to their answer rather
   than greying them: a "3 of 4" that never reaches 3 is a broken promise. */
.wiz-rail { display: flex; gap: 6px; list-style: none; padding: 0;
  margin: 0 0 22px; overflow-x: auto; scrollbar-width: none; }
.wiz-rail::-webkit-scrollbar { display: none; }
.wiz-rail li { display: flex; align-items: center; gap: 7px; flex: 0 0 auto;
  font-size: 12.5px; color: var(--text-dim); padding-right: 6px; }
.wiz-rail li b { display: grid; place-items: center; width: 22px; height: 22px;
  border-radius: 50%; background: var(--surface-2); border: 1px solid var(--border);
  font-size: 11.5px; font-weight: 600; flex: 0 0 auto; }
.wiz-rail li.on { color: var(--text); font-weight: 500; }
.wiz-rail li.on b { background: var(--accent); border-color: var(--accent); color: #fff; }
.wiz-rail li.done b { background: var(--accent-bg); border-color: var(--accent);
  color: var(--accent); }
.wiz-rail li + li::before { content: ""; width: 14px; height: 1px;
  background: var(--border); margin-right: 1px; order: -1; }

.wiz-nav { display: flex; gap: 10px; align-items: center; margin-top: 4px; }
.wiz-nav .btn { flex: 1; }
.wiz-nav #wiz-back { flex: 0 0 auto; min-width: 88px; }

/* Same shape as .seg, but a list rather than a pair — a two-column grid of
   five reads as an incomplete row. */
.type-grid { display: grid; gap: 8px; margin-bottom: 16px; }
.type-grid button { display: block; text-align: left; padding: 13px 15px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); cursor: pointer; color: var(--text-secondary);
  font: inherit; }
.type-grid button b { display: block; font-size: 14px; font-weight: 600;
  color: var(--text); margin-bottom: 2px; }
.type-grid button span { font-size: 12.5px; line-height: 1.45; }
.type-grid button:hover { border-color: var(--border-strong); }
.type-grid button.on { border-color: var(--accent); background: var(--accent-bg); }
.type-grid button.on b { color: var(--accent); }

@media (min-width: 620px) {
  .type-grid { grid-template-columns: 1fr 1fr; }
  .wiz-rail li span { display: inline; }
}
/* On a phone the rail is icons-and-current-label only: five words of step
   names wrap to three lines and push the actual question off the screen. */
@media (max-width: 619px) {
  .wiz-rail li span { display: none; }
  .wiz-rail li.on span { display: inline; }
}

/* The paste block. Wide by nature — it is markup — so it scrolls inside its
   own box; without this the PAGE scrolled sideways, which is the one thing a
   phone layout must never do. */
.embed-out { margin: 0; padding: 12px 14px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 8px;
  overflow-x: auto; max-width: 100%; }
.embed-out code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px; line-height: 1.5; white-space: pre; color: var(--text-secondary);
  background: none; border: 0; padding: 0; }
#s-embed .reveal .muted { margin: 6px 0 0; }

@media (max-width: 560px) { .seg { grid-template-columns: 1fr; gap: 8px; } }

/* Confirm-before-change. Bordered in the accent rather than the error colour:
   this is a deliberate action being checked, not a mistake being reported. */
.confirm { margin-top: 16px; border: 1px solid var(--accent);
  border-radius: var(--radius); background: var(--accent-bg); padding: 16px; }
.confirm h3 { margin: 0 0 10px; font-size: 14.5px; }
.confirm ul { margin: 0 0 10px; padding-left: 20px; font-size: 14px; }
.confirm li { margin-bottom: 6px; }
.confirm code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px; overflow-wrap: anywhere; }
.confirm .muted { font-size: 13px; margin: 0 0 12px; }

/* Change history. Three columns on desktop, stacked on a phone. */
.hist { display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 4px 14px; align-items: baseline; padding: 10px 0;
  border-bottom: 1px solid var(--border); font-size: 13px; }
.hist:last-child { border-bottom: 0; }
.hist .when { color: var(--text-secondary); font-variant-numeric: tabular-nums;
  white-space: nowrap; font-size: 12.5px; }
.hist .what { min-width: 0; overflow-wrap: anywhere; }
.hist .what code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; color: var(--text-secondary); }
.hist .who { color: var(--text-dim); font-size: 12px; white-space: nowrap; }

@media (max-width: 560px) {
  /* Edge-to-edge: 18px of padding on each side of a 44-character key on a
     360px screen leaves nothing for the key. */
  .genwrap { padding: 14px 12px; margin-left: -4px; margin-right: -4px; }
  .confirm { padding: 13px 12px; }
  /* Three columns of history do not fit; the timestamp and actor share a row
     above the change itself rather than squeezing the address. */
  .hist { grid-template-columns: minmax(0, 1fr) auto; }
  .hist .when { grid-column: 1; }
  .hist .who { grid-column: 2; grid-row: 1; }
  .hist .what { grid-column: 1 / -1; grid-row: 2; }

  /* Three columns cannot hold label + address + button at this width, so the
     value takes its own row and the button sits under the label. Keeps the
     copy target full-size instead of shrinking it to fit. */
  .val { grid-template-columns: minmax(0, 1fr) auto; gap: 6px 10px; }
  .val-k { grid-column: 1; }
  .chip { grid-column: 2; grid-row: 1; }
  .val-v { grid-column: 1 / -1; grid-row: 2; font-size: 12px; }

  /* 2 columns at 360px; auto-fill alone would try for 3 and clip the words. */
  .phrase { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 6px; }
  .phrase .word { padding: 7px 9px; font-size: 13px; }

  .row-actions { gap: 8px; }
  .row-actions button { flex: 1 1 auto; min-width: 0; }

  /* 24px is a miss on a phone, and these copy a seed phrase and private keys
     — values the seller cannot get back if the tap lands wrong and they close
     the panel. Sized for a thumb, not for the label. */
  .chip { min-height: 38px; padding: 9px 14px; }
  .genrow-head .chip, .val .chip { min-height: 38px; }

  /* Full-width button, caption on its own line under it. Side by side at this
     width would squeeze the button to fit the caption. */
  .grab { gap: 8px; }
  .grab .btn { width: 100%; }
  .grab .grab-note { width: 100%; }

  /* ONE touch-target rule for every button on a phone.
     At the base size a button computes to roughly 37px tall, under the 44px
     minimum a finger needs, and the fix had been applied ad hoc — 42px here,
     7px padding there — so buttons ended up close-but-unequal, which reads as
     sloppier than if they were plainly different. min-height rather than more
     padding: it raises the short ones to a common floor without stretching the
     already-large `.btn-primary`. */
  .btn { min-height: 44px; }
}

/* ── connect-to-Claude card ───────────────────────────────────────────── */
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* ── Connect your agent: one URL, one pick per client, one panel ────────── */
.connect { border: 1px solid var(--border-strong); background: var(--surface); border-radius: var(--radius); padding: 18px 20px; }
.connect > label { display: block; margin-bottom: 7px; }
.connect-picks { display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 14px; }
.connect-pick { display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 999px;
  border: 1px solid var(--border); background: transparent; color: var(--text-secondary);
  font: 600 13.5px "Inter", system-ui, sans-serif; cursor: pointer; }
.connect-pick svg { width: 18px; height: 18px; fill: currentColor; }
.connect-pick:hover { color: var(--text); border-color: var(--border-strong); }
.connect-pick.on { color: var(--text); border-color: var(--accent); background: var(--accent-bg); }
.connect-panel ol { margin: 0; padding-left: 18px; font-size: 14px; color: var(--text-secondary); }
.connect-panel li { margin-bottom: 8px; }
.connect-panel li .btn { margin-right: 6px; vertical-align: middle; }
.connect-panel p { margin: 0 0 10px; font-size: 14px; }
.connect-code { margin: 8px 0 10px; padding: 12px 14px; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; font: 12.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; overflow-x: auto; white-space: pre; }
.connect code { background: var(--surface-2); border: 1px solid var(--border); border-radius: 5px; padding: 1px 5px; font-size: 12.5px; }
.connect-code code { background: none; border: 0; padding: 0; font-size: inherit; }
.connect-foot { margin: 14px 0 0; font-size: 13px; }

/* Destructive confirmation, in the panel rather than a browser confirm().
   A native dialog covers the title, price and sales figures — exactly the
   context you need to check you are retiring the right thing. */
.danger { margin-top: 14px; padding: 14px 16px; border-radius: var(--radius);
  background: var(--error-bg); border: 1px solid var(--error); }
.danger-head { font-size: 14px; font-weight: 600; color: var(--error);
  margin-bottom: 6px; }
.danger-body { font-size: 13px; line-height: 1.5; color: var(--text-secondary);
  margin: 0 0 8px; }
.danger-body b { color: var(--text); font-weight: 600; }
.danger .row-actions { margin-top: 12px; }

/* The one button in the product that destroys something. It is the only place
   the error colour is used as a fill rather than as text. */
.btn-danger { background: var(--error); color: #fff; font-weight: 600; }
.btn-danger:hover:not(:disabled) { filter: brightness(1.08); }

/* Retired rows read as history: dimmed, but not so faint they look broken.
   The record is intact — that is the whole point of a void over a delete. */
.row-archived { opacity: .72; }
.row-archived .t { color: var(--text-secondary); }

/* ------------------------------------------------------------------- modal */
/* A real <dialog>, not a div pretending to be one. The element gives focus
   trapping, Escape, inertness of the page behind it and the top layer for
   free — all of which a hand-rolled modal gets wrong on the first pass and
   nobody notices, because you have to be using a keyboard to find out.

   `alert()` was doing this job for errors. A native dialog is drawn by the
   operating system, cannot be styled, says "localhost:8403 says", and on a
   phone it is a system sheet that looks like a browser warning rather than
   something this product said. */
dialog.modal { border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); color: var(--text); padding: 0;
  width: min(440px, calc(100vw - 32px)); box-shadow: 0 24px 60px rgba(0,0,0,.55); }
dialog.modal::backdrop { background: rgba(0,0,0,.6); }
.modal-head { font-family: "Space Grotesk", sans-serif; font-size: 16px;
  font-weight: 600; padding: 18px 20px 0; }
.modal-head.is-danger { color: var(--error); }
.modal-body { padding: 10px 20px 0; font-size: 13.5px; line-height: 1.55;
  color: var(--text-secondary); }
.modal-body b { color: var(--text); font-weight: 600; }
/* The figures that tell you WHICH one you are about to act on. The retire flow
   used to be an inline panel specifically so the title and price stayed on
   screen while you decided; moving it into a dialog would have thrown that
   away, so the dialog carries them instead. */
.modal-facts { display: flex; gap: 18px; flex-wrap: wrap; margin: 14px 20px 0;
  padding: 10px 14px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); }
.modal-facts div { display: flex; flex-direction: column; gap: 2px; }
.modal-facts b { font-family: "Space Grotesk", sans-serif; font-size: 15px;
  color: var(--text); }
.modal-facts span { font-size: 10.5px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-secondary); }
.modal-actions { display: flex; gap: 10px; justify-content: flex-end;
  padding: 18px 20px 20px; }
@media (max-width: 560px) {
  .modal-actions { flex-direction: column-reverse; }
  .modal-actions .btn { width: 100%; }
}

/* --------------------------------------------------------------- analytics */
.an-filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end;
  margin-bottom: 18px; }
.an-filters label { display: block; font-size: 10.5px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-secondary); margin-bottom: 5px; }
.an-filters input, .an-filters select { min-width: 140px; }
.an-totals { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px; margin-bottom: 20px; }
.an-total { background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px 16px; }
.an-total b { display: block; font-family: "Space Grotesk", sans-serif;
  font-size: 23px; line-height: 1.1; }
.an-total span { font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-secondary); }
.an-total.is-bad b { color: var(--error); }

/* Bars rather than a line: the question is "which days earned", and a bar
   chart answers it without axes, a library, or a tooltip you have to hover to
   read. Empty days are drawn as empty bars for the same reason the series
   fills them — a gap is the thing you came to see. */
.an-chart { display: flex; align-items: flex-end; gap: 2px; height: 120px;
  padding: 0 2px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.an-bar { flex: 1 1 0; min-width: 2px; background: var(--accent); border-radius: 2px 2px 0 0;
  min-height: 1px; opacity: .85; }
/* A day with no sales must be VISIBLE as a day with no sales. At 1px it was
   indistinguishable from no data at all, which is the opposite of why the
   series fills empty buckets in the first place. */
.an-bar.is-zero { background: var(--border-strong); opacity: .55; min-height: 3px; }
.an-bar:hover { opacity: 1; }
.an-axis { display: flex; justify-content: space-between; font-size: 11px;
  color: var(--text-secondary); margin-bottom: 22px; }
.an-empty { padding: 26px; text-align: center; color: var(--text-secondary);
  font-size: 13.5px; border: 1px dashed var(--border); border-radius: var(--radius); }

/* Two fields that belong to one fact (author + date, scope + duration).
   Stacks on narrow screens, where side-by-side inputs stop being a pair
   and start being a squeeze. */
.fieldpair { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.fieldpair > div { min-width: 0; }
@media (max-width: 560px) { .fieldpair { grid-template-columns: 1fr; } }

/* The paste block. Wraps rather than scrolls: a seller copies it with the
   button, and what they see should be the whole thing, not a slice. */
.snippet-out { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap; word-break: break-word; font-size: 12px;
  line-height: 1.5; max-height: 320px; overflow: auto; margin: 10px 0 0;
  padding: 12px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2, rgba(128,128,128,.06)); }

/* ── Spending wallets ─────────────────────────────────────────────────────
   One card per chain; every panel a card opens (confirm, the one-time secret,
   the revealed key, the pay drawer) opens INSIDE it, under its buttons, with a
   short fade-and-rise. Panels that appeared at the bottom of the page, far
   from the button that opened them, were what "clunky" meant. */
/* Two kinds of wallet, two colours, everywhere they appear: receiving is
   blue (--recv), money in, yours; spending is orange (--burn), money out, a
   burner. Not the accent green, which the rest of the UI already uses. */
.sw { display: inline-block; width: 10px; height: 10px; border-radius: 3px; vertical-align: -1px; margin-right: 7px; }
.sw-in { background: var(--recv); } .sw-out { background: var(--burn); }
.sp-legend { font-size: 12.5px; color: var(--text-secondary); margin: 0 0 14px; }
.sp-legend .sw + .sw, .sp-legend .sw-in { margin-left: 12px; }
#s-spending > h2::before, #s-wallets > h2::before { content: ""; display: inline-block; width: 12px; height: 12px;
  border-radius: 3px; margin-right: 10px; vertical-align: 0; }
#s-spending > h2::before { background: var(--burn); }
#s-wallets > h2::before { background: var(--recv); }
.sp-how ul { margin: 6px 0 14px; padding-left: 18px; display: grid; gap: 8px; font-size: 14px; color: var(--text-secondary); }
.sp-how li b { color: var(--text); }
.ack { display: flex; gap: 10px; align-items: flex-start; font-size: 14px; color: var(--text);
  padding: 12px 14px; border: 1px solid var(--burn); border-radius: var(--radius); background: var(--burn-bg); margin-bottom: 12px; }
.ack input { margin-top: 3px; accent-color: var(--burn); }
.sp-recv h3 .sw { vertical-align: 0; }
.btn-burn { border: 1px solid var(--burn); color: var(--burn); background: transparent; }
.btn-burn:hover { background: var(--burn-bg); }
.sp-chains button.on { border-color: var(--burn); background: var(--burn-bg); }
.sp-chains button.on b { color: var(--burn); }
.sp-card { border: 1px solid var(--burn); border-radius: var(--radius);
  background: var(--surface); padding: 16px 18px; margin: 14px 0; }
.sp-card-head { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 12px; }
.sp-card-head > div { display: flex; align-items: center; gap: 10px; }
.sp-card-head h3 { margin: 0; font-size: 12px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-secondary); }
.sp-pill { font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
  padding: 2px 8px; border-radius: 999px; border: 1px solid var(--border);
  color: var(--text-dim); }
.sp-pill.on { border-color: var(--burn); color: var(--burn); }
.sp-balance { font-family: "Space Grotesk", sans-serif; font-size: 15px;
  color: var(--text); font-variant-numeric: tabular-nums; }
.sp-addr { margin-bottom: 12px; }
.sp-addr code { white-space: normal; overflow-wrap: anywhere; overflow: visible;
  text-overflow: clip; }
.sp-card .row-actions { margin-top: 0; }
.sp-card .notice { margin-top: 14px; }
.sp-slot > .confirm, .sp-slot > .genwrap { margin-top: 14px; }
.sp-drawer { margin-top: 14px; border: 1px solid var(--border-strong);
  border-radius: var(--radius); padding: 14px 16px; background: var(--surface-2); }
.sp-drawer-head { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; }
.sp-drawer-head h4 { margin: 0; font-size: 14px; }
.sp-drawer > .muted { margin: 4px 0 10px; font-size: 13px; }
.sp-drawer .field { margin-bottom: 10px; }

/* The entrance. `hidden` still wins (the reset's [hidden]); `.in` is added on
   the frame after unhiding, so the transition has a start state to leave. */
.sp-panel { opacity: 0; transform: translateY(6px);
  transition: opacity .18s ease, transform .18s ease; }
.sp-panel.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .sp-panel { transition: none; transform: none; opacity: 1; }
}
.sp-card .btn .spinner { margin-left: 8px; }
.sp-card .btn { display: inline-flex; align-items: center; }

/* How your agent pays: a three-way toggle over one code block. */
.sp-howto { margin-top: 28px; padding-top: 22px; border-top: 1px solid var(--border); }
.sp-howto h3 { margin: 0 0 6px; font-size: 15px; }
.sp-howto > .muted { margin: 0 0 14px; }
.sp-seg { grid-template-columns: repeat(3, 1fr); }
/* Stacked boxes in the section never touch: a notice above the picker takes
   the same 16px the picker keeps below itself. */
#s-spending > .notice { margin: 0 0 16px; }
.sp-chains { grid-template-columns: 1fr 1fr; margin: 0 0 16px; }
.sp-picker { margin: 0 0 18px; }
.sp-list { display: grid; gap: 10px; }
.sp-group h4 { margin: 0 0 6px; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); }
.sp-group { display: grid; gap: 6px; }
.sp-group button { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; text-align: left;
  padding: 10px 12px; border: 1px solid var(--border-strong); border-radius: 10px; background: var(--surface); color: var(--text); cursor: pointer; }
.sp-group button span { color: var(--text-dim); font-size: 12.5px; }
.sp-group button.on { border-color: var(--burn); background: var(--burn-bg); }
.sp-group button.on b { color: var(--burn); }
.sp-two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
#sp-burn-box { margin-bottom: 16px; }
.sp-send { border: 1px solid var(--border-strong); border-radius: 12px; padding: 12px 14px; margin: 12px 0; }
.sp-send h5, .sp-or { margin: 0 0 8px; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); }
.sp-or { margin: 14px 0 8px; }
@media (max-width: 640px) { .sp-two { grid-template-columns: 1fr; } }
.sp-chains button span { color: var(--text-dim); }
@media (max-width: 640px) { .sp-seg { grid-template-columns: 1fr; } }
.sp-howto p { font-size: 14px; line-height: 1.55; }
/* A code line and its copy chip share a row: the code scrolls inside its own
   box and the chip keeps its place, so nothing overlaps in a 400px pane. */
.sp-code { display: flex; align-items: flex-start; gap: 10px; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 10px 10px 10px 14px; margin: 10px 0; }
.sp-code pre { flex: 1 1 auto; min-width: 0; margin: 2px 0 0; overflow-x: auto; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; line-height: 1.55; white-space: pre; }
.sp-code .chip { flex-shrink: 0; }


/* ── Agent budget: the checklist, the stages, the funding sheet ──────────── */
.sp-check { list-style: none; padding: 0; margin: 0 0 18px; display: flex; gap: 14px 22px; flex-wrap: wrap; }
.sp-check li { display: flex; align-items: center; gap: 8px; color: var(--text-dim); font-size: 13.5px; }
.sp-check li.on { color: var(--text); }
.sp-check i { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--border-strong);
  display: inline-grid; place-items: center; font-style: normal; font-size: 11px; flex: none;
  transition: background .18s ease, border-color .18s ease; }
.sp-check li.on i { background: var(--accent); border-color: var(--accent); color: #042f2a; }
.sp-stage { margin-top: 14px; }
.sp-stage h3 { margin: 0 0 6px; font-size: 18px; }
.sp-stage h4 { margin: 0 0 4px; font-size: 14px; }
.sp-stage > .muted { margin: 0 0 12px; }
.chips { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 8px 0 10px; }
.chips .chip.on { border-color: var(--accent); color: var(--accent); }
.sp-other { width: 92px; padding: 5px 10px; font-size: 13px; }
.sp-warnline { font-size: 12.5px; color: var(--warn, #d97706); background: rgba(217,119,6,.1);
  border-radius: 6px; padding: 6px 10px; margin: 0 0 12px; }
.sp-doors { display: grid; gap: 18px; margin-bottom: 14px; }
.sp-door .muted { margin: 6px 0 0; font-size: 12.5px; }
.sp-door { display: flex; flex-wrap: wrap; gap: 12px 14px; align-items: center; }
.sp-door .muted { flex-basis: 100%; }
.sp-balance-row { margin: 14px 0 6px; align-items: center; }
.sp-balance-row .muted { flex-basis: 100%; }
.sp-qr { width: 190px; height: 190px; background: #fff; border-radius: 10px; padding: 6px; box-sizing: border-box; }
.sp-qr svg { width: 100%; height: 100%; display: block; }
.sp-wait { display: flex; align-items: center; gap: 8px; margin: 10px 0 4px; font-size: 13px; }
.sp-wait .spinner { width: 12px; height: 12px; }
.sp-exchanges { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.sp-exchanges > div { border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; font-size: 13px; }
.sp-exchanges p { margin: 4px 0 8px; color: var(--text-secondary); font-size: 12.5px; }
.sp-limits { margin-top: 14px; font-size: 13.5px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.sp-limits-edit { flex-basis: 100%; margin-top: 8px; }
@media (max-width: 640px) {
  .sp-exchanges { grid-template-columns: 1fr; }
  /* The funding sheet is the whole screen on a phone: one action at thumb
     height, nothing else competing. */
  #sp-fund { position: fixed; left: 0; right: 0; bottom: 0; top: auto; max-height: 92vh; overflow-y: auto;
    border-radius: 16px 16px 0 0; z-index: 40; box-shadow: 0 -12px 40px rgba(0,0,0,.35); }
  #sp-fund .btn { display: block; width: 100%; text-align: center; margin: 6px 0; }
}

/* The how-to-fund article under the Add money button: the person is not
   sent away to search for how USDC reaches a chain. */
.sp-howfund { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.sp-howfund h5 { margin: 0 0 8px; font-size: 13px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-secondary); }
.sp-howfund ol { margin: 0; padding-left: 20px; display: grid; gap: 6px; font-size: 13.5px; color: var(--text-secondary); line-height: 1.5; }
.sp-howfund ol b { color: var(--text); }
.sp-howfund a { color: var(--accent); }
.sp-howfund p { margin: 10px 0 0; }

.sp-inline { display: inline-flex; align-items: center; gap: 6px; margin-left: 12px; font-size: 13px; }
.sp-inline input { width: auto; margin: 0; accent-color: var(--burn); }

/* Support threads (dashboard, Account > Support): one message per row,
   the operator's answers set off from the account's own. */
.su-m { padding: 8px 0; border-top: 1px solid var(--border); white-space: pre-wrap; }
.su-m:first-of-type { border-top: 0; }
.su-op { padding-left: 10px; border-left: 2px solid var(--accent, #f0a040); }
.su-m > div { margin-top: 4px; }

/* Organizations: the account chooser (members only, once per session) and
   the switcher that stays at the top while acting. */
.acting-gate { border: 1px solid var(--border); border-radius: 12px; padding: 22px 24px; margin: 0 0 18px; background: var(--surface); }
.acting-gate h2 { margin: 0 0 6px; }
.acting-choices { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; margin-top: 14px; }
.acting-choice { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; text-align: left; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--bg); color: var(--text); font: inherit; cursor: pointer; }
.acting-choice:hover, .acting-choice.on { border-color: var(--accent); }
.acting-choice.on { box-shadow: inset 0 0 0 1px var(--accent); }
.acting-banner { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 8px 12px; margin: 0 0 14px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface); font-size: 14px; }
.acting-banner-label { font-family: ui-monospace, monospace; font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-soft); }
.acting-banner select { background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: 8px; padding: 5px 8px; font: inherit; }
#app.gated .page-head, #app.gated section { display: none; }

/* ── Dashboard restructure (owner review, 2026-09-05) ──────────────────── */
/* The account switcher in the top bar: members only. */
.acct-switch { display: inline-flex; align-items: center; gap: 8px; margin-right: 14px; }
.acct-switch .acct-k { font-family: ui-monospace, monospace; font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim); }
.acct-switch select { background: var(--surface); color: var(--text); border: 1px solid var(--border-strong); border-radius: 8px;
  padding: 6px 30px 6px 10px; font: inherit; font-size: 13px; min-height: 32px; }
/* Buttons: one size for a row, one for the button that ends a form; the
   full-width primary is gone (it made every form end in a slab). */
.btn-primary { width: auto; margin-top: 16px; padding: 10px 20px; font-size: 14px; }
.chip { min-height: 30px; padding: 0 12px; display: inline-flex; align-items: center; font-weight: 500; }
.row-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
/* The rail's third group. */
.rail li.rail-records::before { background: var(--border-strong); }
/* The wallets table: real rows, grouped by branch. */
.wtable { width: 100%; border-collapse: collapse; margin: 0 0 8px; font-size: 13.5px; }
.wtable th { text-align: left; font-family: ui-monospace, monospace; font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-dim); font-weight: 600; padding: 6px 10px 8px 0; border-bottom: 1px solid var(--border-strong); }
.wtable td { padding: 10px 10px 10px 0; border-bottom: 1px solid var(--border); vertical-align: middle; color: var(--text-secondary); }
.wtable tr.wrow { cursor: pointer; }
.wtable tr.wrow:hover td { background: var(--surface-2); }
.wtable tr.wrow.on td { background: var(--burn-bg); }
.wtable tr.wrow.on td:first-child { box-shadow: inset 3px 0 0 var(--burn); padding-left: 10px; }
.wtable td.wname b { color: var(--text); font-weight: 600; }
.wtable td.wname span { display: block; font-family: ui-monospace, monospace; font-size: 11.5px; color: var(--text-dim); }
.wtable td.wbal { font-family: ui-monospace, monospace; color: var(--text); white-space: nowrap; }
.wtable td.wstate { white-space: nowrap; }
.wtable .pill-awake { color: var(--accent); }
.wtable .pill-asleep { color: var(--text-dim); }
.wtable tr.wgroup td { padding: 16px 0 6px; border-bottom: 1px solid var(--border-strong); background: transparent; }
.wtable tr.wgroup h4 { margin: 0; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--text); display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.wtable tr.wgroup h4 .muted { font-weight: 400; letter-spacing: 0; text-transform: none; }
.wtable tr.wgroup .row-actions { margin: 8px 0 0; }
.wtable tr.wgroup .rule-boxes { margin-top: 8px; }
.wtable td.wkey { font-family: ui-monospace, monospace; font-size: 11.5px; color: var(--text-dim); white-space: nowrap; }
@media (max-width: 720px) { .wtable th:nth-child(3), .wtable td:nth-child(3), .wtable th:nth-child(5), .wtable td:nth-child(5) { display: none; } }
.wt-actions { display: flex; gap: 8px; align-items: center; margin: 4px 0 14px; flex-wrap: wrap; }
/* The three ways a branch pays: boxes that say what they do. */
.rule-boxes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.rule-boxes label { display: block; padding: 10px 12px; border: 1px solid var(--border-strong); border-radius: 10px; cursor: pointer;
  background: var(--surface); }
.rule-boxes label:has(input:checked) { border-color: var(--burn); background: var(--burn-bg); }
.rule-boxes input { position: absolute; opacity: 0; pointer-events: none; }
.rule-boxes b { display: block; font-size: 13px; color: var(--text); }
.rule-boxes small { display: block; font-size: 12px; line-height: 1.4; color: var(--text-dim); margin-top: 2px; }
@media (max-width: 640px) { .rule-boxes { grid-template-columns: 1fr; } }
/* The directory inside the dashboard. */
.dsearch { display: flex; gap: 8px; align-items: center; margin: 0 0 12px; }
.dsearch input { flex: 1; min-width: 0; }
.dtable { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.dtable td { padding: 9px 10px 9px 0; border-bottom: 1px solid var(--border); color: var(--text-secondary); vertical-align: top; }
.dtable td.dname b { color: var(--text); font-weight: 600; display: block; }
.dtable td.dname span { font-family: ui-monospace, monospace; font-size: 11.5px; color: var(--text-dim); }
.dtable td.dprice { font-family: ui-monospace, monospace; color: var(--text); white-space: nowrap; text-align: right; }
.dtable td.dstate { color: var(--accent); white-space: nowrap; }

/* The New wallet and New branch folds open from the buttons above the table;
   their own summaries would be a second copy of those buttons. */
#cw-wrap > summary, #br-new-wrap > summary { display: none; }
#cw-wrap[open], #br-new-wrap[open] { margin: 6px 0 16px; padding: 14px 16px; border: 1px solid var(--border-strong); border-radius: 12px; }
.topbar nav a { white-space: nowrap; }

/* Wallet states on the card: a loading bar while a fee-owing wallet gathers
   its first dollar; the checklist rows are buttons that name the next move. */
.sp-progress { display: flex; align-items: center; gap: 10px; margin: 4px 0 10px; }
.sp-progress-bar { flex: 1; height: 8px; border-radius: 4px; background: var(--border); overflow: hidden; }
.sp-progress-bar i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .4s ease; }
.sp-progress span { font-size: 12px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.sp-check li[data-step]:not(.on) { cursor: pointer; }
.sp-check li .sp-next { margin-left: 2px; font-style: normal; font-size: 12px; padding: 3px 10px; border-radius: 999px;
  background: var(--accent); color: #042f2a; white-space: nowrap; }
.sp-check li:not(.on):hover .sp-next { filter: brightness(1.08); }
#sp-refusal .btn, #sp-low .btn { margin-left: 8px; vertical-align: middle; }
.sp-chains button[data-none] span { white-space: normal; }

/* Moving a wallet: the row lifts, the branch it may land in is outlined. */
.wtable tr.wrow.dragging td { opacity: .45; }
.wtable tr.wgroup.drop-on td { box-shadow: inset 0 0 0 2px var(--accent); border-radius: 8px; background: var(--surface-2); }
.wtable tr.wrow[draggable] { cursor: grab; }
.wtable tr.wrow[draggable]:active { cursor: grabbing; }
#sp-move-row select { font: inherit; font-size: 13.5px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: transparent; color: var(--text); }

/* Confirmations open in front of the person: a centred dialog over a
   backdrop on a desk, a sheet from the bottom on a phone. */
#sp-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, .55); z-index: 1000;
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
#sp-backdrop[hidden] { display: none; }
#sp-confirm.modal { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); margin: 0;
  width: min(560px, calc(100vw - 32px)); max-height: calc(100vh - 32px); overflow: auto; z-index: 1001;
  background: var(--surface); box-shadow: 0 24px 60px rgba(0, 0, 0, .5); }
#sp-confirm.modal.in { animation: sp-pop .16s ease-out; }
@keyframes sp-pop { from { opacity: 0; transform: translate(-50%, -50%) scale(.98); } to { opacity: 1; transform: translate(-50%, -50%) scale(1); } }
@media (max-width: 640px) {
  #sp-confirm.modal { top: auto; bottom: 0; left: 0; transform: none; width: 100%; border-radius: 14px 14px 0 0; }
  #sp-confirm.modal.in { animation: none; }
}
@media (prefers-reduced-motion: reduce) { #sp-confirm.modal.in { animation: none; } }

/* The QR's halo (also on the funding page). */
/* The QR sits centred in a card with a slow beam of light travelling round
   its edge: one accent sweep, blurred behind and crisp in front. Under
   reduced motion the beam holds still. */
@property --halo-a { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.qr-wrap { display: flex; justify-content: center; margin: 18px 0; }
.qr-halo { position: relative; padding: 10px; border-radius: 20px; isolation: isolate; }
.qr-halo::before, .qr-halo::after { content: ""; position: absolute; inset: -6px; border-radius: 24px; z-index: -1;
  background: conic-gradient(from var(--halo-a), transparent 0deg 250deg, var(--accent, #2dd4bf) 310deg, #ffffff 335deg, transparent 360deg);
  animation: halo-turn 4.2s linear infinite; }
.qr-halo::before { filter: blur(14px); opacity: .85; inset: -10px; }
.qr-halo::after { inset: -2px; border-radius: 22px; padding: 2px; -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude; }
.qr-halo > * { position: relative; z-index: 1; display: block; margin: 0; }
@keyframes halo-turn { to { --halo-a: 360deg; } }
@media (prefers-reduced-motion: reduce) { .qr-halo::before, .qr-halo::after { animation: none; } }
  .qr-halo { display: inline-block; flex: 0 0 auto; width: max-content; }
.qr-wrap { flex: 1 1 100%; }
#sp-door-qr { text-align: center; }
#sp-door-qr .qr-wrap { margin-bottom: 8px; }

/* Wallets as a list and an inspector: the rows on the left, the chosen
   wallet's card pinned on the right, on a screen wide enough for both.
   Below that width the card sits under the list as before. */
@media (min-width: 1100px) {
  body[data-view="s-spending"] .wrap, body[data-view="s-spending"] .topbar-in { max-width: 1440px; }
  #s-spending.has-wallets .sp-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(400px, 38%); gap: 28px; align-items: start; }
  /* Each pane is its own scroll: the list on the left and the inspector on
     the right stay put while the other moves, like a mail client. Neither
     drags the page when it reaches its end. */
  #s-spending.has-wallets .sp-list-pane, #s-spending.has-wallets .sp-view-pane {
    max-height: max(460px, calc(100vh - var(--split-top, 290px) - var(--split-below, 20px))); overflow: auto; overscroll-behavior: contain; scrollbar-width: thin; }
  #s-spending.has-wallets .sp-list-pane { padding-right: 6px; }
  /* The page title above already says Wallets; the section's own heading
     would say it again a line lower and cost the panes the room. */
  #s-spending.has-wallets > h2, #s-spending.has-wallets > h2 + p { display: none; }
  /* New wallet and New branch stay in reach while a long list scrolls. */
  #s-spending.has-wallets .wt-actions { position: sticky; top: 0; z-index: 2; background: var(--bg); padding-bottom: 10px;
    box-shadow: 0 1px 0 var(--border); margin-bottom: 8px; }
  #s-spending.has-wallets .sp-view-pane { padding: 0 2px 8px 0; }
  #s-spending.has-wallets .sp-view-pane .insp { margin-top: 0; }
  #s-spending.has-wallets .sp-check { margin-bottom: 12px; }
  /* The list gives up the key column (the key is on the card), keeps names
     on one line, lets the branch tools wrap, and scrolls sideways before it
     ever clips. */
  #s-spending.has-wallets .wtable .wkey, #s-spending.has-wallets .wtable th:nth-child(5) { display: none; }
  #s-spending.has-wallets .wtable .wname b { white-space: nowrap; }
  #s-spending.has-wallets .wtable .wgroup .row-actions { flex-wrap: wrap; }
  /* The pane is the scroll box, sideways too: an overflow rule on the list
     wrapper would make it the toolbar's sticky container instead. */
  #s-spending.has-wallets #sp-picker { overflow: visible; }
  #s-spending.has-wallets .wtable .pill-sub { display: none; }
  #s-spending.has-wallets .wtable td:last-child { white-space: nowrap; }
  #s-spending.has-wallets .wtable td:last-child .chip { padding: 2px 7px; min-height: 0; height: 24px; line-height: 20px; margin-left: 2px; }
  #s-spending.has-wallets .wtable td, #s-spending.has-wallets .wtable th { padding-left: 8px; padding-right: 8px; }
  #s-spending.has-wallets .wtable td:first-child, #s-spending.has-wallets .wtable th:first-child { padding-left: 0; }
  #s-spending.has-wallets .wtable tr.wrow.on td:first-child { padding-left: 10px; }
}
@media (min-width: 1500px) {
  body[data-view="s-spending"] .wrap, body[data-view="s-spending"] .topbar-in { max-width: 1560px; }
  #s-spending.has-wallets .sp-split { grid-template-columns: minmax(0, 1fr) minmax(420px, 36%); gap: 36px; }
}

/* ── The inspector: the picked wallet, one panel, built for a column ─────── */
.insp { border: 1px solid var(--border-strong); border-radius: 14px; background: var(--surface); overflow: hidden; }
.insp-head { padding: 18px 18px 14px; border-bottom: 1px solid var(--border); }
.insp-id { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.insp-id h3 { margin: 0; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary); }
.insp-id .muted { font-size: 12.5px; }
.insp-balance { font-family: "Space Grotesk", sans-serif; font-weight: 700; font-size: 30px; letter-spacing: -.02em;
  margin: 6px 0 2px; font-variant-numeric: tabular-nums; min-height: 36px; }
.insp-state { margin: 0; font-size: 13px; color: var(--text-secondary); }
.insp .sp-progress { margin: 8px 0 0; }
.insp-steps { margin: 0; padding: 12px 18px; border-bottom: 1px solid var(--border); gap: 8px 18px; font-size: 13px; }
.insp-actions { display: flex; gap: 8px; flex-wrap: wrap; padding: 14px 18px 0; }
.insp-addr { padding: 10px 18px 0; }
.insp-addr code { display: block; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; color: var(--text-secondary);
  overflow-wrap: anywhere; white-space: normal; }
.insp-next { margin: 14px 18px 0; padding: 12px 14px; border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 10px;
  font-size: 13.5px; line-height: 1.5; color: var(--text-secondary); }
.insp-next p { margin: 0 0 8px; } .insp-next p:last-child { margin-bottom: 0; }
.insp-next b { color: var(--text); }
.insp-next .row-actions { margin: 0; }
.insp-next .chip { vertical-align: baseline; }
.insp-next .fold { margin-top: 10px; }
.insp > .sp-drawer { margin: 14px 18px 0; }
.insp > .notice { margin: 14px 18px 0; }
.insp-secs { margin-top: 16px; border-top: 1px solid var(--border); }
.insp-sec { border-bottom: 1px solid var(--border); padding: 0 18px; }
.insp-sec > summary { cursor: pointer; list-style: none; display: flex; align-items: baseline; gap: 10px; padding: 13px 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-secondary); }
.insp-sec > summary::-webkit-details-marker { display: none; }
.insp-sec > summary::after { content: "+"; margin-left: auto; font-size: 14px; color: var(--text-dim); }
.insp-sec[open] > summary::after { content: "\2212"; }
.insp-sec > summary .muted { text-transform: none; letter-spacing: 0; font-family: inherit; font-size: 12px; }
.insp-sec > summary:hover { color: var(--text); }
.insp-sec > *:not(summary) { margin-bottom: 14px; }
.insp-sec > .muted { margin-top: 0; font-size: 13px; }
.insp #sp-page-line { margin: 0; padding: 12px 18px; font-size: 12.5px; }
.insp .btn .spinner { margin-left: 8px; }
.insp .btn { display: inline-flex; align-items: center; }
.insp .sp-slot { padding: 0 18px 14px; }
.insp .sp-slot:empty { padding: 0; }
@media (max-width: 640px) { .insp-head, .insp-steps, .insp-actions, .insp-addr, .insp-sec, .insp #sp-page-line { padding-left: 14px; padding-right: 14px; }
  .insp-next, .insp > .sp-drawer, .insp > .notice { margin-left: 14px; margin-right: 14px; } }

/* ── The phone: the wallet list is the screen; the inspector slides over it ── */
.insp-bar { display: none; }
@media (max-width: 820px) {
  /* A push from the right, the way a list opens a detail on a phone: the
     pane comes in over the list in 300ms on an ease-out curve and leaves the
     same way. A bottom sheet is for a task inside the page (the funding
     drawer); this is a place, and it has a way back in its top-left. */
  #s-spending.has-wallets .sp-view-pane { position: fixed; inset: 0; z-index: 40; background: var(--bg); overflow: auto;
    overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 0 16px 28px;
    transform: translateX(100%); visibility: hidden; box-shadow: -18px 0 40px rgba(0, 0, 0, .45);
    transition: transform .3s cubic-bezier(.2, .8, .2, 1), visibility 0s linear .3s; }
  #s-spending.has-wallets .sp-view-pane.open { transform: none; visibility: visible;
    transition: transform .3s cubic-bezier(.2, .8, .2, 1); }
  #s-spending.has-wallets .sp-view-pane { touch-action: pan-y; }
  /* The list slides a little to the left and dims under the viewer, and
     follows a swipe back (--swipe is 0 closed-over, 1 fully dragged open). */
  #s-spending.has-wallets .sp-list-pane { transition: transform .3s cubic-bezier(.2, .8, .2, 1), opacity .3s; }
  body.sp-sheet-open #s-spending.has-wallets .sp-list-pane { transform: translateX(calc(-22% * (1 - var(--swipe, 0)))); opacity: calc(.5 + .5 * var(--swipe, 0)); }
  body.sp-sheet-drag #s-spending.has-wallets .sp-list-pane { transition: none; }
  /* Wide tables scroll inside their own box instead of pushing the page. */
  .table, .stat-table { display: block; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  #s-spending.has-wallets .insp-bar { display: flex; align-items: center; gap: 12px; position: sticky; top: 0; z-index: 2;
    margin: 0 -16px 12px; padding: 10px 16px; background: var(--bg); border-bottom: 1px solid var(--border); }
  .insp-back { background: none; border: 0; color: var(--accent); font: 600 15px "Inter", system-ui, sans-serif;
    padding: 6px 10px 6px 0; min-height: 44px; cursor: pointer; }
  .insp-bar-title { font: 600 15px "Space Grotesk", "Inter", system-ui, sans-serif; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #s-spending.has-wallets .sp-view-pane .insp { margin-top: 0; }
  body.sp-sheet-open { overflow: hidden; }
  /* Rows on a phone: the name stays on one line and the state's sub-line
     goes; the row is a button into the sheet, not a report. */
  #s-spending .wtable td.wname b { white-space: nowrap; }
  #s-spending .wtable .pill-sub { display: none; }
  /* The address fits one line at 360px at this size; if a font is wider it
     breaks anywhere rather than leaving one digit alone on a second line. */
  .insp-addr code { font-size: 11.5px; word-break: break-all; }
  /* Chips are real targets on a phone: the drawers' ways, the copy chips. */
  .chips .chip, .sp-code .chip, .copy .chip, .insp-sec .chip { min-height: 38px; padding: 8px 12px; }
}
@media (prefers-reduced-motion: reduce) {
  #s-spending.has-wallets .sp-view-pane, #s-spending.has-wallets .sp-view-pane.open, #s-spending.has-wallets .sp-list-pane { transition: none; }
}

/* ── Keys: three kinds, one tag each, wherever a key appears ─────────────── */
.ktag { display: inline-block; font: 600 10.5px ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .1em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 5px; border: 1px solid var(--border-strong); color: var(--text-secondary); vertical-align: middle; white-space: nowrap; }
.ktag-wallet { color: var(--accent); border-color: var(--accent); background: var(--accent-bg); }
.ktag-branch { color: var(--text); border-color: var(--border-strong); background: var(--surface-2); }
.ktag-account { color: var(--burn); border-color: var(--burn); background: var(--burn-bg); }
.kladder { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0 0 22px; }
.kk { border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px; background: var(--surface); display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.kk code { font: 12.5px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--text-secondary); }
.kk p { margin: 0; font-size: 13.5px; }
.ksec { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 22px 0 10px; font-size: 14px; }
.ksec .muted { font-weight: 400; font-size: 13px; }
.klist { border-top: 1px solid var(--border); }
.klist > p { padding: 12px 0; margin: 0; }
.krow { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; gap: 8px 12px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--border); }
.krow .kwho { display: flex; flex-direction: column; min-width: 0; }
.krow .kwho b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.krow .kwho .muted { font-size: 12.5px; }
.krow .kpre { font: 12px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--text-secondary); }
.krow .kacts { display: flex; gap: 6px; }
.krow .kshown { grid-column: 1 / -1; }
@media (max-width: 820px) {
  .kladder { grid-template-columns: 1fr; }
  .krow { grid-template-columns: auto minmax(0, 1fr); }
  .krow .kpre { grid-column: 2; }
  .krow .kacts { grid-column: 1 / -1; }
}
