/* ==========================================================================
   Sections — page-specific layout, mobile-first with tablet/desktop overrides
   Breakpoints: 640px (tablet), 1024px (desktop), 1280px (wide desktop)
   ========================================================================== */

/* ---------------------------------------------------------------------
   HERO
   --------------------------------------------------------------------- */
.hero {
  display: flex;
  flex-direction: column;
  background: var(--color-white);
  text-align: center;
}

/* The white part of the hero owns the full-screen minimum, not .hero — the
   header is in flow (sticky, not fixed), so its height comes off the top and
   white covers the whole first viewport. The cream visa bar below therefore
   starts at the fold, matching the other pages' leading white section. */
.hero__content {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-lg);
  padding-block: var(--space-3xl);
  min-height: calc(100vh - var(--header-height));
}

@supports (height: 100svh) {
  .hero__content {
    min-height: calc(100svh - var(--header-height));
  }
}

@media (min-width: 1024px) {
  .hero__content {
    padding-top: var(--space-5xl);
  }
}

.hero__title {
  font-family: var(--font-display);
  font-size: var(--fs-display-xl);
  font-weight: var(--fw-semibold);
  line-height: 1.1;
  color: var(--color-navy-700);
  max-width: 800px;
  /* Pulls the 24px .hero__content gap back to the sitewide 16px
     heading-to-lead rhythm without disturbing the gap below the subtitle. */
  margin-bottom: -0.5rem; /* 24px gap - 8px = 16px */
}

.hero__title-line2 {
  display: block;
}

.hero__title-dark {
  color: var(--color-navy-700);
}

.hero__title-gold {
  color: var(--color-gold-400);
}

/* Phones drop this — see the mobile rule below, which lets "Intelligence"
   run on to "Before the" instead of forcing a break beforehand. */
.hero__title-break {
  display: block;
}

/* Phones (320-639px): no forced breaks — the 38px size, 1.05 line-height,
   and 360px measure are tuned together so the text wraps on its own into
   Immigration / Intelligence Before the / Petition Is Written at the
   374px reference width, and stays balanced either side of it. */
@media (max-width: 639px) {
  /* .hero__content's 24px gap minus 8px = a 16px badge-to-H1 rhythm, so
     the badge reads as part of the same cluster as the H1 and
     description rather than sitting a full gap-step away from them. */
  .hero__content > .badge {
    margin-bottom: -8px;
  }

  .hero__title {
    font-size: 38px;
    line-height: 1.15;
    max-width: 360px;
    margin-inline: auto;
    /* .hero__content's 24px gap minus 4px = a 20px H1-to-description
       rhythm on mobile. */
    margin-bottom: -4px;
  }

  .hero__title-break {
    display: none;
  }

  .hero__title-line2 {
    display: inline;
  }
}

.hero__subtitle {
  max-width: 46rem;
  font-size: var(--fs-body-lg);
  color: var(--color-text-body);
}

/* Phones set the subtitle on a narrower measure, so it reads as short
   centred rows under the title — breaking a clause at a time rather than
   running full width and leaving a short remainder.

   70vw is the operative value across the whole phone range (320–639px):
   at 320px that's 224px, at 639px it's 447px, so the column keeps growing
   with the screen the entire way rather than plateauing at some point in
   the middle. The clamp's floor and ceiling only guard the true extremes
   beyond any real phone — a foldable narrower than ~296px, or the instant
   this rule hands off to tablet at 640px — so they sit outside the range
   this media query ever actually sees, and 70vw alone is what determines
   the width for every phone in between. */
@media (max-width: 639px) {
  .hero__subtitle {
    max-width: 358px;
    font-size: var(--fs-body); /* 16px */
    line-height: 1.475;
  }
}

.hero__ctas {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
  margin-top: var(--space-sm);
}

@media (min-width: 1024px) {
  .hero__ctas {
    margin-top: var(--space-lg);
  }
}

/* .hero__content's 24px gap plus 16px = a 40px description-to-CTA gap on
   mobile, in place of the default rule's extra 12px. */
@media (max-width: 639px) {
  .hero__ctas {
    margin-top: 16px;
  }
}

.hero__cta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-md);
}

.hero__legal-note {
  font-size: var(--fs-body-sm);
  color: var(--color-text-body);
}

.hero__footnote {
  max-width: 42rem;
  font-size: var(--fs-body);
  color: var(--color-text-body);
  margin-top: var(--space-lg);
}

.hero__footnote a {
  color: var(--color-gold-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* The underline is the resting affordance; hovering lifts it rather than
   adding more emphasis on top of the colour change. */
.hero__footnote a:hover,
.hero__footnote a:focus-visible {
  text-decoration: none;
  color: var(--color-gold-600);
}

/* ---- Visa bar ----
   Flush against hero__content (no margin-top) so the cream band transitions
   directly off the white hero with no stray gap, and directly into the
   navy audience section below with no gap either. */
.visa-bar {
  background: var(--color-cream-100);
  padding-block: 5.625rem 7.5rem; /* 90px / 120px */
  padding-inline: var(--container-pad);
  text-align: center;
}

/* Two lines always — the markup breaks after "categories" itself rather
   than leaving the wrap to width, same approach as .audience__heading. */
.visa-bar__heading {
  font-family: var(--font-display);
  font-size: var(--fs-display-lg);
  font-weight: var(--fw-semibold);
  line-height: 1.21;
  letter-spacing: -0.5px;
  color: var(--color-navy-700);
  margin-bottom: 3.75rem; /* 60px */
}

.visa-bar__list {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xl);
  max-width: 1280px;
  margin-inline: auto;
}

.visa-bar__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2xs);
}

.visa-bar__code {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 1.75rem;
  color: var(--color-navy-900);
}

.visa-bar__label {
  font-size: var(--fs-body-sm);
  color: var(--color-navy-900);
}

.visa-bar__divider {
  display: none;
}

/* Five categories are more than fit on one line below desktop, so the row
   wraps here and the dividers stay hidden — a divider left at the end of a
   wrapped line joins nothing. */
@media (min-width: 640px) {
  .visa-bar__list {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-xl);
  }
}

/* One line, with the dividers back. 1280px is where all five items plus
   their gutters actually fit; the gap tracks the viewport from there so it
   stays clear of the page padding at the low end and lands on the comp's
   48px at 1440px. */
@media (min-width: 1280px) {
  .visa-bar__list {
    flex-wrap: nowrap;
    column-gap: clamp(2rem, 3.33vw, 3rem);
  }

  /* Each item holds its line here; below this range they wrap as whole
     items and a long label is free to break instead. */
  .visa-bar__label {
    white-space: nowrap;
  }

  .visa-bar__divider {
    display: block;
    width: 1px;
    height: 62px;
    background: #c7defd;
  }
}

/* ---------------------------------------------------------------------
   AUDIENCE — "Built for people doing extraordinary work"
   --------------------------------------------------------------------- */
.audience {
  background: var(--color-navy-800);
  padding-block: var(--space-6xl);
}

/* Centred, two lines always — the markup breaks after "doing" itself
   (a <br>) rather than leaving the wrap to width, so the split lands in
   the same place at every breakpoint. No max-width — a measure cap here
   would fight that manual break. */
.audience__heading {
  font-family: var(--font-display);
  font-size: clamp(2rem, 3.85vw, 3.5rem);
  font-weight: var(--fw-semibold);
  color: var(--color-white);
  text-align: center;
  margin-bottom: var(--space-3xl);
}

/* Same max-width/centering/padding formula as .container so the first and
   last card line up exactly with the navbar edges at every breakpoint.
   Below desktop the row still overflows and scrolls (there are more cards
   than can comfortably fit); at desktop it fits exactly and the hover
   expand/contract interaction takes over instead. */
.audience__scroller {
  display: flex;
  gap: var(--space-lg);
  width: 100%;
  max-width: calc(var(--container-max) + (var(--container-pad) * 2));
  margin-inline: auto;
  padding-inline: var(--container-pad);
  padding-bottom: var(--space-sm);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* Without this the snap aligns a card against the scrollport edge and
     pulls it out past the row's own padding, so the first card sits flush
     to the screen instead of inset like the rest of the page. */
  scroll-padding-inline: var(--container-pad);
  -webkit-overflow-scrolling: touch;
  /* The row keeps its own arrows, and swipe and keyboard scrolling are
     unaffected, so the native bar is only a stray line across the navy.
     It is an overlay bar here — it claims no layout space — so hiding it
     moves nothing. */
  scrollbar-width: none;
}

.audience__scroller::-webkit-scrollbar {
  display: none;
}

.audience-card {
  position: relative;
  flex: 0 0 200px;
  height: 356px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  scroll-snap-align: start;
}

/* Paging arrows for the scrolling row. The row is still swipeable — these
   just give it a visible, pointer-and-keyboard-reachable control. */
.audience__controls {
  display: flex;
  justify-content: center;
  gap: var(--space-md);
  margin-top: var(--space-xl);
  padding-inline: var(--container-pad);
}

.audience__nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; /* full 44px touch target */
  height: 44px;
  border-radius: 50%;
  background: var(--color-cream-100);
  color: var(--color-gold-500);
  transition: background var(--duration-base) var(--ease-standard),
    color var(--duration-base) var(--ease-standard),
    opacity var(--duration-base) var(--ease-standard);
}

.audience__nav:hover {
  background: var(--color-white-off);
  color: var(--color-gold-400);
}

.audience__nav--prev svg {
  transform: scaleX(-1);
}

/* Dimmed rather than removed at the ends of the row, so the pair does not
   shift position as it becomes unavailable. */
.audience__nav:disabled {
  opacity: 0.35;
  cursor: default;
}

/* From here up the cards fit the container and expand on hover instead of
   scrolling, so there is nothing left for the arrows to page through.

   1300px rather than the sheet's usual 1024px desktop breakpoint: this row
   needs more width than most sections. The active card holds a fixed
   420px, so between 1024 and 1300 the five inactive cards were splitting
   what little was left and came out around 100px each — too narrow to read
   as cards, and their labels wrapped to three lines. The scrolling layout
   handles that range far better, so it now keeps it. */
@media (min-width: 1300px) {
  .audience__controls {
    display: none;
  }
}

.audience-card--wide {
  flex-basis: 330px;
}

/* Below the row-and-arrows breakpoint (min-width: 1300px above), the row
   pages one card at a time the same as it does on phones — so every card
   takes the same slot and the lead card loses its extra width, which
   otherwise fills the screen edge to edge on a narrower screen and leaves
   the next card not visible at all. Sized to leave the next card showing
   at the edge, which is what marks the row as scrollable. */
@media (max-width: 1299px) {
  .audience-card,
  .audience-card--wide {
    flex-basis: min(76vw, 330px);
  }
}

.audience-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The source photo is a tall portrait with her face in the upper third;
   a centered crop clips into her hairline. Anchored higher so the whole
   face stays in frame. */
.audience-card img[src*="card-physicians"] {
  object-position: 50% 15%;
}

/* Same fix as card-physicians above: a centered crop clips into the tops
   of these subjects' heads. Anchored higher, staying centered
   horizontally, so heads and upper bodies stay fully in frame. */
.audience-card img[src*="card-scientists"] {
  object-position: 50% 10%;
}

.audience-card img[src*="card-founders"] {
  object-position: 50% 8%;
}

/* The scrim lives on the card rather than on the label, because the label
   box is only about a quarter of the card's height — far too short a run
   for a gradient to fade out gradually, so any ramp confined to it reads as
   a visible edge. Given ~60% of the card to travel, it can stay nearly
   clear over the subject and still reach full strength behind the text.
   The stops ease rather than ramp linearly: a straight interpolation has a
   perceptible onset where it leaves transparent, while holding the early
   stops low and accelerating late keeps the top of the scrim invisible. */
.audience-card::before {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 60%;
  /* Above the photo, which is itself positioned from the desktop
     breakpoint up and would otherwise paint over this by DOM order. */
  z-index: 1;
  background: linear-gradient(
    to bottom,
    rgba(8, 8, 8, 0) 0%,
    rgba(8, 8, 8, 0.05) 22%,
    rgba(8, 8, 8, 0.15) 38%,
    rgba(8, 8, 8, 0.31) 52%,
    rgba(8, 8, 8, 0.5) 66%,
    rgba(8, 8, 8, 0.68) 80%,
    rgba(8, 8, 8, 0.8) 91%,
    rgba(8, 8, 8, 0.86) 100%
  );
  pointer-events: none;
}

.audience-card__label {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  padding: var(--space-xl) var(--space-lg);
  color: var(--color-white-off);
  font-size: 1.1rem;
  font-weight: var(--fw-medium);
  text-align: center;
  white-space: nowrap;
}

/* Desktop: the six cards fit the container without scrolling, so the
   interaction switches from horizontal scroll to a hover-expand gallery —
   the active card grows via flex-grow while its siblings proportionally
   yield the space back, purely through flexbox's own distribution math.

   The gallery always has an active card, not just while the pointer is
   over one: the first card carries that state by default (same flex-grow,
   same full-strength image and label as an actual hover) so the row never
   sits in an undifferentiated, all-equal rest state. Hovering a different
   card hands the state to it for as long as the pointer stays there, and
   it returns to the first card the moment the pointer leaves — mirroring
   the CSS-only pattern already used for a card's own hover/focus, just
   keyed on ":first-child" for the default instead of the pointer. */
@media (min-width: 1300px) {
  .audience__scroller {
    overflow: visible;
    scroll-snap-type: none;
    padding-bottom: 0;
  }

  .audience__scroller {
    /* The active card is a fixed width rather than a share of the row, so
       it measures the same on every desktop size. The rest of the row
       divides whatever is left. */
    --audience-card-active: 420px;
  }

  .audience-card {
    flex: 1 1 0;
    min-width: 0;
    height: 380px;
  }

  /* Same transition as the base .audience-card rule, but declared on a
     descendant selector so its specificity matches (rather than loses to)
     .js-reveal [data-reveal] in base.css — that rule's own transition
     (opacity, transform, for this card's one-time scroll-reveal) is a
     shorthand, and shorthands replace rather than merge, so without this
     the card would carry no flex-grow transition at all and the
     expand/contract would happen as a sudden jump. Reusing the reveal
     system's own duration and easing for the two properties it owns keeps
     that entrance animation exactly as it was; flex-grow keeps the
     hover-expand's own duration and easing. */
  .audience__scroller .audience-card {
    transition: flex-basis var(--duration-slower) var(--ease-glide),
      flex-grow var(--duration-slower) var(--ease-glide),
      opacity var(--duration-reveal) var(--ease-reveal),
      transform var(--duration-reveal) var(--ease-reveal);
  }

  /* The row always has exactly one active card, and it stays where the
     pointer last left it rather than snapping back to the first card.
     That "last hovered stays" part is why .is-active exists at all:
     :hover stops matching the moment the cursor leaves, so CSS on its own
     has no way to remember which card was most recently pointed at.
     main.js moves the class on hover and then simply leaves it there.

     :first-child / :hover / :focus-within are kept as the no-JS path. If
     the script never runs, no .is-active exists anywhere, the :has()
     demotions below never match, and the row degrades to exactly the
     behaviour it had before: first card expanded, plain hover to expand
     another, reverting on leave. */
  /* Fixed basis, and no grow or shrink, so the active card is exactly
     --audience-card-active wide whatever the viewport. The others keep
     `1 1 0`, which splits the remaining space between them — so widening
     this card narrows them by exactly the amount it takes, and the row
     still fills its container with no overflow. */
  .audience-card:first-child,
  .audience-card:hover,
  .audience-card:focus-within,
  .audience-card.is-active {
    flex: 0 0 var(--audience-card-active);
  }

  /* Once a card is active, every other card stands down — including the
     first card's default and any card the pointer merely passes over,
     since main.js has already handed .is-active to whatever is hovered.
     Back to a zero basis that grows, so they share what is left rather
     than each claiming a width of their own. */
  .audience__scroller:has(.audience-card.is-active)
    .audience-card:not(.is-active) {
    flex: 1 1 0;
  }

  /* The card is a mask, not a frame. These sources are portrait (340x510),
     so at 176px wide `cover` solves against the height while at hover width
     it solves against the width — re-scaling the photo mid-transition and
     reading as a zoom. Laying the photo out at one constant width instead
     (wider than any card ever grows) means widening the card only uncovers
     the part that was cropped, with no rescale at all. It also keeps the
     raster stable, so the only per-frame work is moving the clip.

     The active card reads at full strength; every other card desaturates
     and dims so attention reads unambiguously on the one being considered.
     Every property runs on the same duration and curve so the width, the
     colour and the label arrive together instead of drifting apart. */
  .audience-card img {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    /* Exactly the active card's width — the widest the card ever gets — so
       the photo fills it edge to edge when expanded and never sticks out
       past it. Held at that one width rather than sized to the card, so a
       contracted card just clips more of the same raster: the width is
       constant through the whole expand, which is what keeps the photo
       from rescaling mid-animation. max-width: none overrides the global
       img { max-width: 100% } in base.css, which would otherwise pull it
       back to the contracted card's width and reintroduce the rescale. */
    width: var(--audience-card-active);
    max-width: none;
    height: 100%;
    filter: grayscale(1) brightness(0.55);
    transition: filter var(--duration-slower) var(--ease-glide);
  }

  .audience-card:first-child img,
  .audience-card:hover img,
  .audience-card:focus-within img,
  .audience-card.is-active img {
    filter: grayscale(0) brightness(1);
  }

  .audience__scroller:has(.audience-card.is-active)
    .audience-card:not(.is-active) img {
    filter: grayscale(1) brightness(0.55);
  }

  /* Always promoted, not just while the row is in use: the first card
     carries the filtered, full-strength treatment at rest, so its layer
     needs to be ready from the start rather than created on first hover. */
  .audience-card img {
    will-change: filter;
  }

  .audience-card__label {
    white-space: normal;
    opacity: 0.6;
    transition: opacity var(--duration-slower) var(--ease-glide);
  }

  .audience-card:first-child .audience-card__label,
  .audience-card:hover .audience-card__label,
  .audience-card:focus-within .audience-card__label,
  .audience-card.is-active .audience-card__label {
    opacity: 1;
  }

  .audience__scroller:has(.audience-card.is-active)
    .audience-card:not(.is-active)
    .audience-card__label {
    opacity: 0.6;
  }
}

/* ---------------------------------------------------------------------
   CLARITY — "Clarity before you commit" + "How it works"
   --------------------------------------------------------------------- */
.clarity {
  /* Height and pinned offset live on the section so they stay in step: the
     offset centres the image in the space the sticky header leaves. */
  --media-height: min(466px, 65vh);
  --media-pin-top: calc(
    var(--header-height) + (100vh - var(--header-height) - var(--media-height)) / 2
  );

  background: var(--color-white);
  padding-block: var(--space-6xl);
}

.clarity__grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xl);
}

/* Stacked layout (below the row breakpoint further down) renders the image
   after the text instead of in its source-first position. A CSS order
   rather than moving the markup, so reading order for assistive tech is
   unchanged and this rule simply stops applying once the row layout takes
   over — nothing to reset at that breakpoint. */
@media (max-width: 1023px) {
  .clarity__media {
    order: 1;
  }
}

.clarity__media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 4 / 3;
}

.clarity__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.clarity__content {
  display: flex;
  flex-direction: column;
  gap: 5.75rem; /* 92px */
}

@media (max-width: 639px) {
  .clarity__content {
    gap: 48px;
  }
}

.clarity__block {
  display: flex;
  flex-direction: column;
  gap: 1.25rem; /* 20px */
}

/* Gap above covers the eyebrow/heading spacing here; the shared
   .eyebrow margin-bottom would stack on top of it. */
.clarity__block .eyebrow {
  margin-bottom: 0;
}

/* Groups the eyebrow, heading and process tracks of the "how it works"
   block so they run a 30px rhythm, independent of the button below —
   which stays on the 20px .clarity__block gap. */
.clarity__block-intro {
  display: flex;
  flex-direction: column;
  gap: 1.875rem; /* 30px */
}

/* The first block sets its lead a step further from the bullet list than
   the second block sets its heading from the numbered tracks. */
.clarity__content > .clarity__block:first-child .clarity__block-intro {
  gap: 2.25rem; /* 36px */
}

/* Groups the eyebrow, heading and lead paragraph at the sitewide 16px
   heading-to-lead rhythm, independent of the wider gap around them. */
.clarity__heading-group {
  display: flex;
  flex-direction: column;
  gap: 1rem; /* 16px */
}

.clarity__heading-group .section-heading {
  margin-bottom: 0;
}

.feature-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.feature-list__item {
  display: flex;
  gap: var(--space-xs);
  align-items: flex-start;
}

.feature-list__icon {
  flex-shrink: 0;
}

.feature-list__title {
  /* 28px, not the 20px this was while set in Inter. Cormorant Garamond's
     x-height is ~41% shorter at the same pixel size, so once the face
     changed the old 20px stopped reading as a heading at all. 28px is
     where Cormorant's x-height matches Inter's at 20px, restoring the
     size this heading appeared to be before — and it is the same size
     the rest of the site's Cormorant sub-headings already use. */
  font-size: 1.75rem;
  font-weight: var(--fw-semibold);
  line-height: 1.4;
  color: var(--color-navy-700);
  margin-bottom: var(--space-xs);
}

@media (max-width: 639px) {
  .feature-list__title {
    font-size: 1.5rem; /* 24px, was 18px — same reason as above */
  }
}

.feature-list__text {
  font-size: var(--fs-body);
  color: var(--color-text-body);
}

.process-track-group {
  display: flex;
  flex-direction: column;
  gap: 2.5rem; /* 40px, separating the evaluation and attorney-led tracks */
}

/* Each offering is a numbered item: an index in the display face beside a
   body carrying the title, the step row, and (on 01) the CTA. */
.process-track {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
}

/* Same treatment as .numbered-list__index in the sample-report section, at
   the slightly larger size the comp sets here. Decorative — the numbers are
   aria-hidden, the list order carries the meaning. */
.process-track__index {
  flex-shrink: 0;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: 2.3125rem; /* 37px */
  line-height: 1;
  color: rgba(12, 32, 60, 0.5);
}

.process-track__body {
  display: flex;
  flex: 1 0 0;
  min-width: 0;
  flex-direction: column;
  gap: 1.25rem; /* 20px, title block to step row */
}

.process-track__heading {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

/* The display face here, not .feature-list__title's body face: the comp
   promotes these two offerings above the bullet list above them. */
.process-track__title {
  font-family: var(--font-display);
  font-size: 1.75rem; /* 28px */
  font-weight: var(--fw-semibold);
  line-height: 1.36;
  color: var(--color-navy-700);
}

@media (max-width: 639px) {
  .process-track__title {
    font-size: 1.5rem; /* 24px */
  }
}

.process-track__subtitle {
  font-size: var(--fs-body);
  color: var(--color-text-body);
}

.process-track__steps {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
}

.process-step {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.process-step__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(203, 166, 72, 0.12);
  border: 0.5px solid rgba(203, 166, 72, 0.28);
  flex-shrink: 0;
}

.process-step__text {
  font-size: var(--fs-body);
  color: var(--color-navy-700);
  white-space: nowrap;
}

.process-step__connector {
  width: 32px;
  height: 1px;
  background: #d1d9e3;
  flex-shrink: 0;
}

/* Phones run the track as a column. The steps already wrapped one per line
   at this width, but the connectors did not wrap with them — each was left
   sitting at the end of its step's line as a stray horizontal dash out to
   the right of the label, joining nothing. Turning the track into a real
   column and standing the rule on end puts each connector back between the
   two icons it belongs to. */
@media (max-width: 639px) {
  .process-track__steps {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: flex-start;
    /* Tighter than the row layout's --space-sm: stood on end, that same
       12px gap either side of the connector added up to 44px between
       icons — comfortable spread out horizontally, but a lot of dead
       vertical space stacked into a column. */
    gap: var(--space-xs);
  }

  .process-step__connector {
    width: 1px;
    /* Shortened to match the tighter gap around it, so the line still
       reaches between the two icons it connects rather than floating
       short of one. Icon size and text are untouched — only the two
       values that made up the 44px gap moved, now totalling 28px. */
    height: 12px;
    /* Centres the rule under the icon column: half the 36px icon, less the
       rule's own width. */
    margin-inline-start: calc((36px - 1px) / 2);
  }
}

@media (min-width: 1024px) {
  .clarity__grid {
    flex-direction: row;
    align-items: flex-start;
    gap: 3.5rem; /* 56px */
  }

  .clarity__media {
    /* The comp's 445px, capped as a share of the row so the image doesn't
       crowd the text column on a narrow desktop. The width the text column
       gets back is what lets each track's three steps sit on one line. */
    flex: 0 0 445px;
    max-width: 38%;
    aspect-ratio: auto;
    height: var(--media-height);
    /* Starts level with "Why PetitionIQ" rather than centred against the
       much taller text column, then pins with equal space above and below.
       (A transform-based offset was tried but a translateY on a sticky
       element isn't clamped by its containing block — it can shove the box
       up into the previous section. A plain top offset stays inside.) */
    align-self: flex-start;
    position: sticky;
    top: var(--media-pin-top);
  }

  .clarity__content {
    flex: 1 1 auto;
    min-width: 0;
  }
}

/* ---------------------------------------------------------------------
   SAMPLE REPORT
   --------------------------------------------------------------------- */
.sample-report {
  background: var(--color-cream-100);
  padding-block: var(--space-6xl);
}

.sample-report__grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xl);
}

.sample-report__intro {
  margin-bottom: var(--space-xl);
}

.sample-report__intro > .eyebrow {
  margin-bottom: var(--space-sm);
}

.numbered-list {
  display: flex;
  flex-direction: column;
}

.numbered-list__item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-lg);
  padding-block: var(--space-lg);
  border-bottom: 1px solid var(--color-border-subtle);
}

@media (max-width: 639px) {
  .numbered-list__item {
    padding-block: var(--space-md); /* 16px, was 24px */
    gap: var(--space-xs); /* 8px, was 24px */
  }
}

.numbered-list__item:first-child {
  border-top: 1px solid var(--color-border-subtle);
}

@media (max-width: 639px) {
  .numbered-list__item:first-child {
    border-top: none;
  }
}

.numbered-list__index {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: 2rem;
  color: rgba(12, 32, 60, 0.5);
  flex-shrink: 0;
  width: 2.5rem;
}

.numbered-list__title {
  font-size: 1.75rem; /* 28px — see .feature-list__title */
  font-weight: var(--fw-semibold);
  color: var(--color-navy-700);
  margin-bottom: var(--space-xs);
}

@media (max-width: 639px) {
  .numbered-list__title {
    font-size: 1.5rem; /* 24px */
  }
}

.numbered-list__text {
  font-size: var(--fs-body);
  color: var(--color-text-body);
}

/* ---- Report card mock ---- */
.report-card {
  background: var(--color-white);
  border: 1px solid var(--color-white-off);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.report-card__header {
  background: var(--color-navy-900);
  padding: var(--space-lg);
}

@media (max-width: 639px) {
  .report-card__header {
    padding: 20px;
  }
}

.report-card__title {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 1.25rem;
  color: var(--color-white-off);
  margin-bottom: var(--space-2xs);
}

.report-card__subtitle {
  font-size: var(--fs-body-sm);
  color: rgba(250, 250, 247, 0.6);
}

.report-card__body {
  padding: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

@media (max-width: 639px) {
  .report-card__body {
    padding: 20px;
  }
}

.report-card__section-label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-body);
}

.criteria-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.criteria-list__item {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  background: var(--color-white-off);
  border-radius: var(--radius-sm);
  padding: var(--space-md);
}

.criteria-list__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}

.criteria-list__dot--strong {
  background: var(--color-green-text);
}

.criteria-list__dot--develop {
  background: var(--color-gold-400);
}

.criteria-list__dot--unclear {
  background: var(--color-grey-dot);
}

.criteria-list__name {
  flex: 1 1 auto;
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  color: var(--color-navy-900);
}

.criteria-list__status {
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}

.criteria-list__status--strong {
  color: var(--color-green-text);
}

.criteria-list__status--develop {
  color: var(--color-gold-text);
}

.criteria-list__status--unclear {
  color: var(--color-grey-dot);
}

/* Mobile: stack each criteria row — dot + name share the first line, and
   status moves to its own line directly beneath the name (indented past
   the dot) instead of being squeezed against the row's right edge.
   Scoped away from .criteria-list--detailed, which already has its own
   mobile layout below to fit the extra explanatory note that variant
   carries per criterion. */
@media (max-width: 639px) {
  .criteria-list:not(.criteria-list--detailed) .criteria-list__item {
    display: grid;
    grid-template-columns: 9px 1fr;
    column-gap: var(--space-sm);
    row-gap: 4px;
    align-items: start;
  }

  .criteria-list:not(.criteria-list--detailed) .criteria-list__dot {
    grid-row: 1;
    grid-column: 1;
    margin-top: 0.4em;
  }

  .criteria-list:not(.criteria-list--detailed) .criteria-list__name {
    grid-row: 1;
    grid-column: 2;
  }

  .criteria-list:not(.criteria-list--detailed) .criteria-list__status {
    grid-row: 2;
    grid-column: 2;
    white-space: normal;
  }
}

.evidence-gaps {
  background: rgba(254, 253, 236, 0.7);
  border: 1px solid #fefdec;
  border-radius: var(--radius-sm);
  padding: var(--space-lg);
}

.evidence-gaps__label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  color: var(--color-gold-text);
  margin-bottom: var(--space-sm);
}

.evidence-gaps__item {
  display: flex;
  gap: var(--space-sm);
  font-size: var(--fs-body);
  color: var(--color-navy-900);
  padding-block: var(--space-2xs);
}

.evidence-gaps__item span {
  color: var(--color-gold-text);
  font-weight: var(--fw-bold);
  flex-shrink: 0;
}

.report-card__disclaimer {
  font-size: var(--fs-caption);
  line-height: 1.55;
  color: var(--color-text-body);
  opacity: 0.85;
  border-top: 1px solid var(--color-white-off);
  padding-top: var(--space-lg);
}

@media (max-width: 639px) {
  .report-card__disclaimer {
    padding-top: 20px;
  }
}

@media (min-width: 1024px) {
  .sample-report__grid {
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4xl);
  }

  .sample-report__content {
    flex: 0 1 560px;
  }

  .report-card {
    flex: 0 1 600px;
    /* No max-height and no sticky: the card's natural height is taller than
       the viewport, so capping it produced a scrollbar inside the card and
       pinning it would trap its own lower half off-screen. Top-aligned with
       the heading, it scrolls with the page and stays whole. */
    align-self: flex-start;
  }
}

/* ---------------------------------------------------------------------
   STAND BANNER — "Know where you stand"
   --------------------------------------------------------------------- */
.stand-banner {
  background: var(--color-navy-800);
  padding-block: var(--space-5xl);
}

.stand-banner__grid {
  display: flex;
  /* Content is first in the markup; plain column renders it first (the
     image last) while stacked. Row further down overrides this anyway, so
     the change only reaches the stacked layout. */
  flex-direction: column;
  gap: var(--space-3xl);
  align-items: center;
}

.stand-banner__content {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
  align-items: flex-start;
}

/* Eyebrow, heading and lead as one 16px-rhythm group, separate from the
   24px gap (.stand-banner__content above) that sets them off from the
   button below. Zeroing the heading's own margin-bottom (base.css) keeps
   that rhythm from stacking an extra 16px on top of the group's own gap. */
.stand-banner__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.stand-banner__intro .eyebrow,
.stand-banner__intro .section-heading {
  margin-bottom: 0;
}

.stand-banner__media {
  width: 100%;
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.stand-banner__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 4 / 3;
}

@media (min-width: 1024px) {
  .stand-banner__grid {
    flex-direction: row;
    align-items: center;
    gap: var(--space-6xl);
  }

  .stand-banner__content {
    flex: 1 1 55%;
  }

  .stand-banner__media {
    flex: 1 1 45%;
  }
}

/* ---------------------------------------------------------------------
   VISA CATEGORIES
   --------------------------------------------------------------------- */
.visa-categories {
  /* Shared by both columns: the image applies these to size and pin itself,
     and the card stack pins to the same offset so the two line up. */
  --media-height: min(483px, 65vh);
  --media-pin-top: calc(
    var(--header-height) + (100vh - var(--header-height) - var(--media-height)) / 2
  );

  background: var(--color-cream-100);
  padding-block: var(--space-6xl);
}

.visa-categories__grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xl);
}

/* Same reasoning as .clarity__media: order rather than moving the markup,
   scoped to stop applying once the row layout below takes over. */
@media (max-width: 1023px) {
  .visa-categories__media {
    order: 1;
  }
}

.visa-categories__media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 4 / 3;
}

.visa-categories__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.visa-categories__intro {
  margin-bottom: var(--space-xl);
}

.visa-categories__intro > .eyebrow {
  margin-bottom: var(--space-sm);
}

/* Stacking-cards scroll effect. Each card pins one --stack-peek lower than
   the one before it, so a card that gets covered still shows a strip of its
   own header — the deck reads as a stack rather than one swapped panel.
   The pinning is pure CSS; main.js only layers on the recede by setting
   --stack-depth (how many cards are now stacked on top of this one), which
   drives the scale-down and the tint. With JS off, depth stays 0 and the
   cards still stack correctly, just without the recede. */
.category-group {
  --stack-top: calc(var(--header-height) + var(--space-lg));
  /* The strip a covered card keeps. Deep enough for the card's own top
     padding plus the whole line box of .category-card__name — the name is
     the one thing the strip exists to show, and at the old 3rem it was cut
     off mid-letter on shorter viewports. Derived from the padding token so
     the two stay in step. */
  --stack-peek: calc(var(--space-lg) + 2.25rem);

  margin-bottom: var(--space-3xl);
}

.category-group:last-child {
  margin-bottom: 0;
}

.category-group__title {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-display-md);
  color: var(--color-navy-700);
  margin-bottom: var(--space-lg);
}

.category-card {
  --stack-index: 0;
  --stack-depth: 0;
  position: sticky;
  top: calc(var(--stack-top) + var(--stack-index) * var(--stack-peek));
  background: color-mix(
    in srgb,
    var(--color-cream-100) calc(min(var(--stack-depth), 1) * 62%),
    var(--color-white)
  );
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  /* 24px rather than 32px. A pinned card has to fit between its own pin
     and the fold or its last rows are cut off at every scroll position,
     and the deepest card in a four-card deck has the least room of all —
     so the card's own chrome is kept as tight as it can be without
     crowding the content. */
  padding: var(--space-lg);
  margin-bottom: var(--space-lg);
  /* Shrink from the top edge so the pinned strip stays put while the card
     insets from both sides as the next one slides over it. */
  transform: scale(calc(1 - var(--stack-depth) * 0.022));
  transform-origin: top center;
}

.category-card:last-child {
  margin-bottom: 0;
}

.category-group .category-card:nth-of-type(1) { --stack-index: 0; z-index: 1; }
.category-group .category-card:nth-of-type(2) { --stack-index: 1; z-index: 2; }
.category-group .category-card:nth-of-type(3) { --stack-index: 2; z-index: 3; }
.category-group .category-card:nth-of-type(4) { --stack-index: 3; z-index: 4; }
.category-group .category-card:nth-of-type(5) { --stack-index: 4; z-index: 5; }
.category-group .category-card:nth-of-type(6) { --stack-index: 5; z-index: 6; }

@media (prefers-reduced-motion: reduce) {
  .category-card {
    transform: none;
  }
}

/* Phones opt out of the deck entirely and let the cards flow.
   A pinned card only works if it fits in the space below its own pin, and
   none of these do on a short phone: at 375x667 every card needs more room
   than the viewport leaves it, and the last row of four of the seven can
   not be brought fully on screen at any scroll position — the next card is
   already covering it before it clears the fold. Stacking is kept from
   640px up, where there is room for it.

   Card styling is untouched; only the pinning and the recede that goes with
   it are dropped, so each card takes its own natural content height. */
@media (max-width: 639px) {
  .category-card {
    position: static;
    transform: none;
    /* main.js still writes --stack-depth. With no stack to recede into,
       hold the surface flat so a stray depth cannot tint a card. */
    background: var(--color-white);
    /* Tighter inset on phones — the content sets the card's height either
       way, so this only pulls the edges in, it does not clip anything. */
    padding: 20px; /* was 24px, was 32px before that */
  }
}

.category-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  border-bottom: 1px solid var(--color-border-subtle);
  padding-bottom: var(--space-md);
  margin-bottom: var(--space-sm);
}

.category-card__name {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 1.5rem;
  /* Tight: this line box is what --stack-peek has to clear on every covered
     card, and the body's 1.625 was adding 9px of air to each one. */
  line-height: 1.25;
  color: var(--color-navy-700);
}

.category-card__meta {
  display: flex;
  flex-direction: column;
}

.category-card__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-xs);
  padding-block: var(--space-sm);
  border-bottom: 1px solid var(--color-border-subtle);
}

.category-card__row--last {
  border-bottom: none;
  padding-bottom: 0;
}

.category-card__row dt {
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-gold-400);
}

.category-card__row dd {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.category-card__row dd strong {
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--color-navy-700);
}

.category-card__row dd span {
  font-size: var(--fs-body-sm);
  color: var(--color-text-body);
}

@media (min-width: 640px) {
  .category-card__row {
    grid-template-columns: 140px 1fr;
    gap: var(--space-lg);
  }
}

/* A taller viewport can afford to go deeper still, clearing the header row
   with room to spare rather than just fitting it. The height floor is what
   the deck can spare: every extra pixel of peek is a pixel the deepest
   pinned card loses from its own space below the fold. */
@media (min-width: 640px) and (min-height: 800px) {
  .category-group {
    --stack-peek: calc(var(--space-lg) + 2.75rem);
  }
}

/* Short viewports run the deck as tight as it goes: the deepest card has
   the least room of the four and this is what keeps its last rows above
   the fold. The peek still clears a covered card's header, which is
   20px of padding plus the 36px status pill. */
@media (min-width: 640px) and (max-height: 719px) {
  .category-group,
  .visa-categories .category-group {
    --stack-top: calc(var(--header-height) + var(--space-xs));
    --stack-peek: calc(var(--space-md) + 2.5rem);
  }

  .category-card {
    padding: 20px;
  }
}

@media (min-width: 1024px) {
  .visa-categories__grid {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--space-5xl);
  }

  .visa-categories__media {
    flex: 0 0 34%;
    aspect-ratio: auto;
    height: var(--media-height);
    /* Top-aligned with the heading rather than centred against the card
       column — that column is several screens tall, so centring the box
       started the image far down the section. */
    align-self: flex-start;
    position: sticky;
    /* Pinned centre: equal gap above and below the image within the space
       the sticky header leaves. So it starts level with the heading and
       settles mid-screen while the cards stack past it. */
    top: var(--media-pin-top);
  }

  .visa-categories__content {
    flex: 1 1 auto;
    min-width: 0;
  }

  /* Pin the deck on the same line as the image, so the top card and the
     image share a top edge while both are stuck — but never deeper than
     the deck can afford. A pinned card has to fit between its own pin and
     the fold or its last rows are cut off at every scroll position, and
     --stack-reserve is what the deepest card needs: the three peeks it
     sits below the first card, plus a full card. On a tall viewport the
     image alignment wins outright; on a short one the deck slides up by
     the difference rather than running off the bottom. */
  .visa-categories .category-group {
    --stack-reserve: calc(3 * var(--stack-peek) + 27rem);
    --stack-top: max(
      calc(var(--header-height) + var(--space-lg)),
      min(var(--media-pin-top), calc(100vh - var(--stack-reserve)))
    );
  }
}

/* ---------------------------------------------------------------------
   WORK PRODUCT — "The Work Behind the Filing"
   --------------------------------------------------------------------- */
.work-product {
  background: var(--color-white);
  padding-block: var(--space-6xl);
}

.work-product__grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xl);
}

.work-product__intro {
  max-width: 640px;
  margin-bottom: var(--space-xl);
}

.work-product__intro > .eyebrow {
  margin-bottom: var(--space-sm);
}

.doc-tabs {
  display: flex;
  flex-direction: column;
}

.doc-tab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  width: 100%;
  text-align: left;
  padding: var(--space-lg) var(--space-md) var(--space-lg) var(--space-lg);
  border-bottom: 1px solid rgba(12, 32, 60, 0.12);
  border-left: 4px solid transparent;
  transition: border-color var(--duration-base) var(--ease-standard), background var(--duration-base);
}

.doc-tab:hover {
  background: var(--color-cream-100);
}

.doc-tab.is-active {
  border-left-color: var(--color-gold-400);
}

.doc-tab__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

/* Every title reads at full strength, selected or not. The gold left
   border and the circular arrow on the active tab carry that state on
   their own, so the unselected titles are not dimmed to signal it. */
.doc-tab__title {
  /* These are document titles, so they take the same face, size and
     weight as every other sub-heading on the site. A span rather than a
     heading tag (it sits inside the tab button), so the base h1-h6 rule
     does not reach it and all three are set here. */
  font-family: var(--font-display);
  font-size: 1.75rem; /* 28px */
  font-weight: var(--fw-semibold);
  line-height: 1.25;
  color: var(--color-navy-700);
}

@media (max-width: 639px) {
  .doc-tab__title {
    font-size: 1.5rem; /* 24px, matching the other sub-headings on phones */
  }
}

.doc-tab__desc {
  font-size: var(--fs-body);
  color: var(--color-text-body);
}

.doc-tab__icon {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  display: none;
  align-items: center;
  justify-content: center;
}

@media (min-width: 1024px) {
  .doc-tab.is-active .doc-tab__icon {
    display: flex;
  }
}

/* Below 1024px the tab list reads as an accordion (see the
   max-width: 1023px block further down), so every item gets this
   chevron instead of the circular icon above, which stays desktop-only. */
.doc-tab__chevron {
  display: none;
  flex-shrink: 0;
  color: var(--color-text-body);
  transition: transform var(--duration-base) var(--ease-standard);
}

@media (max-width: 1023px) {
  .doc-tab__chevron {
    display: inline-flex;
  }

  .doc-tab.is-expanded .doc-tab__chevron {
    transform: rotate(180deg);
  }
}

/* ---- Memo card mock ---- */
.memo-card {
  background: var(--color-white);
  border: 1px solid #dcdcdc;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

/* The whole card is tuned to clear a laptop viewport under the sticky
   header: the paddings, gaps and body line-height below are all a step
   tighter than the section defaults so the memo reads in one screen
   instead of forcing a scroll to reach its last criterion. */
.memo-card__header {
  background: var(--color-navy-900);
  padding: var(--space-md) var(--space-lg);
}

@media (max-width: 639px) {
  .memo-card__header {
    padding: 20px;
  }
}

.memo-card__header p {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 1.25rem;
  color: var(--color-white-off);
}

.memo-card__body {
  padding: var(--space-md) var(--space-lg) var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

@media (max-width: 639px) {
  .memo-card__body {
    padding: 20px;
  }
}

.memo-card__section {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.memo-card__label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-gold-text);
}

.memo-card__text {
  font-size: var(--fs-body-sm);
  line-height: 1.5;
  color: var(--color-text-body);
}

.assessment-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-xs) var(--space-sm);
  align-items: start;
  border: 1px solid rgba(15, 42, 79, 0.16);
  border-radius: var(--radius-sm);
  padding: var(--space-sm);
}

.assessment-row__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin-top: 6px;
}

.assessment-row__dot--strong {
  background: var(--color-green-dot);
}

.assessment-row__dot--develop {
  background: var(--color-amber-dot);
}

.assessment-row__dot--gap {
  background: var(--color-red-dot);
}

.assessment-row__text {
  font-size: var(--fs-body-sm);
  line-height: 1.5;
  color: var(--color-text-body);
  grid-column: 2;
}

.assessment-row__text strong {
  color: var(--color-navy-800);
}

.assessment-row .chip {
  grid-column: 2;
  justify-self: start;
}

@media (min-width: 480px) {
  .assessment-row {
    grid-template-columns: auto 1fr auto;
  }

  .assessment-row__text {
    grid-column: 2;
  }

  .assessment-row .chip {
    grid-column: 3;
    align-self: center;
  }
}

/* Below 1024px each doc's own memo card relocates to sit directly under
   its doc-tab when expanded, reading as an accordion rather than a fixed
   side-by-side column — closed by default, and any number of rows can be
   open at once (each independently). .work-product__content and .doc-tabs
   are wrapper divs with no visual styling of their own at this width (the
   real layout is flex column with no gap, same as always) — display:
   contents lets their children (the intro block and the three tab
   buttons) take part in .work-product__grid's own areas directly, so a
   card can slot in right after its own tab, purely in CSS.

   .is-expanded is independent of .is-active: .is-active tracks which
   single tab/card pair is loaded into desktop's fixed side panel (always
   exactly one, a tablist is inherently single-select), while .is-expanded
   tracks which accordion rows are open here — any combination. initDocTabs
   (see main.js) toggles is-doc-0 / is-doc-1 / is-doc-2 on
   .work-product__grid independently per tab, so the grid-template-areas
   below cover every combination of open rows. */
@media (max-width: 1023px) {
  .work-product__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;
    grid-template-areas:
      'intro'
      'tab0'
      'tab1'
      'tab2';
  }

  .work-product__grid.is-doc-0:not(.is-doc-1):not(.is-doc-2) {
    grid-template-areas:
      'intro'
      'tab0'
      'card0'
      'tab1'
      'tab2';
  }

  .work-product__grid.is-doc-1:not(.is-doc-0):not(.is-doc-2) {
    grid-template-areas:
      'intro'
      'tab0'
      'tab1'
      'card1'
      'tab2';
  }

  .work-product__grid.is-doc-2:not(.is-doc-0):not(.is-doc-1) {
    grid-template-areas:
      'intro'
      'tab0'
      'tab1'
      'tab2'
      'card2';
  }

  .work-product__grid.is-doc-0.is-doc-1:not(.is-doc-2) {
    grid-template-areas:
      'intro'
      'tab0'
      'card0'
      'tab1'
      'card1'
      'tab2';
  }

  .work-product__grid.is-doc-0.is-doc-2:not(.is-doc-1) {
    grid-template-areas:
      'intro'
      'tab0'
      'card0'
      'tab1'
      'tab2'
      'card2';
  }

  .work-product__grid.is-doc-1.is-doc-2:not(.is-doc-0) {
    grid-template-areas:
      'intro'
      'tab0'
      'tab1'
      'card1'
      'tab2'
      'card2';
  }

  .work-product__grid.is-doc-0.is-doc-1.is-doc-2 {
    grid-template-areas:
      'intro'
      'tab0'
      'card0'
      'tab1'
      'card1'
      'tab2'
      'card2';
  }

  .work-product__content,
  .doc-tabs {
    display: contents;
  }

  .work-product__intro {
    grid-area: intro;
  }

  #doc-tab-0 {
    grid-area: tab0;
  }

  #doc-tab-1 {
    grid-area: tab1;
  }

  #doc-tab-2 {
    grid-area: tab2;
  }

  /* The gold left rail is a desktop-tablist cue for "this is the selected
     side-panel document" — with each open row's own card sitting right
     under it instead, the chevron already carries that signal. */
  .doc-tab.is-active {
    border-left-color: transparent;
  }

  .doc-tab {
    padding: var(--space-md) 0;
  }

  /* No hover fill on this breakpoint's accordion — a touch tap has no real
     hover state, and the chevron/gold-title cues already show which items
     are open. */
  .doc-tab:hover {
    background: none;
  }

  /* The divider that normally sits under every collapsed item would
     otherwise land between an open item's header and its own card right
     below it — moved to the bottom of the card instead, so it closes off
     the expanded content rather than cutting through it. */
  .doc-tab.is-expanded {
    border-bottom: none;
  }

  /* Each card is only placed in the grid (via its own card0/1/2 area,
     named above) once its own row is expanded; unplaced otherwise, which
     is what display: none actually hides here — an unplaced grid item
     would still render via auto-placement rather than disappearing. */
  .memo-card {
    display: none;
    margin-top: 20px;
    margin-bottom: var(--space-lg);
  }

  .memo-card[data-doc="0"] {
    grid-area: card0;
  }

  .memo-card[data-doc="1"] {
    grid-area: card1;
  }

  .memo-card[data-doc="2"] {
    grid-area: card2;
  }

  .work-product__grid.is-doc-0 .memo-card[data-doc="0"],
  .work-product__grid.is-doc-1 .memo-card[data-doc="1"],
  .work-product__grid.is-doc-2 .memo-card[data-doc="2"] {
    display: block;
  }

  /* The card's own border already frames its bottom edge, too close in
     colour to the divider to read as one — so the divider that "ends"
     doc0's or doc1's expanded content is placed on the tab right after it
     instead, in the actual blank space between the two. This only depends
     on that row's own open state, not on whether any other row is also
     open. doc2 has no tab after it (its card is always last), so it has
     nothing to add this to. */
  .work-product__grid.is-doc-0 #doc-tab-1 {
    border-top: 1px solid rgba(12, 32, 60, 0.12);
  }

  .work-product__grid.is-doc-1 #doc-tab-2 {
    border-top: 1px solid rgba(12, 32, 60, 0.12);
  }
}

@media (min-width: 1024px) {
  .work-product__grid {
    flex-direction: row;
    gap: var(--space-5xl);
    align-items: flex-start;
  }

  .work-product__content {
    flex: 1 1 45%;
    min-width: 0;
  }

  /* One .memo-card per doc now (see index.html) rather than one shared,
     rewritten card — only the tablist's active doc's card is shown here,
     so the fixed side panel still ever shows exactly one at a time. */
  .memo-card {
    display: none;
  }

  .memo-card.is-active {
    display: block;
    flex: 1 1 55%;
    /* No max-height and no sticky: the memo's natural height exceeds the
       viewport, so capping it put a scrollbar inside the card and pinning it
       would trap its lower half off-screen. Top-aligned with the heading, it
       scrolls with the page and stays whole. Same as .report-card. */
    align-self: flex-start;
  }
}

/* ---------------------------------------------------------------------
   PRICING
   --------------------------------------------------------------------- */
.pricing {
  background: var(--color-navy-800);
  padding-block: var(--space-6xl);
}

.pricing__heading {
  margin-bottom: var(--space-3xl);
  text-align: center;
}

.pricing__heading > .eyebrow {
  margin-bottom: var(--space-sm);
}

.pricing__heading .section-heading {
  max-width: 20ch;
  margin-inline: auto;
}

.pricing__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
}

.price-card {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background: rgba(12, 32, 60, 0.8);
  border: 1px solid var(--color-border-on-dark);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.price-card--featured {
  border-color: var(--color-gold-400);
}

.price-card__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-md);
  padding: var(--space-lg);
}

@media (max-width: 639px) {
  .price-card__body {
    gap: var(--space-xs);
    padding: 20px;
  }
}

.price-card__price {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 1.75rem;
  color: var(--color-white);
}

.price-card__price-sub {
  font-size: var(--fs-body-sm);
  color: rgba(255, 255, 255, 0.5);
  margin-top: calc(var(--space-2xs) * -2);
}

.price-card__desc {
  font-size: var(--fs-body);
  color: var(--color-text-on-dark-faint);
}

.price-card__footer {
  background: rgba(13, 34, 64, 0.8);
  border-top: 0.67px solid var(--color-border-on-dark);
  padding: var(--space-md) var(--space-lg) var(--space-lg);
}

.price-card__footer p {
  font-size: var(--fs-body-sm);
  color: rgba(255, 255, 255, 0.6);
}

@media (min-width: 900px) {
  .pricing__grid {
    grid-template-columns: repeat(3, 1fr);
    align-items: stretch;
  }

  .price-card {
    height: 100%;
  }
}

/* ---------------------------------------------------------------------
   FOUNDER
   --------------------------------------------------------------------- */
.founder {
  background: var(--color-white);
  padding-block: var(--space-6xl);
}

.founder__grid {
  display: flex;
  /* Content is first in the markup; plain column renders it first (the
     portrait last) while stacked. Row further down overrides this anyway,
     so the change only reaches the stacked layout. */
  flex-direction: column;
  gap: var(--space-3xl);
}

.founder__content {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

/* Eyebrow, heading and the paragraph that finishes its thought are one
   block. .founder__content's own 40px gap is a break between sections of
   the column — far too much between a heading and its own description,
   which was landing 56px below it once .section-heading's margin was added
   on top. Inside here the three lines take an even 16px rhythm, so the
   margins the eyebrow and the heading carry for use elsewhere are zeroed. */
.founder__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.founder__intro .eyebrow,
.founder__intro .section-heading {
  margin-bottom: 0;
}

/* The founder's own account, under the heading and above the pull quote —
   body copy at the section's reading width, set to support the quote
   rather than compete with it. */
.founder__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.founder__body p {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-text-body);
}

.founder__quote {
  border-left: 2px solid var(--color-gold-400);
  padding-left: var(--space-lg);
}


.founder__quote p {
  font-size: var(--fs-body);
  font-weight: 400;
  color: var(--color-navy-700);
  margin-bottom: var(--space-sm);
}

.founder__quote cite {
  font-style: normal;
  font-size: var(--fs-body-sm);
  color: var(--color-text-body);
}

.founder__features {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-xl);
}

.founder-feature img {
  margin-bottom: var(--space-sm);
}

.founder-feature h3 {
  font-size: 1.75rem; /* 28px — see .feature-list__title */
  font-weight: var(--fw-semibold);
  color: var(--color-navy-700);
  margin-bottom: var(--space-xs);
}

@media (max-width: 639px) {
  .founder-feature h3 {
    font-size: 1.5rem; /* 24px, matching the other sub-headings on phones */
  }
}

.founder-feature p {
  font-size: var(--fs-body-sm);
  color: var(--color-text-body);
}

.founder__portrait {
  position: relative;
  border: 0.75px solid #e3decf;
  border-radius: var(--radius-lg);
  overflow: hidden;
  max-width: 350px;
}

/* The source photo is square and the frame is taller than it is wide, so
   cover crops the left and right edges. The subject sits right of centre in
   the photo, so the focal point moves right with her — otherwise the crop
   leaves her off-centre in the frame. */
.founder__portrait img {
  width: 100%;
  aspect-ratio: 350 / 481;
  object-fit: cover;
  object-position: 55% center;
}

/* The scrim has to carry the caption on its own: the photo behind it is
   light in places, so a gradient that has already faded out by the time it
   reaches the name leaves white text on a near-white background. It stays
   near-opaque through the whole text block and only fades above it, which
   keeps both lines well past the 4.5:1 contrast floor whatever the photo
   is doing underneath. */
.founder__portrait figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--space-3xl) var(--space-lg) var(--space-lg);
  background: linear-gradient(
    0deg,
    rgba(16, 26, 41, 0.96) 0%,
    rgba(16, 26, 41, 0.9) 45%,
    rgba(16, 26, 41, 0.6) 75%,
    rgba(16, 26, 41, 0) 100%
  );
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.founder__portrait-name {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 1.75rem;
  color: var(--color-white);
}

.founder__portrait-role {
  font-size: var(--fs-body);
  color: rgba(255, 255, 255, 0.92);
}

@media (min-width: 1024px) {
  .founder__grid {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--space-4xl);
  }

  .founder__features {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* ---------------------------------------------------------------------
   CLIENT RESULTS — testimonial carousel
   --------------------------------------------------------------------- */
.results {
  background: var(--color-cream-100);
  padding-block: var(--space-6xl);
}

.results__intro {
  margin-bottom: var(--space-3xl);
}

.results__intro > .eyebrow {
  margin-bottom: var(--space-sm);
}

/* The viewport clips; the track slides. Replaces the old scroll container,
   so there is no horizontal scrollbar and movement happens a page at a time
   under the dots (or a swipe) rather than by free scrolling. Positioned so
   .testimonial-carousel__controls (a sibling, absolutely placed) can anchor
   to its bottom-right corner — which lines up with .testimonial-card__person
   on whichever card is showing, since every card is stretched to the same
   height and pinned there with justify-content: space-between. */
.testimonial-carousel__viewport {
  position: relative;
  overflow: hidden;
}

.testimonial-carousel__track {
  display: flex;
  gap: var(--space-xl);
  transition: transform var(--duration-slow) var(--ease-glide);
  will-change: transform;
  /* Let a vertical page scroll through, but claim horizontal drags. */
  touch-action: pan-y;
}

.testimonial-carousel__track.is-dragging {
  transition: none;
  cursor: grabbing;
}

@media (prefers-reduced-motion: reduce) {
  .testimonial-carousel__track {
    transition: none;
  }
}

/* Flat on the section background rather than a floating card — the divider
   above .testimonial-card__person is what separates quote from attribution
   now. justify-content: space-between pins that divider to the bottom of
   the card regardless of quote length, since every card in the flex row is
   stretched to the height of the tallest one. */
.testimonial-card {
  flex: 0 0 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

/* Icon beside the quote rather than stacked above it. align-items: flex-start
   keeps the mark pinned to the first line regardless of how tall the quote
   grows; the bottom margin here (not on the mark or the quote) is what
   separates the whole block from .testimonial-card__person below. */
.testimonial-card__body {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  margin-bottom: var(--space-xl);
}

.testimonial-card__mark {
  font-family: var(--font-quote);
  font-style: italic;
  font-size: 2.5rem;
  color: var(--color-gold-400);
  line-height: 1;
  flex-shrink: 0;
}

/* Groups a multi-paragraph quote (see the first testimonial) at a fixed
   16px rhythm. A single-paragraph quote skips this wrapper entirely. */
.testimonial-card__quote-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.testimonial-card__quote {
  /* Overrides the sitewide p { max-width: 75ch } (base.css) — this section
     wants the quote to use the full card width rather than the readability
     measure every other paragraph on the site is held to. */
  max-width: none;
  font-family: var(--font-body);
  font-style: italic;
  font-size: var(--fs-body-lg);
  line-height: var(--lh-body);
  color: var(--color-text-body);
}

@media (max-width: 639px) {
  .testimonial-card__quote {
    font-size: var(--fs-body);
  }
}

/* Right padding reserves room for .testimonial-carousel__controls, which
   overlays this row from outside the card (see .testimonial-carousel__viewport)
   rather than sharing its flex layout — the arrows are one global control,
   not per-slide, so they can't live inside the sliding track. */
.testimonial-card__person {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding-top: var(--space-lg);
  padding-right: 100px;
  border-top: 1px solid var(--color-border-subtle);
}

@media (max-width: 479px) {
  .testimonial-card__person {
    padding-right: 88px;
  }
}

.testimonial-card__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 45px;
  height: 45px;
  border-radius: 50%;
  background: var(--color-navy-800);
  color: var(--color-gold-400);
  font-weight: var(--fw-bold);
  font-size: var(--fs-body-sm);
  flex-shrink: 0;
}

.testimonial-card__name {
  display: block;
  font-style: normal;
  font-weight: var(--fw-semibold);
  font-size: var(--fs-body-sm);
  color: var(--color-navy-900);
}

.testimonial-card__role {
  display: block;
  font-size: 0.8rem;
  color: var(--color-text-body);
}

.testimonial-carousel__dots {
  display: flex;
  gap: var(--space-sm);
  margin-top: var(--space-lg);
}

.testimonial-carousel__dots button {
  width: 9px;
  height: 9px;
  border-radius: 5px;
  background: var(--color-grey-dot);
  transition: width var(--duration-base) var(--ease-standard), background var(--duration-base);
}

.testimonial-carousel__dots button.is-active {
  width: 22px;
  background: var(--color-gold-400);
}

/* Anchored to the viewport's own bottom-right corner (see
   .testimonial-carousel__viewport) rather than flowing after the track, so
   it stays aligned with .testimonial-card__person regardless of which card
   is currently showing. Height matches the avatar so the buttons land
   vertically centred on it. */
.testimonial-carousel__controls {
  position: absolute;
  right: 0;
  bottom: 0;
  height: 45px;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

/* Solid gold rather than the hairline outline these used to carry: a 1px
   gold border on the cream section background barely registered, and the
   arrows sit over a card footer rather than empty space. Navy on gold is
   the same pairing as the primary button, so they read as controls. */
.testimonial-carousel__nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--color-gold-400);
  color: var(--color-navy-900);
  flex-shrink: 0;
  transition: background var(--duration-base) var(--ease-standard),
    color var(--duration-base) var(--ease-standard);
}

@media (max-width: 479px) {
  .testimonial-carousel__nav {
    width: 36px;
    height: 36px;
  }
}

.testimonial-carousel__nav:hover {
  background: var(--color-gold-500);
  color: var(--color-navy-900);
}

/* Faded, but still solid enough to read as a button that is simply off —
   the old 0.35 left it invisible against the cream background. */
.testimonial-carousel__nav:disabled {
  background: var(--color-gold-tint);
  color: var(--color-gold-600);
  cursor: default;
}

.testimonial-carousel__nav--prev svg {
  transform: scaleX(-1);
}

/* ---------------------------------------------------------------------
   CASE STUDIES
   --------------------------------------------------------------------- */
.case-studies {
  background: var(--color-cream-100);
  padding-top: 36px;
  padding-bottom: 36px;
}

@media (max-width: 639px) {
  .case-studies {
    padding-top: 32px;
    padding-bottom: 44px;
  }
}

@media (min-width: 1024px) {
  .case-studies {
    padding-top: 32px;
    padding-bottom: 120px;
  }
}

.case-studies__heading {
  margin-bottom: var(--space-2xl);
}

.case-studies__heading > .eyebrow {
  margin-bottom: var(--space-sm);
}

.case-studies__heading .section-heading {
  margin-bottom: var(--space-xl);
}

/* The manual break keeps "successful petitions." on its own line at the h2
   size used from tablet up. At that size it also wraps "The evidence
   profiles behind" onto two lines on a narrow phone, orphaning "behind" —
   so below 640px the heading drops to --fs-display-md (the same size
   .section-heading--sm uses) and the break is dropped, letting all six
   words wrap on their own into two clean lines instead. */
@media (max-width: 639px) {
  .case-studies__heading .section-heading {
    font-size: var(--fs-display-md);
  }

  .case-studies__break {
    display: none;
  }
}

.case-studies__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2xl);
}

.case-study {
  padding-top: var(--space-lg);
  border-top: 1px solid rgba(12, 32, 60, 0.2);
}

.case-study:first-child {
  border-top: none;
  padding-top: 0;
}

/* Numbered in the markup for structure and assistive tech, but the design
   leads with the visa category instead — kept off-screen rather than
   removed so the heading hierarchy (01/02/03 before EB-1A) stays intact. */
.case-study__index {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.case-study__category {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: 1.5rem;
  color: var(--color-navy-700);
  margin-bottom: var(--space-xs);
}

@media (min-width: 1024px) {
  .case-study__category {
    font-size: 28px;
  }
}

.case-study__status {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--color-gold-400);
  margin-bottom: var(--space-md);
}

.case-study__status span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-gold-400);
}

.case-study__profile {
  font-size: var(--fs-body);
  color: var(--color-text-body);
  margin-bottom: var(--space-md);
}

.case-study__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-bottom: var(--space-md);
}

.case-study__tags span {
  border: 1px solid #d2cfcb;
  border-radius: var(--radius-pill);
  padding: 6px var(--space-md);
  font-size: 0.75rem;
  font-weight: var(--fw-semibold);
  color: var(--color-text-body);
}

.case-study__note {
  font-size: var(--fs-body);
  color: var(--color-text-body);
}

@media (min-width: 1024px) {
  .case-studies__grid {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-4xl);
  }

  .case-study {
    border-top: none;
    border-left: 1px solid rgba(12, 32, 60, 0.2);
    padding-top: 0;
    padding-left: var(--space-xl);
  }

  .case-study:first-child {
    border-left: none;
    padding-left: 0;
  }
}

/* ---------------------------------------------------------------------
   FAQ
   --------------------------------------------------------------------- */
.faq {
  background: var(--color-white);
  padding-block: var(--space-6xl);
}

.faq__intro {
  max-width: 680px;
  margin-bottom: var(--space-2xl);
}

.faq__intro > .eyebrow {
  margin-bottom: var(--space-sm);
}

.accordion-item {
  border-bottom: 1px solid var(--color-border-subtle);
}

.accordion-item__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  width: 100%;
  text-align: left;
  padding-block: var(--space-lg);
  font-size: 1.75rem; /* 28px — see .feature-list__title */
  font-weight: var(--fw-semibold);
  color: var(--color-navy-700);
}

@media (max-width: 639px) {
  .accordion-item__trigger {
    font-size: 1.5rem; /* 24px */
  }
}

.accordion-item__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  color: var(--color-navy-900);
  transition: transform var(--duration-base) var(--ease-standard);
}

.accordion-item.is-open .accordion-item__icon {
  transform: rotate(180deg);
}

.accordion-item__panel {
  overflow: hidden;
  padding-bottom: var(--space-lg);
}

.accordion-item__panel[hidden] {
  display: none;
}

.accordion-item__panel p {
  font-size: var(--fs-body);
  color: var(--color-text-body);
  max-width: none;
}

/* ---------------------------------------------------------------------
   CLOSING CTA
   --------------------------------------------------------------------- */
.closing-cta {
  background: var(--color-navy-800);
  padding-top: var(--space-4xl);
  padding-bottom: var(--space-2xl);
}

.closing-cta__card {
  max-width: 960px;
  margin-inline: auto;
  background: rgba(12, 32, 60, 0.8);
  border-radius: var(--radius-lg);
  padding: var(--space-3xl) var(--space-xl);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xl);
  text-align: center;
}

.closing-cta__heading {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-display-lg);
  color: var(--color-white);
  /* Pulls the 32px .closing-cta__card gap back to the sitewide 16px
     heading-to-lead rhythm without disturbing the gap below the text. */
  margin-bottom: -1rem; /* 32px gap - 16px = 16px */
}

.closing-cta__text {
  max-width: 46rem;
  font-size: var(--fs-body);
  color: var(--color-text-on-dark-muted);
}

.closing-cta__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-md);
}

/* ---------------------------------------------------------------------
   ATTORNEY PARTNERSHIP HERO (attorney.html)
   Figma: Attorney / node 3021:4595. The comp is a single 1440px column
   with 80px padding — .container already resolves to exactly that inline
   padding at 1440px, so the section only owns its block padding.
   --------------------------------------------------------------------- */
.attorney-hero {
  background: var(--color-white);
  padding-block: var(--space-4xl);
}

@media (max-width: 639px) {
  .attorney-hero {
    padding-block: 44px;
  }
}

.attorney-hero__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-lg);
}

.attorney-hero__title {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 1.6rem + 2.6vw, 3rem);
  font-weight: var(--fw-semibold);
  line-height: 1.21;
  letter-spacing: -0.01em;
  color: var(--color-navy-ink);
  /* The comp sets both the headline and the lead on a single line at 1440
     and lets them wrap naturally below that, so neither takes a measure cap. */
  max-width: none;
  /* Pulls the 24px .attorney-hero__inner gap back to the sitewide 16px
     heading-to-lead rhythm without disturbing the other gaps in this block. */
  margin-bottom: -0.5rem; /* 24px gap - 8px = 16px */
}

.attorney-hero__title-accent {
  color: var(--color-gold-accent);
}

.attorney-hero__lead {
  font-size: var(--fs-body-lg);
  line-height: var(--lh-body);
  color: rgba(10, 29, 56, 0.7);
  max-width: none;
}

@media (max-width: 639px) {
  .attorney-hero__lead {
    font-size: var(--fs-body);
  }
}

.attorney-hero__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.attorney-hero__list-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  font-size: var(--fs-body-lg);
  line-height: 1.5;
  color: rgba(10, 29, 56, 0.8);
}

@media (max-width: 639px) {
  .attorney-hero__list-item {
    font-size: var(--fs-body);
  }
}

.attorney-hero__list-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  /* Nudge the glyph onto the first line's optical centre. */
  margin-top: 2px;
}

.attorney-form {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  width: 100%;
  max-width: 635px;
  margin-top: var(--space-xs);
}

.attorney-form__input {
  flex: 1 1 260px;
  min-width: 0;
  height: 56px;
  padding-inline: var(--space-md);
  border: 1px solid rgba(10, 29, 56, 0.6);
  border-radius: 8px;
  background: var(--color-white);
  font-size: var(--fs-body-sm);
  color: var(--color-navy-ink);
  transition: border-color var(--duration-fast) var(--ease-standard);
}

.attorney-form__input::placeholder {
  font-size: var(--fs-body);
  color: var(--color-text-placeholder);
}

.attorney-form__input:hover {
  border-color: var(--color-navy-ink);
}

.attorney-form__input[aria-invalid="true"] {
  border-color: var(--color-red-dot);
}

/* Its own line, directly under the input, rather than the shared
   .attorney-form__status line after the button — a required-field error
   reads as belonging to the field it names, not as a submission outcome.
   flex-basis: 100% forces the line break in the row's flex-wrap layout;
   margin-top turns the row's 16px gap into the 8px this element needs
   below the input, while the 16px gap to the button after it is already
   correct as the container's default. Only ever occupies space when it
   has text — :empty keeps the input+button row untouched otherwise. */
.attorney-form__error {
  flex-basis: 100%;
  margin-top: calc(var(--space-xs) - var(--space-md));
  font-size: var(--fs-body-sm);
  color: var(--color-red-dot);
}

.attorney-form__error:empty {
  display: none;
}

.attorney-form__status {
  flex-basis: 100%;
  font-size: var(--fs-body-sm);
  color: var(--color-text-body);
}

.attorney-form__status:empty {
  display: none;
}

.attorney-form__status--error {
  color: var(--color-red-dot);
}

/* Once the field and the CTA stack, a full-width button keeps the left
   edge of the form from looking ragged. */
@media (max-width: 520px) {
  .attorney-form .btn {
    width: 100%;
  }
}

@media (min-width: 1024px) {
  .attorney-hero {
    /* 80px block padding, matching the comp. */
    padding-block: 5rem;
  }
}

/* ---------------------------------------------------------------------
   FREE RESOURCES (resources.html)
   Figma: Resources / node 3021:4698. Intro block over a stack of
   download rows. The comp pins "Download all five" absolutely at the
   right of the lead; here it is the second item of a flex row, which
   lands in the same place at 1440 and wraps under the lead on narrow
   screens instead of overlapping it.
   --------------------------------------------------------------------- */
.resources {
  background: var(--color-white);
  padding-block: var(--space-4xl);
}

@media (max-width: 639px) {
  .resources {
    padding-block: 44px;
  }
}

.resources__inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.resources__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.resources__title {
  margin-bottom: 0;
}

.resources__intro-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-lg);
}

.resources__lead {
  flex: 1 1 34rem;
  max-width: 833px;
  font-size: var(--fs-body-lg);
  line-height: 1.55;
  color: var(--color-text-body);
}

@media (max-width: 639px) {
  .resources__lead {
    font-size: var(--fs-body);
  }
}

.resources__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.list-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: var(--space-lg);
  background: var(--color-white);
  border: 1px solid #d6dee8;
  border-radius: var(--radius-lg);
}

@media (max-width: 639px) {
  .list-card {
    padding: 20px;
  }
}

.list-card__top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}

.list-card__download {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  cursor: pointer;
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-medium);
  color: var(--color-navy-800);
  text-decoration: underline;
  text-underline-position: from-font;
}

.list-card__download:hover {
  color: var(--color-gold-600);
}

.list-card__download img {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
}

.list-card__title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: var(--fw-semibold);
  line-height: 1.25;
  color: var(--color-text-heading);
  /* Tops up the card's 10px gap to the sitewide 16px heading-to-lead
     rhythm without disturbing the gap above the title. */
  margin-bottom: 6px; /* 10px gap + 6px = 16px */
}

/* Article card with a cover image: thumbnail beside the text rather than
   a full-bleed image above it. These cards are full-width rows, so a 16:9
   image across the top was taller than the copy it belonged to. Scoped
   with :has() so the resources page cards, which have no thumbnail, keep
   the plain stacked layout. */
.list-card:has(.list-card__thumb) {
  flex-direction: row;
  align-items: flex-start;
  gap: var(--space-lg);
}

.list-card__thumb {
  display: block;
  flex: 0 0 240px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-cream-100);
}

.list-card__thumb img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  transition: transform var(--duration-slow) var(--ease-standard);
}

.list-card:hover .list-card__thumb img {
  transform: scale(1.04);
}

/* The text column; min-width lets it shrink below its content width so a
   long title wraps instead of pushing the thumbnail narrower. */
.list-card__body {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
  gap: 10px;
}

/* Stacked on phones, where 240px beside the text leaves no usable measure. */
@media (max-width: 639px) {
  .list-card:has(.list-card__thumb) {
    flex-direction: column;
  }

  .list-card__thumb {
    flex: 0 0 auto;
    width: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .list-card__thumb img,
  .list-card:hover .list-card__thumb img {
    transition: none;
    transform: none;
  }
}

/* An article title that links out. Inherits the heading colour so the card
   looks unchanged at rest, and picks up gold on hover like every other
   link on the site. The arrow glyph sits inline at the end of the text so
   it wraps with the last word rather than stranding on its own line. */
.list-card__link {
  color: inherit;
  transition: color var(--duration-base) var(--ease-standard);
}

.list-card__link:hover,
.list-card__link:focus-visible {
  color: var(--color-gold-text);
}

.list-card__link .icon-inline {
  display: inline;
  vertical-align: baseline;
  margin-left: 2px;
}

.list-card__desc {
  max-width: none;
  font-size: var(--fs-body-sm);
  line-height: 1.625;
  color: var(--color-text-body);
}

@media (min-width: 1024px) {
  .resources {
    /* 80px block padding, matching the comp. */
    padding-block: 5rem;
  }
}

/* ---------------------------------------------------------------------
   ARTICLES (articles.html)
   Figma: Articals / node 3021:4494. Same list-row card as the resources
   page, carrying only a tag and a title, so this section owns nothing but
   the intro and the stack spacing.
   --------------------------------------------------------------------- */
.articles {
  background: var(--color-white);
  padding-block: var(--space-4xl);
}

@media (max-width: 639px) {
  .articles {
    padding-block: 44px;
  }
}

.articles__inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.articles__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.articles__title {
  margin-bottom: 0;
  letter-spacing: -0.009em;
}

.articles__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

@media (min-width: 1024px) {
  .articles {
    /* 80px block padding, matching the comp. */
    padding-block: 5rem;
  }
}

/* ---------------------------------------------------------------------
   FREE EVALUATION FORM (evaluation.html)
   Figma: Free evaluation / nodes 3021:4858, 3021:5034, 3021:5203. Three
   panels share one page; main.js swaps which is visible and drives the
   stepper, so the flow works without a round trip per step.
   --------------------------------------------------------------------- */
.evaluation {
  background: var(--color-white);
  padding-block: var(--space-3xl);
  /* Wider gutter than the sitewide --container-pad: the form reads better
     with more breathing room from the viewport edges than a text section
     does. Tapers with viewport width like --container-pad, just from a
     higher floor and ceiling. */
  --evaluation-pad: clamp(2.25rem, 12vw, 13rem);
}

.evaluation__inner {
  display: flex;
  flex-direction: column;
  gap: 32px;
  /* Narrower content measure than the sitewide 994px: a form reads better
     tighter than a text section, and the smaller number leaves more of the
     gutter doing the work of the premium, wide-margin feel. */
  max-width: calc(760px + var(--evaluation-pad) * 2);
  padding-inline: var(--evaluation-pad);
}

.evaluation__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-md);
}

/* Needed for the same reason .evaluation__result[hidden] and
   .evaluation__form[hidden] are: the block above sets `display: flex`,
   which outranks the UA stylesheet's `[hidden] { display: none }` and
   would otherwise leave a "hidden" heading on screen above the result. */
.evaluation__intro[hidden] {
  display: none;
}

/* The sitewide .eyebrow carries its own margin-bottom for use outside flex
   containers; here it would stack on top of .evaluation__intro's gap and
   double the space before the heading, so it's cancelled. */
.evaluation__intro .eyebrow {
  margin-bottom: 0;
}

.evaluation__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.4rem + 2.6vw, 3rem);
  font-weight: var(--fw-semibold);
  line-height: 1.21;
  letter-spacing: -0.01em;
  color: var(--color-navy-ink);
}

.evaluation__form {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}

/* ---- Progress stepper ----
   A grid of equal columns; each step draws the connector to its left as a
   pseudo-element, so the rail always spans exactly between two markers
   whatever the container width. */
.stepper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Spacing to the next panel comes from .evaluation__form's own flex gap;
     this margin-bottom used to stack on top of it and double the gap. */
  margin-bottom: 0;
}

.stepper__step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  text-align: center;
}

.stepper__step:first-child {
  align-items: flex-start;
}

.stepper__step:last-child {
  align-items: flex-end;
}

/* The rail runs from the previous marker's edge to this one's. The first
   marker sits at the start of its column and the last at the end, so the
   two gaps need different geometry — hence the per-child offsets rather
   than one symmetric rule. 32px is the marker width, 16px its radius. */
.stepper__step:not(:first-child)::before {
  content: '';
  position: absolute;
  top: 16px;
  height: 1px;
  background: var(--color-border-rail);
}

.stepper__step:nth-child(2)::before {
  left: calc(-100% + 32px);
  right: calc(50% + 16px);
}

.stepper__step:nth-child(3)::before {
  left: calc(-50% + 16px);
  right: 32px;
}

/* The rail leading into a reached step is filled in. */
.stepper__step.is-done::before,
.stepper__step.is-current::before {
  background: var(--color-text-body-strong);
}

.stepper__marker {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--color-border-rail);
  border-radius: 50%;
  background: var(--color-white);
  font-size: var(--fs-caption);
  line-height: 1;
  color: var(--color-step-idle);
  transition: background var(--duration-base) var(--ease-standard),
    border-color var(--duration-base) var(--ease-standard),
    color var(--duration-base) var(--ease-standard);
}

.stepper__label {
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-medium);
  letter-spacing: 0.07em;
  color: var(--color-step-idle);
}

/* The current step has to be the loudest thing in the rail. It used to be
   only an outlined circle while completed steps were filled navy, so the
   step you were on read as weaker than the ones behind you. Filled gold
   with a halo now, and its label is the only one at semibold. */
.stepper__step.is-current .stepper__marker {
  border-color: var(--color-step-current);
  background: var(--color-step-current);
  /* Navy, not white: white on this gold is 2.46:1, navy is 5.84:1. */
  color: var(--color-navy-800);
  box-shadow: 0 0 0 4px rgba(197, 160, 89, 0.22);
}

.stepper__step.is-current .stepper__label,
.stepper__step.is-done .stepper__label {
  color: var(--color-form-ink);
}

.stepper__step.is-current .stepper__label {
  font-weight: var(--fw-semibold);
}

.stepper__step.is-done .stepper__marker {
  border-color: var(--color-navy-800);
  background: var(--color-navy-800);
  color: var(--color-white);
  font-size: 0; /* hide the step number; the checkmark below replaces it */
}

/* Classic border-trick checkmark: a short rotated L drawn from two borders,
   so it stays crisp at any size without an icon asset. */
.stepper__step.is-done .stepper__marker::after {
  content: '';
  width: 8px;
  height: 4px;
  border-left: 1.5px solid var(--color-white);
  border-bottom: 1.5px solid var(--color-white);
  transform: rotate(-45deg) translate(1px, -1px);
}

/* ---- Panels ---- */
.evaluation__panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
  padding: 0;
  border: none;
  min-width: 0;
}

.evaluation__panel[hidden] {
  display: none;
}

.evaluation__panel-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.evaluation__panel-title {
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: var(--fw-semibold);
  line-height: 1.25;
  color: var(--color-form-ink);
}

.evaluation__panel-lead {
  max-width: none;
  font-size: var(--fs-body-lg);
  line-height: 1.625;
  color: var(--color-text-body);
}

@media (max-width: 639px) {
  .evaluation__panel-lead {
    font-size: var(--fs-body);
  }
}

.evaluation__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
}

.evaluation__stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.criteria-checks {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

/* .evaluation__panel's 32px flex gap puts this a full section-break away
   from the checklist it names — pulled back to the same 8px every other
   field error sits below its input, so it reads as attached to the group
   rather than as its own block. Only matters once it has text: .field__error
   is display:none while :empty, same as every other field error. */
.criteria-checks__error {
  margin-top: calc(var(--space-xs) - var(--space-xl));
}

.evaluation__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
}

.evaluation__actions .btn {
  flex: 0 1 196px;
}

.evaluation__status {
  max-width: none;
  font-size: var(--fs-body);
  color: var(--color-green-text);
}

.evaluation__status:empty {
  display: none;
}

/* The comp only draws the success state. A rejected submission — a rate
   limit, a validation error from the server, an unreachable API — cannot
   read as green confirmation, so it takes the same red the other two form
   status lines already use. */
.evaluation__status--error {
  color: var(--color-red-dot);
}

/* ---- Live result ----
   What /api/evaluate actually answers, shown on the page rather than only
   in the email. It is drawn with the .report-card component defined for
   the landing page's sample report, so the real result and the sample the
   landing page shows are the same object — the Evidence Gaps box below
   even reuses that component's own classes unmodified. Only the things
   the live data has and the sample does not — a breakdown line under the
   indicator, a sentence per criterion, and a next-steps list — are added
   here.

   The form is hidden once this appears: step 3 of 3 is finished, and the
   answer is what the page is for at that point. #evaluation-restart brings
   the empty form back. */
/* max-width narrower than the form's own 760px measure: a finished report
   reads better closer to a single editorial column, and scoping the width
   to the result region alone (rather than to .evaluation__inner) keeps the
   three-step form's own width untouched. */
.evaluation__result {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
  max-width: 650px;
  margin-inline: auto;
  width: 100%;
}

/* Both of these are needed, for the same reason .evaluation__panel[hidden]
   is: the block sets `display: flex`, which outranks the UA stylesheet's
   `[hidden] { display: none }` and leaves a "hidden" element on screen. */
.evaluation__result[hidden] {
  display: none;
}

.evaluation__form[hidden] {
  display: none;
}

/* Focused programmatically after a result lands, so a keyboard or screen
   reader user is placed on the answer rather than left where the submit
   button used to be. Not a control, so it draws no ring. */
.evaluation__result:focus {
  outline: none;
}

/* ---- Wide layout for the finished report ----
   The result is something to read, not to fill in, so once it is on screen
   it breaks out of the form's 760px measure and lays its two long lists in
   two columns. The card ends up roughly twice as wide and half as tall, so
   the verdict, the criteria and the next steps are reachable without a long
   scroll. :has() keys this to the result being visible, which leaves the
   three-step form at its own narrower measure. Browsers without :has() fall
   back to the single-column card above. */
@media (min-width: 1024px) {
  .evaluation__inner:has(> .evaluation__result:not([hidden])) {
    max-width: calc(1120px + var(--evaluation-pad) * 2);
  }

  .evaluation__result {
    max-width: 1120px;
  }

  /* align-items: start so a criterion with a short note does not stretch to
     the height of the tallest one in its row. */
  .evaluation__result .criteria-list--detailed,
  .evaluation__result .next-steps {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
    column-gap: var(--space-lg);
  }

  .evaluation__result .evidence-gaps {
    columns: 2;
    column-gap: var(--space-2xl);
  }

  .evaluation__result .evidence-gaps__label {
    column-span: all;
  }

  .evaluation__result .evidence-gaps__item {
    break-inside: avoid;
  }
}

/* ---- Overall outcome banner ----
   A single stacked column — label, verdict, note, then a breakdown line
   counting how each criterion below landed. Colour comes from outcomeTone()
   in main.js, keyed off the response's own wording rather than the score,
   so a 0/7 result reads amber ("insufficient evidence") and not red ("not
   supported") unless the backend's own text actually says so. */
.report-card__outcome {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-lg);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
}

.report-card__outcome-eyebrow {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.report-card__outcome-title {
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: var(--fw-semibold);
  color: var(--color-navy-900);
}

.report-card__outcome-desc {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-text-body);
}

.report-card__outcome-breakdown {
  margin-top: var(--space-2xs);
  font-size: var(--fs-body-sm);
  color: var(--color-text-body);
}

.report-card__outcome-count {
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
}

.report-card__outcome-count--positive {
  color: var(--color-green-text);
}

.report-card__outcome-count--develop {
  color: var(--color-amber-dot);
}

.report-card__outcome-count--unclear {
  color: var(--color-grey-dot);
}

.report-card__outcome-count--negative {
  color: var(--color-red-dot);
}

.report-card__outcome--positive {
  background: var(--color-green-bg);
  border-color: rgba(45, 184, 135, 0.24);
}
.report-card__outcome--positive .report-card__outcome-eyebrow {
  color: var(--color-green-text);
}

/* Amber, not grey and not red: insufficient evidence is a data gap, not a
   failed result. */
.report-card__outcome--caution {
  background: var(--color-gold-tint);
  border-color: rgba(203, 166, 72, 0.3);
}
.report-card__outcome--caution .report-card__outcome-eyebrow {
  color: var(--color-amber-dot);
}

.report-card__outcome--negative {
  background: rgba(228, 81, 44, 0.08);
  border-color: rgba(228, 81, 44, 0.24);
}
.report-card__outcome--negative .report-card__outcome-eyebrow {
  color: var(--color-red-dot);
}

/* ---- Criteria assessment (live result) ----
   Each row is numbered rather than dotted, with the criterion's name and
   status pill sharing a head row that wraps on narrow screens, and its
   explanatory sentence hanging beneath. Scoped to the modifier: the landing
   page's sample card keeps its plain dot-and-status row, which carries
   neither a note nor a number. */
.criteria-list--detailed {
  counter-reset: criterion;
}

.criteria-list--detailed .criteria-list__item {
  align-items: flex-start;
  gap: var(--space-md);
}

.criteria-list--detailed .criteria-list__item::before {
  counter-increment: criterion;
  content: counter(criterion, decimal-leading-zero);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-blue-tag-bg);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  color: var(--color-blue-tag);
  font-variant-numeric: tabular-nums;
}

.criteria-list__main {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  flex: 1 1 auto;
  min-width: 0;
}

.criteria-list__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}

.criteria-list__note {
  font-size: var(--fs-body-sm);
  line-height: 1.55;
  color: var(--color-text-body);
}

.criteria-list__pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  flex-shrink: 0;
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-pill);
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}

.criteria-list__pill-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.criteria-list__pill--positive {
  background: var(--color-green-bg);
  color: var(--color-green-text);
}
.criteria-list__pill--positive .criteria-list__pill-dot {
  background: var(--color-green-dot);
}

.criteria-list__pill--develop {
  background: var(--color-gold-tint);
  color: var(--color-amber-dot);
}
.criteria-list__pill--develop .criteria-list__pill-dot {
  background: var(--color-amber-dot);
}

.criteria-list__pill--unclear {
  background: rgba(107, 114, 128, 0.12);
  color: var(--color-grey-dot);
}
.criteria-list__pill--unclear .criteria-list__pill-dot {
  background: var(--color-grey-dot);
}

.criteria-list__pill--negative {
  background: rgba(228, 81, 44, 0.1);
  color: var(--color-red-dot);
}
.criteria-list__pill--negative .criteria-list__pill-dot {
  background: var(--color-red-dot);
}

/* ---- Numbered rather than bulleted (live result) ----
   Order is load-bearing for next steps: the backend guarantees the first
   is always consulting an attorney. Evidence Gaps needs no equivalent rule
   here — it reuses .evidence-gaps/.evidence-gaps__item from the landing
   page's sample report component unmodified. */
.next-steps {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  counter-reset: next-step;
}

.next-steps__item {
  display: flex;
  gap: var(--space-sm);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-navy-900);
}

.next-steps__item::before {
  counter-increment: next-step;
  content: counter(next-step, decimal-leading-zero);
  flex-shrink: 0;
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-bold);
  line-height: 1.85;
  color: var(--color-gold-300);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 520px) {
  .evaluation__actions .btn {
    flex: 1 1 100%;
  }

  .stepper__label {
    font-size: var(--fs-caption);
    letter-spacing: 0.04em;
  }
}

/* Below the sitewide 640px mobile breakpoint, drop the generous desktop/
   tablet gutter and match the sitewide 16px mobile page margin exactly. */
@media (max-width: 639px) {
  .evaluation {
    --evaluation-pad: var(--space-md); /* 16px */
  }
}

@media (min-width: 640px) {
  .evaluation__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .evaluation {
    padding-block: 5rem;
  }

  .evaluation__inner {
    gap: 60px;
  }
}

/* ---------------------------------------------------------------------
   LEGAL (terms.html, privacy.html)
   Long-form legal copy narrowed to a comfortable reading column and
   centered within the sitewide .container, with numbered sections
   separated by a hairline rule and a highlighted closing notice.
   --------------------------------------------------------------------- */
.legal {
  background: var(--color-white);
  padding-block: var(--space-4xl);
}

@media (max-width: 639px) {
  .legal {
    padding-block: 44px;
  }
}

@media (min-width: 1024px) {
  .legal {
    padding-block: 5rem;
  }
}

.legal__inner {
  display: flex;
  flex-direction: column;
}

.legal__intro {
  margin-bottom: var(--space-3xl);
}

.legal__intro > .eyebrow {
  margin-bottom: var(--space-sm);
}

.legal__meta {
  font-size: var(--fs-body-sm);
  color: var(--color-text-body);
}

.legal__meta strong {
  color: var(--color-text-body-strong);
  font-weight: var(--fw-semibold);
}

.legal__meta-label {
  margin-left: var(--space-lg);
}

.legal__sections {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

.legal-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.legal-section__title {
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: var(--fw-semibold);
  line-height: var(--lh-heading);
  color: var(--color-text-heading);
}

.legal-section p {
  max-width: none;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-text-body);
}

.legal-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.legal-list li {
  position: relative;
  padding-left: var(--space-lg);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--color-text-body);
}

.legal-list li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 0.65em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--color-text-body);
}

.legal-contact {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.legal-contact__label {
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  color: var(--color-text-heading);
}

.legal-contact p {
  color: #13294b;
}

.legal-contact p.legal-contact__value--muted {
  color: var(--color-text-body);
}

.legal-contact p .legal-link {
  color: var(--color-navy-700);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--duration-fast);
}

.legal-contact p .legal-link:hover {
  color: var(--color-gold-600);
}

.legal-notice {
  margin-top: var(--space-sm);
  padding: 20px;
  background: #fefcf9;
  border: 1px solid #e8d6b8;
  border-radius: var(--radius-md);
}

.legal-notice p.legal-notice__title {
  color: #13294b;
  margin-bottom: var(--space-xs);
}

.legal-notice p {
  color: var(--color-text-body);
}

/* ---------------------------------------------------------------------
   MOBILE SECTION RHYTHM

   On phones every landing section takes the same vertical step, top and
   bottom, so the page scrolls as one even rhythm. At desktop the 96–120px
   band is proportionate to the space around it; on a 375px screen it is
   most of a viewport, and the page reads as a scroll through empty colour
   fields between blocks of content.

   Was: 120px content bands, 96px banner, 64/40 closing CTA (unbalanced).
   Now: --section-pad-mobile on both ends of all of them.

   Tablet and desktop are untouched — this block only applies below the
   640px breakpoint the rest of the sheet uses.
   --------------------------------------------------------------------- */
@media (max-width: 639px) {
  .audience,
  .clarity,
  .sample-report,
  .stand-banner,
  .visa-categories,
  .work-product,
  .pricing,
  .founder,
  .results,
  .faq,
  .closing-cta {
    padding-block: var(--section-pad-mobile);
  }

  /* The hero carries its padding on the two bands inside it — the section
     itself sits at 0 — so they take the step rather than .hero.

     .hero__content also drops the full-viewport minimum: the copy stops
     well short of 100vh on a phone, so it was padding the fold with dead
     space rather than filling it. Height follows the content instead. */
  .hero__content {
    min-height: 0;
    padding-block: var(--section-pad-mobile);
    /* 56px gap from the navbar to the badge — bumped past the sitewide
       44px mobile section rhythm for breathing room right under the
       sticky header. Bottom padding stays at the shared 44px. */
    padding-top: 56px;
  }

  .visa-bar {
    padding-block: var(--section-pad-mobile);
  }

  .visa-bar__heading {
    margin-bottom: var(--space-xl); /* 32px, from the desktop 60px */
  }
}

/* ==========================================================================
   CONTACT (contact.html)

   Two columns on desktop: a fixed 448px intro rail carrying the heading and
   the direct channels, and the inquiry card taking the rest. Below 1024px
   the pair stacks and the card runs full width.
   ========================================================================== */
.contact {
  background: var(--color-white);
  padding-block: var(--space-5xl);
}

.contact__inner {
  display: grid;
  gap: var(--space-2xl);
  align-items: start;
}

@media (min-width: 1024px) {
  .contact__inner {
    grid-template-columns: 448px minmax(0, 1fr);
    gap: 30px;
  }
}

/* ---- Left rail ---- */
.contact__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.contact__intro-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

@media (min-width: 1024px) {
  .contact__intro-body {
    gap: 55px;
  }
}

.contact__heading-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

/* The comp sets this heading at 48px rather than the 56px every other
   section heading takes, so it clamps to its own ceiling. */
.contact__title {
  font-size: clamp(2rem, 1.6rem + 1.9vw, 3rem);
  color: var(--color-navy-ink);
  margin-bottom: 0;
}

.contact__lead {
  color: var(--color-text-placeholder);
  margin-bottom: 0;
}

.contact__channels {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}

/* Stacked, the page runs heading, then form, then the direct channels: on a
   phone the visitor wants to know where they have landed, then act, and
   only then look for another way through. The two rail wrappers go
   display: contents so their children become items of .contact__inner's own
   grid and can be ordered against the form between them — the alternative,
   moving .contact__channels out of the rail in the markup, would have to be
   undone for the desktop two-column layout. Placed after the rules it
   overrides, since a media query adds no specificity of its own. */
@media (max-width: 1023px) {
  .contact__intro,
  .contact__intro-body {
    display: contents;
  }

  .contact__heading-group {
    order: 1;
  }

  .contact-form {
    order: 2;
  }

  .contact__channels {
    order: 3;
  }
}

.contact-channel {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
}

.contact-channel__icon {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
}

.contact-channel__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  min-width: 0;
}

.contact-channel__title {
  font-family: var(--font-display);
  font-size: 1.75rem; /* 28px */
  font-weight: var(--fw-semibold);
  line-height: 1.2;
  color: var(--color-form-ink);
}

.contact-channel__link {
  font-size: var(--fs-body);
  line-height: 1.75;
  color: var(--color-form-ink);
  text-decoration: underline;
  word-break: break-word;
}

.contact-channel__link:hover {
  color: var(--color-gold-600);
}

.contact-channel__text {
  font-size: var(--fs-body-lg);
  line-height: 1.45;
  color: var(--color-text-body);
}

.contact-channel__cta {
  align-self: flex-start;
  height: 54px;
  margin-top: var(--space-md);
  padding-inline: 31px;
}

/* ---- Inquiry card ---- */
.contact-form {
  display: flex;
  flex-direction: column;
  gap: 30px;
  padding: var(--space-lg);
  border: 1px solid #c9d4e8;
  border-radius: 20px;
  background: var(--color-white);
}

.contact-form__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
}

@media (min-width: 640px) {
  .contact-form__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 30px;
  }

  .contact-form__field--full {
    grid-column: 1 / -1;
  }
}

/* 18px labels here rather than the evaluation form's 16px, per the comp. */
.contact-form .field__label {
  font-size: var(--fs-body-lg);
  line-height: 1.55;
}

.contact-form .field__control {
  border-color: #c3ccdf;
}

.contact-form__textarea {
  min-height: 147px;
  line-height: 1.5;
}

/* ---- Do-not-send notice ---- */
.contact-form__note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);
}

.contact-form__note-icon {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
}

.contact-form__note-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  min-width: 0;
}

.contact-form__note-title {
  font-size: var(--fs-body);
  font-weight: var(--fw-bold);
  line-height: 1.625;
  color: var(--color-form-ink);
}

.contact-form__note-text {
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--color-text-placeholder);
}

/* ---- Actions ---- */
.contact-form__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.contact-form__buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}

.contact-form__submit,
.contact-form__cancel {
  height: 54px;
  min-width: 196px;
}

.contact-form__submit[disabled] {
  background: var(--color-disabled-fill);
  color: var(--color-white);
  cursor: not-allowed;
}

.contact-form__submit[disabled]:active {
  transform: none;
}

.contact-form__status {
  font-size: var(--fs-body-sm);
  color: var(--color-text-body);
}

.contact-form__status:empty {
  display: none;
}

.contact-form__status--error {
  color: var(--color-red-dot);
}

@media (max-width: 520px) {
  .contact-form__submit,
  .contact-form__cancel {
    width: 100%;
  }
}

@media (max-width: 639px) {
  .contact {
    padding-block: var(--section-pad-mobile);
  }
}
