/* Vanity: the project preset (roles re-pointed to the owner's Design System.dc.html) and the page layout.
   Components come from kit/components.css and read these roles.
   Rules (research 2026-11-08, see DESIGN.md): one ink element per view (Start); selection is a tone step;
   secondary actions are a tone-step fill; labels uppercase over tabular figures; 8-12 inside a group,
   24 between groups, 32 between sections. */

@font-face { font-family: "Geist"; src: url("/fonts/geist.woff2") format("woff2"); font-weight: 100 900; font-display: swap; }
@font-face { font-family: "Geist Mono"; src: url("/fonts/geist-mono.woff2") format("woff2"); font-weight: 100 900; font-display: swap; }
@font-face { font-family: "Schibsted Grotesk"; src: url("/fonts/schibsted-grotesk.woff2") format("woff2"); font-weight: 400 900; font-display: swap; }

/* ---------------------------------------------------------------- Preset: roles */
:root {
  color-scheme: dark;
  /* 2026-11-09 reskin to the approved Astryx demo landing: tinted near-black steps, one lime accent */
  --ground: #08090b;
  --surface: #171719;
  --raised: #212124;
  --raised-hover: #2a2a2e;
  --raised-active: #333338;
  --overlay: #1c1c1f;
  --panel-line: #2a2a2e; /* the system's 1px panel border: identity, recorded in DESIGN.md */
  --line-row: #232326; /* list rows only */
  --line: #66666c; /* field and control edges, 3:1 on ground and surface */
  --text-strong: #ededed;
  --text-body: #cfcfcf;
  --text-dim: #8f8f94;
  /* One accent, four roles: Start, the matched pattern in the hero address, focus, live state */
  --accent: #c8f169;
  --accent-hover: #d6f78a;
  --accent-ink: #08090b;
  --accent-text: #c8f169;
  --accent-soft: #c8f16914;
  --focus: #c8f169;
  --font-display: "Schibsted Grotesk", "Geist", system-ui, sans-serif;
  --veil: #ffffff0d;
  --scrim: #000000;
  --positive: oklch(0.78 0.15 150);
  --negative: oklch(0.72 0.17 25);
  --warning: oklch(0.8 0.14 80);
  --info: oklch(0.76 0.12 240);
  --radius-control: 0.5rem; /* 8 */
  --radius-panel: 0.875rem; /* 14: the system's panel radius */
  --hit: 2.75rem;
  --control-xl: 2.75rem; /* 44: main fields, segments and the primary action */
  --gutter: var(--s-4);
}

@media (min-width: 640px) {
  :root { --gutter: var(--s-6); }
}

html { scrollbar-gutter: stable; }

body {
  background: var(--ground);
  color: var(--text-body);
  font-size: var(--type-body);
  line-height: var(--leading-body);
}

[hidden] { display: none !important; }

/* Labels: the system's small uppercase caption over a figure (identity, DESIGN.md) */
.label,
.figures dt,
.budget dt,
.job-stats dt,
.field-label {
  color: var(--text-dim);
  font-size: var(--type-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ---------------------------------------------------------------- Shell */
.wrap {
  width: 100%;
  max-width: calc(45rem + 2 * var(--gutter)); /* 720 content */
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.crumb {
  color: var(--text-strong);
  font: 600 var(--type-small) / 1 var(--font-mono);
  letter-spacing: 0.14em;
}

main.wrap {
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
  padding-block: var(--s-5) var(--s-8);
}

.view {
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
  min-height: 24rem;
  animation: view-in var(--duration-quick) var(--ease-out);
}

@keyframes view-in { from { opacity: 0; } }


.intro { display: flex; flex-direction: column; gap: var(--s-2); }

.intro h1 {
  color: var(--text-strong);
  font-family: var(--font-display);
  font-size: 2rem; /* 32 at 390 */
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
  text-wrap: balance;
}

@media (min-width: 640px) {
  .intro h1 { font-size: 2.75rem; } /* 44 */
}

.intro { gap: var(--s-2); }
.intro p { text-wrap: pretty; }

/* The composer sits on the dither field: the approved landing's signature */
.field-wrap {
  position: relative;
  isolation: isolate;
  padding: var(--s-3);
  border-radius: calc(var(--radius-panel) + var(--s-3));
  background: var(--ground);
  overflow: hidden;
}

@media (min-width: 640px) {
  .field-wrap { padding: var(--s-4); border-radius: calc(var(--radius-panel) + var(--s-4)); }
}

.field-art { position: absolute; inset: 0; z-index: 0; pointer-events: none; }

/* Paper Shaders' own canvas rules (its injected <style> is blocked by the CSP) */
:where([data-paper-shader]) { isolation: isolate; }
[data-paper-shader] canvas {
  contain: strict;
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: inherit;
}

.field-wrap > .composer {
  position: relative;
  z-index: 1;
  border-radius: var(--radius-panel);
  background: var(--surface);
}

.intro p { max-width: 60ch; color: var(--text-dim); }

.panel { border: 1px solid var(--panel-line); }

/* ---------------------------------------------------------------- Groups */
.group { display: flex; flex-direction: column; gap: var(--s-3); }
.group-lg { display: flex; flex-direction: column; gap: var(--s-5); }

.pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-3);
}

/* ---------------------------------------------------------------- Composer */
.composer {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  padding: var(--s-4);
}

@media (min-width: 640px) {
  .composer { padding: var(--s-5); }
}

/* The address is the hero: two fixed rows of 22, sized to its own container, never truncated */
.preview {
  container-type: inline-size;
  display: grid;
  justify-items: center;
  gap: var(--s-3);
  padding: var(--s-5) var(--s-4);
  border-radius: var(--radius-control);
  background: var(--ground);
}

.address {
  width: max-content;
  max-width: 100%;
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: min(2rem, calc((100cqi - 1rem) / 14));
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0;
  overflow-wrap: anywhere;
}

.address > .line { display: block; white-space: nowrap; }
.address .pat { color: var(--accent); font-weight: 650; }

/* List addresses: one line, cut in the middle, the match always visible */
.address.is-small {
  width: auto;
  font-size: var(--type-body);
  line-height: var(--leading-tight);
  white-space: nowrap;
}

.field { gap: var(--s-2); }

.field-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2);
}

.chars-left {
  color: var(--text-dim);
  font-size: var(--type-label);
  font-variant-numeric: tabular-nums;
}

.composer .input,
.dialog .input {
  height: var(--control-xl);
  background: var(--ground);
}

.composer .input { font-family: var(--font-mono); }

/* Hint and error share one slot that reserves two lines, so nothing below moves */
.composer .field-hint,
.composer .field-error {
  min-height: calc(2 * var(--type-label) * var(--leading-tight));
  align-items: flex-start;
}

@media (min-width: 640px) {
  .composer .field-hint,
  .composer .field-error { min-height: calc(var(--type-label) * var(--leading-tight)); }
}

.field-error { color: var(--text-body); }
.field-error .dot,
.field-note .dot { margin-top: 0.3rem; color: var(--negative); }

.field-note {
  display: flex;
  align-items: flex-start;
  gap: var(--s-2);
  min-height: calc(var(--type-label) * var(--leading-tight));
  color: var(--text-body);
  font-size: var(--type-small);
}

/* Segmented controls: equal segments in a well; the selected one is a tone step with ink text */
.seg.is-fill {
  display: flex;
  width: 100%;
  height: var(--control-xl);
  padding: 3px;
  gap: 2px;
  background: var(--ground);
  box-shadow: inset 0 0 0 1px var(--panel-line);
}

.seg.is-fill > button {
  flex: 1 1 0;
  min-width: 0;
  gap: var(--s-1);
  font-size: var(--type-body);
}

.seg > [aria-checked="true"],
.seg > [aria-selected="true"] {
  --ink: var(--text-strong);
  background: var(--raised-active);
  font-weight: 600;
}

/* Estimate: label over figure in one joined strip; before a pattern exists, one line instead */
.estimate-empty {
  padding: var(--s-4);
  border-radius: var(--radius-control);
  background: var(--ground);
  color: var(--text-dim);
}

.figures {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  overflow: hidden;
  border-radius: var(--radius-control);
  background: var(--panel-line);
}

@media (min-width: 560px) {
  .figures { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.figures > div {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s-1);
  min-width: 0;
  padding: var(--s-3);
  background: var(--ground);
}

.figures dd,
.budget dd,
.job-stats dd {
  color: var(--text-strong);
  font-family: var(--font-mono);
  font-size: var(--type-reading);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-tight);
  overflow-wrap: anywhere;
  border-radius: 0.25rem;
  transition: background-color var(--duration-base) var(--ease-out);
}

.flash { background: var(--raised-active); }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); }

.btn-xl {
  --btn-h: var(--control-xl);
  padding: 0 var(--s-5);
  font-size: var(--type-body);
}

/* The one ink element: a 1px inset highlight and one sheen on hover (finish, not glow) */
.btn-primary { overflow: hidden; }
.btn-primary:not(:disabled) { box-shadow: inset 0 1px 0 #ffffff66; }

.btn-primary:not(:is(.is-loading, [aria-busy="true"]))::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 30%, #ffffff99 50%, transparent 70%);
  transform: translateX(-120%);
  pointer-events: none;
}

@media (hover: hover) {
  .btn-primary:not(:disabled):hover::after {
    transform: translateX(120%);
    transition: transform var(--duration-long) var(--ease-out);
  }
}

.action-note { color: var(--text-dim); font-size: var(--type-small); }

@media (max-width: 479px) {
  .actions > .btn { width: 100%; }
}

.reason {
  display: flex;
  align-items: flex-start;
  gap: var(--s-2);
  color: var(--text-body);
  font-size: var(--type-small);
  overflow-wrap: anywhere;
}

.reason .dot { margin-top: 0.3rem; color: var(--tone, var(--warning)); }

/* Live card: the job you just started, under the composer */
.live-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4) var(--s-4);
  border-radius: var(--radius-control);
  background: var(--ground);
}

.live-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.live-card .job { padding: var(--s-2) 0 0; }

/* ---------------------------------------------------------------- Jobs */
.signed-out {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-6) var(--s-4);
  color: var(--text-dim);
  text-align: center;
}

.budget {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-4) var(--s-3);
  padding: var(--s-4);
}

.budget .is-key { grid-column: 1 / -1; }

@media (min-width: 560px) {
  .budget { grid-template-columns: 1.4fr repeat(3, minmax(0, 1fr)); padding: var(--s-5); }
  .budget .is-key { grid-column: auto; }
}

.budget > div { display: flex; flex-direction: column; justify-content: flex-end; gap: var(--s-1); min-width: 0; }

.budget .is-key dd,
.job-stats .is-key dd {
  font-size: var(--type-title);
  line-height: 1;
  letter-spacing: -0.01em;
}

.job-list { display: flex; flex-direction: column; padding: 0; margin: 0; list-style: none; }

.job { display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-4); }
.job + .job { border-top: 1px solid var(--line-row); }

@media (min-width: 640px) {
  .job { padding: var(--s-4) var(--s-5); }
}

.job-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-2) var(--s-3);
}

.job-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-1) var(--s-2); min-width: 0; }

.job-pattern {
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: var(--type-reading);
  overflow-wrap: anywhere;
}

.job-pattern .pat { color: var(--text-strong); font-weight: 650; }

.job-meta { color: var(--text-dim); font-size: var(--type-small); font-variant-numeric: tabular-nums; white-space: nowrap; }

.chip { align-self: center; }

.job .live { font-size: var(--type-small); }
.live > .dot { color: var(--tone, var(--positive)); }

.job-stats {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, minmax(0, 1fr));
  gap: var(--s-3);
  align-items: start;
}

@media (max-width: 479px) {
  .job-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .job-stats .is-key { grid-column: 1 / -1; }
}

.job-stats > div { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }
.job-stats dd { font-size: var(--type-body); }

.unlucky { color: var(--text-dim); font-size: var(--type-small); }

.progress { --tone: var(--text-strong); }
.progress > i { transition: width var(--duration-base) var(--ease-out); }
.progress.is-booting > i { width: 30%; animation: booting 1.2s var(--ease-in-out) infinite alternate; }

@keyframes booting {
  from { transform: translateX(-30%); }
  to { transform: translateX(260%); }
}

.job-error {
  display: flex;
  align-items: flex-start;
  gap: var(--s-2);
  color: var(--text-body);
  font-size: var(--type-small);
  overflow-wrap: anywhere;
}

.job-error .dot { margin-top: 0.3rem; color: var(--negative); }

/* Results: one line per address with its actions, one save line, keys under their address */
.results summary {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  width: fit-content;
  min-height: var(--control-md);
  color: var(--text-body);
  font-size: var(--type-small);
  cursor: pointer;
  list-style: none;
}

.results summary::-webkit-details-marker { display: none; }

.results summary::before {
  content: "";
  width: 0.375rem;
  height: 0.375rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--duration-fast) var(--ease-out);
}

.results[open] summary::before { transform: rotate(45deg); }
.results summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 0.25rem; }
.results-body { display: flex; flex-direction: column; gap: var(--s-3); padding-top: var(--s-2); }

/* Key row: the address (and a dim meta line) on the left, one joined action group on the right.
   Same row in a job's results and on the Addresses tab. */
.key-list { display: flex; flex-direction: column; padding: 0; margin: 0; list-style: none; }

.key-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-2) var(--s-4);
  min-width: 0;
}

.key-list > .key-row + .key-row { padding-top: var(--s-3); margin-top: var(--s-3); border-top: 1px solid var(--line-row); }

.key-main { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }
.key-meta { color: var(--text-dim); font-size: var(--type-small); }

/* The group is a well like the segmented controls: 1px line, small inset, buttons step up a tone on hover */
.key-actions {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--line-row);
  border-radius: var(--radius-control);
  background: var(--ground);
}

.key-btn {
  display: inline-grid;
  place-items: center;
  height: var(--control-md);
  padding: 0 var(--s-3);
  border: 0;
  border-radius: calc(var(--radius-control) - 2px);
  background: transparent;
  color: var(--text-body);
  font: inherit;
  font-size: var(--type-small);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}

.key-btn > span { grid-area: 1 / 1; transition: opacity var(--duration-fast) var(--ease-out); }
.key-btn > .done,
.key-btn > .armed { opacity: 0; }
.key-btn[data-copied] > .idle,
.key-btn[data-armed] > .idle { opacity: 0; }
.key-btn[data-copied] > .done,
.key-btn[data-armed] > .armed { opacity: 1; }
.key-btn[data-copied] { color: var(--text-strong); }

@media (hover: hover) {
  .key-btn:hover { background: var(--raised); color: var(--text-strong); }
  .key-btn.is-danger:hover { color: var(--negative); }
}

.key-btn:active { background: var(--raised-active); }
.key-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.key-btn:disabled { color: var(--text-dim); cursor: default; }
.key-btn[aria-busy="true"] { cursor: progress; color: var(--text-dim); }
.key-btn.is-danger { color: var(--text-dim); }
.key-btn.is-danger[data-armed] { background: color-mix(in oklab, var(--negative) 16%, transparent); color: var(--negative); }

/* Addresses tab rows sit in the panel's own padding */
#addr-history > .key-row { padding: var(--s-3) var(--s-4); }
#addr-history > .key-row + .key-row { border-top: 1px solid var(--line-row); }

@media (min-width: 640px) {
  #addr-history > .key-row { padding: var(--s-3) var(--s-5); }
}

/* Phones: the group drops under the address and spreads full width, with touch-sized targets */
@media (max-width: 639px) {
  .key-row { grid-template-columns: minmax(0, 1fr); }
  .key-actions { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; }
}

@media (pointer: coarse) {
  .key-btn { height: 2.75rem; }
}

.job-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }

.more { align-self: center; }

.empty-line { padding: var(--s-6) var(--s-4); color: var(--text-dim); text-align: center; }

/* Copy word: reserves the wider of its two labels, confirms in a word */
.copy-word { display: inline-grid; }
.copy-word > span { grid-area: 1 / 1; transition: opacity var(--duration-fast) var(--ease-out); }
.copy-word > .done { opacity: 0; }
.copy-word[data-copied] > .idle { opacity: 0; }
.copy-word[data-copied] > .done { opacity: 1; }

/* ---------------------------------------------------------------- Sign-in dialog */
.dialog { border: 1px solid var(--panel-line); }
body:has(dialog[open]) { overflow: hidden; }
.dialog-body { display: flex; flex-direction: column; gap: var(--s-4); }
.dialog-body > p { color: var(--text-dim); }

/* Wallet sign-in: one row per wallet the browser has, with the wallet's own icon. */
.wallet-signin { display: flex; flex-direction: column; gap: var(--s-3); }
.wallet-signin > p { color: var(--text-dim); }
.wallet-list { display: flex; flex-direction: column; gap: var(--s-2); margin: 0; padding: 0; list-style: none; }
.wallet-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  min-height: 3.5rem;
  padding: var(--s-2) var(--s-4) var(--s-2) var(--s-2);
  border: 0;
  border-radius: 0.75rem;
  background: var(--raised);
  box-shadow: inset 0 0 0 1px var(--panel-line);
  color: var(--text-strong);
  font: inherit;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
}
.wallet-row:hover { background: var(--raised-hover); }
.wallet-row:active { background: var(--raised-active); }
.wallet-row:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.wallet-row[aria-busy="true"] { box-shadow: inset 0 0 0 1px var(--accent); cursor: progress; }
.wallet-row:disabled:not([aria-busy="true"]) { opacity: 0.5; cursor: not-allowed; }
.wallet-icon {
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  padding: var(--s-1);
  border-radius: 0.5rem;
  background: var(--ground);
  object-fit: contain;
}
.wallet-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wallet-tag { flex: none; color: var(--text-dim); font-size: var(--type-small); font-weight: 500; }
.wallet-row[aria-busy="true"] .wallet-tag { color: var(--accent-text); }
.wallet-none { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-4); border-radius: 0.75rem; background: var(--ground); box-shadow: inset 0 0 0 1px var(--panel-line); }
.wallet-none > p { color: var(--text-dim); }
.wallet-get { display: flex; flex-wrap: wrap; gap: var(--s-4); }
.wallet-get a { color: var(--text-strong); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--panel-line); }
.wallet-get a:hover { text-decoration-color: currentColor; }
.password-toggle { align-self: center; color: var(--text-dim); }
.password-toggle:hover { color: var(--text-strong); }
.password-part { display: flex; flex-direction: column; gap: var(--s-4); }
.password-part[hidden] { display: none; }

/* How many: a plain number field; empty means 1. */
.count-input { font-variant-numeric: tabular-nums; }

/* Add SOL credit */
.credit-row { margin-top: calc(var(--s-2) * -1); }
/* The dialog follows shadcn's Dialog: header (title, one muted line, close), fields, one full-width action.
   Fields are input groups: a box holding the input and its suffix or button. */
.credit-dialog:focus { outline: none; }
.credit-dialog .dialog-head {
  align-items: flex-start;
  min-height: 0;
  padding: var(--s-5) var(--s-3) var(--s-5) var(--s-5);
}
.credit-dialog .dialog-body { padding: 0 var(--s-5) var(--s-5); }
.credit-dialog .dialog-foot { padding: 0 var(--s-5) var(--s-5); gap: var(--s-3); }
.dialog-heading { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; }
.dialog-desc { color: var(--text-dim); font-size: var(--type-body); line-height: var(--leading-tight); }
.credit-dialog .dialog-head .btn-icon { --btn-h: var(--control-lg); flex: none; margin-top: calc(var(--s-2) * -1); }
.credit-dialog .dialog-body { gap: var(--s-5); }
.credit-dialog .field { gap: var(--s-2); }
.credit-dialog .field-hint { min-height: 0; }

.credit-dialog .input-group {
  height: var(--control-xl);
  padding: 0 var(--s-1) 0 var(--s-4);
  border-radius: var(--radius-control);
  background: var(--ground);
}
.credit-dialog .input-group:focus-within {
  border-color: var(--accent);
  outline: none;
  box-shadow: inset 0 0 0 1px var(--accent);
}
.credit-dialog .field[data-invalid] .input-group { border-color: var(--negative); }
.credit-dialog .input-group > input {
  font-family: var(--font-mono);
  font-size: var(--type-reading);
  font-variant-numeric: tabular-nums;
  caret-color: var(--accent);
}
.credit-dialog .credit-input { padding-right: var(--s-4); }
.credit-dialog .input-unit { padding-right: 0; font-family: var(--font-mono); font-size: var(--type-body); }

.credit-presets { display: flex; gap: var(--s-2); }
.credit-presets .chip-toggle {
  flex: 1 1 0;
  justify-content: center;
  height: var(--control-lg);
  font-family: var(--font-mono);
  font-size: var(--type-body);
}
.credit-presets .chip-toggle:focus-visible { outline-offset: 2px; }

.treasury {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: var(--type-body);
  color: var(--text-strong);
  white-space: nowrap;
}
.credit-address { color: var(--text-strong); }
.credit-address .btn-icon { --btn-h: var(--control-lg); flex: none; }

.credit-terms { color: var(--text-dim); font-size: var(--type-small); line-height: var(--leading-body); }
.credit-foot { flex-direction: column; align-items: stretch; }
.credit-foot .btn { width: 100%; }
.credit-foot:not(:has(> :not([hidden]))) { display: none; }

/* Copy as an icon: the glyph swaps for a check */
.copy-icon { display: inline-grid; place-items: center; }
.copy-icon > svg { grid-area: 1 / 1; transition: opacity var(--duration-fast) var(--ease-out); }
.copy-icon > svg + svg { opacity: 0; color: var(--text-strong); }
.copy-icon[data-copied] > svg:first-child { opacity: 0; }
.copy-icon[data-copied] > svg + svg { opacity: 1; }

@media (max-width: 639px) {
  .credit-dialog .dialog-head .btn-icon,
  .credit-address .btn-icon { --btn-h: var(--hit); }
  .credit-presets .chip-toggle { height: var(--hit); }
  .credit-dialog .dialog-head { padding: var(--s-4) var(--s-2) var(--s-4) var(--s-4); }
  .credit-dialog .dialog-body { padding: 0 var(--s-4) var(--s-4); }
  .credit-dialog .dialog-foot { padding: 0 var(--s-4) var(--s-4); }
  .credit-dialog .dialog-head .btn-icon { margin-top: 0; }
}

/* ---------------------------------------------------------------- States */
@media (hover: none) {
  .btn:hover { background: var(--btn-bg); }
  .seg > button:hover { --ink: var(--text-dim); }
  .seg > [aria-checked="true"]:hover,
  .seg > [aria-selected="true"]:hover { --ink: var(--text-strong); }
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .view { animation: none; }
  .progress.is-booting > i { animation: none; transform: none; width: 100%; opacity: 0.4; }
  .btn-primary::after { display: none; }
}


@media (max-width: 379px) {
  .chars-left { display: none; }
}

/* ---------------------------------------------------------------- App shell: the page never scrolls.
   Top bar and view switch stay put; the Grind view scrolls on its own when a phone is too short,
   and the Jobs and Addresses lists scroll inside their panels. */
html, body { height: 100%; }

body {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  overflow: hidden;
}

.topbar { flex: none; }

main.wrap {
  flex: 1 1 auto;
  min-height: 0;
  padding-bottom: var(--s-4);
}


.view {
  flex: 1 1 auto;
  min-height: 0;
}

.view.is-scroll {
  overflow-y: auto;
  scrollbar-gutter: stable;
  overscroll-behavior: contain;
  padding-bottom: var(--s-4);
}

.fill {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.scroll-panel {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  scrollbar-gutter: stable;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--raised-active) transparent;
}

.view.is-scroll { scrollbar-width: thin; scrollbar-color: var(--raised-active) transparent; }

.has-more {
  mask-image: linear-gradient(to bottom, #000 calc(100% - 2.5rem), transparent);
}

/* The Grind view reserves no scrollbar gutter, so its panel edges line up with the view switch */
.view.is-scroll { scrollbar-gutter: auto; }


/* ---------------------------------------------------------------- Calm job rows (2026-11-08: "better on the eyes")
   One bright thing per row at most: the matched part of the address. Words over mono bold, no inner wells,
   quiet text buttons, status and meta dim. */
.job { gap: var(--s-2); }
.job-top { align-items: baseline; }
.job-title { align-items: baseline; gap: var(--s-1) var(--s-3); }

.job-words { color: var(--text-dim); font-size: var(--type-body); }
.job-pat { color: var(--text-body); font-family: var(--font-mono); font-weight: 500; }
.job-meta { color: var(--text-dim); }

.job .live { color: var(--text-dim); font-size: var(--type-small); }
.job .live > .dot { width: 0.375rem; height: 0.375rem; }

.address.is-small { color: var(--text-dim); font-size: 0.9375rem; }
.address.is-small .pat { color: var(--text-strong); font-weight: 500; }

.job-actions .btn {
  --ink: var(--text-dim);
}

@media (hover: hover) {
  .job-actions .btn:hover { --ink: var(--text-strong); }
}

.job-actions { gap: var(--s-1) var(--s-3); }
.job-actions .btn { padding-inline: 0; height: 1.75rem; }
.job-actions .copy-word > span { justify-self: start; }
.job-actions .btn:hover { background: none; text-decoration: underline; text-underline-offset: 3px; }
.results-body { gap: var(--s-2); padding-top: var(--s-1); }

/* List panels hug their content and only scroll once they reach the bottom of the view */
.scroll-panel { flex: 0 1 auto; }

.job-pat,
.address.is-small .pat { font-weight: 450; }
.scroll-panel { scrollbar-gutter: auto; }

/* ---------------------------------------------------------------- Polish 2026-11-09 ("more professional and legit")
   One name (vanity wordmark), tabs in the header as product chrome, a short lede, a sourced trust strip,
   sentence-case field labels, and a flat Start button with no sheen. */

.wordmark {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--hit);
  color: var(--text-strong);
  font-family: var(--font-display);
  font-size: var(--type-head);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  text-decoration: none;
}
.wordmark-mark { display: block; width: 1.25rem; height: 1.25rem; flex: none; }

.wordmark:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 0.25rem; }

/* ---------------------------------------------------------------- Header (2026-11-09, owner: "completely rethink and
   elevate our navbar"). An instrument header, not a floating card: full width, one hairline, contents on the 720
   column so the mark lines up with the page title. Tabs are text; the active one is marked by a 2px lime rule
   that rides the hairline and slides between tabs. The right side is grouped by job: Docs, then the credit
   figure (click to top up), then the account. Phones: the tabs become a bottom tab bar whose rule rides its top. */
.topbar {
  position: relative;
  z-index: 20;
  flex: none;
  height: auto; /* the kit's .topbar pins 48px; this bar is 56 */
  padding: 0;
  border-bottom: 1px solid var(--line-row);
  background: var(--ground);
}

.topbar .wrap {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  height: 3.5rem;
}

.views { display: flex; flex: 1 1 auto; align-self: stretch; min-width: 0; }

.nav-tabs { position: relative; display: flex; align-items: stretch; gap: var(--s-1); }

.nav-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  padding: 0 var(--s-2);
  border: 0;
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: var(--type-body);
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}
.nav-tab[aria-selected="true"],
.nav-tab[aria-current="page"] { color: var(--text-strong); }
.nav-tab:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; border-radius: var(--radius-control); }
@media (hover: hover) and (pointer: fine) {
  .nav-tab:hover { color: var(--text-strong); }
}

.nav-icon { display: none; width: 1.25rem; height: 1.25rem; flex: none; }
.nav-docs-tab { display: none; }

/* Owner 2026-11-09: no numbers beside Jobs and Addresses; the live dot alone says a job is running. */
.tab-count { display: none; }
.nav-tab .dot { color: var(--accent); }

/* The shared active marker: placed by app.js (--ind-x, --ind-w), it sits on the header's hairline. */
.nav-ind {
  position: absolute;
  bottom: -1px;
  left: 0;
  width: var(--ind-w, 0px);
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--accent);
  transform: translateX(var(--ind-x, 0px));
  pointer-events: none;
}
.nav-tabs.ind-ready .nav-ind {
  transition: transform var(--duration-base) var(--ease-out), width var(--duration-base) var(--ease-out);
}

.account-nav {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--s-3);
  margin-left: auto;
}

/* Docs and X are resources, not account controls: quiet links, set off from the account by one short rule. */
.nav-links {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-1);
  padding-right: var(--s-2);
}
.nav-links::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 0;
  width: 1px;
  height: var(--s-4);
  background: var(--line-row);
  transform: translateY(-50%);
}
.nav-x { justify-content: center; min-width: var(--hit); }
/* On /docs the Docs link is the current page: strong, with the same lime rule on the header's hairline. */
.nav-link[aria-current="page"] { position: relative; color: var(--text-strong); }
.nav-link[aria-current="page"]::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: calc((var(--hit) - 3.5rem) / 2 - 1px);
  left: 0;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--accent);
}
.nav-x > svg { width: 0.875rem; height: 0.875rem; }
.nav-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--hit);
  color: var(--text-dim);
  font-size: var(--type-body);
  font-weight: 500;
  line-height: 1.25rem;
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out);
}
.nav-link:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--radius-control); }
@media (hover: hover) and (pointer: fine) {
  .nav-link:hover { color: var(--text-strong); }
}

/* Credit: the figure a paying visitor watches, shown as a figure; one click opens Add SOL. */
.credit-chip,
.account-trigger,
.nav-signin {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  height: 2rem;
  border: 0;
  border-radius: var(--radius-control);
  font: inherit;
  font-size: var(--type-body);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.credit-chip,
.account-trigger,
.nav-signin { text-decoration: none; }
.credit-chip[hidden],
.account-trigger[hidden],
.nav-signin[hidden] { display: none; }

.credit-chip {
  padding: 0 var(--s-2) 0 var(--s-3);
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--panel-line);
  color: var(--text-strong);
}
.credit-chip-label { display: none; }
.credit-chip-value { font-weight: 600; font-variant-numeric: tabular-nums; }
.credit-chip-plus { width: 0.875rem; height: 0.875rem; color: var(--text-dim); transition: color var(--duration-fast) var(--ease-out); }
.credit-chip.is-empty .credit-chip-value { color: var(--text-dim); font-weight: 500; }

.account { position: relative; }

.account-trigger {
  max-width: 100%;
  padding: 0 var(--s-2);
  background: transparent;
  color: var(--text-body);
}

@media (hover: hover) and (pointer: fine) {
  .credit-chip:hover,
  .account-trigger:hover { background: var(--raised); }
  .credit-chip:hover .credit-chip-plus { color: var(--text-strong); }
}
.account-trigger[aria-expanded="true"] { background: var(--raised); color: var(--text-strong); }
.credit-chip:active,
.account-trigger:active { background: var(--raised-hover); }
.credit-chip:focus-visible,
.account-trigger:focus-visible,
.nav-signin:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

.account-avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  overflow: hidden;
  border-radius: var(--radius-pill);
  background: var(--raised-active);
  color: var(--text-body);
  font-size: var(--type-label);
  font-weight: 600;
  line-height: 1;
}
.account-avatar > img { width: 100%; height: 100%; object-fit: cover; }
.account-avatar > svg { width: 0.75rem; height: 0.75rem; }

.account-id { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.account-id.is-mono { font-family: var(--font-mono); font-size: var(--type-small); font-weight: 400; }
.account-credit { display: none; }

.account-caret { flex: none; width: 0.875rem; height: 0.875rem; color: var(--text-dim); transition: transform var(--duration-fast) var(--ease-out); }
.account-trigger[aria-expanded="true"] .account-caret { transform: rotate(180deg); }

/* Signed out, Sign in is the header's one solid control: the strong text tone, so Start keeps the lime. */
.nav-signin {
  padding: 0 var(--s-3);
  background: var(--text-strong);
  color: var(--ground);
  font-weight: 600;
}
@media (hover: hover) and (pointer: fine) {
  .nav-signin:hover { background: var(--text-body); }
}
.nav-signin:active { transform: scale(0.98); }

@media (prefers-reduced-motion: reduce) {
  .nav-tabs.ind-ready .nav-ind,
  .account-caret { transition: none; }
  .nav-signin:active { transform: none; }
}

/* Phones: a top row with the mark, credit and account; the views move to a bottom tab bar (icon over label,
   44px+ targets, safe-area aware) whose lime rule rides the bar's top edge. */
@media (max-width: 639px) {
  .topbar .wrap { gap: var(--s-3); }
  .account-nav { gap: var(--s-2); }
  /* Docs moves to the tab bar; X stays as an icon in the top row. */
  .nav-links { padding-right: 0; }
  .nav-links::after { display: none; }
  .nav-links .nav-link:not(.nav-x) { display: none; }

  .views {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 30;
    height: calc(3.5rem + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    border-top: 1px solid var(--line-row);
    background: var(--ground);
  }
  .nav-tabs { flex: 3 1 0; gap: 0; }
  .nav-tab {
    flex: 1 1 0;
    flex-direction: column;
    justify-content: center;
    gap: var(--s-1);
    min-height: var(--hit);
    padding: 0;
    font-size: var(--type-label);
  }
  .nav-docs-tab { display: inline-flex; }
  .nav-icon { display: block; }
  .tab-count { display: none; }
  .nav-tab .dot { position: absolute; top: var(--s-2); left: calc(50% + var(--s-2)); margin: 0; }
  .nav-ind { top: -1px; bottom: auto; border-radius: 0 0 2px 2px; }

  main.wrap { padding-bottom: calc(3.5rem + env(safe-area-inset-bottom, 0px) + var(--s-4)); }
  .credit-chip, .account-trigger, .nav-signin { height: var(--hit); }
  .account-popover .menu-item { height: var(--hit); }
}

/* The top row holds mark, X, credit and account on a phone: the account shows its icon, the address lives in its menu. */
@media (max-width: 479px) {
  .account-id { display: none; }
}

.account-popover {
  position: absolute;
  top: calc(100% + var(--s-2));
  right: 0;
  z-index: 50;
  min-width: 13rem;
  transform-origin: top right;
  box-shadow: inset 0 0 0 1px var(--panel-line);
  animation: pop-in var(--duration-quick) var(--ease-out);
}
.account-popover .menu-item { height: 2.5rem; padding: 0 var(--s-3); }
.account-popover .menu-item[hidden] { display: none; }
.account-popover .menu-sep { margin-inline: 0; background: var(--panel-line); }
.account-popover .menu-sep[hidden] { display: none; }
.account-popover .menu-item:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.account-popover .swap { display: inline-grid; }
.account-popover .swap > span { grid-area: 1 / 1; transition: opacity var(--duration-fast) var(--ease-out); }
.account-popover .swap > .done { opacity: 0; }
.account-popover [data-copied] .swap > .idle { opacity: 0; }
.account-popover [data-copied] .swap > .done { opacity: 1; }


main.wrap { padding-top: var(--s-6); }

/* Lede: one sentence at reading size */
.intro p { font-size: 1.125rem; line-height: 1.5; color: var(--text-body); }

/* Field labels in sentence case; figure captions keep the system's uppercase */
.field-label {
  color: var(--text-body);
  font-size: var(--type-small);
  letter-spacing: 0;
  text-transform: none;
}

/* Start: a flat lime fill, no sheen, no highlight */
.btn-primary:not(:disabled) { box-shadow: none; }
.btn-primary::after { content: none; }

/* ---------------------------------------------------------------- Controls (owner 2026-11-09: "these inputs and toggles look tacky")
   Cause: every control was a stock outlined box of equal weight, the chosen segment was just another grey,
   and focus drew a double ring, so the panel read as an admin form.
   Segments: Osmo "Toggle Switch" pattern (osmo-vault toggle-switch), ported to CSS: one thumb slides under
   the chosen option, positioned from the aria state app.js already sets. Inputs: taller mono fields with a
   lime caret and a single crisp focus edge. */

.seg.is-fill {
  --n: 2;
  --i: 0;
  --inset: 3px;
  position: relative;
  isolation: isolate;
  height: 3rem;
  padding: var(--inset);
  gap: 0;
  border-radius: 0.75rem;
  box-shadow: inset 0 0 0 1px var(--panel-line);
}

#count,
#views { --n: 3; }

.seg.is-fill:has(> :nth-child(2):is([aria-checked="true"], [aria-selected="true"])) { --i: 1; }
.seg.is-fill:has(> :nth-child(3):is([aria-checked="true"], [aria-selected="true"])) { --i: 2; }

.seg.is-fill::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: var(--inset);
  bottom: var(--inset);
  left: var(--inset);
  width: calc((100% - 2 * var(--inset)) / var(--n));
  border-radius: calc(0.75rem - var(--inset));
  background: var(--raised-active);
  box-shadow: inset 0 1px 0 #ffffff14;
  transform: translateX(calc(var(--i) * 100%));
  transition: transform 450ms cubic-bezier(0.625, 0.05, 0, 1);
}

.seg.is-fill > button,
.seg.is-fill > [aria-checked="true"],
.seg.is-fill > [aria-selected="true"] {
  background: transparent;
  border-radius: calc(0.75rem - var(--inset));
  transition: color 180ms var(--ease-out);
}

.seg.is-fill > button:active { transform: none; }

/* Inputs: one height with the segments, mono text, lime caret, a single 2px lime edge on focus */
.composer .input {
  height: 3rem;
  padding: 0 var(--s-4);
  border-radius: 0.75rem;
  font-size: var(--type-reading);
  caret-color: var(--accent);
}

.composer .input:focus-visible {
  border-color: var(--accent);
  outline: none;
  box-shadow: inset 0 0 0 1px var(--accent);
}

.composer .input::placeholder { color: var(--text-dim); }

/* Estimate and preview wells: same radius as the controls */
.preview,
.estimate-empty,
.figures { border-radius: 0.75rem; }

@media (prefers-reduced-motion: reduce) {
  .seg.is-fill::before { transition: none; }
}

/* (Header tabs: see the Nav block above; the bar's items are plain pills, not a sliding well) */

/* ---------------------------------------------------------------- Running job (owner 2026-11-09: "expands really aggressivly",
   "the cancle button looks really bad", the blue Grinding marker and the amber square on the warning line)
   Cause: the Jobs-tab row was dropped into the composer whole (36px figure, uppercase stats, a padding-less grey
   pill for Cancel, the kit's square markers in off-palette blue and amber) and it appeared with no transition. */

/* Live state is the accent (one of its four roles); markers are small round dots everywhere */
:root { --info: var(--accent); }

.dot {
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 999px;
}

.dot.is-live::after { animation-duration: 1.6s; }

.reason .dot,
.job-error .dot,
.field-error .dot,
.field-note .dot { margin-top: 0.45rem; }

/* The live card eases open instead of popping in */
.live-card {
  gap: var(--s-3);
  padding: var(--s-4);
  border-radius: 0.75rem;
  overflow: clip;
  interpolate-size: allow-keywords;
  transition: height 250ms var(--ease-out), opacity 250ms var(--ease-out);
}

@starting-style {
  .live-card { height: 0; opacity: 0; }
}

.live-card-head .label {
  font-size: var(--type-small);
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-body);
}

.live-card .job { padding: 0; gap: var(--s-3); }

/* Compact stats in the live card: the chance figure leads at figure size, the rest sit beside it */
/* Two tidy rows at every width: the chance figure on its own row, then Checked | Speed | Elapsed in three
   equal columns. Labels share one baseline, figures never wrap mid-value; "of ~21 min" sits dim underneath. */
.live-card .job-stats {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-4) var(--s-3);
  align-items: start;
}

.live-card .job-stats .is-key { grid-column: 1 / -1; }
.live-card .job-stats dt { font-size: var(--type-label); white-space: nowrap; }
.live-card .job-stats .is-key dd { font-size: var(--type-figure); }
.live-card .job-stats dd { white-space: nowrap; overflow-wrap: normal; min-height: 1.25rem; }

.job-stats dd .val,
.job-stats dd .of { display: block; }

.job-stats dd .of {
  margin-top: var(--s-1);
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: var(--type-small);
  font-weight: 400;
}

.live-card .job-top { align-items: center; }
.live-card .progress { margin-top: var(--s-1); }

/* Progress: a thin lime rule */
.progress { --tone: var(--accent); height: 3px; }

/* Cancel: a real small secondary button, not a squeezed pill */
.job-actions > .btn-secondary {
  height: 2rem;
  padding: 0 var(--s-3);
  border-radius: 0.5rem;
  background: var(--raised);
  color: var(--text-body);
  text-decoration: none;
}

@media (hover: hover) {
  .job-actions > .btn-secondary:hover {
    background: var(--raised-hover);
    color: var(--text-strong);
    text-decoration: none;
  }
}

@media (pointer: coarse) {
  .job-actions > .btn-secondary { height: 2.75rem; }
}

@media (prefers-reduced-motion: reduce) {
  .live-card { transition: none; }
}

/* The Grind view scrolls on short screens; its blocks keep their natural height and no scrollbar shows
   (owner, 2026-11-09: "remove the side bar") */
#view-grind > * { flex: none; }
html { scrollbar-gutter: auto; }
.view.is-scroll { scrollbar-width: none; }
.view.is-scroll::-webkit-scrollbar { display: none; }

/* Empty and signed-out states read at body size */
.signed-out p,
.empty-line { font-size: var(--type-reading); }
