/* ─────────────────────────────────────────────────────────────────────────
   Airrand Bots — brand system for the PUBLIC pages.

   The five static pages nginx serves on bots.airrand.app (landing, pricing,
   terms, privacy, contact) share this one file, for the reason 3d-brand.css
   exists: five pages carrying a palette each is how the first set drifted
   apart, down to a landing page and a legal page running two different
   accents. It mirrors the app's own tokens (the html.bots-app block in
   packages/dashboard/src/index.css). Edit the two together.

   Served from packages/dashboard/public: nginx answers it directly where the
   file is mounted and proxies to the app where it is not, which is also why
   the pages can load /theme-init.js and pick up the SAME stored `bots-theme`
   the app uses. That script stamps data-theme before first paint.

   Colour contract, in one line: indigo ACTS (anything you can click) and
   marks what is ours; everything else is a neutral. There is no second hue.
   A customer's bot wears the customer's colour, so these pages keep to one
   and leave the rest of the wheel to them.

   The values are the app's, token for token: --bg is --forge-bg, --accent is
   --forge-accent (the ink), --accent-fill is --forge-accent-solid under
   --accent-ink (--forge-accent-foreground). A visitor who signs up from the
   pricing page lands on the same ground and presses the same button.
   ───────────────────────────────────────────────────────────────────────── */

:root,
[data-theme="dark"] {
  --bg: #0e0f17;
  --surface: #151722;
  --card: #181b28;
  /* A panel that is a shade off the page rather than a card in its own right —
     the callout boxes on the legal pages. */
  --bg-soft: #181b28;
  --ink: #eceef6;
  --body: #c9cddb;
  --muted: #9ba2b8;
  /* Decorative edge — dividers, card outlines. Not a control. */
  --line: #33384d;
  /* The edge that identifies a control. WCAG 1.4.11 wants 3:1 from this. */
  --border: #6f7693;

  /* Ink: links, highlighted words, section eyebrows. Brand indigo (#4f46e5)
     is 2.9:1 on this ground, so at night the ink is a light tint of the same
     hue: 9.6:1 on --bg, 8.6:1 on --card. */
  --accent: #a5b4fc;
  --accent-soft: #c7d2fe;
  --accent-dim: #818cf8;
  /* Fill: the primary button's ground, and the label that sits on it. A
     shade brighter than brand indigo, so the button stands off a near-black
     page (3.4:1 against --bg) and still carries a white label: 5.6:1 resting,
     4.9:1 hovered. The hover is as light as a white label allows. */
  --accent-fill: #5850ec;
  --accent-fill-hover: #635cf0;
  --accent-ink: #ffffff;

  /* Chip ground: step numerals, plan tags, eyebrows. OPAQUE on purpose. A
     translucent chip inherits whatever it lands on, and these land on tinted
     bands as well as on the page; two tints stacked is how a chip's own label
     quietly drops under 4.5:1. bots-brand-css.test.ts measures both. */
  --accent-chip: #232652;
  --accent-tint: rgba(165, 180, 252, 0.14);
  --accent-tint-edge: rgba(165, 180, 252, 0.30);
  /* The page's own light: one bloom overhead, one at the foot. Dark adds
     light by adding colour, so both are the accent at low alpha. */
  --glow-top: rgba(88, 80, 236, 0.18);
  --glow-bottom: rgba(88, 80, 236, 0.07);
  /* The dotted field behind the landing page. */
  --dot: rgba(165, 180, 252, 0.14);
  --header-bg: rgba(14, 15, 23, 0.72);
  /* The code sample's ground. Darker than the page at night, and dark on
     paper too: a snippet is the one thing on these pages a visitor copies,
     and it should look like where it is going. */
  --code-bg: #090a10;
  --code-ink: #e6e8f2;
  --code-dim: #9ba2b8;
  --code-accent: #a5b4fc;
  /* "Ready", "Live": a state, never a control. */
  --ok: #34d399;
  --shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.75);
  --radius: 16px;

  color-scheme: dark;
}

[data-theme="light"] {
  --bg: #f3f4fa;
  --surface: #ffffff;
  --card: #ffffff;
  --bg-soft: #f8f9fd;
  --ink: #15161f;
  --body: #3a3f52;
  --muted: #4e5468;
  --line: #dcdfea;
  --border: #7c819c;

  /* On paper the ink is one step deeper than brand indigo: 7.2:1 on --bg and
     7.9:1 on white, where #4f46e5 itself is 5.7:1 on --bg and has nothing to
     spare once it lands on a tint. The FILL stays brand indigo, because a
     button is the one place the logo's colour belongs at full strength. */
  --accent: #4338ca;
  /* No lighter indigo survives here. The soft role is chip text, sitting on
     the chip ground and on accent-tint washes, so on paper it collapses into
     the ink. */
  --accent-soft: #4338ca;
  --accent-dim: #3730a3;
  --accent-fill: #4f46e5;
  --accent-fill-hover: #4338ca;
  --accent-ink: #ffffff;

  --accent-chip: #e9e8fd;
  --accent-tint: rgba(79, 70, 229, 0.10);
  --accent-tint-edge: rgba(79, 70, 229, 0.30);
  /* Paper cannot be lit by adding colour the way the night ground is: a
     saturated field over a pale page reads as a stain. So the overhead bloom
     is a brighter WHITE than --bg, light falling on the page, and only the
     foot keeps a breath of the accent. */
  --glow-top: rgba(255, 255, 255, 0.95);
  --glow-bottom: rgba(79, 70, 229, 0.07);
  --dot: rgba(79, 70, 229, 0.16);
  --header-bg: rgba(243, 244, 250, 0.80);
  --code-bg: #14152a;
  --code-ink: #e6e8f2;
  --code-dim: #9ba2b8;
  --code-accent: #a5b4fc;
  --ok: #046c4e;
  --shadow: 0 24px 60px -34px rgba(40, 38, 90, 0.35);
  --radius: 16px;

  color-scheme: light;
}

/* The same values again, for a visitor with JavaScript off: theme-init.js is
   what normally stamps data-theme, and without it the bare :root above would
   hand a light-OS visitor the dark page. Byte-identical to the block above on
   purpose — bots-brand-css.test.ts fails if they drift. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
  --bg: #f3f4fa;
  --surface: #ffffff;
  --card: #ffffff;
  --bg-soft: #f8f9fd;
  --ink: #15161f;
  --body: #3a3f52;
  --muted: #4e5468;
  --line: #dcdfea;
  --border: #7c819c;

  /* On paper the ink is one step deeper than brand indigo: 7.2:1 on --bg and
     7.9:1 on white, where #4f46e5 itself is 5.7:1 on --bg and has nothing to
     spare once it lands on a tint. The FILL stays brand indigo, because a
     button is the one place the logo's colour belongs at full strength. */
  --accent: #4338ca;
  /* No lighter indigo survives here. The soft role is chip text, sitting on
     the chip ground and on accent-tint washes, so on paper it collapses into
     the ink. */
  --accent-soft: #4338ca;
  --accent-dim: #3730a3;
  --accent-fill: #4f46e5;
  --accent-fill-hover: #4338ca;
  --accent-ink: #ffffff;

  --accent-chip: #e9e8fd;
  --accent-tint: rgba(79, 70, 229, 0.10);
  --accent-tint-edge: rgba(79, 70, 229, 0.30);
  /* Paper cannot be lit by adding colour the way the night ground is: a
     saturated field over a pale page reads as a stain. So the overhead bloom
     is a brighter WHITE than --bg, light falling on the page, and only the
     foot keeps a breath of the accent. */
  --glow-top: rgba(255, 255, 255, 0.95);
  --glow-bottom: rgba(79, 70, 229, 0.07);
  --dot: rgba(79, 70, 229, 0.16);
  --header-bg: rgba(243, 244, 250, 0.80);
  --code-bg: #14152a;
  --code-ink: #e6e8f2;
  --code-dim: #9ba2b8;
  --code-accent: #a5b4fc;
  --ok: #046c4e;
  --shadow: 0 24px 60px -34px rgba(40, 38, 90, 0.35);
  --radius: 16px;

  color-scheme: light;
}
}

/* ─── The lockup ─────────────────────────────────────────────────────────
   The horizontal logo, in the cut its ground can carry: the colour file sets
   "rrand" in near-black, which vanishes on the night ground, so the dark
   theme gets the white-wordmark cut with the indigo lifted to match. Both
   files are the same canvas with the artwork on identical bounds, so the swap
   causes no reflow.

   Done in CSS, not script, so the right cut is on screen at first paint — and
   so a visitor with JavaScript off still gets a logo rather than a broken one.

   --lockup-h is the height of the MARK, the tallest thing in the artwork, not
   of the file. The artwork ships with its clear space baked in: on the
   2040x438 canvas it occupies rows 79-370 and columns 110-1927, so a third of
   the file's height and 11% of its width are transparent margin. Setting
   `height` on the <img> would draw a logo a third smaller than the number
   said. So the image is scaled up by that ratio and the baked-in margin
   pulled back off with negative margins, and every number in the ladder
   below is a height you can see. The four factors are those bounds over the
   artwork's own 292px height; regenerate the files and they must be
   re-measured.

   Not clipped: what spills is transparent, and leaving it be keeps the home
   link's tap target a little wider than the letters. */
.brandmark {
  --lockup-h: 30px;
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  line-height: 0;
}
/* On a phone the lockup is 18–25px tall, and a home link a thumb cannot land
   on is no home link. Vertical padding pulled back with a matching negative
   margin grows the tap target to about 44px without moving the row. */
@media (pointer: coarse) {
  .brandmark { padding: 11px 0; margin: -11px 0; }
}
.brandmark img {
  width: auto;
  max-width: none;
  height: calc(var(--lockup-h) / 0.6667);
  margin: calc(var(--lockup-h) * -0.2705) calc(var(--lockup-h) * -0.3836)
          calc(var(--lockup-h) * -0.2295) calc(var(--lockup-h) * -0.3767);
}
.brandmark .logo-light { display: none; }
.brandmark .logo-dark { display: block; }
[data-theme="light"] .brandmark .logo-light { display: block; }
[data-theme="light"] .brandmark .logo-dark { display: none; }
/* The no-JS visitor on a light OS gets the light palette from the media
   block above, so they need the light cut of the logo from the same place. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .brandmark .logo-light { display: block; }
  :root:not([data-theme]) .brandmark .logo-dark { display: none; }
}

/* Visually-hidden label — the theme toggle's buttons are icon-only, and the
   nav is the one place every public page needs this. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ─── Theme toggle ───────────────────────────────────────────────────────
   Three states, matching the app's: system, light, dark. Hidden until the
   script that drives it has run, so a no-JS visitor is not shown a dead
   control — html.js is set by /theme-init.js at the top of every page. */
.theme-toggle {
  display: none;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
}
html.js .theme-toggle { display: inline-flex; }
.theme-toggle button {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--muted);
  cursor: pointer;
  line-height: 0;
}
.theme-toggle button:hover { color: var(--ink); }
.theme-toggle button[aria-pressed="true"] {
  background: var(--accent-fill);
  color: var(--accent-ink);
}
.theme-toggle button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.theme-toggle svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

/* ─── Site nav ───────────────────────────────────────────────────────────
   The one top navigation every public page wears. Defined here, next to the
   palette, for the same reason the palette is: five copies of a header is
   five headers.

   Pages keep their own `header` rule (the landing's is sticky, the others
   are not); this owns what is inside it. */
.site-nav {
  /* Two spacings, not one. The reading (theme toggle, links) wants air
     between items; the CTA and sign in are one control group and read as two
     halves of the same offer, so they sit tight. Both are variables because
     every breakpoint below re-tunes the row. */
  --nav-gap: 26px;
  --nav-btn-gap: 10px;
  display: flex; align-items: center; gap: var(--nav-gap);
}
/* Flex gap is uniform, so the pair is pulled back in rather than spaced out. */
.site-nav .nav-cta + .nav-signin { margin-left: calc(var(--nav-btn-gap) - var(--nav-gap)); }
.site-nav .navlink {
  color: var(--muted);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
  white-space: nowrap;
}
.site-nav .navlink:hover { color: var(--ink); }
.site-nav .navlink[aria-current="page"] { color: var(--ink); }

/* The header CTA. Smaller than a body CTA on purpose: it follows the reader
   down every page and must not compete with the action the page itself is
   asking for. */
.site-nav .nav-cta {
  display: inline-block;
  padding: 8px 16px;
  border: 1px solid transparent;
  border-radius: 10px;
  font-weight: 700;
  font-size: 0.88rem;
  text-decoration: none;
  white-space: nowrap;
  background: var(--accent-fill);
  color: var(--accent-ink);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent),
              0 10px 34px -12px color-mix(in srgb, var(--accent) 60%, transparent);
  transition: background .15s, transform .15s;
}
.site-nav .nav-cta:hover { background: var(--accent-fill-hover); transform: translateY(-1px); }

/* "Sign in" sits last in the row, after the CTA, and is the header's second
   action rather than part of its reading — so it wears a button, not a link.
   Same geometry as .nav-cta so the pair reads as one control group, in the
   ghost treatment: the outline carries it, the fill stays with the CTA. */
.site-nav .nav-signin {
  display: inline-block;
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  font-weight: 700;
  font-size: 0.88rem;
  text-decoration: none;
  white-space: nowrap;
  background: var(--card);
  color: var(--ink);
  transition: border-color .15s, transform .15s;
}
.site-nav .nav-signin:hover { border-color: var(--accent); transform: translateY(-1px); }
.site-nav .nav-cta:focus-visible,
.site-nav .nav-signin:focus-visible,
.site-nav .navlink:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* A second text link beside "Pricing" is the first thing a narrow row cannot
   afford. The secondary reading goes; the two ways in stay. */
@media (max-width: 860px) {
  .site-nav { flex-wrap: wrap; justify-content: flex-end; --nav-gap: 20px; row-gap: 10px; }
  .site-nav .navlink.secondary { display: none; }
  /* Let the row the nav sits in break, so the nav drops below the lockup
     rather than squeezing it. Reached through :has() because the header is
     the page's own element and each page names it differently — a browser
     without :has() simply wraps the nav in place beside the lockup, which is
     the degradation, not a broken layout. */
  header:has(> .site-nav),
  .header-inner:has(> .site-nav) { flex-wrap: wrap; row-gap: 10px; }
}
/* Below this the theme toggle goes too. The palette still follows the OS
   through theme-init.js. The lockup shrinks with the nav. */
@media (max-width: 700px) {
  .site-nav { --nav-gap: 16px; row-gap: 8px; }
  .site-nav .theme-toggle,
  html.js .site-nav .theme-toggle { display: none; }
  .brandmark { --lockup-h: 26px; }
}
/* The reading goes here. Which link that is was never a free choice: the CTA
   is the page's job and sign in is how a customer gets back to their bots, so
   what is left to cut is the text links, and every page still reaches them
   from the footer or the landing page. */
@media (max-width: 560px) {
  .site-nav .navlink { display: none; }
}
/* Two buttons shoulder to shoulder cost most of a phone row, and what pays
   for the second box is the lockup. Sign in gives up its BOX here and keeps
   its place beside the CTA as a link. The vertical padding stays behind to
   keep the 24px tap target WCAG 2.5.8 asks for, since the text alone is 17px
   tall. A header with no CTA (signup closed before launch) has one button
   and room for it, so a lone sign in keeps its box. */
@media (max-width: 494px) {
  .site-nav .nav-cta,
  .site-nav .nav-signin { padding: 7px 12px; font-size: 0.82rem; }
  .site-nav { --nav-gap: 14px; row-gap: 8px; }
  .brandmark { --lockup-h: 22px; }
  .site-nav .nav-cta + .nav-signin {
    padding: 6px 0;
    border-color: transparent;
    background: none;
    color: var(--muted);
    font-weight: 600;
    font-size: 0.9rem;
  }
  .site-nav .nav-cta + .nav-signin:hover { color: var(--ink); border-color: transparent; transform: none; }
}
/* 360px and 375px are still shipping phones. The lockup gives up the
   difference so the row stays one line. */
@media (max-width: 400px) {
  .site-nav { --nav-gap: 10px; row-gap: 8px; }
  .brandmark { --lockup-h: 19px; }
}
/* Below this even the link does not fit, so it goes and the CTA — which is
   also where a returning customer lands, since bots-nav-auth.js relabels it
   "Dashboard" for a live session — is what stays beside the lockup. With no
   CTA, sign in IS that way back, so it stays. */
@media (max-width: 350px) {
  .site-nav .nav-cta + .nav-signin { display: none; }
}

/* ─── Footer links ───────────────────────────────────────────────────────
   WCAG 2.5.8 wants a 24px target, and the spacing exception that forgives a
   small one needs 24px between centres. Padding does the whole job: the box
   grows to 28px and the rows push apart. Scoped to .foot-links, not
   `footer a`, so the "powered by Airrand" link inside a sentence stays
   inline. The negative margin puts the row's outer edge back where it was.

   .foot-links is also the hook cookie-consent.js appends its "Cookie
   settings" link to; a footer without it has no standing way to withdraw
   consent. */
.foot-links { margin-left: -8px; margin-right: -8px; }
.foot-links a { display: inline-block; padding: 6px 8px; margin: 0; }
/* A thumb, not a pointer: 10px brings each link to about 42px. */
@media (pointer: coarse) {
  .foot-links a { padding: 10px 8px; }
}

/* ─── Page furniture ─────────────────────────────────────────────────────
   What all six pages draw the same way: the type, the column, the buttons,
   the cards and the footer. Each page's own <style> comes after this link,
   so a page that needs something different says so there and wins. */
* { box-sizing: border-box; }
body {
  font-family: 'Instrument Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  margin: 0;
  color: var(--ink);
  line-height: 1.6;
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  /* A long URL or the code sample must never be what makes a phone scroll
     sideways; wide content scrolls inside its own box instead. */
  overflow-wrap: break-word;
}
/* Figures. Tabular, so a column of prices lines up, and unbreakable, because a
   figure and its unit are one token to a reader. In the page's own face: the
   mono is kept for the one thing here that is code. */
.num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.wrap { position: relative; z-index: 1; max-width: 1152px; margin: 0 auto; padding: 0 24px; }

.btn {
  display: inline-block; padding: 12px 24px; border-radius: 10px; font-weight: 700;
  text-decoration: none; font-size: 0.95rem; font-family: inherit; cursor: pointer;
  transition: background .15s, border-color .15s, transform .15s;
  /* Transparent border so a primary and a ghost button are the same height. */
  border: 1px solid transparent;
}
.btn-primary {
  background: var(--accent-fill); color: var(--accent-ink);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent),
              0 12px 38px -12px color-mix(in srgb, var(--accent) 65%, transparent);
}
.btn-primary:hover { background: var(--accent-fill-hover); transform: translateY(-1px); }
.btn-ghost { color: var(--ink); border-color: var(--border); background: var(--card); }
.btn-ghost:hover { border-color: var(--accent); }
.btn-lg { padding: 15px 30px; font-size: 1.02rem; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; }
.card h3 { margin: 0 0 8px; font-size: 1rem; }
.card p { margin: 0; color: var(--muted); font-size: 0.92rem; }

/* Small caps label on an opaque chip: eyebrows, plan tags, notice badges. */
.chip {
  display: inline-block; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--accent-soft); background: var(--accent-chip); border: 1px solid var(--accent-tint-edge);
  border-radius: 999px; padding: 5px 12px;
}

/* "Sign-up opens soon": what bots-nav-auth.js leaves where a sign-up button
   stood while the product is not open to everyone. A status, not a control:
   there is nothing to press, so it wears no box. */
.status-soon { display: inline-flex; align-items: center; gap: 10px; font-weight: 700; font-size: 0.95rem; color: var(--ink); }
.status-soon::before {
  content: ""; flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 4px var(--accent-chip);
}

/* The legal and contact pages: one reading column of prose. */
.doc header { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 20px 0; }
.doc main { padding: 24px 0 64px; max-width: 820px; }
.doc main h1 { font-size: 2rem; letter-spacing: -0.02em; line-height: 1.15; margin: 0 0 6px; }
.doc .meta { color: var(--muted); font-size: 0.9rem; margin: 0 0 24px; }
.doc main h2 { font-size: 1.15rem; margin: 32px 0 8px; letter-spacing: -0.01em; }
.doc main h3 { font-size: 1rem; margin: 20px 0 6px; }
.doc main p, .doc main li { font-size: 0.95rem; color: var(--body); }
.doc main ul { padding-left: 22px; }
.doc main a { color: var(--accent); }
.doc .warning {
  background: var(--bg-soft); border: 1px solid var(--line); border-left: 4px solid var(--accent);
  border-radius: 10px; padding: 14px 16px; margin: 16px 0; font-size: 0.93rem; color: var(--body);
}
.doc footer {
  border-top: 1px solid var(--line); padding: 24px 0 40px; color: var(--muted); font-size: 0.85rem;
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px;
}
.doc footer a { color: var(--muted); text-decoration: none; }
.doc footer a:hover { color: var(--ink); }
