/* LapseCoin UI, shared layer. Per-page rules live in css/pages/<page>.css.
 *
 * Visual language (checked against Linear, Vercel, Stripe, Blockscout and
 * mempool.space screenshots, not only their CSS):
 *  - Geist Sans for everything, Geist Mono only for hashes and addresses.
 *    Numbers are sans with tabular figures. Big figures are large and tight,
 *    labels are small and muted: the size contrast carries the hierarchy.
 *  - White surfaces on a warm tinted page, 10px radius, a 1px low-contrast
 *    border and a barely visible shadow. Light header with a hairline.
 *  - One accent for links, focus and the active state. Status colors are
 *    muted and appear on text or a small dot. No gradients, no glow, no glass,
 *    no emoji icons, no purple, no stripe-on-the-left-edge cards.
 *  - Every grey is the ink at an opacity (--ink-rgb), so the palette stays warm.
 *  - Use the page's width: put things side by side (.cols) so a page fits
 *    without scrolling when there is room, and stack below 900px.
 */
@font-face { font-family: "Geist"; font-weight: 100 900; font-style: normal; font-display: swap; src: url("/css/fonts/Geist-Variable.woff2") format("woff2"); }
@font-face { font-family: "Geist Mono"; font-weight: 100 900; font-style: normal; font-display: swap; src: url("/css/fonts/geist-mono.woff2") format("woff2"); }
:root {
  --paper:    #f4f1ea;
  --paper-2:  #ebe7dc;
  --ink:      #1a1813;
  --ink-dim:  #6a6558;
  --ink-rgb:  26 24 19;
  --panel:    #f7f5ef;
  --rule:     rgb(var(--ink-rgb) / .09);
  --rule-lt:  #b9b29b;
  --accent:   #c2570c;
  --link:     #a84a08;
  --gain:     #1d7a3e;
  --loss:     #b42318;
  --live:     #2f4f6c;

  /* Odds-page builder identity. Capped at 3: validated colorblind-safe
     and normal-vision-distinguishable for *any* pair landing next to
     each other (not just adjacent ones), which a scatter of builders
     across time requires. A 4th slot fails that bar even with a
     legend. Every other builder folds into --series-other instead of
     a 4th generated color. */
  --series-1:     #2a78d6;
  --series-2:     #eb6834;
  --series-3:     #1baf7a;
  --series-other: var(--rule-lt);
  --serif: "Geist", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono:  "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --surface: #fffefb;
  --line-strong: rgb(var(--ink-rgb) / .2);
  --hover: rgb(var(--ink-rgb) / .04);
  --radius: 10px;
  --radius-sm: 8px;
  --shadow: 0 1px 2px rgb(var(--ink-rgb) / .05);
  --container: 1240px;

  /* aliases kept so the per-page templates (unchanged) still resolve */
  --muted:  var(--ink-dim);
  --green:  var(--gain);
  --red:    var(--loss);
  --warn:   var(--loss);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--paper); color: var(--ink); font-family: var(--serif);
  font-size: 14px; line-height: 1.5; -webkit-font-smoothing: antialiased; font-feature-settings: "ss01", "cv11";
  display: flex; flex-direction: column; min-height: 100vh;
}
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 2px; }
h1, h2, h3, p, ul, ol { margin: 0; }

/* ===================================================== app bar ======== */
/* One 52px row: brand, nav, status, links. Light, with a hairline, so the
   content below it leads. */
.masthead {
  position: sticky; top: 0; z-index: 100;
  background: var(--surface); color: var(--ink);
  border-bottom: 1px solid var(--rule);
  padding: 0 1.25rem;
}
.masthead-inner {
  max-width: var(--container); margin: 0 auto; min-height: 52px;
  display: flex; align-items: center; gap: .5rem 1rem;
}
.masthead-title {
  order: 1; display: flex; align-items: center; gap: .55rem; flex: 0 0 auto;
  font-size: .95rem; font-weight: 650; letter-spacing: -.02em; white-space: nowrap;
}
.masthead-title img { height: 1.3em; width: auto; }
nav.mainnav {
  order: 2; flex: 1 1 auto; min-width: 0;
  display: flex; flex-wrap: nowrap; gap: .05rem; font-size: .84rem;
  overflow-x: auto; scrollbar-width: none;
}
nav.mainnav::-webkit-scrollbar { display: none; }
nav.mainnav .sep { display: none; }
nav.mainnav a {
  display: inline-flex; align-items: center; gap: .4rem;
  color: var(--ink-dim); text-decoration: none; white-space: nowrap; font-weight: 500;
  padding: .4rem .55rem; border-radius: var(--radius-sm); transition: color .1s, background .1s;
}
nav.mainnav a .ni { width: 14px; height: 14px; flex: 0 0 auto; opacity: .75; }
nav.mainnav a:hover { color: var(--ink); background: var(--hover); text-decoration: none; }
nav.mainnav a.active { color: var(--ink); background: rgb(var(--ink-rgb) / .07); font-weight: 600; }
nav.mainnav a.active .ni { opacity: 1; color: var(--accent); }
/* Explorer: Blocks, Balance and Mempool under one entry */
.nav-group { position: relative; display: inline-flex; }
.nav-group-btn {
  display: inline-flex; align-items: center; gap: .4rem; height: auto;
  background: none; border: 0; color: var(--ink-dim); font: inherit; font-weight: 500; letter-spacing: 0;
  padding: .4rem .55rem; border-radius: var(--radius-sm); cursor: pointer; transition: color .1s, background .1s;
}
.nav-group-btn:hover, .nav-group.open .nav-group-btn { color: var(--ink); background: var(--hover); }
.nav-group.active .nav-group-btn { color: var(--ink); background: rgb(var(--ink-rgb) / .07); font-weight: 600; }
.nav-group.active .nav-group-btn .ni { opacity: 1; color: var(--accent); }
.nav-group-btn .ni { width: 14px; height: 14px; opacity: .75; }
.nav-group-btn .nc { width: 9px; height: 6px; opacity: .6; transition: transform .15s; }
.nav-group.open .nc, .nav-group:hover .nc { transform: rotate(180deg); }
.nav-menu {
  display: none; position: absolute; top: 100%; left: 0; z-index: 120; min-width: 15rem;
  padding: .35rem; margin-top: .35rem; border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--surface); box-shadow: 0 8px 28px rgb(var(--ink-rgb) / .14);
}
.nav-menu::before { content: ""; position: absolute; left: 0; right: 0; top: -.4rem; height: .4rem; }
.nav-group:hover .nav-menu, .nav-group.open .nav-menu, .nav-group:focus-within .nav-menu { display: block; }
nav.mainnav .nav-menu a { display: flex; align-items: center; gap: .65rem; padding: .5rem .6rem; border-radius: var(--radius-sm); }
nav.mainnav .nav-menu a .ni { width: 16px; height: 16px; }
.nav-menu a span { display: flex; flex-direction: column; line-height: 1.25; }
.nav-menu a b { font-weight: 600; font-size: .86rem; color: var(--ink); }
.nav-menu a small { font-size: .76rem; color: var(--ink-dim); font-weight: 400; }
nav.mainnav .nav-menu a.active { background: rgb(var(--ink-rgb) / .07); }
@media (min-width: 761px) { nav.mainnav { overflow: visible; } }
@media (max-width: 760px) {
  /* The strip scrolls sideways here and would clip a dropdown, so the group
     lays its three links out inline instead. */
  .nav-group { display: contents; }
  .nav-group-btn { display: none; }
  .nav-menu { display: contents; }
  nav.mainnav .nav-menu a small { display: none; }
  nav.mainnav .nav-menu a b { color: inherit; font-weight: 500; font-size: inherit; }
  nav.mainnav .nav-menu a.active b { font-weight: 600; }
}
nav.mainnav a.nav-disabled { color: rgb(var(--ink-rgb) / .3); pointer-events: none; }
.live-status { order: 3; flex: 0 0 auto; color: var(--ink-dim); font-size: .72rem; white-space: nowrap; }
.corner-links { order: 4; flex: 0 0 auto; display: flex; gap: .15rem; }
.corner-links a { color: var(--ink-dim); line-height: 0; padding: .4rem; border-radius: var(--radius-sm); }
.corner-links a:hover { color: var(--ink); background: var(--hover); text-decoration: none; }
.corner-links svg { width: 17px; height: 17px; }
.version-alert, .masthead-inner > div:not([class]) { order: 5; }
.version-alert {
  flex: 0 0 auto; display: inline-block; margin: 0; padding: .2rem .65rem;
  border: 1px solid rgb(194 87 12 / .35); border-radius: 999px; background: rgb(194 87 12 / .08); color: var(--link);
  font-size: .74rem; font-weight: 600; text-decoration: none; white-space: nowrap;
}
.version-alert:hover { background: rgb(194 87 12 / .14); text-decoration: none; }
@media (max-width: 1560px) { .live-status { display: none; } }
@media (max-width: 1200px) { nav.mainnav a .ni { display: none; } }
.page-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: .5rem 1rem; margin-bottom: .75rem; }
.page-head h2 { margin: 0; }
@media (max-width: 760px) {
  .masthead { padding: 0 .75rem; }
  .masthead-inner { flex-wrap: wrap; padding: .4rem 0 .15rem; min-height: 0; }
  .masthead-title { order: 1; flex: 1 1 auto; }
  .corner-links { order: 2; }
  .live-status { display: none; }
  nav.mainnav { order: 3; flex: 1 0 100%; padding-bottom: .3rem; }
}

/* ===================================================== layout ========= */
.page { flex: 1; width: 100%; max-width: var(--container); margin: 0 auto; padding: .9rem 1.25rem 1rem; }
.page > *:last-child { margin-bottom: 0; }
h2 { font-size: 1.35rem; font-weight: 650; letter-spacing: -.02em; line-height: 1.2; margin-bottom: .65rem; }
/* Layout helpers: put things side by side when the screen has room, so a
   page fits without scrolling, and stack them below 900px. */
.cols { display: grid; gap: .75rem; grid-template-columns: repeat(var(--n, 2), minmax(0, 1fr)); align-items: start; margin-bottom: .75rem; }
.cols > * { margin-bottom: 0; }
.cols-wide-left { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
.cols-wide-right { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); }
@media (max-width: 900px) { .cols, .cols-wide-left, .cols-wide-right { grid-template-columns: minmax(0, 1fr); } }
h3 { font-size: 1rem; font-weight: 600; letter-spacing: -.01em; margin-bottom: .5rem; }

/* ===================================================== components ===== */
.card {
  border: 1px solid var(--rule); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: .85rem 1.1rem; margin-bottom: .75rem; background: var(--surface);
}
.form-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .75rem;
  padding: .4rem 0; border-bottom: 1px solid var(--rule);
}
.form-row:last-child { border-bottom: none; }
.form-row label { flex: 0 0 auto; min-width: 180px; margin-bottom: 0; }
.form-row input[type="text"], .form-row input[type="number"] { flex: 1 1 200px; width: auto; max-width: 260px; }
.form-row input[type="checkbox"] { width: auto; margin-right: .35rem; }
.form-row .stat-sub { flex: 1 1 100%; margin-top: 0; }
.card-title {
  font-size: .8rem; font-weight: 600; color: var(--ink-dim); margin-bottom: .55rem;
}

.stats { display: flex; flex-wrap: wrap; border: 1px solid var(--rule); border-radius: var(--radius); box-shadow: var(--shadow);
  background: var(--surface); overflow: hidden; margin-bottom: .75rem; }
.stat {
  flex: 1 1 150px; min-width: 130px; padding: .7rem 1.1rem; border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.stat:last-child { border-right: none; }
.stat-label { font-size: .78rem; font-weight: 500; color: var(--ink-dim); margin-bottom: .15rem; }
.stat-value { font-size: 1.4rem; font-weight: 600; letter-spacing: -.02em; line-height: 1.25; font-variant-numeric: tabular-nums; overflow-wrap: break-word; }
.stat-sub { color: var(--ink-dim); font-size: .78rem; margin-top: .15rem; }
/* Scoped to a stat tile specifically (not every .stat-sub, some are
   form hint text elsewhere and should keep wrapping normally): label +
   value + one line of this is the budget, a tile never grows a 4th
   line for a long sentence. */
.stat .stat-sub {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Several small figures sharing one box, each keeping its own label so
   none of them has to be guessed from context. Same label and value
   type as a box holding one figure, just in columns. */
/* A box holding three figures gets about twice the room of one holding
   a single figure, so its columns stay on one line at the widths that
   matter. */
.stat.stat-trio { flex: 1 1 250px; }
.stat-group { display: flex; flex-wrap: wrap; gap: .3rem 1.1rem; }
/* Figures, so they never break mid-number the way .stat-value's
   break-word (there for addresses) would: the column wraps to the next
   line instead, which stays readable. */
.stat-group .stat-value { font-size: 1.15rem; overflow-wrap: normal; white-space: nowrap; }

/* A stat whose first real value hasn't arrived yet (page just loaded,
   the live poll below hasn't answered once): a fresh node briefly at
   height 0 with 0 peers reads as broken, not as "starting up", so the
   first paint shows this instead of a number. Replaced outright by
   the poll's own textContent/innerHTML write on its first response,
   genuine or not: a peer count that really is 0 shows 0 once that's
   confirmed, this only covers the gap before anything is confirmed. */
.stat-spinner {
  display: inline-block; width: .85em; height: .85em;
  border: 2px solid var(--rule-lt); border-top-color: var(--ink-dim);
  border-radius: 50%; animation: stat-spin .7s linear infinite;
  vertical-align: -.1em;
}
@keyframes stat-spin { to { transform: rotate(360deg); } }

.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 -1.15rem; padding: 0 1.15rem; }
table { width: 100%; min-width: 460px; border-collapse: collapse; font-size: .9rem; }
th {
  text-align: left; padding: .5rem .8rem; font-weight: 500; color: var(--ink-dim); font-size: .78rem;
  border-bottom: 1px solid var(--rule); white-space: nowrap;
}
td { padding: .55rem .8rem; border-bottom: 1px solid var(--rule); font-variant-numeric: tabular-nums; white-space: nowrap; }
tbody tr:hover td { background: var(--hover); }
tr:last-child td { border-bottom: none; }

/* Fixed layout plus an explicit colgroup (in peers.html) stops the
   browser's default column-width algorithm from dumping all of a
   table's leftover width into whichever column it picks, which on
   the peers table left a large empty gap in one column instead of
   the table simply being however wide its content needs. */
table.stacked-wide { table-layout: fixed; }

table.kv-table { min-width: 0; }
table.kv-table td { white-space: normal; font-size: .9rem; }
table.kv-table td.hash, table.kv-table td .hash { font-family: var(--mono); }
table.kv-table td:first-child {
  color: var(--ink-dim); white-space: nowrap; width: 1%; padding-right: 1.5rem;
}

/* Below this width a multi-column data table no longer fits without
   scrolling, so it's presented as a stack of labelled rows (one card
   per record) instead of asking the reader to scroll sideways. Label
   sits above its value (rather than side by side) so a long hash or
   address can still wrap across multiple lines without the layout
   fighting it. */
@media (max-width: 640px) {
  .table-wrap { overflow-x: visible; margin: 0; padding: 0; }
  table.stacked { min-width: 0; }
  table.stacked thead { display: none; }
  table.stacked, table.stacked tbody, table.stacked tr, table.stacked td { display: block; width: 100%; }
  table.stacked tr {
    border: 1px solid var(--rule-lt); margin-bottom: .75rem; padding: .6rem .75rem;
  }
  table.stacked tr:last-child { margin-bottom: 0; }
  table.stacked td {
    border-bottom: 1px dotted var(--rule-lt); padding: .4rem 0; white-space: normal; word-break: break-all;
  }
  table.stacked td:last-child { border-bottom: none; }
  table.stacked td[colspan] { text-align: center; border-bottom: none; }
  table.stacked td::before {
    content: attr(data-label); display: block; font-family: var(--serif);
    font-size: .78rem; color: var(--ink-dim); margin-bottom: .15rem;
  }
  table.stacked td[colspan]::before { content: none; }
}

/* The peers table has six columns (wider than any other table on the
   site) and stops fitting the page's own 900px content width before
   640px, so it needs to switch to the stacked layout earlier than
   everything else does. Same rules as above, just a wider trigger,
   so this table never gets a horizontal scrollbar at any width where
   the general 640px breakpoint would otherwise leave it in table
   mode. */
@media (max-width: 900px) {
  table.stacked-wide { min-width: 0; }
  table.stacked-wide thead { display: none; }
  table.stacked-wide, table.stacked-wide tbody, table.stacked-wide tr, table.stacked-wide td { display: block; width: 100%; }
  table.stacked-wide tr {
    border: 1px solid var(--rule-lt); margin-bottom: .75rem; padding: .6rem .75rem;
  }
  table.stacked-wide tr:last-child { margin-bottom: 0; }
  table.stacked-wide td {
    border-bottom: 1px dotted var(--rule-lt); padding: .4rem 0; white-space: normal; word-break: break-all;
  }
  table.stacked-wide td:last-child { border-bottom: none; }
  table.stacked-wide td[colspan] { text-align: center; border-bottom: none; }
  table.stacked-wide td::before {
    content: attr(data-label); display: block; font-family: var(--serif);
    font-size: .78rem; color: var(--ink-dim); margin-bottom: .15rem;
  }
  table.stacked-wide td[colspan]::before { content: none; }
}

.form-group { margin-bottom: .5rem; }
label { display: block; font-size: .82rem; font-weight: 500; color: var(--ink-dim); margin-bottom: .35rem; }
:where(input:not([type="radio"], [type="checkbox"], [type="file"], [type="hidden"], [type="range"]), textarea, select) {
  width: 100%; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); color: var(--ink);
  padding: 0 .75rem; height: 36px; font-family: var(--serif); font-size: .9rem;
  border-radius: var(--radius-sm); transition: border-color .12s;
}
:where(input[type="radio"], input[type="checkbox"]) { accent-color: var(--accent); width: 1.05rem; height: 1.05rem; margin: 0 .4rem 0 0; vertical-align: -.2em; }
select { appearance: none; padding-right: 2rem !important; cursor: pointer;
  background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%235a5547' stroke-width='1.5'/%3E%3C/svg%3E") no-repeat right .75rem center; }
input[type="file"] { font-family: var(--serif); font-size: .85rem; max-width: 100%; }
input[type="file"]::file-selector-button {
  background: var(--panel); color: var(--ink); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  padding: .35rem .8rem; margin-right: .6rem; font: inherit; font-weight: 600; cursor: pointer;
}
label:has(> input[type="radio"]) {
  display: inline-flex; align-items: center; margin: 0; padding: .35rem .8rem; cursor: pointer;
  font-size: .88rem; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
}
label:has(> input[type="radio"]:checked) { border-color: var(--ink); background: var(--ink); color: var(--surface); font-weight: 600; }
input::placeholder, textarea::placeholder { color: rgb(var(--ink-rgb) / .38); }
input:focus, textarea:focus, select:focus { outline: 2px solid rgb(194 87 12 / .35); outline-offset: 1px; border-color: var(--accent); }

button {
  background: var(--ink); color: var(--surface); border: 1px solid var(--ink);
  padding: 0 1.1rem; height: 36px; font-size: .88rem; font-family: var(--serif); font-weight: 550; cursor: pointer;
  border-radius: var(--radius-sm); transition: background .12s, transform .06s;
}
button:active:not(:disabled) { transform: translateY(1px); }
button:hover { background: rgb(var(--ink-rgb) / .82); }
button:disabled, button:disabled:hover {
  background: rgb(var(--ink-rgb) / .08); color: rgb(var(--ink-rgb) / .38); border-color: transparent;
  cursor: not-allowed;
}
.btn-ghost { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn-ghost:hover { background: var(--hover); }

.btn-sm {
  display: inline-block; background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: 6px; padding: .22rem .65rem; font-size: .75rem;
  font-family: var(--serif); font-weight: 550; text-decoration: none; white-space: nowrap;
}
.btn-sm:hover { background: var(--hover); text-decoration: none; }

.alert { padding: .65rem 1rem; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--surface); font-size: .88rem; margin-bottom: 1rem; }
.alert-ok  { background: #eef7f0; border-color: rgb(29 122 62 / .25); color: #14602f; }
.alert-err { background: #fdf0ee; border-color: rgb(180 35 24 / .25); color: #98201a; }

.hash { font-family: var(--mono); }
table.kv-table td:first-child {
  color: var(--ink-dim); white-space: nowrap; width: 1%; padding-right: 1.5rem;
}

/* Below this width a multi-column data table no longer fits without
   scrolling, so it's presented as a stack of labelled rows (one card
   per record) instead of asking the reader to scroll sideways. Label
   sits above its value (rather than side by side) so a long hash or
   address can still wrap across multiple lines without the layout
   fighting it. */
@media (max-width: 640px) {
  .table-wrap { overflow-x: visible; margin: 0; padding: 0; }
  table.stacked { min-width: 0; }
  table.stacked thead { display: none; }
  table.stacked, table.stacked tbody, table.stacked tr, table.stacked td { display: block; width: 100%; }
  table.stacked tr {
    border: 1px solid var(--rule-lt); margin-bottom: .75rem; padding: .6rem .75rem;
  }
  table.stacked tr:last-child { margin-bottom: 0; }
  table.stacked td {
    border-bottom: 1px dotted var(--rule-lt); padding: .4rem 0; white-space: normal; word-break: break-all;
  }
  table.stacked td:last-child { border-bottom: none; }
  table.stacked td[colspan] { text-align: center; border-bottom: none; }
  table.stacked td::before {
    content: attr(data-label); display: block; font-family: var(--serif);
    font-size: .78rem; color: var(--ink-dim); margin-bottom: .15rem;
  }
  table.stacked td[colspan]::before { content: none; }
}

/* The peers table has six columns (wider than any other table on the
   site) and stops fitting the page's own 900px content width before
   640px, so it needs to switch to the stacked layout earlier than
   everything else does. Same rules as above, just a wider trigger,
   so this table never gets a horizontal scrollbar at any width where
   the general 640px breakpoint would otherwise leave it in table
   mode. */
@media (max-width: 900px) {
  table.stacked-wide { min-width: 0; }
  table.stacked-wide thead { display: none; }
  table.stacked-wide, table.stacked-wide tbody, table.stacked-wide tr, table.stacked-wide td { display: block; width: 100%; }
  table.stacked-wide tr {
    border: 1px solid var(--rule-lt); margin-bottom: .75rem; padding: .6rem .75rem;
  }
  table.stacked-wide tr:last-child { margin-bottom: 0; }
  table.stacked-wide td {
    border-bottom: 1px dotted var(--rule-lt); padding: .4rem 0; white-space: normal; word-break: break-all;
  }
  table.stacked-wide td:last-child { border-bottom: none; }
  table.stacked-wide td[colspan] { text-align: center; border-bottom: none; }
  table.stacked-wide td::before {
    content: attr(data-label); display: block; font-family: var(--serif);
    font-size: .78rem; color: var(--ink-dim); margin-bottom: .15rem;
  }
  table.stacked-wide td[colspan]::before { content: none; }
}

.form-group { margin-bottom: .5rem; }
label { display: block; font-size: .82rem; font-weight: 500; color: var(--ink-dim); margin-bottom: .35rem; }
:where(input:not([type="radio"], [type="checkbox"], [type="file"], [type="hidden"], [type="range"]), textarea, select) {
  width: 100%; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); color: var(--ink);
  padding: 0 .75rem; height: 36px; font-family: var(--serif); font-size: .9rem;
  border-radius: var(--radius-sm); transition: border-color .12s;
}
:where(input[type="radio"], input[type="checkbox"]) { accent-color: var(--accent); width: 1.05rem; height: 1.05rem; margin: 0 .4rem 0 0; vertical-align: -.2em; }
select { appearance: none; padding-right: 2rem !important; cursor: pointer;
  background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%235a5547' stroke-width='1.5'/%3E%3C/svg%3E") no-repeat right .75rem center; }
input[type="file"] { font-family: var(--serif); font-size: .85rem; max-width: 100%; }
input[type="file"]::file-selector-button {
  background: var(--panel); color: var(--ink); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  padding: .35rem .8rem; margin-right: .6rem; font: inherit; font-weight: 600; cursor: pointer;
}
label:has(> input[type="radio"]) {
  display: inline-flex; align-items: center; margin: 0; padding: .35rem .8rem; cursor: pointer;
  font-size: .88rem; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
}
label:has(> input[type="radio"]:checked) { border-color: var(--ink); background: var(--ink); color: var(--surface); font-weight: 600; }
input::placeholder, textarea::placeholder { color: rgb(var(--ink-rgb) / .38); }
input:focus, textarea:focus, select:focus { outline: 2px solid rgb(194 87 12 / .35); outline-offset: 1px; border-color: var(--accent); }

button {
  background: var(--ink); color: var(--surface); border: 1px solid var(--ink);
  padding: 0 1.1rem; height: 36px; font-size: .88rem; font-family: var(--serif); font-weight: 550; cursor: pointer;
  border-radius: var(--radius-sm); transition: background .12s, transform .06s;
}
button:active:not(:disabled) { transform: translateY(1px); }
button:hover { background: rgb(var(--ink-rgb) / .82); }
button:disabled, button:disabled:hover {
  background: rgb(var(--ink-rgb) / .08); color: rgb(var(--ink-rgb) / .38); border-color: transparent;
  cursor: not-allowed;
}
.btn-ghost { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn-ghost:hover { background: var(--hover); }

.btn-sm {
  display: inline-block; background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: 6px; padding: .22rem .65rem; font-size: .75rem;
  font-family: var(--serif); font-weight: 550; text-decoration: none; white-space: nowrap;
}
.btn-sm:hover { background: var(--hover); text-decoration: none; }

.alert { padding: .65rem 1rem; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--surface); font-size: .9rem; margin-bottom: 1rem; }
.alert-ok  { border-left: 4px solid var(--gain); color: var(--gain); }
.alert-err { border-left: 4px solid var(--loss); color: var(--loss); }

.hash { font-family: var(--mono); font-size: .82rem; color: var(--ink-dim); word-break: break-all; white-space: normal; }
.hash-short { font-family: var(--mono); font-size: .85rem; }

.pager { display: flex; flex-wrap: wrap; gap: .8rem; align-items: baseline; margin-top: .25rem; font-size: .9rem; }
.pager-current { font-weight: 650; }
.pager-ellipsis { color: rgb(var(--ink-rgb) / .35); }
