/* ============================================================
   Guard4AI — shared stylesheet
   The design system every page loads: tokens, type, buttons, nav
   and footer, followed by the components the account pages need.
   Page-specific rules stay inline in the page that needs them.
   ============================================================ */


/* Ink is a green-black, never pure black. Canvas is never pure white.
   Brand green is rationed: marks, labels and highlights only, never a
   filled button or a section background. */

:root {
  /* Ink: green-black, carries the brand hue into the neutrals */
  --ink:        #0a1f18;
  --ink-80:     #2c443b;
  --ink-60:     #55685f;
  --ink-40:     #7d8d86;

  /* Surfaces: canvas steps up to paper, never the reverse */
  --canvas:     #f4f7f3;
  --canvas-2:   #eaefe8;
  --paper:      #ffffff;

  /* Hairlines do the structural work that shadows would */
  --line:       #dfe6de;
  --line-soft:  #ebf0ea;
  --line-ink:   rgba(10,31,24,.12);

  /* Brand green, rationed */
  --green:      #22c55e;
  --green-deep: #0f7a3f;
  /* The Talk to us button, and only that. Set apart from --green-deep on
     purpose: it is the one filled green surface on the site, so it is allowed
     its own value rather than dragging every tick, badge and wordmark with
     it. Change this to restyle that button alone. */
  --green-cta:  #0d7a3e;
  --green-cta-h: #0b6835;
  --green-wash: #e8f8ee;
  --green-line: #bfe8cd;

  /* Type */
  --sans: 'Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Shape */
  --r-xs:   4px;
  --r-sm:   8px;
  --r:     12px;
  --r-lg:  20px;
  --r-pill: 999px;

  /* Elevation, used sparingly */
  --lift: 0 1px 2px rgba(10,31,24,.04);
  --float: 0 32px 64px -28px rgba(10,31,24,.22), 0 10px 24px -12px rgba(10,31,24,.08);

  --maxw: 1180px;
  --gutter: 28px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--sans);
  background: var(--canvas);
  color: var(--ink-80);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "kern" 1;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
::selection { background: var(--green-wash); color: var(--ink); }

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }

/* Anchor jumps land under the sticky nav without this: the nav is 68px tall,
   so #how and #faq arrived with their heading sliced off. */
[id] { scroll-margin-top: 88px; }
/* #how is on the demonstration frame, not on the section that contains it.
   Anchored to the section, the heading landed at 88px and the frame started
   393px below that, so on an 820px viewport the frame ran to 939px and the
   scrub bar and caption were off screen entirely. Clicking "How it works"
   showed a heading and the top edge of a dark box.

   Measured: frame top to caption bottom is 592px. Anchoring the frame itself
   is what makes this correct at every width, because the offset is taken from
   the thing that has to be visible rather than from a heading whose height
   changes as it wraps. 16vh gives a tall screen some of the heading above the
   frame and still fits the whole demonstration on a short one. */
#how { scroll-margin-top: clamp(92px, 15vh, 200px); }
.section { padding: 112px 0; }

/* ---------- Type ---------- */
h1, h2, h3, h4 { color: var(--ink); font-weight: 700; }

.display {
  font-size: clamp(42px, 6.1vw, 74px);
  line-height: .99;
  letter-spacing: -.036em;
}
.h2 {
  font-size: clamp(30px, 3.9vw, 47px);
  line-height: 1.04;
  letter-spacing: -.032em;
}
.h3 { font-size: 20px; line-height: 1.25; letter-spacing: -.018em; font-weight: 600; }

/* Wide-tracked mono micro-label, the counterweight to tight display type */
.label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--green-deep);
  display: inline-block;
}
.label--muted { color: var(--ink-40); }

.lede { font-size: 19px; line-height: 1.55; color: var(--ink-60); }
.small { font-size: 15px; line-height: 1.6; color: var(--ink-60); }

/* The single keyword highlight. Green earns its place in the headline
   by carrying the meaning, not by decorating around it. */
.mark { color: var(--green-deep); }

/* The rotating word in the hero. inline-block so it can be transformed, and
   so the whole word-plus-stop moves as one atom rather than the stop sliding
   on its own while the word behind it changes width. */
.rot {
  display: inline-block;
  transition: opacity .2s ease, transform .2s cubic-bezier(.16, 1, .3, 1);
}
.rot.is-out { opacity: 0; transform: translateY(-.1em); }
/* Rotating text is motion. Honouring the preference means stopping it, not
   just removing the fade, so the script never starts and this is belt only. */
@media (prefers-reduced-motion: reduce) {
  .rot { transition: none; }
  .rot.is-out { opacity: 1; transform: none; }
}

/* ---------- Buttons: primary is ink, never green ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
  padding: 13px 22px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, color .18s ease, transform .18s ease;
  white-space: nowrap;
}
.btn-primary { background: var(--ink); color: #fff; }
.btn-primary:hover { background: #05130e; transform: translateY(-1px); }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { border-color: var(--ink); background: var(--paper); }
/* Third-rank action: reads as a link, keeps the button's height so it sits on
   the same baseline as the two beside it. */
.btn-plain { background: transparent; color: var(--ink-60); border-color: transparent; padding-left: 4px; padding-right: 4px; }
.btn-plain:hover { color: var(--ink); background: transparent; border-color: transparent; }
/* .btn-lg's padding shorthand is declared after .btn-plain, so the flush left
   edge has to be reasserted at higher specificity or the link sits inset. */
.btn-plain.btn-lg { padding-left: 0; padding-right: 0; }
.btn-sm { padding: 9px 16px; font-size: 14px; }
.btn-lg { padding: 16px 30px; font-size: 16px; }
.btn svg { width: 16px; height: 16px; }

/* ---------- Nav ---------- */
.nav {
  position: sticky; top: 0; z-index: 60;
  background: rgba(244,247,243,.82);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.nav__in { display: flex; align-items: center; gap: 32px; height: 68px; }
.brand { display: flex; align-items: center; gap: 9px; }
.brand img { height: 28px; width: auto; }
.brand span {
  font-size: 18px; font-weight: 700; color: var(--ink); letter-spacing: -.03em;
}
.brand b { color: var(--green-deep); font-weight: 700; }
.nav__links { display: flex; gap: 26px; margin-left: 8px; }
.nav__links a {
  font-size: 14px; font-weight: 500; color: var(--ink-60); letter-spacing: -.005em;
  transition: color .15s ease;
  /* A nav label broken over two lines reads as two labels. It never wraps;
     when the row runs out of room the burger takes over instead. */
  white-space: nowrap;
}
.nav__links a:hover { color: var(--ink); }
.nav__right { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.nav__note { font-family: var(--mono); font-size: 11.5px; color: var(--ink-40); letter-spacing: .04em; }

/* ---------- Section heads ---------- */
.head { max-width: 640px; margin-bottom: 64px; }
.head .label { margin-bottom: 18px; }
.head .lede { margin-top: 18px; }
.head--center { margin-left: auto; margin-right: auto; text-align: center; }

/* ---------- Footer ---------- */
.foot { border-top: 1px solid var(--line); padding: 56px 0 44px; }
.foot__top { display: flex; align-items: center; justify-content: space-between; gap: 26px; flex-wrap: wrap; }
.foot__links { display: flex; gap: 30px; flex-wrap: wrap; }
.foot__links a { font-size: 15px; color: var(--ink-60); transition: color .15s ease; }
.foot__links a:hover { color: var(--ink); }
.foot__bot {
  margin-top: 40px; padding-top: 26px; border-top: 1px solid var(--line-soft);
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  font-family: var(--mono); font-size: 12px; letter-spacing: .04em; color: var(--ink-40);
}


/* ---------- Nav: account actions ---------- */
/* Sign in stays a quiet text link so the two green-free buttons in the corner
   do not compete. Sign up borrows the same ink fill as Add to Chrome, one step
   smaller, because it is the same kind of commitment. */
.nav__signin {
  font-size: 14px; font-weight: 500; color: var(--ink-60);
  letter-spacing: -.005em; transition: color .15s ease; white-space: nowrap;
}
.nav__signin:hover { color: var(--ink); }
.nav__sep { width: 1px; height: 20px; background: var(--line); }

/* ---------- Page header, for pages that are not the landing page ---------- */
.phead { padding: 92px 0 0; }
.phead .label { margin-bottom: 18px; }
.phead .lede { margin-top: 20px; max-width: 560px; }
.phead--center { text-align: center; }
.phead--center .lede { margin-left: auto; margin-right: auto; }

/* ---------- Pricing ---------- */
/* Same hairline-gap construction as the stats row on the landing page: cells
   sit on a 1px line background rather than floating as separate cards.

   Five elements per card, deliberately: name, price, seat band, list, button.
   The old card carried nine registers, including a savings badge and a
   struck-through per-seat rate, and the sum read as a supermarket shelf.
   Discounts are stated once each, as a plain per-seat figure beside the seat
   band; a buyer who does the arithmetic finds the 40% themselves, which lands
   harder than a banner saying so. */
/* ============================================================
   Pricing page
   ------------------------------------------------------------
   Two plans for a buyer who is deciding whether to trust us with
   what their team types. It reads as one calm block: the same
   hairlines and green-black ink as everywhere else, with depth
   added only where it helps the eye rank things.

   Two deliberate departures from the rules at the top of this
   file, both asked for: soft shadows appear here alongside the
   hairlines, and the recommended plan takes a FILLED green
   button. Green is rationed everywhere else on the site; it is
   spent here, once, on the action this page exists to get.

   No monospace on this page. The micro-labels elsewhere use it;
   here the whole block is set in the text face so it reads as a
   document rather than an interface.
   ============================================================ */

/* The page is a decision, and the decision has to be on the first screen.
   Everything below is budgeted against 1440x900: 69px of nav, then the hero,
   then two cards whose buttons must land above 900. That is why the hero is
   short and centred rather than a full section header. */
.pr.phead { padding: 34px 0 0; }
.pr__head { max-width: 900px; margin: 0 auto; text-align: center; }
/* Sized to hold the headline on one line at 1440 and to wrap gracefully
   below that, rather than to be as large as the space allows. */
.pr__h1 {
  font-size: clamp(30px, 3.1vw, 43px); line-height: 1.1;
  letter-spacing: -.03em; margin: 0;
}
.pr__lede {
  font-size: 17px; line-height: 1.55; color: var(--ink-60);
  margin: 12px auto 0; max-width: 60ch;
}

/* Signed-in state as a status chip: it is a fact about the session, not a
   sentence in the argument, so it should not sit in the hero as loose text. */
/* inline-block, NOT inline-flex. The script writes a sentence into this
   element — "Signed in as <b>you@example.com</b>. Start your…" — and a flex
   container turns every text node into a flex item, so `gap` opens a hole
   before the full stop. The dot is an inline marker with a margin instead. */
.pr__status {
  display: inline-block;
  margin: 14px 0 0; padding: 7px 14px 7px 12px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13px; line-height: 1.4; color: var(--ink-60);
}
.pr__status[hidden] { display: none; }
.pr__status::before {
  content: ""; display: inline-block; vertical-align: 1px;
  width: 7px; height: 7px; border-radius: 50%; margin-right: 9px;
  background: var(--green-deep);
}
.pr__status b { color: var(--ink); font-weight: 600; }
.pr__status a { color: var(--ink); font-weight: 500; border-bottom: 1px solid var(--line); }
.pr__status a:hover { border-bottom-color: var(--ink); }

/* ---------- The two plans ---------- */
/* Equal height and stretched, so the two CTAs land on one line and the eye
   can compare across rather than down. */
.plans {
  display: grid; grid-template-columns: repeat(2, 1fr);
  align-items: stretch; gap: 22px;
  max-width: 1060px; margin: 26px auto 0;
}
.plan {
  display: flex; flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 26px 30px 24px;
  box-shadow: 0 1px 2px rgba(10, 31, 24, .04), 0 10px 28px rgba(10, 31, 24, .045);
}
/* The recommended one. Pale green at the head of the card and a slightly
   firmer edge — enough to rank it, not enough to make the other look like a
   consolation. */
.plan--rec {
  border-color: var(--green-line);
  background:
    linear-gradient(180deg, var(--green-wash) 0, rgba(232, 248, 238, 0) 190px),
    var(--paper);
  box-shadow: 0 1px 2px rgba(10, 31, 24, .05), 0 14px 34px rgba(15, 122, 63, .09);
}

/* 28px clears the badge's own height. At 26 the badge made this row one pixel
   taller than the plain name beside it, and that one pixel walked all the way
   down the card: price, description, rule and features all sat a pixel low. */
.plan__top { display: flex; align-items: center; gap: 10px; min-height: 28px; }
.plan__name {
  font-size: 15px; font-weight: 600; color: var(--ink); letter-spacing: -.01em;
}
.plan__badge {
  font-size: 12px; font-weight: 600; letter-spacing: .01em;
  color: var(--green-deep); background: var(--green-wash);
  border: 1px solid var(--green-line); border-radius: 999px;
  padding: 3px 10px;
}

/* One baseline for both, so $14 and Custom sit on the same line. */
.plan__price {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  margin-top: 14px; min-height: 44px;
}
.plan__amt {
  font-size: 40px; font-weight: 700; color: var(--ink);
  letter-spacing: -.038em; line-height: 1;
}
/* Same size as the real price, deliberately. A smaller word would sit on a
   different baseline to $14 in the card beside it, and the two price lines
   are the first thing the eye compares across. */
.plan__amt--word { letter-spacing: -.03em; }
.plan__cycle { font-size: 14.5px; color: var(--ink-40); }

/* Fixed at two lines so the rule under it lands at the same height in both
   cards, whichever description is longer. */
.plan__for {
  margin: 12px 0 0; font-size: 15px; line-height: 1.5; color: var(--ink-60);
  min-height: 45px;
}

.plan__seats {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line-soft);
  font-size: 14px; font-weight: 600; color: var(--ink);
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
}
/* The seat rule, demoted to a footnote with the full explanation on hover
   rather than taking the headline it used to have. */
.plan__hint {
  font-size: 12.5px; font-weight: 400; color: var(--ink-40);
  border-bottom: 1px dotted var(--line); cursor: help;
}

.plan__feats { list-style: none; margin: 18px 0 22px; display: grid; gap: 11px; }
.plan__feats li {
  display: grid; grid-template-columns: 18px 1fr; gap: 11px;
  align-items: start;
  font-size: 15px; line-height: 1.45; color: var(--ink-80);
}
.feat__i { width: 14px; height: 14px; color: var(--green-deep); margin-top: 4px; }

/* Pushed to the foot so both land on one line; taller than the site default
   because this is the one thing on the page worth making easy to hit. */
.plan__cta {
  margin-top: auto; width: 100%;
  padding: 15px 24px; font-size: 15.5px; border-radius: var(--r);
}
.plan__cta--ink { background: var(--ink); color: #fff; border-color: var(--ink); }
.plan__cta--ink:hover { background: #05130e; border-color: #05130e; transform: none; }
.plan__cta--green { background: var(--green-cta); color: #fff; border-color: var(--green-cta); }
.plan__cta--green:hover { background: var(--green-cta-h); border-color: var(--green-cta-h); transform: none; }
.plan__cta:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.plan__note {
  margin: 10px 0 0; font-size: 12.5px; line-height: 1.5;
  color: var(--ink-40); text-align: center;
}

/* ---------- The full list ---------- */
/* Everything both plans include, below the decision area. The cards show the
   four lines that decide it; this is where the rest went, unchanged. */
.compare {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px;
  max-width: 1060px; margin: 56px auto 0;
}
.compare__col {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); padding: 24px 26px;
}
.compare__h {
  display: block; font-size: 14px; font-weight: 600; color: var(--ink);
  margin-bottom: 14px;
}
.compare__list { list-style: none; display: grid; gap: 10px; }
.compare__list li {
  font-size: 14.5px; line-height: 1.45; color: var(--ink-60);
  padding-left: 16px; position: relative;
}
.compare__list li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--green-line);
}

/* ---------- Trust row ---------- */
/* Three facts the product can stand behind, set as one quiet line. */
.trust {
  list-style: none; display: flex; flex-wrap: wrap; gap: 10px 26px;
  align-items: center; justify-content: center;
  max-width: 1060px; margin: 22px auto 0;
  font-size: 13.5px; color: var(--ink-60);
}
.trust li { display: flex; align-items: center; gap: 10px; }
.trust li + li::before {
  content: ""; width: 3px; height: 3px; border-radius: 50%;
  background: var(--ink-40); margin-right: 16px;
}

.pr__more {
  max-width: 1060px; margin: 26px auto 0; text-align: center;
  font-size: 13.5px; line-height: 1.6; color: var(--ink-40);
}
.pr__more a { color: var(--ink); border-bottom: 1px solid var(--line); }
.pr__more a:hover { border-bottom-color: var(--ink); }

@media (max-width: 760px) {
  .plans, .compare { grid-template-columns: 1fr; gap: 18px; }
  .plan__for { min-height: 0; }
  .trust { gap: 8px; flex-direction: column; align-items: flex-start; }
  .trust li + li::before { display: none; }
}

/* ---------- The fine print, plainly ---------- */
/* Three questions in quiet type, replacing the pill, the bordered box and the
   fine-print paragraph that used to stack around the grid. Reassurance reads
   as confidence only after the price, and only said once. */
/* Four now that coverage is stated here: this strip is what a buyer should
   know before paying, and where the product stops belongs in it. */
/* Five items now, not four. Three columns puts them 3 + 2 instead of leaving
   one stranded alone on a second row. */
.fine {
  margin: 56px 0 104px; display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 34px 40px; max-width: 880px;
}
.fine__item a { color: var(--ink); border-bottom: 1px solid var(--line); }
.fine__item a:hover { border-bottom-color: var(--ink); }
.fine__item strong { display: block; font-size: 14.5px; color: var(--ink); margin-bottom: 8px; }
.fine__item p { font-size: 14px; line-height: 1.6; color: var(--ink-60); }

.signedin { margin-top: 14px; font-size: 14.5px; color: var(--ink-60); }
.signedin b { color: var(--ink); font-weight: 600; }
/* The global `a { color: inherit; text-decoration: none }` means a link dropped
   into this note is invisible: same colour, no underline, no weight change.
   These messages are mostly links now (open the dashboard, email us), so they
   take the same treatment as inline links in the fine print below. */
.signedin a { color: var(--ink); font-weight: 500; border-bottom: 1px solid var(--line); }
.signedin a:hover { border-bottom-color: var(--ink); }

/* Shown for as long as the trial runs, above everything else on the dashboard.
   Quiet by default; the last three days turn it amber so the deadline is not a
   surprise, and an expired trial drops to a plain grey bar. */
.trialbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-bottom: 30px; padding: 11px 16px;
  background: var(--green-wash); border: 1px solid var(--green-line);
  border-radius: var(--r); font-size: 14.5px; color: var(--ink-80);
}
/* Same trap as .ok__steps below: the author `display: flex` above outranks the
   browser's [hidden] { display: none }, so a company with no trial was getting
   an empty bar. renderTrial() returns early for those and never unhides it. */
.trialbar[hidden] { display: none; }
.trialbar__k {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--green-deep);
}
.trialbar b { font-weight: 600; color: var(--ink); }
.trialbar__dot { color: var(--ink-40); }
.trialbar__act {
  margin-left: auto; font-size: 13.5px; color: var(--ink-60);
  border-bottom: 1px solid var(--line);
}
.trialbar__act:hover { color: var(--ink); }
.trialbar--soon { background: #fdf4e3; border-color: #efd9a8; }
.trialbar--soon .trialbar__k { color: #8a5a12; }
.trialbar--ended { background: var(--canvas-2); border-color: var(--line); }
.trialbar--ended .trialbar__k { color: var(--ink-60); }

/* ---------- Auth pages ---------- */
.auth { min-height: calc(100vh - 68px); display: flex; align-items: center; justify-content: center; padding: 56px 0 80px; }
.auth__box { width: 100%; max-width: 428px; }
.auth__box .label { display: block; margin-bottom: 16px; }
.auth__box h1 { font-size: 34px; letter-spacing: -.03em; line-height: 1.1; }
.auth__box > p { margin-top: 14px; font-size: 16px; color: var(--ink-60); }
.form { margin-top: 34px; display: grid; gap: 18px; }
/* display:grid on the line above BEATS the hidden attribute, so form.hidden
   = true was setting a property that changed nothing: the form stayed on
   screen with its button frozen on "Sending...". Any author display wins over
   the UA's [hidden] rule, so it has to be said again here. */
.form[hidden] { display: none; }
.field { display: grid; gap: 8px; }
.field label {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-40);
}
.field input {
  font-family: var(--sans); font-size: 15.5px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 13px 14px; width: 100%;
  transition: border-color .15s ease;
}
.field input:focus { outline: none; border-color: var(--ink); }
.field input::placeholder { color: var(--ink-40); }

/* The contact form adds a select and a textarea to the same component. They
   inherit the input's box so the column reads as one stack rather than three
   different form libraries. */
.field select, .field textarea {
  font-family: var(--sans); font-size: 15px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 11px 14px; width: 100%;
}
.field select:focus, .field textarea:focus { outline: none; border-color: var(--ink); }
.field textarea { resize: vertical; min-height: 96px; line-height: 1.55; }
/* The native arrow differs per platform and none of them match this page, so
   it is drawn here and the platform one is turned off. */
.field select {
  appearance: none; -webkit-appearance: none;
  padding-right: 38px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'><path d='m6 9 6 6 6-6' stroke='%237d8d86' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 16px;
}
/* The label is mono and uppercased, and "OPTIONAL" shouted in it reads as
   part of the field name. Set back to sentence case so it reads as the aside
   it is. */
.field__opt {
  font-family: var(--sans); font-size: 12px; letter-spacing: 0;
  text-transform: none; color: var(--ink-40);
}
/* The free-mail nudge. Quiet, and it never blocks the send. */
.field__note { margin-top: 2px; font-size: 13px; line-height: 1.5; color: var(--ink-60); }
.field__note[hidden] { display: none; }

/* The honeypot. Out of sight and out of the tab order, but NOT display:none
   and NOT hidden: a bot that skips hidden inputs would skip this too, and the
   whole point of it is to be filled in. */
.hp {
  position: absolute; left: -9999px; top: auto;
  width: 1px; height: 1px; overflow: hidden;
}
.form .btn { width: 100%; margin-top: 4px; }
/* What replaces the form once it has been sent. Not a message tucked under a
   button: the form is gone and this is the whole of what is left, because the
   only thing left to say is that it arrived. */
.sent { margin-top: 34px; }
.sent[hidden] { display: none; }
/* ---------- The contact form, once it has been sent ----------
   One card, centred in what is left of the viewport, and the only thing on
   the page. The pitch above it is hidden rather than left in place: a
   confirmation with the sales copy still over it is asking for something it
   has already been given. */
/* .auth pads 56 top and 80 bottom, which is right for a form that ends in a
   button and wrong for a card that is supposed to sit in the middle of the
   screen: it pushed this one 24px high. Evened out only while the card is
   showing, so the form state keeps the spacing it was designed with. */
.auth.is-sent { padding: 56px 0; }
.sentwrap { display: flex; justify-content: center; }
.sentwrap[hidden] { display: none; }
.sentcard {
  width: 100%; max-width: 620px;
  background: var(--paper);
  border: 1px solid var(--green-line);
  border-radius: var(--r-lg);
  padding: 54px 56px 46px;
  text-align: center;
  /* Restrained on purpose: enough to lift the card off the canvas, not
     enough to announce itself. */
  box-shadow: 0 1px 2px rgba(10, 31, 24, .04), 0 14px 40px rgba(15, 122, 63, .07);
}

/* A letterhead. It says who received this, which is the one thing a
   confirmation from a security company should not leave the reader guessing
   about. */
.sentcard__brand {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: 16px; font-weight: 700; color: var(--ink);
  letter-spacing: -.02em; margin-bottom: 34px;
}
.sentcard__brand img { width: 22px; height: 22px; }
.sentcard__brand b { color: var(--green-deep); font-weight: 700; }

.sentcard__tick {
  display: flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; margin: 0 auto 22px;
  border-radius: 50%;
  background: var(--green-wash); border: 1px solid var(--green-line);
  color: var(--green-deep);
}
.sentcard__tick svg { width: 26px; height: 26px; }

/* The strongest thing in the card, and the brand green rather than the one
   the buttons wear: a confirmation is not an action. */
.sentcard__h {
  font-size: clamp(34px, 4.6vw, 46px); line-height: 1.05;
  letter-spacing: -.032em; color: var(--green-deep); margin: 0;
}
.sentcard__h:focus { outline: none; }

.sentcard__p {
  margin: 16px auto 0; max-width: 42ch;
  font-size: 16.5px; line-height: 1.62; color: var(--ink-60);
}
.sentcard__p a { color: var(--ink); font-weight: 600; border-bottom: 1px solid var(--line); }
.sentcard__p a:hover { border-bottom-color: var(--ink); }

.sentcard__cta {
  margin-top: 32px; width: 100%;
  padding: 15px 24px; font-size: 15.5px;
  background: var(--green-cta); color: #fff; border-color: var(--green-cta);
}
.sentcard__cta:hover { background: var(--green-cta-h); border-color: var(--green-cta-h); transform: none; }
.sentcard__cta:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.sentcard__back {
  display: inline-block; margin-top: 18px;
  font-size: 14.5px; color: var(--ink-60);
  border-bottom: 1px solid var(--line);
}
.sentcard__back:hover { color: var(--ink); border-bottom-color: var(--ink-40); }

@media (max-width: 560px) {
  .sentcard { padding: 38px 24px 32px; border-radius: var(--r); }
  .sentcard__brand { margin-bottom: 26px; }
  .sentcard__p { font-size: 16px; }
}

.form__alt { margin-top: 22px; font-size: 14.5px; color: var(--ink-60); text-align: center; }
.form__alt a { color: var(--ink); font-weight: 600; border-bottom: 1px solid var(--line); }
.form__alt a:hover { border-bottom-color: var(--ink); }

/* One message slot, three tones, no icon set and no colour wash.
   Named under .form because .msg already belongs to the hero mockup. */
.form__msg {
  font-size: 14.5px; line-height: 1.5; padding: 12px 14px;
  border-radius: var(--r-sm); border: 1px solid var(--line);
  background: var(--paper); color: var(--ink-80); display: none;
}
.form__msg.is-on { display: block; }
.form__msg--bad  { border-color: #f0c4bb; color: #8c3d2e; }
.form__msg--good { border-color: var(--green-line); color: var(--green-deep); }

/* ---------- Mobile nav ----------
   Below 940px the inline links used to vanish with no replacement, which left
   phones unable to reach Pricing at all, and the three right-side controls
   overflowed a 375px viewport by 25px. Now: burger + Sign up in the bar, and
   everything else in a panel under it. The burger's onclick lives in the
   markup so no page needs a script file for its own navigation. */
.nav__burger {
  display: none; width: 42px; height: 42px; flex: none;
  align-items: center; justify-content: center;
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-sm); cursor: pointer;
}
.nav__burger svg { width: 19px; height: 19px; }
.nav__burger .x { display: none; }
.nav.is-open .nav__burger .x { display: block; }
.nav.is-open .nav__burger .lines { display: none; }
.nav__panel { display: none; }

/* ---------- Responsive ---------- */
@media (max-width: 940px) {
  .section { padding: 78px 0; }
  .nav__links { display: none; }
  .nav__note { display: none; }
  .nav__signin, .nav__sep, .nav__right .btn-ghost { display: none; }
  .nav__burger { display: inline-flex; }
  .nav.is-open .nav__panel {
    display: flex; flex-direction: column;
    position: absolute; top: 100%; left: 0; right: 0;
    background: var(--paper); border-bottom: 1px solid var(--line);
    box-shadow: var(--float); padding: 8px 0 14px;
  }
  .nav__panel a {
    padding: 13px var(--gutter); font-size: 16px; font-weight: 500;
    color: var(--ink-80); border-top: 1px solid var(--line-soft);
  }
  .nav__panel a:first-child { border-top: 0; }
  .nav__panel a:active { background: var(--canvas); }
}
@media (max-width: 560px) {
  .nav__in { gap: 14px; }
}
@media (max-width: 1080px) {
  .fine { grid-template-columns: 1fr 1fr; gap: 30px; }
  .plan { padding: 28px 26px 24px; }
}
@media (max-width: 620px) {
  .fine { grid-template-columns: 1fr; gap: 26px; }
  /* One per row: nothing left to align against, so drop the reserved space. */
  .plan__price { min-height: 0; }
}
@media (max-width: 560px) {
  :root { --gutter: 20px; }
  .nav__sep { display: none; }
  .foot__top { flex-direction: column; align-items: flex-start; }
  .phead { padding: 52px 0 0; }
  .valueline { font-size: 16px; }
  .trialline { display: flex; border-radius: var(--r); }
}

/* ---------- Footer: columns ---------- */
/* Wide first column for the mark and the one-liner, then three narrow link
   columns. Same hairline rules and mono headings as everything else. */
.foot__grid {
  display: grid;
  /* Three columns since the Company column's links did not exist yet. */
  grid-template-columns: 1.8fr 1fr 1fr;
  gap: 48px;
  padding-bottom: 44px;
}
.foot__about { max-width: 300px; }
.foot__about .brand { margin-bottom: 16px; }
.foot__about p { font-size: 14.5px; line-height: 1.6; color: var(--ink-60); }
.foot__col { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.foot__h {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-40); margin-bottom: 3px;
}
.foot__col a { font-size: 14.5px; color: var(--ink-60); transition: color .15s ease; }
.foot__col a:hover { color: var(--ink); }
/* Sits with the description rather than in a column of its own: it is the one
   place to find us, not a fourth category of link. Mark inherits currentColor
   so it reads as quietly as the text around it and darkens with it on hover. */
.foot__social {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 18px;
  font-size: 14.5px; color: var(--ink-60); transition: color .15s ease;
}
.foot__social svg { width: 16px; height: 16px; flex: none; }
.foot__social:hover { color: var(--ink); }

@media (max-width: 940px) {
  .foot__grid { grid-template-columns: 1fr 1fr; gap: 40px 32px; }
  .foot__about { grid-column: 1 / -1; max-width: none; }
}
@media (max-width: 560px) {
  .foot__grid { grid-template-columns: 1fr; gap: 32px; }
}

/* ---------- Dashboard ---------- */
/* Dense and quiet. The same hairline-gap cells and mono micro-labels as the
   marketing pages, so this reads as the same product rather than an admin
   template bolted on the side. */
.dash { padding: 44px 0 96px; }
.dash__top {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 32px; flex-wrap: wrap; margin-bottom: 40px;
}
.dash__top .label { display: block; margin-bottom: 14px; }
.dash__top h1 { font-size: clamp(28px, 3.4vw, 40px); letter-spacing: -.032em; line-height: 1.05; }

/* The invite code is the one thing an admin comes here to copy. */
.invite { display: flex; align-items: center; gap: 10px; }
.invite__code {
  font-family: var(--mono); font-size: 15px; letter-spacing: .08em; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 11px 16px;
}
.invite__copy {
  font-family: var(--sans); font-size: 13.5px; font-weight: 600; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 11px 15px; cursor: pointer; transition: border-color .15s ease, color .15s ease;
}
.invite__copy:hover { border-color: var(--ink); }
.invite__copy.is-done { color: var(--green-deep); border-color: var(--green-line); }

/* ---------- Scanning policy (admin) ---------- */
/* Two options presented as what they do to the people using it, not as their
   names. Radios, not a switch: this is a choice between two states that both
   have consequences, and a switch would imply one of them is "off". */
.policy { margin: 0 0 30px; }
/* Same guard as .trialbar and .ok__steps above: written out rather than left
   to the browser, so adding a `display` here later cannot silently un-hide it. */
.policy[hidden] { display: none; }
.policy__h { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.policy__h h2 { font-size: 17px; letter-spacing: -.015em; }
.policy__since { font-family: var(--mono); font-size: 11.5px; color: var(--ink-40); }
.policy__opts {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--line); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden; margin-top: 12px;
}
.policy__opt {
  display: block; background: var(--paper); padding: 18px 20px; cursor: pointer;
  transition: background .15s ease;
}
.policy__opt:hover { background: var(--canvas); }
.policy__opt input { position: absolute; opacity: 0; pointer-events: none; }
.policy__opt.is-on { background: var(--green-wash); }
.policy__lab { display: flex; align-items: center; gap: 9px; font-weight: 600; font-size: 15px; }
.policy__dot {
  width: 15px; height: 15px; border-radius: 50%; flex: none;
  border: 1.5px solid var(--line); background: var(--paper);
}
.policy__opt.is-on .policy__dot { border-color: var(--green-deep); border-width: 4.5px; }
.policy__opt input:focus-visible ~ .policy__lab .policy__dot { outline: 2px solid var(--ink); outline-offset: 2px; }
.policy__d { font-size: 13.5px; line-height: 1.55; color: var(--ink-60); margin-top: 7px; }
.policy__note { font-size: 13px; color: var(--ink-60); margin-top: 12px; }
.policy__note.is-bad { color: #8c3d2e; }
.policy.is-busy { opacity: .55; pointer-events: none; }

/* The lock checklist. Only shown under Enforced, because under Flexible it
   would be a list of choices that have no effect — and a <details>, because 29
   rows open by default buries the rest of the dashboard. Native disclosure
   rather than a scripted one: it is keyboard-operable and findable in-page
   without a line of JS. */
.policy__locks {
  margin-top: 18px; background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--r);
}
.policy__locks[hidden] { display: none; }
.policy__lockhead {
  display: flex; align-items: center; gap: 11px;
  padding: 16px 20px; cursor: pointer; list-style: none;
  border-radius: var(--r);
}
.policy__lockhead::-webkit-details-marker { display: none; }
.policy__lockhead:hover { background: var(--canvas); }
.policy__locks[open] .policy__lockhead,
.seats[open] .policy__lockhead {
  border-bottom: 1px solid var(--line); border-radius: var(--r) var(--r) 0 0;
}
.policy__lockhead:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.policy__caret { display: flex; color: var(--ink-40); transition: transform .18s ease; }
.policy__caret svg { width: 15px; height: 15px; }
.policy__locks[open] .policy__caret,
.seats[open] .policy__caret { transform: rotate(90deg); }
.policy__lockh { font-size: 15px; font-weight: 600; color: var(--ink); letter-spacing: -.01em; }
/* The state, readable without opening the thing. */
.policy__count {
  margin-left: auto; font-family: var(--mono); font-size: 11.5px;
  letter-spacing: .04em; color: var(--ink-40);
}
.policy__lockbody { padding: 0 20px 20px; }

/* The action bar. Sticky under the site nav so Save is reachable from row 1
   and row 29 alike — the list is long enough that a footer button would mean
   scrolling back down to commit a tick made at the top. */
.policy__bar {
  position: sticky; top: 68px; z-index: 2;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 14px 0 12px; margin-bottom: 2px;
  background: var(--paper); border-bottom: 1px solid var(--line-soft);
}
.policy__bulk { display: flex; gap: 8px; }
.policy__dirty {
  margin-left: auto; font-family: var(--mono); font-size: 11.5px;
  letter-spacing: .04em; color: var(--green-deep);
}
/* A refused save, said next to the button that was pressed. */
.policy__dirty.is-bad { color: #8c3d2e; font-weight: 500; }
/* Two honest states, never a greyed-out "Save changes" that reads as a click
   that did not land. Dirty: an ink primary that invites the click. Clean: a
   quiet green confirmation that the current state IS saved. */
.policy__save { transition: background .18s ease, color .18s ease, border-color .18s ease; }
.policy__save:disabled { cursor: default; }
.policy__save.btn-primary:disabled { opacity: .45; }
.policy__save.btn-primary:disabled:hover { background: var(--ink); transform: none; }
.policy__save.is-saved {
  background: var(--green-wash); color: var(--green-deep);
  border-color: var(--green-line); opacity: 1;
  padding-left: 14px;
}
.policy__save.is-saved::before {
  content: ""; width: 14px; height: 14px; flex: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'><path d='m5 12.5 4.5 4.5L19 7.5' stroke='%230f7a3f' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-size: contain; background-repeat: no-repeat; background-position: center;
}
.policy__save.is-saved:hover { background: var(--green-wash); transform: none; }
/* One pulse when a save actually lands, so the click is acknowledged rather
   than only reflected a moment later. */
@keyframes policySaved {
  0%   { transform: scale(1); }
  38%  { transform: scale(1.045); }
  100% { transform: scale(1); }
}
.policy__save.just-saved { animation: policySaved .34s cubic-bezier(.16,1,.3,1); }
@media (prefers-reduced-motion: reduce) {
  .policy__save.just-saved { animation: none; }
}
@media (max-width: 560px) {
  .policy__bar { position: static; }
  .policy__dirty { margin-left: 0; width: 100%; }
}
.bulk-btn {
  font-family: var(--sans); font-size: 12.5px; font-weight: 600; color: var(--ink-60);
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 6px 11px; cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}
.bulk-btn:hover { border-color: var(--ink); color: var(--ink); }
.bulk-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* Sections inside the one dropdown, matching the extension's own headings. */
.policy__grp { margin-top: 22px; }
.policy__grp h4 {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-40); margin-bottom: 4px;
}
/* One column, deliberately. The panel is long, but the whole point of this
   list is that an admin can read it down beside the extension's own settings
   page and match the two line for line. Columns break that: the eye has to
   jump back up and across, and the order stops being obvious. */
.policy__list {
  display: flex; flex-direction: column;
  border-top: 1px solid var(--line-soft);
}
.policy__lock {
  display: flex; align-items: center; gap: 9px; padding: 9px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14px; line-height: 1.4; cursor: pointer;
}
.policy__lock:hover { color: var(--ink); }
/* Which extension screen this switch is on. Quiet, right-aligned, and the
   reason it earns its place: the list spans two screens the admin does not
   have open, so "Popup" or "Settings" is what makes a row findable. */
.policy__where {
  margin-left: auto; font-family: var(--mono); font-size: 10px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-40);
  flex: none;
}
.policy__lock input {
  appearance: none; -webkit-appearance: none;
  width: 16px; height: 16px; flex: none;
  border: 1.5px solid var(--line); border-radius: 4px; background: var(--paper);
  cursor: pointer; transition: background .12s ease, border-color .12s ease;
}
.policy__lock input:checked {
  background: var(--green-deep); border-color: var(--green-deep);
  /* The tick is drawn rather than a glyph, so it stays crisp at any zoom. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'><path d='m5 12.5 4.5 4.5L19 7.5' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-size: 12px 12px; background-position: center; background-repeat: no-repeat;
}
.policy__lock input:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.policy__lock span { color: var(--ink-80); }
@media (max-width: 620px) {
  .policy__opts { grid-template-columns: 1fr; }
  .policy__list { grid-template-columns: 1fr; }
}

/* ---------- The lead line ---------- */
/* Reads as a sentence, not a heading: it restates the three cells below it,
   so it must not compete with them for weight. */
.lead {
  font-size: clamp(16px, 1.7vw, 19px); line-height: 1.5;
  color: var(--ink-80); letter-spacing: -.012em;
  max-width: 62ch; margin: 0 0 22px;
}
.lead[hidden] { display: none; }

/* State, not a number, so it sits with the company name rather than in the
   metric strip. Same wash the policy control uses for a chosen option. */
.dash__badge {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 12px; padding: 5px 11px 5px 9px;
  background: var(--green-wash); border: 1px solid var(--green-line);
  border-radius: 999px; text-decoration: none;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--green-deep);
}
.dash__badge[hidden] { display: none; }
.dash__badge::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--green-deep);
}
.dash__badge:hover { background: #dff2e6; }

.metrics {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden;
}
.metric { background: var(--paper); padding: 26px 26px 24px; }
.metric__k {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-40); display: block;
}
.metric__n {
  font-size: 40px; font-weight: 700; color: var(--ink);
  letter-spacing: -.035em; line-height: 1; margin-top: 16px;
}
.metric__n small { font-size: 17px; font-weight: 500; color: var(--ink-40); letter-spacing: -.01em; }
.metric__sub { margin-top: 9px; font-size: 13.5px; color: var(--ink-60); }

.panels { display: grid; grid-template-columns: 1.35fr 1fr; gap: 20px; margin-top: 20px; }
.panel {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 26px 26px 22px;
}
.panel__h {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  margin-bottom: 26px;
}
.panel__h strong { font-size: 15px; font-weight: 600; color: var(--ink); letter-spacing: -.015em; }
.panel__h span {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-40);
}

/* Fourteen columns on a hairline baseline. No gradient, no glow, no grid. */
/* The chart grows to match whichever panel is taller, so the two sit level
   without a pocket of dead space under the bars. */
.panels > .panel { display: flex; flex-direction: column; }
.chart {
  display: flex; align-items: flex-end; gap: 5px;
  flex: 1; min-height: 168px;
  border-bottom: 1px solid var(--line);
}
.chart__col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; }
.chart__bar {
  width: 100%; background: var(--ink); border-radius: 2px 2px 0 0;
  min-height: 2px; opacity: .82;
}
.chart__col:last-child .chart__bar { background: var(--green-deep); opacity: 1; }
.chart__col--empty .chart__bar { background: var(--canvas-2); opacity: 1; }
.chart__x {
  display: flex; justify-content: space-between;
  margin-top: 11px; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .06em; color: var(--ink-40);
}

.bars { display: grid; gap: 15px; }
.bar__row { display: grid; grid-template-columns: 1fr auto; gap: 10px 14px; align-items: baseline; }
.bar__k { font-size: 13.5px; color: var(--ink-80); }
.bar__n { font-family: var(--mono); font-size: 12.5px; color: var(--ink-40); }
.bar__track { grid-column: 1 / -1; height: 5px; border-radius: 3px; background: var(--canvas-2); overflow: hidden; }
.bar__fill { height: 100%; background: var(--green-deep); border-radius: 3px; }

/* ---------- Attachments (admin) ---------- */
/* Three counts that are parts of one total, drawn as parts of one total.
   They were three headline numbers in the metric strip's own type, which hid
   the only ratio the panel exists to show. The unread segment is hatched
   rather than filled: it is the part Guard4AI could not see into, and an
   absence should not look like a measurement. */
.files { margin-top: 20px; }
.fstack {
  display: flex; height: 14px; border-radius: 3px; overflow: hidden;
  background: var(--canvas-2);
}
.fstack[hidden] { display: none; }
.fstack__seg { display: block; height: 100%; }
.fstack__seg--checked { background: var(--ink); opacity: .38; }
.fstack__seg--blocked { background: var(--green-deep); }
.fstack__seg--unreadable {
  background: repeating-linear-gradient(
    -45deg, var(--canvas-2) 0 4px, rgba(10, 31, 24, .2) 4px 6px);
}

.fkeys { list-style: none; display: grid; grid-template-columns: repeat(3, auto);
  justify-content: space-between; gap: 18px 40px; margin-top: 20px; }
.fkeys:empty { display: none; margin: 0; }
.fkey { display: grid; grid-template-columns: auto auto auto; gap: 3px 10px;
  align-items: baseline; justify-content: start; }
.fkey__sw { width: 9px; height: 9px; border-radius: 2px; align-self: center; }
.fkey__sw--checked { background: var(--ink); opacity: .38; }
.fkey__sw--blocked { background: var(--green-deep); }
.fkey__sw--unreadable {
  background: repeating-linear-gradient(
    -45deg, var(--canvas-2) 0 2px, rgba(10, 31, 24, .3) 2px 3px);
}
.fkey__lab { font-size: 13.5px; color: var(--ink-80); }
.fkey b {
  font-family: var(--mono); font-size: 15px; font-weight: 600;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
/* The number the panel exists for keeps the accent it had as a headline. */
.fkey--unreadable b { color: var(--green-deep); }
.fkey__sub { grid-column: 2 / -1; font-size: 12.5px; color: var(--ink-40); margin: 0; }
.files__note { font-size: 13px; line-height: 1.55; color: var(--ink-60); margin-top: 20px; }
.files__note[hidden] { display: none; }
@media (max-width: 760px) {
  .fkeys { grid-template-columns: 1fr; gap: 14px; justify-content: start; }
}

/* ---------- AI tools (admin) ---------- */
/* One row per tool, and TWO bars on one scale. The old row showed two
   percentages of two different totals in identical type with a single bar
   keyed to one of them, so a row could read "0% of use, 8% of catches" beside
   an empty track and look broken. Drawn as a pair, equal width means equal
   share and the gap between the bars is the finding. */
.tools { margin-top: 20px; }
.tools__rows { display: grid; gap: 22px; }
.tool { display: grid; gap: 9px; }
.tool__head {
  display: flex; align-items: baseline; gap: 10px 14px; flex-wrap: wrap;
}
.tool__k { font-size: 14.5px; color: var(--ink); font-weight: 500; }
.tool__n {
  margin-left: auto;
  font-family: var(--mono); font-size: 12.5px; color: var(--ink-40);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.tool__n b { color: var(--ink-80); font-weight: 500; }
/* Catches is the column an admin is looking for trouble in, so its number
   carries the accent while "of use" stays neutral reference. */
.tool__n b.c { color: var(--green-deep); font-weight: 600; }
/* An absence, set in italics so it cannot be mistaken for a measurement. */
.tool__unknown { font-style: italic; color: var(--ink-40); }

/* Only ever on a row where both shares clear the floor and the gap is wide,
   so this is rare by construction and can afford to be the loudest thing in
   the panel. Green is already doing "look here" duty on this page. */
.tool__flag {
  font-family: var(--mono); font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--green-deep);
  background: var(--green-wash); border: 1px solid var(--green-line);
  border-radius: var(--r-sm); padding: 3px 7px;
}

.tool__bars { display: grid; grid-template-columns: auto 1fr; gap: 6px 11px; align-items: center; }
.tool__lab {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .11em;
  text-transform: uppercase; color: var(--ink-40); width: 52px;
}
.tool__track { height: 5px; border-radius: 3px; background: var(--canvas-2); overflow: hidden; }
.tool__track i { display: block; height: 100%; background: var(--ink); opacity: .38; border-radius: 3px; }
.tool__track--c i { background: var(--green-deep); opacity: 1; }
.tools__note { font-size: 13px; line-height: 1.55; color: var(--ink-60); margin-top: 20px; }
.tools__note[hidden] { display: none; }
@media (max-width: 560px) {
  .tool__n { margin-left: 0; width: 100%; white-space: normal; }
}

.tablewrap { margin-top: 20px; border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; background: var(--paper); }
.tablewrap .panel__h { padding: 24px 26px 0; margin-bottom: 18px; }

/* Seats: the same disclosure as "What stays on", because this is the same
   kind of thing — a long list you open to act on, not a panel you read. */
.seats > .policy__lockhead { padding: 20px 26px; }
.seats__body { padding-bottom: 8px; }
.seats__sub {
  font-size: 13.5px; line-height: 1.55; color: var(--ink-60);
  margin: 0 26px 18px; max-width: 64ch;
}
.tscroll { overflow-x: auto; }
table.tbl { width: 100%; border-collapse: collapse; min-width: 520px; }
.tbl th {
  text-align: left; font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: .13em; text-transform: uppercase; color: var(--ink-40);
  padding: 12px 26px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  background: var(--canvas);
}
.tbl td { padding: 15px 26px; border-bottom: 1px solid var(--line-soft); font-size: 14.5px; color: var(--ink-80); }
.tbl tr:last-child td { border-bottom: 0; }
.tbl td.id { font-family: var(--mono); font-size: 12.5px; color: var(--ink); letter-spacing: .05em; }
/* Name first, seat id under it. The id stays because two people called Sarah
   Chen have to be tellable apart, and because Remove and every support
   conversation are keyed on it. */
.seatname { display: block; font-size: 14.5px; color: var(--ink); font-weight: 550; }
.seatname--none { color: var(--ink-60); font-weight: 400; }
.seatid {
  display: block; margin-top: 3px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .05em; color: var(--ink-60);
}
/* ink-60, not the ink-40 the rest of the table's secondary text uses. Measured
   on the table ground, ink-40 is 3.23:1, and both of these carry information
   somebody has to read accurately: the id is how two people with the same name
   are told apart and what a support conversation quotes, and "Not named" is a
   state, not decoration. The weight and size keep them secondary. */
/* Rename sits beside Remove and is deliberately the quieter of the two. */
.seatedit {
  background: none; border: 1px solid var(--line); border-radius: var(--r-sm);
  color: var(--ink-40); font-family: inherit; font-size: 12.5px;
  padding: 6px 12px; cursor: pointer; margin-right: 6px;
  transition: color .15s ease, border-color .15s ease;
}
.seatedit:hover { color: var(--ink); border-color: var(--ink-40); }
.seatedit:disabled { opacity: .55; cursor: default; }
.seatform { display: flex; gap: 6px; align-items: center; }
.seatform input {
  width: 8.5ch; min-width: 0; flex: 1;
  font: inherit; font-size: 13.5px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 5px 8px;
}
.seatform input:focus { outline: 2px solid var(--green-deep); outline-offset: 1px; border-color: transparent; }
.tbl td.num { font-variant-numeric: tabular-nums; }
.tbl td.dim { color: var(--ink-40); font-size: 13.5px; }

.empty { padding: 34px 26px; font-size: 14.5px; color: var(--ink-60); }

/* Removing a seat. Click to arm, click again to remove: this deletes the seat
   and every count filed against it, so the confirming click lands on a button
   that has visibly become a different button. */
.tbl__act { text-align: right; width: 1%; white-space: nowrap; }
.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.seatdel {
  background: none; border: 1px solid var(--line); border-radius: var(--r-sm);
  color: var(--ink-40); font-family: inherit; font-size: 12.5px;
  padding: 6px 12px; cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.seatdel:hover { color: var(--ink); border-color: var(--ink-40); }
.seatdel.is-armed {
  color: #8c3d2e; border-color: #f0c4bb; background: #fdf3f1; font-weight: 600;
}
.seatdel:disabled { opacity: .55; cursor: default; }
.seatmsg {
  padding: 16px 26px; margin: 0; font-size: 14px; color: var(--green-deep);
  border-top: 1px solid var(--line-soft);
}
.seatmsg.is-bad { color: #8c3d2e; }
.dash__state { padding: 80px 0; font-size: 15px; color: var(--ink-60); line-height: 1.6; }
.dash__state strong { font-size: 18px; color: var(--ink); font-weight: 600; letter-spacing: -.01em; }
/* The second line of the waiting-for-Stripe state: quieter than the headline,
   and roomy, because someone reads it right after entering a card. */
/* Block, so it always sits under the headline rather than depending on every
   caller remembering a <br />. */
.dash__sub { display: block; margin-top: 6px; max-width: 460px; color: var(--ink-60); }
.dash__state .btn { margin-top: 18px; }
/* Recovery form for an account that has no company yet. */
.dash__make { display: flex; gap: 10px; margin-top: 20px; flex-wrap: wrap; }
.dash__make input {
  flex: 1 1 260px; max-width: 340px;
  font-family: var(--sans); font-size: 15px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 11px 14px;
}
.dash__make input:focus { outline: none; border-color: var(--green-deep); }
.dash__make .btn { margin-top: 0; }

@media (max-width: 940px) {
  .metrics { grid-template-columns: repeat(2, 1fr); }
  .panels { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .metrics { grid-template-columns: 1fr; }
  .invite { width: 100%; }
}

/* ---------- Analytics consent bar ---------- */
/* A bar, not a modal: nothing is covered, nothing is blocked, and the page is
   readable and usable while it is open. It appears only where consent is
   required, and only until it is answered once.

   The two buttons are the same size and sit together. Refusing must not be
   the harder of the two to do, which rules out the pattern where one is a
   button and the other is a line of grey text. */
.cbar {
  position: fixed; left: 16px; right: 16px; bottom: 16px; z-index: 60;
  display: grid; grid-template-columns: 1fr auto; gap: 6px 26px;
  align-items: center;
  max-width: 880px; margin: 0 auto;
  padding: 18px 20px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: 0 10px 34px rgba(10, 31, 24, .13);
  animation: cbarIn .28s cubic-bezier(.16, 1, .3, 1);
}
@keyframes cbarIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .cbar { animation: none; } }

.cbar__t { font-size: 13.5px; line-height: 1.55; color: var(--ink-60); margin: 0; }
.cbar__t strong { color: var(--ink-80); font-weight: 600; }
.cbar__a { display: flex; gap: 8px; }
.cbar__a .btn { margin-top: 0; white-space: nowrap; }
.cbar__more {
  grid-column: 1; font-size: 12.5px; color: var(--ink-40);
  text-decoration: none; border-bottom: 1px solid var(--line); justify-self: start;
}
.cbar__more:hover { color: var(--ink-80); border-bottom-color: var(--ink-40); }

@media (max-width: 620px) {
  .cbar { grid-template-columns: 1fr; gap: 14px; left: 10px; right: 10px; bottom: 10px; }
  .cbar__a .btn { flex: 1; }
  .cbar__more { grid-column: 1; }
}

/* The way back to a decision already made, offered on the privacy page. */
.cchoice {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 18px;
}
.cchoice__s {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .04em;
  color: var(--ink-40);
}

/* ---------- Checkout success ---------- */
/* Wider than the sign-in form it borrows its shell from: this page holds a
   key, three steps and a button, not two fields. */
.ok { max-width: 520px; }

.ok__key {
  margin-top: 30px; padding: 22px 22px 20px;
  background: var(--green-wash); border: 1px solid var(--green-line);
  border-radius: var(--r);
}
.ok__k {
  display: block; margin-bottom: 12px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--green-deep);
}
/* The code sits on paper inside the wash so it reads as the object to copy
   rather than as part of the panel. */
.ok__key .invite__code { font-size: 17px; padding: 13px 18px; }
.ok__plan {
  margin-top: 14px; font-family: var(--mono); font-size: 12px;
  color: var(--ink-60); letter-spacing: .02em;
}

.ok__steps {
  margin: 28px 0 0; padding: 0; list-style: none;
  counter-reset: step; display: grid; gap: 14px;
}
/* An author `display` outranks the browser's own [hidden] { display: none },
   so a grid or flex element that starts hidden shows anyway. Every block on
   this page is revealed by script, so each one that sets display needs this. */
.ok__steps[hidden] { display: none; }
.ok__steps li {
  counter-increment: step; position: relative; padding-left: 34px;
  font-size: 15.5px; line-height: 1.55; color: var(--ink-80);
}
.ok__steps li::before {
  content: counter(step);
  position: absolute; left: 0; top: 1px;
  width: 22px; height: 22px; border-radius: var(--r-pill);
  display: grid; place-items: center;
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  color: var(--green-deep); background: var(--green-wash);
  border: 1px solid var(--green-line);
}
.ok__steps b { font-weight: 600; color: var(--ink); }

.ok__mail { margin-top: 22px; font-size: 14px; line-height: 1.6; color: var(--ink-60); }
.ok__cta { margin-top: 28px; }
.ok__cta .btn { width: 100%; }

/* Waiting on the webhook. Dimmed rather than replaced, so the page does not
   jump when the key arrives a second later. */
.ok[data-state="loading"] #sub { color: var(--ink-40); }

@media (max-width: 560px) {
  .ok__key { padding: 18px 16px 16px; }
  .ok__key .invite { width: 100%; }
  .ok__key .invite__code { flex: 1 1 auto; font-size: 15px; }
}

/* ---------- Reveal on scroll (shared) ---------- */
/* ---- reveal on scroll ----
   The .fx class is added by script, and only to elements that start BELOW the
   viewport, so nothing already on screen ever blinks out. The hidden state
   lives under prefers-reduced-motion: no-preference: a reduced-motion reader
   gets a page that was never hidden, not one that un-hides quickly. */
@media (prefers-reduced-motion: no-preference) {
  /* The curve is most of the class: fast out of the gate, then a long
     settle. Paired with a soft blur dissolve — the arriving block reads as
     coming into focus rather than sliding in. */
  /* The transition lives on the revealed state, not the base: opting an
     element in hides it instantly, and only the reveal animates. On the
     base state, adding the class would itself animate a fade-out. */
  .fx { opacity: 0; transform: translateY(22px); filter: blur(6px); }
  .fx.is-in {
    opacity: 1; transform: none; filter: blur(0);
    transition: opacity .75s cubic-bezier(.16,1,.3,1),
                transform .75s cubic-bezier(.16,1,.3,1),
                filter .75s cubic-bezier(.16,1,.3,1);
  }

  /* Stagger parents: the container is never hidden itself; its direct
     children arrive in sequence, 90ms apart. Grids and pairs cascade,
     which is the difference between a slab appearing and a page being
     set down piece by piece. */
  .fxs > * { opacity: 0; transform: translateY(22px); filter: blur(6px); }
  .fxs.is-in > * {
    opacity: 1; transform: none; filter: blur(0);
    transition: opacity .75s cubic-bezier(.16,1,.3,1),
                transform .75s cubic-bezier(.16,1,.3,1),
                filter .75s cubic-bezier(.16,1,.3,1);
  }
  .fxs.is-in > :nth-child(2) { transition-delay: .09s; }
  .fxs.is-in > :nth-child(3) { transition-delay: .18s; }
  .fxs.is-in > :nth-child(4) { transition-delay: .27s; }
  .fxs.is-in > :nth-child(5) { transition-delay: .36s; }
  .fxs.is-in > :nth-child(n+6) { transition-delay: .45s; }
}


/* ---- the dashboard carousel ------------------------------------------------
   Five panels of the real dashboard, one at a time. The stage is a scroll-snap
   strip rather than a JS-driven track: it swipes natively on touch, it still
   scrolls if the script never runs, and the buttons only ever ask it to scroll
   somewhere it could already go. */
.car { position: relative; }
/* The frame follows the slide rather than every slide being padded out to the
   tallest. Five panels of very different natural depth in one fixed frame
   means four of them float in dead space. */
.car__stage { position: relative; overflow: hidden; transition: height .3s ease; }
@media (prefers-reduced-motion: reduce) { .car__stage { transition: none; } }
.car__track {
  display: flex; margin: 0; padding: 0; list-style: none;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scroll-behavior: smooth;
  scrollbar-width: none; -ms-overflow-style: none;
}
.car__track::-webkit-scrollbar { display: none; }
@media (prefers-reduced-motion: reduce) { .car__track { scroll-behavior: auto; } }
.car__slide { flex: 0 0 100%; scroll-snap-align: center; }
.car__slide img { display: block; width: 100%; height: auto; }

/* Beside the caption, not floating over the image. The slides are themselves
   screenshots of a dense interface, and a control laid on top of one reads as
   part of the product being shown. */
.car__btns {
  grid-column: 3; grid-row: 1 / span 2;
  display: flex; gap: 8px; align-self: center;
}
.car__nav {
  width: 38px; height: 38px; border-radius: 999px; cursor: pointer;
  display: grid; place-items: center;
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--line);
  transition: opacity .15s ease, background .15s ease, border-color .15s ease;
}
.car__nav svg { width: 18px; height: 18px; }
.car__nav:hover:not([disabled]) { background: var(--canvas-2); border-color: var(--ink-40); }
.car__nav[disabled] { opacity: .3; cursor: default; }
.car__nav:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 2px; }

.car__cap {
  display: grid; grid-template-columns: auto 1fr auto; gap: 2px 14px;
  align-items: baseline; padding: 16px 18px 4px;
}
/* Placed rather than auto-flowed. Three items of two different row spans in a
   three-column grid do not land where you would guess. */
.car__step {
  grid-column: 1; grid-row: 1 / span 2;
  font-family: var(--mono); font-size: 11px;
  letter-spacing: .1em; color: var(--ink-40); padding-top: 3px;
}
.car__t {
  grid-column: 2; grid-row: 1;
  font-size: 15px; font-weight: 650; color: var(--ink); letter-spacing: -.01em;
}
.car__d {
  grid-column: 2; grid-row: 2;
  font-size: 13.5px; line-height: 1.55; color: var(--ink-60);
}

.car__dots { display: flex; gap: 7px; justify-content: center; padding: 12px 0 16px; }
.car__dot {
  width: 7px; height: 7px; border-radius: 999px; cursor: pointer;
  background: var(--line); border: 0; padding: 0;
  transition: background .15s ease, transform .15s ease;
}
.car__dot[aria-current="true"] { background: var(--green-deep); transform: scale(1.3); }
.car__dot:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 3px; }

@media (max-width: 620px) {
  /* Swiping is the primary control at this width, so the caption gets the full
     row and the buttons drop beneath it rather than squeezing the text. */
  .car__cap { padding: 14px 14px 2px; grid-template-columns: auto 1fr; }
  .car__btns { grid-column: 1 / -1; grid-row: 3; margin-top: 10px; }
  .car__nav { width: 40px; height: 40px; }
}


/* ---- the header's three states ---------------------------------------------
   data-auth is stamped on <html> by an inline script in <head>, before first
   paint, so the correct header is the FIRST thing drawn. There is deliberately
   no signed-out default: "out" is a resolved answer, not a fallback, and
   defaulting to it is what produces the swap this is built to avoid.

     out      resolved: no session
     in       resolved: a session
     unknown  localStorage could not be read at all (private mode, blocked
              site data). A neutral placeholder holds the width until the
              module says which it is. */
.nav__seat { display: none; align-items: center; gap: 14px; }
:root[data-auth="out"] .nav__seat--out { display: flex; }
:root[data-auth="in"] .nav__seat--in { display: flex; }
:root[data-auth="unknown"] .nav__seat--wait { display: flex; }

/* Roughly the resolved width, so resolving does not shove the burger sideways.
   Not animated: a pulsing skeleton in a header reads as a broken page. */
.nav__skel { display: block; height: 32px; border-radius: var(--r-sm); background: var(--canvas-2); }
.nav__skel--a { width: 118px; }
.nav__skel--b { width: 92px; }

/* ---- the account menu ---- */
.acct { position: relative; }
.acct__btn {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  padding: 4px 8px 4px 4px; border-radius: 999px;
  background: transparent; border: 1px solid var(--line);
  transition: background .15s ease, border-color .15s ease;
}
.acct__btn:hover { background: var(--canvas-2); border-color: var(--ink-40); }
.acct__btn:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 2px; }
.acct__ini {
  width: 26px; height: 26px; border-radius: 999px; flex: none;
  display: grid; place-items: center;
  background: var(--green-deep); color: var(--paper);
  font-size: 12px; font-weight: 700; line-height: 1;
}
.acct__chev { width: 14px; height: 14px; color: var(--ink-60); }
.acct__menu {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 60;
  min-width: 232px; padding: 6px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--float);
}
.acct__menu[hidden] { display: none; }
.acct__email {
  display: block; padding: 9px 10px 10px;
  font-size: 12.5px; color: var(--ink-60); word-break: break-all;
  border-bottom: 1px solid var(--line-soft); margin-bottom: 4px;
}
.acct__item {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 9px 10px; border: 0; background: transparent; border-radius: var(--r-sm);
  font-size: 14px; font-weight: 500; color: var(--ink);
}
.acct__item:hover { background: var(--canvas-2); }
.acct__item[disabled] { opacity: .6; cursor: default; }

/* ---- the same three states in the mobile panel ---- */
.nav__panel .nav__seat { flex-direction: column; align-items: stretch; gap: 0; }
:root[data-auth="out"] .nav__panel .nav__seat--out,
:root[data-auth="in"] .nav__panel .nav__seat--in { display: flex; }
.navm__email {
  padding: 13px var(--gutter); font-size: 13px; color: var(--ink-60);
  border-top: 1px solid var(--line-soft); word-break: break-all;
}
.navm__signout {
  width: 100%; text-align: left; cursor: pointer;
  padding: 13px var(--gutter); font-size: 16px; font-weight: 500;
  color: var(--ink-80); background: transparent; border: 0;
  border-top: 1px solid var(--line-soft);
}
.navm__signout:active { background: var(--canvas); }

@media (max-width: 940px) {
  /* The desktop seats collapse to the burger exactly as the old header did.
     Stated for the account button too, or it survives into the mobile bar. */
  .nav__right .acct { display: none; }
  .nav__seat--wait { display: none !important; }
}

/* ---- the hero's second call to action -------------------------------------
   Offering a fourteen-day trial to somebody already inside one tells a
   customer the page does not know who they are. data-plan is cached from the
   last resolved answer and stamped before paint, so a returning subscriber
   never sees the trial offer flash past. */
.cta--dash { display: none; }
:root[data-plan="live"] .cta--trial { display: none; }
:root[data-plan="live"] .cta--dash { display: inline-flex; }


/* ---- a field-level error --------------------------------------------------
   Under the field it belongs to, not in the form-wide box at the bottom. The
   box is for "the submit failed"; this is "this value is the problem", and an
   answer that names a field ought to sit against it. */
.field__err {
  font-size: 13.5px; line-height: 1.5; color: #8c3d2e; margin: 0;
}
.field__err[hidden] { display: none; }
.field__err a { color: #8c3d2e; font-weight: 600; border-bottom: 1px solid #e0b3a8; }
.field__err a:hover { border-bottom-color: #8c3d2e; }
.field input[aria-invalid="true"] { border-color: #f0c4bb; }
.field input[aria-invalid="true"]:focus { border-color: #8c3d2e; }

/* ---- the sign-up confirmation --------------------------------------------
   Same card as the contact form's, with two additions. */

/* Quieter than the body copy above it, not louder. Delivery through Resend
   lands in the inbox, so this is the rare case rather than the expected one,
   and a line that outshouts the heading advertises a failure we do not have. */
.sentcard__fallback {
  margin: 14px auto 0; max-width: 42ch;
  font-size: 13.5px; line-height: 1.55; color: var(--ink-60);
}
/* ink-60 rather than ink-40: measured on the card, ink-40 is 3.48:1 and fails
   AA at this size. The size does the quietening, the colour does not have to. */

.sentcard__resend { margin: 30px 0 0; }
.sentcard__resendbtn {
  cursor: pointer; background: transparent; border: 0; padding: 0;
  font: inherit; font-size: 15px; font-weight: 600; color: var(--green-deep);
  border-bottom: 1px solid var(--green-line);
}
.sentcard__resendbtn:hover:not([disabled]) { border-bottom-color: var(--green-deep); }
.sentcard__resendbtn[disabled] {
  cursor: default; color: var(--ink-40); border-bottom-color: transparent;
}
.sentcard__resendbtn:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 3px; }
.sentcard__resendmsg {
  display: block; margin-top: 8px;
  font-size: 13.5px; line-height: 1.5; color: var(--ink-60);
}


/* ---- Dashboard or Account, decided by the plan ----------------------------
   An individual has no team dashboard, so the header must not offer them one.
   Two anchors picked by CSS rather than one relabelled by script: the href has
   to be right at first paint too, and CSS cannot set an href. */
.nav__acct { display: none; }
:root[data-dest="account"] .nav__dash { display: none; }
:root[data-dest="account"] .nav__acct { display: inline-flex; }
.nav__panel .nav__acct { display: none; }
:root[data-dest="account"] .nav__panel .nav__acct { display: block; }
:root[data-dest="account"] .nav__panel .nav__dash { display: none; }

/* Business keeps the team dashboard and gets the billing page beside its code. */
.invite__billing {
  margin-left: 14px; font-size: 13px; color: var(--ink-60);
  border-bottom: 1px solid var(--line); white-space: nowrap;
}
.invite__billing:hover { color: var(--ink); border-bottom-color: var(--ink-40); }

/* ---- /account -------------------------------------------------------------
   The individual's own dashboard: the team layout with everything that only
   means something for a team removed. It borrows .dash, .metrics, .panels,
   .chart and .bars wholesale, so there are only two rules of its own. */
.acct-page { padding-bottom: 96px; }

}


/* ---- signing up while already signed in ----------------------------------
   Its own name, not .signedin: that one is the pricing page's status line and
   restyling it from here would move a component on a different page. */
.suwarn {
  margin-top: 30px; padding: 22px 24px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.suwarn[hidden] { display: none; }
.suwarn__t { font-size: 16px; color: var(--ink); }
.suwarn__t b { font-weight: 650; }
.suwarn__p { margin-top: 8px; font-size: 14px; line-height: 1.55; color: var(--ink-60); }
.suwarn__acts { display: flex; gap: 10px; margin-top: 18px; flex-wrap: wrap; }


/* ---- the range picker ---- */
.rangepick {
  display: inline-flex; align-items: center; gap: 2px; flex: none;
  background: var(--canvas-2); border: 1px solid var(--line);
  border-radius: var(--r-pill); padding: 3px;
}
.rangepick__b {
  cursor: pointer; border: 0; background: transparent;
  padding: 6px 13px; border-radius: var(--r-pill);
  font: inherit; font-size: 13px; font-weight: 550; color: var(--ink-60);
  white-space: nowrap; transition: background .15s ease, color .15s ease;
}
.rangepick__b:hover:not([aria-pressed="true"]):not([disabled]) { color: var(--ink); }
.rangepick__b[aria-pressed="true"] {
  background: var(--paper); color: var(--ink);
  box-shadow: 0 1px 2px rgba(10, 31, 24, .06);
}
.rangepick__b:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 2px; }
.rangepick.is-busy { opacity: .55; }
.rangepick.is-busy .rangepick__b { cursor: default; }

/* The lead sentence and the control share a line: the sentence names the
   window, so the thing that changes it belongs beside it rather than in a
   corner of the page arguing with the invite code for the same space. */
.leadrow {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin: 22px 0 0;
}
.leadrow .lead { margin: 0; flex: 1 1 420px; }
@media (max-width: 620px) {
  .leadrow { gap: 14px; }
  .rangepick__b { padding: 6px 11px; font-size: 12.5px; }
}

.invite__comped {
  margin-left: 14px; font-size: 13px; color: var(--green-deep);
  background: var(--green-wash); border: 1px solid var(--green-line);
  border-radius: var(--r-pill); padding: 3px 10px; white-space: nowrap;
}


/* ---- password fields ----
   The field is the positioning context, so the button sits inside its right
   edge. The input gets padding to match, or the text runs under the icon as
   it fills. */
.pwwrap { position: relative; display: block; }
.field input.has-reveal { padding-right: 46px; }
.reveal {
  position: absolute; right: 1px; top: 1px; bottom: 1px;
  width: 44px; display: grid; place-items: center;
  background: transparent; border: 0; cursor: pointer;
  color: var(--ink-40); border-radius: var(--r-sm);
}
.reveal svg { width: 18px; height: 18px; }
.reveal:hover { color: var(--ink); }
.reveal[aria-pressed="true"] { color: var(--ink); }
.reveal:focus-visible { outline: 2px solid var(--green-deep); outline-offset: -2px; }

.field__help { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-40); }
.field__help[hidden] { display: none; }

.form__forgot {
  margin-left: auto; font-size: 12.5px; color: var(--ink-60);
  border-bottom: 1px solid var(--line);
}
.form__forgot:hover { color: var(--ink); border-bottom-color: var(--ink-40); }
.field__row { display: flex; align-items: baseline; gap: 10px; }

/* ---- "Already using enterprise AI?" ---------------------------------------
   One objection, answered in a few seconds: the approved account only covers
   itself, and the tabs beside it sit outside it.

   The section is a pale panel rather than another band of body copy, so it
   reads as a distinct beat. No shadow, no gradient, no icons: a tint and one
   hairline, which is how the rest of the site separates things.

   TRANSITION. .section is 112px top and bottom, so this ran 224px below "Why
   now" and looked like a page break. The section keeps its bottom padding and
   drops its top padding to nothing; the panel's own 56px of interior padding
   is what keeps the content off the edge. */
.eai-sec { padding-top: 0; padding-bottom: 48px; }
@media (max-width: 940px) { .eai-sec { padding-top: 0; padding-bottom: 36px; } }

.eai {
  background: var(--green-wash);
  border: 1px solid var(--green-line);
  border-radius: 18px;
  padding: 52px 56px 44px;
}
@media (max-width: 700px) { .eai { padding: 34px 22px 30px; border-radius: 14px; } }

/* Headline and illustration start on the same line, which is the whole point
   of the two columns. align-items: start, never center. */
.eai__top { display: grid; gap: 32px; align-items: start; }
/* The graphic gains about 54px. The headline still breaks after "Already
   using" at the narrower copy column, so nothing is squeezed. */
@media (min-width: 900px) { .eai__top { grid-template-columns: .95fr 1.05fr; gap: 50px; } }
/* No max-width: the column is the constraint. 19ch was fractionally narrower
   than "One approved account." at the capped size and broke it across three
   lines. */
/* The question is the heading now, so it starts the column: the 15px used to
   sit under the eyebrow that has gone. */
/* balance stops "AI?" being stranded on a line of its own; browsers without
   it simply wrap as before. */
.eai__copy .h2 { margin: 0; text-wrap: balance; }
/* The old headline, demoted. Green and roughly half the size of the heading
   above it, so the two read in order rather than competing. */
.eai__sub {
  margin: 12px 0 0;
  /* Floor at 19px: at 18 it sat a single pixel above the 17px intro below it
     and stopped reading as a subheading on a phone. */
  font-size: clamp(19px, 1.65vw, 22px); line-height: 1.3;
  letter-spacing: -.014em; font-weight: 650; color: var(--green-deep);
}
.eai__intro {
  margin: 18px 0 0; max-width: 46ch;
  font-size: 17px; line-height: 1.6; color: var(--ink-60);
}

/* One strip, not a stack of paragraphs. */
.eai__strip {
  margin: 40px 0 0; padding-top: 30px; border-top: 1px solid var(--green-line);
  display: grid; gap: 8px;
}
@media (min-width: 900px) { .eai__strip { grid-template-columns: 1fr 1.35fr; gap: 40px; } }
.eai__strip h3 { margin: 0; font-size: 19px; line-height: 1.3; letter-spacing: -.016em; color: var(--ink); }
.eai__strip p { margin: 0; font-size: 16px; line-height: 1.62; color: var(--ink-80); }
.eai__foot {
  margin: 26px 0 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 26px;
}
.eai__aside { font-size: 14.5px; color: var(--ink-60); margin: 0; }
.eai__foot a { font-size: 15px; font-weight: 600; color: var(--green-deep); border-bottom: 1px solid var(--green-line); }
.eai__foot a:hover { border-bottom-color: var(--green-deep); }
.eai__foot a:focus-visible { outline: 2px solid var(--green-deep); outline-offset: 3px; }

/* ---- the account boundary ----
   One idea: the approved account is a bounded thing, the tools beside it are
   not inside that boundary, and Guard4AI runs under both. So only the left
   group is outlined, and the green strip spans the full width beneath them.

   The right group is neutral grey, never amber or red. These tools are not
   unsafe and the graphic must not say they are; they are simply outside the
   boundary the approved account draws. */
.ab__groups { display: grid; gap: 14px; align-items: stretch; }
@media (min-width: 620px) {
  /* The right group gets the width, so Claude and Gemini sit side by side and
     it stands two rows tall rather than three. Stretched groups match heights,
     so a taller right group is dead space inside the left one. */
  /* Measured, not guessed. The illustration column is 451px, and the two
     labels want 184px and 164px unwrapped, so no three-column split gives both
     of them two lines. This split is the one that keeps Claude and Gemini side
     by side; widening the left group past it pushes them onto three rows and
     puts the space straight back into the approved box. */
  /* Re-split for the wider column: the approved group now clears the 146px
     that "YOUR APPROVED" needs, so its heading drops from three lines to two,
     and the other group still holds Claude and Gemini side by side. */
  .ab__groups { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1.32fr); gap: 10px; }
}
.ab__grp { border-radius: 12px; padding: 13px 13px 14px; }
/* The outline belongs to the approved group alone. */
/* A step darker than --green-line (#bfe8cd), which almost disappeared against
   the panel tint. The tiles inside keep the lighter border, so the boundary is
   what the eye picks up rather than its contents. */
.ab__grp--ok { border: 1.5px solid #8ac9a6; background: #f4fbf6; }
.ab__grp--out { border: 1px solid var(--line); background: var(--paper); }
.ab__glabel {
  display: block; margin-bottom: 10px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; line-height: 1.35;
}
.ab__grp--ok .ab__glabel { color: var(--green-deep); }
.ab__grp--out .ab__glabel { color: var(--ink-40); }
.ab__tiles { display: flex; flex-wrap: wrap; gap: 7px; }
.ab__tile {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 8px; padding: 7px 10px;
  font-size: 12.5px; font-weight: 600; color: var(--ink-80); white-space: nowrap;
}
.ab__grp--ok .ab__tile { border-color: var(--green-line); }
.ab__tile svg { width: 15px; height: 15px; flex: none; color: var(--ink-60); }

/* Horizontal between the groups on desktop, vertical between them stacked, so
   the relationship survives the breakpoint instead of becoming decoration. */
.ab__arrow {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  color: var(--ink-60); font-size: 11.5px; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; text-align: center;
}
.ab__arrow svg { width: 22px; height: 22px; flex: none; color: var(--ink-80); transform: rotate(90deg); }
@media (min-width: 620px) {
  .ab__arrow { flex-direction: column; max-width: 86px; line-height: 1.3; }
  .ab__arrow svg { transform: none; }
}

/* Under BOTH groups: additional cover, not a replacement for what is above. */
/* Solid, because this is the point of the graphic. It is the only filled
   surface in the panel, which is what makes it the focal point without
   anything else having to get louder. */
.ab__strip {
  margin-top: 12px; display: flex; align-items: center; gap: 10px;
  background: var(--green-deep); border: 1px solid var(--green-deep);
  border-radius: 12px; padding: 13px 15px;
  font-size: 13.5px; line-height: 1.45; color: #fff;
}
/* The word space after </b> is really there; it just reads as closed up,
   because the bold capital I sits hard against it at this size. A 3px nudge,
   not a second space, so it stays one space if the copy ever changes. */
.ab__strip b { color: #fff; font-weight: 700; white-space: nowrap; margin-right: 3px; }
.ab__strip svg { width: 18px; height: 18px; flex: none; color: #fff; }
.bw__cap { margin: 12px 2px 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-60); }

@media (max-width: 420px) {
  .ab__tile { font-size: 12px; padding: 6px 8px; }
  .ab__glabel { font-size: 10.5px; letter-spacing: .04em; }
}

/* the diagram */
.eflow { max-width: 660px; margin: 34px auto 0; }
.eflow__zone {
  background: var(--canvas); border: 1px solid var(--line); border-radius: var(--r);
  padding: 16px 20px 18px;
}
.eflow__zonelabel, .eflow__outlabel, .eflow__blabel {
  display: block; font-size: 11px; font-weight: 700; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-40); margin-bottom: 10px;
}
.eflow__steps { list-style: none; margin: 0; padding: 0; }
.eflow__steps li {
  display: flex; gap: 11px; align-items: baseline;
  font-size: 15px; line-height: 1.55; color: var(--ink-80);
}
.eflow__steps li + li { margin-top: 9px; }
.eflow__steps b {
  flex: none; width: 20px; height: 20px; border-radius: 50%;
  background: var(--green-wash); color: var(--green-deep);
  font-size: 11.5px; font-weight: 700; line-height: 20px; text-align: center;
  align-self: flex-start; position: relative; top: 2px;
}
/* The arrow is the boundary crossing, so it is labelled rather than decorative. */
.eflow__arrow {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 10px 0; color: var(--ink-60); font-size: 13.5px; text-align: center;
}
.eflow__arrow svg { width: 18px; height: 18px; color: var(--ink-40); }
.eflow__out {
  background: var(--paper); border: 1px solid var(--line-ink); border-radius: var(--r);
  padding: 16px 20px 18px;
}
.eflow__out p { margin: 0; font-size: 15px; line-height: 1.55; color: var(--ink-80); }
/* The side channel: dotted, because it is not on the path the message takes. */
.eflow__branch {
  margin-top: 6px; margin-left: 22px; padding: 16px 20px 18px 22px;
  border-left: 2px dotted var(--line); border-top: 0;
  position: relative;
}
.eflow__branch::before {
  content: ""; position: absolute; left: -2px; top: 0; width: 2px; height: 22px;
  background: transparent;
}
.eflow__bcard {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r);
  padding: 16px 20px 18px;
}
.eflow__bcard p { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--ink-60); }
.eflow__bcard p + p { margin-top: 9px; }
.eflow__bcard b { color: var(--ink); font-weight: 650; }
.eflow__never { color: var(--ink) !important; }

/* ---- /demo ----------------------------------------------------------------
   The page is a link sent to a prospect, so it is one block: heading, player,
   caption, centred in the first screen. Arriving on it should show the whole
   demonstration, not the top two thirds of it. The dark frame is gone: it
   took 80px of height the player needed, and a hairline holds the edge. */
.demostage {
  display: flex;
  min-height: calc(100vh - 69px);   /* 69px is the sticky nav, which is in flow */
  min-height: calc(100svh - 69px);  /* svh: the mobile bar is out at load */
  padding: 32px 0;
}
/* Auto margins rather than align-items: center, which would push the top of an
   over-tall block above the scroll origin and out of reach. */
/* Wider than the site's 1180 measure: this page is the player, and on a tall
   screen the text column was the only thing holding it back. */
.demostage > .wrap { margin-block: auto; max-width: 1520px; }

/* Heading, player and caption share one width, so the group stays a group as
   the viewport shortens. The cap is the widest 16:9 player that still leaves
   room for the rest: 69 nav + 64 stage padding + 111 heading. */
.demostage__in {
  --chrome: 244px;
  width: min(100%, calc((100vh - var(--chrome)) * 16 / 9));
  width: min(100%, calc((100svh - var(--chrome)) * 16 / 9));
  margin-inline: auto;
}
.demostage__in .label { display: block; margin-bottom: 16px; }
.demostage__h { margin: 0 0 22px; }

/* Only so the sound cue has something to sit against. */
.demoplayer { position: relative; }

.demovid {
  display: block; width: 100%; height: auto;
  border-radius: var(--r-lg);
  /* The video opens on a near-white title card, which without an edge bleeds
     into the paper background. A hairline, not a frame. */
  border: 1px solid var(--ink);
  /* Black behind the poster and between frames, so letterboxing on an odd
     aspect ratio reads as part of the player rather than as a gap. */
  background: #000;
}
/* Narrow screens: the player is short enough to fit whatever the heading does,
   so the width cap comes off and the block just uses the gutter. */
@media (max-width: 940px) {
  .demostage { padding: 24px 0; }
  .demostage__in { width: 100%; }
}
@media (max-width: 560px) { .demovid { border-radius: 8px; } }
/* Added by script, and only when the browser refused sound, so it never shows
   for a visitor who already has it. Top right, clear of the control bar. */
.soundcue {
  position: absolute; top: 14px; right: 14px; z-index: 2;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 14px; border: 0; border-radius: 999px;
  background: rgba(10, 31, 24, .88); color: #fff;
  font: inherit; font-size: 13.5px; font-weight: 600; letter-spacing: -.01em;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.soundcue:hover { background: var(--ink); }
.soundcue svg { width: 15px; height: 15px; flex: none; }
@media (max-width: 560px) {
  .soundcue { top: 10px; right: 10px; padding: 7px 11px; font-size: 12.5px; }
}
