/* ------------------------------------------------------------------
   /features — lifecycle layout

   Self-contained. The button and section classes on the home page live
   in home-live.css, which this page does not load, so everything the
   page needs is redefined here under an `fx-` prefix rather than being
   borrowed from a stylesheet that is not on the page.

   Brand variables (--primary, --green, --bg) come from styles.css,
   which root.tsx loads globally.
   ------------------------------------------------------------------ */

/* ---------- Hero ---------- */

/* Header clearance is NOT this page's job. PageWrapper renders
   `.content-sections`, which already carries `padding-top: 90px` to sit clear
   of the fixed header. Adding a second allowance here stacks on top of it and
   leaves this page with visibly more air above the headline than every other
   page on the site. These values match `.feature-page-hero`, the shared hero
   every other feature page uses — including its -4px, which closes a hairline
   between the white header band and the beige. */
.fx-hero {
  background: var(--bg);
  padding: 56px 0 70px;
  margin-top: -4px;
  color: var(--primary);
}

.fx-hero-inner {
  max-width: 860px;
  text-align: center;
}

.fx-hero h1 {
  /* Size, leading and tracking come from the shared page-title rule in
     styles.css — this hero is where that scale came from. */
  color: var(--primary);
  margin-bottom: 24px;
}

.fx-hero-sub {
  font-size: 1.2rem;
  line-height: 1.65;
  color: rgba(47, 72, 80, 0.82);
  max-width: 680px;
  margin: 0 auto;
}

.fx-hero-actions {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 34px;
}

.fx-btn {
  display: inline-block;
  padding: 15px 36px;
  border-radius: 10px;
  font-weight: 600;
  font-size: 1.05rem;
  text-decoration: none;
  transition: transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
}

.fx-btn-primary {
  background: var(--green);
  color: white;
}

.fx-btn-primary:hover {
  background: #8fa557;
  transform: translateY(-2px);
  box-shadow: 0 10px 20px rgba(162, 185, 100, 0.3);
}

.fx-btn-ghost {
  background: transparent;
  color: var(--primary);
  border: 2px solid rgba(47, 72, 80, 0.25);
}

.fx-btn-ghost:hover {
  border-color: var(--primary);
  transform: translateY(-2px);
}

.fx-hero-note {
  margin-top: 26px;
  font-size: 0.95rem;
  color: rgba(47, 72, 80, 0.6);
}

.fx-inline-link {
  color: var(--primary);
  text-decoration: underline;
  text-underline-offset: 3px;
  font-weight: 600;
}

.fx-inline-link:hover {
  color: #1d3138;
}

/* ---------- Sticky stage nav ---------- */

.fx-stagenav {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(47, 72, 80, 0.1);
}

.fx-stagenav-inner {
  display: flex;
  gap: 4px;
  /* A single centred row while all eight links fit (they need ~940px).
     Below the breakpoint this wraps instead — see the media query.
     If a band is ever added or renamed, re-measure: the breakpoint must stay
     above the row's intrinsic width or the centred row overflows, and a
     centred overflowing flex row cannot be scrolled back to its first item. */
  justify-content: center;
  scrollbar-width: none;
  padding-top: 10px;
  padding-bottom: 10px;
}

.fx-stagenav-inner::-webkit-scrollbar {
  display: none;
}

.fx-stagenav-link {
  flex: 0 0 auto;
  padding: 8px 14px;
  border-radius: 999px;
  font-size: 0.9rem;
  font-weight: 600;
  /* Full-strength brand colour and a standing underline: these read as links
     at rest, not as inert labels that only reveal themselves on hover. */
  color: var(--primary);
  text-decoration: underline;
  text-decoration-color: rgba(47, 72, 80, 0.35);
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  white-space: nowrap;
  transition: background 0.2s ease, color 0.2s ease, text-decoration-color 0.2s ease;
}

.fx-stagenav-link:hover {
  background: rgba(47, 72, 80, 0.07);
  text-decoration-color: var(--primary);
}

.fx-stagenav-link:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
}

/* ---------- Lifecycle stages ---------- */

.fx-stages {
  background: white;
  padding: 80px 0 40px;
  color: var(--primary);
}

.fx-stage {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: 60px;
  align-items: center;
  padding: 60px 0;
  border-top: 1px solid rgba(47, 72, 80, 0.1);
  /* Clear the sticky nav when jumped to from the stage nav. */
  scroll-margin-top: 80px;
}

.fx-stage:first-child {
  border-top: none;
  padding-top: 0;
}

/* The testimonial splits the bands into two sections. The second one picks up
   where the first left off, so it gets no leading padding of its own.
   Doubled-up class selector on purpose: the responsive blocks re-declare
   `.fx-stages` with a `padding` shorthand, and at equal specificity those come
   later in the file and would quietly win. */
.fx-stages.fx-stages-continued {
  padding-top: 0;
}

/* Spacing around the testimonial that breaks the bands.
   Three separate things used to stack above the card — the band's 60px bottom
   padding, the section's 40px, and the card's own 40px margin — while only the
   card's margin sat below it. That gave 140px above and 40px below, so the
   quote floated up near the band it had just interrupted.
   Everything above is zeroed here and the card owns the gap on both sides, so
   the two numbers below are the whole story. */
.fx-stages.fx-stages-lead,
.fx-stages-lead .fx-stage:last-child {
  padding-bottom: 0;
}

.fx-stages + .sodium-testimonial,
.fx-index + .sodium-testimonial {
  margin-top: 72px;
  margin-bottom: 72px;
}

/* Alternate the screenshot side so the page does not read as a column of
   identical rows. Grid order, not flex-direction, so the DOM order stays
   text-then-image for screen readers and for the mobile stack. */
.fx-stage-reversed .fx-stage-text {
  order: 2;
}

.fx-stage-reversed .fx-stage-shot {
  order: 1;
}

.fx-stage-title {
  font-size: clamp(1.7rem, 3vw, 2.4rem);
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin-bottom: 18px;
  color: var(--primary);
}

.fx-stage-lede {
  font-size: 1.1rem;
  line-height: 1.7;
  color: rgba(47, 72, 80, 0.8);
  margin-bottom: 26px;
}

/* ---------- Feature chips ---------- */

.fx-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  padding: 0;
  margin: 0;
}

.fx-chip {
  display: inline-block;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid rgba(47, 72, 80, 0.18);
  font-size: 0.9rem;
  font-weight: 500;
  color: rgba(47, 72, 80, 0.85);
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.fx-chip:hover {
  background: var(--primary);
  border-color: var(--primary);
  color: white;
}

/* ---------- Screenshots ----------
   No forced aspect ratio: the library holds everything from a 7.9:1 strip
   to a 1.2:1 panel, and cover-cropping to a single frame would slice the
   wide ones in half. Natural height, capped, so a tall shot cannot run
   away with the row. */

.fx-stage-shot {
  border-radius: 14px;
  overflow: hidden;
  background: white;
  box-shadow: 0 14px 40px rgba(47, 72, 80, 0.16);
  border: 1px solid rgba(47, 72, 80, 0.08);
}

.fx-stage-shot img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 560px;
  object-fit: cover;
  object-position: top center;
}

/* A very wide, very short crop (the acceptance-steps strip is 7.9:1) is only a
   sliver tall at column width. Sitting it on a tinted, padded ground and
   centring it in the row turns that from an accident into a detail shot,
   rather than a screenshot that failed to fill its frame. */
.fx-stage-shot-strip {
  display: flex;
  align-items: center;
  padding: 34px 26px;
  background: var(--bg);
  box-shadow: 0 10px 30px rgba(47, 72, 80, 0.12);
}

.fx-stage-shot-strip img {
  border-radius: 8px;
  box-shadow: 0 4px 14px rgba(47, 72, 80, 0.16);
}

/* ---------- Mid-page CTA ---------- */

.fx-cta {
  background: var(--primary);
  color: white;
  padding: 70px 0;
  text-align: center;
}

.fx-cta-inner h2 {
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  margin-bottom: 12px;
  color: white;
}

.fx-cta-inner > p {
  font-size: 1.1rem;
  color: rgba(255, 255, 255, 0.75);
}

.fx-cta .fx-btn-ghost {
  color: white;
  border-color: rgba(255, 255, 255, 0.35);
}

.fx-cta .fx-btn-ghost:hover {
  border-color: white;
}

/* ---------- A-Z index ---------- */

.fx-index {
  background: white;
  /* No trailing padding: the closing testimonial owns the gap below this
     section, the same way the mid-page one does. See the testimonial spacing
     note further up. */
  padding: 80px 0 0;
  color: var(--primary);
  scroll-margin-top: 70px;
}

.fx-index-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 30px;
  flex-wrap: wrap;
  margin-bottom: 34px;
}

.fx-index-head h2 {
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  letter-spacing: -0.015em;
  margin-bottom: 6px;
}

.fx-index-sub {
  color: rgba(47, 72, 80, 0.65);
  font-size: 1rem;
}

.fx-search {
  position: relative;
  flex: 0 1 340px;
  min-width: 240px;
}

.fx-search-input {
  width: 100%;
  padding: 13px 42px 13px 16px;
  border-radius: 10px;
  border: 1px solid rgba(47, 72, 80, 0.22);
  background: white;
  font-size: 1rem;
  font-family: inherit;
  color: var(--primary);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.fx-search-input:focus {
  outline: none;
  border-color: var(--green);
  box-shadow: 0 0 0 3px rgba(162, 185, 100, 0.25);
}

/* Suppress the native WebKit clear affordance — we render our own so the
   control looks the same in every browser. */
.fx-search-input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.fx-search-clear {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 50%;
  background: rgba(47, 72, 80, 0.08);
  color: var(--primary);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.fx-search-clear:hover {
  background: rgba(47, 72, 80, 0.16);
}

.fx-index-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 2px;
  list-style: none;
  padding: 0;
  margin: 0;
}

.fx-index-item {
  display: block;
  padding: 14px 16px;
  border-radius: 8px;
  text-decoration: none;
  color: var(--primary);
  transition: background 0.15s ease;
  height: 100%;
}

.fx-index-item:hover {
  background: rgba(47, 72, 80, 0.05);
}

.fx-index-title {
  display: block;
  font-weight: 600;
  font-size: 1rem;
  margin-bottom: 2px;
}

.fx-index-blurb {
  display: block;
  font-size: 0.9rem;
  line-height: 1.45;
  color: rgba(47, 72, 80, 0.6);
}

.fx-pro {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 4px;
  background: rgba(181, 164, 203, 0.3);
  color: #5c4d70;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
}

.fx-index-empty {
  padding: 30px 0;
  font-size: 1.05rem;
  color: rgba(47, 72, 80, 0.7);
}

.fx-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Responsive ---------- */

@media (max-width: 960px) {
  /* Below this width the eight links need ~940px and the row cannot hold them.
     Rather than hide four of them behind a sideways swipe with no affordance,
     the strip wraps and shows everything at once — which is also the clearer
     signal of how the page is laid out.
     It stops being sticky at the same time: a wrapped bar is two or three rows
     tall, and pinning that to the top of a phone screen would cost a permanent
     slice of the viewport to save one flick back up. */
  .fx-stagenav {
    position: static;
  }

  .fx-stagenav-inner {
    flex-wrap: wrap;
    justify-content: center;
    overflow-x: visible;
    gap: 2px 4px;
  }

  /* Tighter chips so the wrapped strip lands in as few rows as possible. */
  .fx-stagenav-link {
    padding: 6px 10px;
    font-size: 0.85rem;
  }

  .fx-stage {
    grid-template-columns: 1fr;
    gap: 32px;
    padding: 44px 0;
  }

  /* Undo the desktop alternation: on one column the image always follows
     its text, otherwise every other screenshot floats above its heading. */
  .fx-stage-reversed .fx-stage-text,
  .fx-stage-reversed .fx-stage-shot {
    order: 0;
  }

  .fx-stage-shot img {
    max-height: 420px;
  }

  /* Bands sit closer together on a narrow screen, so the breaks do too. */
  .fx-stages + .sodium-testimonial,
  .fx-index + .sodium-testimonial {
    margin-top: 44px;
    margin-bottom: 44px;
  }
}

@media (max-width: 768px) {
  .fx-hero {
    padding: 36px 0 50px;
  }

  .fx-hero-sub {
    font-size: 1.05rem;
  }

  .fx-btn {
    padding: 14px 28px;
    font-size: 1rem;
  }

  .fx-stages {
    padding: 50px 0 20px;
  }

  .fx-index {
    padding: 56px 0 0;
  }

  .fx-index-head {
    align-items: stretch;
  }

  .fx-search {
    flex: 1 1 100%;
  }
}

/* The hero's "Jump to all N features" link needs 415px of viewport to share a
   line with the question before it, so on anything narrower it breaks
   mid-phrase. Below that it gets its own line instead. The breakpoint is the
   measured reflow point rather than a round number: it covers every common
   phone width (320-414) and leaves the larger handsets on one line. */
@media (max-width: 420px) {
  .fx-hero-note .fx-inline-link {
    display: block;
    margin-top: 4px;
  }
}
