/* ==========================================================================
   PACKAGE DETAILS — the fourth step of the results journey
   ==========================================================================
   Scope: `.qpd`, stamped on the root next to `.qr .qc` by PackageDetailsStep.

   WHY THIS FILE EXISTS
   --------------------
   This screen was ported with Tailwind utilities for everything except the
   rail. Tailwind sets size and weight but never `font-family`, so every string
   in the main column fell through to the app shell's own body font (Inter, set
   in app/layout.tsx) while the rest of the journey renders in the design's
   Instrument Sans / Host Grotesk / Geist. Same page, two typefaces — which is
   what "the font is not matching the other pages" was.

   So the chrome here is the design's OWN markup wherever the design already
   has it — `.qr-tabs`/`.qr-tab*` for the stepper (the Customise page's
   stepper, cell for cell), `.qr-specs` for the bullets, `.qr-price-cap` /
   `.qr-price-val` for the two figures, `.qr-cta` for the CTA, `.qr-side-card`
   for the rail. Only what the design has no class for is authored below, and
   it is authored in the same tokens: `--font-sans`, `--font-display`,
   `--font-ui`, `--ink`, `--accent`, `--radius`.

   Loaded AFTER quote-customize.css, because the two blocks it re-places
   (`.qc-pkg`'s interior and `.qr-tabs`'s width) are declared there and in
   quote-results.css.
   ========================================================================== */

/* ==========================================================================
   1. THE RAIL — the chosen package, its price, and the way forward
   ==========================================================================
   `.qc-pkg` is the Customise rail's card: a 356x392 box at card-relative
   (0,128) with a masked lime -> #869435 gradient ring, holding the product art
   at (20,20). Reused verbatim so the card is identical across the journey.

   What changes is only its INTERIOR. Customise puts a title and a "What's
   included" chip at authored y's (272 / 340); this screen puts the price pair
   and the CTA there instead — the title lives in the main column here, where
   there is room for a sixty-character catalogue name.

   FLOW, not authored y's. The figures are real money (£10,860 or £128,940.50)
   and the CTA label is tenant copy, so a fixed y for each would let a long
   value slide under the button. `height: auto` + a padding-top that clears the
   art means each block pushes the next one down.

   ITS HEIGHT IS A CONSTRAINT, NOT A FREE VARIABLE. The rail's lower cluster —
   `.qr-rule`, `.qr-trust`, `.qr-help`, `.qr-fab` — is BOTTOM-anchored to the
   card, the topmost of them (`.qr-rule`) at `bottom: 9.125rem`, so the last
   148 of the card is spoken for. The budget:

   FIGMA (Details frame) STATES THE WHOLE CARD: Frame 1707481526 is 356 x 458
   at (40,140) of the rail, i.e. card-relative (28,128). Its interior is fixed
   by two more nodes — Vector 11, the lime rule, at y288, and Link-Solid-Black,
   the CTA, at y394 x 44 — and the four parts reconcile to the 458 exactly:

     288  padding-top     = the art, then Figma's own gap to the rule
     106  the price group = Vector 10's own height (see §1b)
      44  the CTA, which starts at 288 + 106 = 394, its stated y
      20  padding-bottom
     ---
     458  of card, at card-relative 128   <- Figma's own height

   128 + 458 + 148 = 734 of card, i.e. 758 of rail — which is why the floor
   below is raised from the 39rem quote-results.css sets. Under that floor the
   page simply scrolls the rail, which is the fallback that sheet already
   documents for its own content. */
.qpd .qc-pkg {
  height: auto;
  /* 18 across, not the design system's usual 20: the CTA is stated 316 wide
     at x20 of a 356 card, and 356 - 20 - 20 = 316 measures from the card's
     OUTER edge. Its 2px border is inside, so a 20 padding leaves only 312 of
     content box. 18 + the 2 of border = Figma's 20, and the CTA lands on 316. */
  padding: 18rem 1.125rem 1.25rem;                  /* 288 / 18 — Vector 11's y */
}

/* ==========================================================================
   1a. THE BACK PILL — Frame 113 and its two children
   ==========================================================================
   quote-customize.css authors this pill for the CUSTOMISE rail, where the
   label is "Back to results" and Figma puts the row at x228. The Details
   frame states its own values, and all three differ:

     Frame 113          hug 89 x 48 at (307, 46), gap 8, padding [4,,4,]
                        307 + 89 = 396 = the card's 436 less 40, i.e. the row
                        ends on the same 40 inset the logo starts from
     Link-Solid-Black   40 x 40, radius 12, fill AND 2px border #111111 @ 4%
     Arrow Icon         28 x 28 at (6,6), rotation -180  (a flipped arrow)
     Back (text)        Instrument Sans 500 Medium, 18 / 100% / -0.16,
                        #111111 @ 70%

   Right-anchored rather than set to x307: the row hugs its label, and a
   right-inset holds Figma's 40 gutter whatever the label's length.
   `.qpd`-scoped so the Customise rail keeps its own. */
.qpd .qc-back {
  left: auto;
  right: 2.5rem;                                    /* 396 = 436 - 40 */
}
.qpd .qc-back-chip {
  border-radius: var(--radius);                     /* 12, not 8 */
  background: rgba(17, 17, 17, 0.04);               /* @4% */
  box-shadow: inset 0 0 0 0.125rem rgba(17, 17, 17, 0.04);  /* its 2px, inside */
}
.qpd .qc-back-chip img { width: 1.75rem; height: 1.75rem; }  /* 28 */
.qpd .qc-back-label {
  font-family: var(--font-sans);                    /* Instrument Sans */
  font-weight: 500;                                 /* Medium */
  font-size: 1.125rem;                              /* 18 */
  line-height: 1.125rem;                            /* 100% */
  letter-spacing: -0.01rem;                         /* -0.16 */
  color: var(--ink-70);                             /* @70% */
}

/* The floor the budget above needs. quote-results.css sets 39rem for a card
   whose content ends at 452; this screen's ends at 586, so the rail needs 758
   before the package card and the bottom cluster would meet. */
.qpd .qr-side { min-height: 47.375rem; }            /* 758 */

/* --------------------------------------------------------------------------
   1b. THE PRICE GROUP — quote-submit.css's Group 34, on this rail
   --------------------------------------------------------------------------
   THIS IS THE SUBMIT RAIL'S BLOCK, NOT AN APPROXIMATION OF IT. The Submit
   screen already draws this exact pair of figures under exactly these two
   rules, and `.qb-price` / `.qb-price-rule-h` / `.qb-price-rule-v` carry the
   numbers:

     group      356 x 120, at the card's x0 — FULL BLEED, no side inset
     Vector 11  356 x 2 laid across the group's top edge      #e2fa5a
     Vector 10    2 x 120 down x186 — the group's FULL height  #e2fa5a
     captions   @41,31 and @212,31        InstrumentSans 16/19.52, ink-70
     figures    @47,57 and @230,57        HostGrotesk-Medium 24/32, -1.28

   Two things were wrong before, and both are what the lime lines looked like:
   the horizontal rule was inset to the card's padding instead of measuring the
   full 356, and the vertical one was a `border-left` on the second cell, so it
   was only as tall as the text rather than the group's 120.

   So the rules are the box's own edges now — `border-top` on the group and
   `border-right` on cell 1, which a stretched grid row makes exactly 120 tall
   — and the group is pulled out to the card's edges with a negative margin. */
.qpd-price {
  /* full bleed: undoes `.qc-pkg`'s own 20 side padding, so Vector 11 measures
     the card's 356 exactly as it does on the Submit rail */
  /* Full bleed, and NO margin under it. Vector 10 is 106 tall from y288, so
     the band ends at 394 — which is the CTA's own stated y. There is no gap
     between them; the 12 that was here was my inference before Vector 10's
     height was known. The side pull is 18, matching `.qc-pkg`'s padding (see
     the note there), so the group still measures the card's inner 352. */
  margin: 0 -1.125rem 0;                            /* 18 out, 0 under */
  /* THE BAND IS `.qb-price`, NUMBER FOR NUMBER.
     Its height, its divider position and every inset below are copied from
     quote-submit.css's own Group 34 — the same pair of figures under the same
     pair of lime rules on the Submit rail — rather than measured off a
     screenshot. Two earlier passes here DID measure a screenshot, and both
     were wrong: 104, then 68, against the authored 120, and the divider walked
     from 52.25% to 50% to 42% chasing readings taken off crops at unknown
     scale. The sibling implementation was in the repo the whole time and it is
     the authority, so this block now reads off it.
     106 — Vector 10's OWN HEIGHT, no longer inferred. That node is the
     vertical divider: h106, 2px, #E2FA5A, at (178, 288). So the band runs
     288 -> 394, and 394 is the CTA's stated y: they touch, with no gap. The
     card then reconciles exactly — 288 + 106 + 44 + 20 = its stated 458.
     Two earlier passes guessed 124 (copied from the Submit rail's Group 34)
     and then 94 (106 less a 12 gap that does not exist). */
  min-height: 6.625rem;                             /* 106 */
  position: relative;                               /* Vector 10's anchor */
  /* ONE HORIZONTAL RULE, NOT TWO. The Details frame carries exactly two lime
     vectors here: Vector 11 across the top (356 long, 2px) and Vector 10 down
     the middle (106 tall, 2px). There is no rule under the figures — I had
     added one to stop the divider dangling, but it does not dangle: Vector 10
     is exactly as tall as the band and ends where the CTA begins.
     Full width because the group's negative side margins take it out to the
     card's own edges. */
  border-top: 0.125rem solid var(--accent);         /* Vector 11: 356 x 2 */
  display: grid;
  /* WHERE VECTOR 10 FALLS — x178 of the card's 356, i.e. EXACTLY 50%. That is
     this frame's own value; the 52.25% here was `.qb-price-rule-v`'s from the
     Submit rail, a different frame. (178 from the card's outer edge is 176 in
     this group, which is 50% of its 352 — the two agree.)
     A ratio rather than a fixed x, so it lands in the same place at the 428
     width where the card is 388 — and wrapped in `minmax(min-content, …)` so a
     track can never be narrower than the unbroken string inside it. That is
     the guard that matters: a bare percentage is what once broke "£28,690"
     into "£28,69" and "0". Both columns get the floor, because
     `minmax(0, 1fr)` on the second would starve it the same way. */
  grid-template-columns:
    minmax(min-content, 50%) minmax(min-content, 1fr);
}
/* THE INSETS ARE `.qb-cap-1` / `.qb-price-val`'s OWN.
   The Submit rail places these four strings at Figma's coordinates — captions
   at y31, figures at y57, cell 1 at x41 and cell 2's caption at x212, i.e. 26
   off the divider's x186. Reproduced here as padding and a gap, so the two
   rails put their figures in the same place:

     padding-top  24   Frame 1707481537 (the monthly figure row) is at y338
                       and the rule at y288, so the figure sits 50 into the
                       band: 24 + 19.52 of caption + 6.5 of gap = 50 exactly,
                       and its own 32 then ends at 370
     gap         6.5   the run those two y's leave between caption and figure
     padding-left 39   cell 1's stated x41 less the card's own 2 of border,
                       because this group starts at the card's inner edge

   The whole band then measures 24+19.52+6.5+32 = 82 inside its 94, which is
   the same reconciliation the card's 458 gave. */
.qpd-price-cell {
  display: flex;
  flex-direction: column;
  gap: 0.40625rem;                                  /* 6.5 */
  min-width: 0;
  padding: 1.5rem 0.25rem 0 2.4375rem;              /* 24 / 39 */
}

/* THE FIGURES ARE THE DESIGN'S OWN, AND THAT IS THE WHOLE OF THIS BLOCK NOW.
   These two lines used to cut the pair to 13/20 to stop "or, monthly from"
   wrapping. The wrap was never the type — it was the column split above, which
   left cell 2 four pixels short — so shrinking the type fixed a symptom and
   put the rail a size below every other rail in the journey, which is what
   "the font and the height are not the reference's" was.
   Back to `.qr-price-cap` / `.qr-price-val`'s authored 16/19.52 and 24/32, the
   same pair the Submit rail draws. Stated rather than deleted because
   `.qr-price-val`'s own tracking has to come with the size. */
.qpd-price .qr-price-cap {
  font-size: 1rem;                                  /* 16 */
  line-height: 1.22rem;                             /* 19.52 */
}
.qpd-price .qr-price-val {
  font-size: 1.5rem;                                /* 24 */
  line-height: 2rem;                                /* 32 */
  letter-spacing: -0.08rem;                         /* -1.28 */
}
/* the chevron at `.qr-val-2`'s own 20, the size that goes with a 24 figure */
.qpd-price .qr-price-val img { width: 1.25rem; height: 1.25rem; }
/* VECTOR 10 IS ITS OWN NODE, so it is drawn as one — not as a border on cell 1.
   A cell border is only as tall as the grid stretches that cell, which is what
   left the line stopping short of the band's end. As an absolutely positioned
   bar it spans `top: 0` to `bottom: 0` of the band by construction, so it
   always reaches the CTA — which is exactly what Figma states: Vector 10 is
   106 tall from y288, and 288 + 106 = 394 is the CTA's own y.

   `:has()` guards the conditional second cell: a tenant with no finance offer
   renders one cell, and the divider would otherwise be a lime line down the
   middle of nothing. (Replaces the old `:not(:only-child)`, which worked on a
   border but cannot select the PARENT for a pseudo-element.) */
.qpd-price:has(.qpd-price-cell + .qpd-price-cell)::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;                                        /* the band's full run */
  left: 50%;                                        /* Vector 10's x178/356 */
  width: 0.125rem;                                  /* 2 */
  transform: translateX(-50%);
  background: var(--accent);
  pointer-events: none;
}
/* and the lone cell takes the whole group rather than sitting in a 50% column */
.qpd-price-cell:only-child { grid-column: 1 / -1; }
/* Cell 2's own inset, from this frame: Frame 1707481537 (the monthly figure
   row) is at x216 of the card, i.e. 214 in this group, and Vector 10 is at 176
   — so 38 off the divider. The 26 here was `.qb-cap-2`'s offset on the Submit
   rail, a different frame. */
.qpd-price-cell + .qpd-price-cell { padding-left: 2.375rem; }   /* 38 */

/* `.qr-price-cap` and `.qr-price-val` carry ONLY type — their geometry lives on
   the `.qr-cap-*` / `.qr-val-*` modifiers, which are deliberately not used
   here. So these two lines are the design's exact caption and figure, in flow.

   NEITHER OF THESE MAY WRAP, AND THE FIGURE LEAST OF ALL.
   They were `white-space: normal` with `overflow-wrap: anywhere` on the
   figure, which is what broke "£28,690" into "£28,69" and "0" — a split money
   figure is a correctness bug, not an ugly line break, and it is the one thing
   this box must never do. `anywhere` also made it worse than it looks:
   unlike `break-word` it lowers the element's MIN-CONTENT width, so the grid
   track above was free to shrink under the text and the break became
   inevitable. `nowrap` restores the real min-content width, which is what the
   `minmax(min-content, …)` track then respects. */
.qpd-price .qr-price-cap { white-space: nowrap; }
.qpd-price .qr-price-val {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  white-space: nowrap;
  overflow-wrap: normal;
}
/* NO INDENT UNDER EITHER CAPTION ON THIS FRAME. The Submit rail offsets each
   figure a little past its caption (x47 against x41, x230 against x212) and I
   had carried both across — but the Details frame stacks them on one left
   edge, which is what its own render shows and what its x216 for the monthly
   figure row gives once the divider's x178 is known. Both cleared. */
/* THE CHEVRON POINTS RIGHT, NOT DOWN.
   `.qr-val-2` rotates the shared vector 90deg into a down-chevron for the
   results card, and that rotation was inherited here — but the reference draws
   this one as the bare right-chevron ("£209 >"), which is also the honest
   glyph: the figure beside it opens the finance breakdown, it does not expand
   a panel underneath. */
.qpd-price .qr-price-val img {
  flex: none;
  transform: none;
}

/* `.qr-cta` is authored with `left`/`top` for the results card, where
   `.qr-card > *` makes every child absolute. Inside `.qc-pkg` there is no such
   rule, so it is already static and those two offsets are inert — but the
   authored 300 width is stated for a 332-wide box, and this one is 316 inside
   its padding. Full width instead, so the button cannot be narrower than the
   card on one screen and wider on another. */
.qpd-cta {
  position: static;
  width: 100%;
}

/* ==========================================================================
   2. THE STEPPER — declared once, and not here
   ==========================================================================
   The 4-cell width, the visible check on a completed cell, the 1280 fallback
   and the 428 connectors were all declared in this sheet, scoped to `.qpd`.
   Four screens draw the bar now, so that block lives once in
   quote-results-integration.css instead — duplicating it per screen is how
   they drifted apart. Nothing about the bar is this screen's own any more.
   ========================================================================== */

/* ==========================================================================
   3. THE MAIN COLUMN
   ========================================================================== */
.qpd-main {
  display: flex;
  flex-direction: column;
}

/* The jump row — the results page's own top-bar link, in a centred hug row the
   way `.qr-topbar` and `.qc-topbar` are centred. `.qr-topbar-link` is reused
   for the type, so these read as the same links as the ones on /quote. */
.qpd-jump {
  width: max-content;
  max-width: 100%;
  margin: 1.5rem auto 0;                            /* tabs end y88 -> row y112 */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.5rem;                               /* the design's 24 */
}
.qpd-jump .qr-topbar-link { text-underline-offset: 0.1875rem; }
.qpd-jump .qr-topbar-link:hover { color: var(--ink); }
.qpd-jump .qr-topbar-link:focus-visible {
  outline: 0.125rem solid var(--ink);
  outline-offset: 0.25rem;
  border-radius: 0.25rem;
}

/* Two columns: the package's own copy, and the sections. The design's gap
   between a rail and its content is 40 throughout, so it is 40 here too. */
.qpd-body {
  margin-top: 2.5rem;
  display: grid;
  grid-template-columns: minmax(0, 21.25rem) minmax(0, 1fr);
  align-items: start;
  gap: 2.5rem;                                      /* 40 */
}

/* ---- the package's copy ------------------------------------------------ */
.qpd-info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
}

/* ==========================================================================
   THE PACKAGE'S COPY IS THE "VIEW PACKAGE DETAILS" SHEET'S COPY
   ==========================================================================
   The three runs below — title, lede, paragraph — are lifted from the popup
   the design draws for the same content, `.qd-title` / `.qd-copy-p` in that
   screen's own quote-details.css. Not approximated: both projects load the
   SAME base.css (the token block is byte-identical, tokens and the 100vw/120
   root scale included), so its rem values mean the same thing here and can be
   copied straight across.

     .qd-title    HostGrotesk-Medium  32/40  -1.28   ink @.92
     .qd-copy-p   InstrumentSans-MED  16/24  -0.16   ink-70
     .qd-bul-t    InstrumentSans-REG  16/19.52 -0.16 ink      (see the specs
                                                               block below —
                                                               `.qr-specs`
                                                               already IS this)

   What this replaces: a title at 22/28 and a paragraph at 16/22 REGULAR. The
   title was the reduction — 22 against the sheet's 32 — and the paragraph was
   set Regular where the sheet sets it Medium, which is the one weight on that
   screen that is not Regular and is called out as such in its own comment.

   The title WRAPS, never truncates: a real catalogue name runs to "Trina
   Vertex S+ 500W Dual Glass Full Black N Type Mono 500W Panels + Alpha ESS
   SMILE G3 4.8 kWh Battery" and the homeowner needs all of it. The sheet gives
   it a 469 box where this column is 340, so it takes more lines here — the
   type is the sheet's, the measure is this screen's. */
/* FIGMA (Details frame, Dev Mode) — "Trina Vertex S+ …" text node:
     Host Grotesk · 500 Medium · 24 / 32 · -1.28 · #111111 @ 92%
     box 340 x 128 at (540, 172)

   24, not the 32 that was here. That 32 came from the "view package details"
   POPUP's `.qd-title`, which is a different frame at a different size — this
   screen's title is a size down. 128 of box is four lines of 32, which is what
   the reference product name occupies.

   HEIGHT IS NOT FIXED. Figma states 128 because that string is four lines; a
   longer catalogue name has to push the paragraph below it down rather than
   overlap it, so nothing here is given a height. */
.qpd-h {
  margin: 0;
  font-family: var(--font-display);                 /* HostGrotesk-Medium */
  font-weight: 500;
  font-size: 1.5rem;                                /* 24 */
  line-height: 2rem;                                /* 32 */
  letter-spacing: -0.08rem;                         /* -1.28 */
  color: rgba(17, 17, 17, 0.92);
  overflow-wrap: break-word;
  text-wrap: balance;
}

/* `.qd-copy-p` exactly. No `max-width`: the sheet bounds this run with its own
   329-wide box and the grid column here (340) already is that bound, so a 38ch
   cap on top of it only made the paragraph narrower than the title above it. */
.qpd-p {
  margin: 0.75rem 0 0;
  font-family: var(--font-sans);
  font-weight: 500;                                 /* InstrumentSans-Medium */
  font-size: 1rem;                                  /* 16 */
  line-height: 1.5rem;                              /* 24 */
  letter-spacing: -0.01rem;
  color: var(--ink-70);
}

/* NO BADGE ROW. The BNPL / 0% APR chips were rendered here and are dropped on
   the user's instruction — the reference carries neither, and both facts are
   already in the spec list below ("Up-to 2 years 0% APR"), so the chips were
   saying a second time what the bullets say once.
   `featureBadges` is still read: it goes into the `PackageOffer` the shared
   proposal breakdown receives, which is the only other place it is used. */

/* `.qr-specs` is the design's spec list — the check at 20x20, a 4 gap, and
   InstrumentSans 16/19.52 REGULAR at -0.16, in full ink. That is `.qd-bul-t`
   and `.qd-bullets` to the declaration: same 20 icon, same 4 icon-to-text gap,
   same 12 between rows, same type, same colour — so the sheet's bullets need
   nothing copied here beyond leaving this list alone. It is authored
   `position: absolute` at (24,152) inside the results card's panel, so only
   that is undone; the type, the icon and the row rhythm are the design's.
   (quote-results-integration.css already unpins the row height and lets
   `.qr-spec-t` wrap, so a long spec is handled there.) */
.qpd-specs.qr-specs {
  position: static;
  left: auto; top: auto;
  /* FIGMA: the paragraph's box ends at 408 and Frame 1707481540 (this list)
     starts at 432 — so 24, where 20 was set by eye. Its own `gap: 12px` and
     `Flow: Vertical` are already what `.qr-specs` declares. */
  margin: 1.5rem 0 0;                               /* 24 */
  gap: 0.75rem;                                     /* 12 — Figma's own gap */
}

/* THE ROWS MUST WRAP, AND THIS IS THE RULE THAT MAKES THEM.
   quote-results-integration.css's `@media (min-width: 768px)` block puts the
   results card's own spec rows on ONE line each — `max-width: 33rem` with
   `white-space: nowrap` + `overflow: hidden` + `text-overflow: ellipsis` —
   because there they have 528px of clear run before the price box. Those
   selectors are unscoped, so they were landing on this list too, inside a
   column a third that wide: "7kWh Fox ESS CQ7 7.02kWh Slave Battery storage
   system" was cut off mid-string at the column edge.
   Put back to wrapping, at a specificity that beats (0,2,1).

   TYPE IS `.qr-specs`'S OWN — 16/19.52 — and is deliberately not restated: a
   13 here read a size below the bullets on the card the homeowner just came
   from. Only the height that pins a row to one line, and the alignment a
   wrapped row needs, are undone. */
.qpd .qpd-specs li {
  max-width: none;
  min-width: 0;
  height: auto;
  align-items: flex-start;
}
.qpd .qpd-specs li .qr-spec-t {
  min-width: 0;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  overflow-wrap: anywhere;
}
/* the check at the card's own 20, sitting on the first line rather than on the
   centre of a row that may now be two lines tall */
.qpd .qpd-specs li img {
  width: 1.25rem; height: 1.25rem;                  /* 20 — the card's own */
  margin-top: 0;
}

/* The design's chip vocabulary as a full-width row: `.qr-inc`'s @.06 fill and
   ink-70 label, opened out to the column. */
.qpd-terms {
  /* FIGMA — Frame 1707481532: 340 x hug 32 at (540, 882), radius 8,
     `Justify: space-between`, padding [6, 8, 6, 8], fill #111111 @ 6%.
     6+20+6 = its 32, so the label's line is 20. `min-height` rather than a
     height: a longer label must grow the chip, not spill out of it. */
  margin-top: 1.5rem;
  align-self: stretch;
  min-height: 2rem;                                 /* 32 */
  display: flex;
  align-items: center;
  justify-content: space-between;                   /* Figma's own */
  gap: 0.75rem;
  padding: 0.375rem 0.5rem;                         /* 6 / 8 */
  border-radius: var(--radius-sm);                  /* 8 */
  background: rgba(17, 17, 17, 0.06);               /* @6%, not @4% */
  font-family: var(--font-sans);
  font-weight: 400;
  /* FIGMA — the "Terms & Condition" text node: Instrument Sans 400 Regular,
     16 / 100%, -0.16, #111111 @ 70%, in a box Figma reports 20 tall. A 20
     line on a 16 font gives that box exactly, and 6 + 20 + 6 is the row's
     stated 32. */
  font-size: 1rem;                                  /* 16 */
  line-height: 1.25rem;                             /* the node's own 20 box */
  letter-spacing: -0.01rem;
  color: var(--ink-70);
  text-decoration: none;
  transition: background var(--dur-hover) var(--ease-premium);
}
.qpd-terms:hover { background: rgba(17, 17, 17, 0.08); color: var(--ink); }
/* FIGMA: the chevron sits in its own 20 x 20 frame. */
.qpd-terms-chev {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;                                  /* 20 */
  display: grid;
  place-items: center;
  line-height: 1;
  color: var(--ink-70);
}

/* ---- the sections ------------------------------------------------------ */
.qpd-acc {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;                                     /* 20 */
  min-width: 0;
}

/* The journey's card recipe: white, r12, and a 2px INSIDE stroke expressed as
   an inset shadow rather than a border — the same reason `.qr-card-n` does it,
   and here it also means opening a row cannot shift its contents by 2px. */
/* A CLOSED ROW IS A FILL, NOT AN OUTLINE.
   The reference draws the shut rows as the design's soft panel — `#f5f6f0`,
   r12, no stroke at all — which is the same chip ground `.qr-inc` and
   `.qc-pkg-inc` use for a dormant control. They were white with a 2px grey
   ring here, so five closed rows read as five empty boxes instead of one quiet
   stack. */
/* FIGMA — Frame 1707481612: 960 x 72, radius 20, fill #111111 @ 6%.
   Radius 20 rather than the journey's `--radius` 12, and a 6% ink wash rather
   than `--panel` — both stated on the frame, and 20 is the one measurement
   that makes these rows read as their own stack rather than as cards. */
.qpd-acc-row {
  border-radius: 1.25rem;                           /* 20 */
  background: rgba(17, 17, 17, 0.06);               /* @6% */
  transition: background var(--dur-hover) var(--ease-premium),
              box-shadow var(--dur-hover) var(--ease-premium);
}
.qpd-acc-row:hover { background: rgba(17, 17, 17, 0.08); }
/* the mark was the only thing the chip's fill did on hover; it is the mark
   itself now */
.qpd-acc-row:not(.is-open):hover .qpd-acc-chip { color: var(--ink-70); }

/* FIGMA — Frame 1707481545, the open panel: 960 wide, radius 20, fill
   #FEFFF9, border 4px #E2FA5A with INNER alignment, and no shadow.

   Three corrections: the ring is 4px, not 2; the fill is #FEFFF9 (`--bg`, the
   page's own cream) rather than pure white; and there is no drop shadow — the
   `0 2px 40px rgba(0,0,0,.06)` here was mine.

   Still an inset shadow rather than a real border, and that is the faithful
   reading of "Inner alignment": drawn inside the box, taking no layout. It
   also means opening a row cannot shift its contents sideways by 4px. */
.qpd-acc-row.is-open {
  background: var(--bg);                            /* #FEFFF9 */
  box-shadow: inset 0 0 0 0.25rem var(--accent);    /* 4px, inside */
}
.qpd-acc-row.is-open:hover { background: var(--white); }

/* --------------------------------------------------------------------------
   A JUMP LINK POINTING AT A CARD THAT IS ALREADY OPEN
   --------------------------------------------------------------------------
   The links above the stack open a section. When the section they name is
   already the open one there is nothing left to open, so the click produced no
   render and no feedback at all and the link read as broken. This is what it
   does instead: the card it meant lights briefly in the ring's own lime, which
   answers the only question the click was asking — WHICH card is this?

   Deliberately quiet. It runs once, at a wash the ring already establishes, and
   it animates `background` alone: the row's 4px inset ring, its radius and its
   contents do not move, so nothing reflows under the reader's eye. The open
   row's own `background` transition is overridden for the duration by the
   animation, and returns to it when the class is dropped.
   -------------------------------------------------------------------------- */
@keyframes qpd-acc-pulse {
  0%   { background: var(--bg); }
  30%  { background: rgba(226, 250, 90, 0.38); }    /* --accent, washed */
  100% { background: var(--bg); }
}
.qpd-acc-row.is-pulse { animation: qpd-acc-pulse 720ms var(--ease-premium); }
/* A flash is exactly the kind of motion this setting is about. The link still
   works; it simply arrives without the animation. */
@media (prefers-reduced-motion: reduce) {
  .qpd-acc-row.is-pulse { animation: none; }
}

.qpd-acc-h { margin: 0; }
.qpd-acc-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  /* FIGMA: the row is 72 tall; its title sits at x40 and its 40-tall chip at
     y16, so 16 of vertical padding and 40 across. `min-height` not height —
     a section name that wraps has to grow the row. */
  min-height: 4.5rem;                               /* 72 */
  padding: 1rem 2.5rem;                             /* 16 / 40 */
  border: 0;
  background: none;
  appearance: none;
  cursor: pointer;
  border-radius: var(--radius);
  text-align: left;
}
/* FIGMA — the "What's included" text node:
     Instrument Sans · 500 Medium · 24 · line height 100% · -0.16 · #111111
   Line height is Figma's literal 100%, i.e. 24 — not the 29 that was guessed
   here — and the tracking is a flat -0.16, not the -0.24 I had scaled up. */
.qpd-acc-t {
  min-width: 0;
  font-family: var(--font-sans);
  font-weight: 500;                                 /* InstrumentSans-Medium */
  font-size: 1.5rem;                                /* 24 */
  line-height: 1.5rem;                              /* 100% */
  letter-spacing: -0.01rem;                         /* -0.16 */
  color: var(--ink);
  overflow-wrap: break-word;
}
/* THE +/- IS A BARE MARK ON A CLOSED ROW AND A CHIPPED ONE ON THE OPEN ROW.
   Both states carried a filled 32 circle — WHITE on the closed rows, which on
   the #f5f6f0 ground is the one thing that reads as a control the reference
   does not draw: it shuts a row with the plus alone, a tall thin mark with
   nothing behind it, and saves the chip for the row that is open. So the fill
   goes, the box keeps its size (it still reserves the same column, so five
   rows agree on where their marks sit), and the open row puts the design's own
   @.06 chip back under a smaller glyph — see below.
   Set in the UI face at 400 so the minus and the plus have the same optical
   weight; at 600 a plus reads heavier than a minus of the same size. */
/* FIGMA — "Arrow Icon Wrapper": 40 x 40, radius 8, padding [5, ,5, ].
   A ROUNDED SQUARE, NOT A CIRCLE, and 40 rather than the 32 set here. The
   `border-radius: 50%` was mine; the frame states 8. */
.qpd-acc-chip {
  flex: none;
  width: 2.5rem; height: 2.5rem;                    /* 40 */
  display: grid;
  place-items: center;
  border-radius: var(--radius-sm);                  /* 8 */
  background: none;
  /* THE MARK IS DRAWN, NOT TYPED.
     Figma builds it from two vectors — 16.33 long, 2px, #000000, centred in a
     28 frame inside this 40 wrapper — so a font glyph can only approximate it:
     "+" and "−" in any face differ in stroke weight, length and optical
     centre from each other and from a 2px rule. The text node stays in the
     markup (it is `aria-hidden`, and the button's own `aria-expanded` carries
     the state) but is not rendered. */
  font-size: 0;
  position: relative;
  color: var(--ink);
  transition: background var(--dur-hover) var(--ease-premium);
}
.qpd-acc-chip::before,
.qpd-acc-chip::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: #000;                                 /* the vectors' own fill */
}
/* the horizontal stroke — 16.33 x 2 */
.qpd-acc-chip::before {
  width: 1.020625rem;
  height: 0.125rem;
  transform: translate(-50%, -50%);
}
/* the vertical stroke — 2 x 16.33. Only a closed row has it; the open row's
   mark is the minus alone. */
.qpd-acc-chip::after {
  width: 0.125rem;
  height: 1.020625rem;
  transform: translate(-50%, -50%);
}
.qpd-acc-row.is-open .qpd-acc-chip::after { display: none; }
/* the open row's mark, in the design's small-control fill. Smaller than the
   bare one: a chip gives the glyph its own presence, so a 28 minus inside a 32
   circle would fill it edge to edge. */
/* FIGMA: the open panel's chip is at y24 where a closed row's is at y16, and
   it is the only one with a fill — #F6F6F6, stated on the node. */
.qpd-acc-row.is-open .qpd-acc-btn { padding-top: 1.5rem; padding-bottom: 1.5rem; }  /* 24 */
.qpd-acc-row.is-open .qpd-acc-chip { background: #f6f6f6; }
.qpd-acc-btn:focus-visible {
  outline: 0.125rem solid var(--ink);
  outline-offset: -0.25rem;
}

/* THE FONT-FAMILY HANDOFF.
   The bodies render `SolarProposalBreakdown`, which is shared with the
   proposal page and styled with Tailwind utilities. Those set size and weight
   but not `font-family`, so its strings inherit — and inheriting from here is
   what puts them in the journey's face instead of the app shell's Inter,
   without editing a component three other screens also render. */
.qpd-acc-body {
  /* NO RULE UNDER THE HEADING. The reference separates the heading from the
     body with space alone — a border here drew a line the reference does not
     have, directly under every open row's title. */
  /* THE BODY SHARES THE HEADING'S OWN INSET.
     Figma draws Group 30 (the priced rows) 904 wide at x28 of the 960 panel,
     against a heading at x40 — so the design does inset the body less than its
     title, and that is what was built. On real content it reads as a mistake
     rather than as a decision: "Financial Summary" and the "−" chip stand 12
     inside "Longi HiMo6 …" and its price, so every line of the card is a
     column out from the heading that names it, at both edges at once.
     Matching `.qpd-acc-btn`'s 40 puts the labels under their heading and the
     values under the chip. */
  margin: 0 2.5rem;                                 /* 40 — .qpd-acc-btn's own */
  padding: 0 0 1.5rem;
  /* a wide table or chart scrolls in its own box; the page never scrolls
     sideways */
  overflow-x: auto;
  font-family: var(--font-sans);
  letter-spacing: -0.01rem;
  color: var(--ink);
}

/* "What's included" — the one body this screen renders itself */
.qpd-inc {
  margin: 0.75rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.75rem;
}
.qpd-inc li { display: flex; flex-direction: column; gap: 0.125rem; }
.qpd-inc-t {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 1.0625rem;                             /* 17 — the row scale */
  line-height: 1.375rem;
  letter-spacing: -0.01rem;
  color: var(--ink);
}
.qpd-inc-s {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 0.9375rem;                             /* 15 */
  line-height: 1.375rem;
  letter-spacing: -0.01rem;
  color: var(--ink-70);
}

/* ---- the financial summary -------------------------------------------- */
/* THREE BLOCKS, AND ONLY ONE RULE BETWEEN THEM.
   The reference reads: the priced lines with NO dividers at all, then the
   running totals on a soft grey band, then the Total on white above a single
   hairline. Every row carried a `border-bottom` here, so the panel came out as
   a fifteen-line ruled ledger instead of three grouped blocks — that is the
   ruling visible in ours and absent from the reference. */
.qpd-fin { display: block; }
.qpd-fin-list {
  margin: 0.5rem 0 0;
  padding: 0;
  list-style: none;
}
/* the running totals — Figma's own soft panel, inset from the ring */
.qpd-fin-band {
  margin: 0.75rem 0 0;
  /* vertical only: the band's rows sit on the same left edge as the priced
     lines above them, so the fill is full-width inside the body */
  padding: 0.5rem 0;
  list-style: none;
  border-radius: var(--radius-sm);
  background: rgba(17, 17, 17, 0.04);
}
/* the Total, on white, under the one hairline the reference does draw */
.qpd-fin-total {
  margin: 0;
  padding: 0;
  list-style: none;
}
.qpd-fin-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.25rem;
  /* FIGMA: each row's text box is 28 tall and the values step 30 apart
     (y287, 317, 347, 377, 407, 437, 467), so 1 either side of the 28. The 9
     here gave a 40 pitch, sized by eye before these nodes were captured. */
  padding: 0.0625rem 0;                             /* 1 -> a 30 pitch */
}
/* FIGMA — "Company margin": Instrument Sans 400 Regular, 20 / 28, -0.16,
   #111111 @ 70%. Its box is 28 tall, which is the line. */
.qpd-fin-l {
  min-width: 0;
  font-family: var(--font-sans);
  font-weight: 400;                                 /* Regular */
  font-size: 1.25rem;                               /* 20 */
  line-height: 1.75rem;                             /* 28 */
  letter-spacing: -0.01rem;                         /* -0.16 */
  color: var(--ink-70);                             /* @70% */
  overflow-wrap: break-word;
}
/* FIGMA — "£285.00": Instrument Sans 500 Medium, 20 / 28, -0.16, #111111,
   horizontally aligned RIGHT. */
.qpd-fin-v {
  flex: none;
  font-family: var(--font-sans);
  font-weight: 500;                                 /* Medium */
  font-size: 1.25rem;                               /* 20 */
  line-height: 1.75rem;                             /* 28 */
  letter-spacing: -0.01rem;                         /* -0.16 */
  color: var(--ink);
  text-align: right;                                /* Figma's own alignment */
  font-variant-numeric: tabular-nums;
}
/* the total — the figure the page is about, so it is set in the display face
   at the size the rail gives a price, above the panel's one hairline */
.qpd-fin-row.is-total {
  margin-top: 0.75rem;
  padding: 0.875rem 0 0;
  border-top: 0.0625rem solid rgba(17, 17, 17, 0.12);
}
/* FIGMA — "£3,863.54": Instrument Sans 500 Medium, 28 / 28, -0.16, #111111,
   aligned RIGHT. INSTRUMENT SANS, not the display face: this row was set in
   HostGrotesk here, at a 36 line with -1.28 of tracking. The "Total" label's
   own node was not captured; it is set to match its figure, which is what the
   frame renders. */
.qpd-fin-row.is-total .qpd-fin-l {
  font-family: var(--font-sans);
  font-weight: 500;                                 /* Medium */
  font-size: 1.75rem;                               /* 28 */
  line-height: 1.75rem;                             /* 28 */
  letter-spacing: -0.01rem;
  color: var(--ink);
}
.qpd-fin-row.is-total .qpd-fin-v {
  font-family: var(--font-sans);                    /* Instrument Sans */
  font-weight: 500;                                 /* Medium */
  font-size: 1.75rem;                               /* 28 */
  line-height: 1.75rem;                             /* 28 */
  letter-spacing: -0.01rem;                         /* -0.16 */
}
.qpd-fin-row.is-muted .qpd-fin-l,
.qpd-fin-row.is-muted .qpd-fin-v {
  color: var(--ink-70);
  font-weight: 400;
}
.qpd-fin-note {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  line-height: 1.375rem;
  letter-spacing: -0.01rem;
  color: var(--ink-70);
}

/* ---- loading / error --------------------------------------------------- */
.qpd-note {
  margin-top: 2.5rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 1.5rem;
  border-radius: var(--radius);
  background: var(--white);
  box-shadow: inset 0 0 0 0.125rem rgba(17, 17, 17, 0.08);
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  line-height: 1.375rem;
  letter-spacing: -0.01rem;
  color: var(--ink-70);
}
.qpd-note p { margin: 0; }
.qpd-note-err { box-shadow: inset 0 0 0 0.125rem rgba(190, 60, 60, 0.35); }
.qpd-spin {
  width: 1.25rem; height: 1.25rem;
  border-radius: 50%;
  border: 0.125rem solid rgba(17, 17, 17, 0.12);
  border-top-color: #869435;
  animation: qpd-spin 700ms linear infinite;
}
@keyframes qpd-spin { to { transform: rotate(360deg); } }
.qpd-note-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }
/* the journey's two button weights, at the size a dialog action takes */
.qpd-btn {
  padding: 0.5rem 1.125rem;
  border: 0;
  border-radius: var(--radius-sm);
  appearance: none;
  cursor: pointer;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 0.9375rem;
  line-height: 1.375rem;
  letter-spacing: -0.01rem;
}
.qpd-btn-dark { background: var(--ink); color: var(--white); }
.qpd-btn-ghost {
  background: none;
  box-shadow: inset 0 0 0 0.125rem rgba(17, 17, 17, 0.12);
  color: var(--ink);
}

/* THE MOBILE-ONLY PINNED CTA.
   `.qc-topbar` is the design's own bottom bar: above 768 a centred hug row in
   the main column, and below it a fixed 124-tall band holding `.qc-continue`
   full width — which is how Customise and Submit put their CTA on the phone.
   This screen borrows that bar wholesale, so `.qpd-fabbar` carries no geometry
   of its own; it only decides WHERE the bar exists. Here, nowhere: above 768
   the CTA lives on the rail. */
.qpd-fabbar { display: none; }
/* The phone card's name and summary line — see their note in the JSX. The
   desktop rail is its own composition and does not carry them. */
.qpd-pkg-name,
.qpd-pkg-desc { display: none; }
/* The rail's copy of the journey bar — see the note at its JSX. Hidden here so
   the desktop tree holds only the one in the main column. */
.qpd-steps-m { display: none; }

/* ==========================================================================
   3b. FIGMA'S FIXED HEIGHTS ARE FLOORS HERE, NOT CEILINGS
   ==========================================================================
   Figma states a height on several of these boxes because it is drawing ONE
   product: the title's 128 is four lines of that particular catalogue name,
   the accordion row's 72 is one line of "What's included", the terms chip's 32
   is one line of its label. Our strings are the tenant's and are longer —
   "LONGi Hi-MO 6 Explorer 485W Panels + Fox ESS EP12 11.52kWh Li-ion Battery
   w/ heating function" runs to six lines, and a section name can wrap.

   So every one of those is a `min-height` or is left to flow, and no box on
   this screen is given a fixed height (user: "make it responsive, if text
   detail grows then do not overlap with each other"). Figma's number is
   reproduced as the box's RESTING size; growth pushes the next block down
   instead of running under it.

   The stack that has to keep working:
     title (flows) -> 12 -> paragraph (flows) -> 24 -> specs (flows)
       -> 24 -> terms chip (min 32)
   All in one flex column (`.qpd-info`), so each pushes the next. The rail's
   own card is `height: auto` for the same reason, and its floor is the 758
   above.
   ========================================================================== */
/* Nothing here may collapse its content: `min-width: 0` on the grid children
   lets a long unbroken product name shrink the track instead of overflowing
   the page, and the two columns wrap at 1024 (see §4). */
.qpd-body > * { min-width: 0; }

/* The accordion body is the one place a wide child (a table, a chart) can
   appear, so it scrolls inside itself rather than widening the page. */
.qpd-acc-body { max-width: 100%; }

/* ==========================================================================
   3c. TABLET — below 1024 the two columns stack
   ==========================================================================
   Figma draws one desktop frame (1920) and one phone frame (428) and nothing
   between, so this band is not a Figma layout — it is the rule that stops the
   desktop one breaking before the phone one takes over. 340 + 40 + 960 = 1340
   needs the full 1920 canvas; under it the accordion column would squeeze the
   copy column past readability, so the two stack and each takes the width.
   ========================================================================== */
@media (min-width: 768px) and (max-width: 1023.98px) {
  .qpd-body {
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
  }
  /* the row's 40 inset is a 1920 measure; at this width it eats the column */
  .qpd-acc-btn { padding: 1rem 1.5rem; }
  .qpd-acc-body { margin: 0 1.5rem; }
}

/* ==========================================================================
   4. NARROW — the 428 canvas
   ==========================================================================
   base.css scales the root below 768 so 1rem is 1 Figma mobile px, and
   quote-results.css's own 428 block dissolves the two-pane shell: `.qr-side`
   becomes an in-flow header with a 180 pinned band, `.qr-tabs` is pulled out
   of the main column to sit at (20,132) between the restart pill and the card,
   and the rule / Trustpilot / help / FAB are dropped. All of that already
   applies here — only the four-cell stepper and the two-column body are this
   screen's own.
   ========================================================================== */
@media (max-width: 767.98px) {
  /* One column. The copy comes first — it names what the sections below are
     about — and the gap is the frame's own 20. */
  .qpd-body {
    margin-top: 1.25rem;
    grid-template-columns: minmax(0, 1fr);
    gap: 1.25rem;
    padding: 0 1.25rem;                             /* the 20 gutter -> 388 */
  }
  .qpd-jump {
    margin-top: 1.25rem;
    padding: 0 1.25rem;
    gap: 0.5rem 1rem;
  }
  .qpd-note { margin: 1.25rem; }
  /* The sheet's 32 title is a desktop measure — it has a 469 box there and 348
     here. 28/34 keeps its proportion against the 16 paragraph on this track. */
  /* NO TITLE OVERRIDE. This used to step 32 down to 28; the desktop size is
     Figma's 24 now, and on the 428 canvas 1rem is 1 mobile px, so 24/32 comes
     through unchanged. A 28 here would make the phone's title LARGER than the
     desktop's. */

  /* THE DESKTOP FLOOR MUST BE UNDONE. `.qpd .qr-side { min-height: 47.375rem }`
     buys the taller package card its clearance from the bottom cluster on the
     1920 canvas — but here `.qr-side` is an in-flow header with `height: auto`
     and no bottom cluster at all (quote-results.css's 428 block drops the rule,
     the Trustpilot row, the help line and the FAB, and sets `min-height: 0`).
     Left standing, that floor is 756 of empty header above the main column —
     and it WOULD stand, because (0,2,0) outranks the (0,1,0) it replaces
     regardless of the media query. */
  .qpd .qr-side { min-height: 0; }

  /* The 24 heading is a desktop step. On the 388 track a six-row stack of them
     crowds the +/- chip, so the row goes back to the wizard's own 20/25. */
  .qpd-acc-t { font-size: 1.25rem; line-height: 1.5625rem; }
  .qpd-acc-btn { padding: 1rem 1.25rem; }
  /* the 40 inset is a 1920 measure — 80 of it inside a 348 column */
  .qpd-acc-body { margin: 0 1.25rem; padding: 0 0 1.25rem; }
  /* the 40 chip is a 1920 measure; the drawn strokes scale with it */
  .qpd-acc-chip { width: 2rem; height: 2rem; }                      /* 32 */
  .qpd-acc-chip::before { width: 0.875rem; }                        /* 14 */
  .qpd-acc-chip::after { height: 0.875rem; }

  /* The rail card is `position: relative` with a 20 side margin here (see
     quote-customize.css's 428 block) and its art group moves to x40. The
     padding-top that clears the art is the desktop's — the art is 232 tall on
     both canvases and Figma's own gap to the lime rule is the same 36 — and
     the price group's own -20 side margin still lands on the card's edges, so
     only the side padding is restated. */
  /* the 18 side padding is the desktop's, so the band's -18 pull still lands
     on the card's own edges here too */
  .qpd .qc-pkg { padding: 18rem 1.125rem 1.25rem; }  /* 288 / 18, as on 1920 */

  /* ---- the card names the package, and prices it nowhere ---------------
     FIGMA `Frame 1707481589` — 388 x 221 at (20,192), r12, a 2px lime->#869435
     gradient ring on #FEFFF9 — holds the art, the package NAME and a summary
     line. It does NOT hold a price: on this canvas both figures are in the
     pinned bar at the foot of the screen, and rendering them here as well put
     the same two numbers on screen twice while the package itself went
     unnamed. So the pair is hidden and the name takes its place. */
  .qpd .qpd-price { display: none; }

  /* ---- the card is `Frame 1707481589`, 388 x 221 at (20,192) ------------
     Everything in it is placed, because Figma places it: the art group at
     (12,16), the name beside it at (199,31) and the summary line across the
     foot at (20,157). The card was a top-padded stack with the art on its own
     band, which is the 1920 rail's shape rather than this one's. */
  .qpd .qc-pkg {
    position: relative;
    /* `display: block`, and `min-height: 0`, and both are load-bearing.
       quote-details-integration.css gives this card `display: flex` with a
       `min-height: 24.5rem` — the 392 the 1920 rail needs. A min-height is not
       overridden by a smaller HEIGHT: it is a floor, so the card stayed 392
       tall here however short its content, which is the empty band under the
       summary line in the report. The flex column has to go too, since every
       child is placed. */
    display: block;
    height: 13.8125rem;                               /* 221 */
    min-height: 0;
    padding: 0;
    overflow: hidden;
  }

  /* THE ART GROUP IS THE 1920 GROUP, SCALED — not re-coordinated.
     Figma's `Group 26` here is 166.49 x 125 where the wide canvas draws
     309 x 232, and 166.49/309 and 125/232 are the SAME 0.5388. So the phone
     group is the desktop group at 0.5388, and every child lands on its stated
     coordinate by arithmetic: the panels at (12,37.55) 103.45 square, the
     battery at (103.06,65.57) 75.43 square, both logos likewise. One transform
     instead of four rewritten offsets — and the brand names scale with it, as
     the design shows them. */
  .qpd .qc-pkg-art {
    position: absolute;
    left: 0.75rem;                                    /* 12 */
    top: 1rem;                                        /* 16 */
    width: 19.3125rem;                                /* the group's own 309 */
    height: 14.5rem;                                  /* 232 */
    transform: scale(0.5388);
    transform-origin: top left;
  }

  .qpd .qpd-pkg-name {
    display: block;
    position: absolute;
    left: 12.4375rem;                                 /* 199 */
    top: 1.9375rem;                                   /* 31 */
    width: 10.5625rem;                                /* 169 */
    /* the node is 96 tall, i.e. four of its own 24 lines */
    display: -webkit-box;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: 0;
    font-family: var(--font-display);                 /* Host Grotesk */
    font-weight: 500;
    font-size: 1.125rem;                              /* 18 */
    line-height: 1.5rem;                              /* 24 */
    letter-spacing: -0.08rem;                         /* -1.28 */
    color: rgba(17, 17, 17, 0.92);
  }
  /* the summary line @20,157 348x48 — Instrument Sans Medium 16/24 at 70%,
     two of its own lines, clipped as the design clips it */
  .qpd .qpd-pkg-desc {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    position: absolute;
    left: 1.25rem;                                    /* 20 */
    top: 9.8125rem;                                   /* 157 */
    width: 21.75rem;                                  /* 348 */
    margin: 0;
    font-family: var(--font-sans);
    font-weight: 500;
    font-size: 1rem;                                  /* 16 */
    line-height: 1.5rem;                              /* 24 */
    letter-spacing: -0.01rem;
    color: var(--ink-70);
  }
  /* the ring Figma draws on this card: 2px, lime -> #869435, inside */
  .qpd .qc-pkg {
    border-radius: var(--radius);                     /* 12 */
    background: var(--bg);                            /* #FEFFF9 */
  }

  /* ---- the accordion rows are Figma's own 64 at r12 -------------------
     `Frame 1707481590` is 388 x 64 at r12 on ink @6%, and the open panel
     (`Frame 1707481545`) is the same 12 with a 4px lime ring. The 20 radius
     here is the 1920 rail's, and the 72 row is its height too. */
  .qpd .qpd-acc-row { border-radius: var(--radius); }  /* 12, not 20 */
  .qpd .qpd-acc-btn { min-height: 4rem; }              /* 64, not 72 */

  /* THE WAY FORWARD HAS TO STAY REACHABLE.
     On this canvas the rail is the page's header, so the rail's CTA scrolls
     away above six accordion rows. The journey's own answer to that is the
     pinned bar Customise and Submit already use at 428 — `.qc-topbar` fixed to
     the bottom at 124 tall, holding `.qc-continue` as an 84-tall green button
     with its lime-chipped inner pill — so the bar is simply switched ON here
     and every measurement stays quote-customize.css's.

     One line of clearance is needed for it, and that already exists: that same
     sheet's 428 block sets `.qr-shell { padding-bottom: 9rem }` for its own
     copy of this bar, unscoped, so it applies here too.

     The rail's copy of the CTA is hidden rather than rendered twice, so the
     accessibility tree holds exactly one "Next, customize". */
  .qpd-cta { display: none; }
  .qpd-fabbar { display: block; }

  /* THE JOURNEY BAR MOVES INTO THE HEADER. `.qr-tabs`' own 620 width, white
     ground and shadow are the 1920 rail's; on this track it is the flat
     388-wide row the other phone screens draw, which is what
     `.qc .qr-tabs`'s own 428 rule already sets up. Only the swap is here. */
  /* ---- THE JOURNEY BAR IS PINNED, NOT FLOWED ---------------------------
     The rail's logo and back pill are ABSOLUTE on this canvas (`.qr-logo` at
     20,40, `.qr-restart` at y46), so a flow child here has nothing above it to
     measure from and a top MARGIN is only as right as the box it happens to
     start in — which is what left the bar drifting down the screen instead of
     sitting on 132.

     Pinned, it is Figma's (20,132) 388-wide bar whatever the header does,
     which is the same position and the same 20 gutter the Customise screen's
     bar has. The card then carries the y192 `Frame 1707481589` is drawn at,
     since the bar no longer occupies flow. */
  .qpd .qpd-steps-m {
    display: flex;
    position: absolute;
    left: 1.25rem;                                   /* 20 */
    top: 8.25rem;                                    /* 132 */
    width: 24.25rem;                                 /* 388 */
    margin: 0;
  }
  .qpd .qc-pkg { margin: 12rem 1.25rem 0; }          /* 192 — the card's own y */

  /* AND NO 180 BAND ABOVE IT. quote-results.css gives `.qr-side` a
     `padding: 11.25rem 0 0` — the 180 the RESULTS page reserves for its own
     pinned header band. This screen places its header itself (logo and back
     pill absolute, journey bar pinned), so that padding is 180 of nothing, and
     the card came out at 180 + 192 = 372 instead of 192. Absolutely positioned
     children measure from the padding EDGE, so dropping it moves the card and
     leaves the bar on its 132. */
  .qpd .qr-side { padding-top: 0; }

  /* ---- WHAT THE PHONE DOES NOT DRAW ------------------------------------
     Figma's 428 frame goes header -> bar -> package card -> Financial Summary
     -> the accordion rows. It has no jump links and no second copy of the
     package name: the card names it, and the rows below are the sections the
     links pointed at, one tap away and already on screen. All three were the
     1920 column's, rendered here as well, so the phone repeated the package
     name directly under the card that states it. */
  .qpd .qpd-jump,
  .qpd .qpd-h,
  .qpd .qpd-p { display: none; }
  .qpd .qpd-steps-d { display: none; }

  /* ---- the pinned bar carries the price pair ---------------------------
     `.qc-topbar`'s 124 is a one-button bar. This one holds two rows, so it
     grows to its content and the shell's bottom clearance grows with it —
     `.qr-shell { padding-bottom: 9rem }` (quote-customize.css's own 428 block,
     unscoped) would otherwise leave the last accordion row under the bar. */
  .qpd .qpd-fabbar { height: auto; padding: 0.75rem 1.25rem 1.25rem; }
  .qpd.qr .qr-shell { padding-bottom: 14.5rem; }

  /* The green moves off the button and onto this wrapper, so the figures and
     the pill sit on one ground and the price is outside the hit area. */
  .qpd-fabbar-panel {
    padding: 0.75rem;                                 /* 12, the pill's own */
    border-radius: var(--radius);
    background: #057442;
    box-shadow: 0 0 2.5rem rgba(0, 171, 85, 0.32);
  }
  /* TWO HALVES WITH A RULE BETWEEN THEM, which is how Figma sets this row:
     "Price estimate" is 104 wide at x45 and "or, monthly from" 119 at x231 —
     each centred in its own half of the 388 — and `Vector 16`, a 2px white
     hairline at 8%, stands at x194, the midline. Spreading the pair to the
     outer edges instead left the middle of the bar empty and the two figures
     reading as unrelated. */
  .qpd-fabbar-prices {
    position: relative;
    display: grid;
    grid-template-columns: 1fr 1fr;
    padding: 0.25rem 0.5rem 0.75rem;
  }
  .qpd-fabbar-prices::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 0.25rem;
    bottom: 0.75rem;
    width: 0.125rem;                                  /* 2 */
    transform: translateX(-50%);
    background: rgba(255, 255, 255, 0.08);            /* #FFFFFF @ 8% */
  }
  .qpd-fabbar-cell {
    display: flex;
    flex-direction: column;
    align-items: center;                              /* centred in its half */
    gap: 0.125rem;
    min-width: 0;
  }
  .qpd-fabbar-cap {
    font-family: var(--font-sans);
    font-weight: 400;
    font-size: 0.875rem;                              /* 14 */
    line-height: 1.0625rem;
    letter-spacing: -0.01rem;
    color: rgba(255, 255, 255, 0.78);
  }
  .qpd-fabbar-val {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: 1.25rem;                               /* 20 */
    line-height: 1.5rem;
    letter-spacing: -0.02rem;
    color: var(--white);
    white-space: nowrap;
  }
  /* the wrapper is the green now — the button keeps only its inner pill */
  .qpd-fabbar .qc-continue {
    height: auto;
    padding: 0;
    background: none;
    box-shadow: none;
  }
  .qpd-fabbar .qc-continue:hover { background: none; box-shadow: none; }
}

/* ==========================================================================
   5. REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .qpd-acc-row,
  .qpd-acc-chip,
  .qpd-terms { transition: none; }
  .qpd-spin { animation: none; }
}
