/* Classic phone-directory look: yellow newsprint, black ink, narrow type, ruled columns. */

:root {
  --paper: #f6d64a;
  --paper-light: #fbe57f;
  --ink: #17140f;
  --ink-soft: #3d3626;
  --rule: #17140f;
  --red: #a8201a;
  --amber: #7a4b00;
  --green: #1f5a1a;
  --narrow: "Archivo Narrow", "Arial Narrow", "Helvetica Neue", Arial, sans-serif;
  --black: "Archivo Black", "Arial Black", Impact, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;
}

/* Dark mode is the same page with ink and paper swapped: yellow type on a black sheet.
   It follows the system unless the toggle stored a choice (data-theme on <html>). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #17140f;
    --paper-light: #221d14;
    --ink: #f6d64a;
    --ink-soft: #c4aa45;
    --rule: #f6d64a;
    --red: #ff7b6b;
    --amber: #f0a73a;
    --green: #8fd67c;
  }
}

:root[data-theme="dark"] {
  --paper: #17140f;
  --paper-light: #221d14;
  --ink: #f6d64a;
  --ink-soft: #c4aa45;
  --rule: #f6d64a;
  --red: #ff7b6b;
  --amber: #f0a73a;
  --green: #8fd67c;
}

/* Testnet: the same directory printed on blue stock, so it is never mistaken for the real one.
   data-network is set from the node's chain type (and early from a testnet.* hostname). */
:root[data-network="testnet"] {
  --paper: #a4d4f4;
  --paper-light: #c6e5f9;
  --ink: #0b1a2c;
  --ink-soft: #23405e;
  --rule: #0b1a2c;
  --red: #9e1b16;
  --amber: #6a3f00;
  --green: #17501a;
}

@media (prefers-color-scheme: dark) {
  :root[data-network="testnet"]:not([data-theme="light"]) {
    --paper: #0b1622;
    --paper-light: #13212f;
    --ink: #86c8f2;
    --ink-soft: #5f9fca;
    --rule: #86c8f2;
    --red: #ff7b6b;
    --amber: #f0a73a;
    --green: #8fd67c;
  }
}

:root[data-network="testnet"][data-theme="dark"] {
  --paper: #0b1622;
  --paper-light: #13212f;
  --ink: #86c8f2;
  --ink-soft: #5f9fca;
  --rule: #86c8f2;
  --red: #ff7b6b;
  --amber: #f0a73a;
  --green: #8fd67c;
}

* {
  box-sizing: border-box;
}

/* Component display rules (buttons, banners) must not override the hidden attribute. */
[hidden] {
  display: none !important;
}

html {
  background: var(--paper);
}

/* The footer stays at the bottom of the window on short pages. */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--narrow);
  font-size: 16px;
  line-height: 1.35;
}

a {
  color: inherit;
}

code {
  font-family: var(--mono);
  font-size: 0.85em;
}

/* ---------- masthead ---------- */

.masthead {
  background: var(--ink);
  color: var(--paper);
}

.masthead-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 18px 16px 14px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.brand {
  text-decoration: none;
  display: flex;
  flex-direction: column;
}

.brand-title {
  font-family: var(--black);
  font-size: clamp(34px, 7vw, 64px);
  letter-spacing: -0.02em;
  line-height: 0.9;
}

/* Testnet stamp after the name; the same word in every language. */
:root[data-network="testnet"] .brand-title::after {
  content: "TESTNET";
  display: inline-block;
  vertical-align: top;
  margin-left: 0.5em;
  padding: 3px 6px 2px;
  border: 2px solid currentColor;
  font-family: var(--narrow);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.12em;
  line-height: 1;
}

.brand-sub {
  font-style: italic;
  font-size: 18px;
  margin-top: 6px;
}

/* Every link in the nav is the same height box, so they line up. */
.masthead-nav {
  --nav-h: 34px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  font-weight: 700;
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.masthead-nav a {
  height: var(--nav-h);
  display: inline-flex;
  align-items: center;
  border: 1px solid transparent;
}

.masthead-nav a {
  text-decoration: none;
  padding: 0 12px;
}

.masthead-nav a:hover {
  border-color: var(--paper);
}

.masthead-nav .cta {
  background: var(--paper);
  color: var(--ink);
}


.edition-bar {
  border-top: 1px solid var(--paper);
  max-width: 1200px;
  margin: 0 auto;
  padding: 4px 16px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* ---------- banners ---------- */

.banner {
  margin: 12px max(16px, calc((100% - 1168px) / 2)) 0;
  padding: 8px 12px;
  border: 2px solid var(--ink);
  font-weight: 600;
}

.banner.warn {
  background: var(--paper-light);
}

.banner.bad {
  background: var(--ink);
  color: var(--paper);
}

/* ---------- page ---------- */

/* Grows to push the footer down; auto side margins would otherwise shrink it to its content. */
.page {
  flex: 1 0 auto;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 16px;
}

.search {
  display: flex;
  align-items: center;
  gap: 12px;
  border-top: 3px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: 10px 0;
  margin-bottom: 18px;
}

.search label {
  font-family: var(--black);
  text-transform: uppercase;
  white-space: nowrap;
}

.search input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 18px;
  padding: 6px 10px;
  background: var(--paper-light);
  border: 2px solid var(--ink);
  color: var(--ink);
}

.columns {
  column-count: 3;
  column-gap: 28px;
  column-rule: 1px solid var(--rule);
}

@media (max-width: 960px) {
  .columns {
    column-count: 2;
  }
}

@media (max-width: 600px) {
  .columns {
    column-count: 1;
  }
  .search {
    flex-direction: column;
    align-items: stretch;
  }
}

/* Categories may continue in the next column, like a printed directory, so the columns stay even.
   A listing is never cut, and a heading never ends a column on its own. */
.category {
  margin-bottom: 18px;
}

.category-head {
  break-after: avoid;
}

.category-head,
.section-head {
  font-family: var(--black);
  font-size: 15px;
  letter-spacing: 0.08em;
  background: var(--ink);
  color: var(--paper);
  margin: 0 0 8px;
  padding: 3px 8px;
}

/* ---------- listings ---------- */

/* The whole row opens the listing: the name link is stretched over it. */
.listing {
  position: relative;
  break-inside: avoid;
  padding: 3px 0;
}

.listing-name::after {
  content: "";
  position: absolute;
  inset: 0;
}

.listing-line {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.listing-name {
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 65%;
}

.listing-name:hover {
  text-decoration: underline;
}

.leader {
  flex: 1;
  min-width: 12px;
  border-bottom: 2px dotted var(--ink-soft);
  transform: translateY(-4px);
}

.listing-addr {
  font-family: var(--mono);
  font-size: 13px;
  white-space: nowrap;
}

.listing-sub {
  font-size: 14px;
  padding-left: 12px;
  color: var(--ink-soft);
}

.listing.featured {
  border: 3px double var(--ink);
  background: var(--paper-light);
  padding: 8px 10px;
  margin: 6px 0 10px;
}

.listing.featured .listing-line {
  flex-wrap: wrap;
}

.listing.featured .listing-loc {
  font-size: 14px;
  color: var(--ink-soft);
}

/* Without a location the address alone sits at the right, with no dots leading from nowhere. */
.listing.featured .listing-name + .leader {
  visibility: hidden;
}

.listing.featured .listing-name {
  flex-basis: 100%;
  max-width: none;
  white-space: normal;
  font-family: var(--black);
  font-weight: 400;
  font-size: 19px;
  text-transform: uppercase;
}

.listing-bio {
  margin: 6px 0 4px;
  font-style: italic;
}

.listing-links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 14px;
  font-weight: 600;
}

/* One icon size everywhere, relative to the adjacent text (1.2em). Inline holders (badge, tip) are exactly
   one line tall and center the icon in it, so the icon sits on the middle of the text line it belongs to. */
.icon {
  display: block;
  flex: none;
  width: 1.2em;
  height: 1.2em;
}

.badge,
button.tip {
  display: inline-flex;
  align-items: center;
  height: 1lh;
  vertical-align: top;
  flex: none;
}

.badge {
  cursor: help;
}

/* Badges sit at the end of a row, so their tooltip opens leftwards instead of past the column edge. */
button.tip.badge::after {
  left: auto;
  right: 0;
  transform: none;
}

/* Multi-line notices: the icon box is one line tall, so it centers on the first line of text. */
.warning .icon,
.notice .icon {
  height: 1lh;
}

/* Beats button.tip's hover colour, so a status keeps its colour while its tooltip is open. */
button.tip.badge.ok {
  color: var(--green);
}
button.tip.badge.bad {
  color: var(--red);
}
button.tip.badge.warn {
  color: var(--amber);
}
button.tip.badge.muted {
  color: var(--ink-soft);
}

.empty {
  border: 2px dashed var(--ink);
  padding: 28px;
  text-align: center;
  font-size: 18px;
}

/* ---------- other anchors (collapsed) ---------- */

.others {
  margin-top: 28px;
  overflow-x: auto;
}

.others summary {
  cursor: pointer;
}

.registry {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
}

.registry th {
  text-align: left;
  text-transform: uppercase;
  font-size: 12px;
  letter-spacing: 0.06em;
  border-bottom: 2px solid var(--rule);
  padding: 4px 8px 4px 0;
}

.registry td {
  border-bottom: 1px dotted var(--ink-soft);
  padding: 5px 8px 5px 0;
  vertical-align: middle;
}

.registry td a {
  font-family: var(--mono);
  font-size: 13px;
}

/* ---------- entry card ---------- */

.card {
  --card-pad-y: 22px;
  --card-pad-x: 22px;
  max-width: 760px;
  margin: 0 auto;
  border: 4px double var(--ink);
  background: var(--paper-light);
  padding: var(--card-pad-y) var(--card-pad-x);
}

/* Featured: a heavier frame and a solid band reaching the frame on three sides. */
.card.featured {
  border-width: 6px;
}

.card-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 16px;
  margin: calc(-1 * var(--card-pad-y)) calc(-1 * var(--card-pad-x)) var(--card-pad-y);
  padding: 9px var(--card-pad-x);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--black);
  font-size: 16px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.card-banner > span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.card-banner .icon {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

.card-banner-locked {
  font-family: var(--narrow);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  opacity: 0.85;
}

.back {
  display: inline-block;
  font-weight: 700;
  margin-bottom: 12px;
}

.card-cat {
  font-size: 13px;
  letter-spacing: 0.1em;
  font-weight: 700;
}

.card-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
}

.card-top .back {
  margin-bottom: 0;
}

/* Category, featured stamp and verdict; right-aligned, and still right-aligned when they wrap below. */
.card-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px 10px;
  margin-left: auto;
}

.card-name {
  font-family: var(--black);
  font-weight: 400;
  font-size: clamp(28px, 5vw, 40px);
  line-height: 1;
  margin: 18px 0 8px;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

/* The listing's status as a compact badge (a tip: the full sentence shows on hover or tap). */
button.tip.verdict {
  gap: 5px;
  height: auto;
  padding: 3px 8px;
  border: 2px solid currentColor;
  font-weight: 700;
  font-size: 14px;
  cursor: help;
}

/* Retry next to an unavailable verdict: icon only, as tall as the verdict (one text line + padding + border). */
button.tip.verdict.retry {
  min-height: calc(1lh + 10px);
  padding: 3px 5px;
  color: var(--ink);
  cursor: pointer;
}

button.tip.verdict.retry.busy .icon {
  animation: retry-spin 0.8s linear infinite;
}

@keyframes retry-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  button.tip.verdict.retry.busy .icon {
    animation: none;
  }
}

/* At the right edge, so the tooltip opens leftwards. */
button.tip.verdict::after {
  left: auto;
  right: 0;
  transform: none;
}

/* Beats button.tip's hover colour, like the status badges. */
button.tip.verdict.ok {
  color: var(--green);
}
button.tip.verdict.bad {
  color: var(--red);
}
button.tip.verdict.warn {
  color: var(--amber);
}
button.tip.verdict.muted {
  color: var(--ink-soft);
}

.warning,
.notice {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.warning {
  background: var(--ink);
  color: var(--paper);
  padding: 8px 12px;
  font-weight: 700;
}

/* Close under the name: it reads as the name's subtitle. */
.card-bio {
  font-size: 19px;
  font-style: italic;
  margin: 0 0 16px;
}

/* The location belongs to the description, so it sits close below it. */
.card-bio:has(+ .card-loc) {
  margin-bottom: 4px;
}

.card-loc {
  margin-top: 0;
}

/* A form's introduction, close under its title like a listing's description. */
.card-lead {
  margin: 0;
}

.card-links,
.card-files {
  list-style: none;
  padding: 0;
  margin: 16px 0;
}

.card-links li {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 0;
  font-size: 18px;
}

.link-label {
  font-weight: 700;
}

.card-links a {
  font-weight: 600;
  overflow-wrap: anywhere;
}

.link-blocked {
  text-decoration: line-through;
  color: var(--ink-soft);
}

.card-files li {
  padding: 2px 0;
}

.hash {
  color: var(--ink-soft);
}

.facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 6px 16px;
  border-top: 2px solid var(--rule);
  padding-top: 12px;
  margin: 20px 0 12px;
}

.facts dt {
  font-weight: 700;
  text-transform: uppercase;
  font-size: 13px;
  letter-spacing: 0.04em;
  padding-top: 2px;
}

.facts dd {
  margin: 0;
  min-width: 0;
}

.wrap {
  overflow-wrap: anywhere;
}

@media (max-width: 600px) {
  .facts {
    grid-template-columns: 1fr;
  }
  .facts dd {
    margin-bottom: 6px;
  }
}

.fine {
  font-size: 13px;
  color: var(--ink-soft);
}

/* ---------- advertise form ---------- */

.ad-form {
  display: grid;
  gap: 12px;
  margin-top: 16px;
}

.field {
  display: grid;
  gap: 4px;
  font-weight: 700;
}

/* Label on the left, "12 / 80" on the right. */
.field-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}

.field .count {
  font-weight: 400;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}

.field .count.full {
  color: var(--amber);
  font-weight: 700;
}

.field input,
.field select,
.field textarea {
  font: inherit;
  font-weight: 400;
  padding: 6px 8px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  width: 100%;
}

button,
.button {
  font-family: var(--black);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--ink);
  color: var(--paper);
  border: 0;
  padding: 10px 16px;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  justify-self: start;
}

button:hover,
.button:hover {
  background: var(--ink-soft);
}

/* Secondary actions (copy, explorer): outlined, smaller. */
/* No taller than a line of text, so a row with buttons keeps the height of the others. */
button.small,
.button.small {
  font-size: 12px;
  line-height: 1.2;
  padding: 3px 8px;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--ink);
}

button.small:hover,
.button.small:hover {
  background: var(--ink);
  color: var(--paper);
}

.result h3 {
  font-family: var(--black);
  font-weight: 400;
  text-transform: uppercase;
  font-size: 16px;
  margin: 22px 0 8px;
}

.result pre,
details.tech pre,
.extras-panel pre {
  font-family: var(--mono);
  font-size: 13px;
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 10px;
  overflow-x: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* What activating costs, read at a glance before the details. */
.ad-cost {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 14px;
  margin: 12px 0 16px;
  padding: 10px 12px;
  border: 2px solid var(--ink);
}

.ad-cost dt {
  font-weight: 700;
}

.ad-cost dd {
  margin: 0;
}

.result input[readonly] {
  background: transparent;
}

.account-check {
  margin: 6px 0 12px;
  font-size: 15px;
  color: var(--ink-soft);
}

.account-check.ok {
  color: var(--green);
  font-weight: 700;
}

.account-check.warn {
  color: var(--amber);
  font-weight: 700;
}

.account-check.bad {
  color: var(--red);
  font-weight: 700;
}

.ad-request-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin: 12px 0 6px;
}

.activation.ok {
  color: var(--green);
  font-weight: 700;
}

/* The buttons after "Activated" or "already live": their own row, side by side. */
.listing-actions {
  display: flex;
  gap: 6px;
  margin-top: 6px;
}

/* Right under step 1's line (an update with nothing to change): close to it, not a paragraph away. */
.result > .listing-actions {
  margin-top: -10px;
}

.activation.waiting::before {
  content: "";
  display: inline-block;
  width: 9px;
  height: 9px;
  margin-right: 8px;
  border-radius: 50%;
  background: currentColor;
  animation: skel-pulse 1.4s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .activation.waiting::before {
    animation: none;
  }
}

/* ---------- footer ---------- */

.colophon {
  width: 100%;
  max-width: 1200px;
  margin: 32px auto 0;
  padding: 14px 16px 28px;
  border-top: 3px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px 24px;
}

#stats {
  margin: 0;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 14px;
}

.colophon-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
}

/* The page's promise as a stamp, like the verdict on a listing card; the explanation is its tooltip. */
button.tip.seal {
  gap: 6px;
  height: auto;
  padding: 3px 9px;
  border: 2px solid currentColor;
  color: var(--green);
  font-weight: 700;
  font-size: 14px;
  cursor: help;
}

button.tip.seal:hover,
button.tip.seal.open {
  color: var(--green);
}

/* It sits at the left edge, so the tooltip opens rightwards. */
button.tip.seal::after {
  left: 0;
  transform: none;
}

/* Language and theme: one height, ink on paper (the masthead above is the inverse). */
.prefs {
  --pref-h: 32px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.lang-switch,
button.theme-toggle {
  height: var(--pref-h);
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--ink);
}

.lang-switch button {
  height: 100%;
  font-family: var(--narrow);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.06em;
  background: transparent;
  color: var(--ink);
  padding: 0 10px;
}

.lang-switch button[aria-pressed="true"] {
  background: var(--ink);
  color: var(--paper);
}

button.theme-toggle {
  width: var(--pref-h);
  justify-content: center;
  padding: 0;
  background: transparent;
  color: var(--ink);
}

button.theme-toggle:hover {
  background: var(--ink);
  color: var(--paper);
}

:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}

/* ---------- tooltips ---------- */

/* A help icon; its text comes from data-tip and shows on hover, keyboard focus or tap (.open). */
button.tip {
  position: relative;
  padding: 0 1px;
  border: 0;
  background: transparent;
  color: var(--ink-soft);
  font: inherit;
  letter-spacing: 0;
  text-transform: none;
}

button.tip:hover,
button.tip.open {
  background: transparent;
  color: var(--ink);
}

button.tip::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: 300px;
  padding: 8px 10px;
  background: var(--ink);
  color: var(--paper-light);
  font: 400 14px/1.35 var(--narrow);
  text-align: left;
  white-space: normal;
  z-index: 10;
  visibility: hidden;
  pointer-events: none;
}

button.tip:hover::after,
button.tip:focus-visible::after,
button.tip.open::after {
  visibility: visible;
}

/* On phones the text docks to the bottom of the screen instead of risking the edges. */
@media (max-width: 600px) {
  button.tip::after,
  button.tip.badge::after,
  button.tip.seal::after,
  button.tip.verdict::after {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom));
    transform: none;
    width: auto;
    max-width: none;
    padding: 12px 14px;
    font-size: 16px;
    border: 2px solid var(--paper);
    box-shadow: 0 6px 24px rgb(0 0 0 / 0.45);
  }
}

/* ---------- collapsed details ---------- */

details.tech,
details.how {
  margin-top: 18px;
  border-top: 1px dotted var(--ink-soft);
  padding-top: 8px;
}

details.tech > summary,
details.how > summary {
  cursor: pointer;
  font-weight: 700;
  font-size: 14px;
  color: var(--ink-soft);
}

/* The explanation reads as the answer to its question, right under it. */
details.how > p {
  margin: 4px 0 0;
}

/* Open, the summary is ruled off from its content like the listing card's panels. */
details.tech[open] > summary {
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--rule);
}

details.tech p {
  margin: 14px 0 6px;
}

/* The summary's own margin is the gap to whatever opens first, so every section opens alike. */
details.tech > summary + * {
  margin-top: 0;
}

/* ---------- listing card extras ---------- */

/* Toggles in one row under a dotted rule, styled like the summaries above; the open panel spans the card. */
.card-extras {
  margin-top: 18px;
  border-top: 1px dotted var(--ink-soft);
  padding-top: 8px;
}

.extras-bar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 24px;
}

button.extras-toggle {
  padding: 0;
  background: transparent;
  color: var(--ink-soft);
  font: 700 14px var(--narrow);
  letter-spacing: 0;
  text-transform: none;
}

button.extras-toggle::before {
  content: "▸";
  margin-right: 6px;
}

button.extras-toggle[aria-expanded="true"]::before {
  content: "▾";
}

button.extras-toggle:hover,
button.extras-toggle[aria-expanded="true"] {
  background: transparent;
  color: var(--ink);
}

/* Every open panel is set off from the toggles by the same rule, whatever it holds. */
.extras-panel {
  margin-top: 12px;
  border-top: 2px solid var(--rule);
  padding-top: 12px;
}

.extras-panel .facts {
  margin-top: 0;
  border-top: 0;
  padding-top: 0;
}

/* Update and remove side by side; stacked on phones. */
.owner-actions {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 16px 24px;
  align-items: start;
}

.owner-actions .button {
  white-space: nowrap;
}

.owner-actions p {
  margin: 0 0 10px;
}

.owner-actions .fine {
  margin: 8px 0 0;
}

@media (max-width: 600px) {
  .owner-actions {
    grid-template-columns: 1fr;
  }
}

/* Listed since and account: leader rows like the links, a little smaller; the copy and explorer
   buttons move under the address when the row is too narrow. */
/* Set off by a dotted rule rather than a gap, but only when links or files come right before. */
.card-links:not(.card-facts) + .card-facts,
.card-files + .card-facts {
  margin-top: -6px;
  padding-top: 8px;
  border-top: 1px dotted var(--ink-soft);
}

.card-facts li {
  align-items: center;
  flex-wrap: wrap;
  font-size: 16px;
}

/* Centred rows (the buttons are taller than the text), so the dots drop to the text's baseline. */
.card-facts .leader {
  transform: translateY(5px);
}

.card-facts .link-label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.row-actions {
  display: flex;
  gap: 6px;
  margin-left: auto;
}

/* On phones the buttons always take their own line under the address, rather than only when they overflow. */
@media (max-width: 600px) {
  .row-actions {
    flex-basis: 100%;
    justify-content: flex-end;
    margin-top: 2px;
  }
}

/* Same mark as the masthead's TESTNET: a ruled box of small capitals after the category. */
.stamp {
  display: inline-block;
  padding: 2px 5px 1px;
  border: 2px solid currentColor;
  font-size: 0.85em;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1;
  vertical-align: 1px;
}

.card-cat a {
  text-decoration: none;
}

.card-cat a:hover {
  text-decoration: underline;
}

/* ---------- advertise extras ---------- */

.link-rows {
  display: grid;
  gap: 6px;
}

.link-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: 6px;
}

.link-row input {
  font: inherit;
  font-weight: 400;
  padding: 6px 8px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  width: 100%;
}

.link-row input:invalid:not(:placeholder-shown) {
  border-color: var(--red);
}

button.link-add {
  background: transparent;
  color: var(--ink);
  font: 700 14px var(--narrow);
  text-transform: none;
  letter-spacing: 0;
  padding: 4px 0;
  text-decoration: underline;
}

button.link-add:hover {
  background: transparent;
  color: var(--ink-soft);
}

.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
}

.check > span {
  flex: 1;
}

.check label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.upload-status {
  font-weight: 700;
}

.upload-status.ok {
  color: var(--green);
}

.upload-status.bad {
  color: var(--red);
}

.notice {
  border-left: 4px solid var(--amber);
  padding: 4px 0 4px 10px;
  font-size: 15px;
}

/* Placeholders in the page's soft ink instead of the browser's grey; italic so they never read as typed text. */
::placeholder {
  color: var(--ink-soft);
  font-style: italic;
  opacity: 1;
}

/* ---------- checkbox ---------- */

/* Drawn in the page's ink instead of the browser default; the tick is a rotated border (no images under the CSP). */
input[type="checkbox"] {
  appearance: none;
  flex: none;
  display: inline-grid;
  place-items: center;
  font-size: 16px;
  width: 22px;
  height: 22px;
  margin: 0;
  border: 2px solid var(--ink);
  background: var(--paper);
  cursor: pointer;
}

input[type="checkbox"]::before {
  content: "";
  width: 0.32em;
  height: 0.62em;
  margin-top: -0.12em;
  border: solid var(--paper);
  border-width: 0 0.16em 0.16em 0;
  transform: rotate(45deg);
  visibility: hidden;
}

input[type="checkbox"]:checked {
  background: var(--ink);
}

input[type="checkbox"]:checked::before {
  visibility: visible;
}

input[type="checkbox"]:hover:not(:checked) {
  background: var(--paper-light);
}

/* ---------- phones ---------- */

/* Help icons and badges are small; an invisible pad makes them a comfortable finger target. */
button.tip::before {
  content: "";
  position: absolute;
  inset: -10px;
}

.cat-jump {
  display: none;
}

@media (max-width: 600px) {
  .page {
    padding: 12px;
  }

  /* Sticky category row; it scrolls sideways when the categories do not fit. */
  .cat-jump {
    display: flex;
    gap: 6px;
    position: sticky;
    top: 0;
    z-index: 5;
    margin: -10px -12px 12px;
    padding: 8px 12px;
    overflow-x: auto;
    scrollbar-width: none;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
  }

  .cat-jump::-webkit-scrollbar {
    display: none;
  }

  .cat-jump button {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 36px;
    padding: 0 12px;
    font-family: var(--narrow);
    font-weight: 700;
    font-size: 14px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    background: var(--paper-light);
    color: var(--ink);
    border: 2px solid var(--ink);
    cursor: pointer;
  }

  .cat-jump .count {
    font-family: var(--mono);
    font-size: 12px;
    color: var(--ink-soft);
  }

  .cat-jump button[aria-current] {
    background: var(--ink);
    color: var(--paper);
  }

  .cat-jump button[aria-current] .count {
    color: inherit;
  }

  /* Leave room for the sticky row when jumping to a category. */
  .category {
    scroll-margin-top: 64px;
  }

  .masthead-inner {
    padding: 14px 12px 10px;
    gap: 10px;
  }

  .masthead-nav {
    --nav-h: 40px;
    width: 100%;
    gap: 8px;
  }

  /* Two halves of the full width; the directory link gets an outline so both read as buttons. */
  .masthead-nav a {
    flex: 1;
    justify-content: center;
    padding: 0 8px;
  }

  .masthead-nav a:not(.cta) {
    border-color: var(--paper);
  }

  .prefs {
    --pref-h: 40px;
  }

  .lang-switch button {
    padding: 0 12px;
  }

  /* 16px keeps iOS from zooming into the page when a field is focused. */
  .search input,
  .field input,
  .field select,
  .field textarea,
  .link-row input {
    font-size: 16px;
  }

  .search input {
    padding: 10px 12px;
  }

  .field input,
  .field select,
  .link-row input {
    min-height: 44px;
  }

  /* Taller rows: easier to hit with a thumb, and to scan. */
  .listing:not(.featured) {
    padding: 9px 0;
    border-bottom: 1px dotted var(--ink-soft);
  }

  .listing.featured {
    margin: 8px 0;
  }

  .listing-name {
    max-width: 62%;
  }

  .card {
    --card-pad-y: 18px;
    --card-pad-x: 14px;
    border-width: 3px;
  }

  .card.featured {
    border-width: 5px;
  }

  .card-name {
    overflow-wrap: anywhere;
  }

  button[type="submit"],
  .result .button {
    width: 100%;
    min-height: 48px;
    text-align: center;
  }

  .link-row {
    grid-template-columns: 1fr;
    gap: 4px;
    padding-bottom: 8px;
    border-bottom: 1px dotted var(--ink-soft);
  }

  /* Other records: each row becomes a two-line entry instead of a cramped four-column table. */
  /* Stacked rows fit the width, so no scroller (it would also catch the badges' invisible touch pads). */
  .others {
    overflow-x: visible;
  }

  .registry,
  .registry tbody {
    display: block;
  }

  .registry thead {
    display: none;
  }

  .registry tr {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "account status"
      "what since";
    gap: 2px 12px;
    padding: 8px 0;
    border-bottom: 1px dotted var(--ink-soft);
  }

  .registry td {
    border: 0;
    padding: 0;
  }

  .registry td:nth-child(1) {
    grid-area: account;
  }

  .registry td:nth-child(2) {
    grid-area: what;
  }

  .registry td:nth-child(3) {
    grid-area: status;
    justify-self: end;
  }

  .registry td:nth-child(4) {
    grid-area: since;
    justify-self: end;
    color: var(--ink-soft);
    font-size: 13px;
  }
}

/* ---------- loading skeleton ---------- */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Ink at low opacity, so it reads right on every palette and theme. */
.skel {
  display: block;
  height: 0.8em;
  margin: 6px 0;
  background: var(--ink);
  opacity: 0.12;
  animation: skel-pulse 1.4s ease-in-out infinite;
}

.skel.on-ink {
  background: var(--paper);
  opacity: 0.35;
  margin: 3px 0;
}

.skel.tall {
  height: 1.1em;
}

.skel.title {
  height: 0.85em;
  margin: 0;
}

.skel.w-badge {
  width: 110px;
  height: 30px;
  margin: 0;
}

.w-20 { width: 20%; }
.w-25 { width: 25%; }
.w-30 { width: 30%; }
.w-40 { width: 40%; }
.w-45 { width: 45%; }
.w-55 { width: 55%; }
.w-60 { width: 60%; }
.w-70 { width: 70%; }
.w-80 { width: 80%; }
.w-90 { width: 90%; }

/* A name on the left, an address on the right: the shape of a directory row. */
.skel-line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0;
}

.skel-head {
  padding: 4px 8px;
}

.skel-rows {
  margin-top: 18px;
}

@keyframes skel-pulse {
  50% {
    opacity: 0.05;
  }
}

@media (prefers-reduced-motion: reduce) {
  .skel {
    animation: none;
  }
}

/* No empty slot before the seal while the count is still unknown. */
#stats:empty {
  display: none;
}
