/* Nocturne — design-system tokens and component classes. This file is the source of truth for the system's look; retune it here and see readme.md. */
/* Inter, served from this host rather than fetched from Google.
 *
 * It used to be `@import url(fonts.googleapis.com/css2?family=Inter...)`, and
 * that had three problems, of which only the first is about speed.
 *
 *   * It is the slowest possible way to load a font. An @import inside a
 *     stylesheet cannot start until that stylesheet has been fetched AND
 *     parsed, so the chain is: HTML, then styles.css, then Google's CSS, then
 *     the woff2. Four serialised round trips before the text is right, and
 *     with font-display:swap the reader watches the fallback reflow into
 *     place. Declared here, the font is one request that starts as soon as
 *     this file is parsed, and index.html preloads it earlier still.
 *
 *   * It is somebody else's uptime. A blocker, a privacy extension, a
 *     corporate proxy or a bad minute on the network and the page silently
 *     falls back to system-ui -- which is exactly the report that sent
 *     somebody looking at this file.
 *
 *   * It tells Google who is reading the page. Nothing on this site needs a
 *     third party to know that.
 *
 * The two files are the same ones the portal serves, byte for byte, so the
 * marketing page and the product it advertises are set in the same font
 * rather than in two builds of it. One variable face covers 100-900, which
 * is more weights than the Google request asked for, in less bytes than the
 * four static instances it would have returned. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
    U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
    U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}

:root {
  --color-bg: #161826;
  --color-surface: #232532;
  --color-text: #e9e9ed;
  --color-accent: #9184d9; /* review round 7 (Barron): the accent moves to
     the product's blurple — OKLCH hue 289.2, the hue of the app's own Pro
     accent (#9a8fe0, --om-accent-pro) — at the same lightness the steel
     accent held (L 0.660, so the documented ratios survive) and chroma
     in the product blurple's own range (its token sits at C 0.118; the
     accent takes 0.125, from the old steel's 0.030):
     the accent now reads as an accent rather than another neutral. */
  --color-accent-2: #a7a1db; /* the machine-derived stand-in follows: same
     hue, same L 0.734, chroma at the same 2:3 proportion it held */
  --color-divider: color-mix(in srgb, #e9e9ed 16%, transparent);

  /* The portal's own healthy, marginal and exhausted, to the same values, so
     the log sample and the capacity table on this page read as the product
     they are a picture of rather than as screenshots from something else. */
  --color-ok: #5fbf8a;
  --color-warn: #e0b350;
  --color-danger: #f2706d;

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f3f5fe;
  --color-neutral-200: #e4e7f5;
  --color-neutral-300: #cfd3e5;
  --color-neutral-400: #b2b6ca;
  --color-neutral-500: #9397ab;
  --color-neutral-600: #75798c;
  --color-neutral-700: #595d6c;
  --color-neutral-800: #3f424d;
  --color-neutral-900: #292b31;

  --color-accent-100: #f5f4ff;
  --color-accent-200: #e7e5fe;
  --color-accent-300: #d2cefd;
  --color-accent-400: #b5abfc;
  --color-accent-500: #968ae0;
  --color-accent-600: #796cbf;
  --color-accent-700: #5d5294;
  --color-accent-800: #423a6a;
  --color-accent-900: #2b2741;

  --color-accent-2-100: #f5f4ff;
  --color-accent-2-200: #e7e5fe;
  --color-accent-2-300: #d2cefd;
  --color-accent-2-400: #b5afe8;
  --color-accent-2-500: #9690c9;
  --color-accent-2-600: #7972a9;
  --color-accent-2-700: #5c5783;
  --color-accent-2-800: #423e5d;
  --color-accent-2-900: #2b293a;

  /* Deck section-divider ground — review round 3: saturation as presence.
     Dividers take a saturated deep indigo (hue 277, the neutral ramp's own
     family; C 0.094 — written when the accent held C 0.030, before the
     round-7 blurple raised it past the ground's) with a lighter bloom and
     a ghost tint of the same hue, while the slide grounds stay
     desaturated. Deck-scale fills only — not interface colors. */
  --color-section: #262a60;
  --color-section-glow: #353b80;
  --color-section-ghost: #4c5397;

  --font-heading: "Inter", system-ui, sans-serif;
  --font-heading-weight: 500;
  --font-body: "Inter", system-ui, sans-serif;

  --space-1: 2.8px;
  --space-2: 5.6px;
  --space-3: 8.4px;
  --space-4: 11.2px;
  --space-6: 16.8px;
  --space-8: 22.4px;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 14px;

  /* Elevation — derived from the ground: soft ink-tinted shadows on a
     light theme, a hairline edge + ambient darkness on a dark one. */
  --shadow-sm: 0 0 0 1px #3f424d;
  --shadow-md: 0 0 0 1px #595d6c, 0 6px 18px rgba(0,0,0,0.55);
  --shadow-lg: 0 0 0 1px #9397ab, 0 16px 40px rgba(0,0,0,0.65);
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
}
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); }


/* ══════════════════════════════════════════════════════════════════════════
   Components — built with the tokens above. Plain CSS
   on plain HTML: no JavaScript, no build step. Each class is documented in
   readme.md and demonstrated in foundations/ and components/.
   ══════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 400; }
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
h1 { font-size: 42px; }
h2 { font-size: 32px; }
h3 { font-size: 25px; }
h4 { font-size: 20px; }
h5 { font-size: 16px; }
h6 { font-size: 13px; }
h6 { letter-spacing: 0.08em; text-transform: uppercase; }
p { margin: 0 0 var(--space-3); }
a { color: var(--color-accent); text-underline-offset: 3px; }
img { display: block; max-width: 100%; }
figure { margin: 0; }
figcaption {
  font-size: 11px; margin-top: var(--space-1);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.text-muted { color: color-mix(in srgb, var(--color-text) 55%, transparent); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* — rules — */
/* Rules fade to transparent at both ends instead of stopping cleanly — a
   Nocturne signature. The ramp is 48px an end (one deck baseline unit),
   painted from the same divider token. Freestanding rules fade; box
   outlines, in-control separators, and short accent marks stay solid. */


/* — buttons — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; line-height: 1.2; color: var(--color-text); /* matches the .input's 14px —
     the pair sits side by side in sign-up rows */
  background: transparent; border: 1px solid transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: var(--radius-md);
}
.btn svg { display: block; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary { color: var(--color-accent); border-color: var(--color-accent); }
.btn-primary:hover { background: color-mix(in srgb, var(--color-accent) 12%, transparent); }
.btn-primary:active { background: color-mix(in srgb, var(--color-accent) 22%, transparent); }


.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); }
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }


/* — forms — */


/* — cards — */
.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface);
}

.card-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 17px; line-height: 1.2;
}
.card-body { margin: 0; font-size: 13px; opacity: 0.8; flex: 1; }

.elev-sm { box-shadow: var(--shadow-sm); }
.elev-md { box-shadow: var(--shadow-md); }


/* — tags — */
.tag {
  display: inline-flex; align-items: center; font-size: 11px;
  letter-spacing: 0.02em; padding: 3px 10px;
  border-radius: calc(var(--radius-md) * 0.75);
}


.tag-outline { border: 1px solid var(--color-accent); color: var(--color-accent); }

/* — navigation — */
.nav {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: none;
  /* Wraps rather than pushing the whole document wider than the phone it is
     being read on. Without this the row is one unbreakable line, and every
     section added to the page is another 80px of horizontal scroll on
     everything below it, including the prose. */
  flex-wrap: wrap; row-gap: var(--space-2);
}
.nav-brand {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 18px; margin-right: auto;
}
.nav a { color: inherit; text-decoration: none; font-size: 14px; }
.nav a:hover, .nav a[aria-current='page'] { color: var(--color-accent); }

/* — tables — */
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
  padding: var(--space-2); border-bottom: 1px solid transparent; /* keeps layout; the row paints the fading rule */
}
.table td {
  padding: var(--space-2);
  border-bottom: 1px solid transparent;
}
/* Row rules as row-level strips so the end-fade spans the row, not each cell. */
.table thead tr {
  background: linear-gradient(to right,
    transparent, var(--color-divider) 48px,
    var(--color-divider) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px;
}
.table tbody tr {
  background: linear-gradient(to right,
    transparent, color-mix(in srgb, var(--color-text) 8%, transparent) 48px,
    color-mix(in srgb, var(--color-text) 8%, transparent) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px;
}
.table tbody tr:hover {
  /* the hover tint layers over the row rule, which keeps painting */
  background:
    linear-gradient(color-mix(in srgb, var(--color-text) 4%, transparent),
                    color-mix(in srgb, var(--color-text) 4%, transparent)) no-repeat 0 0 / 100% 100%,
    linear-gradient(to right,
      transparent, color-mix(in srgb, var(--color-text) 8%, transparent) 48px,
      color-mix(in srgb, var(--color-text) 8%, transparent) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px;
}

/* — dialog — */




/* ---- page classes distilled from repeated inline styles ---- */
.mono { font-family:ui-monospace,Menlo,monospace; }
.mono-14 { font-family:ui-monospace,Menlo,monospace;font-size:14px; }
.code { font-family:ui-monospace,Menlo,monospace;font-size:0.92em; }
.rule { height:1px;border:0;margin:0;background:linear-gradient(to right, transparent, var(--color-divider) 48px calc(100% - 48px), transparent); }
.h-32 { font-size:32px;line-height:42px;letter-spacing:-0.012em;margin:0; }
.stat-num { font-size:clamp(36px,3.6vw,52px);line-height:56px;margin:0 0 0 -0.055em;font-family:var(--font-heading);font-weight:500; }
.stat-label { font-size:13px;line-height:14px;letter-spacing:0.06em;text-transform:uppercase;color:color-mix(in srgb, var(--color-text) 64%, transparent);margin:14px 0 0; }
.kicker { display:block;font-size:13px;line-height:14px;letter-spacing:0.06em;text-transform:uppercase;color:var(--color-accent);margin:0 0 14px; }
.lede { font-size:17px;line-height:28px;margin:0; }
.step-num { font-size:15px;line-height:28px;color:var(--color-accent);margin:0;font-feature-settings:'tnum' 1; }
.section-h { font-size:24px;line-height:28px;letter-spacing:-0.01em;margin:0; }
.body-copy { font-size:15.5px;line-height:28px;margin:0;color:color-mix(in srgb, var(--color-text) 78%, transparent);max-width:52ch; }
.prose { font-size:15.5px;line-height:28px;color:color-mix(in srgb, var(--color-text) 78%, transparent);max-width:64ch;margin:20px 0 0; }
.diagram { width:100%;height:auto;display:block; }
.figcap { font-size:13px;line-height:20px;margin-top:12px; }
.wrap { max-width:1200px;margin:0 auto;padding:0 clamp(20px,5vw,72px); }
.step { display:grid;grid-template-columns:minmax(64px,160px) minmax(0,420px) minmax(0,1fr);gap:28px clamp(24px,4vw,72px);align-items:baseline;padding:42px 0;position:relative; }
.step-rule { position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(to right, transparent, var(--color-neutral-700) 48px calc(100% - 48px), transparent); }
.note { font-size:15px;line-height:26px;margin:4px 0 0;color:color-mix(in srgb, var(--color-text) 72%, transparent); }
.tag-sm { font-size:10px;padding:1px 7px;white-space:nowrap; }
.dim { color:var(--color-neutral-500); }
.gap-36 { margin:36px 0 0; }
.sec-pad { padding:84px 0 56px; }

/* A photograph on a dark page. The frame is the same radius and hairline the
   diagrams beside it use, so a photo and a drawing sit at the same depth
   rather than one floating on the ground; overflow is clipped because the
   corners are on the frame and a photo has square ones. Nothing here touches
   the image itself -- a plant photograph is evidence, and dimming or tinting
   one to suit a palette would be editing it. */
.lighten { border:1px solid var(--color-neutral-700); border-radius:var(--radius-md);
  overflow:hidden; background:var(--color-surface); line-height:0; }
.lighten img { display:block; width:100%; height:auto; }

/* The unfilled photo placeholder. A visible empty slot on purpose: the
   two-column figure grid the design intends survives, and a missing asset is
   obvious rather than silently absent. To fill one, replace the whole div with
   <img src="..." alt="..."> wrapped in <div class="lighten"> above. */
.photo-slot { display:grid; place-items:center; text-align:center;
  border:1px dashed var(--color-neutral-600); border-radius:var(--radius-md);
  background:var(--color-surface); color:var(--color-neutral-500);
  font-size:13px; line-height:20px; padding:16px; }

/* The skip link is first in the tab order and visible only while focused. It
   is positioned off-screen rather than display:none, which would take it out
   of the tab order entirely and defeat the point. */
.skip-link { position: absolute; left: -9999px; top: 0; z-index: 10;
  background: var(--color-surface); color: var(--color-text);
  padding: 10px 16px; border-radius: var(--radius-md);
  border: 1px solid var(--color-accent); text-decoration: none; }
.skip-link:focus { left: 8px; top: 8px; }
main:focus { outline: none; }
