/* CommitPath AI marketing site. Light palette only: the logo's navy
   lettering is built for a light background. Values mirror the app's
   light-mode tokens so the two feel like one product.
   2026-10-22: --faint was the app's OLD faint (#8B93AC, 3.06:1 on white,
   the footer on every page); both now carry the app's AA values. */
:root {
  --ink: #F4F6F8;
  --panel: #FFFFFF;
  --line: #DCE1E8;
  --text: #031C50;
  --muted: #4A5578;
  --faint: #596580;
  --brand: #0459F4;
  --teal: #007265;
  --teal-soft: #E6F4F2;
  --radius: 12px;
  color-scheme: light;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font: 400 17px/1.6 "Inter", system-ui, -apple-system, sans-serif;
}
a { color: var(--brand); }
a:hover { text-decoration: none; }
h1, h2, h3 { font-family: "Space Grotesk", "Inter", sans-serif; line-height: 1.2; }

/* Headlines are title-cased at BUILD time, not here — see build.mjs and
   scripts/titleCase.js. This was briefly a text-transform: capitalize
   rule, which capitalises EVERY word including "by" and "the"; his call
   is conventional title case, where short joining words stay lowercase
   unless they open or close the headline, and CSS has no notion of a
   stop word. Doing it in the build also means the shipped HTML carries
   the real text, so it is what a crawler and a screen reader get. */

.wrap { max-width: 1080px; margin: 0 auto; padding: 0 24px; }

/* Header */
.site-header { background: var(--panel); border-bottom: 1px solid var(--line); }
.site-header .wrap { display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 104px; }
/* The header wordmark, set rather than drawn — see the comment in the
   markup for why the trademark could not live in the PNG. Sized to sit
   where the old image did: a 44px icon beside 30px text, which matches
   the proportions the raster logo had at 78px tall. */
.site-header img { height: 44px; width: auto; display: block; }
.site-header a.logo { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.site-header .logo-word {
  font-family: "Space Grotesk", sans-serif; font-weight: 700;
  font-size: 30px; letter-spacing: -0.5px; color: var(--text);
  white-space: nowrap;
}
.site-header .logo-ai { color: var(--brand); }
/* The trademark. It goes AFTER "AI", on trademark counsel's
   instruction of 9 October 2026: the mark as used is "CommitPath AI"
   and the symbol marks the whole of it. The markup used to put it
   after "CommitPath", on the argument that "AI" is descriptive and
   would be disclaimed in a filing — recorded here as OVERRULED rather
   than deleted, because it is a plausible enough argument to be
   re-invented by whoever reads this next. Pinned by
   trademarkPlacement.test.js in the app repository, which checks this
   one when the two are checked out side by side.
   Once per surface, on the header wordmark — repeating it down the
   page reads as the site defending itself rather than selling, and
   marking gains nothing legally beyond the claim itself. Sized in em
   so it tracks whatever it sits inside. */
.tm {
  font-size: 0.38em; vertical-align: super; font-weight: 600;
  letter-spacing: 0; margin-left: 0.02em;
}
.site-header nav { display: flex; align-items: center; gap: 22px; font-size: 15.5px; }
.site-header nav a { color: var(--muted); text-decoration: none; font-weight: 500; }
.site-header nav a:hover { color: var(--text); }
.btn {
  display: inline-block; background: var(--brand); color: #FFFFFF !important;
  text-decoration: none; font-weight: 600; border-radius: 8px; padding: 11px 20px;
}
.btn:hover { filter: brightness(1.08); }
.btn-quiet { background: transparent; color: var(--text) !important; border: 1px solid var(--line); }
.site-header .btn { padding: 8px 16px; }

/* Hero */
.hero { padding: 88px 0 72px; }
.eyebrow { color: var(--teal); font-weight: 600; font-size: 14.5px; letter-spacing: 0.4px; text-transform: uppercase; margin: 0 0 14px; }
.hero h1 { font-size: clamp(34px, 5.4vw, 56px); margin: 0 0 20px; max-width: 16ch; letter-spacing: -0.5px; }
.hero p.lede { font-size: clamp(18px, 2vw, 20px); color: var(--muted); max-width: 60ch; margin: 0 0 32px; }
.hero .actions { display: flex; gap: 12px; flex-wrap: wrap; }

/* Steps */
.section { padding: 64px 0; border-top: 1px solid var(--line); }
.section h2 { font-size: 28px; margin: 0 0 8px; }
.section .sub { color: var(--muted); margin: 0 0 36px; max-width: 62ch; }
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 28px 32px; list-style: none; padding: 0; margin: 0; counter-reset: step; }
.steps li { counter-increment: step; position: relative; padding-left: 46px; }
.steps li::before {
  content: counter(step); position: absolute; left: 0; top: 0;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--teal-soft); color: var(--teal); border: 1.5px solid #9FD3CC;
  font: 700 15px/27px "Space Grotesk", sans-serif; text-align: center;
}
.steps h3 { font-size: 18px; margin: 3px 0 6px; }
.steps p { margin: 0; color: var(--muted); font-size: 16px; }

.frameworks { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 28px; }
.frameworks span { border: 1px solid var(--line); background: var(--panel); border-radius: 999px; padding: 5px 14px; font-size: 15px; font-weight: 600; color: var(--muted); }

.cta { text-align: center; }
.cta p { color: var(--muted); margin: 0 auto 24px; max-width: 52ch; }

/* Legal pages */
.doc { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: clamp(24px, 5vw, 56px); margin: 40px auto 64px; max-width: 820px; }
.doc h1 { font-size: 34px; margin: 0 0 8px; }
.doc h2 { font-size: 22px; margin: 40px 0 10px; padding-top: 22px; border-top: 1px solid var(--line); }
.doc h3 { font-size: 18px; margin: 26px 0 6px; }
.doc p, .doc li { color: #1D2B52; }
.doc ul { padding-left: 22px; }
.doc li { margin: 6px 0; }
.doc hr { display: none; }
.doc table { border-collapse: collapse; width: 100%; font-size: 15.5px; display: block; overflow-x: auto; }
.doc th, .doc td { border: 1px solid var(--line); padding: 8px 10px; text-align: left; vertical-align: top; }
.doc code { background: var(--ink); border-radius: 4px; padding: 1px 5px; font-size: 0.92em; }

/* Footer */
.site-footer { border-top: 1px solid var(--line); background: var(--panel); padding: 28px 0; font-size: 15px; color: var(--faint); }
.site-footer .wrap { display: flex; justify-content: space-between; gap: 14px 24px; flex-wrap: wrap; }
.site-footer a { color: var(--muted); text-decoration: none; margin-right: 18px; }
.site-footer a:hover { color: var(--text); }

@media (max-width: 640px) {
  .site-header nav a.hide-sm { display: none; }
  .site-header img { height: 34px; }
  .site-header .logo-word { font-size: 22px; }
  .hero { padding: 56px 0 48px; }
}

/* Signup page */
.signup { padding: 56px 0 72px; }
.signup-grid { display: grid; grid-template-columns: 1fr 440px; gap: 56px; align-items: start; }
.signup-pitch h1 { font-size: clamp(30px, 4vw, 42px); margin: 0 0 16px; max-width: 14ch; letter-spacing: -0.5px; }
.signup-pitch .lede { font-size: 18.5px; color: var(--muted); max-width: 46ch; margin: 0 0 28px; }
.ticks { list-style: none; padding: 0; margin: 0; }
.ticks li { position: relative; padding-left: 30px; margin: 12px 0; color: var(--muted); font-size: 16.5px; }
.ticks li::before {
  content: "✓"; position: absolute; left: 0; top: -1px;
  color: var(--teal); font-weight: 700; font-size: 17px;
}
.signup-card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 28px; }
.field { margin-bottom: 18px; }
.field label { display: block; font-size: 15px; font-weight: 600; margin-bottom: 6px; }
.field input {
  width: 100%; border: 1px solid var(--line); border-radius: 8px; padding: 11px 13px;
  font: 400 16px/1.4 "Inter", system-ui, sans-serif; color: var(--text); background: #FFFFFF;
}
.field input:focus { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand); }
.field .hint { margin: 6px 0 0; font-size: 14px; color: var(--faint); }
.btn-full { width: 100%; border: none; cursor: pointer; font: 600 16.5px "Inter", system-ui, sans-serif; padding: 13px 20px; }
.form-error {
  margin: 0 0 16px; padding: 11px 13px; border-radius: 8px; font-size: 15.5px;
  background: #FDECEC; border: 1px solid #F3BDBD; color: #8A1C1C;
}
.finefine { margin: 14px 0 0; font-size: 13.8px; line-height: 1.55; color: var(--faint); }
.alt { margin: 18px 0 0; font-size: 15.5px; color: var(--muted); text-align: center; }

@media (max-width: 900px) {
  .signup-grid { grid-template-columns: 1fr; gap: 34px; }
  .signup-card { order: -1; }
  .signup-pitch h1 { max-width: none; }
}

/* Product screenshots */
.shotlead { padding: 0 0 8px; }
.shot { margin: 0; }
.shot img {
  display: block; width: 100%; height: auto; border-radius: 12px;
  border: 1px solid var(--line);
  /* The app is dark and the page is light, so the shots need a little lift
     off the background or they read as holes in the page. */
  box-shadow: 0 18px 50px rgba(3, 28, 80, 0.16), 0 3px 10px rgba(3, 28, 80, 0.08);
}
.shot figcaption { margin-top: 12px; font-size: 15.5px; color: var(--faint); text-align: center; }

.feature { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: 40px; align-items: center; margin: 52px 0; }
.feature.reverse .feature-text { order: 2; }
.feature h3 { font-size: 23px; margin: 0 0 12px; }
.feature p { color: var(--muted); margin: 0 0 12px; font-size: 16.5px; }
.feature p:last-child { margin-bottom: 0; }

/* Pricing */
.price-card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: clamp(22px, 4vw, 34px); max-width: 720px; }
.price-head { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; padding-bottom: 20px; border-bottom: 1px solid var(--line); margin-bottom: 20px; }
.price-amount { font-family: "Space Grotesk", sans-serif; font-size: 46px; font-weight: 700; line-height: 1; letter-spacing: -1px; }
.price-unit { color: var(--muted); font-size: 16px; margin-top: 6px; }

/* FAQ */
.faq { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: 30px 44px; }
.qa h3 { font-size: 17.5px; margin: 0 0 7px; }
.qa p { color: var(--muted); margin: 0; font-size: 16.5px; }

@media (max-width: 860px) {
  .feature { grid-template-columns: 1fr; gap: 22px; margin: 40px 0; }
  .feature.reverse .feature-text { order: 0; }
}

.contact-line { margin-top: 10px; }

/* Outcomes band — the part a visitor reads when they read nothing else. */
.outcomes-band { border-top: 1px solid var(--line); }
.outcomes { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 32px 38px; margin-top: 30px; }
.outcomes h3 { font-size: 19.5px; margin: 0 0 8px; letter-spacing: -0.2px; }
.outcomes p { margin: 0; color: var(--muted); font-size: 16.5px; }

/* ─────────────────────────────────────────────────────────────────────
   Visual polish. The page was structurally sound but flat: one flat
   background, one weight of rule, and screenshots floating unframed.
   Everything below adds depth and rhythm without adding decoration for
   its own sake — a buyer should feel the product is made with care, not
   notice the website trying.
   ───────────────────────────────────────────────────────────────────── */

/* A soft wash behind the hero instead of flat grey, and a faint grid so
   the space reads as designed rather than empty. */
.hero {
  position: relative;
  background:
    radial-gradient(1100px 520px at 12% -10%, rgba(4, 89, 244, 0.10), transparent 60%),
    radial-gradient(820px 420px at 88% 0%, rgba(0, 193, 173, 0.10), transparent 62%);
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, rgba(3, 28, 80, 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(3, 28, 80, 0.045) 1px, transparent 1px);
  background-size: 46px 46px;
  /* Fades out before it reaches the text, so it never fights the words. */
  -webkit-mask-image: radial-gradient(760px 420px at 20% 0%, #000 0%, transparent 78%);
  mask-image: radial-gradient(760px 420px at 20% 0%, #000 0%, transparent 78%);
  pointer-events: none;
}
.hero .wrap { position: relative; }

/* The eyebrow becomes a pill — a small, deliberate object rather than
   four floating words. */
.eyebrow {
  display: inline-block;
  background: var(--teal-soft);
  border: 1px solid #9FD3CC;
  border-radius: 999px;
  padding: 5px 13px;
  margin-bottom: 20px;
  text-transform: none;
  letter-spacing: 0.2px;
  font-size: 14px;
}

h1, h2 { letter-spacing: -0.8px; }
.hero h1 { max-width: 18ch; }

/* Buttons with a little more presence and a response to the cursor. */
.btn {
  box-shadow: 0 6px 18px rgba(4, 89, 244, 0.22);
  transition: transform 0.14s ease, box-shadow 0.14s ease, filter 0.14s ease;
}
.btn:hover { transform: translateY(-1px); box-shadow: 0 10px 24px rgba(4, 89, 244, 0.28); }
.btn-quiet { box-shadow: none; background: var(--panel); }
.btn-quiet:hover { box-shadow: 0 6px 16px rgba(3, 28, 80, 0.10); border-color: #C3CBD8; }

/* Section rhythm: alternate the page background with white panels so the
   eye has somewhere to rest between ideas. */
.section { position: relative; }
.outcomes-band, #inside, #faq { background: var(--panel); }
#pricing { background: linear-gradient(180deg, rgba(4,89,244,0.05), transparent 60%); }

/* Outcome cards, each led by a small accent bar. */
.outcomes > div {
  position: relative;
  padding-left: 16px;
}
.outcomes > div::before {
  content: "";
  position: absolute; left: 0; top: 4px; bottom: 4px;
  width: 3px; border-radius: 2px;
  background: linear-gradient(180deg, var(--brand), #00C1AD);
}

/* Screenshots get a browser frame. An unframed screenshot on a page reads
   as a picture; a framed one reads as software. */
.shot {
  border-radius: 14px;
  /* A light bezel, matching the light-mode screenshots inside it. A dark
     frame around a light screenshot reads as two different windows. */
  background: #E7ECF3;
  border: 1px solid #D3DBE6;
  padding: 34px 10px 10px;
  position: relative;
  box-shadow: 0 24px 60px rgba(3, 28, 80, 0.20), 0 4px 12px rgba(3, 28, 80, 0.10);
}
.shot::before {
  content: "";
  position: absolute; top: 13px; left: 16px;
  width: 9px; height: 9px; border-radius: 50%;
  background: #FF5F57;
  box-shadow: 16px 0 0 #FEBC2E, 32px 0 0 #28C840;
}
.shot img { border-radius: 8px; border: 1px solid #DDE3EC; box-shadow: none; }
.shot figcaption { margin-top: 14px; padding-bottom: 6px; color: var(--faint); }

/* Steps: stronger numbers, and a hairline that ties the row together. */
.steps li::before {
  background: linear-gradient(180deg, var(--brand), #0447C4);
  color: #FFFFFF;
  border: none;
  box-shadow: 0 4px 10px rgba(4, 89, 244, 0.28);
}

/* Pricing panel lifts off the page. */
.price-card {
  box-shadow: 0 20px 50px rgba(3, 28, 80, 0.12), 0 3px 10px rgba(3, 28, 80, 0.06);
  border-color: #CFD7E3;
}
.price-amount { background: linear-gradient(180deg, var(--text), #0A3FA8); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* Closing call to action, as an actual object on the page. */
.cta {
  background: linear-gradient(135deg, rgba(4,89,244,0.10), rgba(0,193,173,0.10));
  border-top: 1px solid var(--line);
}

@media (prefers-reduced-motion: reduce) {
  .btn, .btn:hover { transition: none; transform: none; }
}

/* ─────────────────────────────────────────────────────────────────────
   Layout rework.
   The page had three separate balance problems: a hero with an empty
   right half, feature rows whose splits and image sizes varied so the
   alternation looked accidental, and a pricing card hugging the left
   edge. Everything below is about balance and rhythm, not decoration.
   ───────────────────────────────────────────────────────────────────── */

.wrap { max-width: 1140px; }

/* ─────────────────────────────────────────────────────────────────────
   Page width.
   At 1800px the 1140px container left 330px of empty margin on each side
   — 37% of the screen — and squeezed the hero screenshot down to 689px
   from a 1600px source, so the product shot, which is the whole argument,
   rendered at 43% size and its text was unreadable.
   Prose is not affected: every text block here is already capped in `ch`
   (the lede at 46, section subs at 62, feature text at 74), so widening
   the container gives the screenshots room without stretching a single
   line of copy past a comfortable measure. That cap is why this is safe.
   ───────────────────────────────────────────────────────────────────── */
.wrap { max-width: 1340px; }
/* Side padding scales with the viewport. At 1280 the container now fills
   the screen, so a flat 24px left the content almost touching the edge on
   a laptop; at 390 anything larger eats a phone's usable width. */
.wrap { padding-inline: clamp(20px, 2.6vw, 40px); }

/* Hero: the words and the product, side by side. A visitor sees the
   software in the first screen instead of scrolling to find it. */
.hero { padding: 72px 0 84px; }
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: 56px;
  align-items: center;
}
.hero-copy h1 { font-size: clamp(34px, 3.9vw, 50px); max-width: 15ch; margin: 0 0 18px; }
.hero-copy .lede { font-size: 18.5px; max-width: 46ch; margin: 0 0 28px; }
.hero-note { margin: 18px 0 0; font-size: 15px; color: var(--faint); }
/* The shot runs slightly past the text column - it reads as a window into
   the product rather than a picture pasted beside the copy. */
.hero-shot { margin: 0; }
.hero-shot img { max-height: 460px; object-fit: cover; object-position: top left; }

/* Outcomes: cards on a tinted band, so four short statements read as four
   things rather than one paragraph in columns. */
.outcomes-band { background: linear-gradient(180deg, #EEF2F8, var(--ink)); }
.outcomes { grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr)); gap: 22px; }
.outcomes-band .sub { margin-bottom: 0; }
.outcomes > div {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px 22px 22px 26px;
  box-shadow: 0 2px 8px rgba(3, 28, 80, 0.05);
}
.outcomes > div::before { left: 14px; top: 22px; bottom: 22px; }

/* Steps: two by two rather than four across, which stops each one being a
   narrow column of broken lines. */
.steps { grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr)); gap: 30px 44px; }

/* Feature rows: one geometry for all of them. Equal columns, equal image
   treatment, alternating sides - the alternation now reads as a decision. */
.feature { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 52px; margin: 64px 0; }
.feature .shot { margin: 0; }
.feature .shot img { height: 330px; object-fit: cover; object-position: top left; }
.feature-text h3 { font-size: 25px; }

/* Pricing: centred, and wide enough to breathe. */
#pricing .wrap > h2, #pricing .wrap > .sub { text-align: center; }
#pricing .sub { margin-left: auto; margin-right: auto; }
.price-card { margin: 0 auto; max-width: 780px; }

/* FAQ reads better in two wider columns than three narrow ones. */
.faq { grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr)); gap: 32px 52px; }

@media (max-width: 900px) {
  .hero { padding: 48px 0 56px; }
  .hero-grid { grid-template-columns: 1fr; gap: 34px; }
  .hero-copy h1 { max-width: none; }
  /* Restated here because the rule above appears LATER in this file than
     the original 860px breakpoint, so it would otherwise win and leave
     feature rows in two columns on a phone. */
  .feature, .feature.reverse { grid-template-columns: 1fr; gap: 24px; margin: 44px 0; }
  .feature.reverse .feature-text { order: 0; }
  .hero-shot img, .feature .shot img { max-height: none; height: auto; object-fit: contain; }
}

/* Who it is for, in words rather than stock photographs of strangers.
   A rule in the brand gradient above each one instead of a picture: it
   gives the three columns a shared top edge to sit on, which is what the
   photographs were really doing, without pretending to show anybody. */
.roles { background: var(--panel); }
.roles-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 34px 44px;
  margin-top: 34px;
}
.role { padding-top: 22px; border-top: 2px solid transparent; border-image: linear-gradient(90deg, var(--brand), #00C1AD) 1; }
.role h3 { font-size: 20px; margin: 0 0 10px; letter-spacing: -0.2px; }
.role p { margin: 0; color: var(--muted); font-size: 16.2px; line-height: 1.6; }
/* Both of these are <p> too, so they are written as .role .x rather than
   .x — a bare class selector loses to `.role p` on specificity and the tag
   silently rendered muted grey instead of teal. Matching the descendant
   shape is the fix; !important would only have hidden the clash. */
.role .role-tag {
  margin: 0 0 10px; font-size: 13.5px; font-weight: 600; letter-spacing: 0.5px;
  text-transform: uppercase; color: var(--teal);
}
/* The concrete detail under each claim. Quieter than the claim, because it
   is evidence for it rather than a second claim. */
.role .role-proof {
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--line);
  font-size: 15px; color: var(--faint);
}

/* ─────────────────────────────────────────────────────────────────────
   The flywheel.
   The six benefits are a loop, not a list: time saved goes into finding
   deals, better conversations close them sooner, and the relationships
   built along the way bring the next one. Drawn as a ring on a wide
   screen, and as a numbered sequence on a narrow one - where a circle
   would be unreadable, and where the loop reads perfectly well as an
   ordered list.
   ───────────────────────────────────────────────────────────────────── */
.flywheel { position: relative; margin-top: 34px; }

/* Wide screens: a real ring with the six nodes around it. */
@media (min-width: 1000px) {
  .flywheel { height: 780px; display: flex; align-items: center; justify-content: center; }
  .flywheel-ring { position: absolute; width: 470px; height: 470px; }
  .flywheel-ring svg { width: 100%; height: 100%; display: block; }
  .flywheel-hub {
    position: absolute; inset: 0; margin: auto;
    width: 172px; height: 172px; border-radius: 50%;
    background: var(--panel); border: 1px solid var(--line);
    box-shadow: 0 10px 30px rgba(3, 28, 80, 0.10);
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    font-family: "Space Grotesk", sans-serif; line-height: 1.25; text-align: center;
  }
  .flywheel-hub span { font-size: 16px; color: var(--muted); }
  .flywheel-hub strong { font-size: 25px; color: var(--text); letter-spacing: -0.4px; }

  .flywheel-nodes { list-style: none; margin: 0; padding: 0; position: absolute; inset: 0; }
  /* Each node sits on a point around the ring, then anchors OUTWARD from
     it - a node centred on its point would lay its text across the ring. */
  .flywheel-nodes li {
    position: absolute; width: 292px; top: 50%; left: 50%;
    --r: 250px;
    transform: translate(-50%, -50%) rotate(var(--angle)) translate(var(--r)) rotate(calc(-1 * var(--angle)));
  }
  .flywheel-nodes .pos-right {
    transform: translate(-50%, -50%) rotate(var(--angle)) translate(var(--r)) rotate(calc(-1 * var(--angle))) translateX(50%);
  }
  .flywheel-nodes .pos-left {
    transform: translate(-50%, -50%) rotate(var(--angle)) translate(var(--r)) rotate(calc(-1 * var(--angle))) translateX(-50%);
  }
  .flywheel-nodes .pos-top {
    transform: translate(-50%, -50%) rotate(var(--angle)) translate(var(--r)) rotate(calc(-1 * var(--angle))) translateY(-50%);
  }
  .flywheel-nodes .pos-bottom {
    transform: translate(-50%, -50%) rotate(var(--angle)) translate(var(--r)) rotate(calc(-1 * var(--angle))) translateY(50%);
  }
  .flywheel-nodes .pos-right { text-align: left; }
  .flywheel-nodes .pos-left { text-align: right; }
  .flywheel-nodes .pos-top, .flywheel-nodes .pos-bottom { text-align: center; }
  .flywheel-nodes .pos-left .node-num { margin-left: auto; }
  .flywheel-nodes .pos-top .node-num, .flywheel-nodes .pos-bottom .node-num { margin-left: auto; margin-right: auto; }
}

/* Narrow screens: the same loop as a numbered sequence, with a line
   running through it so it still reads as one continuous thing. */
@media (max-width: 999px) {
  .flywheel-ring { display: none; }
  .flywheel-nodes { list-style: none; margin: 0; padding: 0 0 0 8px; position: relative; }
  .flywheel-nodes::before {
    content: ""; position: absolute; left: 25px; top: 18px; bottom: 18px; width: 2px;
    background: linear-gradient(180deg, #0459F4, #00C1AD); opacity: 0.35;
  }
  .flywheel-nodes li { position: relative; padding: 0 0 26px 62px; }
  .flywheel-nodes li:last-child { padding-bottom: 0; }
  .flywheel-nodes .node-num { position: absolute; left: 0; top: 0; }
}

.node-num {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%;
  background: linear-gradient(180deg, #0459F4, #0447C4); color: #FFFFFF;
  font: 700 16px/1 "Space Grotesk", sans-serif;
  box-shadow: 0 4px 12px rgba(4, 89, 244, 0.30);
  margin-bottom: 10px;
}
.flywheel-nodes h3 { font-size: 18.5px; margin: 0 0 6px; letter-spacing: -0.2px; }
.flywheel-nodes p { margin: 0; color: var(--muted); font-size: 15.8px; line-height: 1.55; }


/* A dark screenshot wants a dark bezel; a light one wants a light bezel.
   A mismatched frame just looks like a mistake.

   All four screenshots are dark now, so every .shot on the page also
   carries .shot-dark. The class is kept rather than folded into .shot
   because the app genuinely has both themes, and a light capture would
   otherwise need this rule written again from scratch. If a light shot is
   ever added, leave .shot-dark off that one and it will get the light
   bezel above. */
.shot-dark { background: #11161F; border-color: rgba(3, 28, 80, 0.18); }
.shot-dark img { border-color: #232B38; }

/* ─────────────────────────────────────────────────────────────────────
   Pricing.
   A narrow card with a number in it left most of the page empty and never
   said what the money buys. Two panels now: the price and the commitment
   on the left, everything included on the right - which is the question a
   buyer is actually asking at this point on the page.
   ───────────────────────────────────────────────────────────────────── */
/* No card, no navy panel. The price sits on the page like the rest of the
   content - a box around it made it look like an advert dropped into the
   middle of the page rather than part of it. */
.plan {
  display: grid; grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  gap: 56px; align-items: start; margin-top: 36px;
}
.plan-price { padding-right: 20px; border-right: 1px solid var(--line); }
.plan-tag {
  display: inline-block; font-size: 13.5px; letter-spacing: 0.5px; text-transform: uppercase;
  color: var(--teal); background: var(--teal-soft); border: 1px solid #9FD3CC; border-radius: 999px;
  padding: 4px 12px; margin-bottom: 20px;
}
.plan-amount {
  font-family: "Space Grotesk", sans-serif; font-weight: 700; font-size: 78px; line-height: 1;
  letter-spacing: -2.5px; display: flex; align-items: flex-start; gap: 2px;
  background: linear-gradient(180deg, var(--text), #0A3FA8);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.plan-currency { font-size: 36px; line-height: 1.25; }
.plan-unit { margin: 10px 0 0; color: var(--muted); font-size: 17px; }
.plan-min { margin: 18px 0 24px; color: var(--muted); font-size: 16px; line-height: 1.6; }
.plan-min strong { color: var(--text); }
.plan-note { margin: 12px 0 0; font-size: 15px; color: var(--faint); }

.plan-includes h3 { font-size: 19px; margin: 0 0 16px; }
.ticks-two { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); gap: 2px 30px; }
.ticks-two li { font-size: 15.8px; margin: 9px 0; }
.plan-small { margin: 24px 0 0; padding-top: 18px; border-top: 1px solid var(--line); font-size: 15px; color: var(--faint); line-height: 1.6; }

@media (max-width: 860px) {
  .plan { grid-template-columns: 1fr; gap: 32px; }
  .plan-price { padding-right: 0; border-right: none; border-bottom: 1px solid var(--line); padding-bottom: 28px; }
}

/* ─────────────────────────────────────────────────────────────────────
   Bigger screenshots.
   Side by side with a paragraph, each screenshot rendered about 500px
   wide and was cropped to a fixed height - too small to read the words
   inside, which is the only reason to show a screenshot at all. The text
   now sits above its screenshot and the image runs the full width of the
   page, roughly twice the size, uncropped.
   ───────────────────────────────────────────────────────────────────── */
@media (min-width: 901px) {
  .feature, .feature.reverse { grid-template-columns: 1fr; gap: 22px; margin: 70px 0; }
  .feature.reverse .feature-text { order: 0; }
  .feature-text { max-width: 74ch; }
  .feature .shot img { height: auto; max-height: none; object-fit: contain; }

  /* The hero screenshot can be taller now that nothing sits beside it. */
  .hero-shot img { max-height: 540px; }
}

/* The hero screenshot is the first thing anyone sees, so it should be
   legible too: a larger share of the row, and allowed to run toward the
   right edge of the viewport on wide screens rather than stopping at the
   text column's margin. */
@media (min-width: 1000px) {
  .hero-grid { grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr); gap: 44px; }
  /* 1340px must match .wrap's max-width: this pulls the shot into the
     gutter, so a stale number here either does nothing or overhangs. */
  .hero-shot { margin-right: calc(-1 * min(72px, max(0px, (100vw - 1340px) / 2))); }
  .hero-shot img { max-height: 600px; }
}

/* The closing line of the method section. A .sub that sits AFTER the list
   rather than before it, so it needs the top margin the leading one gets
   at the bottom — and a hairline above it, because it is a different kind
   of statement from the three questions: provenance, not mechanism. */
#method .method-note {
  margin: 34px 0 0;
  padding-top: 22px;
  border-top: 1px solid var(--line);
  max-width: 68ch;
}

/* ─────────────────────────────────────────────────────────────────────
   Column counts that depend on the container width.
   These two grids use auto-fit, so their column count is a consequence of
   how wide .wrap happens to be — widening the page silently changed both.
   Pinned here, at the end of the file so they actually win, rather than
   left to depend on a number that just moved.

   .steps was already wrong before the width changed: four items in a grid
   that fitted three meant three across and a single orphan beneath, which
   is not the "two by two" its own comment describes. 420px is chosen so
   three cannot fit at either the old or the new width.

   .faq was right, but only by accident of the narrow container — at the
   new width it would have become the three narrow columns its comment
   explicitly rejects.
   ───────────────────────────────────────────────────────────────────── */
.steps { grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr)); }
.faq { grid-template-columns: repeat(auto-fit, minmax(min(430px, 100%), 1fr)); }

/* ── While the product screenshots are down ─────────────────────────
   Both of these layouts are two-column grids built around an image,
   and with the images gone their second column is empty: at 1280px the
   hero copy sat in 456px with 713px of nothing beside it.

   Kept as an override at the end of the file rather than edited in
   place, so reverting the commit that removed the screenshots restores
   the original layout by deleting this block — nothing to merge by
   hand, and no chance of the pictures coming back to a layout that no
   longer expects them.
   ------------------------------------------------------------------ */
.hero-grid { grid-template-columns: 1fr; }
.feature { grid-template-columns: 1fr; }
/* Full-bleed body text is unreadable; this is roughly the measure the
   rest of the page already uses for prose. */
.hero-copy, .feature-text { max-width: 720px; }
