/* NADO browser light-miner — mobile-first dark theme */
:root {
  --bg: #0b0f14;
  --bg-elev: #131a23;
  --bg-elev2: #1a232e;
  --border: #243140;
  --txt: #e6edf3;
  --txt-dim: #93a1b0;
  --txt-faint: #5d6b7a;
  --accent: #00ad93;          /* NADO brand teal (matches the logo + nadochain.com) */
  --accent-2: #00c9a7;        /* lighter teal for gradients/hover */
  /* --accent-rgb repeats --accent in bare channels: rgba() cannot take a hex custom property, and the
     page wash / button shadow / pill fills all need alpha over the accent. These were hardcoded to the
     teal, so a theme recoloured the buttons and left the page glow teal. See the THEMES block below. */
  --accent-rgb: 0, 173, 147;
  --bonded: #d29922;
  --open: #3fb950;
  --danger: #f85149;
  --warn: #d29922;
  --radius: 14px;
  --shadow: 0 6px 24px rgba(0,0,0,.35);
  /* one shared type system across the interface + the nadochain.com site */
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; padding: 0; }
body {
  background: radial-gradient(1100px 560px at 50% -12%, rgba(var(--accent-rgb),.10), var(--bg) 62%);
  background-attachment: fixed;
  color: var(--txt);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  padding: 0 0 64px;
  min-height: 100vh;
}

.wrap { max-width: 720px; margin: 0 auto; padding: 16px; }

header.app {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 7px 14px;
  background: rgba(11,15,20,.82);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
#langSelect { max-width: 130px; margin-top: 4px; }
header.app .logo {
  width: 26px; height: 26px;
  display: block; flex: none;
  /* the real NADO torus mark (static/logo.svg) — transparent bg, its own band colors + black stroke */
}
header.app h1 { font-size: 14px; margin: 0; font-weight: 700; letter-spacing: .2px; }
header.app .sub { font-size: 11px; color: var(--txt-dim); margin-top: 1px; }
header.app .conn { margin-left: auto; text-align: right; font-size: 11px; color: var(--txt-dim); }
/* network tag: which chain this wallet build talks to (client CHAIN_ID, red on relay mismatch) */
.net-tag { display: inline-block; padding: 0 7px; margin-right: 8px; border: 1px solid var(--border); border-radius: 999px; font-size: 10px; line-height: 15px; letter-spacing: .3px; vertical-align: middle; color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.net-tag.mismatch { color: var(--danger); border-color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, transparent); }
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--txt-faint); margin-right: 5px; vertical-align: middle; }
.dot.ok { background: var(--accent); box-shadow: 0 0 8px var(--accent); }
.dot.bad { background: var(--danger); }
.dot.warn { background: var(--warn); }
/* stat-value status tints (e.g. the exec "Delay behind L1" chip: green at the finality window, amber if it grows) */
.value.ok { color: var(--accent); }
.value.warn { color: var(--warn); }

.card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin: 14px 0;
  box-shadow: var(--shadow);
}
.card h2 { margin: 0 0 12px; font-size: 14px; text-transform: uppercase; letter-spacing: .08em; color: var(--txt-dim); font-weight: 700; }
.card h2 .pill { float: right; text-transform: none; letter-spacing: 0; }

.row { display: flex; gap: 10px; flex-wrap: wrap; }
.row > * { flex: 1 1 0; min-width: 0; }
.grow { flex: 1 1 auto; }

button, .btn {
  font-family: inherit; font-size: 15px; font-weight: 600;
  border: 1px solid var(--border); border-radius: 11px;
  background: var(--bg-elev2); color: var(--txt);
  padding: 12px 16px; cursor: pointer;
  transition: transform .05s ease, background .15s ease, border-color .15s;
}
button:active { transform: translateY(1px); }
button:disabled { opacity: .5; cursor: not-allowed; }
/* brand-teal CTAs (match nadochain.com): dark text on a teal gradient, subtle lift on hover */
button.primary, button.accent { background: linear-gradient(135deg, var(--accent), var(--accent-2)); border-color: transparent; color: var(--bg); font-weight: 800; box-shadow: 0 6px 20px rgba(var(--accent-rgb),.30); }
button.primary:hover:not(:disabled), button.accent:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 10px 28px rgba(var(--accent-rgb),.42); }
button.ghost { background: transparent; }
button.ghost:hover:not(:disabled) { border-color: var(--accent); }
button.danger { color: var(--danger); border-color: #4a2326; background: #1c1416; }
button.big { width: 100%; padding: 18px; font-size: 18px; font-weight: 800; border-radius: 14px; letter-spacing: .3px; }

label { display: block; font-size: 12px; color: var(--txt-dim); margin: 0 0 5px; }
input, textarea, select {
  width: 100%; font-family: var(--mono); font-size: 13px;
  background: var(--bg); color: var(--txt);
  border: 1px solid var(--border); border-radius: 10px;
  padding: 11px 12px;
}
textarea { resize: vertical; min-height: 64px; }
/* Native <select> ignores the background above on most platforms — the closed control and its dropdown
 * render in the OS default (white) unless appearance is reset. Reset it, draw our own chevron, and paint
 * the option list dark. option/optgroup colours are honoured by Chromium+Firefox on Windows/Linux; macOS
 * draws the popup natively regardless, but the control itself is then dark either way. */
select {
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  background-color: var(--bg);
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2393a1b0' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 34px; cursor: pointer;
}
select option, select optgroup { background: var(--bg-elev); color: var(--txt); }
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent-2); }

.mono { font-family: var(--mono); }
.small { font-size: 12px; }
.dim { color: var(--txt-dim); }
.faint { color: var(--txt-faint); }
.center { text-align: center; }
.mt { margin-top: 12px; }
.mb { margin-bottom: 12px; }
.hidden { display: none !important; }
.break { word-break: break-all; }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; align-items: baseline; }
.kv .k { color: var(--txt-dim); font-size: 12px; }
.kv .v { font-family: var(--mono); font-size: 13px; text-align: right; word-break: break-all; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
.stat { background: var(--bg-elev2); border: 1px solid var(--border); border-radius: 12px; padding: 12px; }
.stat .label { font-size: 11px; color: var(--txt-dim); text-transform: uppercase; letter-spacing: .06em; }
.stat .value { font-size: 20px; font-weight: 700; margin-top: 4px; font-family: var(--mono); }
.stat .value.sm { font-size: 15px; }
.stat[title] { cursor: help; }
/* the help badge is DRAWN, not a glyph: ⓘ (U+24D8) is missing from many system fonts and renders as a box */
.hint { display: inline-grid; place-items: center; width: 13px; height: 13px; margin-left: 4px; vertical-align: 1px;
  border: 1px solid var(--txt-faint); border-radius: 50%; color: var(--txt-faint); font-size: 0; cursor: help; }
.hint::before { content: "i"; font: 700 9px/1 var(--sans); }
.stat[title]:hover { border-color: var(--accent-2); }

.badge { display: inline-block; font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 999px; border: 1px solid var(--border); }
.badge.ok { background: rgba(63,185,80,.14); color: var(--accent); border-color: rgba(63,185,80,.4); }
.badge.no { background: rgba(248,81,73,.12); color: var(--danger); border-color: rgba(248,81,73,.4); }
.badge.idle { background: rgba(147,161,176,.1); color: var(--txt-dim); }

.addr-box { display: flex; align-items: center; gap: 8px; background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; }
.addr-box .a { font-family: var(--mono); font-size: 12.5px; word-break: break-all; flex: 1; }
.copy { font-size: 12px; padding: 6px 10px; flex: 0 0 auto; }

.warnbox { background: rgba(210,153,34,.1); border: 1px solid rgba(210,153,34,.4); color: #f0d488; border-radius: 10px; padding: 10px 12px; font-size: 12.5px; }
.warnbox.danger { background: rgba(248,81,73,.1); border-color: rgba(248,81,73,.4); color: #ffb4ae; }

/* progress */
.progress { height: 10px; background: var(--bg); border: 1px solid var(--border); border-radius: 999px; overflow: hidden; }
.progress > span { display: block; height: 100%; width: 0%; background: linear-gradient(90deg, var(--accent-2), var(--accent)); transition: width .2s; }
.progress.indet > span { width: 35%; animation: indet 1.1s ease-in-out infinite; }
@keyframes indet { 0%{margin-left:-35%} 100%{margin-left:100%} }

/* lane split visual */
.lanes { margin-top: 6px; }
.lanebar { display: flex; height: 30px; border-radius: 9px; overflow: hidden; border: 1px solid var(--border); }
.lanebar .open { background: linear-gradient(180deg,#3fb95040,#3fb95015); border-right: 1px solid var(--border); display: grid; place-items: center; color: var(--open); font-size: 11px; font-weight: 700; }
.lanebar .bonded { background: linear-gradient(180deg,#d2992240,#d2992215); display: grid; place-items: center; color: var(--bonded); font-size: 11px; font-weight: 700; }
.lane-legend { display: flex; gap: 16px; margin-top: 8px; font-size: 11.5px; color: var(--txt-dim); }
.lane-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: middle; }
.lane-legend i.open { background: var(--open); }
.lane-legend i.bonded { background: var(--bonded); }
.myshare { margin-top: 10px; font-size: 12px; color: var(--txt-dim); }

/* log */
#log { font-family: var(--mono); font-size: 12px; max-height: 260px; overflow-y: auto; background: var(--bg); border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; }
#log .line { padding: 3px 0; border-bottom: 1px dashed #1c2630; white-space: pre-wrap; word-break: break-word; }
#log .line:last-child { border-bottom: none; }
#log .t { color: var(--txt-faint); }
#log .ok { color: var(--accent); }
#log .err { color: var(--danger); }
#log .info { color: var(--accent-2); }
#log .win { color: #f0d488; font-weight: 700; }

/* self-test */
#selftest .case { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; font-family: var(--mono); padding: 3px 0; border-bottom: 1px dashed #1c2630; }
#selftest .case .name { color: var(--txt-dim); }
#selftest .case .res.pass { color: var(--accent); }
#selftest .case .res.fail { color: var(--danger); }
.summary-line { font-weight: 700; margin: 8px 0; }

footer { text-align: center; color: var(--txt-faint); font-size: 11px; padding: 24px 0 0; }
a { color: var(--accent-2); }

/* ---- full-wallet additions ---- */

/* tab bar */
.tabbar {
  display: flex; gap: 2px; flex-wrap: wrap;   /* wrap so every tab is reachable without horizontal scroll (touchless) */
  padding: 6px; margin: 14px 0;
  background: var(--bg-elev); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  scrollbar-width: none;
}
.tabbar::-webkit-scrollbar { display: none; }
.tabbar .tab {
  flex: 0 0 auto; font-size: 13px; font-weight: 700;
  padding: 8px 10px; border-radius: 10px;
  background: transparent; border: 1px solid transparent; color: var(--txt-dim);
}
.tabbar .tab.active { background: var(--bg-elev2); border-color: var(--border); color: var(--txt); }
/* a plain link in the tab bar (Web) must look exactly like the sibling tab buttons, not like body text */
.tabbar a.tab { text-decoration: none; color: var(--txt-dim); line-height: normal; }
.tabbar a.tab:hover { color: var(--txt); background: var(--bg-elev2); }

/* grouped tab dropdowns — collapse many tabs into a few labelled menus (hover on desktop, tap/focus on mobile) */
.tabgroup { position: relative; }
.tabgroup-btn {
  flex: 0 0 auto; font-size: 13px; font-weight: 700; cursor: pointer;
  padding: 8px 10px; border-radius: 10px;
  background: transparent; border: 1px solid transparent; color: var(--txt-dim);
}
.tabgroup-btn::after { content: "▾"; margin-left: 5px; opacity: .55; font-size: 10px; }
.tabgroup:hover .tabgroup-btn, .tabgroup:focus-within .tabgroup-btn, .tabgroup.open .tabgroup-btn { color: var(--txt); }
.tabgroup:has(.tab.active) .tabgroup-btn { background: var(--bg-elev2); border-color: var(--border); color: var(--txt); }
.tabmenu {
  display: none; position: absolute; top: calc(100% + 4px); left: 0; z-index: 30;
  flex-direction: column; gap: 4px; min-width: 168px; padding: 6px;
  background: var(--bg-elev); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow);
}
/* invisible hover bridge over the button→menu gap: crossing it must not break :hover and snap the menu shut */
.tabmenu::before { content: ""; position: absolute; top: -6px; left: 0; right: 0; height: 6px; }
/* .open = the JS-managed state (hover-intent grace on desktop, tap-toggle on touch); :hover/:focus-within
   stay as instant, JS-free openers. .closing wins over both so a just-picked menu folds even under the cursor. */
.tabgroup:hover .tabmenu, .tabgroup:focus-within .tabmenu, .tabgroup.open .tabmenu { display: flex; }
.tabgroup.closing .tabmenu { display: none !important; }
.tabmenu .tab { width: 100%; text-align: left; }
.tabmenu .tab:hover { background: var(--bg-elev2); color: var(--txt); }

/* receive QR */
.qr-wrap { display: grid; place-items: center; padding: 10px 0 4px; }
.qr { background: #fff; border-radius: 10px; padding: 10px; max-width: 100%; image-rendering: pixelated; image-rendering: crisp-edges; }

/* transaction history */
.hist { display: flex; flex-direction: column; gap: 8px; max-height: 440px; overflow-y: auto; }
.hist .empty { color: var(--txt-faint); font-size: 12px; text-align: center; padding: 14px; }
.hist .htx { display: flex; align-items: center; gap: 10px; background: var(--bg-elev2); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; cursor: help; }
.hist .htx .ic { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; font-size: 14px; flex: 0 0 auto; background: var(--bg); border: 1px solid var(--border); }
.hist .htx .mid { flex: 1 1 auto; min-width: 0; }
.hist .htx .tp { font-size: 13px; font-weight: 700; text-transform: capitalize; }
.hist .htx .cp { font-family: var(--mono); font-size: 11px; color: var(--txt-dim); word-break: break-all; }
.hist .htx .meta { font-size: 11px; color: var(--txt-faint); }
.hist .htx .amt { font-family: var(--mono); font-size: 13px; font-weight: 700; flex: 0 0 auto; text-align: right; white-space: nowrap; }
.hist .htx .amt.pos { color: var(--accent); }
.hist .htx .amt.neg { color: var(--danger); }
.hist .htx .amt.zero { color: var(--txt-dim); }

/* inline form-result messages */
.msg-ok { color: var(--accent); }
.msg-err { color: var(--danger); }

/* payment-request banner (reuses the .hint ⓘ convention) on the Send tab */
.hint-banner {
  display: flex; align-items: center; gap: 8px;
  background: rgba(var(--accent-rgb),.08); border: 1px solid rgba(var(--accent-rgb),.28);
  color: var(--txt-dim); border-radius: 12px; padding: 13px 15px;
  font-size: 12.5px; line-height: 1.5; margin: 14px 0;
}
/* block-layout banners (the APY estimate + auto-bond controls) space their rows evenly */
.hint-banner[style*="block"] > * + * { margin-top: 10px; }
.hint-banner label { font-weight: 600; color: var(--txt); }
.hint-banner .hint { color: inherit; cursor: default; font-size: 12px; margin: 0; font-weight: 400; }
.hint-banner b { color: var(--txt); }
/* staged status banner state variants (registration confirmed / failed) */
.hint-banner.ok { background: rgba(63,185,80,.10); border-color: rgba(63,185,80,.4); color: #8be39a; }
.hint-banner.warn { background: rgba(248,81,73,.10); border-color: rgba(248,81,73,.4); color: #ffb4ae; }

/* inline button spinner — shown on the Start/Mine button while one-time registration is underway */
.spin {
  display: inline-block; width: 14px; height: 14px; flex: 0 0 auto;   /* never squashed into an ellipse by a flex row's text */
  margin-right: 9px; vertical-align: -2px;
  border: 2px solid rgba(255,255,255,.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* non-blocking toast */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  max-width: 90%; z-index: 50;
  background: var(--bg-elev2); border: 1px solid var(--border); color: var(--txt);
  border-radius: 12px; padding: 12px 16px; font-size: 13px; box-shadow: var(--shadow);
}
.toast.err { border-color: rgba(248,81,73,.5); color: #ffb4ae; }
.toast.ok { border-color: rgba(63,185,80,.4); color: var(--accent); }
.toast.info { border-color: rgba(47,129,247,.4); color: #9fc6ff; }

/* Address book (Send tab): saved contacts with labels + resolved @aliases */
.ab-head { font-weight:600; margin:8px 0 4px; opacity:.85; }
.ab-row { display:flex; align-items:baseline; gap:8px; padding:5px 0; border-bottom:1px solid var(--line,#1c2530); }
.ab-row:last-child { border-bottom:none; }
.ab-name { font-weight:600; cursor:pointer; }
.ab-sub { font-size:11px; }
.ab-acts { margin-left:auto; white-space:nowrap; }
.ab-acts a { cursor:pointer; margin-left:10px; opacity:.6; text-decoration:none; }
.ab-acts a:hover { opacity:1; }

/* Custom dialogs (replace native confirm/alert/prompt) — styled + translatable */
.modal-backdrop { position:fixed; inset:0; z-index:100; display:flex; align-items:center; justify-content:center;
  padding:20px; background:rgba(3,6,10,.66); backdrop-filter:blur(3px); animation:modalFade .14s ease; }
.modal-backdrop.hidden { display:none; }
.modal { max-width:400px; width:100%; margin:0; animation:modalPop .16s cubic-bezier(.2,.9,.3,1.15); }
.modal-title { margin:0 0 12px; font-size:16px; font-weight:700; color:var(--txt); }
.modal-body { color:var(--txt-dim); font-size:14px; margin-bottom:14px; white-space:pre-line; }
.modal-rows { display:flex; flex-direction:column; gap:9px; margin-bottom:16px; }
.modal-rows.hidden, .modal-body.hidden, .modal-warn.hidden, .modal-note.hidden, .modal-input.hidden { display:none; }
.modal-row { display:flex; justify-content:space-between; gap:14px; font-size:14px; align-items:baseline; }
.modal-row .k { color:var(--txt-dim); white-space:nowrap; }
.modal-row .v { font-family:var(--mono); text-align:right; word-break:break-all; }
.modal-warn { color:var(--warn); font-size:13px; font-weight:600; margin-bottom:14px; }
.modal-note { color:var(--txt-faint); font-size:12px; margin-bottom:14px; }
.modal-input { margin-bottom:16px; }
.modal-actions { display:flex; gap:10px; }
.modal-actions button { flex:1; }
@keyframes modalFade { from{opacity:0} to{opacity:1} }
@keyframes modalPop { from{opacity:0; transform:translateY(10px) scale(.97)} to{opacity:1; transform:none} }

/* Messages tab (doc/messaging.md) — WhatsApp-style two-pane: identities left, chat right; each scrolls */
.msg-layout { display: flex; gap: 10px; height: 62vh; min-height: 320px; }
.msg-side { flex: 0 0 240px; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.msg-main { flex: 1; display: flex; flex-direction: column; min-width: 0;
  border: 1px solid var(--border); border-radius: 12px; padding: 8px; background: var(--bg); }
.msgconv-list { flex: 1; display: flex; flex-direction: column; gap: 4px; overflow-y: auto; padding-right: 2px; }
.msgconv { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; text-align: left; width: 100%;
  background: var(--bg-elev); border: 1px solid var(--border); border-radius: 10px; padding: 7px 10px; cursor: pointer; color: var(--txt); font: inherit; }
.msgconv:hover, .msgconv.msgconv-active { border-color: var(--accent); }
.msgconv.msgconv-active { background: rgba(var(--accent-rgb),.08); }
.msgconv > * { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msgthread { flex: 1; display: flex; flex-direction: column; gap: 6px; overflow-y: auto; padding: 4px; }
.msg-compose { margin-top: 8px; }
.msgbubble { max-width: 84%; padding: 7px 11px; border-radius: 12px; }
.msgbubble.in { align-self: flex-start; background: var(--bg-elev); border: 1px solid var(--border); border-bottom-left-radius: 4px; }
.msgbubble.out { align-self: flex-end; background: var(--accent); color: var(--bg); border-bottom-right-radius: 4px; }
.msgbubble .msgtext { white-space: pre-wrap; word-break: break-word; line-height: 1.35; }
.msgbubble .msgmeta { margin-top: 2px; }
.msgbubble.out .msgmeta { color: rgba(4,17,10,.72); }
.msgempty { margin: auto; color: var(--txt-faint); text-align: center; padding: 20px; }
@media (max-width: 640px) {   /* stack the panes on a phone */
  .msg-layout { flex-direction: column; height: auto; }
  .msg-side { flex: none; }
  .msgconv-list { max-height: 24vh; }
  .msgthread { height: 46vh; flex: none; }
}

/* unread badge on the Messages tab button */
.tabbadge { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px;
  padding: 0 4px; margin-left: 5px; border-radius: 8px; background: var(--danger); color: #fff;
  font-size: 10px; font-weight: 800; line-height: 1; vertical-align: middle; }

/* rollup / contracts tab */
.rollup-item { padding: 6px 9px; border: 1px solid var(--border); border-radius: 8px; margin-bottom: 4px; cursor: pointer; }
.rollup-item:hover { border-color: var(--accent); }
.rollup-item.rollup-pending { border-style: dashed; opacity: .72; }
.rollup-mbtn { padding: 5px 10px; font-size: 13px; }
.rollup-hist { padding: 5px 0; border-bottom: 1px solid var(--border); word-break: break-word; }
.rollup-hist:last-child { border-bottom: 0; }
#rollupArgs .rollup-arg { margin-top: 2px; }


/* >>> SHARED-COMPONENTS — copied VERBATIM into static/theme.css by tools/gen_theme_tokens.py.
 * Everything between the sentinels must depend on nothing but the palette variables, because it is
 * served to the ten game pages, which carry their own inline <style> and load no other stylesheet.
 * Edit it HERE and regenerate; theme.css is not hand-editable. --------------------------------------
 *
 * ONE TOGGLE, EVERYWHERE. There used to be two, and neither worked properly:
 *
 * 1. `.switch` was a class with NO rules behind it — the Settings/Quorum/Assets toggles and every game
 *    page's toggles were plain NATIVE checkboxes. On a dark card an unchecked native box paints as a
 *    white square, and accent-color cannot help because it only tints the CHECKED fill. A box is also
 *    the wrong affordance: each of these is an on/off preference, not a form field.
 * 2. `.tgl` was a hand-built pill that DID look right, but it cost three elements of markup, lived in
 *    interface.css where no game page could see it, and sat directly below the white native boxes in
 *    the same Settings panel — which is precisely what made them read as broken.
 *
 * `.switch` is now that same pill drawn on the input itself with appearance:none: identical geometry,
 * zero extra markup, and `.tgl` is deleted rather than kept in parallel. Because it is in this shared
 * region it reaches the wallet and all ten game pages from one definition, so an SDK toggle can no
 * longer stay OS-green while the wallet themes.
 *
 * The reset below is load-bearing: the generic `input, textarea, select` rule (correct for text fields)
 * sets width:100%, padding, a border and a background, which stretched every box into a full-width
 * padded block long before theming existed. Undo those four before styling anything, or the sizing
 * here fights inherited padding. Boxes that are NOT .switch keep accent-color, and color-scheme:dark
 * paints their unchecked state dark instead of white — every palette is dark. */
/* The page glow. The wallet already derived it from the accent; all 24 game pages hardcoded the brand
 * teal into their own body rule, so a themed page still sat in a teal halo. Restating it here from
 * --accent-rgb gives both surfaces one definition — this sheet loads after their inline style, so the
 * literal loses. Identical to the wallet's own rule, and `background` is a shorthand, so the
 * attachment has to be restated with it or a themed page would scroll its glow. */
html, body {
  background: radial-gradient(1100px 560px at 50% -12%, rgba(var(--accent-rgb),.10), var(--bg) 62%);
  background-attachment: fixed;
}

input[type="checkbox"], input[type="radio"] {
  width: auto; padding: 0; border: 0; background: none; border-radius: 0;   /* undo the text-field rule */
  accent-color: var(--accent);
  color-scheme: dark;                   /* unchecked native box paints dark, not white */
  cursor: pointer; flex: 0 0 auto;
}
input[type="range"], progress { accent-color: var(--accent); }
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible {
  outline: 2px solid var(--accent-2); outline-offset: 2px;
}

input[type="checkbox"].switch {
  -webkit-appearance: none; appearance: none;
  position: relative; width: 44px; height: 25px; margin: 0; border-radius: 999px;
  background: var(--bg-elev2); border: 1px solid var(--border);
  transition: background .18s, border-color .18s;
}
input[type="checkbox"].switch::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 19px; height: 19px; border-radius: 50%;
  background: var(--txt); box-shadow: 0 1px 3px rgba(0,0,0,.4); transition: transform .18s, background .18s;
}
input[type="checkbox"].switch:checked {
  background: linear-gradient(135deg, var(--accent), var(--accent-2)); border-color: transparent;
}
input[type="checkbox"].switch:checked::after { transform: translateX(19px); background: var(--bg); }
input[type="checkbox"].switch:disabled { opacity: .5; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) {
  input[type="checkbox"].switch, input[type="checkbox"].switch::after { transition: none; }
}
/* <<< SHARED-COMPONENTS */

/* the save-and-continue button PULSES once it's armed (ack toggled on) — the eye goes straight to it */
.pulse-ready:not(:disabled) { animation: pulseready 1.3s ease-in-out infinite; }
@keyframes pulseready {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(0,201,167,.45); }
  50% { transform: scale(1.035); box-shadow: 0 0 0 8px rgba(0,201,167,0); }
}
@media (prefers-reduced-motion: reduce) { .pulse-ready:not(:disabled) { animation: none; } }

/* PENDING / CONFIRMING chips (wallet card + send panel): amber = "in flight, not spendable yet".
   Gentle pulse so a mid-flight send/buy-in reads as ALIVE, not stuck; static under reduced-motion. */
.pend { margin-top: 6px; font-size: 12px; font-weight: 600; font-family: var(--mono); color: #f0d488;
  background: rgba(210,153,34,.12); border: 1px solid rgba(210,153,34,.45); border-radius: 10px;
  padding: 4px 9px; display: inline-block; max-width: 100%; box-sizing: border-box; text-align: left;
  overflow-wrap: anywhere; line-height: 1.45; cursor: help; animation: pendpulse 2.4s ease-in-out infinite; }
.pend.hidden { display: none; }
.pendnote { margin-top: 10px; font-size: 12.5px; color: #f0d488; background: rgba(210,153,34,.08);
  border: 1px solid rgba(210,153,34,.35); border-radius: 10px; padding: 8px 12px; }
.pendnote.hidden { display: none; }
@keyframes pendpulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
@media (prefers-reduced-motion: reduce) { .pend { animation: none; } }

/* ---- MINING REWARDS chart (wallet landing, directly under the menu) -------------------------------
   A week of mined rewards as a stacked column per UTC day, split by the two lanes and coloured with the
   SAME --open / --bonded tokens the rest of the interface uses for them, so the lanes read identically
   wherever they appear. Sized by viewBox + width:100%, so it stays wide and sharp at any width. */
.mine-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin: -2px 0 10px; }
.mine-total { font-family: var(--mono); font-size: 26px; font-weight: 700; letter-spacing: -.5px;
  line-height: 1.1; color: var(--txt); }
.mine-total small { font-size: 12px; font-weight: 600; color: var(--txt-faint); letter-spacing: .06em; }
.mine-legend { margin-left: auto; display: flex; gap: 12px; flex-wrap: wrap; font-size: 11.5px; color: var(--txt-dim); }
.mine-legend .lg { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.mine-legend b { font-family: var(--mono); color: var(--txt); font-weight: 600; }
.mine-legend .sw { width: 9px; height: 9px; border-radius: 3px; display: inline-block; flex: none; }
.mine-legend .sw.open { background: var(--open); }
.mine-legend .sw.bonded { background: var(--bonded); }
.mine-legend .sw.div { background: var(--accent); }
.mine-chart { width: 100%; }
.mine-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.mine-chart .grid { stroke: var(--border); stroke-width: 1; }
.mine-chart .axis { fill: var(--txt-faint); font-size: 11px; font-family: var(--sans); }
.mine-chart .axis.today { fill: var(--accent); font-weight: 700; }
.mine-chart .val { fill: var(--txt-dim); font-size: 10.5px; font-family: var(--mono); }
.mine-chart .bar { transition: opacity .15s ease; }
.mine-chart g.col:hover .bar { opacity: .82; }
.mine-chart .empty { fill: var(--txt-faint); font-size: 12px; font-family: var(--sans); }
.mine-note { margin-top: 8px; font-size: 11.5px; color: var(--txt-faint); }
.mine-note.warn { color: #f0d488; }
/* the share-of-network figure next to each stream's total — a quiet companion to the number, not a rival */
.mine-legend .mshare { color: var(--txt-faint); font-weight: 600; font-size: 10.5px; }

/* ---------------------------------------------------------------------------------------------------
 * THEMES. Each is three variables — the accent, its lighter partner for gradients, and the same accent
 * in bare RGB channels for the alpha washes. Everything else (surfaces, text, borders) is deliberately
 * shared: recolouring only the accent keeps every contrast ratio the base theme was built with, so a
 * theme cannot quietly make text unreadable. `teal` is the default and needs no block.
 *
 * The pairs run light -> dark within one hue so the 135deg button gradient reads as depth rather than as
 * two different colours, and each is picked to stay legible against the dark #0b0f14 ground.
 * ------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------
 * THEMES. A theme replaces the WHOLE palette — page ground, card surfaces, borders, the three text
 * weights and the accent pair — so the interface is recoloured rather than just its buttons. Everything
 * downstream already reads these variables (101 uses across the stylesheet), so no rule needs touching.
 *
 * CONTRAST IS MEASURED, NOT EYEBALLED. Tinting surfaces toward a hue is exactly how a theme quietly
 * makes text unreadable, so every palette here was checked with the WCAG relative-luminance formula and
 * tests/test_themes.mjs recomputes it on every run. The bar is the base theme's own behaviour: body text
 * >= 4.5:1 on both the page and a card, dim text >= 4.5:1, faint text >= 3:1, accent >= 3:1. Measured
 * results run 14.6-16.8:1 for body text and 4.5-7.6:1 for the accent — all above WCAG AA.
 *
 * --accent-rgb repeats the accent in bare channels because rgba() cannot take a hex custom property; the
 * page wash, button shadow and pill fills need alpha over it. The test asserts it is arithmetically the
 * same colour as --accent, since a mismatch is invisible in review and obvious on screen.
 *
 * `teal` is the default and deliberately has no block — the :root values stay authoritative, so a stale
 * or tampered stored theme leaves a fully-styled page rather than a half-applied one.
 * ------------------------------------------------------------------------------------------------ */
html[data-theme="aqua"] {
  --bg: #06120f; --bg-elev: #0d1f1b; --bg-elev2: #132a25; --border: #1e4239;
  --txt: #e2f7f2; --txt-dim: #8fc3b9; --txt-faint: #5d8880;
  --accent: #40e0d0; --accent-2: #7ceee3; --accent-rgb: 64, 224, 208;
}
html[data-theme="violet"] {
  --bg: #0d0a16; --bg-elev: #171327; --bg-elev2: #1f1a33; --border: #312a4d;
  --txt: #ece9f6; --txt-dim: #a49bc4; --txt-faint: #6b6390;
  --accent: #7c5cff; --accent-2: #a78bfa; --accent-rgb: 124, 92, 255;
}
html[data-theme="ocean"] {
  --bg: #080f18; --bg-elev: #101c2b; --bg-elev2: #172538; --border: #243a55;
  --txt: #e4eefb; --txt-dim: #95aecd; --txt-faint: #5f7796;
  --accent: #2f81f7; --accent-2: #58a6ff; --accent-rgb: 47, 129, 247;
}
html[data-theme="ember"] {
  --bg: #150d08; --bg-elev: #231810; --bg-elev2: #2e2016; --border: #472f1e;
  --txt: #f7ebe2; --txt-dim: #c5a68f; --txt-faint: #8d715c;
  --accent: #f0883e; --accent-2: #ffab70; --accent-rgb: 240, 136, 62;
}
html[data-theme="rose"] {
  --bg: #150a11; --bg-elev: #24141d; --bg-elev2: #301a27; --border: #4b2b3d;
  --txt: #f8e9f1; --txt-dim: #c99cb4; --txt-faint: #8f6a7e;
  --accent: #db61a2; --accent-2: #f778ba; --accent-rgb: 219, 97, 162;
}
html[data-theme="forest"] {
  --bg: #08120b; --bg-elev: #0f2015; --bg-elev2: #152b1d; --border: #22432e;
  --txt: #e6f4e9; --txt-dim: #98bda4; --txt-faint: #638071;
  --accent: #3fb950; --accent-2: #56d364; --accent-rgb: 63, 185, 80;
}
html[data-theme="gold"] {
  --bg: #121006; --bg-elev: #201c0e; --bg-elev2: #2b2513; --border: #443a1c;
  --txt: #f6f0dd; --txt-dim: #c3b384; --txt-faint: #8b7d55;
  --accent: #d29922; --accent-2: #e3b341; --accent-rgb: 210, 153, 34;
}

/* The theme picker: one swatch per theme, each showing its own gradient so the choice is the preview. */
.themegrid { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
.themedot {
  width: 38px; height: 38px; border-radius: 50%; cursor: pointer; padding: 0;
  border: 2px solid var(--border); transition: transform .12s ease, border-color .12s ease;
}
.themedot:hover { transform: translateY(-2px); }
.themedot[aria-pressed="true"] { border-color: var(--txt); transform: translateY(-2px); }
.themedot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }


/* ---------------------------------------------------------------------------------------------------
 * LOGO RAMP. The mark is five shades of one hue — a depth ramp, not five colours — so it re-hues cleanly
 * per theme: each ramp keeps the artwork's original LIGHTNESS curve and only rotates the hue, with the
 * lightest step being exactly that theme's --accent. Recomputing the curve rather than picking five new
 * colours by hand is what keeps the facets reading as the same solid under every theme.
 *
 * logo.svg keeps the brand teal as each var's fallback, so the favicon and any <img src="logo.svg"> —
 * neither of which can see page CSS — still render the original mark. Only the INLINED copy in the header
 * follows the theme. -------------------------------------------------------------------------------- */
:root {
  --logo-1: #00443a; --logo-2: #006c5c; --logo-3: #00836f; --logo-4: #009982; --logo-5: #00ad93;
}
html[data-theme="aqua"] {
  --logo-1: #106159; --logo-2: #199b8e; --logo-3: #1ebcac; --logo-4: #24dbc9; --logo-5: #40e0d0;
}
html[data-theme="violet"] {
  --logo-1: #1b0088; --logo-2: #2b00d9; --logo-3: #3808ff; --logo-4: #5c34ff; --logo-5: #7c5cff;
}
html[data-theme="ocean"] {
  --logo-1: #04306f; --logo-2: #074cb1; --logo-3: #085dd6; --logo-4: #0e6df6; --logo-5: #2f81f7;
}
html[data-theme="ember"] {
  --logo-1: #6e3309; --logo-2: #af510e; --logo-3: #d46210; --logo-4: #ed741e; --logo-5: #f0883e;
}
html[data-theme="rose"] {
  --logo-1: #651741; --logo-2: #a12567; --logo-3: #c32c7d; --logo-4: #d44390; --logo-5: #db61a2;
}
html[data-theme="forest"] {
  --logo-1: #19491f; --logo-2: #277332; --logo-3: #308c3d; --logo-4: #38a447; --logo-5: #3fb950;
}
html[data-theme="gold"] {
  --logo-1: #533c0d; --logo-2: #836015; --logo-3: #9f741a; --logo-4: #ba871e; --logo-5: #d29922;
}

/* HAZARD PALETTES — the signage/rave combos: a near-black ground with one fluorescent accent.
 * The look depends on the accent screaming, so the surfaces stay almost neutral; the risk is that a
 * saturated fluorescent on black reads as vibrating rather than legible, which is why these were
 * measured like every other theme (toxic 14.8:1, hazard 15.8:1, alarm 5.3:1 accent-on-ground). */
html[data-theme="toxic"] {
  --bg: #060806; --bg-elev: #101410; --bg-elev2: #171d16; --border: #2a3a26;
  --txt: #eaf7e6; --txt-dim: #a6c69c; --txt-faint: #6f8a67;
  --accent: #39ff14; --accent-2: #7cff5a; --accent-rgb: 57, 255, 20;
}
html[data-theme="toxic"] {
  --logo-1: #116c00; --logo-2: #1bac00; --logo-3: #21d000; --logo-4: #26f300; --logo-5: #39ff14;
}
html[data-theme="hazard"] {
  --bg: #0a0800; --bg-elev: #151200; --bg-elev2: #1e1a04; --border: #3d3512;
  --txt: #faf6e2; --txt-dim: #cbbf86; --txt-faint: #8d8352;
  --accent: #ffe600; --accent-2: #fff45c; --accent-rgb: 255, 230, 0;
}
html[data-theme="hazard"] {
  --logo-1: #645a00; --logo-2: #9f9000; --logo-3: #c1ae00; --logo-4: #e2cc00; --logo-5: #ffe600;
}
html[data-theme="alarm"] {
  --bg: #0a0303; --bg-elev: #180909; --bg-elev2: #210d0d; --border: #421a1a;
  --txt: #fdeaea; --txt-dim: #d09a9a; --txt-faint: #946a6a;
  --accent: #ff1f1f; --accent-2: #ff6161; --accent-rgb: 255, 31, 31;
}
html[data-theme="alarm"] {
  --logo-1: #700000; --logo-2: #b30000; --logo-3: #d90000; --logo-4: #fd0000; --logo-5: #ff1f1f;
}

/* settings: one card, clearly sectioned — a reader finds "Network" or "Backup" by scanning, not by reading */
.settings-sect { margin: 24px 0 8px; padding-top: 14px; border-top: 1px solid var(--border); font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--txt-faint); }
