/* ============================================================
   25 — THE SAVINGS ENGINE
   Numbered spine on the left, one artefact beside it whose three
   panels carry the same numerals. Panel N is step N; the panel
   matching the step under the reader's eye is raised by a ring,
   and the other two are left alone — the only other way to signal
   focus on a money table is to dim two thirds of it, which puts
   13px figures at 1.4–1.9:1.

   Every figure, every stacked-bar segment and every row swatch is
   written from window.Pyncht by the IIFE at the end of the partial.
   ============================================================ */

.sv {
  --sv-gap: clamp(var(--s-10), 7vw, var(--s-13));   /* head → body → result */
  --sv-num: var(--s-8);                             /* the numbered disc */
  --sv-vis: 29rem;                                  /* artefact measure */
}

/* --c-brand on --surface-alt is 4.45:1 — a hair under. The pressed
   brand is 5.83:1 and reads identically at 14px uppercase. */
.sv__eyebrow { color: var(--c-brand-press); }

/* ---------- head ---------- */

.sv__title {
  margin-top: var(--s-4);
  max-width: 24ch;
}

.sv__lead {
  margin-top: var(--s-5);
  max-width: 62ch;
}

/* ---------- body: spine + artefact ---------- */

.sv__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, var(--sv-vis));
  align-items: start;
  gap: clamp(var(--s-9), 5vw, var(--s-12));
  margin-top: var(--sv-gap);
}

/* ---------- the spine ---------- */

.sv__step {
  position: relative;
  display: grid;
  grid-template-columns: var(--sv-num) minmax(0, 1fr);
  gap: var(--s-5);
  padding-bottom: var(--s-10);
}
.sv__step:last-child { padding-bottom: 0; }

/* hairline connector: starts under the disc, fades out before the next one
   so the run never reads as a hard rule */
.sv__step::before {
  content: "";
  position: absolute;
  left: calc(var(--sv-num) / 2);
  top: var(--sv-num);
  bottom: 0;
  width: 1px;
  transform: translateX(-50%);
  background: linear-gradient(
    to bottom,
    var(--c-hairline) 0%,
    var(--c-hairline) 62%,
    transparent 100%);
}
.sv__step:last-child::before { content: none; }

/* the disc and the panel numeral are the same object at two sizes — that
   sameness is the whole linkage between the spine and the artefact */
.sv__num,
.sv__panel-num {
  display: grid;
  place-items: center;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--c-brand-tint);
  color: var(--c-brand-press);        /* 5.42:1 on the tint; --c-brand is 4.14 */
  font-weight: var(--fw-semi);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-normal);
}
.sv__num {
  width: var(--sv-num);
  height: var(--sv-num);
  font-size: var(--fs-sm);
}
.sv__step-title {
  font-size: var(--fs-h4);
  color: var(--text-strong);
  /* optical: sits the cap height on the disc's numeral, not its box */
  margin-top: calc(var(--s-2) - 1px);
}

.sv__step-copy {
  margin-top: var(--s-3);
  max-width: 46ch;
}

.sv__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-5);
}
.sv__tag {
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-pill);
  border: 1px solid var(--c-hairline);
  background: var(--c-white);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--text-body);
  letter-spacing: var(--tracking-snug);
  line-height: var(--lh-normal);
}

/* ---------- the artefact ---------- */

.sv__artefact {
  padding: var(--s-4);
  border-radius: var(--r-xl);
  background: var(--c-white);
  box-shadow: var(--sh-lg), 0 0 0 1px color-mix(in srgb, var(--c-navy) 5%, transparent);
}

.sv__panel {
  padding: var(--s-4);
  border-radius: var(--r-lg);
  transition: box-shadow var(--t-base) var(--ease-out);
}
.sv__panel + .sv__panel { margin-top: var(--s-2); }
.sv__panel + .sv__panel::before {
  content: "";
  display: block;
  height: 1px;
  margin: calc(var(--s-4) * -1) calc(var(--s-2) * -1) var(--s-4);
  background: var(--c-hairline-soft);
  transition: opacity var(--t-base) var(--ease-out);
}
/* the raised panel is the one whose step you are reading; the ring is
   colour and elevation only, so no figure loses contrast to it */
.sv__panel.is-active {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--c-brand) 30%, transparent), var(--sh-sm);
}
.sv__panel.is-active::before,
.sv__panel.is-active + .sv__panel::before { opacity: 0; }

.sv__panel-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
.sv__panel-num {
  width: var(--s-7);
  height: var(--s-7);
  font-size: var(--fs-xs);
}
.sv__panel-title {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  color: var(--text-strong);
  letter-spacing: var(--tracking-snug);
  min-width: 0;
}
.sv__badge {
  display: inline-flex;
  align-items: center;
  height: var(--s-6);
  margin-left: auto;
  padding-inline: var(--s-3);
  flex: none;
  border-radius: var(--r-pill);
  border: 1px solid var(--c-hairline);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  color: var(--text-body);
  letter-spacing: var(--tracking-snug);
  font-variant-numeric: tabular-nums;
}
.sv__badge--rate {
  border-color: transparent;
  background: var(--c-brand-tint);
  color: var(--c-brand-press);        /* 5.42:1 on the tint; --c-brand is 4.14 */
}
.sv__badge--on {
  border-color: transparent;
  background: color-mix(in srgb, var(--c-lime) 34%, var(--c-white));
  color: var(--c-navy);               /* 14.01:1 on the mixed lime */
}

/* -- connect: four facts -- */

/* 2×2 rather than four stacked rows — the connect step is the least
   interesting of the three and should not own the most vertical space */
.sv__facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-4) var(--s-6);
  margin: var(--s-4) 0 0;
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
}
.sv__fact dt { color: var(--text-body); }
.sv__fact dd {
  margin: var(--s-1) 0 0;
  font-weight: var(--fw-semi);
  color: var(--text-strong);
  letter-spacing: var(--tracking-snug);
  font-variant-numeric: tabular-nums;
}
.sv__per {
  margin-left: .08em;
  font-weight: var(--fw-medium);
  color: var(--text-body);
  letter-spacing: var(--tracking-normal);
}

/* -- analyse / recover: one stacked bar, then the named lines -- */

/* Seven categories spanning 100:2 cannot each own a 4px track — four of
   them come out empty and read as skeletons. One 100%-wide stacked bar
   spends the width on the shape of the distribution instead, and the
   smallest slice is still a visible sliver at 360px. */
.sv__dist {
  display: flex;
  height: var(--s-2);
  margin-top: var(--s-4);
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--c-hairline-soft);
}
.sv__seg {
  flex: 0 0 var(--w, 0%);
  min-width: 1px;                           /* guard; the smallest real slice is ~4px */
  border-right: 1px solid var(--c-white);   /* hairline split between slices */
}
.sv__seg:last-child { border-right: 0; }

/* --tone ramps each slice from full ink to a pale tint, so adjacent
   slices stay separable and the row swatch below keys row → slice.
   Cost is inked in navy, recovery in brand: two different quantities. */
.sv__dist--cost .sv__seg,
.sv__lines--cost .sv__line::before {
  background: color-mix(in srgb, var(--c-navy) var(--tone, 100%), var(--c-white));
}
.sv__dist--gain .sv__seg,
.sv__lines--gain .sv__line::before {
  background: color-mix(in srgb, var(--c-brand) var(--tone, 100%), var(--c-white));
}

.sv__lines { margin-top: var(--s-4); }
.sv__line {
  display: grid;
  grid-template-columns: var(--s-2) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-3);
  padding-block: var(--s-1);
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
}
/* the swatch: decorative, and the row states its own name and amount */
.sv__line::before {
  content: "";
  width: var(--s-2);
  height: var(--s-2);
  border-radius: var(--r-xs);
}
.sv__line-name {
  color: var(--text-body);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sv__line-amt {
  font-weight: var(--fw-semi);
  color: var(--text-strong);
  letter-spacing: var(--tracking-snug);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.sv__sum {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  margin-top: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--c-hairline);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--text-body);
  letter-spacing: var(--tracking-snug);
}
.sv__sum-amt {
  font-size: var(--fs-h4);
  font-weight: var(--fw-semi);
  color: var(--text-strong);
  letter-spacing: var(--tracking-tight);
  font-variant-numeric: tabular-nums;
}
.sv__sum--gain .sv__sum-amt { color: var(--c-brand); }
/* the period rides on the figure, a step down so it reads as a unit and not
   as part of the number — one card holds a monthly total and an annual one */
.sv__sum-amt .sv__per { font-size: var(--fs-sm); }

/* ---------- result strip ---------- */

.sv__result {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-6) var(--s-9);
  margin-top: var(--sv-gap);
  padding: var(--s-7);
  border-radius: var(--r-lg);
  background: var(--c-white);
  box-shadow: var(--sh-sm);
}

/* three equal columns, not a wrapping flex row: at 768 a flex row broke
   2 + 1 and orphaned the third figure under the section's closing line */
.sv__figures {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  flex: 1 1 26rem;
  gap: var(--s-5) var(--s-7);
  margin: 0;
}
.sv__figure { min-width: 0; }
.sv__figure-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--text-body);
  letter-spacing: var(--tracking-snug);
}
.sv__figure-value {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: var(--s-2) 0 0;
  font-variant-numeric: tabular-nums;
}
.sv__was {
  font-size: var(--fs-h4);
  font-weight: var(--fw-medium);
  color: var(--text-body);           /* 18px/500 is normal text: needs 4.5:1 */
  letter-spacing: var(--tracking-tight);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--c-slate-light) 60%, transparent);
}
.sv__to { flex: none; color: var(--text-muted); }
.sv__now {
  font-size: var(--fs-h3);
  font-weight: var(--fw-semi);
  color: var(--text-strong);
  letter-spacing: var(--tracking-tight);
  line-height: var(--lh-snug);
}

/* .arrow-link is a 15px inline-flex with no line-height of its own, so it
   inherits 1.62 → ~24px. This is the section's only link: clear the 44px
   touch target from a token (--s-9 is 48px) without touching the shared
   primitive. */
.sv__link {
  flex: none;
  min-height: var(--s-9);
  align-items: center;
}

/* ---------- honesty line ---------- */

.sv__note {
  margin-top: var(--s-5);
  max-width: 74ch;
  font-size: var(--fs-xs);
  line-height: var(--lh-normal);
  color: var(--text-body);
}

/* ---------- responsive ---------- */

/* The artefact gives width back before the spine is squeezed. At a fixed
   29rem the copy column measured 369px at 1024 — narrower than the
   illustration beside it, with the tag rows wrapping to two lines. The widest
   tag row needs 420px of body, i.e. ~480px of column once the numbered
   gutter is paid; 24rem here keeps the column above that to the stack point. */
@media (max-width: 1119px) {
  .sv { --sv-vis: 24rem; }
}

/* Below 1024 the two columns cannot both keep a usable measure, so the
   artefact goes under the spine rather than the copy going to a ribbon. */
@media (max-width: 1023px) {
  .sv__body {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-11);
  }
  .sv__visual { max-width: var(--sv-vis); }
  .sv__step { padding-bottom: var(--s-9); }
}

@media (max-width: 599px) {
  .sv__figures { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 560px) {
  .sv {
    --sv-num: var(--s-7);
  }
  .sv__step { gap: var(--s-4); }
  .sv__step-title { margin-top: 0; }
  .sv__artefact { padding: var(--s-3); }
  .sv__panel { padding: var(--s-3); }
  .sv__result { padding: var(--s-6); }
  .sv__figures { gap: var(--s-5); }
}
