/* Quote Tool Phase 2 — copy of quote-tool.css, loaded only on the [quote_tool_phase2] page. Edit freely; the live tool loads the original. */
/**
 * Quote tool — the 3-step membership explorer, restyled 2026-08 to the approved
 * join/quote design (Claude Design project "Join Quote Tool Final").
 *
 * Ported from ymcacva.org. Two things are deliberately different from the source:
 *
 * 1. No form-id selectors. CVA hardcodes its form id 2 (#field_2_26,
 *    #gform_submit_button_2, …); this site's form id is different, so everything
 *    here is scoped to #quote-tool with attribute selectors.
 * 2. No Bootstrap. functions/dequeue.php deregisters it, so .d-none does not
 *    resolve — .quote-tool__hidden replaces it.
 *
 * Tokens are declared here rather than in assets/css/general/defaults.css, which
 * is generated by build-notes/header-footer/extract_css.py and overwritten on
 * every run. Values come verbatim from the extracted ymcachicago.org design
 * system (design-system/foundations/tokens.css).
 *
 * Layout notes:
 * - Pages are identified by ROLE via :has() — never by GF's numbered ids. The
 *   intro page is the one holding .qt-copy-intro, the finder page holds
 *   .quote-tool-map-field. The intro page can be switched off entirely.
 * - The rates step sits on the band's gradient: JS stamps .quote-tool--on-last
 *   on the module (keyed off data-total-steps, never "page 3") and this sheet
 *   paints the container, makes the band transparent, and floats a white sheet
 *   under the cards with negative-margin bleeds.
 */

:root {
  --qt-navy: #00345f;
  --qt-blue: #0060af;
  --qt-blue-light: #0460ad;
  --qt-purple: #862889;
  /* Step state — the filled progress segments and numbered tokens. */
  --qt-step-fill: var(--qt-purple);
  --qt-magenta: #c91f88;
  --qt-cyan-hover: #25afd2;
  --qt-ink: #2a2a2a;
  --qt-gray: #666;
  --qt-rule: #d0d0d1;
  --qt-hairline: #dcdcdc;
  --qt-input-border: #cacaca;
  --qt-surface-gray: #f5f5f5;
  --qt-white: #fff;
  --qt-gradient: linear-gradient(90deg, #00345f 0, #0460ad 100%);
  /* Pill hover. The navy→blue gradient slides to purple — the design system's
     hover accent — instead of growing a shadow (client note 2026-09-02: the
     glow was too easy to miss). Three equal thirds on an image 300% the pill's
     width: at rest the first third shows (identical to --qt-gradient), on hover
     the last, and background-position is what animates between them —
     gradients themselves can't interpolate, so a straight swap would snap.
     Pills set `background-size: 300% 100%` and move only the position. */
  --qt-gradient-pill: linear-gradient(90deg, #00345f 0, #0460ad 33.333%, #5b2e91 66.667%, #931f8d 100%);
  --qt-gradient-banner: linear-gradient(72deg, #045da8 66%, #c91f88 100%);
  --qt-gradient-panel-purple: linear-gradient(156.86deg, #931f8d 0, #5b2e91 52%);
  /* Blue -> purple, for the distance badge on a location card. */
  --qt-gradient-badge: linear-gradient(135deg, #0460ad 0, #862889 100%);
  --qt-surface-grad: linear-gradient(146.98deg, #f1f1f1 0, #ffffff 100%);
  --qt-radius-card: 20px;
  --qt-radius-input: 25px;
  --qt-radius-pill: 29px;
  --qt-radius-photo: 30px;
  --qt-radius-hero: 100px 0 0 100px;
  --qt-glow: 0 0 16px 1px rgba(0, 0, 0, 0.31);
  --qt-font-heading: Cachet, Geneva, sans-serif;
  --qt-font-body: Lato, sans-serif;
  /* Type scale — the 2026-09-29 sizing guide for this tool. Every text size
     below comes from these, and none goes under --qt-text-small:
     - body and form copy 16px; supporting text 14px (meta lines, notes, hints,
       eyebrows and other uppercase captions); labels 16px or more (field and
       choice labels, buttons, text links that act as controls);
     - card titles 18–20px: 20 for a card's own title, 18 for a section inside
       one;
     - section headings 28–36px by viewport: the max here, the min under 60em
       (the responsive block at the end), and the min in the sign-up dialog,
       which is phone-width at every viewport.
     Display figures (prices, the FAYMCA code) sit outside the scale. */
  --qt-text-small: 14px;
  --qt-text-body: 16px;
  --qt-text-label: 16px;
  --qt-text-card-subtitle: 18px;
  --qt-text-card-title: 20px;
  --qt-text-heading-min: 28px;
  --qt-text-heading-max: 36px;
  --qt-text-heading: var(--qt-text-heading-max);
}

.quote-tool__hidden {
  display: none !important;
}

/* Module shell ----------------------------------------------------------- */

#quote-tool {
  --qt-pad-x: 40px;
  position: relative;
  margin: 2rem auto 3rem;
  border-radius: var(--qt-radius-photo);
  overflow: hidden;
  background: var(--qt-white);
  /* Deliberate departure from the design system's "no resting shadows" —
     requested 2026-08 to lift the module off the page. Navy-tinted and
     diffuse so it reads as ambient light, not a card border. */
  box-shadow: 0 10px 40px rgba(0, 52, 95, 0.18);
  font-family: var(--qt-font-body);
  font-size: var(--qt-text-body);
  color: var(--qt-ink);
}

#quote-tool .quote-tool-notice,
.quote-tool-notice {
  color: var(--qt-gray);
}

#quote-tool .screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Icons (get_icon() output) inherit currentColor and size in em. */
#quote-tool .icon {
  display: inline-flex;
  width: 1.1em;
  height: 1.1em;
  flex: none;
}

#quote-tool .icon svg {
  width: 100%;
  height: 100%;
}

/* Gradient band ------------------------------------------------------------
   The step header every page shares: eyebrow, heading, segmented progress,
   step labels. Headings/segments/labels are all server-rendered per step;
   quoteToolUpdateBanner() toggles which is visible. */

#quote-tool .quote-tool__band {
  padding: 34px var(--qt-pad-x);
  background: var(--qt-gradient-banner);
  color: var(--qt-white);
  transition: background 0.18s ease-in-out;
}

#quote-tool .quote-tool__eyebrow {
  margin: 0;
  font-size: var(--qt-text-small);
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
}

#quote-tool .quote-tool__heading {
  margin: 10px 0 0;
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: var(--qt-text-heading);
  line-height: 1;
  letter-spacing: -2px;
  color: var(--qt-white);
}

#quote-tool .quote-tool__progress {
  display: flex;
  gap: 10px;
  margin-top: 24px;
}

/* Track first, then the filled states. Purple-on-blue is the whole point of the
   2026-08-24 change: the previous bars separated done / current / pending by
   white opacity and a travelling glow alone, which did not read as progress. */
#quote-tool .quote-tool__progress span {
  flex: 1;
  height: 8px;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.28);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
  transition: background 0.18s ease-in-out, box-shadow 0.18s ease-in-out;
}

#quote-tool .quote-tool__progress span.is-done {
  background: var(--qt-step-fill);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.45);
}

/* The current segment keeps a white ring so "where I am" still separates from
   "where I have been": the band's gradient reaches magenta under the last
   segment, and purple-on-magenta on its own is too close to call. */
#quote-tool .quote-tool__progress span.is-current {
  background: var(--qt-step-fill);
  box-shadow:
    0 0 0 2px rgba(255, 255, 255, 0.9),
    0 0 12px 2px rgba(134, 40, 137, 0.5);
}

#quote-tool .quote-tool__steplabels {
  display: flex;
  gap: 10px;
  margin-top: 13px;
}

/* [data-step] scopes these to the outer label — the numbered token inside is a
   span too. */
#quote-tool .quote-tool__steplabels span[data-step] {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--qt-text-small);
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
}

#quote-tool .quote-tool__steplabels span[data-step].is-current {
  font-weight: 700;
  color: var(--qt-white);
}

/* The numbered token. Pending is a hollow outline; reaching a step fills it
   purple and it stays filled once passed, so the row answers "how far in am I"
   at a glance instead of only "which label is bold". */
#quote-tool .quote-tool__stepnum {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 9999px;
  border: 2px solid rgba(255, 255, 255, 0.6);
  background: transparent;
  font-family: var(--qt-font-body);
  font-size: var(--qt-text-small);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0;
  color: var(--qt-white);
  transition:
    background 0.18s ease-in-out,
    border-color 0.18s ease-in-out,
    box-shadow 0.18s ease-in-out;
}

#quote-tool .quote-tool__steplabels span[data-step].is-done .quote-tool__stepnum,
#quote-tool .quote-tool__steplabels span[data-step].is-current .quote-tool__stepnum {
  background: var(--qt-step-fill);
  border-color: var(--qt-white);
}

#quote-tool .quote-tool__steplabels span[data-step].is-current .quote-tool__stepnum {
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.22);
}

/* The strip that closes the module: the band's gradient again, thin, so the
   white form reads as sandwiched between two ends of one ribbon. It replaces
   the hairline rule that used to sit above the footer buttons. Markup, not a
   pseudo-element, because the two states below switch it off independently of
   the container it would otherwise be painted on. */
#quote-tool .quote-tool__foot {
  height: 14px;
  background: var(--qt-gradient-banner);
}

/* On the rates step the whole container already wears the gradient; a strip
   with its own 72deg axis over 14px would seam against it. */
#quote-tool.quote-tool--on-last .quote-tool__foot {
  background: transparent;
}

/* Body --------------------------------------------------------------------- */

#quote-tool .quote-tool__body {
  padding: 30px var(--qt-pad-x);
  box-sizing: border-box;
}

#quote-tool .gform_wrapper {
  width: 100%;
}

/* Injected step copy (fields 990–992). */

#quote-tool .qt-copy__title {
  margin: 0;
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: var(--qt-text-heading);
  line-height: 1;
  letter-spacing: -2px;
  color: #000;
}

#quote-tool .qt-copy__text {
  margin: 12px 0 0;
  max-width: 660px;
  font-size: var(--qt-text-body);
  font-weight: 300;
  line-height: 24px;
  text-wrap: pretty;
}

/* Gravity Forms chrome ------------------------------------------------------ */

/* Gravity Forms paints a resting shadow (--gf-ctrl-shadow) on every control;
   the design system is flat at rest — glows are hover-only, and those rules
   out-rank this one. */
#quote-tool input,
#quote-tool select,
#quote-tool textarea,
#quote-tool button {
  box-shadow: none;
}

/* Everything clickable shows the hand. The stay-connected checkbox's label
   measured cursor:auto on the live page (2026-09-02); the rest is here so no
   control — GF's or ours — ships without it. */
#quote-tool button:not(:disabled),
#quote-tool input[type="button"],
#quote-tool input[type="submit"],
#quote-tool a[href],
#quote-tool .gchoice label,
#quote-tool .gfield--type-checkbox label {
  cursor: pointer;
}

#quote-tool .gform_required_legend,
#quote-tool [id^="gf_progressbar_wrapper_"] {
  display: none;
}

#quote-tool [id^="gform_confirmation_wrapper_"] {
  width: 100%;
}

/* No divider rule: the module now closes on a gradient strip (.quote-tool__foot),
   so the buttons belong INSIDE the white middle rather than under a line that
   competed with that edge. The margin is the only separation they get. */
#quote-tool .gform_page_footer.top_label {
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: relative;
  margin-top: 24px;
  padding-top: 0;
  border-top: 0;
}

/* AJAX spinner. Gravity Forms stopped rendering this as a sibling image and now
   appends <span id="gform_ajax_spinner_N" class="gform-loader"> INSIDE whichever
   button submitted, stamping that button .gform-has-spinner. Its own framework
   rule centres it with `inset:0; margin:auto`, so it lands squarely on the
   button's label.

   The old override here tried to push it clear with `right:-20px; top:50%;
   transform:translateY(-50%)` and could not work, for two reasons measured on
   the live page 2026-08-31: it never reset GF's `left:0` or `margin:auto`, so
   the box stayed over-constrained and margin:auto re-centred it horizontally
   regardless; and the loader's spin keyframes animate `transform`, which beats
   any declaration, so the vertical centring was discarded too.

   Moving it out of the button is not the fix either — the loader is a 2px
   circle drawn in white (--gf-local-color), sized for the dark gradient pill.
   On the white footer it is invisible. So GF's centring is left alone and the
   LABEL steps aside instead: the button keeps its size, and the spinner sits
   where the text was. */

/* Gravity Forms already declares `color:transparent` for .gform-has-spinner. It
   loses because this sheet's own button colours are id-scoped and outrank it —
   and the :hover variants below are (1,3,0), which ties the obvious form of this
   rule and wins on source order. A click always carries hover, so the label
   would survive every real press while looking fixed to a scripted one. Hence
   the explicit hover/focus arms: each is a class heavier than the rule it has to
   beat, so this holds wherever it sits in the file. */
#quote-tool .gform_page_footer .gform_next_button.gform-has-spinner,
#quote-tool .gform_page_footer .gform_next_button.gform-has-spinner:hover,
#quote-tool .gform_page_footer .gform_next_button.gform-has-spinner:focus,
#quote-tool .gform_page_footer .gform_previous_button.gform-has-spinner,
#quote-tool .gform_page_footer .gform_previous_button.gform-has-spinner:hover,
#quote-tool .gform_page_footer .gform_previous_button.gform-has-spinner:focus,
#quote-tool.quote-tool--on-last .gform_page_footer .gform_previous_button.gform-has-spinner,
#quote-tool.quote-tool--on-last .gform_page_footer .gform_previous_button.gform-has-spinner:hover {
  color: transparent;
}

/* Previous is Gravity Forms' secondary button, whose arc is GF's #204ce5 —
   invisible on the pill (dark on the early steps, a white outline on the rates
   step's gradient), so it is drawn white like Next's. Written onto the loader's
   own borders rather than through GF's --gf-local-color hook: that variable is
   declared on the BUTTON, and setting it there did not reach the arc (measured
   2026-08-31). The two dim sides are the track the arc travels round. */
#quote-tool .gform_page_footer .gform_previous_button .gform-loader {
  border-color: rgba(255, 255, 255, 0.25);
  border-bottom-color: var(--qt-white);
  border-left-color: var(--qt-white);
}

/* The prospect submits by clicking a rate card's Traction Rec link;
   quoteTool.js forwards that click to this button, so it must stay in the
   layout (visibility, never display). */
#quote-tool [id^="gform_submit_button_"] {
  visibility: hidden;
}

#quote-tool .gform-theme--framework .gform-field-label--type-inline {
  margin: 0;
}

/* Footer buttons: Next, Previous and submit are all the DS gradient pill (hover
   slides the gradient to purple — see --qt-gradient-pill). Previous was a plain
   text link until 2026-09-29, when Jake asked for it to read as a button,
   matching Next. The rates step dresses it for the gradient (further down). */

#quote-tool .gform_page_footer .gform_next_button,
#quote-tool .gform_page_footer .gform_previous_button,
#quote-tool .gform_page_footer [id^="gform_submit_button_"] {
  padding: 18px 35px;
  background: var(--qt-gradient-pill);
  background-size: 300% 100%;
  background-position: 0 0;
  color: var(--qt-white);
  font-family: var(--qt-font-heading);
  font-size: var(--qt-text-label);
  line-height: 22.4px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  border: 0;
  border-radius: var(--qt-radius-pill);
  cursor: pointer;
  transition: all 0.18s ease-in-out;
  box-shadow: none;
}

/* Only the position moves: a `background:` shorthand here would reset the
   size and snap the pill back to a single-width gradient. :focus-visible, not
   :focus, so a tap on a phone doesn't leave the pill stuck purple. */
#quote-tool .gform_page_footer .gform_next_button:hover,
#quote-tool .gform_page_footer .gform_next_button:focus-visible,
#quote-tool .gform_page_footer .gform_previous_button:hover,
#quote-tool .gform_page_footer .gform_previous_button:focus-visible {
  background-position: 100% 0;
  color: var(--qt-white);
  box-shadow: none;
}

/* A footer with no Previous (step 1) keeps its pill on the right. */
#quote-tool .gform_page_footer .gform_next_button:only-child,
#quote-tool .gform_page_footer .gform_next_button:first-child:not(:only-child) {
  margin-left: auto;
}

/* Inputs: roomy white pills. Hover signals via border color; focus keeps the
   browser's default ring (the source system never suppresses outlines). */

#quote-tool .gform_wrapper .gfield input[type="text"],
#quote-tool .gform_wrapper .gfield input[type="email"],
#quote-tool .gform_wrapper .gfield input[type="tel"],
#quote-tool .gform_wrapper .gfield select {
  width: 100%;
  box-sizing: border-box;
  height: 58px;
  padding: 0 22px;
  font-family: var(--qt-font-body);
  font-size: var(--qt-text-body);
  color: var(--qt-ink);
  background: var(--qt-white);
  border: 1px solid var(--qt-input-border);
  border-radius: var(--qt-radius-input);
  transition: all 0.18s ease-in-out;
}

#quote-tool .gform_wrapper .gfield input[type="text"]:hover,
#quote-tool .gform_wrapper .gfield input[type="email"]:hover,
#quote-tool .gform_wrapper .gfield input[type="tel"]:hover,
#quote-tool .gform_wrapper .gfield select:hover {
  border-color: var(--qt-cyan-hover);
}

#quote-tool .gform_wrapper .gfield_label {
  font-family: var(--qt-font-body);
  font-size: var(--qt-text-label);
  font-weight: 700;
  color: var(--qt-ink);
}

/* Gravity Forms' own small print — a field's description ("Income ranges
   update…") and the error under it — comes in at 13px, under the scale's
   floor. The error summary above the fields is form copy. */
#quote-tool .gform_wrapper .gfield_description,
#quote-tool .gform_wrapper .gfield_validation_message {
  font-size: var(--qt-text-small);
  line-height: 21px;
}

#quote-tool .gform_wrapper .gform_submission_error {
  font-size: var(--qt-text-body);
  line-height: 24px;
}

/* GF renders "(Required)" text (the form-level indicator setting is read from
   stored meta, so a render filter can't switch it) — collapse the text and draw
   the design's magenta asterisk instead. */
#quote-tool .gform_wrapper .gfield_required {
  color: var(--qt-magenta);
}

#quote-tool .gform_wrapper .gfield_required_text {
  font-size: 0;
}

#quote-tool .gform_wrapper .gfield_required_text::before {
  content: "*";
  font-size: var(--qt-text-label);
}

/* The stay-connected checkbox row (scoped by field type so the location and
   rate radios stay untouched). Full-row: its old grid partner, the referral
   select, is removed at render. */

#quote-tool .gfield--type-checkbox {
  grid-column: 1 / -1;
}

#quote-tool .gfield--type-checkbox .gchoice {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

/* Gravity Forms' Orbital theme already draws this box itself (appearance:
   none, its own SVG tick) — in GF's #204ce5, not a site colour. Repainted:
   white box, theme-blue border and tick when checked, cyan border on hover to
   match the text inputs. Every background longhand is restated on :checked
   because GF sets them one by one. */
#quote-tool .gfield--type-checkbox input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin: 2px 0 0;
  flex: none;
  border: 2px solid var(--qt-input-border);
  border-radius: 4px;
  background: var(--qt-white);
  accent-color: var(--qt-blue);
  cursor: pointer;
  transition: border-color 0.18s ease-in-out;
}

#quote-tool .gfield--type-checkbox input[type="checkbox"]:hover {
  border-color: var(--qt-cyan-hover);
}

#quote-tool .gfield--type-checkbox input[type="checkbox"]:checked {
  border-color: var(--qt-blue);
  background-color: var(--qt-white);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230060af' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-size: 14px 14px;
  background-position: center;
  background-repeat: no-repeat;
}

/* GF's tick is a ::before pseudo-element painted over the box, so on its own
   the background above just sat underneath GF's #204ce5 tick (measured
   2026-09-02 — two ticks, GF's on top). */
#quote-tool .gfield--type-checkbox input[type="checkbox"]::before,
#quote-tool .gfield--type-checkbox input[type="checkbox"]::after {
  content: none;
  display: none;
}

#quote-tool .gfield--type-checkbox input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--qt-purple);
  outline-offset: 2px;
}

/* The choice's own label. The field's legend ("Stay connected with the Y") is a
   .gform-field-label too; scoped to the inline type, it keeps the standard
   field-label style above instead of this one. */
#quote-tool .gfield--type-checkbox .gform-field-label--type-inline {
  font-size: var(--qt-text-label);
  line-height: 24px;
  font-weight: 400;
  text-wrap: pretty;
}

/* Step 1 — photo beside the field grid (only while the intro step exists). --- */

#quote-tool .gform_page:has(.qt-copy-intro) .gform_page_fields {
  display: grid;
  grid-template-columns: minmax(240px, 33%) 1fr;
  gap: 45px;
}

#quote-tool .gform_page:has(.qt-copy-intro) .gform_page_fields::before {
  content: "";
  /* The photo, not the field column, used to set this row's height — 440px
     against ~380px of fields. Now it stretches to the fields and the floor
     only guards a very short column. */
  min-height: 360px;
  border-radius: var(--qt-radius-photo);
  background-image: url(../../../images/quote-tool/outdoor-stretch.jpg);
  background-size: cover;
  background-position: center;
}

/* The required-fields note sits left of the Next pill on the intro footer. */
#quote-tool .gform_page:has(.qt-copy-intro) .gform_page_footer::before {
  content: '"*" indicates required fields';
  font-size: var(--qt-text-small);
  color: var(--qt-gray);
}

/* Step 2 — the finder page becomes a grid: copy and search span both columns,
   then the map sits beside the card rail. display:contents promotes the
   finder's inner wrappers to grid items without moving any DOM (the finder JS
   queries structure, not layout). */

#quote-tool .gform_page:has(.quote-tool-map-field) .gform_fields {
  display: grid;
  grid-template-columns: minmax(320px, 470px) 1fr;
  gap: 25px;
  align-items: start;
}

#quote-tool .gform_page:has(.quote-tool-map-field) .gform_fields > .gfield.quote-tool-step-copy,
#quote-tool .gform_page:has(.quote-tool-map-field) .loc-finder__searchbar,
#quote-tool .gform_page:has(.quote-tool-map-field) .loc-finder__msg {
  grid-column: 1 / -1;
}

#quote-tool .gfield.quote-tool-map-field,
#quote-tool .quote-tool-map-field .loc-finder,
#quote-tool .quote-tool-map-field .loc-finder__layout,
#quote-tool .quote-tool-map-field .loc-finder__map {
  display: contents;
}

#quote-tool .quote-tool-map-field .shortcode-map {
  grid-column: 1;
  width: 100%;
  height: 540px;
  margin: 0;
  border: 0;
  border-radius: var(--qt-radius-photo);
}

#quote-tool .gform_page:has(.quote-tool-map-field) .gfield.location-cards {
  grid-column: 2;
  align-self: stretch;
}

/* quoteToolRail.js moves Step 2's native Next control into the selected hub's
   detail panel and relabels it "Select This Hub". Hide it while it is parked in
   the footer so there is never a second, competing forward action. */
#quote-tool .gform_page:has(.quote-tool-map-field) .gform_page_footer .gform_next_button {
  display: none;
}

#quote-tool .shortcode-map .marker {
  display: none;
}

/* Step 2's type. The search row, the hub cards and the hub panel are drawn by
   the shared locations-finder.css, which the live tool loads too, so their
   sizes are brought onto the scale here rather than there. That sheet prints
   after this one, so each rule carries one more selector than the rule it
   overrides. Icon sizes (font-size on .icon) stay the shared sheet's. */
#quote-tool .gform_wrapper .loc-finder__search-input,
#quote-tool .loc-finder__msg,
#quote-tool .qt-hub-detail__phone,
#quote-tool .qt-hub-detail__email {
  font-size: var(--qt-text-body);
}

#quote-tool .gform_wrapper .loc-finder__submit,
#quote-tool .gform_wrapper .loc-finder__geo,
#quote-tool .loc-card__more,
#quote-tool .location-cards .qt-hub-detail__back,
#quote-tool .location-cards .qt-hub-detail__select {
  font-size: var(--qt-text-label);
}

#quote-tool .location-cards .qt-rail__count,
#quote-tool .loc-card__address,
#quote-tool .loc-card__distance,
#quote-tool .loc-card__nearest,
#quote-tool .qt-hub-detail__days,
#quote-tool .qt-hub-detail__times,
#quote-tool .qt-hub-detail__amenities li {
  font-size: var(--qt-text-small);
}

/* Tracked -1px, as the rate cards' titles are at this size. */
#quote-tool .loc-card__title,
#quote-tool .qt-hub-detail__title {
  font-size: var(--qt-text-card-title);
  line-height: 22px;
  letter-spacing: -1px;
}

#quote-tool .qt-hub-detail__meta {
  font-size: var(--qt-text-body);
  line-height: 24px;
}

/* "Hours", "Amenities" — sections inside the hub's card. */
#quote-tool .qt-hub-detail__label {
  font-size: var(--qt-text-card-subtitle);
  line-height: 20px;
}

/* Y for All step --------------------------------------------------------------
   Household size + income, answered with an instant qualifies / doesn't-qualify
   card (Claude Design "Financial Assistance Step v2", option 1a). Step 3 of 4
   with the intro on; the page is the one holding .qt-fa-size (fields 36–41,
   functions/general/quote_tool_phase2_yforall.php). quoteToolPhase2YForAll.js
   stamps qt-fa--asking / --done / --skipping on that .gform_page; without the
   script none is set, and the page stays a plain, working Gravity Forms page.

   The questions keep the tool's own controls exactly as the other steps draw
   them — selects, checkbox, footer buttons, step copy. Only the panel, the
   result cards and the FAYMCA pill are new, built from the --qt-* tokens and
   the type sizes already in use in this file. */

/* The finder's and rates step's column rhythm (panel column == map column), so
   the left edge holds still from step 2 through step 4, and like every other
   step the second column runs to the module's edge — the footer's Next lines
   up under it. Paragraphs keep the tool's copy measure instead
   (.qt-copy__text, .qt-fa-card__text).

   The panel spans every row and the trailing 1fr row absorbs its extra height:
   a spanning item only grows content-sized rows when it crosses no flexible
   one, so the questions stay packed at the top instead of spreading out to
   match it. row-gap is 0 because each empty row would add one; the fields carry
   Gravity Forms' own field spacing (--gf-form-gap-y, step 1's rhythm) as
   margins instead. Every field is placed explicitly — GF gives each .gfield
   grid-column: 1 / -1, and step 1's checkbox rule spans both columns too. */
#quote-tool .gform_page:has(.qt-fa-size) .gform_fields {
  display: grid;
  grid-template-columns: minmax(320px, 470px) minmax(0, 1fr);
  grid-template-rows: repeat(5, auto) 1fr;
  column-gap: 25px;
  row-gap: 0;
  align-items: start;
}

#quote-tool .gform_page:has(.qt-fa-size) .gform_fields > .gfield {
  grid-column: 2;
  margin: var(--gf-form-gap-y, 40px) 0 0;
}

#quote-tool .gform_page:has(.qt-fa-size) .gform_fields > .gfield.qt-fa-skip,
#quote-tool .gform_page:has(.qt-fa-size) .gform_fields > .gfield.qt-fa-result {
  margin-top: 0;
}

/* DOM order is questions-first (the reading order on a phone, where the panel
   follows them); on the desktop grid the panel takes column 1 beside them. */
#quote-tool .gform_page:has(.qt-fa-size) .gform_fields > .gfield.qt-fa-panel {
  grid-column: 1;
  grid-row: 1 / -1;
  align-self: stretch;
  margin: 0;
}

/* 1a: the result replaces the questions — never both on screen. */
#quote-tool .gform_page.qt-fa--done .gfield.qt-fa-skip,
#quote-tool .gform_page.qt-fa--done .gfield.qt-copy-fa,
#quote-tool .gform_page.qt-fa--done .gfield.qt-fa-size,
#quote-tool .gform_page.qt-fa--done .gfield.qt-fa-income,
#quote-tool .gform_page:not(.qt-fa--done) .gfield.qt-fa-result,
#quote-tool .qt-fa-verdict[hidden] {
  display: none;
}

/* While asking there is no way forward but an answer or the skip box, so Next
   waits. The script displays it again before the skip clicks it: Gravity
   Forms won't submit through a button that isn't displayed. */
#quote-tool .gform_page.qt-fa--asking .gform_page_footer .gform_next_button {
  display: none;
}

/* Footer: Previous on the left; on the right Next, or the status line while
   the questions wait. Previous's auto margin groups the inserted wrapper with
   Next, where the footer's space-between would float it mid-row. */
#quote-tool .gform_page:has(.qt-fa-size) .gform_page_footer {
  gap: 25px;
}

#quote-tool .gform_page:has(.qt-fa-size) .gform_page_footer .gform_previous_button {
  margin-right: auto;
}

#quote-tool .qt-fa-actions {
  display: flex;
  align-items: center;
  gap: 25px;
}

/* The wrapper holds only the status line, so it goes with it: an empty flex
   item would still take a gap in the footer row, and a second one in the
   stacked phone footer. */
#quote-tool .gform_page:not(.qt-fa--asking) .qt-fa-actions {
  display: none;
}

/* Sized like step 1's required-fields note, which sits in the same spot. */
#quote-tool .qt-fa-actions__status {
  margin: 0;
  font-size: var(--qt-text-small);
  color: var(--qt-gray);
}

/* The skip box is step 1's checkbox exactly, set in a hairline row so it reads
   as a way past the step rather than one of its questions. Cyan on hover, like
   the text inputs. */
#quote-tool .gfield.qt-fa-skip .gchoice {
  align-items: center;
  padding: 14px 18px;
  border: 1px solid var(--qt-hairline);
  border-radius: var(--qt-radius-input);
  transition: border-color 0.18s ease-in-out;
}

#quote-tool .gfield.qt-fa-skip .gchoice:hover {
  border-color: var(--qt-cyan-hover);
}

#quote-tool .gfield.qt-fa-skip input[type="checkbox"] {
  margin: 0;
}

#quote-tool .gfield.qt-fa-skip .gform-field-label {
  flex: 1;
}

/* Gravity Forms draws the select chevron as a background image. The tool's
   base select rule — written before any select was visible on the tool — uses
   the background shorthand, which wipes it, and 22px of side padding that runs
   long labels under where it sits. Both come back here, on these selects only.
   So does centring: GF sets every control's line-height to its 38px control
   size, and unlike a text input, a select doesn't centre its line in a taller
   box — the label rode ~10px high in the tool's 58px pill (measured
   2026-09-24). 56px is the pill's inner height. */
#quote-tool .gform_wrapper .gfield.qt-fa-size select,
#quote-tool .gform_wrapper .gfield.qt-fa-income select {
  padding-top: 0;
  padding-bottom: 0;
  line-height: 56px;
  padding-right: 52px;
  background-image: var(--gf-ctrl-select-icon);
  background-position: right 22px center;
  background-repeat: no-repeat;
  background-size: var(--gf-ctrl-select-icon-size, 10px);
  cursor: pointer;
}

/* "What is Y for All?" — flat grey (the design's surface) with the rates
   panel's type: a card title, the rail's eyebrow, body copy. */
#quote-tool .qt-fa-info {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  height: 100%;
  padding: 28px;
  background: var(--qt-surface-gray);
  border-radius: var(--qt-radius-card);
}

#quote-tool .qt-fa-info__title {
  margin: 0;
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: var(--qt-text-card-title);
  line-height: 22px;
  letter-spacing: -1px;
  color: #000;
  text-wrap: balance;
}

#quote-tool .qt-fa-info__text {
  margin: 12px 0 0;
  font-size: var(--qt-text-body);
  line-height: 24px;
  text-wrap: pretty;
}

#quote-tool .qt-fa-info__eyebrow {
  margin: 22px 0 0;
  font-size: var(--qt-text-small);
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--qt-gray);
}

/* Gravity Forms' theme reset strips list markers inside the form anyway; the
   numbers are drawn tokens, the band's 28px step-token geometry filled with the
   pill gradient. */
#quote-tool .qt-fa-info__steps {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

#quote-tool .qt-fa-info__step {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin: 0;
  font-size: var(--qt-text-body);
  line-height: 24px;
}

#quote-tool .qt-fa-info__num {
  flex: 0 0 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 28px;
  border-radius: 9999px;
  background: var(--qt-gradient);
  font-family: var(--qt-font-body);
  font-size: var(--qt-text-small);
  font-weight: 700;
  line-height: 1;
  color: var(--qt-white);
}

/* Down 2px so the first 24px line centres on the 28px token. */
#quote-tool .qt-fa-info__step-text {
  padding-top: 2px;
  text-wrap: pretty;
}

/* Pinned to the panel's foot, like the rates panel's closing note. */
#quote-tool .qt-fa-info__note {
  margin: auto 0 0;
  padding-top: 18px;
  font-size: var(--qt-text-small);
  line-height: 21px;
  color: var(--qt-gray);
  text-wrap: pretty;
}

/* The result card. Its title and copy are the step copy's own sizes
   (.qt-copy__title / .qt-copy__text), so the answer reads at the weight of the
   question it replaced; the eyebrow is the band's. Blue edge when it's good
   news, the hairline when it isn't. */
#quote-tool .qt-fa-card {
  box-sizing: border-box;
  padding: 30px;
  border: 1px solid var(--qt-hairline);
  border-radius: var(--qt-radius-photo);
  background: var(--qt-white);
}

#quote-tool .qt-fa-card--yes {
  border-color: var(--qt-blue);
}

#quote-tool .qt-fa-card__eyebrow {
  margin: 0;
  font-size: var(--qt-text-small);
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--qt-gray);
}

#quote-tool .qt-fa-card--yes .qt-fa-card__eyebrow {
  color: var(--qt-blue);
}

#quote-tool .qt-fa-card__title {
  margin: 12px 0 0;
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: var(--qt-text-heading);
  line-height: 1;
  letter-spacing: -2px;
  color: #000;
}

#quote-tool .qt-fa-card__text {
  margin: 12px 0 0;
  max-width: 660px;
  font-size: var(--qt-text-body);
  font-weight: 300;
  line-height: 24px;
  text-wrap: pretty;
}

/* FAYMCA is the one string a member has to reproduce exactly — set large, in
   an outline pill, and never broken across a line. */
#quote-tool .qt-fa-code {
  display: flex;
  align-items: center;
  gap: 18px;
  margin: 20px 0 0;
  padding: 20px 0 0;
  border-top: 1px solid var(--qt-hairline);
}

#quote-tool .qt-fa-code__pill {
  flex: none;
  padding: 10px 22px;
  border: 1px solid var(--qt-blue);
  border-radius: var(--qt-radius-pill);
  font-family: var(--qt-font-heading);
  font-size: 22px;
  line-height: 1;
  letter-spacing: 2px;
  color: var(--qt-blue);
  white-space: nowrap;
}

#quote-tool .qt-fa-code__text {
  flex: 1;
  margin: 0;
  font-size: var(--qt-text-body);
  line-height: 24px;
  text-wrap: pretty;
}

/* Under the qualifies card's FAYMCA code (client edits, 2026-10-02): the
   walkthrough link, which is the rates panel's own trigger drawn by the
   sign-up guide's rules further down, then the line naming the chosen hub to
   call. The link keeps its 10px vertical padding for a 44px hit area, so these
   margins are set against it: 20px from the code to the link's label, 16px from
   the label to the line. */
#quote-tool .qt-fa-card .qt-assist-trigger {
  margin-top: 10px;
}

#quote-tool .qt-fa-card__contact {
  margin: 6px 0 0;
  max-width: 660px;
  font-size: var(--qt-text-body);
  line-height: 24px;
  text-wrap: pretty;
}

#quote-tool .qt-fa-card__contact a {
  color: var(--qt-blue);
  /* A phone number never breaks across lines. */
  white-space: nowrap;
  transition: all 0.18s ease-in-out;
}

#quote-tool .qt-fa-card__contact a:hover {
  color: var(--qt-purple);
}

/* Rates step — the whole module wears the band gradient; the discounts panel
   sits ON it beside the cards (2026-08-14 redesign), and only the footer
   closes in white. ---------------------------------------------------------- */

#quote-tool.quote-tool--on-last .quote-tool-container {
  background: var(--qt-gradient-banner);
}

#quote-tool.quote-tool--on-last .quote-tool__band {
  background: transparent;
}

/* Copy spans the full row, then panel | cards — the same :has() promotion AND
   the same column rhythm as the finder page (panel column == map column, so
   the rate cards match the location cards' size). Rows are pinned explicitly:
   the fields' DOM order is cards-before-panel (better reading order for a
   form), and sparse grid auto-placement would otherwise push the column-1
   panel below the cards. */
#quote-tool .gform_page:has(.gfield.quote-tool-radio) .gform_fields {
  display: grid;
  grid-template-columns: minmax(320px, 470px) 1fr;
  gap: 25px;
  align-items: start;
}

#quote-tool .gform_page:has(.gfield.quote-tool-radio) .gfield.quote-tool-step-copy {
  grid-column: 1 / -1;
  grid-row: 1;
}

#quote-tool .gform_page:has(.gfield.quote-tool-radio) .gfield.quote-tool-sheet {
  grid-column: 1;
  grid-row: 2;
  align-self: stretch;
}

#quote-tool .gform_page:has(.gfield.quote-tool-radio) .gfield.quote-tool-radio {
  grid-column: 2;
  grid-row: 2;
}

/* The footer stays on the gradient — the band runs to the module's bottom
   corners. */
#quote-tool.quote-tool--on-last .gform_page_footer.top_label {
  margin-top: 24px;
  background: transparent;
}

/* Previous is the only footer button here, and the navy pill would sink into
   the blue behind it, so it wears the white outline the rate cards do (the
   confirmation's secondary button). It fills white on hover — but not while its
   spinner runs, since the arc is drawn white. */
#quote-tool.quote-tool--on-last .gform_page_footer .gform_previous_button {
  background: transparent;
  border: 1px solid var(--qt-white);
}

#quote-tool.quote-tool--on-last .gform_page_footer .gform_previous_button:not(.gform-has-spinner):hover,
#quote-tool.quote-tool--on-last .gform_page_footer .gform_previous_button:not(.gform-has-spinner):focus-visible {
  background: var(--qt-white);
  color: var(--qt-navy);
}

/* Rate cards ---------------------------------------------------------------- */

/* The location and rate legends stay for screen readers only, and the location
   field's editor-facing description ("Populated at render time…") never shows. */
#quote-tool .quote-tool-radio legend,
#quote-tool .location-cards legend {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

#quote-tool .location-cards .gfield_description {
  display: none;
}

/* The rate field's description IS the joiner-fee footnote the cards' asterisks
   point at (client copy, 2026-09-21): one line under the whole grid, on the
   gradient, sized like the cards' meta line. It sits outside .gfield_radio, so
   the scroller's mask never fades it and it stays put while the list scrolls. */
#quote-tool .quote-tool-radio .gfield_description {
  margin: 12px 0 0;
  padding: 0;
  font-size: var(--qt-text-small);
  line-height: 21px;
  color: rgba(255, 255, 255, 0.85);
}

#quote-tool .quote-tool-radio {
  margin-top: 0;
}

/* The list scrolls beside the discounts panel; the mask fades its last rows
   as a "more below" hint (an overlay can't match the 2-stop gradient behind
   it — masking the content itself is background-agnostic). quoteTool.js drops
   the fade via the at-end class once the list is scrolled out or fits. */
#quote-tool .quote-tool-radio .gfield_radio {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  align-content: start;
  /* Tall enough that the next row of cards visibly peeks above the fade — with
     the peek gone, nothing says "more plans below".

     Held at 540px through the 2026-08-25 card redesign ON PURPOSE. Moving the
     meta onto the title row and dropping the Select pill took roughly 80px off
     every card, so the same box that fitted two rows plus a peek now fits about
     three — more plans above the fold without the step itself growing taller,
     which was the point. The figure is derived from the CSS, not measured: if
     the rows land wrong on the live page, adjust here rather than in the card.
     (2026-09-22: the meta went back under the title at the client's request,
     about 24px per card; still held here — the fourth row is what peeks now.)

     The panel stretches to the row, so the two columns keep a shared bottom
     edge at any height. The fade is short on purpose: it should read as "cut
     off, scroll" on the peeking row, never ghost a whole row's prices.

     540px is the floor, not the cap, since 2026-09-30: the list may run as tall
     as the panel beside it, which quoteToolPhase2.js measures into
     --qt-rates-fit. A Y for All qualifier's panel carries the how-to-apply
     block, with room for every plan and no scroll (Jake). */
  max-height: max(540px, var(--qt-rates-fit, 0px));
  overflow-y: auto;
  mask-image: linear-gradient(to bottom, #000 calc(100% - 36px), transparent);
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 36px), transparent);
}

#quote-tool .quote-tool-radio--at-end .gfield_radio {
  mask-image: none;
  -webkit-mask-image: none;
}

/* Equal-height cards per row: the gchoice→label→.quote-item chain is all flex
   columns so the price + Select cluster pins to each card's bottom. */
#quote-tool .quote-tool-radio .gchoice {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 18px;
  border: 1px solid rgba(255, 255, 255, 0.8);
  border-radius: var(--qt-radius-photo);
  color: var(--qt-white);
  transition: all 0.18s ease-in-out;
}

/* Hover inverts the card off the gradient: white sheet, navy characters. Every
   colour below is restated because .gchoice's white is set on descendants
   directly (see the note above the label rule) — inheritance alone would leave
   white text on a white card. */
#quote-tool .quote-tool-radio .gchoice:hover {
  background: var(--qt-white);
  border-color: var(--qt-white);
}

#quote-tool .quote-tool-radio .gchoice:hover label,
#quote-tool .quote-tool-radio .gchoice:hover .quote-item,
#quote-tool .quote-tool-radio .gchoice:hover .quote-item__title {
  color: var(--qt-navy);
}

#quote-tool .quote-tool-radio .gchoice:hover .quote-item__meta,
#quote-tool .quote-tool-radio .gchoice:hover .quote-item__desc {
  color: rgba(0, 52, 95, 0.78);
}

/* Gravity Forms colors the choice <label> directly, which severs the card's
   white inheritance from .gchoice — on the gradient, the meta line and the
   price then render GF's dark control color. Everything inside opts back in. */
#quote-tool .quote-tool-radio .gchoice label,
#quote-tool .quote-tool-radio .quote-item {
  display: flex;
  flex-direction: column;
  flex: 1;
  color: var(--qt-white);
}

#quote-tool .quote-tool-radio input[type="radio"] {
  display: none;
}

/* Title, then the ages + term line under it. They shared one row (meta
   right-aligned, nowrap) from the 2026-08-25 redesign until 2026-09-22, when
   the client asked for the age requirements below the membership type and
   above the price. Stacking also retires the ≤375px special case that row
   needed — one title word plus the nowrap meta could overrun a 242px card. */
#quote-tool .quote-item__top {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
}

/* -1px tracking: the -2px the headings carry turns crunchy at card-title size. */
#quote-tool .quote-item__title {
  min-width: 0;
  margin: 0;
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: var(--qt-text-card-title);
  line-height: 22px;
  letter-spacing: -1px;
  color: var(--qt-white);
}

/* The footnote asterisk on a type the joiner fee can apply to (the note it
   points at is the rate field's description, under the grid). Untracked, so
   the title's tracking doesn't glue it to the last letter. */
#quote-tool .quote-item__footnote-mark {
  margin-left: 2px;
  letter-spacing: 0;
}

#quote-tool .quote-item__meta {
  margin: 0;
  font-size: var(--qt-text-small);
  line-height: 21px;
  text-wrap: pretty;
}

/* Composition line on group plans ("Up to 2 adults … and 4 children …") —
   supporting copy, so it steps back half a tone from the meta line. */
#quote-tool .quote-item__desc {
  margin: 6px 0 0;
  font-size: var(--qt-text-small);
  line-height: 21px;
  color: rgba(255, 255, 255, 0.85);
  text-wrap: pretty;
}

/* Price + Select are the card's bottom cluster: the auto margin takes the
   row's slack (rows stretch to their tallest card), so prices and pills stay
   aligned across a row however long each card's copy runs. The padding is the
   floor — the gap never closes past it on the row's tallest card. */
#quote-tool .quote-item__price {
  margin: auto 0 0;
  padding: 10px 0 0;
}

#quote-tool .quote-item__amount {
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: 30px;
  line-height: 30px;
  letter-spacing: -2px;
}

#quote-tool .quote-item__amount--verbatim {
  font-size: 24px;
  line-height: 26px;
  letter-spacing: -1px;
}

#quote-tool .quote-item__term {
  font-family: var(--qt-font-body);
  font-weight: 400;
  font-size: var(--qt-text-small);
  letter-spacing: 0;
}

/* Y for All: a qualifying household's card shows the standard price slashed out
   beside the reduced one (quote_tool_phase2_yforall_card_price_html) — the two
   amounts only, never a percentage. The old price steps down a size and fades;
   the new one keeps the card's usual price style, so it still reads as the
   price. The slash is drawn rather than a line-through so it can run corner to
   corner; forced-colors mode gets the plain line-through back. */
#quote-tool .quote-item__price--reduced {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 10px;
}

#quote-tool .quote-item__was {
  position: relative;
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: 20px;
  line-height: 20px;
  letter-spacing: -1px;
  color: rgba(255, 255, 255, 0.6);
}

#quote-tool .quote-item__was s,
#quote-tool .qt-confirm__was s {
  text-decoration: none;
}

#quote-tool .quote-item__was::after,
#quote-tool .qt-confirm__was::after {
  content: "";
  position: absolute;
  top: 50%;
  left: -3px;
  right: -3px;
  height: 2px;
  border-radius: 2px;
  background: var(--qt-white);
  transform: rotate(-14deg);
  pointer-events: none;
}

/* On hover the card goes white with navy type; the old price follows at half
   strength and the slash takes the brand magenta. */
#quote-tool .quote-tool-radio .gchoice:hover .quote-item__was {
  color: rgba(0, 52, 95, 0.5);
}

#quote-tool .quote-tool-radio .gchoice:hover .quote-item__was::after {
  background: var(--qt-magenta);
}

@media (forced-colors: active) {
  #quote-tool .quote-item__was s,
  #quote-tool .qt-confirm__was s {
    text-decoration: line-through;
  }

  #quote-tool .quote-item__was::after,
  #quote-tool .qt-confirm__was::after {
    display: none;
  }
}

/* Was the white Select pill; since 2026-08-25 it is the card's hit area,
   stretched edge to edge over .gchoice (which is position:relative for exactly
   this). Invisible, but still a real anchor: it carries the Traction Rec deep
   link, and being the only focusable thing in the card — the rate radios are
   display:none — it is also how the keyboard reaches a plan. */
#quote-tool .quote-item__select {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: var(--qt-radius-photo);
  text-decoration: none;
}

/* Its label is for screen readers; the card's own text is what sighted users
   read underneath. */
#quote-tool .quote-item__select-label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* The anchor covers the card, so its focus ring IS the card's focus ring. */
#quote-tool .quote-item__select:focus-visible {
  outline: 3px solid var(--qt-white);
  outline-offset: 3px;
}

#quote-tool .quote-tool-radio .gchoice:hover .quote-item__select:focus-visible {
  outline-color: var(--qt-navy);
}

/* Shown by quoteTool.js if a branch somehow renders with no plans at all (a
   catalog fetch degrading, not a normal state). Created in JS, so it has no
   markup counterpart. Sits on the gradient. */
#quote-tool .quote-tool-empty {
  grid-column: 1 / -1;
  margin: 1rem 0 0;
  padding: 1.5rem;
  border: 1px dashed rgba(255, 255, 255, 0.6);
  border-radius: var(--qt-radius-card);
  text-align: center;
  color: var(--qt-white);
  font-size: var(--qt-text-body);
}

/* The Discounts & Add-Ons panel — a white card on the gradient, beside the
   rate cards. The Y for All note leads it; the add-ons follow. ------------- */

#quote-tool .gfield.quote-tool-sheet {
  box-sizing: border-box;
  padding: 20px;
  background: var(--qt-white);
  border-radius: var(--qt-radius-card);
}

/* Fills the stretched field, so a short panel still reaches the band's bottom. */
#quote-tool .qt-sheet {
  display: flex;
  flex-direction: column;
  height: 100%;
}

#quote-tool .qt-sheet__change-hub {
  /* GF themes bare buttons inline-flex and top-aligned, which drops this one
     below the sentence it sits in. */
  display: inline-block;
  vertical-align: baseline;
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  /* GF's Orbital theme gives every <button> its control height (min-height
     38px). Inline in a 25px line, that made whichever line it landed on ~13px
     taller — invisible on desktop, where it ends the paragraph, obvious on
     phones, where the wrap puts it mid-paragraph (measured 2026-09-02: one
     38px line box among 22px ones). */
  min-height: 0;
  height: auto;
  color: var(--qt-blue);
  cursor: pointer;
  transition: all 0.18s ease-in-out;
}

#quote-tool .qt-sheet__change-hub:hover {
  color: var(--qt-purple);
}

/* In the on-gradient intro sentence the link reads white and underlined. */
#quote-tool .qt-rates-intro .qt-sheet__change-hub {
  color: var(--qt-white);
  text-decoration: underline;
}

#quote-tool .qt-rates-intro .qt-sheet__change-hub:hover {
  color: rgba(255, 255, 255, 0.8);
}

/* One step under the card's headline (.qt-sheet__assist-title): the card
   subtitle to its card title. Both were one size for a day (2026-09-17) and
   the card read as two unrelated panels glued together — type scale is what
   carries hierarchy in this design system. Tracked -1px like the hub panel's
   subheads (on white, -2px gets crunchy). */
#quote-tool .qt-sheet__discounts-title {
  margin: 0;
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: var(--qt-text-card-subtitle);
  line-height: 20px;
  letter-spacing: -1px;
  color: #000;
  text-wrap: balance;
}

/* With no how-to-apply block above it (only households that qualify get one),
   it heads the whole card, so it takes the card title's size. */
#quote-tool .qt-sheet > .qt-sheet__discounts-title:first-child {
  font-size: var(--qt-text-card-title);
  line-height: 22px;
}

/* Intro line under the panel title (client copy, 2026-09-10). It carries the
   list's top margin so .qt-sheet__list keeps its own spacing rhythm. */
#quote-tool .qt-sheet__discounts-intro {
  margin: 10px 0 0;
  font-size: var(--qt-text-body);
  line-height: 24px;
  color: var(--qt-gray);
  text-wrap: pretty;
}

#quote-tool .qt-sheet__list {
  display: flex;
  flex-direction: column;
  gap: 15px;
  margin: 16px 0 0;
}

#quote-tool .qt-sheet__discount-label {
  margin: 0;
  font-size: var(--qt-text-label);
  font-weight: 700;
}

#quote-tool .qt-sheet__discount-detail {
  margin: 4px 0 0;
  font-size: var(--qt-text-small);
  line-height: 21px;
  color: var(--qt-gray);
  text-wrap: pretty;
}

/* Leads the panel as of 2026-09-17 — the client wanted Y for All read first and
   the add-ons demoted below it, so the hairline that used to sit above this note
   now closes it off from the Discounts section that follows. Since 2026-09-29
   it renders only for households that qualify (quote_tool_phase2_populate_form());
   a skip or a no leaves Discounts alone in the card.

   The icon sits beside the headline (Jake, 2026-09-29) and the copy and link run
   under them on the card's left edge. That is not the icon column it once was:
   an icon beside the whole body put a 30px headline 38px further right than the
   Discounts heading under it and left a dead gutter beside the copy. The link's
   own 10px bottom padding is part of the 20px visual gap above the rule, hence
   the 10px padding here. */
#quote-tool .qt-sheet__assist {
  padding-bottom: 10px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--qt-hairline);
  font-size: var(--qt-text-body);
  line-height: 24px;
  text-wrap: pretty;
}

/* The card's one visual anchor, beside the headline and centred on however many
   lines it wraps to (two on desktop, three on a phone). Stroked, blue, 32px —
   24px read as a bullet against two lines — so the pair reads as one unit. */
#quote-tool .qt-sheet__assist-head {
  display: flex;
  align-items: center;
  gap: 14px;
}

#quote-tool .qt-sheet__assist-head .icon {
  display: flex;
  width: 32px;
  height: 32px;
  color: var(--qt-blue);
}

/* The card's headline, a step above .qt-sheet__discounts-title: the panel reads
   as two sections, Y for All first. It was a 15px <p> sized like a discount row
   while the note was a footnote pinned under the list. */
#quote-tool .qt-sheet__assist-title {
  margin: 0;
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: var(--qt-text-card-title);
  line-height: 22px;
  letter-spacing: -1px;
  color: #000;
  text-wrap: balance;
}

#quote-tool .qt-sheet__assist-text {
  margin: 12px 0 0;
  font-size: var(--qt-text-body);
  line-height: 24px;
  color: var(--qt-gray);
}

/* The three application steps (client copy, 2026-09-18). Numbered, unlike the
   discount rows below: these are actions in sequence and the order IS the
   instruction. Markers hang in a 22px gutter rather than using list-style, so a
   wrapped step keeps one straight left edge with the paragraphs around it —
   list-style-position: inside would re-indent the wrap under the number, and
   Gravity Forms' theme reset strips list markers inside the form anyway. */
#quote-tool .qt-sheet__assist-steps {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: qt-assist-step;
}

#quote-tool .qt-sheet__assist-steps li {
  position: relative;
  counter-increment: qt-assist-step;
  margin: 8px 0 0;
  padding-left: 22px;
  font-size: var(--qt-text-body);
  line-height: 24px;
  color: var(--qt-gray);
  text-wrap: pretty;
}

#quote-tool .qt-sheet__assist-steps li::before {
  content: counter(qt-assist-step) ".";
  position: absolute;
  top: 0;
  left: 0;
  font-weight: 700;
  color: var(--qt-blue);
}

/* FAYMCA is the one string a member has to reproduce exactly, so it reads at
   full ink weight and never breaks across a line. Matches the <strong> the
   sign-up guide wraps the same code in (quoteToolAssistance.js). */
#quote-tool .qt-sheet__assist-steps strong {
  color: var(--qt-ink);
  white-space: nowrap;
}

/* Step 1 says "to the right", which is only true in the desktop grid (panel in
   column 1, rate cards in column 2). Under 60em the panel drops below the cards
   — see the stacked step-3 rules in the max-width: 60em block — so the other
   span takes over and the sentence says "above". Exactly one is ever shown. */
#quote-tool .qt-assist-dir--above {
  display: none;
}

#quote-tool .qt-sheet__assist a {
  color: var(--qt-blue);
  /* A phone number never breaks across lines. */
  white-space: nowrap;
}

/* Y for All sign-up guide. Native dialog escapes the tool's clipped shell. */
#quote-tool .qt-assist-trigger {
  display: inline-flex;
  align-items: flex-start;
  gap: 8px;
  width: auto;
  max-width: 100%;
  min-height: 44px;
  height: auto;
  margin: 8px 0 0;
  padding: 10px 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--qt-blue);
  font: 700 var(--qt-text-label)/24px var(--qt-font-body);
  text-align: left;
  white-space: normal;
  cursor: pointer;
}

/* A stroked icon in the label's own blue, not the gradient badge this used to
   be: the badge was the heaviest mark in the panel, so a secondary link out-
   shouted the Y for All note it sits under and clashed with the stroked
   heart-handshake heading that icon set. Sized to the label, not to a chip. */
#quote-tool .qt-assist-trigger__icon {
  position: relative;
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  /* Optically centers on the first 24px text line, including when it wraps. */
  margin-top: 3px;
  border-radius: 50%;
  color: var(--qt-blue);
}

/* The icon has to fill the 18px box the pulse ring is measured against, where
   the base .icon rule would size it to 1.1em of the label. In both places the
   link sits: the rates panel and the Y for All step's qualifies card. */
#quote-tool .qt-sheet__assist .qt-assist-trigger__icon .icon,
#quote-tool .qt-fa-card .qt-assist-trigger__icon .icon {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  color: inherit;
}

#quote-tool .qt-assist-trigger__icon::after {
  content: '';
  position: absolute;
  inset: 0;
  border: 1px solid var(--qt-purple);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}

/* Three pulses until the guide has been opened once, from either link. The
   card's link starts pulsing when the card appears: an animation doesn't run
   while its element is display:none. */
#quote-tool.quote-tool--on-last .qt-assist-trigger:not([data-seen]) .qt-assist-trigger__icon::after,
#quote-tool .qt-fa-card .qt-assist-trigger:not([data-seen]) .qt-assist-trigger__icon::after {
  animation: qt-assist-pulse 1.6s ease-out 3;
}

@keyframes qt-assist-pulse {
  0% { transform: scale(1); opacity: .6; }
  100% { transform: scale(1.65); opacity: 0; }
}

#quote-tool .qt-assist-trigger:hover .qt-assist-trigger__icon {
  color: var(--qt-purple);
}

#quote-tool .qt-assist-trigger:hover .qt-assist-trigger__label {
  text-decoration: underline;
  text-underline-offset: 3px;
}

body.qt-assist-open { overflow: hidden; }

.qt-assist-guide {
  box-sizing: border-box;
  position: fixed;
  inset: auto;
  width: min(520px, calc(100vw - 32px));
  max-width: none;
  max-height: calc(100dvh - 32px);
  margin: 0;
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--qt-hairline);
  border-radius: var(--qt-radius-card);
  background: var(--qt-white);
  box-shadow: 0 16px 54px rgba(0, 52, 95, .24);
  color: var(--qt-ink);
  font-family: var(--qt-font-body);
  text-align: left;
}

.qt-assist-guide:not([open]), .qt-assist-guide [hidden] { display: none !important; }
.qt-assist-guide::backdrop { background: rgba(0, 32, 59, .2); }

.qt-assist-guide__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 12px 8px 24px;
  background: var(--qt-gradient);
  color: var(--qt-white);
}

.qt-assist-guide__eyebrow {
  margin: 0;
  font-size: var(--qt-text-small);
  line-height: 1.4;
  font-weight: 700;
  letter-spacing: .04em;
}
.qt-assist-guide__eyebrow span { margin: 0 5px; opacity: .6; }

.qt-assist-guide__close {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--qt-white);
  font: 300 30px/1 var(--qt-font-body);
  cursor: pointer;
}
.qt-assist-guide__close:hover { background: rgba(255, 255, 255, .16); }
.qt-assist-guide__copy { padding: 20px 24px 16px; }
.qt-assist-guide__title {
  margin: 0 0 8px;
  color: var(--qt-navy);
  font: 700 var(--qt-text-heading-min)/1 var(--qt-font-heading);
  letter-spacing: -1px;
}
/* Two lines tall at least, so a one-line step doesn't jump the video up. */
.qt-assist-guide__description {
  min-height: 48px;
  margin: 0;
  color: var(--qt-gray);
  font-size: var(--qt-text-body);
  line-height: 24px;
}
.qt-assist-guide__step { padding: 0 16px; }
.qt-assist-guide__video {
  display: block;
  width: 100%;
  height: auto;
  max-height: 48dvh;
  border: 1px solid var(--qt-hairline);
  border-radius: 10px;
  background: #f4f7fa;
  object-fit: contain;
}
.qt-assist-guide__error { margin: 8px 0; font-size: var(--qt-text-small); line-height: 1.5; }
.qt-assist-guide__error a { color: var(--qt-blue); text-decoration: underline; }
.qt-assist-guide__footer {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 24px 20px;
  background: var(--qt-white);
}
.qt-assist-guide__progress { display: flex; gap: 6px; margin-right: auto; }
.qt-assist-guide__progress span { width: 8px; height: 8px; border-radius: 50%; background: var(--qt-rule); }
.qt-assist-guide__progress .is-current { background: var(--qt-purple); }
.qt-assist-guide__next, .qt-assist-guide__back {
  min-height: 44px;
  margin: 0;
  border: 0;
  cursor: pointer;
  font: 700 var(--qt-text-label)/1 var(--qt-font-heading);
}
.qt-assist-guide__next {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 12px 22px;
  border-radius: var(--qt-radius-pill);
  background: var(--qt-gradient-pill);
  background-size: 300% 100%;
  color: var(--qt-white);
  transition: background-position .18s ease-in-out;
}
.qt-assist-guide__next:hover { background-position: 100% 0; }
.qt-assist-guide__back { padding: 0; background: none; color: var(--qt-blue); }
.qt-assist-guide__back:hover { color: var(--qt-purple); }
#quote-tool .qt-assist-trigger:focus-visible, .qt-assist-guide button:focus-visible,
.qt-assist-guide video:focus-visible, .qt-assist-guide a:focus-visible {
  outline: 3px solid var(--qt-purple);
  outline-offset: 3px;
}
.qt-assist-guide__close:focus-visible { outline-color: var(--qt-white) !important; }

@media (max-width: 767px) {
  .qt-assist-guide__header { padding-left: 20px; }
  .qt-assist-guide__copy { padding: 16px 20px; }
  .qt-assist-guide__footer { padding: 12px 20px 16px; }
  .qt-assist-guide__step { padding: 0 12px; }
}

@media (prefers-reduced-motion: reduce) {
  #quote-tool.quote-tool--on-last .qt-assist-trigger .qt-assist-trigger__icon::after,
  #quote-tool .qt-fa-card .qt-assist-trigger .qt-assist-trigger__icon::after { animation: none; }
  .qt-assist-guide__next { transition: none; }
}

@media (max-height: 500px) and (min-width: 568px) {
  .qt-assist-guide__header { padding-top: 2px; padding-bottom: 2px; }
  .qt-assist-guide__copy { padding: 10px 20px; }
  .qt-assist-guide__title { margin-bottom: 6px; }
  .qt-assist-guide__description { min-height: 0; }
  .qt-assist-guide__video { max-height: max(90px, calc(100dvh - 246px)); }
  .qt-assist-guide__footer { padding: 8px 20px; }
}

/* Step-3 body copy sits on the gradient — same anatomy as the other steps'
   qt-copy, opted to white. */
#quote-tool .qt-copy-rates .qt-copy__title {
  color: var(--qt-white);
}

#quote-tool .qt-copy-rates .qt-copy__text {
  color: var(--qt-white);
}

/* Confirmation ----------------------------------------------------------------
   The purple thank-you panel (gform_confirmation filter). .submitted is added
   by quoteTool.js at click time and re-asserted by gform_confirmation_loaded. */

#quote-tool.submitted .quote-tool__band {
  display: none;
}

/* Belt and braces: gform_confirmation_loaded does not fire for a custom
   confirmation string, so the on-last gradient could linger behind the panel. */
#quote-tool.submitted .quote-tool-container {
  background: none;
}

#quote-tool.submitted .quote-tool__body {
  padding: 0;
}

/* The purple thank-you panel closes the module itself. */
#quote-tool.submitted .quote-tool__foot {
  display: none;
}

#quote-tool .qt-confirm {
  display: flex;
  align-items: stretch;
  min-height: 520px;
  background: var(--qt-gradient-panel-purple);
  font-family: var(--qt-font-body);
}

#quote-tool .qt-confirm__media {
  flex: 0 0 40%;
  background-image:
    linear-gradient(156.86deg, rgba(147, 31, 141, 0.62) 0, rgba(91, 46, 145, 0.62) 52%),
    url(../../../images/quote-tool/gym-celebration.jpg);
  background-size: cover, cover;
  background-position: center, center;
  border-radius: var(--qt-radius-hero);
}

#quote-tool .qt-confirm__content {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 45px 40px;
  color: var(--qt-white);
}

#quote-tool .qt-confirm__eyebrow {
  margin: 0;
  font-size: var(--qt-text-small);
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
}

#quote-tool .qt-confirm__title {
  margin: 12px 0 0;
  font-family: var(--qt-font-heading);
  font-weight: 700;
  font-size: var(--qt-text-heading);
  line-height: 1;
  letter-spacing: -2px;
  color: var(--qt-white);
}

#quote-tool .qt-confirm__body {
  margin: 20px 0 0;
  max-width: 440px;
  font-size: var(--qt-text-body);
  font-weight: 300;
  line-height: 24px;
  text-wrap: pretty;
}

#quote-tool .qt-confirm__summary {
  max-width: 440px;
  margin-top: 0;
}

#quote-tool .qt-confirm__summary-title {
  max-width: 440px;
  margin: 28px 0 0;
  padding: 18px 0 6px;
  font-family: var(--qt-font-heading);
  font-size: var(--qt-text-card-subtitle);
  line-height: 22px;
  letter-spacing: -0.3px;
  border-top: 1px solid rgba(255, 255, 255, 0.35);
}

#quote-tool .qt-confirm__row {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 12px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.25);
}

#quote-tool .qt-confirm__row:last-child {
  border-bottom: 0;
}

#quote-tool .qt-confirm__row dt {
  font-size: var(--qt-text-small);
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
}

#quote-tool .qt-confirm__row dd {
  margin: 0;
  font-size: var(--qt-text-body);
  text-align: right;
}

/* The summary's Y for All pair, on its own line under the plan name: the
   standard price faded and slashed (the slash rule sits with the rate card's,
   above, at a gentler angle for the longer text), the reduced one in bold. */
#quote-tool .qt-confirm__price {
  display: block;
  margin-top: 4px;
}

#quote-tool .qt-confirm__was {
  position: relative;
  margin-right: 6px;
  color: rgba(255, 255, 255, 0.7);
  white-space: nowrap;
}

#quote-tool .qt-confirm__was::after {
  transform: rotate(-8deg);
}

#quote-tool .qt-confirm__now {
  font-weight: 700;
  white-space: nowrap;
}

#quote-tool .qt-confirm__actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  max-width: 720px;
  margin-top: 32px;
}

#quote-tool .qt-confirm__path {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 22px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 10px;
}

#quote-tool .qt-confirm__path-title {
  margin: 0;
  font-family: var(--qt-font-heading);
  font-size: var(--qt-text-card-title);
  line-height: 22px;
}

#quote-tool .qt-confirm__path-copy {
  margin: 8px 0 18px;
  font-size: var(--qt-text-small);
  line-height: 21px;
  color: rgba(255, 255, 255, 0.9);
}

/* DS ButtonWhite on the purple panel. */
#quote-tool .qt-confirm__cta {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 100%;
  min-height: 58px;
  margin-top: auto;
  padding: 16px 18px;
  background: var(--qt-white);
  color: #000;
  font-family: var(--qt-font-heading);
  font-size: var(--qt-text-label);
  line-height: 22.4px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  border: 1px solid var(--qt-white);
  border-radius: var(--qt-radius-photo);
  transition: all 0.18s ease-in-out;
}

#quote-tool .qt-confirm__cta:hover {
  background: transparent;
  color: var(--qt-white);
}

#quote-tool .qt-confirm__cta--secondary {
  background: transparent;
  color: var(--qt-white);
}

#quote-tool .qt-confirm__cta--secondary:hover {
  background: var(--qt-white);
  color: #000;
}

#quote-tool .qt-confirm__restart {
  align-self: flex-start;
  margin-top: 18px;
  color: var(--qt-white);
  font-size: var(--qt-text-label);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, 0.55);
}

#quote-tool .qt-confirm__restart:hover {
  text-decoration-color: currentColor;
}

#quote-tool .qt-confirm__note {
  margin: 28px 0 0;
  max-width: 440px;
  font-size: var(--qt-text-small);
  line-height: 21px;
  color: rgba(255, 255, 255, 0.9);
}

#quote-tool .qt-confirm__note a {
  color: var(--qt-white);
  text-decoration: underline;
}

/* Responsive ------------------------------------------------------------------
   Desktop-first; the DS ladder's 60em breakpoint does the heavy lifting. */

@media (max-width: 60em) {
  /* Every section heading takes the scale's narrow-viewport size. */
  :root {
    --qt-text-heading: var(--qt-text-heading-min);
  }

  #quote-tool {
    --qt-pad-x: 24px;
  }

  #quote-tool .quote-tool__band {
    padding-top: 30px;
    padding-bottom: 30px;
  }

  #quote-tool .quote-tool__foot {
    height: 10px;
  }

  /* Three labels plus their tokens will not sit side by side at this width, so
     the token stacks over its label and the column centres instead. */
  #quote-tool .quote-tool__progress span {
    height: 6px;
  }

  #quote-tool .quote-tool__steplabels span[data-step] {
    flex-direction: column;
    gap: 6px;
    text-align: center;
    letter-spacing: 0.3px;
  }

  #quote-tool .quote-tool__stepnum {
    width: 26px;
    height: 26px;
  }

  /* Step 1: photo strip above a single column. */
  #quote-tool .gform_page:has(.qt-copy-intro) .gform_page_fields {
    grid-template-columns: 1fr;
    gap: 25px;
  }

  #quote-tool .gform_page:has(.qt-copy-intro) .gform_page_fields::before {
    min-height: 180px;
  }

  /* Step 2: single column, map first (DOM order: copy, search, map, cards). */
  #quote-tool .gform_page:has(.quote-tool-map-field) .gform_fields {
    grid-template-columns: 1fr;
  }

  #quote-tool .gform_page:has(.quote-tool-map-field) .gform_fields > .gfield.quote-tool-step-copy,
  #quote-tool .gform_page:has(.quote-tool-map-field) .loc-finder__searchbar,
  #quote-tool .gform_page:has(.quote-tool-map-field) .loc-finder__msg,
  #quote-tool .quote-tool-map-field .shortcode-map,
  #quote-tool .gform_page:has(.quote-tool-map-field) .gfield.location-cards {
    grid-column: 1;
  }

  #quote-tool .quote-tool-map-field .shortcode-map {
    height: 320px;
  }

  /* Step 3: single column — the plans first, the Discounts & Add-Ons panel
     after them (DOM order). The panel used to lead, on the theory that
     discounts belong above the fold; on a phone it runs a full screen tall and
     pushed every plan below the fold instead (client note 2026-09-02). The
     list flows in full instead of scrolling. */
  #quote-tool .gform_page:has(.gfield.quote-tool-radio) .gform_fields {
    grid-template-columns: 1fr;
  }

  #quote-tool .gform_page:has(.gfield.quote-tool-radio) .gfield.quote-tool-sheet {
    grid-column: 1;
    grid-row: 3;
    align-self: auto;
  }

  #quote-tool .gform_page:has(.gfield.quote-tool-radio) .gfield.quote-tool-radio {
    grid-column: 1;
    grid-row: 2;
  }

  /* Cards above, panel below (the rows just set) — so step 1 of the Y for All
     copy has to point up, not right. */
  #quote-tool .qt-assist-dir--beside {
    display: none;
  }

  #quote-tool .qt-assist-dir--above {
    display: inline;
  }

  /* minmax(0, 1fr), not 1fr: a bare 1fr track can't go below its content's
     min-content width, so one unbreakable title word could push the cards past
     the column edge. */
  #quote-tool .quote-tool-radio .gfield_radio {
    grid-template-columns: minmax(0, 1fr);
    max-height: none;
    mask-image: none;
    -webkit-mask-image: none;
  }

  /* Confirmation stacks, photo on top. */
  #quote-tool .qt-confirm {
    flex-direction: column;
  }

  #quote-tool .qt-confirm__media {
    flex: none;
    min-height: 200px;
    border-radius: 0;
  }

  #quote-tool .qt-confirm__content {
    padding: 30px 24px;
  }

  /* Y for All: one column — the questions (or the result) first, the panel
     after them, as the rates step puts its cards before its panel. */
  #quote-tool .gform_page:has(.qt-fa-size) .gform_fields {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
  }

  #quote-tool .gform_page:has(.qt-fa-size) .gform_fields > .gfield {
    grid-column: 1;
  }

  #quote-tool .gform_page:has(.qt-fa-size) .gform_fields > .gfield.qt-fa-panel {
    grid-row: auto;
    margin-top: var(--gf-form-gap-y, 40px);
  }
}

@media (max-width: 48em) {
  #quote-tool .gform_page_footer.top_label {
    flex-direction: column-reverse;
    gap: 15px;
    align-items: stretch;
  }

  #quote-tool .gform_page_footer .gform_next_button,
  #quote-tool .gform_page_footer .gform_next_button:only-child,
  #quote-tool .gform_page_footer .gform_previous_button {
    width: 100%;
    margin-left: 0;
  }

  #quote-tool .gform_page:has(.qt-copy-intro) .gform_page_footer::before {
    order: 1;
    text-align: center;
  }

  #quote-tool .qt-confirm__actions {
    grid-template-columns: 1fr;
  }

  /* The stacked footer reads Next (or the status line while the questions
     wait), then Previous — the phone footer's own gap and full-width rows. */
  #quote-tool .gform_page:has(.qt-fa-size) .gform_page_footer {
    gap: 15px;
  }

  #quote-tool .gform_page:has(.qt-fa-size) .gform_page_footer .gform_previous_button {
    margin-right: 0;
  }

  #quote-tool .qt-fa-actions {
    justify-content: center;
    text-align: center;
  }

  #quote-tool .qt-fa-card {
    padding: 24px;
  }

  #quote-tool .qt-fa-code {
    flex-wrap: wrap;
  }
}

/* Phones: at the scale's 14px floor the four step names no longer fit side by
   side — MEMBERSHIP alone is wider than a quarter of the band under ~500px
   (measured 2026-09-29: 95px of text in a 93px column at 480px), and the
   columns then slide out from under the progress segments. The tokens keep
   the row; only the current step's name shows, on one line under its token,
   running into the neighbours' empty columns. The first and last names hug
   their outer edges so they never leave the band. */
@media (max-width: 32em) {
  #quote-tool .quote-tool__steplabels span[data-step] {
    min-width: 0;
  }

  #quote-tool .quote-tool__steplabels span[data-step]:not(.is-current) .quote-tool__steptext {
    display: none;
  }

  #quote-tool .quote-tool__steptext {
    white-space: nowrap;
  }

  #quote-tool .quote-tool__steplabels span[data-step]:first-child .quote-tool__steptext {
    align-self: flex-start;
  }

  #quote-tool .quote-tool__steplabels span[data-step]:last-child .quote-tool__steptext {
    align-self: flex-end;
  }
}
