/* ==========================================================================
   The public pages.

   Loaded after app.css and only by templates/public/shell.html, so it
   inherits every colour token, the button rules, the table card-collapse and
   the safe area insets without redefining any of them.

   **The layout model, because it changed and the old one is still visible in
   places.** This used to be one 760px column: every public page was prose,
   and `.pubpage` carried the measure. A marketing site wants full-width
   bands of alternating colour with a centred column inside each, so the
   measure moved inward: `.pubpage` is now full-bleed, `.band` is a
   horizontal stripe, and `.wrap` is the column inside it. A page that is
   still prose — the legal drafts, the features copy — puts `.prose` inside a
   `.wrap` and gets the old behaviour.

   No inline styles anywhere, here or in the templates. The application's
   Content-Security-Policy allows none (see app/security.py), and the one
   exception it does make — the per-tenant accent colour — is not something a
   public page has or should have. The same goes for scripts: the one the
   public pages load is a file, and it is in js/reveal.js.
   ========================================================================== */

/* ------------------------------------------------------------- the shell -- */

.pubbar {
  /* Slate, matching the signed-in top bar: the same edge doing the same
     job. See --line-strong in app.css. */
  border-bottom: 1px solid var(--line-strong);
  background: var(--panel);
  padding-top: var(--sat);
}

.pubbar-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: 10px calc(var(--gap) + var(--sal)) 10px calc(var(--gap) + var(--sar));
  display: flex;
  align-items: center;
  gap: 12px;
  /* **The bar never wraps.** It used to, with the nav claiming a row of
     its own below 700px, which on a 320px screen was three rows of
     chrome before the page started. Below 900px the links go behind the
     disclosure button instead and the bar is one row at every width. */
  flex-wrap: nowrap;
  min-height: 56px;
}

.pubbrand {
  text-decoration: none;
  margin-right: 2px;
  /* 22px high before this, and it is a link to the front page. 2.5.8 again.
     Still a flex row and still at least --target-min tall now that it holds
     an image rather than a word: the target size rule is about the link, not
     about what is inside it. */
  display: inline-flex; align-items: center; min-height: var(--target-min);
  flex: none;
}

/* The lockup is 1371x152, so a little over 9:1. At 26px tall it is 235px
   wide, which fits a 320px screen beside a 44px button with room to
   spare. `max-width: 100%` is the guard: if a future change puts
   something else beside it, the logo shrinks rather than overflowing. */
.pubbrand-logo {
  display: block;
  height: 24px;
  width: auto;
  max-width: 100%;
}

@media (min-width: 900px) {
  .pubbrand-logo { height: 30px; }
}

.pubnav {
  display: flex;
  align-items: center;
  gap: 2px 6px;
  flex: 1;
  min-width: 0;
}

.pubnav a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 10px;
  font-size: .9375rem;
  color: var(--muted);
  text-decoration: none;
  border-radius: var(--radius);
  white-space: nowrap;
}

.pubnav a:hover { color: var(--text); background: var(--panel-2); }
.pubnav a.is-active { color: var(--text); box-shadow: inset 0 -2px 0 var(--accent); }

/* The one primary action in the bar. Orange with black ink, 5.06:1,
   which is the only combination D-126 allows on the brand colour. It
   keeps its own hover and never takes the link hover above. */
.pubnav .pubnav-cta {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  padding: 0 16px;
  box-shadow: none;
}
.pubnav .pubnav-cta:hover {
  background: var(--accent-hover);
  color: var(--accent-ink);
}

/* ------------------------------------------------- the disclosure button -- */

.pubnav-toggle {
  display: none;
  flex: none;
  margin-left: auto;
  width: var(--tap);
  height: var(--tap);
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--control-line);
  border-radius: var(--radius);
  color: var(--text);
  cursor: pointer;
}
.pubnav-toggle:hover { background: var(--panel-2); }
.pubnav-toggle:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* Three bars, drawn. The middle one is the element's own background and
   the outer two are its pseudo-elements, so the icon is one box and no
   SVG request. */
.pubnav-bars,
.pubnav-bars::before,
.pubnav-bars::after {
  display: block;
  width: 18px;
  height: 2px;
  background: var(--text);
  border-radius: 1px;
}
.pubnav-bars { position: relative; }
.pubnav-bars::before,
.pubnav-bars::after { content: ""; position: absolute; left: 0; }
.pubnav-bars::before { top: -6px; }
.pubnav-bars::after { top: 6px; }

/* The bars become a cross when the panel is open, which is the one piece
   of state the icon carries beyond `aria-expanded`. Transform only. */
.nav-open .pubnav-bars { background: transparent; }
.nav-open .pubnav-bars::before { transform: translateY(6px) rotate(45deg); }
.nav-open .pubnav-bars::after { transform: translateY(-6px) rotate(-45deg); }
@media (prefers-reduced-motion: no-preference) {
  .pubnav-bars::before,
  .pubnav-bars::after { transition: transform .18s ease; }
}

@media (max-width: 899px) {
  .pubnav-toggle { display: flex; }

  /* The panel. Positioned under the bar rather than inside it, so the
     bar keeps its height and the panel can be full width.

     `display: none` when closed rather than a height animation: this is
     a menu, a visitor who opened it wants it now, and an animated panel
     on a phone is the thing that feels slow. It is also what keeps the
     links out of the tab order while they are not on screen, with no
     `inert` and no `tabindex` juggling. */
  .pubnav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 8px max(var(--gap), var(--sal)) 14px;
    background: var(--panel);
    border-bottom: 1px solid var(--line-strong);
    box-shadow: 0 18px 34px -20px rgba(0, 0, 0, .9);
  }
  .nav-open .pubnav { display: flex; }

  .pubnav a {
    min-height: 48px;
    padding: 0 12px;
    font-size: 1rem;
    border-radius: var(--radius);
  }
  .pubnav .spacer { display: none; }
  .pubnav .pubnav-cta { justify-content: center; margin-top: 6px; }
}

/* The bar is the positioning context for the panel above, and it has to
   sit over the page rather than under it. */
.pubbar {
  position: relative;
  z-index: 20;
}

/* Full bleed. The measure lives in `.wrap` now; see the file header. The
   safe-area padding stays here so a notch never clips a band's background,
   only its contents. */
.pubpage {
  padding: 0 0 calc(var(--gap) + var(--sab));
}

/* ------------------------------------------------------- bands and wraps -- */

/* A full-width horizontal stripe. Alternating `.band-alt` gives the page the
   rhythm a long marketing page needs without a border between every
   section — a rule every 600px reads as a table of contents. */
/* One rhythm for the whole page: 120px top and bottom on a desktop, 72
   on a phone, interpolated between. Every band reads this token rather
   than its own clamp, so a section that wants to be tighter has to say
   so by name (`.band-tight`) instead of drifting. */
:root { --band-pad: 72px; }
@media (min-width: 1024px) { :root { --band-pad: 120px; } }

.band {
  padding: var(--band-pad) 0;
  border-bottom: 1px solid var(--line-soft);
}
.band-alt { background: var(--panel); }
.band-tight { padding: calc(var(--band-pad) * .6) 0; }
.band:last-of-type { border-bottom: 0; }

/* The column inside a band. 1120px rather than the old 760: a two-column
   before/after and a six-card grid both need the room, and the prose that
   wants 68ch still says so with `.prose`. */
.wrap {
  max-width: 1120px;
  margin: 0 auto;
  padding-left: max(var(--gap), var(--sal));
  padding-right: max(var(--gap), var(--sar));
}
.wrap-narrow { max-width: 820px; }
/* The desk wants more room than the prose column: two halves side by
   side, each of which has to stay legible. */
.wrap-wide { max-width: 1200px; }

/* A section's own heading block: an eyebrow, a big title, one line under it.
   Used often enough to be worth naming rather than repeating three rules. */
.band-head { margin: 0 0 clamp(24px, 3vw, 40px); }
.band-head.is-centred { text-align: center; }
.band-head.is-centred .band-sub { margin-left: auto; margin-right: auto; }

.eyebrow {
  display: block;
  font-size: .8125rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 10px;
}

/* The section titles. `h2` inherits the system font from app.css — only
   `h1` is Barlow Condensed there — so the display face is asked for by
   name here, on the two classes that want it. Keeping it to a class rather
   than retyping every `h2` means a prose heading on the features page is
   still the system font, which is what a paragraph of explanation wants. */
.display {
  font-family: "Barlow Condensed", var(--font);
  font-style: italic;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0;
  line-height: 1.05;
  margin: 0;
}
h1.display { font-size: clamp(2rem, 5vw, 3.25rem); }
h2.display { font-size: clamp(1.75rem, 4.2vw, 2.75rem); }
h3.display { font-size: clamp(1.25rem, 2.6vw, 1.625rem); }

.band-sub {
  margin: 14px 0 0;
  max-width: 58ch;
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--muted);
}

.pubfoot {
  border-top: 1px solid var(--line);
  margin-top: calc(var(--gap) * 2);
  padding-top: var(--gap);
  font-size: .8125rem;
  color: var(--muted);
}

.pubfoot-links { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 0 0 10px; }
/* 24px, for the same reason the signed-in side has it: WCAG 2.2 2.5.8 asks
   it of a target and these measured 19px high in a browser at both widths.
   The public pages are the ones a customer meets first and they were outside
   the accessibility suite's walk, which only visits pages behind a login. */
.pubfoot-links a {
  color: var(--muted);
  display: inline-flex; align-items: center; min-height: var(--target-min);
}
.pubfoot-links a:hover { color: var(--text); }

/* ---------------------------------------------------------------- prose -- */

.prose { max-width: 68ch; }
/* Sized up from 1.5rem for the same reason app.css's h1 is: Barlow
   Condensed reads smaller than the system font at the same size, so this is
   the same optical size rather than a louder one. The family, style, weight
   and casing all come from app.css's `h1` rule, which this only overrides
   the size and margin of. */
.prose h1 { font-size: 2rem; margin-top: 0; }
.prose h2 { font-size: 1.125rem; margin-top: 1.6em; text-transform: none; letter-spacing: 0; }
.prose h3 { font-size: .9375rem; margin-top: 1.4em; text-transform: none; letter-spacing: 0; color: var(--text); }
.prose h4 { font-size: .875rem; margin-top: 1.2em; color: var(--muted); }
.prose p, .prose li { line-height: 1.6; }
.prose ul, .prose ol { padding-left: 1.3em; margin: 0 0 1em; }
.prose li { margin-bottom: .4em; }
.prose hr { border: 0; border-top: 1px solid var(--line); margin: 1.8em 0; }
.prose code {
  font-family: var(--mono); font-size: .875em;
  background: var(--panel-2); border: 1px solid var(--line-soft);
  border-radius: 2px; padding: 0 3px;
  /* A path or a constant name has no spaces in it, so it has to be told it may
     break or it widens the page past a phone's viewport. */
  overflow-wrap: anywhere;
}
.prose blockquote {
  margin: 0 0 1em; padding-left: var(--gap);
  border-left: 2px solid var(--line); color: var(--muted);
}
.prose .table-wrap { margin: 0 0 1.2em; }
/* Every table on a public page, not only the ones in prose. A three-column
   comparison at 320px is the case this exists for: it scrolls sideways
   inside its own box rather than widening the page. */
.table-wrap { overflow-x: auto; }

/* The hero lockup. Capped by width rather than height here, because this
   one is as large as the column allows rather than as tall as a bar — and
   capped at 420px so it does not become a billboard on a wide screen while
   the headline under it stays the same size. */
.hero-logo {
  display: block;
  width: 100%;
  max-width: 420px;
  height: auto;
  margin: 0 0 var(--gap);
}

.lede { font-size: 1.0625rem; color: var(--muted); }

/* --------------------------------------------------------------- claims -- */

.claim { margin: 0 0 var(--gap); }
.claim h3 { margin-bottom: .3em; }

.pubcta {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin: calc(var(--gap) * 1.5) 0;
}

/* ---------------------------------------------------- the draft warnings -- */

/* The legal draft notice. Loud on purpose: the whole point of publishing an
   unreviewed document is that nobody can mistake it for a reviewed one. */
.legal-draft {
  border: 2px solid var(--bad);
  border-radius: var(--radius);
  background: rgba(168, 67, 67, .12);
  padding: 12px var(--gap);
  margin: 0 0 var(--gap);
}
.legal-draft h2 {
  margin: 0 0 .4em; font-size: .9375rem; color: var(--text);
  text-transform: uppercase; letter-spacing: .04em;
}
.legal-draft p { margin: 0; font-size: .875rem; }

/* A fact only Zach can supply. Rendered rather than hidden in a comment,
   because a tidy page with a quiet TODO in the source is how a half-finished
   document ends up in front of a customer. */
.needs-zach {
  background: var(--accent-dim);
  color: var(--text);
  border-radius: 2px;
  padding: 0 4px;
  font-size: .9375em;
  /* The marker text is a whole sentence, so it has to wrap like one. */
  overflow-wrap: anywhere;
}

.placeholder-count {
  display: inline-block;
  border: 1px solid var(--accent);
  border-radius: 2px;
  padding: 1px 6px;
  font-size: .75rem;
  /* The border is the accent; the number is not. D-123. */
  color: var(--muted);
}

/* ----------------------------------------------------------- the one form -- */

/* The honeypot. Taken out of the layout, out of the tab order and out of the
   accessibility tree, so a person using a screen reader is not asked to fill
   in a field that must stay empty. `display: none` would be simpler and some
   form-filling bots skip a field they can see is not rendered, which defeats
   the point. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-note {
  border: 1px solid var(--line);
  border-left: 2px solid var(--accent);
  border-radius: var(--radius);
  background: var(--panel);
  padding: 12px var(--gap);
  margin: 0 0 var(--gap);
  font-size: .875rem;
}
.form-note p:last-child { margin-bottom: 0; }

.problems {
  border: 1px solid var(--bad);
  border-left-width: 2px;
  border-radius: var(--radius);
  padding: 10px var(--gap);
  margin: 0 0 var(--gap);
}
.problems ul { margin: 0; padding-left: 1.2em; }

.reference {
  font-family: var(--mono);
  font-size: 1.125rem;
  letter-spacing: .08em;
  color: var(--text);
}

/* ============================================================== the hero -- */

.hero {
  padding: clamp(40px, 6vw, 84px) 0 0;
  border-bottom: 1px solid var(--line-soft);
  /* A very soft warm wash behind the headline, so the fold has some depth
     without a second background colour. `--accent` at 7% over Charcoal is
     well under anything that could affect the contrast of text on it, and
     the text sits on --bg either way. */
  background:
    radial-gradient(
      90ch 46ch at 12% -10%,
      rgba(211, 84, 31, .10),
      transparent 70%
    );
}

/* 64ch, measured rather than chosen: the headline is six lines at 46ch on
   a laptop and four at 64, because Barlow Condensed fits far more
   characters into a `ch` of the body font than the body font does. The
   supporting line keeps its own 52ch, so only the headline gets the room.
   Below 600px the gutter decides the width and this changes nothing. */
.hero-copy { max-width: 64ch; }

/* The one place on the site with a 1.5rem-plus headline. Clamped so it is
   big on a desktop and still three or four lines on a 320px phone rather
   than eleven. */
.hero h1 {
  font-size: clamp(2.125rem, 6.2vw, 4rem);
  line-height: 1.02;
  margin: 0;
  /* The display face is already on `h1` from app.css. Only the size and the
     measure change here. */
}

.hero-sub {
  margin: 20px 0 0;
  font-size: clamp(1.0625rem, 1.5vw, 1.25rem);
  line-height: 1.55;
  color: var(--muted);
  max-width: 52ch;
}

.hero-actions {
  display: flex; flex-wrap: wrap; gap: 12px;
  margin: 30px 0 0;
}
.hero-actions .btn { min-height: 48px; padding-inline: 22px; font-size: 1rem; }

/* The product shot. A browser frame drawn in CSS — a title bar with three
   dots — because a screenshot floating on a page reads as a picture and a
   screenshot in a frame reads as software. Drawn rather than photographed
   so it carries no chrome from whatever machine took it. */
.hero-shot {
  position: relative;
  margin: clamp(36px, 5vw, 60px) 0 0;
  /* Room under the frame for the phone to hang into. Deep enough that the
     phone never lands on the band's bottom rule, which reads as a picture
     cut off rather than one overlapping another. */
  padding-bottom: clamp(44px, 8vw, 118px);
}

.frame {
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--panel);
  overflow: hidden;
  box-shadow: 0 24px 60px -24px rgba(0, 0, 0, .7);
}

.frame-bar {
  display: flex; align-items: center; gap: 7px;
  padding: 10px 14px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line);
}
.frame-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--line-strong);
}
.frame img { display: block; width: 100%; height: auto; }

/* The phone, overlapping the desktop frame's bottom-right corner. Hidden
   below 720px: on a phone the desktop shot is already small, and a second
   smaller screen on top of it is two illegible pictures instead of one
   legible one. */
.hero-phone { display: none; }

@media (min-width: 720px) {
  .hero-phone {
    display: block;
    position: absolute;
    right: clamp(8px, 3vw, 48px);
    bottom: clamp(16px, 3vw, 44px);
    width: clamp(132px, 15vw, 188px);
    border: 1px solid var(--line-strong);
    border-radius: 18px;
    overflow: hidden;
    background: var(--panel);
    box-shadow: 0 18px 44px -14px rgba(0, 0, 0, .75);
  }
  .hero-phone img { display: block; width: 100%; height: auto; }
}

/* ======================================================= before / after -- */

.compare {
  display: grid;
  gap: clamp(20px, 3vw, 36px);
  grid-template-columns: 1fr;
}
@media (min-width: 820px) {
  .compare { grid-template-columns: 1fr 1fr; }
}

.compare-col {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(20px, 2.4vw, 30px);
  background: var(--bg);
}
.compare-col.is-after {
  background: var(--panel);
  border-color: var(--line-strong);
}
.compare-col h3 { margin: 0 0 18px; font-size: 1rem; }

.compare-list { list-style: none; margin: 0; padding: 0; }
.compare-list li {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 12px;
  align-items: start;
  padding: 11px 0;
  border-bottom: 1px solid var(--line-soft);
  line-height: 1.5;
}
.compare-list li:last-child { border-bottom: 0; }

/* The "without it" column. Struck through and muted, which is the whole
   point of the section — but the strike is decoration and the meaning is
   carried by the column heading and by `.sr-only` text on each mark, so a
   screen reader is not left to infer it from a line through some words. */
.compare-before .compare-list li { color: var(--muted); }
.compare-before .compare-list span:last-child { text-decoration: line-through; }

/* The tick and the cross are **drawn, not typed**, and that is D-123
   rather than a flourish.

   An orange `&check;` is a glyph, and `color: var(--accent)` on a glyph is
   the brand colour used as text — which `tests/test_contrast.py` forbids
   outright and which would here be 3.52:1 against `--panel`, under the
   4.5:1 that text has to clear. Drawn as a shape it is an icon: WCAG
   1.4.11 applies at 3:1, which 3.52:1 clears, and the test's own comment
   says a border and a fill are where the brand colour is still welcome.

   Both are `aria-hidden` in the markup and carry no meaning on their own.
   The column headings ("Without it", "With Thanks for Business") are what
   tell a screen reader which list is which. */
.mark {
  position: relative;
  width: 20px;
  height: 20px;
  /* Optical: lines up with the cap height of the first line of text
     beside it rather than with its box. */
  margin-top: 2px;
}

.mark-yes::before {
  content: "";
  position: absolute;
  left: 4px; top: 1px;
  width: 7px; height: 13px;
  border-right: 2.5px solid var(--accent);
  border-bottom: 2.5px solid var(--accent);
  transform: rotate(40deg);
}

.mark-no::before,
.mark-no::after {
  content: "";
  position: absolute;
  left: 2px; top: 9px;
  width: 15px; height: 2px;
  /* A fill, and `--control-line` is 3.68:1 on `--panel`, so the cross
     clears 1.4.11 as well. Muted rather than red: this column is the old
     way of working, not an error state. */
  background: var(--control-line);
}
.mark-no::before { transform: rotate(45deg); }
.mark-no::after { transform: rotate(-45deg); }

/* ========================================================== how it works -- */

.steps {
  display: grid;
  gap: clamp(22px, 3vw, 34px);
  grid-template-columns: 1fr;
  counter-reset: step;
}
@media (min-width: 860px) {
  .steps { grid-template-columns: repeat(3, 1fr); }
}

.step { position: relative; }
.step-n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 800;
  font-size: 1.0625rem;
  margin: 0 0 16px;
}
.step h3 { margin: 0 0 8px; font-size: 1.0625rem; }
.step p { margin: 0; color: var(--muted); line-height: 1.6; }

/* =========================================================== product tour -- */

.tour-row {
  display: grid;
  gap: clamp(22px, 4vw, 52px);
  grid-template-columns: 1fr;
  align-items: center;
  padding: clamp(28px, 4vw, 52px) 0;
  border-bottom: 1px solid var(--line-soft);
}
.tour-row:last-child { border-bottom: 0; padding-bottom: 0; }
.tour-row:first-child { padding-top: 0; }

@media (min-width: 900px) {
  .tour-row { grid-template-columns: 0.85fr 1.15fr; }
  /* Alternate which side the picture is on. `order` rather than a second
     grid definition, so the markup order stays caption-then-picture and a
     screen reader hears the words before the image either way. */
  .tour-row.is-flipped .tour-shot { order: -1; }
}

.tour-copy h3 { margin: 0 0 10px; }
.tour-copy p { margin: 0; color: var(--muted); line-height: 1.6; max-width: 46ch; }

.tour-shot .frame { box-shadow: 0 18px 44px -22px rgba(0, 0, 0, .65); }

/* ============================================================== built for -- */

.trades {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 640px) { .trades { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 980px) { .trades { grid-template-columns: repeat(6, 1fr); } }

.trade {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  padding: 18px 14px;
  text-align: center;
  font-weight: 600;
  font-size: .9375rem;
}

/* ================================================================== trust -- */

.trust {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
}
@media (min-width: 640px) { .trust { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 980px) { .trust { grid-template-columns: repeat(4, 1fr); } }

.trust-item {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 12px;
  align-items: start;
  line-height: 1.5;
}
.trust-item strong { display: block; }
.trust-item span { color: var(--muted); font-size: .9375rem; }

/* ================================================================ pricing -- */

.price-grid {
  display: grid;
  gap: clamp(16px, 2.5vw, 28px);
  grid-template-columns: 1fr;
}
@media (min-width: 760px) { .price-grid { grid-template-columns: 1fr 1fr; } }

.price-card {
  /* 2px on both cards, so colouring one of them does not change its
     size. The width is the fix: at 1px the featured card's Orange edge
     antialiases against a dark background into a dull red and reads as
     pink rather than as the brand colour — the computed value was
     always #D3541F, and sampling the painted pixels showed the straight
     edges correct and the rounded corners blending to (103,53,34).
     Every other accent edge on this site is 2px or 3px, which is why
     this was the only one that looked wrong. */
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  padding: clamp(21px, 2.6vw, 31px);
  display: flex;
  flex-direction: column;
}
.price-card.is-featured { border-color: var(--accent); }
.price-name { margin: 0; font-size: 1.0625rem; }
.price-amount {
  font-family: "Barlow Condensed", var(--font);
  font-style: italic; font-weight: 800;
  font-size: clamp(2.25rem, 5vw, 3rem);
  line-height: 1;
  margin: 14px 0 4px;
}
.price-unit { color: var(--muted); font-size: .9375rem; }
.price-card ul { list-style: none; margin: 18px 0 0; padding: 0; }
.price-card li {
  display: grid; grid-template-columns: 20px 1fr; gap: 10px;
  padding: 7px 0; line-height: 1.5; font-size: .9375rem;
}
.price-card .btn { margin-top: 22px; }
/* The one-line description of the tier, read from `plans.py` rather than
   written here, so the page and the gate can never drift. It also takes the
   slack in the shorter card, which lines the two cards' actions up. */
.price-blurb {
  flex: 1;
  margin: 18px 0 0;
  color: var(--muted);
  font-size: .9375rem;
  line-height: 1.6;
}

.price-note {
  margin: clamp(20px, 3vw, 32px) 0 0;
  color: var(--muted);
  font-size: .9375rem;
  line-height: 1.6;
}

.founding {
  margin: clamp(20px, 3vw, 30px) 0 0;
  border: 1px solid var(--accent);
  border-left-width: 3px;
  border-radius: var(--radius);
  padding: 16px clamp(16px, 2vw, 22px);
  background: var(--panel);
}
.founding p { margin: 0; line-height: 1.6; }

/* The comparison table under the cards. app.css already collapses a table
   to cards on a phone; this only sets the column rhythm. */
.compare-table { width: 100%; border-collapse: collapse; margin: 0; }
.compare-table th, .compare-table td {
  text-align: left; padding: 11px 12px;
  border-bottom: 1px solid var(--line-soft);
  font-size: .9375rem;
}
.compare-table thead th { color: var(--muted); font-weight: 600; }
.compare-table td:not(:first-child), .compare-table th:not(:first-child) {
  text-align: center;
}
/* The tick and cross are 20px blocks; centring them needs the box centred,
   not the text inside it. */
.compare-table td .mark { display: inline-block; margin: 0; }

/* ======================================== what it does: the capability grid -- */

/* Two columns of prose rather than one 68ch column running the length of the
   page. The copy is unchanged; it was a wall and is now eight things. */
.cap-grid {
  display: grid;
  gap: clamp(24px, 3vw, 40px) clamp(28px, 4vw, 56px);
  grid-template-columns: 1fr;
}
@media (min-width: 860px) { .cap-grid { grid-template-columns: 1fr 1fr; } }

.cap h2 {
  margin: 0 0 10px;
  font-size: 1.0625rem;
  text-transform: none;
  letter-spacing: 0;
  /* The card's rule, drawn above the heading rather than around the whole
     card: eight bordered boxes of long prose reads as a form. */
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
.cap p { margin: 0; color: var(--muted); line-height: 1.65; }

/* ======================================================== the demo page -- */

/* The pitch on the left, the form on the right, one column on a phone. The
   form is second in the markup as well, so the tab order matches. */
.demo-split {
  display: grid;
  gap: clamp(28px, 4vw, 64px);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 900px) {
  .demo-split { grid-template-columns: 1fr 1fr; }
}

.demo-copy h1 { margin: 0; }
.demo-copy .form-note { margin-top: clamp(20px, 3vw, 28px); }
.demo-copy .muted.small { display: block; margin-top: 18px; line-height: 1.6; }

/* The form sits in a panel on a wide screen so the two columns read as two
   things rather than as one long page that happens to have inputs in it. On
   a phone it is the page, so it loses the frame and keeps the space. */
.demo-form .form { max-width: none; }
@media (min-width: 900px) {
  .demo-form {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--panel);
    padding: clamp(22px, 2.6vw, 32px);
  }
}

/* ==================================================================== faq -- */

.faq { display: grid; gap: 0; }
.faq details {
  border-bottom: 1px solid var(--line-soft);
  padding: 4px 0;
}
.faq details:first-child { border-top: 1px solid var(--line-soft); }
.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 16px 36px 16px 0;
  position: relative;
  font-weight: 600;
  font-size: 1.0625rem;
  line-height: 1.4;
  min-height: var(--tap);
  display: flex;
  align-items: center;
}
.faq summary::-webkit-details-marker { display: none; }
/* The chevron. A rotated square border rather than a glyph, so it needs no
   font and cannot arrive as tofu. */
.faq summary::after {
  content: "";
  position: absolute; right: 8px; top: 50%;
  width: 9px; height: 9px;
  margin-top: -6px;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: rotate(45deg);
  transition: transform .18s ease;
}
.faq details[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
.faq summary:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.faq-answer { padding: 0 0 18px; margin: 0; color: var(--muted); line-height: 1.65; max-width: 70ch; }
.faq-answer p { margin: 0 0 .8em; }
.faq-answer p:last-child { margin-bottom: 0; }

/* ============================================================ final band -- */

/* Orange, with black on it. `--accent-ink` is black for this orange and is
   5.06:1 against it, which clears 4.5:1 — see ACCESSIBILITY.md. The button
   inside inverts: Charcoal fill, Stone text. */
.band-cta {
  background: var(--accent);
  color: var(--accent-ink);
  border-bottom: 0;
  text-align: center;
}
.band-cta .display { color: var(--accent-ink); }
.band-cta p {
  color: var(--accent-ink);
  opacity: .82;
  margin: 14px auto 0;
  max-width: 46ch;
  font-size: 1.0625rem;
  line-height: 1.55;
}
.band-cta .btn-invert {
  margin-top: 26px;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--panel);
  min-height: 50px;
  padding-inline: 28px;
  font-size: 1rem;
}
.band-cta .btn-invert:hover { background: var(--bg); border-color: var(--bg); }
.band-cta .btn-invert:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 3px;
}

/* ================================================= the founder placeholder -- */

/* The founder section. A rule down the left rather than a box: it is one
   paragraph of prose and a bordered panel would make it look like a
   callout somebody added, when it is the part of the page that is
   supposed to read as a person talking.

   The rule is the brand colour as a *border*, which is what D-123
   permits; the words take the ordinary text colour. */
.founder .eyebrow { margin-bottom: 12px; }
.founder-body {
  margin: clamp(18px, 2.5vw, 26px) 0 0;
  padding-left: clamp(16px, 2vw, 24px);
  border-left: 3px solid var(--accent);
  font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
  line-height: 1.65;
  color: var(--text);
  max-width: 62ch;
}

/* ================================================================ motion -- */

/* Visible by default. `js-reveal` is added to <html> by js/reveal.js only
   when it has decided to animate — so with the script blocked, failed or
   switched off, or with prefers-reduced-motion set, every section is simply
   on the page. Hiding in CSS and revealing in JS is how a marketing page
   ends up blank for the people with the worst connections. */
.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .5s ease, transform .5s ease;
}
.js-reveal [data-reveal="shown"] {
  opacity: 1;
  transform: none;
}

/* Belt to the script's braces. If the class is ever added by something that
   did not check the preference, this still refuses to move anything. */
@media (prefers-reduced-motion: reduce) {
  .js-reveal [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .faq summary::after { transition: none; }
}
