/* ============================================================
   Expand Quickly landing pages: shared structure and components.
   Consumes brand tokens from tokens.css. No token values are
   defined in this file; if a colour or font is needed, it comes
   from a custom property. Used by /sales/, /admin/, /accounting/ and /seo/.
   ============================================================ */

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font-body);
  color: var(--espresso);
  background: var(--cream);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img, video { max-width: 100%; display: block; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(2.3rem, 5.2vw, 3.9rem); }
h2 { font-size: clamp(1.9rem, 3.6vw, 2.9rem); }
h3 { font-size: 1.35rem; }

p { max-width: 62ch; }

.container {
  width: min(var(--container), 92vw);
  margin: 0 auto;
}

.eyebrow {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--terracotta);
  margin-bottom: 1rem;
}
.eyebrow-light { color: var(--sage); }

.lede {
  font-size: 1.13rem;
  color: var(--espresso-soft);
  margin-top: 1.3rem;
}

em { font-style: normal; color: var(--terracotta); }

section { padding: 4.5rem 0; }
@media (min-width: 940px) { section { padding: 6rem 0; } }

/* ---------- buttons ---------- */
.btn {
  display: inline-block;
  background: var(--maroon);
  color: var(--cream);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1rem;
  padding: 0.95rem 2rem;
  border: 0;
  border-radius: 10px;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.2s ease;
}
.btn:hover { background: var(--terracotta-dark); }
.btn-block { display: block; width: 100%; text-align: center; }

/* ---------- focus visibility ---------- */
a:focus-visible,
button:focus-visible,
input:focus-visible,
video:focus-visible,
summary:focus-visible {
  outline: 3px solid var(--terracotta);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- header and footer ---------- */
.l-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem 4vw;
  border-bottom: 1px solid var(--linen);
  background: var(--cream);
}
.l-header .brand-logo { height: 44px; width: auto; }
.l-header .btn { padding: 0.6rem 1.2rem; font-size: 0.88rem; }
/* This was hidden entirely under 600px while the CTA read "I want a
   salesperson on my pipeline", which wrapped to three lines at 375px and
   swallowed the header. The shorter CTA fits, so the button is back, but it
   needs tightening on the narrowest screens to stay on one line beside the
   logo. If the CTA is ever lengthened again, check the header at 375px
   before shipping it. */
@media (max-width: 430px) {
  .l-header .btn { padding: 0.5rem 0.8rem; font-size: 0.76rem; white-space: nowrap; }
  /* The wordmark is 262x64, so at 44px tall it takes 180px of a 375px
     screen and leaves the button too little to sit on one line. Dropping it
     to 34px frees about 40px, which is the difference between one line and
     two, and the logo is still comfortably legible. */
  .l-header .brand-logo { height: 34px; }
}

.l-footer {
  background: var(--espresso);
  color: rgba(253, 251, 247, 0.72);
  font-size: 0.88rem;
  padding: 2rem 4vw;
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem 2rem;
  justify-content: space-between;
}
.l-footer a { color: rgba(253, 251, 247, 0.85); text-decoration: none; }
.l-footer a:hover { color: var(--cream); }

/* ---------- hero ---------- */
.hero { padding-top: 3rem; }
.hero .terms-line {
  margin-top: 1.1rem;
  font-size: 0.88rem;
  color: var(--espresso-soft);
}
.hero .btn { margin-top: 1.6rem; }

/* ---------- video slot ---------- */
.vsl-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  width: 100%;
  border: 0;
  background: rgba(35, 27, 24, 0.35);
  color: var(--cream);
  cursor: pointer;
}
.vsl-overlay .play-ring {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  border: 2px solid var(--cream);
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(253, 251, 247, 0.12);
}
.vsl-overlay .play-ring::after {
  content: "";
  border-left: 16px solid var(--cream);
  border-top: 10px solid transparent;
  border-bottom: 10px solid transparent;
  margin-left: 4px;
}

/* ---------- section furniture is centred on every landing page ----------
   Owner direction 2026-08-14: the pages all sat hard left and he wants them
   centred. Applied here rather than per page so /sales/, /admin/,
   /accounting/ and /seo/ cannot drift apart.

   Only the furniture centres: the eyebrow, the section heading, and an
   intro paragraph that is a direct child of the container. Everything
   inside a card, a list, a step or the form stays left aligned on purpose,
   because centred body copy gives the eye no stable left edge to return to
   and long passages become harder to read.

   The hero is excluded: it is a two column grid with the video beside it,
   and centring the copy column would break the alignment that grid exists
   to create.

   text-align alone is NOT enough here and that caught us out once already.
   The base paragraph and heading rules cap these elements at a readable
   measure, so an eyebrow is a 430px box sitting hard against the left
   gutter. Centring the text inside that box leaves the box where it was and
   the heading still reads as left aligned. The margin-inline: auto is what
   actually moves it. Any element added to this list needs both. */
section:not(.hero) > .container > .eyebrow,
section:not(.hero) > .container > h2,
section:not(.hero) > .container > .lede,
section:not(.hero) > .container > .split-close {
  text-align: center;
  margin-inline: auto;
}
section:not(.hero) > .container > .lede {
  max-width: 64ch;
}

/* ---------- pricing section, centred ----------
   The panel keeps its own left aligned contents: a centred list of
   inclusions is hard to scan, and the price itself needs a stable left
   edge to sit against. Only the section furniture around it centres. */
.pricing-centred { text-align: center; }
.pricing-centred > .lede {
  margin-left: auto; margin-right: auto; max-width: 62ch;
}
.pricing-centred .price-panel { text-align: left; }

/* ---------- proof strip ----------
   Four hard figures directly under the fold. Sits on linen so it reads as a
   band rather than another content section, and stays a single row on
   desktop so the four numbers are compared at a glance rather than scrolled
   through. Two columns on a phone, never one: a single column turns the
   strip into a list and it stops reading as evidence. */
.proof { background: var(--linen); padding: 2.6rem 0; }
.proof-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.8rem 1.2rem;
}
@media (min-width: 820px) {
  .proof-grid { grid-template-columns: repeat(3, 1fr); gap: 2.5rem; }
}
/* Three figures in a two column grid leaves the last one orphaned beside a
   gap on a phone. Spanning it closes the block off so the strip reads as a
   finished set rather than a row that ran out. */
@media (max-width: 819px) {
  .proof-item:last-child { grid-column: 1 / -1; }
}
.proof-item { display: flex; flex-direction: column; gap: 0.35rem; }
.proof-num {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 3.4vw, 2.3rem);
  line-height: 1;
  color: var(--maroon);
}
.proof-lbl {
  font-size: 0.84rem;
  line-height: 1.4;
  color: var(--espresso-soft);
}

/* ---------- steps ---------- */
.steps-grid {
  display: grid;
  gap: 1.5rem;
  margin-top: 2.5rem;
}
@media (min-width: 760px) { .steps-grid { grid-template-columns: repeat(3, 1fr); } }
.step {
  background: #fff;
  border: 1px solid var(--linen);
  border-radius: var(--radius);
  padding: 1.6rem;
}
.step .week {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--terracotta);
  margin-bottom: 0.7rem;
}
.step h3 { margin-bottom: 0.6rem; }
.step p { font-size: 0.95rem; color: var(--espresso-soft); }

/* ---------- dark band (objection) ---------- */
.band-dark {
  background: var(--olive);
  color: var(--cream);
}
.band-dark .lede { color: rgba(253, 251, 247, 0.85); }
.band-dark h2 { color: var(--cream); }

/* ---------- card grids ---------- */
.cards-3 {
  display: grid;
  gap: 1.2rem;
  margin-top: 2.5rem;
}
@media (min-width: 760px) { .cards-3 { grid-template-columns: repeat(3, 1fr); } }
.card {
  background: #fff;
  border: 1px solid var(--linen);
  border-radius: var(--radius);
  padding: 1.5rem;
}
.band-dark .card {
  background: rgba(253, 251, 247, 0.07);
  border-color: rgba(253, 251, 247, 0.16);
}
.card h3 { font-size: 1.08rem; margin-bottom: 0.5rem; }
.card p { font-size: 0.92rem; color: var(--espresso-soft); }
.band-dark .card p { color: rgba(253, 251, 247, 0.78); }

/* ---------- price ---------- */
.price-panel {
  background: #fff;
  border: 1px solid var(--linen);
  border-radius: var(--radius);
  padding: 2.2rem;
  box-shadow: var(--shadow);
  max-width: 640px;
  /* Centred at owner request 2026-08-14: left aligned, the panel sat with a
     wide dead column to its right and the section read unbalanced against
     the full width grids around it. */
  margin-inline: auto;
}
.promo-badge {
  display: inline-block;
  background: var(--maroon);
  color: var(--cream);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.35rem 0.9rem;
  border-radius: 999px;
  margin-bottom: 1.2rem;
}
.price-now {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.2rem, 5vw, 3.2rem);
  color: var(--maroon);
}
.price-now small { font-size: 0.45em; font-weight: 400; color: var(--espresso-soft); }
.price-was {
  font-size: 1rem;
  color: var(--espresso-soft);
  margin-top: 0.3rem;
}
.price-was s { text-decoration-color: var(--terracotta); text-decoration-thickness: 2px; }
.inclusions {
  list-style: none;
  margin-top: 1.6rem;
}
.inclusions li {
  padding: 0.5rem 0 0.5rem 1.7rem;
  position: relative;
  font-size: 0.95rem;
  border-bottom: 1px solid var(--linen);
}
.inclusions li:last-child { border-bottom: 0; }
.inclusions li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.95rem;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--terracotta);
}

/* ---------- form ---------- */
.form-panel {
  background: #fff;
  border: 1px solid var(--linen);
  border-radius: var(--radius);
  padding: 2rem;
  box-shadow: var(--shadow);
  max-width: 520px;
}
.form-field { margin-bottom: 1.2rem; }
.form-field label {
  display: block;
  font-weight: 600;
  font-size: 0.92rem;
  margin-bottom: 0.35rem;
}
.form-field input {
  width: 100%;
  font: inherit;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--linen);
  border-radius: 8px;
  background: var(--cream);
  color: var(--espresso);
}
.field-error {
  display: none;
  font-size: 0.83rem;
  color: var(--maroon);
  margin-top: 0.35rem;
}
.form-field.invalid input { border-color: var(--maroon); }
.form-field.invalid .field-error { display: block; }
.form-note {
  margin-top: 0.9rem;
  font-size: 0.83rem;
  color: var(--espresso-soft);
}
.form-status { margin-top: 1rem; font-size: 0.92rem; }
.form-status.error { color: var(--maroon); }
.form-success {
  padding: 1.5rem 0;
}
.form-success h3 { margin-bottom: 0.6rem; }
/* The global reset strips paragraph margins, so the success message needs its
   own spacing or the two lines collide. */
.form-success p + p { margin-top: 0.7rem; }

/* ---------- tinted band, used for how it works and pricing ---------- */
.how {
  background: var(--linen);
  border-top: 1px solid rgba(35, 27, 24, 0.06);
  border-bottom: 1px solid rgba(35, 27, 24, 0.06);
}

/* ---------- risk reversal band ---------- */
.risk {
  background: var(--maroon);
  color: var(--cream);
  text-align: center;
}
.risk h2, .risk h3 { color: var(--cream); }
/* Named-guarantee paragraph under the risk band heading. Constrained and
   centred so it reads as a statement rather than a block of body copy on
   the maroon. */
.risk-lede {
  max-width: 60ch;
  margin: 1rem auto 0;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--cream);
  opacity: 0.92;
}
.risk-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.6rem;
  margin-top: 2.2rem;
}
@media (min-width: 760px) { .risk-grid { grid-template-columns: repeat(3, 1fr); gap: 2rem; } }
.risk-grid .r h3 {
  font-family: var(--font-display);
  font-size: 1.35rem;
  margin-bottom: 0.4rem;
}
.risk-grid .r p {
  font-size: 0.93rem;
  opacity: 0.88;
  max-width: 28ch;
  margin-inline: auto;
}

/* ---------- final call to action band ---------- */
.final {
  background: var(--espresso);
  color: var(--cream);
  text-align: center;
}
.final h2 { color: var(--cream); max-width: 20ch; margin-inline: auto; }
.final > .container > p {
  max-width: 56ch;
  margin-inline: auto;
  opacity: 0.9;
  font-size: 1.05rem;
  margin-top: 1rem;
}
.final .form-panel {
  background: rgba(253, 251, 247, 0.06);
  border-color: rgba(253, 251, 247, 0.16);
}
.final .form-panel label { color: var(--cream); }
.final .form-panel input {
  background: rgba(253, 251, 247, 0.94);
  border-color: rgba(253, 251, 247, 0.2);
}
.final .form-note { color: rgba(253, 251, 247, 0.7); }

/* The invalid state has to beat the dark-surface input rule above, which
   shares its specificity and would otherwise win on source order and leave
   a failed field looking untouched. Declared last and scoped to the panel
   so the maroon error border shows on light and dark surfaces alike. */
.form-field.invalid input,
.final .form-panel .form-field.invalid input {
  border-color: var(--maroon);
  border-width: 2px;
}

/* ---------- hero: copy left, portrait player right ----------
   Stacked, the 9:16 player pushed itself most of a screen below the fold and
   left a wide empty column beside the headline. Worse, its wrapper centred it
   while the copy was left aligned, so the copy, the player and the section
   each sat on a different axis and the hero read as unaligned.

   Side by side fixes both at once: the player occupies space that was already
   empty, it comes back above the fold, and the hero has one alignment instead
   of three.

   The breakpoint is 900px rather than the usual one because that is the point
   where a 380px player and a readable line length stop fitting together.
   Below it the two stack, which is already the right answer on a phone. */
.hero-video { margin-top: 2.8rem; }

@media (min-width: 900px) {
  .hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 380px;
    gap: 4rem;
    align-items: center;
  }
  .hero-copy { max-width: 640px; }
  .hero-video { margin-top: 0; }
}

/* ---------- 9:16 video block (founder video, hero position) ----------
   Portrait, not landscape. The founder video was shot vertical, and this
   page is built for paid traffic arriving from Meta on a phone, so the
   player matches the footage instead of cropping it into a letterbox.
   object-fit: cover on a 16:9 frame would have cut the shot down to a
   band across the middle and taken his head off.

   Width is capped so the player does not tower over the copy on a desktop
   screen: at 380px the frame is about 676px tall, which still sits inside
   a laptop viewport. If a landscape video is ever added to another page,
   add a separate class rather than widening this one. */
.vsl-tall {
  position: relative;
  aspect-ratio: 9 / 16;
  width: 100%;
  max-width: 380px;
  margin-inline: auto;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--espresso);
  box-shadow: var(--shadow);
}
.vsl-tall video { width: 100%; height: 100%; object-fit: cover; }
.vsl-tall .vsl-overlay { flex-direction: column; }
.vsl-tall.playing .vsl-overlay { display: none; }
.vsl-runtime {
  position: absolute; bottom: 12px; right: 14px;
  font-size: 0.75rem; color: var(--cream);
  background: rgba(35, 27, 24, 0.6);
  padding: 4px 9px; border-radius: 4px;
}

/* ---------- two column self identification ---------- */
.split-2 {
  display: grid; gap: 1.2rem; margin-top: 2.2rem;
}
@media (min-width: 800px) { .split-2 { grid-template-columns: 1fr 1fr; gap: 1.6rem; } }
.split-2 .col {
  background: #fff; border: 1px solid var(--linen);
  border-radius: var(--radius); padding: 1.8rem;
}
.split-2 .col .tag {
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--terracotta); margin-bottom: 0.7rem;
}
.split-2 .col h3 { font-size: 1.25rem; margin-bottom: 0.6rem; }
.split-2 .col p { font-size: 0.95rem; color: var(--espresso-soft); }
/* Closing line under a section. Centred and constrained so it reads as a
   conclusion drawn from the block above rather than as another paragraph
   of it. Both instances on /sales/ do the same job. */
.split-close {
  margin: 1.6rem auto 0; font-family: var(--font-display);
  font-size: clamp(1.15rem, 2.2vw, 1.5rem); color: var(--maroon);
  text-align: center; max-width: 46ch;
}

/* ---------- the difference: photo led feature ---------- */
.feature-grid { display: grid; gap: 2rem; align-items: center; }
@media (min-width: 940px) { .feature-grid { grid-template-columns: 1fr 1fr; gap: 3.5rem; } }
.feature-photo {
  border-radius: var(--radius); overflow: hidden;
  /* 3 / 2 matches the team photograph exactly. It was 4 / 3 for the
     placeholder; keeping that would have object-fit-cropped 5% off each
     side and clipped the people standing at the edges of the frame. */
  background: var(--linen); aspect-ratio: 3 / 2;
  display: flex; align-items: center; justify-content: center;
}
.feature-photo img { width: 100%; height: 100%; object-fit: cover; }
.feature-points { list-style: none; margin-top: 1.5rem; }
.feature-points li {
  padding: 0.65rem 0 0.65rem 1.8rem; position: relative;
  border-bottom: 1px solid var(--linen); font-size: 0.98rem;
}
.feature-points li:last-child { border-bottom: 0; }
.feature-points li::before {
  content: ""; position: absolute; left: 0; top: 1.15rem;
  width: 9px; height: 9px; border-radius: 50%; background: var(--terracotta);
}

/* ---------- faq ---------- */
/* The 820px cap keeps the questions at a readable measure, but without the
   auto margins the whole block sat against the left gutter with a 380px gap
   on its right, under a centred heading. The question text itself stays
   left aligned: each row is a flex pair with the plus sign pushed to the
   far edge, so centring the text would leave it floating away from its own
   control. */
.faq-list { margin: 2.2rem auto 0; max-width: 820px; }
.faq-list details { border-bottom: 1px solid var(--linen); }
.faq-list summary {
  cursor: pointer; padding: 1.15rem 0; font-weight: 600; font-size: 1rem;
  list-style: none; display: flex; justify-content: space-between;
  align-items: center; gap: 1.2rem;
}
.faq-list summary::-webkit-details-marker { display: none; }
.faq-list summary::after {
  content: "+"; font-family: var(--font-display);
  font-size: 1.4rem; color: var(--maroon); flex-shrink: 0;
}
.faq-list details[open] summary::after { content: "\00d7"; }
.faq-list details p {
  padding: 0 0 1.3rem; max-width: 68ch;
  font-size: 0.95rem; color: var(--espresso-soft);
}

/* ---------- disqualifier ---------- */
.disqualifier {
  margin-top: 1.6rem; font-size: 0.95rem;
  opacity: 0.85; max-width: 52ch; margin-inline: auto;
}

/* ---------- sticky mobile CTA ---------- */
.sticky-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  background: rgba(253, 251, 247, 0.97);
  border-top: 1px solid var(--linen);
  padding: 0.7rem 4vw;
  transform: translateY(110%);
  transition: transform 0.25s ease;
}
.sticky-cta.visible { transform: none; }
.sticky-cta .btn { width: 100%; text-align: center; padding: 0.85rem 1rem; }
@media (min-width: 800px) { .sticky-cta { display: none; } }

/* ---------- reveals ---------- */
.rv {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.rv.in { opacity: 1; transform: none; }

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .rv {
    opacity: 1;
    transform: none;
    transition: none;
  }
  /* The sticky bar slides up on a transform. Show and hide it instantly
     instead, rather than removing the transition and leaving it stuck
     off-screen at translateY(110%). */
  .sticky-cta { transition: none; }
}

/* ---------- touch target sizing ----------
   Measured at 375px on 15 August 2026: the header button came out 36px tall
   and the footer links 16px, against the 44px that iOS and Android both
   recommend and well under what a thumb actually hits reliably. Nothing was
   broken, but a mis-tap on a landing page whose only exit is the call to
   action costs a visitor.

   Padding rather than height, so the text stays where it is and only the
   hit area grows. Applied on coarse pointers only: on a mouse these would
   just be loose. */
@media (pointer: coarse) {
  .l-header .btn { min-height: 44px; display: inline-flex; align-items: center; }
  .l-footer a { display: inline-block; padding: 0.7rem 0.2rem; }
}
