/* ==========================================================================
   BOTSOL — shared visual system
   Frontend spec §5. One design language across all three surfaces.

   This file is COPIED into each repo's public/ folder, not shared at runtime —
   the three services deploy independently and must have no shared dependency.
   If you change it here, copy it to the others deliberately.

   Character (§5): flat, technical, high-contrast, engineered. Visible
   structure — rules and borders over shadows. No gradients, no glassmorphism,
   no rounded-blob decoration.

   FE-1: zero external requests. No @import, no CDN, no remote fonts, no
   remote images. Everything ships in the repo.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   Light is the storefront ground. Dark is the dashboard and relay viewer —
   the SAME tokens inverted, applied via [data-theme="dark"].
   -------------------------------------------------------------------------- */

:root {
  /* Ink and ground — near-black on off-white, per §5. */
  --bg:            oklch(98.5% 0.002 285);
  --surface:       oklch(100% 0 0);
  --surface-sunk:  oklch(96.5% 0.003 285);
  --border:        oklch(90% 0.005 285);
  --border-strong: oklch(78% 0.008 285);
  --text:          oklch(21% 0.012 285);
  --text-muted:    oklch(50% 0.012 285);

  /* ONE brand accent — a violet, Solana-adjacent.
     §5: green and red are reserved EXCLUSIVELY for profit/loss and
     success/failure semantics. The brand accent must never be green or red,
     and semantic colours must never be used decoratively. */
  --accent:        oklch(52% 0.21 292);
  --accent-hover:  oklch(45% 0.21 292);
  --accent-weak:   oklch(96% 0.03 292);
  --on-accent:     oklch(100% 0 0);

  /* Semantic only. Never decorative. */
  --success:       oklch(52% 0.14 155);
  --success-weak:  oklch(96% 0.04 155);
  --warn:          oklch(58% 0.14 70);
  --warn-weak:     oklch(96% 0.05 70);
  --danger:        oklch(52% 0.20 27);
  --danger-weak:   oklch(96% 0.04 27);

  /* Type.
     The frontend spec §5 suggests self-hosted Archivo; the earlier dashboard
     document §4.2 mandates a system stack. Raised with the operator, who chose
     the SYSTEM STACK (2026-07-20): zero bytes against the R8 60KB budget, zero
     external requests (FE-1), native rendering on every target platform.
     Swapping in a self-hosted face later is a change to these two variables
     plus an @font-face block — no component CSS changes. */
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
             Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;

  /* Scale — 12/14/16/20/28, nothing smaller than 12px (§4.2). */
  --fs-xs: 0.75rem;
  --fs-sm: 0.875rem;
  --fs-md: 1rem;
  --fs-lg: 1.25rem;
  --fs-xl: 1.75rem;
  --fs-2xl: 2.5rem;

  /* Spacing — 4/8/12/16/24/32. */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px;
  --s-4: 16px; --s-6: 24px; --s-8: 32px; --s-12: 48px; --s-16: 64px;

  --radius: 8px;
  --radius-sm: 6px;
  --maxw: 1100px;

  /* One shadow, used sparingly. Structure comes from borders (§5). */
  --shadow: 0 1px 2px oklch(21% 0.012 285 / 0.06);
}

[data-theme="dark"] {
  --bg:            oklch(17% 0.012 285);
  --surface:       oklch(21% 0.014 285);
  --surface-sunk:  oklch(14% 0.012 285);
  --border:        oklch(30% 0.014 285);
  --border-strong: oklch(42% 0.016 285);
  --text:          oklch(96% 0.004 285);
  --text-muted:    oklch(70% 0.012 285);

  --accent:        oklch(72% 0.17 292);
  --accent-hover:  oklch(79% 0.15 292);
  --accent-weak:   oklch(28% 0.06 292);
  --on-accent:     oklch(17% 0.012 285);

  --success:       oklch(72% 0.16 155);
  --success-weak:  oklch(26% 0.05 155);
  --warn:          oklch(76% 0.15 70);
  --warn-weak:     oklch(28% 0.06 70);
  --danger:        oklch(68% 0.19 27);
  --danger-weak:   oklch(27% 0.07 27);

  --shadow: 0 1px 2px oklch(0% 0 0 / 0.4);
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--fs-sm);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0 0 var(--s-3); line-height: 1.2; font-weight: 700; }
h1 { font-size: var(--fs-2xl); letter-spacing: -0.02em; }
h2 { font-size: var(--fs-xl); letter-spacing: -0.015em; }
h3 { font-size: var(--fs-lg); letter-spacing: -0.01em; }
p  { margin: 0 0 var(--s-3); }
p:last-child { margin-bottom: 0; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-hover); }

/* All numeric, address, key, hash and log output is monospace with TABULAR
   figures, so columns of numbers align and digits do not jitter on update. */
code, kbd, pre, samp, .mono, .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.9375em;
}
.num { font-variant-numeric: tabular-nums; }

/* §5: never the default browser focus ring. One visible, themed ring. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
:focus:not(:focus-visible) { outline: none; }

/* R9 / FE-4: honour reduced motion. This page may be open for days. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   3. Layout
   -------------------------------------------------------------------------- */

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--s-4); }
.section { padding: var(--s-16) 0; border-top: 1px solid var(--border); }
.section:first-of-type { border-top: 0; }
.stack > * + * { margin-top: var(--s-3); }
.grid { display: grid; gap: var(--s-4); }
@media (min-width: 700px) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
}

/* --------------------------------------------------------------------------
   4. Wordmark
   §5: no logo exists. BOTSOL is a typographic wordmark. Never generate logo
   imagery for it.
   -------------------------------------------------------------------------- */

.wordmark {
  font-weight: 800;
  letter-spacing: 0.08em;
  font-size: var(--fs-md);
  color: var(--text);
  text-decoration: none;
  text-transform: uppercase;
}
.wordmark::after {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  margin-left: 6px;
  background: var(--accent);
  vertical-align: 0.05em;
}

/* --------------------------------------------------------------------------
   5. Card
   -------------------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s-4);
}
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3); margin-bottom: var(--s-3);
}
.card-title { font-size: var(--fs-sm); font-weight: 700; margin: 0; }

/* --------------------------------------------------------------------------
   6. Stat
   -------------------------------------------------------------------------- */

.stat-label {
  font-size: var(--fs-xs); color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600;
}
.stat-value {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-xl); font-weight: 700; line-height: 1.1;
}
.stat-meta { font-size: var(--fs-xs); color: var(--text-muted); }

/* Semantic only — and never colour alone (FE-P2). Pair with a sign or label. */
.is-profit { color: var(--success); }
.is-loss   { color: var(--danger); }

/* --------------------------------------------------------------------------
   7. Badge
   §4.3 / FE-P2: always label + shape, never colour alone. The ::before dot
   gives a non-colour cue, and each variant carries its own text.
   -------------------------------------------------------------------------- */

.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px 3px 8px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface-sunk);
  color: var(--text);
  font-size: var(--fs-xs); font-weight: 600;
  white-space: nowrap;
}
.badge::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; flex: none;
}
.badge-success { color: var(--success); border-color: var(--success); background: var(--success-weak); }
.badge-warn    { color: var(--warn);    border-color: var(--warn);    background: var(--warn-weak); }
.badge-danger  { color: var(--danger);  border-color: var(--danger);  background: var(--danger-weak); }
.badge-neutral { color: var(--text-muted); }
/* Square marker distinguishes "skipped" from a status dot at a glance —
   a skip is normal operation, not an error (FE-S10). */
.badge-skip::before { border-radius: 1px; }

/* --------------------------------------------------------------------------
   8. Button
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  padding: 10px var(--s-4);
  min-height: 44px;                    /* FE-3: touch target >= 44px */
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit; font-weight: 650;
  cursor: pointer;
  transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}
.btn:hover { background: var(--accent-hover); }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled="true"] {
  opacity: 0.55; cursor: not-allowed; pointer-events: none;
}
.btn-secondary {
  background: var(--surface); color: var(--text); border-color: var(--border-strong);
}
.btn-secondary:hover { background: var(--surface-sunk); border-color: var(--text-muted); }
.btn-ghost { background: transparent; color: var(--text); border-color: transparent; }
.btn-ghost:hover { background: var(--surface-sunk); }
.btn-danger { background: var(--danger); color: var(--on-accent); }
.btn-sm { min-height: 32px; padding: 4px var(--s-3); font-size: var(--fs-xs); }

/* Loading state disables the control and swaps the label (§4.3). */
.btn[data-loading="true"] { pointer-events: none; opacity: 0.75; }

/* --------------------------------------------------------------------------
   9. Field
   Errors sit next to the field, not in a global banner (§4.3).
   -------------------------------------------------------------------------- */

.field { display: block; margin-bottom: var(--s-4); }
.field-label {
  display: block; margin-bottom: 6px;
  font-size: var(--fs-xs); font-weight: 650;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted);
}
.field input[type="text"],
.field input[type="email"],
.field select {
  width: 100%; min-height: 44px;
  padding: 10px var(--s-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text);
  font: inherit;
}
.field input::placeholder { color: var(--text-muted); opacity: 0.7; }
.field-hint { margin-top: 6px; font-size: var(--fs-xs); color: var(--text-muted); }
.field-error {
  margin-top: 6px; font-size: var(--fs-xs); color: var(--danger); font-weight: 600;
}
.field-error:not(:empty)::before { content: "▲ "; }
.field[data-invalid="true"] input { border-color: var(--danger); }

/* Segmented choice — used for the chain picker. */
.segmented { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.segmented input { position: absolute; opacity: 0; pointer-events: none; }
.segmented label {
  flex: 1 1 180px;
  padding: var(--s-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
  transition: border-color 150ms ease, background-color 150ms ease;
}
.segmented label:hover { border-color: var(--text-muted); }
.segmented input:checked + label {
  border-color: var(--accent);
  background: var(--accent-weak);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.segmented input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   10. Copyable
   FE-7: the copy button copies the COMPLETE string even when the display
   truncates. A truncated copy of a payment address is a catastrophic failure
   class — the full value always lives in data-copy.
   -------------------------------------------------------------------------- */

.copyable {
  display: flex; align-items: stretch; gap: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-sunk);
  overflow: hidden;
}
.copyable-value {
  flex: 1; min-width: 0;
  padding: var(--s-3);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-xs);
  word-break: break-all;      /* full address stays visible, never clipped */
  line-height: 1.5;
}
.copyable-btn {
  flex: none; min-width: 88px;
  border: 0; border-left: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text);
  font: inherit; font-size: var(--fs-xs); font-weight: 650;
  cursor: pointer;
  transition: background-color 150ms ease;
}
.copyable-btn:hover { background: var(--surface-sunk); }
.copyable-btn[data-copied="true"] { color: var(--success); }

/* Secret values — masked until explicitly revealed (FE-C8). */
.secret-mask {
  font-family: var(--font-mono); letter-spacing: 0.1em; color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   11. Notice / empty / callout
   -------------------------------------------------------------------------- */

.notice {
  border: 1px solid var(--border-strong);
  border-left-width: 3px;
  border-radius: var(--radius-sm);
  padding: var(--s-3) var(--s-4);
  background: var(--surface-sunk);
  font-size: var(--fs-sm);
}
.notice-warn   { border-left-color: var(--warn);    background: var(--warn-weak); }
.notice-danger { border-left-color: var(--danger);  background: var(--danger-weak); }
.notice-success{ border-left-color: var(--success); background: var(--success-weak); }
.notice-accent { border-left-color: var(--accent);  background: var(--accent-weak); }
.notice strong { font-weight: 700; }

.empty {
  padding: var(--s-8) var(--s-4);
  text-align: center; color: var(--text-muted);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
}

/* --------------------------------------------------------------------------
   12. Steps (buy flow)
   States must be explicit and human-readable (§6.4).
   -------------------------------------------------------------------------- */

.steps { display: flex; gap: var(--s-2); margin-bottom: var(--s-6); flex-wrap: wrap; }
.step {
  flex: 1 1 140px;
  padding: var(--s-2) var(--s-3);
  border-top: 3px solid var(--border);
  font-size: var(--fs-xs); color: var(--text-muted); font-weight: 650;
}
.step[data-state="current"] { border-top-color: var(--accent); color: var(--text); }
.step[data-state="done"]    { border-top-color: var(--success); color: var(--text); }
.step[data-state="done"]::after { content: " ✓"; color: var(--success); }

/* --------------------------------------------------------------------------
   13. Table
   -------------------------------------------------------------------------- */

.table-scroll { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
th, td {
  text-align: left; padding: var(--s-2) var(--s-3);
  border-bottom: 1px solid var(--border);
}
th {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted); font-weight: 650;
}
td.num, th.num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   14. Details / FAQ
   Native <details>, no JS (§6.6).
   -------------------------------------------------------------------------- */

details {
  border-bottom: 1px solid var(--border);
  padding: var(--s-3) 0;
}
summary {
  cursor: pointer; font-weight: 650;
  list-style: none; display: flex; justify-content: space-between; gap: var(--s-3);
}
summary::-webkit-details-marker { display: none; }
summary::after { content: "+"; color: var(--accent); font-weight: 700; flex: none; }
details[open] summary::after { content: "−"; }
details > *:not(summary) { margin-top: var(--s-3); color: var(--text-muted); }

/* --------------------------------------------------------------------------
   15. Toast
   -------------------------------------------------------------------------- */

.toast-region {
  position: fixed; top: var(--s-4); right: var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-2);
  z-index: 50;
}
.toast {
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border-strong); border-left: 3px solid var(--success);
  border-radius: var(--radius-sm);
  padding: var(--s-3) var(--s-4); box-shadow: var(--shadow);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   16. Storefront layout
   Surface A only. Kept in the shared file so the token vocabulary stays in one
   place; the dashboard and viewer simply do not use these classes.
   -------------------------------------------------------------------------- */

.nav {
  position: sticky; top: 0; z-index: 20;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.nav-inner {
  display: flex; align-items: center; gap: var(--s-4);
  min-height: 58px;                     /* §6.1: keep nav under 60px tall */
}
.nav nav { display: flex; gap: var(--s-4); margin-left: auto; flex-wrap: wrap; }
.nav nav a {
  color: var(--text-muted); text-decoration: none;
  font-size: var(--fs-sm); font-weight: 600;
}
.nav nav a:hover { color: var(--text); }
@media (max-width: 780px) {
  .nav nav { display: none; }           /* CTA and wordmark always remain */
}

.wrap-narrow { max-width: 720px; }

.hero { padding-top: var(--s-12); }
.eyebrow {
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent); margin-bottom: var(--s-3);
}
.hero h1 { max-width: 18ch; }
.lede {
  font-size: var(--fs-md); color: var(--text-muted);
  max-width: 56ch; margin-top: var(--s-4);
}
.hero-actions { display: flex; gap: var(--s-3); flex-wrap: wrap; margin: var(--s-6) 0; }

.hero-facts {
  display: grid; gap: var(--s-4); margin: var(--s-8) 0 0;
  border-top: 1px solid var(--border); padding-top: var(--s-4);
}
@media (min-width: 700px) { .hero-facts { grid-template-columns: repeat(3, 1fr); } }
.hero-facts div { margin: 0; }
.hero-facts dt {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-muted); font-weight: 650; margin-bottom: 2px;
}
.hero-facts dd { margin: 0; font-weight: 600; }
#hero-price { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
[data-state="loading"] { color: var(--text-muted); }
[data-state="error"] { color: var(--danger); }

.section-intro { color: var(--text-muted); max-width: 60ch; margin-bottom: var(--s-6); }
.sub { margin-top: var(--s-8); }

/* Typographic step diagram — R3 permits diagrammatic graphics, not illustration. */
.flow {
  list-style: none; padding: 0; margin: 0 0 var(--s-6);
  display: grid; gap: var(--s-4);
}
@media (min-width: 860px) { .flow { grid-template-columns: repeat(4, 1fr); } }
.flow li {
  border-top: 3px solid var(--accent);
  padding-top: var(--s-3);
}
.flow-n {
  font-family: var(--font-mono); font-size: var(--fs-xs);
  color: var(--accent); font-weight: 700;
}
.flow h3 { font-size: var(--fs-md); margin: var(--s-1) 0 var(--s-2); }
.flow p { color: var(--text-muted); font-size: var(--fs-sm); }

.ticks, .crosses { list-style: none; padding: 0; margin: 0; }
.ticks li, .crosses li {
  position: relative; padding-left: var(--s-6); margin-bottom: var(--s-2);
}
.ticks li::before {
  content: "✓"; position: absolute; left: 0;
  color: var(--success); font-weight: 700;
}
.crosses li::before {
  content: "✕"; position: absolute; left: 0;
  color: var(--danger); font-weight: 700;
}

.price-card .btn { margin-top: var(--s-4); width: 100%; }
.price-was {
  text-decoration: line-through; color: var(--text-muted);
  font-size: var(--fs-md); margin-bottom: 2px;
}

.pay-grid { display: grid; gap: var(--s-4); margin: var(--s-4) 0; }
@media (min-width: 640px) { .pay-grid { grid-template-columns: 1fr 1fr; } }
.spaced { margin-top: var(--s-4); }
.rule { border: 0; border-top: 1px solid var(--border); margin: var(--s-6) 0; }

.recover { margin-top: var(--s-6); }
.recover .btn { margin-top: var(--s-2); }

.footer {
  border-top: 1px solid var(--border);
  padding: var(--s-8) 0;
  background: var(--surface-sunk);
}
.footer-inner {
  display: flex; gap: var(--s-6); justify-content: space-between;
  flex-wrap: wrap; align-items: flex-start;
}
.footer-inner .field-hint { max-width: 46ch; margin-top: var(--s-2); }
.footer nav { display: flex; gap: var(--s-4); flex-wrap: wrap; }
.footer nav a { font-size: var(--fs-sm); font-weight: 600; }

/* Docs page — sticky section index beside the body. */
.docs-layout { display: grid; gap: var(--s-8); padding-top: var(--s-8); padding-bottom: var(--s-16); }
@media (min-width: 900px) { .docs-layout { grid-template-columns: 200px 1fr; } }
.docs-index nav { display: flex; flex-direction: column; gap: var(--s-1); }
@media (min-width: 900px) { .docs-index { position: sticky; top: 78px; align-self: start; } }
.docs-index a {
  color: var(--text-muted); text-decoration: none;
  font-size: var(--fs-sm); padding: 3px 0;
  border-left: 2px solid transparent; padding-left: var(--s-2);
}
.docs-index a:hover { color: var(--text); border-left-color: var(--accent); }
.docs-index .stat-label { margin-bottom: var(--s-2); }
.docs-body { min-width: 0; }
.docs-body section { margin-bottom: var(--s-12); }
.docs-body h2 {
  padding-top: var(--s-4); margin-top: var(--s-8);
  border-top: 1px solid var(--border);
}
.docs-body section:first-of-type h2 { border-top: 0; margin-top: 0; padding-top: 0; }
.docs-body h3 { margin-top: var(--s-6); }
.docs-body .copyable { margin-bottom: var(--s-4); }
.docs-body .copyable-value { white-space: pre-wrap; }
.docs-body table { margin-bottom: var(--s-4); }
.docs-body td:first-child { white-space: nowrap; }
.docs-body .notice { margin: var(--s-4) 0; }

/* --------------------------------------------------------------------------
   18. Print
   FE-N7: a support screenshot should capture what matters.
   -------------------------------------------------------------------------- */

@media print {
  .no-print { display: none !important; }
  body { background: #fff; color: #000; }
  .card { border-color: #999; break-inside: avoid; }
}

/* Download button row (storefront key screen + docs install). */
.download-row { display: flex; gap: var(--s-3); flex-wrap: wrap; margin: var(--s-3) 0; }
.download-row .btn { flex: 0 1 auto; }
