/* CCXT Router — design system.
   Follows the CCXT docs site: neutral monochrome base, mono for anything numeric or code-like,
   and a palette that follows the system theme rather than imposing one. Colour is reserved for
   syntax and for status; nothing here is decorative. */

:root {
    --bg: #ffffff;
    --bg-2: #fafafa;
    --card: #ffffff;
    --fg: #0a0a0a;
    --muted: #6b7280;
    --border: #e5e7eb;
    --border-strong: #d1d5db;
    --accent: #0a0a0a;
    --accent-fg: #ffffff;
    --ok: hsl(150 55% 34%);
    --warn: hsl(35 80% 42%);
    --bad: hsl(0 65% 45%);
    /* Same syntax palette as the CCXT docs hero, so code reads identically across the two sites. */
    --c-key: hsl(265 60% 50%);
    --c-fn: hsl(35 80% 42%);
    --c-str: hsl(150 55% 34%);
    --c-com: hsl(240 4% 55%);
    --c-num: hsl(20 75% 45%);
    --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
    --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;
    --radius: 8px;
    --w: 1080px;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #0a0a0a;
        --bg-2: #111113;
        --card: #141416;
        --fg: #fafafa;
        --muted: #9096a2;
        --border: #26262b;
        --border-strong: #3a3a42;
        --accent: #fafafa;
        --accent-fg: #0a0a0a;
        --ok: hsl(150 45% 60%);
        --warn: hsl(35 90% 66%);
        --bad: hsl(0 70% 68%);
        --c-key: hsl(265 70% 75%);
        --c-fn: hsl(35 90% 66%);
        --c-str: hsl(150 45% 60%);
        --c-com: hsl(240 5% 50%);
        --c-num: hsl(20 85% 68%);
    }
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--fg);
    font-family: var(--sans);
    font-size: 15px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

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

.wrap { max-width: var(--w); margin: 0 auto; padding: 0 24px; }

/* ---- header ------------------------------------------------------------ */

header.site {
    border-bottom: 1px solid var(--border);
    position: sticky; top: 0; z-index: 20;
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: saturate(160%) blur(8px);
}
header.site .inner { display: flex; align-items: center; gap: 20px; height: 56px; }
.brand { display: flex; align-items: center; gap: 10px; font-weight: 620; text-decoration: none; letter-spacing: -0.01em; }
.brand img { width: 22px; height: 22px; display: block; }
.brand .sep { color: var(--muted); font-weight: 400; }
.brand .sub { color: var(--muted); font-weight: 500; }
nav.site { display: flex; gap: 18px; margin-left: auto; align-items: center; }
nav.site a { text-decoration: none; color: var(--muted); font-size: 14px; }
nav.site a:hover, nav.site a[aria-current] { color: var(--fg); }

/* ---- buttons ----------------------------------------------------------- */

.btn {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--accent); color: var(--accent-fg);
    border: 1px solid var(--accent); border-radius: var(--radius);
    padding: 9px 16px; font-size: 14px; font-weight: 550;
    text-decoration: none; cursor: pointer; font-family: inherit;
}
.btn:hover { opacity: 0.88; }
.btn.ghost { background: transparent; color: var(--fg); border-color: var(--border-strong); }
.btn.ghost:hover { background: var(--bg-2); opacity: 1; }
.btn.sm { padding: 5px 10px; font-size: 13px; }
.btn.danger { background: transparent; color: var(--bad); border-color: var(--bad); }

/* ---- hero -------------------------------------------------------------- */

.hero { padding: 72px 0 56px; border-bottom: 1px solid var(--border); }
.hero h1 {
    font-size: clamp(30px, 4.6vw, 46px); line-height: 1.12; margin: 0 0 16px;
    letter-spacing: -0.025em; font-weight: 640; max-width: 18ch;
}
.hero .lede { font-size: 17px; color: var(--muted); max-width: 62ch; margin: 0 0 28px; }
.hero .cta { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.hero .note { color: var(--muted); font-size: 13px; margin-top: 14px; }

/* ---- generic sections -------------------------------------------------- */

section.band { padding: 56px 0; border-bottom: 1px solid var(--border); }
section.band h2 { font-size: 22px; margin: 0 0 8px; letter-spacing: -0.02em; font-weight: 620; }
section.band .sub { color: var(--muted); margin: 0 0 28px; max-width: 66ch; }

.grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.card {
    border: 1px solid var(--border); border-radius: var(--radius);
    padding: 18px; background: var(--card);
}
.card h3 { margin: 0 0 6px; font-size: 15px; font-weight: 600; }
.card p { margin: 0; color: var(--muted); font-size: 14px; }
.card .stat { font-family: var(--mono); font-size: 22px; font-weight: 600; display: block; margin-bottom: 2px; }

/* ---- code -------------------------------------------------------------- */

pre.code {
    background: var(--bg-2); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 14px 16px; overflow-x: auto; margin: 14px 0;
    font-family: var(--mono); font-size: 13px; line-height: 1.55;
}
pre.code code { font-family: inherit; }
code { font-family: var(--mono); font-size: 0.92em; background: var(--bg-2); padding: 1px 5px; border-radius: 4px; }
pre.code code { background: none; padding: 0; }
.tok-key { color: var(--c-key); }
.tok-str { color: var(--c-str); }
.tok-num { color: var(--c-num); }
.tok-com { color: var(--c-com); }
.tok-fn  { color: var(--c-fn); }

/* ---- tables ------------------------------------------------------------ */

.tbl { width: 100%; border-collapse: collapse; margin: 14px 0; font-size: 14px; }
.tbl th, .tbl td { text-align: left; padding: 9px 12px; border-bottom: 1px solid var(--border); vertical-align: top; }
.tbl th { font-weight: 600; color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; }
.tbl td code { white-space: nowrap; }
.tbl tbody tr:hover { background: var(--bg-2); }
.num { font-family: var(--mono); text-align: right; font-variant-numeric: tabular-nums; }

/* ---- callouts ---------------------------------------------------------- */

.callout {
    border: 1px solid var(--border); border-left: 3px solid var(--muted);
    background: var(--bg-2); border-radius: 0 var(--radius) var(--radius) 0;
    padding: 12px 16px; margin: 16px 0; font-size: 14px;
}
.callout.warn { border-left-color: var(--warn); }
.callout p:first-child { margin-top: 0; }
.callout p:last-child { margin-bottom: 0; }

/* ---- docs layout ------------------------------------------------------- */

.docs { display: grid; grid-template-columns: 210px 1fr; gap: 44px; padding: 36px 0 80px; align-items: start; }
.docs aside { position: sticky; top: 80px; font-size: 14px; }
.docs aside .grp { margin-bottom: 20px; }
.docs aside .grp-title { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin-bottom: 8px; font-weight: 600; }
.docs aside a { display: block; padding: 4px 0; color: var(--muted); text-decoration: none; }
.docs aside a:hover, .docs aside a[aria-current] { color: var(--fg); }
.doc-section { margin-bottom: 40px; scroll-margin-top: 76px; }
.doc-section h2 { font-size: 20px; margin: 0 0 10px; letter-spacing: -0.02em; }
.doc-section h3 { font-size: 15px; margin: 22px 0 6px; }
.doc-body { min-width: 0; }
@media (max-width: 860px) {
    .docs { grid-template-columns: 1fr; gap: 20px; }
    .docs aside { position: static; }
}

/* ---- forms ------------------------------------------------------------- */

.auth { max-width: 380px; margin: 64px auto; }
.auth h1 { font-size: 22px; margin: 0 0 6px; letter-spacing: -0.02em; }
.auth .sub { color: var(--muted); margin: 0 0 24px; font-size: 14px; }
.field { margin-bottom: 14px; }
.field label { display: block; font-size: 13px; margin-bottom: 5px; font-weight: 550; }
.field input {
    width: 100%; padding: 9px 12px; font-size: 14px; font-family: inherit;
    background: var(--card); color: var(--fg);
    border: 1px solid var(--border-strong); border-radius: var(--radius);
}
.field input:focus { outline: 2px solid var(--fg); outline-offset: -1px; border-color: transparent; }
.field .hint { font-size: 12px; color: var(--muted); margin-top: 4px; }
.err { color: var(--bad); font-size: 14px; margin-bottom: 14px; }
.ok-msg { color: var(--ok); font-size: 14px; margin-bottom: 14px; }

/* ---- dashboard --------------------------------------------------------- */

.dash { padding: 32px 0 80px; }
.dash h1 { font-size: 22px; margin: 0 0 4px; letter-spacing: -0.02em; }
.dash .sub { color: var(--muted); margin: 0 0 26px; font-size: 14px; }
.row { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 14px; }
.keyval { font-family: var(--mono); font-size: 13px; }
.pill { font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--border-strong); color: var(--muted); }
.pill.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.pill.dead { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }

/* The one-time key reveal. Deliberately loud: it is shown exactly once and cannot be recovered. */
.reveal {
    border: 1px solid var(--warn); border-radius: var(--radius);
    background: color-mix(in srgb, var(--warn) 7%, var(--card));
    padding: 16px; margin-bottom: 22px;
}
.reveal .k {
    font-family: var(--mono); font-size: 14px; word-break: break-all;
    background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
    padding: 10px 12px; margin: 10px 0; display: block;
}

.spark { display: flex; align-items: flex-end; gap: 2px; height: 34px; }
.spark i { flex: 1; background: var(--muted); min-height: 1px; border-radius: 1px; display: block; }

footer.site { border-top: 1px solid var(--border); padding: 28px 0; color: var(--muted); font-size: 13px; }
footer.site a { color: var(--muted); }
.beta {
    display: inline-block; font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
    border: 1px solid var(--border-strong); color: var(--muted);
    border-radius: 4px; padding: 1px 6px; vertical-align: middle; margin-left: 2px;
}

/* ---- copy button + onboarding steps ------------------------------------ */

.copy {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; flex: 0 0 30px;
    background: var(--card); color: var(--muted);
    border: 1px solid var(--border-strong); border-radius: 6px;
    cursor: pointer; padding: 0; position: relative;
}
.copy:hover { color: var(--fg); border-color: var(--fg); }
.copy svg { width: 15px; height: 15px; display: block; }
.copy .tick { display: none; }
.copy.copied { color: var(--ok); border-color: var(--ok); }
.copy.copied .clip { display: none; }
.copy.copied .tick { display: block; }
/* A confirmation the user can actually see, since the icon change alone is easy to miss. */
.copy.copied::after {
    content: "Copied"; position: absolute; top: -26px; left: 50%; transform: translateX(-50%);
    background: var(--fg); color: var(--bg); font-size: 11px; padding: 2px 7px;
    border-radius: 4px; white-space: nowrap;
}

.copyrow { display: flex; gap: 8px; align-items: stretch; margin: 8px 0; }
.copyrow > .val {
    flex: 1; min-width: 0; font-family: var(--mono); font-size: 13px;
    background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
    padding: 9px 12px; overflow-x: auto; white-space: pre; line-height: 1.5;
}
.copyrow > .val.wrap { white-space: pre-wrap; word-break: break-all; }

ol.steps { list-style: none; counter-reset: step; padding: 0; margin: 0; }
ol.steps > li { counter-increment: step; position: relative; padding-left: 34px; margin-bottom: 22px; }
ol.steps > li::before {
    content: counter(step); position: absolute; left: 0; top: 0;
    width: 22px; height: 22px; border-radius: 999px;
    background: var(--accent); color: var(--accent-fg);
    font-size: 12px; font-weight: 620; font-family: var(--mono);
    display: flex; align-items: center; justify-content: center;
}
ol.steps > li > h4 { margin: 1px 0 4px; font-size: 14px; font-weight: 600; }
ol.steps > li > p { margin: 0 0 6px; color: var(--muted); font-size: 13px; }
ol.steps > li:last-child { margin-bottom: 0; }

.linkrow { display: flex; gap: 16px; flex-wrap: wrap; font-size: 14px; margin-top: 4px; }
.linkrow a { display: inline-flex; align-items: center; gap: 6px; }
.linkrow svg { width: 14px; height: 14px; opacity: 0.6; }

/* =========================================================================
   Hero animation — the fee-adjusted split.
   Animates the one thing that is genuinely counter-intuitive about the router:
   fee-adjusting each venue BEFORE comparing them reorders which venue is best.
   The cheapest raw price here is the most expensive real one. Everything is CSS
   keyframes on a fixed loop; no JS, no build step, and the whole thing collapses
   to its final frame under prefers-reduced-motion.
   ========================================================================= */

.rt { --row-h: 34px; --dur: 13s; }
.rt-card {
    border: 1px solid var(--border); border-radius: 10px; background: var(--card);
    overflow: hidden; box-shadow: 0 1px 2px rgba(0,0,0,.04);
}
.rt-head {
    display: flex; align-items: center; gap: 10px; padding: 9px 14px;
    border-bottom: 1px solid var(--border); background: var(--bg-2);
}
.rt-dots { display: flex; gap: 5px; }
.rt-dots i { width: 8px; height: 8px; border-radius: 999px; background: var(--border-strong); display: block; }
.rt-req { font-family: var(--mono); font-size: 12px; color: var(--muted); }
.rt-req b { color: var(--fg); font-weight: 500; }
.rt-body { padding: 12px 14px 14px; }

.rt-cols {
    display: grid; grid-template-columns: 96px 1fr 84px 64px 92px;
    gap: 10px; align-items: center;
    font-size: 11px; color: var(--muted); text-transform: uppercase;
    letter-spacing: .05em; padding: 0 2px 8px;
}
.rt-cols .c-fee, .rt-cols .c-eff { opacity: 0; animation: rt-fade-in var(--dur) linear infinite; }
.rt-cols .c-eff { animation-name: rt-fade-in-late; }

.rt-rows { position: relative; height: calc(var(--row-h) * 4); }
.rt-row {
    position: absolute; left: 0; right: 0; height: var(--row-h);
    display: grid; grid-template-columns: 96px 1fr 84px 64px 92px;
    gap: 10px; align-items: center; padding: 0 2px;
    font-family: var(--mono); font-size: 13px;
    border-radius: 6px;
}
.rt-venue { color: var(--fg); }
.rt-bar { height: 6px; border-radius: 999px; background: var(--border); position: relative; overflow: hidden; }
.rt-bar i {
    position: absolute; inset: 0 100% 0 0; background: var(--muted); border-radius: 999px;
    animation: var(--dur) linear infinite;
}
.rt-raw { text-align: right; font-variant-numeric: tabular-nums; }
.rt-fee { text-align: right; color: var(--warn); opacity: 0; animation: rt-fade-in var(--dur) linear infinite; }
.rt-eff { text-align: right; font-variant-numeric: tabular-nums; opacity: 0; animation: rt-fade-in-late var(--dur) linear infinite; }

/* Each row travels from its raw-price rank to its fee-adjusted rank. okx has the
   cheapest raw price and the dearest real one, which is the entire point. */
.rt-row.r-okx     { animation: rt-move-okx     var(--dur) cubic-bezier(.65,0,.35,1) infinite; }
.rt-row.r-binance { animation: rt-move-binance var(--dur) cubic-bezier(.65,0,.35,1) infinite; }
.rt-row.r-kucoin  { animation: rt-move-kucoin  var(--dur) cubic-bezier(.65,0,.35,1) infinite; }
.rt-row.r-bybit   { animation: rt-move-bybit   var(--dur) cubic-bezier(.65,0,.35,1) infinite; }

@keyframes rt-move-okx {
    0%,32% { transform: translateY(0); }
    44%,100% { transform: translateY(calc(var(--row-h) * 3)); }
}
@keyframes rt-move-binance {
    0%,32% { transform: translateY(var(--row-h)); }
    44%,100% { transform: translateY(var(--row-h)); }
}
@keyframes rt-move-kucoin {
    0%,32% { transform: translateY(calc(var(--row-h) * 2)); }
    44%,100% { transform: translateY(0); }
}
@keyframes rt-move-bybit {
    0%,32% { transform: translateY(calc(var(--row-h) * 3)); }
    44%,100% { transform: translateY(calc(var(--row-h) * 2)); }
}

/* The two venues that actually get filled, once the ordering has settled. */
.rt-bar i.fill-62 { animation-name: rt-fill-62; }
.rt-bar i.fill-38 { animation-name: rt-fill-38; }
.rt-bar i.fill-0  { animation-name: rt-fill-0; }
@keyframes rt-fill-62 {
    0%,52% { inset: 0 100% 0 0; background: var(--muted); }
    66%,100% { inset: 0 38% 0 0; background: var(--ok); }
}
@keyframes rt-fill-38 {
    0%,52% { inset: 0 100% 0 0; background: var(--muted); }
    66%,100% { inset: 0 62% 0 0; background: var(--ok); }
}
@keyframes rt-fill-0 { 0%,100% { inset: 0 100% 0 0; } }

@keyframes rt-fade-in      { 0%,14% { opacity: 0 } 24%,100% { opacity: 1 } }
@keyframes rt-fade-in-late { 0%,26% { opacity: 0 } 36%,100% { opacity: 1 } }

.rt-out {
    margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--border);
    display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: baseline;
    font-family: var(--mono); font-size: 13px;
    opacity: 0; animation: rt-fade-in-out var(--dur) linear infinite;
}
@keyframes rt-fade-in-out { 0%,64% { opacity: 0 } 74%,100% { opacity: 1 } }
.rt-out .lbl { color: var(--muted); font-size: 12px; }
.rt-out .win { color: var(--ok); }

.rt-steps { display: flex; gap: 6px; margin-top: 12px; flex-wrap: wrap; }
.rt-step {
    font-size: 11px; color: var(--muted); border: 1px solid var(--border);
    border-radius: 999px; padding: 2px 9px; background: var(--card);
    animation: var(--dur) linear infinite;
}
.rt-step.s1 { animation-name: rt-lit-1 }
.rt-step.s2 { animation-name: rt-lit-2 }
.rt-step.s3 { animation-name: rt-lit-3 }
.rt-step.s4 { animation-name: rt-lit-4 }
@keyframes rt-lit-1 { 0%,12% { color: var(--fg); border-color: var(--fg) } 16%,100% { } }
@keyframes rt-lit-2 { 0%,22% { } 26%,42% { color: var(--fg); border-color: var(--fg) } 46%,100% { } }
@keyframes rt-lit-3 { 0%,50% { } 54%,68% { color: var(--fg); border-color: var(--fg) } 72%,100% { } }
@keyframes rt-lit-4 { 0%,70% { } 74%,96% { color: var(--fg); border-color: var(--fg) } 100% { } }

/* Motion is decoration here — the numbers carry the argument on their own. */
@media (prefers-reduced-motion: reduce) {
    .rt *, .rt *::before, .rt *::after { animation: none !important; transition: none !important; }
    .rt .rt-fee, .rt .rt-eff, .rt .rt-out, .rt .c-fee, .rt .c-eff { opacity: 1 !important; }
    .rt-row.r-kucoin  { transform: translateY(0) }
    .rt-row.r-binance { transform: translateY(var(--row-h)) }
    .rt-row.r-bybit   { transform: translateY(calc(var(--row-h) * 2)) }
    .rt-row.r-okx     { transform: translateY(calc(var(--row-h) * 3)) }
    .rt-bar i.fill-62 { inset: 0 38% 0 0; background: var(--ok) }
    .rt-bar i.fill-38 { inset: 0 62% 0 0; background: var(--ok) }
}

@media (max-width: 720px) {
    .rt-cols, .rt-row { grid-template-columns: 74px 1fr 60px 84px; }
    .rt-cols .c-fee, .rt-row .rt-fee { display: none; }
}

/* ---- strategy + benefit diagrams --------------------------------------- */

.strat { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.strat .card { display: flex; flex-direction: column; gap: 10px; }
.strat svg { width: 100%; height: 76px; display: block; }
.strat .nm { font-family: var(--mono); font-size: 13px; color: var(--fg); }
.dg-node { fill: var(--card); stroke: var(--border-strong); }
.dg-node.on { stroke: var(--fg); }
.dg-edge { stroke: var(--border-strong); fill: none; }
.dg-edge.on { stroke: var(--ok); stroke-width: 2; }
.dg-txt { fill: var(--muted); font-size: 9px; font-family: var(--mono); }
.dg-txt.on { fill: var(--fg); }
