/* Decenter portal styles.
   No build step, no external fonts, no JS dependency. This file is embedded in
   the node binary and must also work when the static export is dropped into a
   bare Apache webroot, so everything here is plain CSS. */

:root {
  --bg: #08090b;
  --bg-raise: #0f1116;
  --bg-sunk: #0b0d11;
  --fg: #edf0f4;
  --mut: #8b96a5;
  --dim: #5f6875;
  --line: #1c2028;
  --line-lit: #2a3038;
  --acc: #7fb2f0;
  --acc-dim: #4a7ab8;
  --ok: #56d191;
  --warn: #e8b04b;
  --no: #f0736b;
  --mono: ui-monospace, SFMono-Regular, Menlo, "Cascadia Mono", monospace;

  /* Easing. Never ease-in on UI: it starts slow, delaying the exact moment
     the user is watching most closely, so the same duration reads as slower. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 100%/1.6 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 60rem; margin: 0 auto; padding: 0 1.5rem; }
.narrow { max-width: 46rem; }

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

/* Tracking is size-specific. Large display text reads too loose as it grows so
   it tightens; small caps-y labels need more room, not less. One
   letter-spacing value for everything would be wrong somewhere. */
h1 {
  font-size: clamp(2.1rem, 6vw, 3.6rem);
  line-height: 1.05;
  letter-spacing: -0.035em;
  font-weight: 620;
  margin: 0 0 1rem;
}
h2 {
  font-size: clamp(1.15rem, 2.4vw, 1.45rem);
  line-height: 1.22;
  letter-spacing: -0.02em;
  font-weight: 600;
  margin: 0 0 0.7rem;
}
h3 {
  font-size: 0.78rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--mut);
  font-weight: 600;
  margin: 1.1rem 0 0.5rem;
}
p { margin: 0.7rem 0; }
.lede { font-size: clamp(1.02rem, 2vw, 1.18rem); line-height: 1.55; color: var(--mut); }

/* Nav hover happens tens of times a day, so it changes colour and does not
   move. A transform here would be motion nobody asked for. */
nav.top {
  border-bottom: 1px solid var(--line);
  background: rgba(8, 9, 11, 0.88);
  position: sticky; top: 0; z-index: 10;
  backdrop-filter: blur(10px);
}
nav.top .wrap { display: flex; flex-wrap: wrap; align-items: center; gap: 0.2rem 1.15rem; padding-top: 0.8rem; padding-bottom: 0.8rem; }
nav.top .brand { font-weight: 650; letter-spacing: -0.02em; color: var(--fg); text-decoration: none; margin-right: 0.4rem; }
nav.top a { color: var(--mut); text-decoration: none; font-size: 0.88rem; transition: color 120ms var(--ease-out); }
nav.top a:hover, nav.top a[aria-current] { color: var(--fg); }

header.hero { padding: 4.5rem 0 3rem; border-bottom: 1px solid var(--line); }
header.hero .tag { color: var(--mut); margin: 0; font-size: clamp(1rem, 2.2vw, 1.15rem); max-width: 42rem; line-height: 1.55; }
main { padding: 2.5rem 0 4rem; }

section { margin-bottom: 1.1rem; }
.block { margin-bottom: 3.25rem; }

.card {
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 1.35rem;
  margin-bottom: 1.1rem;
}
.card > :first-child { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }

ul, ol { margin: 0.6rem 0; padding-left: 1.15rem; }
li { margin: 0.35rem 0; }

.grid { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.grid-2 { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); }

blockquote {
  margin: 1.4rem 0;
  padding: 1rem 1.25rem;
  border-left: 2px solid var(--acc-dim);
  background: var(--bg-raise);
  border-radius: 0 8px 8px 0;
  color: #d3e2f3;
}
blockquote p { margin: 0.3rem 0; }
blockquote p:first-child { margin-top: 0; }
blockquote p:last-child { margin-bottom: 0; }

.mono { font-family: var(--mono); font-size: 0.8rem; word-break: break-word; color: var(--mut); line-height: 1.55; }
.mono b { color: var(--fg); font-weight: 600; }

pre {
  font-family: var(--mono);
  font-size: 0.78rem;
  line-height: 1.6;
  overflow-x: auto;
  background: var(--bg-sunk);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  color: #c3cedb;
}

table { width: 100%; border-collapse: collapse; font-size: 0.9rem; margin: 0.7rem 0; }
th, td { text-align: left; padding: 0.55rem 0.65rem; border-bottom: 1px solid var(--line); vertical-align: top; }
th { color: var(--mut); font-weight: 600; font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.05em; }
td.n { font-family: var(--mono); text-align: right; white-space: nowrap; }

.pill { display: inline-block; font-size: 0.7rem; font-family: var(--mono); padding: 0.15rem 0.5rem; border-radius: 999px; border: 1px solid var(--line-lit); color: var(--mut); white-space: nowrap; }
.pill.ok { color: var(--ok); border-color: #1d4d36; }
.pill.no { color: var(--no); border-color: #5c2724; }
.pill.warn { color: var(--warn); border-color: #5c4519; }

.big { font-family: var(--mono); font-size: 1.65rem; color: var(--fg); line-height: 1.1; letter-spacing: -0.01em; }
.stat { background: var(--bg-sunk); border: 1px solid var(--line); border-radius: 10px; padding: 0.85rem 0.95rem; }
.stat .k { color: var(--mut); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.35rem; }

.warnbox { border-color: #5c4519; background: #17120a; }
.warnbox h2 { color: var(--warn); }

video { background: #000; border-radius: 10px; max-width: 100%; display: block; }

/* Buttons must feel responsive to press. */
.btn {
  display: inline-block;
  padding: 0.62rem 1.1rem;
  border-radius: 8px;
  border: 1px solid var(--line-lit);
  background: var(--bg-raise);
  color: var(--fg);
  font-size: 0.92rem;
  font-weight: 550;
  text-decoration: none;
  transition: border-color 140ms var(--ease-out),
              background-color 140ms var(--ease-out),
              transform 120ms var(--ease-out);
}
.btn:hover { border-color: #3d4652; background: #151922; color: var(--fg); }
.btn:active { transform: scale(0.97); }
.btn-primary { background: var(--acc); border-color: var(--acc); color: #06131f; }
.btn-primary:hover { background: #9cc4f5; border-color: #9cc4f5; color: #06131f; }

.row { display: flex; flex-wrap: wrap; gap: 0.7rem; align-items: center; }

/* The claim/counter pair used on the landing page. */
.ledger { display: grid; gap: 0.75rem; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); margin: 1rem 0 0; }
.ledger .stat .v { font-family: var(--mono); font-size: 1.5rem; line-height: 1.15; }
.ledger .stat .v.up { color: var(--ok); }
.ledger .stat .v.flat { color: var(--warn); }
.ledger .stat .n { font-size: 0.74rem; color: var(--dim); margin-top: 0.3rem; line-height: 1.45; }

/* Small screens. Long unbroken strings and multi-column grids are the two
   things that push a page wider than the viewport, so both are handled here
   rather than left to chance. */
@media (max-width: 30rem) {
  .wrap { padding: 0 1.1rem; }
  .card { padding: 1.1rem; }
  .ledger { grid-template-columns: 1fr; }
  header.hero { padding: 3rem 0 2.25rem; }
  h1 { font-size: clamp(1.85rem, 8.5vw, 2.4rem); }
  .row .btn { flex: 1 1 auto; text-align: center; }
}

/* Nothing may exceed the viewport. A long hash or identifier in prose is the
   usual culprit and it should wrap, not scroll the document. */
body { overflow-x: hidden; }
h1, h2, p, li { overflow-wrap: anywhere; }

/* Identifiers must NOT break mid-word. A hash split across two lines is
   unreadable and invites transcription errors, so the table scrolls instead.
   This reverses an earlier blanket rule that treated every cell as prose. */
pre { overflow-wrap: normal; }
td .mono, td b, code { overflow-wrap: normal; }
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.scroll-x table { min-width: 30rem; }

footer { border-top: 1px solid var(--line); color: var(--dim); font-size: 0.86rem; padding: 2rem 0 3.5rem; }
footer p { margin: 0.35rem 0; }
footer a { color: var(--mut); }
.sep { color: var(--line-lit); }

/* Entrance motion only. A landing page is a rare, first-time view, the one
   frequency band where a little delight is earned. It plays once and never in
   response to interaction. */
@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.rise { animation: rise 520ms var(--ease-out) both; }
.d1 { animation-delay: 70ms; }
.d2 { animation-delay: 140ms; }
.d3 { animation-delay: 210ms; }

/* Reduced motion means fewer and gentler animations, not zero. Position change
   is removed; nothing is left mid-fade. */
@media (prefers-reduced-motion: reduce) {
  .rise { animation: none; opacity: 1; transform: none; }
  *, *::before, *::after {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }
}
