/*
 * Patient Savings Card page. Loaded after components.css and patient-shell.css.
 *
 * THE PAGE IS WHITE — sampled at four points on the design rather than assumed.
 * `--plain` is right here; the T&C panel and the checkbox cards are the only
 * surfaces on the page.
 *
 * The form's own contract — why nothing here uses the `disabled` attribute, and
 * why the error is `hidden` rather than display-suppressed — is written out
 * above the form in affordability/index.html. Read that before changing the
 * gate styling below.
 */

.page {
  /* Patient CTAs are navy — the same page-scoped repoint every sibling
     patient page makes. It is what paints the Download button #214a82. */
  --color-cta: var(--color-isi-title-bar);

  /*
   * The form-control palette. Five literals with no upstream token between
   * them, and they only mean anything as a SET — each control reads one of
   * three states off it, so they are declared together rather than scattered
   * down the file:
   *
   *            card border   box border   label / button text   card fill
   *   gated      #ececec       #ececec         #d4d4d4            #fff
   *   resting    #ccc          #b5b5b5         #3a3a3a            #fff
   *   checked    #00306c       (filled)        #3a3a3a            #d1ddec
   */
  --form-stroke-gated: #ececec;
  --form-stroke-resting: #ccc;
  --form-box-stroke: #b5b5b5;
  --form-text-gated: #d4d4d4;
  --form-card-checked: #d1ddec;

  /* The one red on the patient site. */
  --form-error: #dc3545;

  /* The T&C panel: #f8f8f8 behind a #ccc rim, with the header bar a step
     darker at #dcdcdc and the scroll thumb #b3b3b3. */
  --tc-surface: #f8f8f8;
  --tc-header: #dcdcdc;
  --tc-thumb: #b3b3b3;
}

/*
 * Mobile gutter, 32px, matching every sibling patient page. The header is NOT
 * overridden — this page draws the shared partial's 159px 24/24/24.
 */
@media (width < 48rem) {
  main {
    --container-margin: var(--space-xl); /* 32px */
  }
}

/* ===============================================================
 * Page hero
 *
 * Mobile CENTRES the column — the tell is the 80px rule sitting dead centre of
 * the 366 column — while desktop is left-aligned with the same rule at x=0.
 * 56px either side on mobile; 104/56 on desktop.
 *
 * The title pair (28/1.4 mobile, 40/1.1 desktop) comes free from
 * components.css's `--plain` modifier and is not restated here. The desktop
 * title frame reports 48px against the 44px a single 40/1.1 line occupies, so
 * the title is built at the honest 44 with the rule hung 16px off it, exactly
 * as Learn About's hero is, and the two heroes stay in step.
 * ============================================================= */

.savings-hero__inner {
  padding-block: 3.5rem;
  text-align: center;
}

.savings-hero__inner .page-hero__rule {
  margin-block-start: var(--space-m);
  margin-inline: auto;
}

.page-hero__lede {
  margin-block: var(--space-m) 0;
  color: var(--color-text-body);
  font-family: var(--font-heading);
  font-size: var(--font-size-body); /* 16px mobile */
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-body); /* 1.45 */
  letter-spacing: var(--tracking-isi-text);
}

@media (width >= 68rem) {
  .savings-hero__inner {
    padding-block: 6.5rem 3.5rem; /* 104px / 56px */
    text-align: start;
  }

  .savings-hero__inner .page-hero__rule {
    margin-inline: 0;
  }

  .page-hero__lede {
    max-inline-size: 39.5rem; /* 632px */
    font-size: var(--font-size-body-lg); /* 20px */
    letter-spacing: var(--tracking-body-lg);
  }
}

/* ===============================================================
 * The form band
 *
 * The band has no top padding of its own: the hero's own 56px bottom padding
 * carries the whole gap, so the panel starts flush at the hero's edge.
 * ============================================================= */

.savings-form-section {
  padding-block: 0 4rem; /* 64px below on mobile */
}

/*
 * Two 652px columns either side of a 40px gutter in the 1344 container. `1fr
 * 1fr` with that gap reproduces 652 exactly at the container cap, and collapses
 * to one column below the breakpoint, which is the mobile arrangement.
 */
.savings-form {
  display: grid;
  gap: 2.5rem; /* 40px */
}

@media (width >= 68rem) {
  .savings-form-section {
    padding-block: 0 6.5rem; /* 104px */
  }

  .savings-form {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
}

/* ---------------------------------------------------------------
 * Terms & Conditions — the scroll gate itself
 * ------------------------------------------------------------- */

/*
 * A FIXED-HEIGHT box holding roughly three and a half times its own height in
 * content. That overflow is not an accident to be tidied away — it IS the
 * gate. Give this panel `block-size: auto` and the terms stop scrolling, the
 * end condition is true at load, and the attestation is never read.
 *
 * It is also A COLUMN, with the header in flow above the scroller rather than
 * overlaid on a full-height one. The scroll track runs the scroller's whole
 * height, so under an overlay its top 71px sit behind the opaque grey bar and
 * the thumb only appears once it has scrolled clear. The bar has to cover the
 * TEXT and must not cover the TRACK, and both belong to the same element — so
 * no z-index arrangement resolves it. Taking the header out of the overlay
 * does: the scroller then begins below the bar and its track begins with it.
 *
 * The reader sees the same thing either way. The bar is opaque, so text
 * vanishing beneath it and text clipped at the scroller's top edge are the same
 * picture; only the scrollbar's origin moves.
 */
.tc-panel {
  display: flex;
  position: relative;
  flex-direction: column;
  overflow: hidden;
  block-size: 23.0625rem; /* 369px */
  border: var(--border-width) solid var(--form-stroke-resting);
  border-radius: var(--radius-sm);
  background-color: var(--tc-surface);
}

@media (width >= 68rem) {
  .tc-panel {
    block-size: 43.125rem; /* 690px */
  }
}

/*
 * Drawn as a bar the terms slide underneath and which never leaves, with the
 * content padded clear of it.
 *
 * It is the column's FIRST ITEM, not an absolute overlay — still always
 * visible, because only the scroller below it moves, and the bar is opaque so
 * the terms still disappear at its edge. What that buys is the scroller, and
 * with it the scroll track, beginning underneath the bar rather than behind it.
 */
.tc-panel__header {
  flex: 0 0 auto;
  margin: 0;
  padding: var(--space-m) var(--space-l); /* 16 / 24 */
  background-color: var(--tc-header);
  color: var(--color-black);
  font-family: var(--font-heading);
  font-size: var(--font-size-ui); /* 14px */
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-snug); /* 1.4 — two lines on mobile */
  letter-spacing: var(--tracking-tight);
  text-align: center;
}

/*
 * THE MEASURE GOES ON THE SENTENCE, NOT ON THE BAR. Mobile holds the text to
 * 220px so it breaks across two lines as drawn; desktop releases it and runs
 * one line at the tighter 1.1. That pair is the panel's ONLY per-breakpoint
 * divergence — heading, body, padding and every colour are identical at both
 * widths.
 *
 * Put `max-inline-size` on `.tc-panel__header` instead and the BACKGROUND
 * shrinks with the text: the bar stops spanning the panel and reads as a grey
 * tablet floating in the middle of it.
 */
.tc-panel__header-text {
  display: block;
  max-inline-size: 13.75rem; /* 220px */
  margin-inline: auto;
}

@media (width >= 68rem) {
  .tc-panel__header {
    line-height: var(--line-height-tight); /* 1.1 — one line */
  }

  .tc-panel__header-text {
    max-inline-size: none;
  }
}

/*
 * `scroll`, not `auto`, and the difference is not cosmetic: with `auto` a
 * container whose content only just overflows can lose its scrollbar, gain
 * 18px of measure, stop overflowing, and oscillate. Reserving the track makes
 * the text measure below deterministic at both breakpoints.
 *
 * Padding: 24 leading / 20 trailing, plus the 18px track, reproduces the drawn
 * text measure exactly — 588px inside the 652 desktop panel and 302px inside
 * the 366 mobile one.
 */
.tc-panel__scroll {
  /*
   * Takes the column's remaining height. `min-block-size: 0` is required or the
   * flex minimum would hold it at its content height and the panel would grow
   * past 369/690 instead of scrolling.
   *
   * The top padding is 16px at BOTH breakpoints, measured from the bar rather
   * than from the panel: the bar is 71.2px on mobile and 47.4 on desktop, so 16
   * after it puts the first line within a pixel of where the design does.
   */
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: scroll;
  padding-block: var(--space-m); /* 16 */
  padding-inline: var(--space-l) 1.25rem; /* 24 / 20 */
}

/*
 * The drawn thumb is a 5px bar inset 13.5px from the panel's edge — a shape no
 * native scrollbar takes, because a native one sits flush. A wide track with a
 * transparent trailing border and `content-box` clipping paints exactly that
 * 5px bar in exactly that position, and the track width is what the measure
 * arithmetic above is counting.
 *
 * Physical properties on purpose: a scrollbar is a physical artefact and the
 * pseudo-elements do not honour logical ones.
 */
.tc-panel__scroll::-webkit-scrollbar {
  width: 18px;
}

.tc-panel__scroll::-webkit-scrollbar-track {
  background-color: transparent;
}

.tc-panel__scroll::-webkit-scrollbar-thumb {
  border-right: 13px solid transparent;
  border-radius: 20px;
  background-color: var(--tc-thumb);
  background-clip: content-box;
}

/*
 * Firefox gets the colour but not the inset. Guarded rather than declared
 * alongside, because Chromium 121+ ALSO honours `scrollbar-width` and drops
 * every ::-webkit-scrollbar rule above the moment it is set — the two cannot
 * simply be listed together.
 */
@supports not selector(::-webkit-scrollbar) {
  .tc-panel__scroll {
    scrollbar-width: thin;
    scrollbar-color: var(--tc-thumb) transparent;
  }
}

.tc-panel__heading {
  margin: 0 0 var(--space-s); /* 8px to its own list */
  color: var(--color-brand-primary);
  font-family: var(--font-heading);
  font-size: var(--font-size-lead); /* 18px */
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-tight); /* 1.1 */
  letter-spacing: var(--tracking-tight);
}

/*
 * THREE LISTS, and they must stay lists: base.css strips markers from every
 * classed list, so `disc` is asked for explicitly here, and a flattening to
 * paragraphs would change nothing else a reader could point at.
 *
 * 21px of leading padding puts each item's text where the design puts it, with
 * the marker in the space that opens up. The 24px to the next heading is the
 * drawn 8px gap either side of a spacer rectangle.
 */
.tc-panel__list {
  margin: 0 0 var(--space-l); /* 24px */
  padding-inline-start: 1.3125rem; /* 21px */
  list-style-type: disc;
  color: var(--color-black);
  font-family: var(--font-heading);
  font-size: var(--font-size-ui); /* 14px */
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-loose); /* 1.6 */
  letter-spacing: var(--tracking-isi-text);
}

.tc-panel__list:last-child {
  margin-block-end: 0;
}

/* ---------------------------------------------------------------
 * The controls column
 * ------------------------------------------------------------- */

/*
 * No `gap` here on purpose. Three of the four gaps in this column are 24px, but
 * the error's is not — 13px on desktop, 8px on mobile — so a container gap
 * would have to be cancelled with a negative margin on the one element whose
 * position matters most. Explicit margins instead.
 */
.savings-form__controls {
  display: flex;
  flex-direction: column;
}

.savings-card-figure,
.attestations {
  margin-block-end: var(--space-l); /* 24px */
}

/*
 * The card raster sits ABOVE the checkboxes on desktop and BELOW the button —
 * and below the error — on mobile, 40px clear of the block above in both
 * arrangements. `order` rather than a DOM swap, so one markup serves both.
 */

/*
 * CAPPED at the drawn 652px figure. The aspect was never the problem — this box
 * has always been locked at 565/338 — but single-column it simply kept growing
 * with the column, reaching a savings card that fills a tablet screen.
 * `inline-size: 100%` alongside the auto margins so it still fills at the
 * narrow width rather than collapsing to content width in this flex column.
 */
.savings-card-figure {
  position: relative;
  inline-size: 100%;
  max-inline-size: 40.75rem; /* 652px */
  overflow: hidden;
  order: 1;
  margin-block: 2.5rem 0; /* 40px above, as the last item on mobile */
  margin-inline: auto;
  border-radius: 1.25rem; /* 20px */
  aspect-ratio: 565 / 338;
}

/*
 * The design frame CROPS its image fill, and the export is the uncropped
 * source — white margin and soft shadow included — so the crop is reproduced
 * here rather than baked into the raster. Displayed at 100% the card would sit
 * inside a visible rim of its own background.
 *
 * THESE FOUR NUMBERS ARE MEASURED FROM THE SHIPPED RASTER, not taken from the
 * design's own fill percentages: those describe the bitmap the design file
 * holds, whose white margins are a different width, so they do not transfer to
 * the asset we ship. What the design draws is simply the card body filling the
 * frame edge to edge, so the values below map the body's measured box in THIS
 * raster — x 40..1460, y 17..835 of 1512x866 — onto the frame:
 *
 *   inline-size          1512 / 1421 = 106.4039%
 *   block-size            866 /  819 = 105.7387%
 *   inset-inline-start   -  40 / 1421 =  -2.8149%
 *   inset-block-start    -  17 /  819 =  -2.0757%
 *
 * Re-measure them if the raster is ever re-exported; they belong to the file,
 * not to the design. The ~3.8% horizontal squeeze this implies is drawn that
 * way too.
 *
 * `max-inline-size: none` overrides base.css's blanket `img { max-inline-size:
 * 100% }`, which would otherwise shrink the deliberately-oversized fill back
 * to the frame and undo the crop.
 */
.savings-card-figure img {
  position: absolute;
  inset-block-start: -2.0757%;
  inset-inline-start: -2.8149%;
  inline-size: 106.4039%;
  block-size: 105.7387%;
  max-inline-size: none;
}

/* A two-stop wash over the card at the same 20px radius. */
.savings-card-figure::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: linear-gradient(
    203.4274deg,
    rgb(0 0 0 / 10%) 19.473%,
    rgb(255 255 255 / 10%) 97.232%
  );
}

@media (width >= 68rem) {
  .savings-card-figure {
    order: 0;
    margin-block: 0 var(--space-l); /* back above the checkboxes, 24px clear */
  }
}

/* A fieldset needs all three resets before it will behave as a flex column. */
.attestations {
  display: flex;
  flex-direction: column;
  gap: var(--space-s); /* 8px */
  min-inline-size: 0;
  margin-inline: 0;
  padding: 0;
  border: 0;
}

/*
 * The whole card is the <label>, so its entire 652x68 surface toggles the box
 * with no script — which is also what makes the no-JS baseline usable rather
 * than merely present.
 */
.attestation {
  display: flex;
  align-items: center;
  gap: var(--space-m); /* 16px */
  padding: var(--space-m); /* 16px */
  border: var(--border-width) solid var(--form-stroke-resting);
  border-radius: var(--radius-sm); /* 8px */
  background-color: var(--color-white);
  cursor: pointer;
}

.attestation__input {
  appearance: none;
  flex-shrink: 0;
  inline-size: 1.5rem;
  block-size: 1.5rem;
  margin: 0;
  border: var(--border-width) solid var(--form-box-stroke);
  border-radius: var(--space-xs); /* 4px */
  background-color: var(--color-white);
  cursor: pointer;
}

/*
 * `print-color-adjust` because a checked attestation that prints as an empty
 * outline misrepresents what the patient agreed to — the fill and the tick are
 * the state, not decoration.
 */
.attestation__input:checked {
  border-color: var(--color-brand-primary);
  background-color: var(--color-brand-primary);
  background-image: url("../img/icon-checkbox-tick.svg");
  background-position: center;
  background-repeat: no-repeat;
  background-size: 0.7902rem 0.6777rem; /* 12.6429 x 10.8429 */
  print-color-adjust: exact;
}

.attestation:has(.attestation__input:checked) {
  border-color: var(--color-brand-primary);
  background-color: var(--form-card-checked);
  print-color-adjust: exact;
}

.attestation__label {
  color: var(--color-text-body);

  /* Inter, not Manrope. The one place on the patient site --font-support
     carries a control label. */
  font-family: var(--font-support);
  font-size: var(--font-size-body-sm); /* 13px */
  line-height: var(--line-height-snug); /* 1.4 */
  letter-spacing: var(--tracking-isi-text);
}

.savings-form__submit {
  inline-size: 100%;
}

/* ---------------------------------------------------------------
 * The gated (pre-scroll) appearance
 *
 * Styling ONLY. Every control below is still enabled, still focusable and
 * still counted by constraint validation — the greyed look is a class, never
 * the `disabled` attribute, because a disabled control is barred from
 * validation and would make this form report itself valid with zero
 * attestations captured. What actually holds the gate shut is the submit
 * handler in savings-card.js; this block only has to look the part.
 * ------------------------------------------------------------- */

/*
 * `pointer-events` goes on the CARD, not on the box inside it — and that is
 * not a tidying preference. Each card IS the `<label>`, and label activation
 * is not pointer hit-testing: it forwards to the labelled control whatever
 * that control's own `pointer-events` says. Put the block on
 * `.attestation__input` and it blocks nothing at all, leaving the whole card
 * clickable while it draws the disabled state.
 *
 * Blocked on the card, the POINTER path is genuinely shut and the keyboard
 * path deliberately is not — `pointer-events` has no bearing on focus or on
 * the space key. That carve-out is the intended one: the submit-time guard in
 * savings-card.js is the enforcement, and a control the keyboard cannot
 * reach would be a worse defect than an early tick the gate still refuses.
 */
.savings-form[data-gate="closed"] .attestation {
  border-color: var(--form-stroke-gated);
  cursor: default;
  pointer-events: none;
}

.savings-form[data-gate="closed"] .attestation__input {
  border-color: var(--form-stroke-gated);
}

.savings-form[data-gate="closed"] .attestation__label {
  color: var(--form-text-gated);
}

.savings-form[data-gate="closed"] .savings-form__submit {
  background-color: var(--form-stroke-gated);
  color: var(--form-box-stroke);
}

/* ---------------------------------------------------------------
 * The error
 * ------------------------------------------------------------- */

/*
 * No `display` declaration anywhere on this selector, and that absence is
 * load-bearing: an author `display` outranks the UA's `[hidden]` rule, so
 * adding one here would render the message permanently.
 *
 * 13px below the button on desktop, 8px on mobile.
 */
.savings-form__error {
  margin: var(--space-s) 0 0; /* 8px — mobile */
  color: var(--form-error);
  font-family: var(--font-support);
  font-size: var(--font-size-ui); /* 14px */
  line-height: var(--line-height-snug); /* 1.4 */
  letter-spacing: var(--tracking-isi-text);
  text-align: center;
}

@media (width >= 68rem) {
  .savings-form__error {
    margin-block-start: 0.8125rem; /* 13px */
  }
}
