/* 2atomic.com - design 2, "proof2". One light theme: a white technical field,
   cyan structure, violet accents. Concept: trust reduced to its smallest
   verifiable unit (the atom / the "2" in 2atomic), proven not asserted. */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body, h1, h2, h3, h4, p, ul, ol, li, figure, pre, blockquote { margin: 0; padding: 0; }
ul { list-style: none; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
canvas { display: block; }
/* An identifier is one unbreakable word, and `2atomic:exec_byte_account_closure` is wider
   than a 320px column, so it has to be allowed to break rather than leave the column. */
code { overflow-wrap: anywhere; }

:root {
  /* One theme: a white technical field. The sheet carried a dark theme and a
     light alternate behind `prefers-color-scheme` plus a toggle, which meant
     every surface had to be drawn twice and the second drawing was the one
     nobody looked at. */
  --paper:     #ffffff;
  --paper-2:   #f5f7fb;
  --sink:      #eceff6;
  --ink:       #0a0d14;
  --ink-2:     #39414f;
  --muted:     #5d6779;
  --line:      #d8dde8;
  --line-2:    #b4bdcf;

  --accent:    #0a6f8f;   /* deep cyan: structure, rules, figures */
  --accent-2:  #6436c4;   /* violet: small text, the chromatic edge */
  --accent-wash:#e4f3f8;
  --accent-ink:#ffffff;   /* text ON an accent fill */
  --glow:      rgba(10, 111, 143, 0.14);

  --live:      #0a7a4b;   /* semantic, NOT the accent */
  --amber:     #9a6100;
  --danger:    #c0352c;

  --sans: "Helvetica Neue", "Inter", system-ui, "Segoe UI", Roboto, Arial, sans-serif;
  --mono: "SF Mono", "JetBrains Mono", ui-monospace, "IBM Plex Mono", Menlo, Consolas, monospace;
  /* Condensed display for headlines. No webfont is fetched: this is the condensed
     face each platform already has, falling back to the body sans where there is
     none, so the page renders the same offline and adds no third-party request. */
  --display: "Avenir Next Condensed", "HelveticaNeue-CondensedBold", "Roboto Condensed",
             "Liberation Sans Narrow", "Arial Narrow", var(--sans);

  /* The mono eyebrow, and the smaller one under it. Tokens and not literals because
     10px is below what a phone can read, and the override has to reach all 23 rules. */
  --label:    10px;
  --label-sm:  9px;

  --maxw: 1440px;
  --gutter: 28px;  /* .wrap's own side padding */
  --rail: 56px;    /* the rig's first grid column */
  --r: 0px;   /* square: a corner bracket has to land on a corner */
  --shadow: 0 22px 54px -32px rgba(10, 13, 20, 0.30);
  color-scheme: light;
}

/* Measured 2026-10-18 at 320/375/430px: every mono label rendered at 10px or 9px,
   under the 11px floor at which a phone reader can take it in. */
@media (max-width: 620px) {
  :root { --label: 12px; --label-sm: 11px; }
}

body {
  font-family: var(--sans);
  background: var(--paper);
  color: var(--ink);
  line-height: 1.6;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
}
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }

/* The mega-menus splice ~30 links into the tab order on every page, so bypassing
   the header is a real need rather than a formality. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 50;
  background: var(--accent); color: var(--accent-ink); padding: 12px 18px;
  font-size: 14px; font-weight: 600; border-radius: 0 0 var(--r) 0;
}
.skip-link:focus { left: 0; }
.eyebrow {
  font-size: 11px; letter-spacing: 3.2px; text-transform: uppercase;
  color: var(--accent-2); font-weight: 600;
}

/* ------------------------------------------------------------- top bar ----- */
.topbar {
  position: sticky; top: 0; z-index: 30;
  /* OPAQUE, not translucent-with-a-blur. `backdrop-filter` on a sticky bar holds a
     composited GPU layer for the life of the page and re-blurs whatever scrolls
     under it, which is the only permanent per-frame cost the site had. The blur was
     decorative; the bar reads the same solid. */
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.topbar-inner {
  max-width: var(--maxw); margin: 0 auto; padding: 14px 28px;
  display: flex; align-items: center; gap: 18px;
}
/* THE NAME IS THE LOGO, drawn rather than set. Chamfered geometric glyphs on a 100-unit
   cap height: the 45-degree cuts are what read as technical, and a filled outline holds at
   15px where a stroke would go mushy. No webfont, so no third-party request and no
   fallback that renders the logo in Arial. */
/* The padding is the tap target: the wordmark itself is 17px tall and is the only way home. */
.mark { display: inline-flex; align-items: center; text-decoration: none; padding: 8px 0; }
.mark-svg { height: 17px; width: auto; display: block; color: var(--ink); overflow: visible; }
.mark .mk-a { stroke: var(--accent); }
.mark:hover .mark-svg { color: var(--accent); }
:root:not([data-theme="light"]) .mark .mk-a,
:root[data-theme="dark"] .mark .mk-a { filter: drop-shadow(0 0 6px color-mix(in srgb, var(--accent) 55%, transparent)); }
.topnav { margin-left: auto; display: flex; align-items: center; }
.topnav a { font-size: 13px; color: var(--muted); transition: color 0.15s ease; }
.topnav a:hover { color: var(--ink); }

/* ---------------------------------------------------------------- hero ----- */
.hero { position: relative; padding: 60px 0 56px; }
.hero-grid {
  display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 40px; align-items: center;
}
.hero-copy { position: relative; z-index: 2; }
.headline {
  font-family: var(--display);
  font-size: clamp(44px, 6.4vw, 86px);
  line-height: 0.96; letter-spacing: -0.01em; font-weight: 800;
  margin: 14px 0 0; text-wrap: balance;
}
.headline .lo { color: var(--muted); font-weight: 300; }
.headline .hi { color: var(--accent); }
.hero-sub {
  margin-top: 20px; max-width: 58ch; font-size: clamp(16px, 2vw, 20px);
  color: var(--ink-2); line-height: 1.55; text-wrap: pretty;
}
.hero .hero-field {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: 0.9;
  -webkit-mask-image: linear-gradient(100deg, transparent 6%, rgba(0,0,0,0.22) 34%, rgba(0,0,0,0.85) 66%, #000 88%);
  mask-image: linear-gradient(100deg, transparent 6%, rgba(0,0,0,0.22) 34%, rgba(0,0,0,0.85) 66%, #000 88%);
}
/* Nested so the two masks intersect: the diagonal is on the wrapper, the vertical
   fade here, which needs no mask-composite. Without it the field ends on a hard
   horizontal edge and reads as a drawn rectangle. */
#hero-art {
  position: absolute; inset: 0; width: 100%; height: 100%;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 14%, #000 58%, transparent 97%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 14%, #000 58%, transparent 97%);
}
/* The hero was sized by its copy alone; the field needs room to read as a field. */
.hero { min-height: 460px; }
.hero::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(to right, transparent, var(--line) 20%, var(--line) 80%, transparent);
}
@media (max-width: 760px) { .hero { min-height: 0; } .hero .hero-field { opacity: 0.55; } }

.hero-actions { margin-top: 26px; display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 13px 22px; border-radius: var(--r); font-size: 14px; font-weight: 600;
  border: 1px solid transparent; cursor: pointer; transition: transform 0.12s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.btn-primary { background: var(--accent); color: var(--accent-ink); }
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 16px 30px -12px var(--glow); }
.btn-ghost { border-color: var(--line-2); color: var(--ink); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }


/* -------------------------------------------------------- proof chain ------ */

/* ---------------------------------------------------------------- shell ---- */
.section:last-of-type { border-bottom: none; }
/* The first section after a hero does not need the full rhythm above it: the
   hero's own bottom padding is already there. */
.wrap > .section:first-child { padding-top: 52px; }
.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 40px; }
.sec-title {
  font-family: var(--display);
  font-size: clamp(27px, 4.1vw, 42px); font-weight: 800;
  letter-spacing: 0.01em; text-transform: uppercase; text-wrap: balance;
}
.sec-kicker { font-size: 13px; color: var(--muted); max-width: 40ch; text-align: right; }


/* stack table */
.stack { border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--paper-2); }
.srow {
  display: grid; grid-template-columns: 168px 1fr 120px; gap: 22px; align-items: center;
  padding: 20px 22px; border-bottom: 1px solid var(--line); transition: background 0.15s ease;
}
.srow:last-child { border-bottom: none; }
.srow:hover { background: var(--sink); }
.s-name { font-weight: 700; font-size: 15px; letter-spacing: -0.01em; }
.s-name .dotmark { color: var(--accent); }
.s-desc { color: var(--ink-2); font-size: 14px; line-height: 1.5; }
.status {
  justify-self: end; display: inline-flex; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.4px; text-transform: uppercase;
}
.status::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.status.live { color: var(--live); }
.status.build { color: var(--amber); }


/* contact */
.contact-grid { display: grid; grid-template-columns: 1.25fr 1fr; gap: 40px; }
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--muted); margin-bottom: 7px; }
.in {
  width: 100%; background: var(--paper-2); border: 1px solid var(--line-2); border-radius: var(--r);
  color: var(--ink); padding: 12px 14px; font-size: 15px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.in::placeholder { color: var(--muted); }
.in:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--glow); }
textarea.in { resize: vertical; min-height: 110px; }
.reach { border: 1px solid var(--line); border-radius: var(--r); background: var(--sink); padding: 24px; }
.reach h3 { font-size: 12px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--muted); margin-bottom: 16px; font-weight: 600; }
.rrow { display: flex; justify-content: space-between; align-items: baseline; gap: 14px; padding: 11px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
.rrow:last-child { border-bottom: none; }
.rrow .k { color: var(--muted); }
.rrow .v { color: var(--ink); font-weight: 600; text-align: right; }
.rrow .v a { color: var(--accent); }
.reach-note {
  margin: 16px 0 0; padding-top: 14px; font-size: 13px; line-height: 1.55;
  color: var(--muted); border-top: 1px solid var(--line);
}
.reach-note + .reach-note { margin-top: 12px; }
.reach-note strong { color: var(--ink); }

/* services offer grid */
.offer-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.offer-card {
  border: 1px solid var(--line); border-radius: var(--r); background: var(--paper-2);
  padding: 24px; display: flex; flex-direction: column; gap: 10px;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.offer-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.offer-badge {
  align-self: flex-start; font-size: var(--label); letter-spacing: 1px; text-transform: uppercase;
  font-weight: 600; padding: 3px 9px; border-radius: 100px;
}
.offer-badge.available { color: var(--live); background: color-mix(in srgb, var(--live) 13%, transparent); }
/* Every card in a row carries a badge, because the badge is the first flex child
   and a card without one lifts its own heading out of line with its siblings. */
.offer-badge.partial { color: var(--amber); background: color-mix(in srgb, var(--amber) 13%, transparent); }
.offer-name { font-size: 18px; font-weight: 700; letter-spacing: -0.01em; }
.offer-desc { color: var(--ink-2); font-size: 14px; line-height: 1.55; flex: 1; }
.offer-cta { align-self: flex-start; font-size: 13px; font-weight: 600; color: var(--accent); margin-top: auto; padding: 6px 0; }
.offer-cta:hover { text-decoration: underline; }
.offer-card.link { text-decoration: none; }
.offer-card.link:hover .offer-cta { text-decoration: underline; }

/* product grid: three across, links out to each product domain */
.product-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 18px; }


/* footer */
.foot { padding: 28px 0 36px; text-align: center; }
.foot .tag { font-size: 13px; color: var(--muted); }

/* policy prose (disclosure) */
.policy-h1 { font-size: clamp(30px, 5vw, 46px); font-weight: 800; letter-spacing: -0.025em; line-height: 1.08; text-wrap: balance; }
.policy-meta { margin-top: 18px; font-family: var(--mono); font-size: 12px; color: var(--muted); }
.policy { max-width: 44rem; }
.policy-h2 { font-size: 20px; font-weight: 700; letter-spacing: -0.01em; color: var(--ink); margin: 42px 0 14px; }
.policy-h2:first-child { margin-top: 0; }
.policy p { font-size: 16px; line-height: 1.65; color: var(--ink-2); margin-bottom: 14px; }
.policy p strong { color: var(--ink); font-weight: 600; }
.policy code { font-family: var(--mono); font-size: 14px; background: var(--sink); padding: 1px 5px; border-radius: var(--r); color: var(--ink); }
.policy-list { margin: 0 0 16px; padding: 0; }
.policy-list li { position: relative; padding: 8px 0 8px 20px; font-size: 15px; line-height: 1.6; color: var(--ink-2); border-bottom: 1px solid var(--line); }
.policy-list li:last-child { border-bottom: none; }
.policy-list li::before { content: "-"; position: absolute; left: 0; color: var(--accent); font-family: var(--mono); }
.policy-list li strong { color: var(--ink); font-weight: 600; }

/* --------------------------------------------------------- responsive ------ */
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; gap: 8px; }
  .contact-grid { grid-template-columns: 1fr; gap: 26px; }
  .offer-grid { grid-template-columns: 1fr; }
  .product-grid { grid-template-columns: repeat(2, 1fr); }
  .srow { grid-template-columns: 1fr; gap: 8px; }
  .status { justify-self: start; }
  .sec-head { flex-direction: column; align-items: flex-start; }
  .sec-kicker { text-align: left; }
}
@media (max-width: 620px) {
  .hero { padding: 44px 0 34px; }
  .product-grid { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .btn:hover { transform: none; }
}

/* ===========================================================================
   Consolidated site: everything below serves the product, service, solutions
   and compliance pages that moved onto this domain. The block above is the
   original company-page system and its token vocabulary; these families were
   written against a second vocabulary (--border/--surface/--heading/--text),
   so that vocabulary is aliased once here rather than renamed across the
   markup. Aliases sit after every theme block, so each resolves to whichever
   definition won for the current theme.
   =========================================================================== */

:root {
  --border:    var(--line);
  --surface:   var(--paper-2);
  --heading:   var(--ink);
  --text:      var(--ink-2);
  --bg:        var(--paper);
  --link:      var(--accent);
  --highlight: var(--sink);
}

/* ------------------------------------------------------------- mega nav ---- */
/* Hover and keyboard both open a panel; nothing here needs JavaScript. The
   panel anchors to .topbar-inner rather than to its own item, which is what
   lets a mega-menu span the bar. */
.topbar-inner { position: relative; }
.nav-toggle { display: none; }
.topnav { gap: 4px; }
.nav-item { position: static; }
.nav-item.has-drop { position: relative; }
.nav-top {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 12px; border-radius: var(--r); font-size: 13px; color: var(--muted);
  transition: color 0.15s ease, background 0.15s ease;
}
.nav-top:hover, .nav-item:focus-within .nav-top { color: var(--ink); background: var(--sink); }
/* Menu triggers are <button>s; reset the UA chrome a nav link never had. Set only
   font-family: the `font` shorthand would reset font-size too and outrank .nav-top. */
button.nav-top {
  background: none; border: 0; margin: 0; padding: 9px 12px;
  font-family: inherit; font-weight: inherit; letter-spacing: inherit;
  color: var(--muted); cursor: pointer;
}
.nav-item.has-menu .nav-top::after {
  content: ""; width: 5px; height: 5px; margin-top: -2px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); opacity: 0.7;
}

.menu {
  position: absolute; top: 100%; z-index: 40;
  background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: var(--shadow);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity 0.12s ease, transform 0.12s ease, visibility 0.12s;
}
/* A hover and a focus are what a mouse and a keyboard have; a touch screen has neither, so
   the trigger is also a disclosure the script toggles. */
.nav-item:hover > .menu,
.nav-item:focus-within > .menu,
.nav-item[data-open="true"] > .menu { opacity: 1; visibility: visible; transform: none; }
.menu-mega { left: 28px; right: 28px; }
/* right, not left: the bar is right-aligned, so a panel anchored to its item's left
   edge hangs off the end of the page and widened every desktop page by 46px. */
.menu-drop { right: 0; min-width: 232px; padding: 8px; }
/* auto-fit, NOT a fixed count: the grid followed a three-child layout that no
   dropdown has any more, so the third track rendered as blank space in both.
   A hard-coded column count is a second place to remember how many children
   there are. */
.menu-inner { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 0; }
.menu-col { padding: 22px 24px; border-right: 1px solid var(--line); }
.menu-col:last-child { border-right: none; }
.menu-head {
  font-size: var(--label); letter-spacing: 2px; text-transform: uppercase;
  color: var(--muted); font-weight: 700; margin-bottom: 12px;
}
.menu-lnk { display: block; padding: 8px 10px; margin: 0 -10px; border-radius: var(--r); }
.menu-lnk:hover { background: var(--sink); }
.menu-lnk b { display: block; font-size: 14px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }
.menu-lnk span { display: block; font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.5px; color: var(--muted); margin-top: 2px; }
.menu-lnk:hover b { color: var(--accent); }
.menu-panel { padding: 22px 24px; background: var(--sink); border-radius: 0 var(--r) var(--r) 0; }
.menu-panel p { font-size: 13px; line-height: 1.55; color: var(--ink-2); margin-bottom: 14px; }
.menu-panel p b { color: var(--ink); }
.menu-panel .menu-lnk { margin: 0 -10px; }

/* Below the breakpoint the menus were hidden outright while their triggers stayed on
   screen -- a chevron that opens nothing -- on a strip whose later items sat off the side
   of the page and were reachable only by swiping it sideways. So the whole navigation
   becomes one panel the toggle opens, and each group opens in place inside it. */
@media (max-width: 1020px) {
  .nav-toggle {
    display: inline-flex; align-items: center; gap: 9px; margin-left: auto;
    min-height: 44px; padding: 10px 14px; background: none;
    border: 1px solid var(--line-2); border-radius: var(--r);
    font-family: var(--mono); font-size: var(--label-sm); letter-spacing: 1.5px;
    text-transform: uppercase; color: var(--ink); cursor: pointer;
  }
  .nav-toggle[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }
  .nav-toggle-bars, .nav-toggle-bars::before, .nav-toggle-bars::after {
    display: block; width: 16px; height: 1px; background: currentColor;
  }
  .nav-toggle-bars { position: relative; }
  .nav-toggle-bars::before, .nav-toggle-bars::after { content: ""; position: absolute; left: 0; }
  .nav-toggle-bars::before { top: -5px; }
  .nav-toggle-bars::after { top: 5px; }

  .topnav { display: none; }
  .topnav[data-open="true"] {
    display: flex; flex-direction: column; align-items: stretch; gap: 0;
    position: absolute; left: 0; right: 0; top: 100%;
    max-height: calc(100vh - 100%); overflow-y: auto;
    padding: 8px var(--gutter) 24px;
    background: var(--paper); border-top: 1px solid var(--line); box-shadow: var(--shadow);
  }
  .topnav[data-open="true"] .nav-top { padding: 12px 0; font-size: 14px; min-height: 44px; }
  .topnav[data-open="true"] .nav-item { border-bottom: 1px solid var(--line); }
  .topnav[data-open="true"] .nav-item.has-menu .nav-top { width: 100%; justify-content: space-between; }
  /* In flow, so an open group pushes the ones under it down rather than covering them. */
  .topnav[data-open="true"] .menu {
    display: none; position: static; opacity: 1; visibility: visible; transform: none;
    background: none; border: 0; box-shadow: none; padding: 0 0 10px;
  }
  .topnav[data-open="true"] .nav-item[data-open="true"] > .menu { display: block; }
  .topnav[data-open="true"] .menu-inner { grid-auto-flow: row; }
  .topnav[data-open="true"] .menu-col,
  .topnav[data-open="true"] .menu-panel { padding: 0; border-right: 0; background: none; }
  .topnav[data-open="true"] .menu-lnk { margin: 0; padding: 10px 0; }
}
@media (max-width: 620px) {
  /* 44px minimum touch target: these carry chip styling, so the inline-link
     exception to WCAG 2.5.8 does not apply to them. */
  .nav-top { padding: 12px 10px; font-size: 12px; min-height: 44px; }
}

/* ------------------------------------------------------------ page shell --- */
.page-hero { padding: 54px 0 30px; }
.page-hero .headline { font-size: clamp(32px, 5vw, 56px); margin-top: 14px; }
.page-hero .hero-sub { max-width: 66ch; }
.breadcrumbs { font-size: 12px; color: var(--muted); margin-bottom: 4px; }
.breadcrumbs a:hover { color: var(--accent); }
.codename {
  display: inline-block; font-family: var(--mono); font-size: var(--label); letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--accent-2); background: var(--accent-wash);
  border-radius: 100px; padding: 3px 10px; margin-left: 10px; vertical-align: 6px;
}
.sec-sub { font-size: 16px; line-height: 1.65; color: var(--ink-2); max-width: 68ch; margin-bottom: 22px; }
.sec-sub b, .sec-sub strong { color: var(--ink); font-weight: 600; }
.note { font-size: 13px; line-height: 1.6; color: var(--muted); max-width: 68ch; margin-top: 14px; }
.note b { color: var(--ink-2); }
.s-desc .role { font-family: var(--mono); font-size: 13px; color: var(--muted); }

/* The numbers band. Every figure on it traces to a file in the engine tree. */
.proof-row {
  display: flex; gap: 26px; flex-wrap: wrap;
  padding: 16px 0; margin: 26px 0 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.proof { font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.4px; color: var(--ink-2); }
.proof strong { color: var(--accent); font-weight: 700; }

/* A list where each item leads with the claim. */
.threat-list { max-width: 72ch; }
.threat-list li {
  position: relative; padding: 12px 0 12px 20px; border-bottom: 1px solid var(--line);
  font-size: 14.5px; line-height: 1.65; color: var(--ink-2);
}
.threat-list li:last-child { border-bottom: none; }
.threat-list li::before { content: "+"; position: absolute; left: 0; color: var(--accent); font-family: var(--mono); }
.threat-list li strong { color: var(--ink); font-weight: 600; }

/* What a claim does NOT cover, stated beside the claim rather than in an
   appendix. This is the block that keeps the rest of a page honest. */
.limit { border-left: 3px solid var(--accent); background: var(--sink); padding: 18px 20px; margin: 0 0 20px; max-width: 72ch; }
.limit-label { font-family: var(--mono); font-size: var(--label); letter-spacing: 2px; text-transform: uppercase; color: var(--accent); margin-bottom: 8px; }
.limit p { font-size: 14px; line-height: 1.65; color: var(--ink-2); margin: 0; }
.limit p + p { margin-top: 12px; }
.limit strong { color: var(--ink); font-weight: 600; }

.faq-block { padding: 20px 0; border-bottom: 1px solid var(--line); max-width: 72ch; }
.faq-block:last-child { border-bottom: none; }
.faq-q { font-size: 15px; font-weight: 600; color: var(--ink); margin-bottom: 8px; }
.faq-a { font-size: 14.5px; line-height: 1.7; color: var(--ink-2); }
.faq-a strong { color: var(--ink); font-weight: 600; }

/* Wide tables scroll inside their own box so the page body never does. */
.ev-wrap { overflow-x: auto; margin: 0 0 20px; }
.ev-table { width: 100%; border-collapse: collapse; font-size: 14px; min-width: 640px; }
.ev-table th {
  font-family: var(--mono); font-size: var(--label); letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--accent); text-align: left; font-weight: 600;
  padding: 11px 16px 11px 0; border-bottom: 1px solid var(--line-2); vertical-align: bottom;
}
.ev-table td { padding: 14px 16px 14px 0; border-bottom: 1px solid var(--line); color: var(--ink-2); line-height: 1.6; vertical-align: top; }
.ev-table td:first-child { color: var(--ink); font-weight: 600; }
.ev-table tr:last-child td { border-bottom: none; }
.ev-date { font-family: var(--mono); white-space: nowrap; color: var(--ink); }

.entrance-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
.entrance-card {
  display: block; border: 1px solid var(--line); border-top: 2px solid var(--accent);
  border-radius: var(--r); padding: 24px; background: var(--paper-2);
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.entrance-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.entrance-who { font-family: var(--mono); font-size: var(--label); letter-spacing: 2px; text-transform: uppercase; color: var(--muted); margin-bottom: 10px; }
.entrance-name { font-size: 19px; font-weight: 700; letter-spacing: -0.01em; color: var(--ink); margin-bottom: 10px; }
.entrance-desc { font-size: 14px; line-height: 1.65; color: var(--ink-2); margin-bottom: 14px; }
.entrance-cta { font-size: 13px; font-weight: 600; color: var(--accent); }

.platform-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.platform-card { border: 1px solid var(--line); border-radius: var(--r); padding: 18px; background: var(--paper-2); text-align: center; }
.platform-name { font-size: 14px; font-weight: 600; color: var(--ink); margin-bottom: 6px; }
.platform-status { font-family: var(--mono); font-size: var(--label); letter-spacing: 1px; text-transform: uppercase; color: var(--live); }

/* Role bands on /solutions. One band per role, and the shared substance is
   written once above them, which is the whole reason this is one page. */
/* The two audiences are unrelated, so they get two columns rather than two
   stacked sections a reader has to keep re-deciding about. */
.aud-split { display: grid; grid-template-columns: 1fr 1fr; gap: 0; }
.aud-col { padding: 0 36px; border-left: 1px solid var(--line); }
.aud-col:first-child { padding-left: 0; border-left: none; }
.aud-col:last-child { padding-right: 0; }
.aud-for { font-family: var(--mono); font-size: var(--label); letter-spacing: 1.5px; text-transform: uppercase; color: var(--accent); margin-bottom: 10px; }
.aud-title { font-size: 22px; font-weight: 700; letter-spacing: -0.01em; color: var(--ink); margin-bottom: 10px; }
.aud-lede { font-size: 15px; line-height: 1.65; color: var(--ink-2); margin-bottom: 8px; max-width: 48ch; }
.aud-step { border-top: 1px solid var(--line); padding: 15px 0; }
.aud-step-tag { font-family: var(--mono); font-size: var(--label); letter-spacing: 1.5px; text-transform: uppercase; color: var(--muted); }
.aud-step-name { font-size: 16px; font-weight: 650; color: var(--ink); margin: 5px 0; }
.aud-step-desc { font-size: 14px; line-height: 1.6; color: var(--ink-2); }
/* These carry their own display: they sit on a <p> on the agent pages and on a
   <span> inside the consultation radio label, where inline ran all six into one. */
.aud-step-name, .aud-step-desc { display: block; }
label.aud-step { display: grid; grid-template-columns: auto 1fr; column-gap: 12px; align-items: start; cursor: pointer; }
label.aud-step > input { grid-row: 1 / span 2; margin-top: 4px; }
/* What is TRUE at the end of the day, lifted from the course's own outcome line. */
.aud-step-out { font-size: 14px; line-height: 1.6; color: var(--ink); font-weight: 550; margin-top: 7px; padding-left: 11px; border-left: 2px solid var(--accent); }
@media (max-width: 860px) {
  .aud-split { grid-template-columns: 1fr; }
  .aud-col { padding: 26px 0 0; border-left: none; border-top: 2px solid var(--line-2); margin-top: 26px; }
  .aud-col:first-child { border-top: none; margin-top: 0; padding-top: 0; }
}

.role-band { border-top: 1px solid var(--line); padding: 26px 0; display: grid; grid-template-columns: 210px 1fr; gap: 30px; }
.role-band:first-of-type { border-top: none; }
.role-who { font-size: 17px; font-weight: 700; letter-spacing: -0.01em; color: var(--ink); }
.role-who span { display: block; font-family: var(--mono); font-size: var(--label); letter-spacing: 1.5px; text-transform: uppercase; color: var(--muted); margin-top: 6px; font-weight: 400; }
.role-body p { font-size: 14.5px; line-height: 1.7; color: var(--ink-2); margin-bottom: 10px; max-width: 68ch; }
.role-body p strong { color: var(--ink); font-weight: 600; }
.role-gets { font-size: 13px; color: var(--muted); }
.role-gets b { font-family: var(--mono); font-size: var(--label); letter-spacing: 1.5px; text-transform: uppercase; color: var(--accent); margin-right: 8px; }

/* Sitemap footer */
.foot-map { border-top: 1px solid var(--line); padding: 44px 0 10px; }
/* auto-fit, not a hardcoded count: the 5 here outlived a fifth column and left an
   empty track, and a literal has to be edited every time a column is added. */
.foot-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 24px; }
.foot-col h5 { font-size: var(--label); letter-spacing: 2px; text-transform: uppercase; color: var(--muted); font-weight: 700; margin-bottom: 14px; }
.foot-col a { display: block; font-size: 13px; color: var(--ink-2); padding: 7px 0; }
.foot-col a:hover { color: var(--accent); }

@media (max-width: 900px) {
  .entrance-grid { grid-template-columns: 1fr; }
  .platform-grid { grid-template-columns: 1fr; }
  .role-band { grid-template-columns: 1fr; gap: 12px; }
  .foot-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .proof-row { gap: 14px; }
}
@media (max-width: 620px) {
  .foot-cols { grid-template-columns: 1fr; }
}

/* ------------------------------------------- shared analysis components ----
   Written for the firmware page and reused by the endpoint, services, solutions
   and CRA pages, which is why they live here rather than in board.css. That file
   now holds only what draws the 23-component map.
   --------------------------------------------------------------------------- */
/* Five outcomes, five cards. A run that stopped is not a run that finished,
   and the strip exists to say which one happened. */
.outcome-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin: 4px 0 16px; }
.outcome-card { border: 1px solid var(--border); border-top: 2px solid var(--accent); background: var(--surface); padding: 14px 14px 16px; }
.outcome-name { font-family: var(--mono); font-size: 11px; letter-spacing: 2px; text-transform: uppercase; color: var(--heading); margin-bottom: 8px; }
.outcome-desc { font-size: 12px; line-height: 1.55; color: var(--text); }
.outcome-desc code { font-family: var(--mono); font-size: 11px; color: var(--accent); }

/* The pipeline: what the bytes pass through, in order. */
.stage-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0; margin: 4px 0 18px; border: 1px solid var(--border); }
.stage { padding: 14px 16px; border-right: 1px solid var(--border); background: var(--surface); }
.stage:last-child { border-right: none; }
.stage-n { font-family: var(--mono); font-size: var(--label-sm); letter-spacing: 2px; color: var(--muted); margin-bottom: 8px; }
.stage-name { font-family: var(--mono); font-size: 11px; letter-spacing: 2px; text-transform: uppercase; color: var(--accent); margin-bottom: 8px; }
.stage-desc { font-size: 12px; line-height: 1.55; color: var(--text); }

@media (max-width: 900px) {
  .outcome-grid { grid-template-columns: repeat(2, 1fr); }
  .stage-row { grid-template-columns: 1fr; }
  .stage { border-right: none; border-bottom: 1px solid var(--border); }
  .stage:last-child { border-bottom: none; }
}

@media (max-width: 768px) {
  .outcome-grid { grid-template-columns: 1fr; }
}

/* Device classes, one card per class. The count is the evidence: functions
   lifted from that class's own pinned image, so a reader can ask which image. */
.ind-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin: 4px 0 12px; }
.ind { border: 1px solid var(--border); border-left: 3px solid var(--border); padding: 12px 14px; background: var(--surface); }
.ind-on { border-left-color: var(--accent); }
.ind-name { display: block; font-size: 13px; line-height: 1.35; color: var(--muted); margin-bottom: 6px; }
.ind-on .ind-name { color: var(--heading); }
.ind-fn { font-family: var(--mono); font-size: 11px; letter-spacing: 1px; color: var(--muted); font-variant-numeric: tabular-nums; }
.ind-on .ind-fn { color: var(--accent); }

@media (max-width: 900px) { .ind-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 768px) { .ind-grid { grid-template-columns: 1fr; } }

/* Stage counts. The pipeline is three stages on the firmware page and four on the
   services page, so the count is a modifier rather than two families. */
.stage-row-3 { grid-template-columns: repeat(3, 1fr); }
.stage-row-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) {
  .stage-row-3, .stage-row-4 { grid-template-columns: 1fr; }
}

/* A region the reader has to drag needs to look draggable. */
.ev-wrap { position: relative; }
.ev-wrap::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 28px;
  pointer-events: none;
  background: linear-gradient(to right, transparent, var(--paper));
}

/* ------------------------------------------------- screenshot placeholders --
   Deliberately empty frames, each captioned with exactly what belongs in it and
   sized to the real aspect ratio so the layout is final before the captures
   land. They read as unfinished on purpose: a drawn mock of a UI we have not
   photographed would be a picture of a product rather than of this one.
   --------------------------------------------------------------------------- */

.shot { margin: 0 0 6px; }

/* The frame a figure sits in. It carries no aspect-ratio: each figure's own
   viewBox is sized to its content, so a fixed ratio here would letterbox it. */
.shot-frame {
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--sink);
  overflow: hidden;
}
/* A wide technical figure is scrolled, not shrunk. Measured 2026-10-18 at 320px: fitted to
   the frame these figures render at 0.26 scale, which puts their 12-unit row text at 3.1px.
   920px is where that text clears the 11px floor (11 / 12 * 1000 units), so under that the
   figure pans. Above it the min-width does nothing and no scrollbar appears.
   `.dia` is the one wide figure drawn without a frame, and it is here rather than in a rule
   of its own because it had the same two declarations already. */
.shot-art, .dia { overflow-x: auto; overflow-y: hidden; }
.shot-art svg, .dia svg { display: block; width: 100%; height: auto; }
/* Under this the column is narrower than the figure can render legibly, so it pans rather
   than shrinking its 12-unit row text under the 11px floor. Above it the figure fits. */
@media (max-width: 1020px) {
  .shot-art svg, .dia svg { min-width: 920px; }
}

.shot figcaption { display: block; margin-top: 12px; }
.shot-label {
  display: inline-block; margin-right: 8px;
  font-family: var(--mono); font-size: var(--label-sm); letter-spacing: 2px; text-transform: uppercase;
  color: var(--accent); border: 1px solid var(--accent); border-radius: 100px; padding: 3px 10px;
  vertical-align: 2px;
}
.shot-what { font-size: 13px; line-height: 1.55; color: var(--ink-2); }
/* Whether this was measured, designed, or redacted. It belongs next to the
   figure rather than in a footnote nobody reaches. */
.shot-note { display: block; margin-top: 6px; font-size: 12px; line-height: 1.5; color: var(--muted); }

/* A frame beside prose, which is the shape most of these take. */
.shot-split { display: grid; grid-template-columns: 1fr 1fr; gap: 34px; align-items: center; }
.shot-split.flip .shot { order: -1; }
.shot-split p { font-size: 15px; line-height: 1.65; color: var(--ink-2); margin-bottom: 12px; }
.shot-split p:last-child { margin-bottom: 0; }
.shot-split p strong { color: var(--ink); font-weight: 600; }
.shot-split h3 {
  font-size: 19px; font-weight: 700; letter-spacing: -0.01em; color: var(--ink); margin-bottom: 10px;
}

/* Three across, the shape a feature row takes. */
.shot-row { display: grid; grid-template-columns: 1fr; gap: 34px; }
/* min-width: 0 because a grid item defaults to its content's min-content width, and a
   figure that may not shrink below 920px would otherwise widen the whole track. */
.shot-row > *, .shot-split > *, .shot { min-width: 0; }
.shot-row h3 { font-size: 15px; font-weight: 700; color: var(--ink); margin: 12px 0 6px; }
.shot-row p { font-size: 13.5px; line-height: 1.6; color: var(--ink-2); }

@media (max-width: 900px) {
  .shot-split { grid-template-columns: 1fr; gap: 20px; }
  .shot-split.flip .shot { order: 0; }
  .shot-row { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------- feature blocks ---
   One block per capability: a noun kicker, an outcome heading, a short body, one
   action, one frame. The landing page used to carry a card grid AND a row table
   for the same five products, so each was described twice; this is the single
   treatment that replaced both.
   --------------------------------------------------------------------------- */

.feature {
  display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: center;
  padding: 38px 0; border-bottom: 1px solid var(--line);
}
.feature:last-of-type { border-bottom: none; }
.feature.flip .shot { order: -1; }
.feature-kicker {
  font-family: var(--mono); font-size: var(--label); letter-spacing: 2px; text-transform: uppercase;
  color: var(--accent); margin-bottom: 10px;
}
.feature-copy h3 {
  font-size: clamp(21px, 2.6vw, 27px); font-weight: 700; letter-spacing: -0.02em;
  line-height: 1.2; color: var(--ink); margin-bottom: 12px; text-wrap: balance;
}
.feature-copy p { font-size: 15px; line-height: 1.65; color: var(--ink-2); margin-bottom: 16px; max-width: 52ch; }
.feature-copy .offer-cta { display: inline-block; }

/* The mid-page conversion band. */

@media (max-width: 900px) {
  .feature { grid-template-columns: 1fr; gap: 22px; padding: 28px 0; }
  .feature.flip .shot { order: 0; }
}

/* ---------------------------------------------------------------- diagrams --
   Authored mechanism drawings, not pictures of a UI. Colours come from the theme
   tokens rather than literals, so these follow light and dark like the rest of
   the page; the board is the exception that keeps its own substrate because it
   depicts a physical object. Every one carries a title, a desc and a text
   equivalent beneath it, so nothing here is load-bearing for a reader who cannot
   see it.
   --------------------------------------------------------------------------- */

.dia { margin: 0 0 8px; }
.dia figcaption { font-size: 12.5px; line-height: 1.6; color: var(--muted); margin-top: 12px; max-width: 68ch; }
.dia figcaption b { color: var(--ink-2); font-weight: 600; }

.d-box   { fill: var(--paper-2); stroke: var(--line-2); stroke-width: 1.5; }
.d-box-a { fill: var(--accent-wash); stroke: var(--accent); stroke-width: 1.5; }
.d-box-d { fill: none; stroke: var(--line-2); stroke-width: 1.5; stroke-dasharray: 5 4; }
.d-label { fill: var(--ink); font-size: 13px; font-weight: 600; }
.d-sub   { fill: var(--muted); font-size: 11px; font-family: var(--mono); }
.d-accent{ fill: var(--accent); font-size: 11px; font-family: var(--mono); }
.d-flow  { fill: none; stroke: var(--accent); stroke-width: 2; }
.d-weak  { fill: none; stroke: var(--line-2); stroke-width: 1.5; stroke-dasharray: 5 4; }
.d-stop  { fill: none; stroke: var(--muted); stroke-width: 3; }
.d-head  { fill: var(--accent); }
.d-head-w{ fill: var(--line-2); }

/* Hero tick list, and the three-rule band that replaced a bare bullet list. */

/* ------------------------------------------------------ signed-in chrome ---
   The logged-in area is the same design system as the marketing pages, on a
   standalone base: this template engine refuses a chained `extends`, so
   `app_base` cannot inherit the marketing chrome and carries its own.
   --------------------------------------------------------------------------- */

.auth-pane { max-width: 34rem; }
.auth-pane .sec-title { margin-bottom: 12px; }
.auth-pane .sec-sub { margin-bottom: 26px; }
.auth-pane .btn { margin-top: 4px; }
.auth-pane .note { margin-top: 16px; }
.auth-pane .limit { margin-top: 26px; }

.nav-user { font-family: var(--mono); font-size: 12px; color: var(--muted); padding: 0 10px; }
.nav-signout { display: inline-flex; }

.flash {
  border: 1px solid var(--line-2); border-left-width: 3px; border-radius: var(--r);
  background: var(--sink); padding: 12px 16px; margin: 22px 0 0;
  font-size: 14px; color: var(--ink-2);
}
.flash-error { border-left-color: var(--amber); }
.flash-success { border-left-color: var(--live); }

/* The switcher between products, which exists only when a customer holds
   more than one. A single-product account never renders this at all. */
.lens-switch { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 26px; }
.lens-switch a {
  font-size: 13px; color: var(--muted); padding: 8px 14px;
  border: 1px solid var(--line); border-radius: var(--r);
}
.lens-switch a:hover { color: var(--ink); border-color: var(--accent); }

/* ---- technical field -------------------------------------------------- */
/* A lattice, not a texture: drawn in gradients so it re-tints with the theme
   and ships no image. Hero only, faded out downward, never under body text. */
.hero::before {
  content: ""; position: absolute; inset: -60px 0 auto; height: 420px; z-index: 0;
  background:
    repeating-linear-gradient(to right, var(--glow) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(to bottom, var(--glow) 0 1px, transparent 1px 64px);
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0.55), transparent 85%);
  mask-image: linear-gradient(to bottom, rgba(0,0,0,0.55), transparent 85%);
  pointer-events: none;
}
.hero > * { position: relative; z-index: 1; }

/* The panel edge: a hairline the accent owns, on the side the eye enters from. */
.btn-primary { box-shadow: 0 10px 24px -14px var(--glow); }
.shot-frame { box-shadow: -2px 0 0 var(--accent), var(--shadow); }

/* ---- hero panel ------------------------------------------------------- */
/* The per-page graphic: says what the page is before a word is read. Square,
   drawn in house SVG against the theme tokens, decorative to assistive tech. */
.hero-panel { position: relative; aspect-ratio: 1 / 1; width: 100%; max-width: 420px; margin-left: auto; }
.hero-panel svg { width: 100%; height: 100%; display: block; }
.page-hero .hero-panel { max-width: 300px; }
@media (max-width: 860px) {
  .hero-panel { order: -1; max-width: 300px; margin: 0 auto 10px; }
}

/* ---- HUD framing ------------------------------------------------------ */
/* Corner brackets rather than a full border: the panel reads as an instrument
   housing, and the rule the eye follows is still the one the card already had. */
.shot-frame, .offer-card, .platform-card, .entrance-card { position: relative; }
.shot-frame::before, .shot-frame::after,
.offer-card::before, .offer-card::after,
.platform-card::before, .platform-card::after,
.entrance-card::before, .entrance-card::after {
  content: ""; position: absolute; width: 12px; height: 12px; pointer-events: none;
  border-color: var(--accent); opacity: 0.6;
}
.shot-frame::before, .offer-card::before, .platform-card::before,
.entrance-card::before {
  top: -1px; left: -1px; border-top: 1px solid; border-left: 1px solid;
}
.shot-frame::after, .offer-card::after, .platform-card::after,
.entrance-card::after {
  bottom: -1px; right: -1px; border-bottom: 1px solid; border-right: 1px solid;
}
.offer-card.link:hover::before, .offer-card.link:hover::after { opacity: 1; width: 18px; height: 18px; }

/* ---- scanlines -------------------------------------------------------- */
/* Over the hero only, under the copy, at an opacity that reads as a surface
   rather than as a pattern. A second layer on ::after keeps the lattice intact. */
.hero::after {
  content: ""; position: absolute; inset: -60px 0 auto; height: 420px; z-index: 0;
  background: repeating-linear-gradient(
    to bottom, rgba(10, 13, 20, 0.045) 0 1px, transparent 1px 3px);
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0.9), transparent 90%);
  mask-image: linear-gradient(to bottom, rgba(0,0,0,0.9), transparent 90%);
  pointer-events: none;
}

/* ======================================================================== */
/* STRUCTURE: butt joints, nested frames, bleeding rules, a page frame.     */
/* The kit's identity is orthogonal and modular rather than chromatic: the  */
/* panels touch, nest and share edges, and nothing floats.                  */
/* ======================================================================== */

/* 1. Butt joints. The grid's own background becomes the hairline between
      modules, so a row of cards reads as one lattice rather than as cards. */
.offer-grid, .product-grid, .platform-grid, .entrance-grid {
  gap: 1px; background: var(--line); border: 1px solid var(--line);
}
.offer-grid > *, .product-grid > *, .platform-grid > *, .entrance-grid > * { border: none; }
.entrance-grid > .entrance-card { border-top: 2px solid var(--accent); }
.offer-grid > :hover, .product-grid > :hover, .entrance-grid > :hover { border-color: transparent; }

/* 2. Nothing floats and nothing lifts: weight answers the pointer, not motion. */
.offer-card:hover, .entrance-card:hover, .btn-primary:hover { transform: none; }
.offer-card, .entrance-card { transition: background 0.15s ease; }
.offer-card.link:hover, .entrance-card:hover { background: var(--accent-wash); }

/* 3. Nested frames: an outer rule and an inset inner rule, concentric, in
      place of a shadow. The inset is what the eye reads as depth.

      NO SECOND `box-shadow` HERE. This file declared the panel edge twice on
      one selector, 68 rules apart, and the later one won: editing the first
      changed nothing, so a violet trim nobody had chosen outlived the
      decision to drop it. The edge is declared once, where the panel's own
      colours are. */
.shot-frame::before, .shot-frame::after { width: 16px; height: 16px; }
.shot-art { position: relative; }
.shot-art::after {
  content: ""; position: absolute; inset: 10px; border: 1px solid var(--line);
  pointer-events: none;
}

/* 4. Section rules bleed the full viewport, with a tick at the column edge. */
.section { position: relative; counter-increment: sec; border-bottom: none; padding: 92px 0 84px; }
.section::before {
  content: ""; position: absolute; top: 0; left: 50%; width: 100vw; height: 1px;
  transform: translateX(-50%); background: var(--line);
}
.section:first-of-type::before { display: none; }
.section::after {
  content: ""; position: absolute; top: -4px; left: 0; width: 1px; height: 9px;
  background: var(--accent); opacity: 0.8;
}

/* 5. Section indices, emitted rather than typed: instrument labels. */
.wrap { counter-reset: sec; }
/* IN THE FLOW, never at a negative offset: the index used to be placed at
   `left: -56px`, which is outside the wrap on any viewport narrower than the
   measure plus both gutters, so the numbers hung off the edge of the page. */
.sec-head { position: relative; }
.sec-head::before {
  content: counter(sec, decimal-leading-zero);
  display: block; margin-bottom: 10px;
  font-family: var(--mono); font-size: 11px; letter-spacing: 2px;
  color: var(--accent);
}

/* 6. The page frame: a hairline housing with corner registration marks and a
      rail. Fixed, decorative, and never in the way of a pointer. */
.frame { position: fixed; inset: 10px; pointer-events: none; z-index: 40; }
.frame i {
  position: absolute; width: 14px; height: 14px; border-color: var(--line-2);
}
.frame i:nth-child(1) { top: 0; left: 0; border-top: 1px solid; border-left: 1px solid; }
.frame i:nth-child(2) { top: 0; right: 0; border-top: 1px solid; border-right: 1px solid; }
.frame i:nth-child(3) { bottom: 0; left: 0; border-bottom: 1px solid; border-left: 1px solid; }
.frame i:nth-child(4) { bottom: 0; right: 0; border-bottom: 1px solid; border-right: 1px solid; }
@media (max-width: 1100px) { .frame { display: none; } }

/* ======================================================================== */
/* RIG: the instrumented layout. Opt-in per page via .rig, so a page adopts  */
/* it one at a time rather than the whole site changing under one commit.    */
/* ======================================================================== */

.rig { position: relative; }

/* THE RAIL IS A BUS, NOT A RULER. A measuring scale says the page is being
   measured, which is not what it is; the kit's own left edge is stacked bar
   segments tapping a spine, and that is what a section index hangs off. */
/* Both are placed off the GRID COLUMN, not off the padding box: `.rig` is the
   wrap, so its own `left: 0` is outside the gutter and every decoration drawn
   from it landed a gutter's width left of the column it belongs to. */
/* ONE WALL, and nothing else drawn in the rail. The rail used to carry a tick
   ruler, which says the page is being measured; what it is actually for is
   giving every section an index that is attached to something. The wall is the
   thing the index attaches to, and a laid-out opaque cell on it cannot collide
   with what is drawn under it, which bare text over a ruler did. */


/* THE RAIL IS A COLUMN, NOT A PADDING, and the index is a grid item rather
   than an absolutely placed one. Offsetting it by -92px put it outside the
   wrap on any viewport narrower than the measure, so the numbers hung off the
   left edge of the page; a laid-out column cannot leave the page. */
/* The wall is painted by the SECTION, not by the page, so it is positioned off
   the same box the rail column is measured from. Drawn from the wrap it was a
   gutter adrift of the column it belongs to, because an absolutely positioned
   decoration resolves against the padding box and the column against the
   content box. */
.rig .section {
  display: grid; grid-template-columns: var(--rail) 0.82fr 2.18fr; column-gap: 28px;
  padding: 76px 0 68px; position: relative;
  background-image: linear-gradient(var(--line), var(--line));
  background-size: 1px 100%;
  background-position: calc(var(--rail) - 1px) 0;
  background-repeat: no-repeat;
}
.rig .sec-head {
  grid-column: 2; grid-row: 1 / span 99; position: sticky; top: 96px;
  align-self: start; flex-direction: column; align-items: flex-start;
  text-align: left; margin-bottom: 0; gap: 10px;
}
.rig .sec-kicker { text-align: left; max-width: 28ch; }
.rig .sec-title { font-size: clamp(22px, 2.6vw, 30px); }
.rig .section > *:not(.sec-head) { grid-column: 3; }
.rig .section:nth-of-type(even) > *:not(.sec-head) { margin-left: 7%; }

/* A section with no heading has nothing for the middle column, so its body
   takes the whole measure beside the rail. Seven sections are built this way,
   the landing page's feature blocks among them. */
.rig .section:not(:has(.sec-head)) { grid-template-columns: var(--rail) 1fr; }
.rig .section:not(:has(.sec-head)) > * { grid-column: 2; }
.rig .section:not(:has(.sec-head)):nth-of-type(even) > * { margin-left: 0; }

/* The index belongs to the SECTION, not to its heading: a headless section
   printed no number at all while its neighbours did. */
/* A CELL, not a floating figure. Bare text over the rail collided with
   whatever the rail drew under it; a filled cell masks the bus it sits on and
   cannot overlap anything, because it is laid out and opaque. */
.rig .sec-head::before { content: none; }
.rig .section::after {
  content: counter(sec, decimal-leading-zero);
  position: relative; z-index: 1;
  grid-column: 1; grid-row: 1; justify-self: end; align-self: start;
  display: grid; place-items: center; margin-top: 2px;
  width: 38px; height: 26px; padding: 0;
  background: var(--paper); border: 1px solid var(--line-2);
  border-right: 2px solid var(--accent);
  font-family: var(--mono); font-size: 13px; letter-spacing: 1px;
  color: var(--accent);
}

/* Module IDs: every card in the rig is a numbered unit, printed on the unit. */
.rig .platform-grid, .rig .offer-grid, .rig .entrance-grid, .rig .product-grid { counter-reset: mod; }
.rig .platform-card .platform-name::before,
.rig .offer-card .offer-name::before,
.rig .entrance-card .entrance-name::before {
  counter-increment: mod; content: "M-" counter(mod, decimal-leading-zero);
  display: block; font-family: var(--mono); font-size: var(--label-sm); font-weight: 400;
  letter-spacing: 2px; color: var(--accent); opacity: 0.75; margin-bottom: 7px;
}

/* The hero in the same geometry: copy left and wide, panel right and dropped,
   with the rail running past both. */
/* Aligned to the BODY column, not to an invented offset: the hero sits over
   the same measure the sections below it use. */
.rig-hero { padding-left: calc(var(--gutter) + var(--rail) + 28px); position: relative; }
.rig-hero .hero-copy { max-width: 1000px; }

@media (max-width: 1100px) {
  .rig-hero { padding-left: 0; }
  .rig::before, .rig::after { display: none; }
  .rig .section, .rig .section:not(:has(.sec-head)) { grid-template-columns: 1fr; column-gap: 0; }
  .rig .section::after { grid-column: 1; grid-row: auto; justify-self: start; margin-bottom: 6px; }
  .rig .sec-head { position: static; grid-row: auto; margin-bottom: 26px; }
  .rig .section > *:not(.sec-head), .rig .section:nth-of-type(even) > *:not(.sec-head) { grid-column: 1; margin-left: 0; }
}

/* The board is a wide diagram, not a square panel: it takes the hero's whole
   measure under the copy rather than a column beside it, and keeps the
   horizontal scroll board.css gives it on a narrow screen. */

/* ======================================================================== */
/* APP SURFACES: the signed-in and auth pages.                              */
/* They were styled by app.css and workspace.css, which no template links    */
/* and which read main.css's tokens that this sheet does not define, so      */
/* every one of them rendered unstyled. Written here against this sheet's    */
/* own tokens rather than linked, so they carry the same theme as the rest.  */
/* ======================================================================== */

/* The nav and footer come from base.html.rampart, so this centres in the space
   between them. A 100vh min-height here stacked a viewport onto a page that
   already had a header and a footer. */
.auth-shell {
  display: flex; align-items: center; justify-content: center;
  padding: 72px 24px 96px;
}
.auth-card {
  position: relative; width: 100%; max-width: 440px; padding: 36px 34px;
  background: var(--paper-2); border: 1px solid var(--line);
}
.auth-card::before, .auth-card::after {
  content: ""; position: absolute; width: 14px; height: 14px;
  border-color: var(--accent); opacity: 0.6;
}
.auth-card::before { top: -1px; left: -1px; border-top: 1px solid; border-left: 1px solid; }
.auth-card::after { bottom: -1px; right: -1px; border-bottom: 1px solid; border-right: 1px solid; }
.auth-title {
  font-family: var(--display); font-size: 28px; font-weight: 800;
  letter-spacing: 0.01em; text-transform: uppercase; color: var(--ink); margin-bottom: 22px;
}
.auth-subtitle { font-size: 14px; line-height: 1.6; color: var(--ink-2); margin-bottom: 24px; }
.auth-form { display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px; }
.auth-form + .auth-form { padding-top: 20px; border-top: 1px solid var(--line); }
.auth-label {
  font-family: var(--mono); font-size: var(--label); letter-spacing: 2px; text-transform: uppercase;
  color: var(--muted);
}
.auth-input {
  padding: 12px 14px; background: var(--sink); color: var(--ink);
  border: 1px solid var(--line-2); font-size: 15px;
}
.auth-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--glow); }
.auth-submit {
  margin-top: 10px; justify-content: center; background: var(--accent); color: var(--accent-ink);
  border: 1px solid var(--accent); font-weight: 600; padding: 13px 22px; cursor: pointer;
}
.auth-submit:hover { background: var(--accent-2); border-color: var(--accent-2); color: var(--accent-ink); }
.auth-hint { font-size: 13px; line-height: 1.6; color: var(--muted); }
.auth-flash {
  padding: 11px 14px; margin-bottom: 18px; font-size: 13px;
  border-left: 3px solid var(--accent); background: var(--sink); color: var(--ink-2);
}
.auth-flash-error { border-left-color: var(--danger); color: var(--danger); }
.auth-flash-success { border-left-color: var(--live); color: var(--live); }

.dash-shell { max-width: var(--maxw); margin: 0 auto; padding: 36px 28px 72px; }
.dash-topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding-bottom: 16px; margin-bottom: 30px; border-bottom: 1px solid var(--line);
}
.dash-page-title {
  font-family: var(--display); font-size: clamp(26px, 3.4vw, 36px); font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.01em; color: var(--ink);
}
.dash-section { margin-bottom: 42px; }
.dash-section-title {
  font-family: var(--mono); font-size: 11px; letter-spacing: 2.4px; text-transform: uppercase;
  color: var(--accent); margin-bottom: 14px;
}
.dash-muted { color: var(--muted); font-size: 13px; }
.dash-warning {
  padding: 12px 15px; margin-bottom: 20px; font-size: 13px; color: var(--amber);
  border-left: 3px solid var(--amber); background: var(--sink);
}
.dash-list { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.dash-list > * { background: var(--paper-2); padding: 14px 16px; }
.dash-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.dash-table th {
  text-align: left; font-family: var(--mono); font-size: var(--label); letter-spacing: 1.6px;
  text-transform: uppercase; color: var(--muted); padding: 10px 12px;
  border-bottom: 1px solid var(--line-2);
}
.dash-table td { padding: 12px; border-bottom: 1px solid var(--line); color: var(--ink-2); }
.dash-table tr:last-child td { border-bottom: none; }

.project-list { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.project-item {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  background: var(--paper-2); padding: 16px 18px;
}
.project-item:hover { background: var(--accent-wash); }
.project-name { font-weight: 600; color: var(--ink); }
.empty-state, .scan-empty {
  padding: 28px; text-align: center; color: var(--muted); font-size: 14px;
  border: 1px dashed var(--line-2);
}
.scan-meta { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); margin-bottom: 24px; }
.scan-meta-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  background: var(--paper-2); padding: 11px 16px; font-size: 13px; color: var(--ink-2);
}
.scan-meta-row > :first-child {
  font-family: var(--mono); font-size: var(--label); letter-spacing: 1.8px;
  text-transform: uppercase; color: var(--muted);
}

/* ======================================================================
   The firmware surface board, folded in from board.css 2026-10-18. It was a
   separate file only to override the house hero cap for a panel that no
   longer exists; the diagram is now a band like every other page graphic.
   Every token below is defined above.
   ====================================================================== */

/* The hardware surface: the figure, the state key, and the register under it. The figure
   takes its colours from the page's own tokens through its scoped <style>, so nothing
   here styles its interior. */

/* The key. Every state carries a shape as well as a colour, because the map
   has to survive a monochrome print and a reader who cannot separate the two. */
.board-key { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin: 0 0 20px; }
.board-key-item { border-top: 1px solid var(--border); padding-top: 10px; }
.board-key-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.board-key-name { font-family: var(--mono); font-size: var(--label); letter-spacing: 1.5px; text-transform: uppercase; color: var(--heading); }
.board-key-count { font-family: var(--mono); font-size: var(--label); color: var(--muted); }
.board-key-note { font-size: 12px; line-height: 1.55; color: var(--text); margin: 0; }

.board-swatch { width: 16px; height: 12px; flex: none; border: 1px solid var(--muted); }
.board-swatch.st-analyzed  { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent); }
.board-swatch.st-nocode    { border-color: var(--muted); background: transparent; }
.board-swatch.st-encrypted { border-color: var(--amber); background: repeating-linear-gradient(45deg, var(--amber) 0 2px, transparent 2px 5px); }
.board-swatch.st-located   { border-style: dashed; border-color: var(--accent-2); background: transparent; }

/* The authoritative list. The map is the picture of it; this is the text a
   screen reader and a crawler read, and it carries the same 23 rows. */
.board-rows { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 28px; margin: 0 0 14px; }
.board-row { display: flex; align-items: baseline; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 13px; color: var(--text); }
.board-row-name { flex: 1; color: var(--heading); }

/* The register is grouped by state, so each group is headed in the key's own type and the
   state is named once per group rather than once per row. */
.board-group { margin: 0 0 22px; }
.board-group:last-child { margin: 0; }
.board-key-name.st-analyzed { color: var(--accent); }

/* The board is the thesis, so it sits above the prose rather than under a screen
   of it: headline, one line, the object, then the proof and the ask. */

/* These two selectors are declared unconditionally above, and board.css loads
   after proof2.css, so their responsive overrides have to live here or a later
   equal-specificity rule silently wins at every viewport. The 23 text rows are
   the SVG's accessible equivalent, so this is the one grid that must reflow. */
@media (max-width: 900px) { .board-key { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 768px) {
  .board-key { grid-template-columns: 1fr; }
  .board-rows { grid-template-columns: 1fr; }
}
