/* Sona — one stylesheet, tokens at the top.
 *
 * House standard: vanilla, same-origin, no build step, no CDN, system fonts.
 * A webfont is a network dependency for a marginal aesthetic gain, and these
 * pages are served under a CSP where an external stylesheet is one more thing
 * that can fail or be tampered with.
 *
 * Colour discipline: this is greyscale plus MEANING. Green, amber and red carry
 * state and nothing else. If everything is coloured, nothing reads as a warning
 * - which matters more here than in most products, because the thing being sold
 * is that a warning means something.
 */

:root {
  --bg: #fbfbfa;
  --surface: #ffffff;
  --surface-2: #f5f4f1;
  --line: #e5e3df;
  --line-2: #d6d3cc;

  --ink: #1a1a18;
  --ink-2: #5c5a55;
  --ink-3: #8a8781;

  /* Semantic only. Never "the blue one". */
  --ok: #1c7c54;
  --ok-bg: #eef6f1;
  /* 2026-09-21: was #a86400, which is 4.36:1 on --warn-bg - under the 4.5
     WCAG AA minimum for body text, and amber on cream is exactly where
     that happens. Computed, not eyeballed; the gate is
     tests/test_accessibility.py. */
  --warn: #9c5d00;
  --warn-bg: #fdf6ea;
  --bad: #a32b2b;
  --bad-bg: #fbf0ef;
  --accent: #2b5f8a;
  --accent-bg: #eef3f8;

  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-6: 24px; --sp-8: 32px; --sp-12: 48px; --sp-16: 64px;

  --r: 6px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #17171a;
    --surface: #1f1f23;
    --surface-2: #26262b;
    --line: #34343a;
    --line-2: #42424a;

    --ink: #f2f1ef;
    --ink-2: #b6b3ad;
    --ink-3: #8a8781;

    --ok: #5fbf92;      --ok-bg: #16281f;
    --warn: #d8a14a;    --warn-bg: #2a2114;
    --bad: #e08a86;     --bad-bg: #2c1817;
    --accent: #7fb0d8;  --accent-bg: #16222c;
  }
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
}

/* Type scale: 12 / 14 / 16 / 20 / 28. A sixth size is usually a layout problem
   in disguise. */
h1 { font-size: 28px; line-height: 1.25; letter-spacing: -0.02em; margin: 0 0 var(--sp-4); }
h2 { font-size: 20px; line-height: 1.3; letter-spacing: -0.01em; margin: 0 0 var(--sp-3); }
h3 { font-size: 16px; margin: 0 0 var(--sp-2); }
p  { margin: 0 0 var(--sp-4); }

a { color: var(--accent); }

small, .small { font-size: 12px; }
.muted { color: var(--ink-2); }
.dim   { color: var(--ink-3); }

/* Focus is never removed. An outline:none with no replacement is how a screen
   stops being usable by keyboard without anyone noticing. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

.wrap { max-width: 900px; margin: 0 auto; padding: 0 var(--sp-4); }

/* ------------------------------------------------------------------ chrome */
.top {
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.top .wrap {
  display: flex; align-items: center; gap: var(--sp-4);
  min-height: 56px;
  /* PADDING RESTATED, and not redundantly. Several pages carry their own
     `.wrap` for the CONTENT column - pricing.html's is
     `padding: 44px 20px 80px` - and when the shared header is used on one of
     those, the page's rule reaches inside it and gives the nav 80px of bottom
     padding. Everything else here is safe because `.top .wrap` is two classes
     and outranks a bare `.wrap`, but only for properties it actually sets.
     So it sets this one. */
  padding: 0 var(--sp-4);
  /* And the WIDTH, for the same reason and with a sharper consequence. Those
     pages size `.wrap` to their content column - signup's is 440px for a
     narrow form - so the shared header inherited it and came out a different
     width on every page. A nav bar that changes width as you move between
     pages is the inconsistency this header exists to remove. 900px is
     app.css's own `.wrap`, so home and login are unchanged. */
  max-width: 900px;
}
.brand {
  font-weight: 650; letter-spacing: -0.02em; font-size: 20px;
  color: var(--ink); text-decoration: none;
}
.top nav { margin-left: auto; display: flex; gap: var(--sp-4); align-items: center; }
.top nav a { color: var(--ink-2); text-decoration: none; font-size: 14px; }
.top nav a:hover { color: var(--ink); }

/* ------------------------------------------------------------------ blocks */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--sp-6);
}

/* Hit targets >= 32px, and a button is a <button> or an <a> that looks like
   one - never a div with a click handler. */
.btn {
  display: inline-block;
  min-height: 38px;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--ink);
  border-radius: var(--r);
  background: var(--ink);
  color: var(--bg);
  font: 500 14px/22px var(--font);
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { opacity: .88; }
.btn-quiet {
  background: transparent; color: var(--ink); border-color: var(--line-2);
}

/* A caveat is TEXT beside the claim. Not a tooltip, not a footnote, not behind
   an info icon. House rule 5, and the reason this product exists. */
.caveat {
  border-left: 3px solid var(--warn);
  background: var(--warn-bg);
  color: var(--ink);
  padding: var(--sp-3) var(--sp-4);
  border-radius: 0 var(--r) var(--r) 0;
  font-size: 14px;
}
.caveat b { color: var(--warn); }

/* A transcript sample. Real product text only - a fabricated exchange in a
   screenshot of a product whose claim is honesty is itself a dishonest claim. */
.turn {
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--surface);
}
.turn > div { padding: var(--sp-3) var(--sp-4); font-size: 14px; }
.turn .visitor { background: var(--surface-2); color: var(--ink-2); }
.turn .assistant { border-top: 1px solid var(--line); }
.turn .why {
  border-top: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--ink-2);
  font-size: 12px;
  font-family: var(--mono);
}
.turn .why b { color: var(--ok); font-family: var(--font); }
.turn .why.refused b { color: var(--bad); }

.rows { display: grid; gap: var(--sp-4); }
@media (min-width: 720px) {
  .rows.two { grid-template-columns: 1fr 1fr; }
}

.foot {
  border-top: 1px solid var(--line);
  margin-top: var(--sp-16);
  padding: var(--sp-6) 0 var(--sp-12);
  color: var(--ink-3);
  font-size: 12px;
}

/* ------------------------------------------------------- layout primitives
 * Added after a self-check found nineteen inline style attributes on the home
 * page - house rule 7, broken in the page written against it. Inline styles are
 * how a token system quietly stops being one: the values drift back into the
 * markup one "just this once" at a time, and then dark mode is wrong in places
 * nobody can grep for. */

.page { padding-top: var(--sp-16); }

/* Measure. Long lines are the commonest readability failure on a marketing
   page, and 60-66 characters is the range that stops being a wall. */
.measure   { max-width: 62ch; }
.measure-s { max-width: 56ch; }
.measure-l { max-width: 66ch; }

.headline { max-width: 20ch; }

/* One size above body, for the sentence under the headline. Still inside the
   five-size scale - it is the 20px step. */
.lede { font-size: 20px; }

.section { margin-top: var(--sp-16); }
.tight   { margin: 0; }

.list { padding-left: 1.1em; }
.list li { margin-bottom: var(--sp-2); }

.actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

/* ---------------------------------------------------------- landing page
 * Added 2026-09-21 for the rebuilt home page, after studying a Zendesk-style
 * landing page for STRUCTURE. Their persuasion sequence is roughly 70% social
 * proof: eight brand logos, a customer count, a Gartner badge, five named
 * testimonials carrying metrics.
 *
 * None of those devices can appear here. There are no customers but Rop, no
 * audit, and no third-party validation - so every one of those slots would have
 * to be filled with something invented, on the marketing page for a product
 * whose entire claim is that it refuses what it cannot source. The slots are
 * kept and filled with DEMONSTRATION instead: real transcript output, and a
 * status panel that states plainly what is not built yet.
 *
 * No new colours and no sixth type size. These are layout primitives only. */

/* A full-bleed band. The page alternates surface and background so sections
   separate without rules or shadows doing the work. */
.band {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  margin-top: var(--sp-16);
  padding: var(--sp-16) 0;
}
.band > .wrap > :last-child { margin-bottom: 0; }
.band .section:first-child { margin-top: 0; }

/* Hero. Text and a REAL transcript side by side - the demonstration is the
   product shot. Single column until there is room for two, because a
   transcript squeezed into half a phone screen is unreadable. */
.hero { padding-top: var(--sp-16); }
@media (min-width: 900px) {
  .hero-grid {
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    gap: var(--sp-12);
    align-items: start;
  }
}
.hero h1 { font-size: 28px; max-width: 18ch; }

/* The label above a piece of real output. It matters that a reader knows this
   is not a mock-up, so it is said rather than implied. */
.specimen-label {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-3);
  margin-bottom: var(--sp-2);
}

/* THE STATUS PANEL - this page's answer to a stats dashboard.
   Same slot in the sequence, opposite content: what is NOT done. Each row is a
   capability, its state, and what the state costs the reader. */
.status { border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.status-row {
  display: grid;
  gap: var(--sp-1) var(--sp-4);
  padding: var(--sp-4);
  background: var(--surface);
  border-top: 1px solid var(--line);
}
.status-row:first-child { border-top: 0; }
@media (min-width: 720px) {
  .status-row { grid-template-columns: 15rem 9rem 1fr; align-items: baseline; }
}
.status-what { font-weight: 550; }
.status-state {
  font-family: var(--mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.status-state.no  { color: var(--bad); }
.status-state.yes { color: var(--ok); }
.status-note { color: var(--ink-2); font-size: 14px; }

/* Numbered flow. Three stages, and the number is a real ordinal rather than
   decoration, so it is content rather than a ::before. */
@media (min-width: 720px) {
  .steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6); }
}
.steps { margin-top: var(--sp-8); }
.step { display: grid; gap: var(--sp-2); }
.step-n {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-3);
}

/* The explanatory paragraph under a section heading. It needs more space
   beneath it than an ordinary paragraph, because what follows is a block
   rather than more prose. A NAMED concept, not a margin utility - the moment
   this becomes .mb-6 the tokens start leaking back into the markup. */
.section-intro { margin-bottom: var(--sp-6); }

/* Objections, as a real <details> list. Native disclosure gets keyboard and
   screen-reader behaviour for free; a div with a click handler does not. */
.faq { border-top: 1px solid var(--line); margin-top: var(--sp-6); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  padding: var(--sp-4) 0;
  cursor: pointer;
  font-weight: 550;
  list-style-position: outside;
}
.faq summary:hover { color: var(--accent); }
.faq details > p {
  color: var(--ink-2);
  font-size: 14px;
  max-width: 66ch;
  margin: 0 0 var(--sp-4);
}

/* The last ask. Left-aligned on purpose - a centred stack of two buttons is
   the single most template-looking element on the web. */
.closer { margin-top: var(--sp-16); }

/* ---------------------------------------------------------------- forms
 * Added 2026-09-21. app.css had no input, label or fieldset styling at all,
 * which is why every auth page carried its own :root and its own form CSS -
 * eight pages, each with a different palette from this one. These are the
 * primitives that let them stop.
 *
 * Nothing here is decorative. Focus is visible, labels are real <label>s tied
 * to their control, and the error region is a live region so a screen reader
 * is told when a sign-in fails rather than silently left on the form. */

.field { margin-bottom: var(--sp-4); }
.field label {
  display: block;
  font-weight: 550;
  font-size: 14px;
  margin-bottom: var(--sp-1);
}
.field .hint { display: block; color: var(--ink-2); font-size: 12px; margin-bottom: var(--sp-2); }

input[type="text"], input[type="email"], input[type="password"], input[type="url"],
textarea, select {
  width: 100%;
  min-height: 40px;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--surface);
  color: var(--ink);
  font: 16px/1.5 var(--font);   /* 16px: anything smaller makes iOS zoom on focus */
}
input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.btn-block { width: 100%; text-align: center; min-height: 42px; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .55; cursor: default; }

/* A message region. `hidden` until there is something to say, and the colour
   is semantic - never "the red one". */
.msg {
  margin-top: var(--sp-3);
  padding: var(--sp-3);
  border-radius: var(--r);
  font-size: 14px;
  border: 1px solid transparent;
}
.msg.err  { background: var(--bad-bg);  color: var(--bad);  border-color: var(--bad); }
.msg.good { background: var(--ok-bg);   color: var(--ok);   border-color: var(--ok); }

/* "or" divider, drawn with pseudo-elements so the word is real text that a
   screen reader reads once and not three times. */
.or {
  display: flex; align-items: center; gap: var(--sp-3);
  color: var(--ink-3); font-size: 12px;
  margin: var(--sp-4) 0;
}
.or::before, .or::after {
  content: ""; flex: 1; height: 1px; background: var(--line);
}

/* ------------------------------------------------------------ auth layout
 * A sign-in box alone on a page tells a first-time visitor nothing about what
 * they are signing in to. On a wide screen the form sits beside a short
 * statement of what this is; on a phone the FORM COMES FIRST, because someone
 * returning to sign in should not scroll past marketing to reach it. */
.auth { padding: var(--sp-12) 0 var(--sp-16); }
.auth-grid { display: grid; gap: var(--sp-12); }
@media (min-width: 860px) {
  .auth-grid { grid-template-columns: 26rem 1fr; align-items: start; }
}
.auth-card { max-width: 26rem; }
.auth-aside { color: var(--ink-2); font-size: 14px; }
.auth-aside h2 { color: var(--ink); }
