/* Redactron marketing site — dark, centred, dense.
   Shaped after the category convention (openrouter.ai and peers): near-black
   ground, one high-chroma accent, a centred hero, then a grid of capability
   cards. No build step: Cloudflare Pages serves these bytes as committed. */
/* Dark is the default. The light palette is opt-in via [data-theme="light"] or
   the OS preference, so a reader who has asked their system for light gets it
   without touching anything, and the toggle still wins over both. */
:root {
  --bg: #08090a;
  --bg-2: #0f1113;
  --line: #1e2124;
  --line-2: #2a2e33;
  --ink: #f7f8f8;
  --ink-2: #a8b0b8;
  --ink-3: #6f7780;
  --accent: #c6f24e;
  --accent-ink: #0a0b0c;
  --radius: 12px;
  --wrap: 1200px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 28px; }
a { color: inherit; }

/* announcement */
.banner {
  background: var(--bg-2); border-bottom: 1px solid var(--line);
  text-align: center; padding: 11px 20px; font-size: 14px; color: var(--ink-2);
}
.banner a { color: var(--ink); }

/* header */
header { border-bottom: 1px solid var(--line); position: sticky; top: 0; background: rgba(255,255,255,.9); backdrop-filter: blur(8px); z-index: 20; }
.nav { display: flex; align-items: center; gap: 26px; height: 64px; }
.brand { font-weight: 700; letter-spacing: -0.02em; text-decoration: none; font-size: 18px; margin-inline-end: auto; }
.brand span { color: var(--accent); }
.nav a.link { text-decoration: none; color: var(--ink-2); font-size: 14.5px; }
.nav a.link:hover { color: var(--ink); }
.btn {
  display: inline-block; padding: 9px 17px; border-radius: 9px; text-decoration: none;
  font-size: 14.5px; font-weight: 600; border: 1px solid var(--line-2); color: var(--ink);
}
.btn:hover { border-color: var(--ink-3); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn.primary:hover { filter: brightness(1.08); }
.btn.lg { padding: 14px 30px; font-size: 16px; }

/* hero */
.hero { padding: 92px 0 60px; text-align: center; }
h1 { font-size: clamp(40px, 7vw, 76px); line-height: 1.03; letter-spacing: -0.035em; margin: 0 auto 20px; max-width: 15ch; font-weight: 700; }
.sub { font-size: clamp(17px, 2vw, 20px); color: var(--ink-2); max-width: 60ch; margin: 0 auto 34px; }
.cta { display: flex; gap: 13px; justify-content: center; flex-wrap: wrap; }

/* stats */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 26px; padding: 60px 0 8px; text-align: center; }
.stat b { display: block; font-size: clamp(24px, 3.4vw, 38px); letter-spacing: -0.03em; font-weight: 700; }
.stat span { color: var(--ink-3); font-size: 13.5px; }

/* sections */
section { padding: 66px 0; }
section + section { border-top: 1px solid var(--line); }
h2 { font-size: clamp(24px, 3.2vw, 34px); letter-spacing: -0.025em; margin: 0 0 12px; font-weight: 700; }
.lede { color: var(--ink-2); max-width: 64ch; margin: 0 0 32px; }
.grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(252px, 1fr)); }
.card { border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; background: var(--bg-2); }
.card h3 { margin: 0 0 8px; font-size: 16.5px; letter-spacing: -0.01em; }
.card p { margin: 0; color: var(--ink-2); font-size: 14.5px; }
.card .k { display: block; font-family: var(--mono); font-size: 12px; color: var(--accent); margin-bottom: 12px; letter-spacing: .04em; }

/* code */
pre {
  background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 20px 22px; overflow-x: auto; font: 13.5px/1.7 var(--mono); margin: 0; color: var(--ink-2);
}
pre .c { color: var(--ink-3); }
pre .s { color: var(--accent); }

/* tables */
table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
th, td { text-align: start; padding: 14px 18px; border-bottom: 1px solid var(--line); }
th { font-weight: 600; color: var(--ink-3); font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; }
td.num { font-family: var(--mono); white-space: nowrap; }
.scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-2); }
.scroll table { min-width: 560px; }
.scroll tr:last-child td { border-bottom: 0; }

/* legal / docs */
.legal { max-width: 76ch; padding: 54px 0 80px; }
.legal h1 { font-size: clamp(30px, 4vw, 42px); max-width: none; text-align: start; margin-inline-start: 0; }
.legal h2 { font-size: 19px; margin: 36px 0 10px; }
.legal p, .legal li { color: var(--ink-2); }
.legal li { margin-bottom: 8px; }
.legal code { font-family: var(--mono); font-size: 13px; color: var(--ink); }
.meta { color: var(--ink-3); font-size: 14px; margin-top: -6px; }

/* footer */
footer { border-top: 1px solid var(--line); padding: 52px 0 64px; color: var(--ink-3); font-size: 14px; }
.fgrid { display: grid; gap: 30px; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-bottom: 36px; }
.fgrid h4 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-3); margin: 0 0 12px; }
.fgrid a { display: block; text-decoration: none; color: var(--ink-2); margin-bottom: 9px; font-size: 14px; }
.fgrid a:hover { color: var(--ink); }

/* ── Narrow viewports ────────────────────────────────────────────────────────
   Found by screenshotting production at 390px, not by reading the CSS: the nav
   did not collapse, so brand + four links + the button stayed on one row and
   "Sign in" — the primary conversion control — wrapped to two lines and clipped
   at the right edge. It had been live since the dark rebuild because nothing
   below 1000px had ever been looked at.

   The fix hides the secondary links rather than shrinking them. They all survive
   in the footer, so nothing becomes unreachable, and it needs no JavaScript and
   no menu state. */
@media (max-width: 640px) {
  .wrap { padding: 0 18px; }
  .nav { gap: 14px; height: 58px; }
  .nav a.link { display: none; }
  .brand { font-size: 17px; }
  .btn { padding: 8px 14px; white-space: nowrap; }

  .hero { padding: 52px 0 40px; }
  h1 { max-width: none; }
  .cta { flex-direction: column; align-items: stretch; }
  .cta .btn { text-align: center; }

  .stats { grid-template-columns: repeat(2, 1fr); gap: 22px; padding: 44px 0 4px; }
  section { padding: 46px 0; }
  pre { padding: 16px; font-size: 12.5px; }
  .banner { font-size: 13px; padding: 10px 16px; }
  .legal { padding: 36px 0 56px; }

  /* A PRICE TABLE THAT SCROLLS SIDEWAYS HIDES HALF THE PRICE.
     `.scroll` keeps the page from scrolling horizontally, which is the right
     rule and was already here — but measured at 375px it left MODEL and INPUT
     visible and cut "OUTPUT" off mid-word. Someone comparing models on a phone
     saw the input rate and had to discover a horizontal scrollbar to learn what
     the output costs, and output is the larger number on every row.

     So below 640px the table stops being a table: each row becomes a card, and
     each cell carries its own column name from `data-label`. Both prices land in
     the first viewport, nothing is hidden behind a gesture, and the markup stays
     a real <table> for screen readers and for anyone copying it out. */
  .scroll { overflow-x: visible; border: 0; background: none; }
  .scroll table { min-width: 0; }
  .scroll thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .scroll tbody tr {
    display: block;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--bg-2);
    padding: 6px 2px;
    margin-bottom: 12px;
  }
  .scroll tbody tr:last-child { margin-bottom: 0; }
  .scroll tbody td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 16px;
    padding: 9px 16px;
    border-bottom: 1px solid var(--line);
  }
  .scroll tbody tr td:last-child { border-bottom: 0; }
  /* The column name, restored per cell. `attr()` keeps it in the markup rather
     than duplicating every heading in CSS, so a renamed column renames here too. */
  .scroll tbody td::before {
    content: attr(data-label);
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ink-3);
    flex: 0 0 auto;
  }
  /* The model name is the card's heading, not one field among four. */
  .scroll tbody td:first-child {
    font-weight: 600;
    font-size: 16px;
    padding-top: 4px;
  }
  .scroll tbody td:first-child::before { content: none; }
  .scroll tbody td.num { white-space: normal; text-align: end; }
  /* A prose cell — quickstart's "What to do" — needs the whole card width, not
     the right half of a two-column row, or every sentence wraps to three words. */
  .scroll tbody td:not(.num):not(:first-child) {
    display: block;
    text-align: start;
  }
  .scroll tbody td:not(.num):not(:first-child)::before { display: block; margin-bottom: 4px; }
}

@media (max-width: 900px) and (min-width: 641px) {
  .nav { gap: 18px; }
}


/* ── Themes ──────────────────────────────────────────────────────────────────
   Three states, matching the convention: explicit dark, explicit light, and
   "follow the system". The explicit choice is stamped on <html> so it beats the
   media query in both directions — a toggle that only works one way is the
   usual bug here. */
html:root[data-theme="light"] {
  --bg: #ffffff;
  --bg-2: #f7f8fa;
  --line: #e4e7eb;
  --line-2: #d3d8de;
  --ink: #0d0f12;
  --ink-2: #48505a;
  --ink-3: #6f7780;
  --accent: #4d7c0f;
  --accent-ink: #ffffff;
}
@media (prefers-color-scheme: light) {
  html:root:not([data-theme="dark"]):not([data-theme="light"]) {
    --bg: #ffffff;
    --bg-2: #f7f8fa;
    --line: #e4e7eb;
    --line-2: #d3d8de;
    --ink: #0d0f12;
    --ink-2: #48505a;
    --ink-3: #6f7780;
    --accent: #4d7c0f;
    --accent-ink: #ffffff;
  }
}
html:root[data-theme="light"] header { background: rgba(255,255,255,.9); }

.themes { display: inline-flex; border: 1px solid var(--line-2); border-radius: 9px; overflow: hidden; }
.themes button {
  background: none; border: 0; color: var(--ink-3); cursor: pointer;
  padding: 7px 10px; font: inherit; font-size: 13px; line-height: 1;
}
.themes button[aria-pressed="true"] { background: var(--bg-2); color: var(--ink); }
/* THE TOGGLE STAYS ON A PHONE. It was `display: none` here with no replacement
   anywhere — a dark-first site whose light/dark/system control the phone could
   not reach, which is the viewport where the OS scheme matters most. The
   narrow-viewport block above hides the secondary nav links and defends it by
   saying "they all survive in the footer, so nothing becomes unreachable". This
   control survives nowhere, so the same sentence says keep it.

   Measured at 375px: brand 77 + Sign in 78 + two 14px gaps leaves 156, and
   three buttons at this padding need 113. The padding grows rather than the
   font, so the target is 41px tall instead of 27. */
@media (max-width: 640px) {
  .themes button { padding: 13px 12px; }
}


html:root[data-theme="dark"] {
  --bg: #08090a; --bg-2: #0f1113; --line: #1e2124; --line-2: #2a2e33;
  --ink: #f7f8f8; --ink-2: #a8b0b8; --ink-3: #6f7780;
  --accent: #c6f24e; --accent-ink: #0a0b0c;
}
html:root[data-theme="dark"] header { background: rgba(8,9,10,.9); }

/* ── Card illustrations ──────────────────────────────────────────────────────
   Inline SVG, never an <img> or a CDN sprite: a Cloudflare Pages site with a
   strict CSP makes an external asset a silent blank box, and a diagram that
   fails to load is worse than none. Drawn from the product's own vocabulary —
   a hold becoming a charge, a ledger line, scoped keys, a sweep — rather than
   decorative icons. */
.card figure { margin: 0 0 16px; padding: 0; }
.card svg { display: block; width: 100%; height: auto; }
.card svg .bg { fill: var(--bg); }
.card svg .ln { stroke: var(--line-2); stroke-width: 1.5; fill: none; }
.card svg .ac { stroke: var(--accent); stroke-width: 1.5; fill: none; }
.card svg .acf { fill: var(--accent); }
.card svg .mut { fill: var(--ink-3); }
.card svg .inkf { fill: var(--ink-2); }

/* Featured-model cards borrow the table type without the table chrome. */
.card table { font-size: 13.5px; }
.card td { border: 0; }
.card .mut { color: var(--ink-3); }

/* ── Search ──────────────────────────────────────────────────────────────────
   Real, not decorative. A search box that opens nothing is worse than no search
   box: it is a promise the page does not keep. This one filters the models and
   pages that actually exist, entirely client-side — the site is five static
   files, so there is nothing to query and no endpoint to be down. */
.search { position: relative; flex: 0 1 320px; margin-inline-end: auto; }
.search input {
  width: 100%; background: var(--bg-2); border: 1px solid var(--line);
  border-radius: 9px; color: var(--ink); font: inherit; font-size: 14px;
  padding: 8px 46px 8px 32px;
}
.search input::placeholder { color: var(--ink-3); }
.search input:focus { outline: none; border-color: var(--line-2); }
.search .mag { position: absolute; inset-inline-start: 11px; top: 50%; transform: translateY(-50%); color: var(--ink-3); font-size: 13px; pointer-events: none; }
.search kbd {
  position: absolute; inset-inline-end: 9px; top: 50%; transform: translateY(-50%);
  border: 1px solid var(--line-2); border-radius: 5px; padding: 2px 6px;
  font: inherit; font-size: 11px; color: var(--ink-3); pointer-events: none;
}
.results {
  position: absolute; inset-inline: 0; top: calc(100% + 8px);
  background: var(--bg-2); border: 1px solid var(--line-2); border-radius: 10px;
  padding: 6px; display: none; max-height: 340px; overflow-y: auto; z-index: 40;
}
.results.open { display: block; }
.results a { display: block; padding: 9px 11px; border-radius: 7px; text-decoration: none; font-size: 14px; }
.results a:hover, .results a.on { background: var(--bg); }
.results .t { color: var(--ink); }
.results .d { color: var(--ink-3); font-size: 12.5px; }
.results .none { padding: 12px; color: var(--ink-3); font-size: 13.5px; }
@media (max-width: 900px) { .search { display: none; } }


/* ── Direction ───────────────────────────────────────────────────────────────
   The document is Arabic and RTL. These are the islands that must not turn.

   `pre` is the one that matters: a shell or Python line inside an RTL block gets
   its leading `#`, `$` and quotes reordered by the bidi algorithm, so the line
   reads correctly character by character and wrongly as a command. Same for a
   model id, a price and a URL — they are identifiers, not prose.

   `unicode-bidi: isolate` and not just `direction: ltr`: without isolation the
   surrounding RTL paragraph still reorders the run as a whole. */
pre, code, kbd, .mono, .num, .k,
[dir="ltr"] {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: left;
}

/* The brand is a Latin wordmark and stays one. */
.brand { direction: ltr; unicode-bidi: isolate; }
