/* Getting Started only. Loaded after site.css. */

.gs-hero__lede {
  max-width: var(--measure-hero);
}

/* ------------------------------------------------------------- the fork */

/* Four, then two by two, then one. Never three across with a fourth stranded
   underneath it, which is what any auto-fitting track would produce. Two by two
   is the only balanced way to break four. */
.gs-routes {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  align-items: start;
}

/* Flex rather than grid: the button below uses margin-top:auto to sit on the
   card's bottom edge so the three actions line up, and an auto margin has no
   free space to absorb in a grid that packs its rows to the start. */
.gs-route {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  height: 100%;
  padding: 26px 24px 24px;
  border: 1px solid var(--border-subtle);
  border-top: 3px solid rgb(var(--route, 0 0 0));
  border-bottom: 3px solid rgb(var(--route, 0 0 0));
  border-radius: var(--radius);
  background: rgb(var(--route, 255 255 255) / 0.07);
}

/*
 * The four routes are equally legitimate, so none is styled as the
 * recommended one. They are told apart by hue: a cap at each end, a 7% wash
 * of the same hue behind the card, and the cost pill's hairline. The same
 * treatment the Shield tiers use further down this page.
 *
 * One channel triplet per card drives all three, so the cap, the wash and the
 * pill can never drift apart. Channels rather than a hex because the wash
 * needs an alpha and rgb(var(--x) / 0.07) is the only way to get one out of a
 * single custom property.
 *
 * This replaced solid fills. They worked, but four saturated blocks were the
 * loudest thing on the page and every piece of text and every button inside
 * them needed its own colour to survive: one ink per card, a bordered pill per
 * card, a filled button per card and a recoloured focus ring per card, because
 * the shared ring measured 1.28:1 against the yellow and vanished against the
 * blue. At 7% over white, the shared .h3, .body, .btn and focus ring are all
 * correct as they stand.
 */
.gs-route--fixit {
  --route: 255 228 0; /* --fixit-yellow #ffe400 */
}

.gs-route--two {
  --route: 171 66 137; /* --sam #ab4289 */
}

.gs-route--three {
  --route: 25 118 210; /* --primary #1976d2 */
}

.gs-route--four {
  --route: 0 109 119; /* --teal #006d77 */
}

/* The pill sits above the eyebrow question rather than beside it. Stacked, the
   longest label gets the card's whole width instead of what is left over next
   to a line of text, which is what lets it hold one line at the narrowest
   four-across card. */
.gs-route__head {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

/* The question above the heading. It was the route number, and it shared a row
   with the pill; now it has the line to itself and can wrap like ordinary text. */
.gs-route__n {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/*
 * A ring, never a fill.
 *
 * Measured against these three backgrounds: a 20% wash of the card's own ink
 * behind the label drops it to 3.74:1 on --sam and 3.30:1 on TPN blue, and this
 * is 11px type. Left transparent, the label sits on the card's own fill, where
 * it measures 11.20 / 5.42 / 4.60:1 - the same values the eyebrow beside it
 * already passes on, because it is the same ink on the same ground.
 *
 * The ring carries the shape instead. At 70% of the ink it measures 4.99 / 3.48
 * / 3.06:1 against the three fills, which clears the 3:1 that a non-text
 * boundary needs, TPN blue being the tight one.
 */
.gs-route__cost {
  /* A step down from the eyebrow under it, and nowrap.

     10px is not arbitrary. This is a status chip, not a heading, so it should
     read as the smaller of the two labels - and it has to hold "Annual
     Membership Required", 26 tracked uppercase characters, on one line inside
     the 231px a four-across card leaves. At 11px that measures 234px and breaks;
     at 10px with the tracking eased to 0.05em it is 216px and holds. */
  flex: 0 0 auto;
  max-width: 100%;
  padding: 3px 9px;

  /* The hairline carries the card's hue. The label itself stays body ink:
     the colour is on the border, not behind the words, so nothing needs
     re-measuring for contrast. */
  border: 1px solid rgb(var(--route, 0 0 0) / 0.55);
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.05em;
  line-height: 1.5;
  text-transform: uppercase;
  white-space: nowrap;
}

.gs-route__logo {
  width: 152px;
  margin-top: 2px;
}

/* Push the button to the bottom so the four cards' actions line up even when
   the copy above them differs in length. */
.gs-route .btn {
  justify-self: start;
  margin-top: auto;
}

@media (max-width: 1239px) {
  .gs-routes {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 639px) {
  .gs-routes {
    grid-template-columns: 1fr;
  }
}

/* --------------------------------------------------- start before you pay */

.gs-free {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 40px;
  align-items: center;
}

.gs-free__panel {
  padding: 22px 24px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  background: #fff;
}

/* --text-link, not --primary. This eyebrow sits on --grey-100, where --primary
   measures 4.22:1 and misses AA for 12px text. Same swap as the stage
   accordions' See more control, for the same reason. */
.gs-free__eyebrow {
  color: var(--text-link);
}

.gs-free__title {
  margin-bottom: 6px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.gs-free__list {
  display: grid;
  gap: 2px;
  list-style: none;
}

.gs-free__list li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 10px 0;
  font-size: 15px;
  line-height: 1.5;
}

.gs-free__list li + li {
  border-top: 1px solid var(--border-subtle);
}

.gs-free__list .material-icons-outlined {
  flex: 0 0 auto;
  color: var(--primary);
}

@media (max-width: 900px) {
  .gs-free {
    grid-template-columns: 1fr;
    gap: 24px;
  }
}

/* ------------------------------------------------------------ the journey */

/* The stepped ladder. Each rung is inset from the top of the row by one 34px
   notch more than the one after it, so the tops step up while the bottoms stay
   flush. The lift is dropped below 1000px, where the grid is one column and
   there is nothing for the stepping to line up against.

   Height is derived, not declared. Each rung stretches to the row, the card
   fills whatever the rung's lift leaves, and the row is as tall as the tallest
   lift-plus-content - so the ladder is exactly as tall as its fullest card
   needs and no taller.

   This replaced four hardcoded minimum heights, which were both too big and too
   small: they left 77px of dead space inside the Gold Star card at 1280px, and
   at 1001px, where the text wraps harder, that same card needed 532px against a
   468px floor and pushed the row out of step. A pixel floor cannot be right at
   every width; letting the content set it is right at all of them. */
.gs-ladder {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  list-style: none;
}

.gs-rung {
  position: relative;
  display: flex;
  flex-direction: column;
  padding-top: var(--rung-lift);
}

.gs-rung--1 {
  --rung-lift: 102px;
}

.gs-rung--2 {
  --rung-lift: 68px;
}

.gs-rung--3 {
  --rung-lift: 34px;
}

.gs-rung--4 {
  --rung-lift: 0;
}

/* The chevron between two rungs, pinned to the top card's head row. */
/* The chevron between two rungs. Centered on the 20px gutter and wider than it,
   so it sits over both cards rather than in the space between them: at 46px it
   overlaps each neighbour by 13px, which is what makes it read as a link from
   one tier to the next instead of a loose ornament.
   Centered by pulling it back half its own width from the gutter center, not by
   a translate, so the box the shadow and border are drawn on is the real one. */
.gs-rung__arrow {
  --arrow-size: 46px;

  position: absolute;
  right: calc(-10px - var(--arrow-size) / 2);
  top: calc(var(--rung-lift) + 92px);
  z-index: 2;
  display: grid;
  place-items: center;
  width: var(--arrow-size);
  height: var(--arrow-size);
  border: 1px solid var(--border-subtle);
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-card);
  color: var(--navy-800);
}

.gs-tier {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  width: 100%;
  border: 1px solid var(--border-subtle);
  border-top: 3px solid var(--border-strong);
  border-bottom: 3px solid var(--border-strong);
  border-radius: var(--radius);
  background: #fff;
}

.gs-tier--blue {
  border-top-color: var(--badge-blue);
  border-bottom-color: var(--badge-blue);
  background: #f2f6fc;
}

.gs-tier--silver {
  border-top-color: var(--badge-silver);
  border-bottom-color: var(--badge-silver);
  background: #f4f6f8;
}

.gs-tier--gold {
  border-top-color: var(--gold-700);
  border-bottom-color: var(--gold-700);
  background: #fdf8ec;
}

.gs-tier--gold-star {
  border-top-color: var(--gold-500);
  border-bottom-color: var(--gold-500);
  background: #fcf4e0;
}

/* Flex, not grid, so the margin-top:auto on the definition list below can dock
   it to the bottom edge. Under `display: grid; align-content: start` the rows
   pack to the top and the card's slack sits outside every track, so the auto
   margin has nothing to absorb: the rule reads as if it works while the footer
   actually sits wherever the description happens to end. The tiers run to
   different lengths and Gold Star carries an extra paragraph, so the fixed
   `auto 1fr auto` row template that docks the same footer
   is not an option here. */
.gs-tier__body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 22px 22px 18px;
}

.gs-tier__head {
  display: flex;
  gap: 16px;
  align-items: center;
}

.gs-tier__badge {
  width: 52px;
  flex: 0 0 auto;
}

.gs-tier__eyebrow {
  display: block;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.gs-tier__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 600;
  color: var(--text-heading);
}

/* One sentence on what the shield level means. The process detail lives in the
   stages below, so this says what holding the shield tells a content owner and
   nothing about how to get it. */
.gs-tier__desc {
  font-size: 15px;
  line-height: 1.55;
  color: var(--text-body);
}

/* margin-top: auto against the flex column above, so the table docks to the
   bottom edge whatever length the sentence runs to. */
.gs-tier__meta {
  display: grid;
  gap: 12px;
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--border-subtle);
}

.gs-tier__row dt {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.gs-tier__row dd {
  margin: 2px 0 0;
  font-size: 14px;
  color: var(--text-body);
}

/* The note and the call to action share one row: the button sits on the
   right of the text rather than under it, so closing the ladder costs one line
   of height instead of three. It wraps below the text when there is no room for
   both, which is where the row gap applies. */
.gs-journey__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px 32px;
  margin-top: 26px;
}

.gs-journey__notes {
  display: grid;
  gap: 8px;
  max-width: var(--measure);
}

/* The stage list's call to action has no text beside it, so it stays on its own
   line and only needs air above. */
/* The one action closing the paid phase, so it sits at the end of the block
   in both directions: the right edge of the wrap, and far enough below the
   last stage that it reads as the section signing off rather than as an
   eighth item in the list. */
.gs-phase__cta {
  justify-content: flex-end;
  margin-top: 40px;
}

@media (max-width: 1000px) {
  .gs-ladder {
    grid-template-columns: 1fr;
  }

  .gs-rung {
    padding-top: 0;
  }

  .gs-rung__arrow {
    display: none;
  }
}

/* -------------------------------------------------------- what happens */

/* The two phases used to be two cards inside one band, the paid one turned
   navy so the point at which money starts was impossible to miss. They are two
   sections now, and the band's own color does that job, so the card chrome that
   was standing in for a section boundary is gone. */

.gs-phase__head {
  display: grid;
  gap: 8px;
  margin-bottom: 24px;
}

.gs-phase__label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  justify-self: start;
  padding: 5px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: #fff;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--navy-800);
}

.gs-phase__title {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 600;
  color: var(--navy-800);
}

/* No measure cap: this is section sub-text under a full-width heading, so it
   fills its column. See .section__head > p in site.css. */
.gs-phase__note {
  font-size: 15px;
  line-height: 1.6;
  color: var(--text-secondary);
}

.gs-stages {
  list-style: none;
  counter-reset: stage;
}

.gs-stages[start='5'] {
  counter-reset: stage 4;
}

.gs-stage {
  position: relative;
  counter-increment: stage;

  /*
   * One number for the gutter the circle sits in. The <li> pads by it, the
   * sticky summary pulls back out over it by exactly the same amount, and it
   * narrows to 46px below 640. Hardcoding it in both places is what put the
   * rail 10px off the circles on a phone: the padding dropped to 46 and the
   * summary's -56px pull did not, so the circle went 10px further left while
   * the rail stayed where it was.
   */
  --gs-gutter: 56px;

  /* 12, not 20. The other 8 moved into .gs-stage__summary's own padding so it
     is inside the sticky bar rather than above it; 12 + 8 keeps the circle
     exactly where it was. */
  padding: 12px 0 20px var(--gs-gutter);
}

.gs-stage:last-child {
  padding-bottom: 4px;
}

/*
 * The number rides with the title.
 *
 * It was .gs-stage::before, absolutely positioned against the <li>. Once the
 * title became sticky that pinned the circle to the top of the stage while
 * the words travelled down it, so the two came apart. On the summary it is
 * carried by the same sticky box.
 *
 * counter(stage) still resolves: counters inherit down the tree, and the
 * increment is still on the <li>.
 *
 * left:0 lands it on the stage's left edge because the summary is pulled out
 * into that gutter by its negative margin below.
 */
.gs-stage__summary::before {
  content: counter(stage);
  position: absolute;
  left: 0;
  top: 8px;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: #fff;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--navy-800);

  /* For the data-current highlight further down. A short fade reads as the
     circle agreeing with the bar rather than blinking; the site-wide
     prefers-reduced-motion rule cuts it to 0.01ms. */
  transition:
    background-color var(--dur-micro) ease,
    border-color var(--dur-micro) ease,
    color var(--dur-micro) ease;
}

/* A stage that earns a Shield gets a filled marker, so the four moments that
   change your tier are findable by scanning the left rail alone. */
.gs-stage--shield .gs-stage__summary::before {
  background: var(--navy-800);
  border-color: var(--navy-800);
  color: #fff;
}

/* ------------------------------------------------------------- a stage */

/* Every stage is open. There is no <details>, no <summary> and no control: the
   copy is short enough that hiding it behind a click only cost a click, so all
   seven read straight down the page.

   .gs-stage__summary is a plain wrapper now, with no rule of its own. It held
   the title beside a one-line gist in a two-column grid, back when a collapsed
   stage showed only those two. Expanded, that gist restated the first sentence
   of the detail below it in all seven stages, so it is gone and the title is
   the wrapper's only child. The 12px above .gs-stage__detail is what separates
   them. */

/*
 * The step's own bar, stuck under the progress bar.
 *
 * While a reader is inside a stage its number and title hold the top of the
 * screen, directly under the bar that says which step it is. Sticky rather
 * than fixed this time, and it works where the progress bar could not: this
 * one is confined to a single <li>, which is exactly the span it should hold
 * for, so it releases itself at the stage's bottom edge with no script.
 *
 * top is the header plus the progress bar, from the same --gs-progress-h the
 * bar's own height and the region's scroll-margin use, so the three cannot
 * drift apart.
 *
 * The negative margin pulls the bar out over the 56px gutter the circle sits
 * in and the padding puts the text back, so the background spans the number
 * as well as the words. Without it the detail below would scroll up through
 * the gap between the circle and the title.
 *
 * The background matches the section it is in, so the bar reads as the page
 * holding still rather than as a new surface: --grey-100 on the free stages,
 * white on the membership ones. Anything transparent would let the copy
 * underneath show through the title.
 *
 * z-index 2 puts it over the stage's own content and under the progress bar,
 * which is 20.
 */
.gs-stage__summary {
  position: sticky;
  top: calc(var(--header-h) + var(--gs-progress-h));
  z-index: 2;
  margin-left: calc(-1 * var(--gs-gutter));
  padding: 8px 0 10px var(--gs-gutter);
  background: #fff;

  /* The only horizontal in a stage now. It closes the sticky bar, which is
     what stops copy scrolling under it from being sliced mid-line with no
     edge, and it is the separation between stages that the divider used to
     carry. */
  border-bottom: 1px solid var(--border-subtle);
}

.section--grey .gs-stage__summary {
  background: var(--grey-100);
}

/* `flow-root` so the block contains its floated badge. It was a two-column
   grid, and that was wrong: a grid item spanning every row makes those rows tall
   enough to hold it, so a 175px badge beside two lines of copy stretched the
   rows and pushed the bullets and the callout down the page. A float takes the
   badge out of flow entirely - the copy wraps beside it and nothing moves. */
.gs-stage__detail {
  display: flow-root;
  margin-top: 12px;
}

.gs-stage__title {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--text-heading);
}

.gs-stage__points {
  display: grid;
  gap: 8px;
  margin-top: 12px;
  padding-left: 22px;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--text-secondary);
}

/*
 * A chevron rather than a disc, set through ::marker so the list stays a list
 * and no span has to be added to thirty-odd items. ::marker only accepts a
 * handful of properties, and content, color and font-weight are all among them.
 *
 * The gold is decoration and never carries meaning, so it is exempt from the
 * text contrast floor - the words beside it are what has to be readable, and
 * they are unchanged.
 */
.gs-stage__points li::marker {
  content: '\203A  ';
  color: var(--gold-500);
  font-weight: 700;
}

/* The colors here are stated, not inherited. This is a cream panel, so on the
   blue band it would otherwise take that band's white text and its white links
   onto cream, which is worse than the dark-on-blue it was there to fix. */
/* Both selectors: the bare one states the rule, and the second one has to
   out-specify `.section--blue a:not(.btn)` in site.css, which is (0,2,1) and
   would otherwise put white links on this cream. */
.gs-stage__note a,
.section--blue .gs-stage__note a {
  color: var(--text-link);
  text-decoration: underline;
}

/* White with a blue edge. It was cream with a gold one, which read as a warning
   rather than as an aside - and on the blue band a cream panel was the one thing
   on the page fighting its surroundings. White works on both grounds. */
.gs-stage__note {
  /* Clears the shield.

     A float pushes LINE boxes aside, not block boxes: without this the note's
     white panel slid underneath the badge while only its text wrapped, so the
     shield sat on top of the callout. Clearing puts the full-width panel below
     the badge, which is where a closing aside belongs anyway. */
  clear: right;
  margin-top: 12px;
  padding: 12px 14px;
  border-left: 3px solid var(--primary);
  background: #fff;
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--text-body);
}

/*
 * The shield a stage earns, as a panel in the second column.
 *
 * It was a 30px icon on the same line as the words, which is smaller than the
 * body text beside it - a shield at that size is a bullet, not a badge. 76px is
 * the size at which the tier is readable at a glance, which is the whole job of
 * the thing.
 *
 * A panel rather than loose elements, because it has to hold the top-right of a
 * block of prose without looking dropped there. The grey ground is the same one
 * the shield badges sit on elsewhere on the site; the navy outlines vanish on a
 * white surface.
 */
.gs-stage__earns {
  /* First in source order, because a float only affects what follows it. */
  float: right;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 148px;
  margin: 0 0 12px 28px;
  padding: 18px 16px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  background: var(--grey-100);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
  color: var(--text-muted);
}

.gs-stage__earns img {
  width: 76px;
}

.gs-stage__earns strong {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--navy-800);
}

/* One column below the point where a 148px panel plus readable prose stops
/* Below the width where a 148px panel plus readable prose stops fitting, the
   badge stops floating and sits above the copy, left aligned with it. */
@media (max-width: 720px) {
  .gs-stage__earns {
    float: none;
    margin: 0 0 14px;
  }

  /*
   * A rail joining the numbered circles.
   *
   * 720px is where .gs-stage__earns unfloats just above, so from here down a
   * stage is one narrow column and the circles are the only thing holding the
   * left edge. Wider than this they sit against a two-column block that gives
   * them their own alignment, and the line is redundant furniture.
   *
   * A segment per stage, and it spans the gap between two stages rather than
   * running the length of one: it starts below its own circle and stops short
   * of the hairline that divides the stage from the next. So it reads as a
   * link from this number to the one under it, and it neither crosses the
   * number nor collides with the rule.
   *
   * 62px is the circle's bottom edge plus 8: 20px of padding above the circle
   * and 34px of circle is 54. The 8px at the other end matches it, so the
   * segment sits evenly in the space between two stages. That space used to
   * end in a divider and no longer does - the rule under the number and title
   * carries the separation now - so the 8px is breathing room rather than
   * clearance.
   *
   * The segment belongs to the space AFTER a stage, so every stage has one
   * except the very last. "Last" is not :last-child, though: the seven stages
   * are two <ol>s in two sections, and stage 4 is the last child of the first
   * one while still having stage 5 under it. Keyed off [start] instead, which
   * the second list already carries because it continues the numbering at 5 -
   * so its last child is the last stage on the page, and the first list's is
   * not.
   *
   * 16px puts a 2px line on the circles' centre line, which is 17px in from
   * the stage's left edge. That holds at 640 too, where only the stage's
   * padding changes and the circle keeps its position.
   */
  .gs-stage::after {
    content: '';
    position: absolute;
    top: 62px;
    bottom: 8px;
    left: 16px;
    width: 2px;
    background: var(--border-default);
  }

  /* Stage 4 closes its section but not the sequence, and :last-child trims
     its padding to 4px, so the shared 8px would end the rail inside its own
     padding. It runs to the foot of the stage instead and carries the eye on
     to the next section. */
  .gs-stages:not([start]) .gs-stage:last-child::after {
    bottom: 0;
  }

  /* Stage 7. Nothing follows it. */
  .gs-stages[start] .gs-stage:last-child::after {
    content: none;
  }
}

@media (max-width: 640px) {
  .gs-phase__head,
  .gs-stages {
    padding-left: 18px;
    padding-right: 18px;
  }

  .gs-stage {
    --gs-gutter: 46px;
  }
}

/* ------------------------------------------------------------- resources */

/* `.card` in site.css supplies the surface but no display, and an <a> is inline
   by default. The home page's own `.audiences .card` rule is what makes those
   behave; outside it a bare .card collapses into flowing text. That is exactly
   what happened here when this block went missing. */
.gs-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px;
}

.gs-cards .card {
  display: grid;
  align-content: start;
  gap: 12px;
  color: var(--text-body);
}

.gs-cards .card:hover {
  box-shadow: var(--shadow-card-hover);
  text-decoration: none;
}

.gs-cards__logo {
  width: 128px;
  margin-bottom: 2px;
}

/* ------------------------------------------------------- pull quotes */

/* The line that carries the point of a section, set larger than the prose and
   marked with the gold rule the 360 Strong quote uses. Appears twice: under The
   Journey heading and inside stage 6. */

/* The fees link above the Stages 5-7 heading. On the blue band it takes the
   band's white ink, like every other link there. */
.gs-phase__link {
  margin-top: 2px;
  font-size: 15px;
}

/* --------------------------------------------------- process progress bar */

/*
 * The bar's height, in one place. Three things need to agree on it: the bar
 * itself, the scroll-margin that keeps an anchor from landing under it, and
 * the sticky step bar that parks directly beneath it.
 */
:root {
  /* The bar's full border-box height, measured rather than added up: 8px of
     padding above the row, the row, the 3px track, 8px below it and a border
     at each end. It was 45 before the bottom padding went on, which also left
     the step bar 1px under the bar's own edge. */
  --gs-progress-h: 54px;
}

/*
 * The bar that tracks a reader through "The Process, Step by Step". Built by
 * js/where-to-start.js, which is why nothing here is in the markup: with JS
 * off the section is seven numbered stages under two headings and this rule
 * set never matches anything.
 *
 * Fixed rather than sticky. A sticky bar is released at its own parent's
 * bottom, and the stages are two sibling sections - so it would let go at the
 * free/paid seam, the one boundary it exists to narrate. The wrapper that
 * would fix that would take both sections out of `main > section`, which is
 * how site.js finds the seams for its jump chevrons.
 */
.gs-progress {
  position: fixed;
  top: var(--header-h);
  right: 0;
  left: 0;

  /* Under the header, which is 40, and under the drawer. Above the page. */
  z-index: 20;

  /*
   * White, with the separation carried by a rule rather than by a fill.
   *
   * A tint was tried and reverted: --grey-200 does separate from both the
   * white header above and the --grey-100 free section below, but a filled
   * strip reads as a band of chrome rather than as part of the page, and it
   * dragged the phase colour down with it - --primary is 4.60:1 on white and
   * only 3.72:1 on grey-200, which fails at 11px.
   *
   * A rule and a shadow do it instead. The rule is --primary rather than a
   * neutral: it is the one line between two white surfaces, and a coloured
   * hairline separates at 1px where a grey one needed 2. The shadow is wide
   * and soft rather than tight, so the bar lifts off the content under it
   * instead of looking stuck to it.
   *
   * Note the rule does NOT follow the phase - it is blue over the gold half
   * too. The label and the track carry that.
   */
  background: #fff;
  border-top: 1px solid var(--primary);
  border-bottom: 1px solid var(--border-subtle);
  box-shadow: 0 0 6px rgb(0 0 0 / 12%);

  /* Under the track, which .gs-progress__inner deliberately runs flush to.
     Keep --gs-progress-h in step with this: it is the number the sticky step
     bar parks against and the scroll-margin clears. */
  padding-bottom: 8px;

  /* Out of the way until the reader is in the section. visibility, not
     display, so the height can be measured for the anchor line before it is
     ever shown. */
  visibility: hidden;
  opacity: 0;
  transition:
    opacity var(--dur-micro) ease,
    visibility var(--dur-micro) ease;
}

.gs-progress[data-visible] {
  visibility: visible;
  opacity: 1;
}

/* The page's own column, so the bar's text starts where the stages' does. */
.gs-progress__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 8px 32px 0;
}

.gs-progress__row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 7px;
}

.gs-progress__phase {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;

  /* 4.60:1 on white, which is what the bar is again. The gold below is
     --gold-900 rather than the --gold-700 the tier dots use, because 700
     measures 3.20:1 - large text only. --gold-900 is 5.01:1. */
  color: var(--primary);
}

.gs-progress__sep {
  flex: 0 0 auto;
  color: var(--border-strong);
}

/* Truncates rather than wraps: a second line would change the bar's height
   mid-scroll, which moves the anchor line the current stage is chosen by. */
.gs-progress__step {
  overflow: hidden;
  font-size: 13px;
  color: var(--text-secondary);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gs-progress__track {
  height: 3px;
  background: var(--grey-200);
  border-radius: 2px;
}

.gs-progress__fill {
  width: 0;
  height: 100%;
  background: var(--primary);
  border-radius: 2px;
  transition:
    width var(--dur-micro) ease,
    background-color var(--dur-micro) ease;
}

.gs-progress[data-phase='paid'] .gs-progress__phase {
  color: var(--gold-900);
}

.gs-progress[data-phase='paid'] .gs-progress__fill {
  background: var(--gold-700);
}

/* An anchor into either phase has to clear the bar as well as the header,
   because the bar is up whenever the reader is inside this region. The
   attribute is set by the script, so this only applies when the bar exists. */
[data-gs-progress-region] {
  scroll-margin-top: calc(var(--header-h) + var(--gs-progress-h) + 9px);
}

@media (max-width: 640px) {
  .gs-progress__inner {
    padding: 8px 20px 0;
  }

  /* The phase label is the long half of this line - "Free: No Membership
     Required" at 0.16em of tracking - so on a phone the stage title truncated
     to about two characters. "Step 5 of 7" on its own is the part that still
     says something at that width; the title is on screen anyway, a few hundred
     pixels down. */
  .gs-progress__title {
    display: none;
  }

  .gs-progress__count {
    white-space: nowrap;
  }
}

/* Nothing about where the viewport was belongs on paper. */
@media print {
  .gs-progress {
    display: none;
  }
}

/* ------------------------------------------- the stage the reader is on */

/*
 * js/where-to-start.js puts data-current on whichever stage the progress bar
 * is reporting, and takes it off when the bar goes. So this only ever paints
 * while the bar is up, and with JS off no stage is ever marked.
 *
 * Two treatments, and the split is the circle's own: 1-3 are outlines, so
 * their outline and number turn blue; 4-7 are .gs-stage--shield and already
 * filled --navy-800, so their fill turns blue with the number reversed out.
 * The active state follows how each circle is drawn rather than which section
 * it is in, which means it never has to undo the shield fill - an earlier
 * version split on the section and had to reset stage 4 to white to keep its
 * number legible, quietly cancelling the marker that says it earns a tier.
 *
 * Both measure 4.60:1 - --primary on white and white on --primary are the
 * same ratio - against the 4.5 the 15px/600 number needs.
 */
.gs-stage[data-current] .gs-stage__summary::before {
  border-color: var(--primary);
  color: var(--primary);
}

.gs-stage--shield[data-current] .gs-stage__summary::before {
  background: var(--primary);
  color: #fff;
}
