/* =============================================================================
   Product details - Apple-style configurator (ADDITIVE)
   -----------------------------------------------------------------------------
   Styles ONLY the new sections added to Views/Shop/detail.cshtml:
     - condition (New/Used) selector
     - payment options (installment + lease terms)
     - trade-in panel + wizard
     - order summary
     - the sticky bar that drops in on scroll

   Everything already on the page (gallery, colour/storage chips, the legacy payment
   plan tabs, bundles, seller, specs, report, FAQ) is untouched: every rule here is
   namespaced under .sd-v2 / .sd-v2-modal / .sd-stickybar so nothing leaks.

   Design tokens below are lifted from the saved Apple buy page in web/design/apple
   (step1evolution.css, lazy-purchase-options.css). Notes on the ones that matter:

     tile        border-radius 12px, 1px solid #86868b, padding 15px, min-height 78px
     tile:checked border-width 2px + padding 14px  <- padding shrinks by exactly the
                 amount the border grows, so the tile does not shift on selection
     disabled    background #00000003, border #86868b6b, text #6e6e73
     easing      cubic-bezier(.4,0,.6,1) is Apple's signature curve
     stickybar   fixed, translateY(-100%) -> 0 over .5s ease-in-out

   Deliberately plain CSS, not Tailwind: this block lives inside a Bootstrap page,
   so it needs no wrapper class and no `npm run build:css` step.

   RTL-safe: logical properties throughout (inline-start/end, margin-inline...).
   ============================================================================= */

.sd-v2,
.sd-v2-modal,
.sd-stickybar {
    /* ---- Apple palette ---- */
    --sd-ink: #1d1d1f;          /* primary text */
    --sd-ink-2: #6e6e73;        /* secondary text, disabled label */
    --sd-ink-3: #86868b;        /* tertiary text, resting tile border */
    --sd-line: #d2d2d7;         /* hairlines, dividers */
    --sd-surface: #fff;
    --sd-surface-2: #f5f5f7;    /* Apple's light grey panel */
    --sd-blue: #0071e3;         /* selected border, links, primary button */
    --sd-blue-hover: #0077ed;
    --sd-green: #008a20;
    --sd-red: #e30000;

    /* ---- geometry ---- */
    --sd-radius-tile: 12px;
    --sd-radius-card: 18px;
    --sd-radius-pill: 980px;

    /* ---- motion ---- */
    --sd-ease: cubic-bezier(.4, 0, .6, 1);

    /* ---- type ---- */
    --sd-font: "SF Pro Text", "SF Pro Display", "SF Pro Icons", -apple-system,
               BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
}

.sd-v2 {
    font-family: var(--sd-font);
    color: var(--sd-ink);
    margin-block-start: 32px;
    -webkit-font-smoothing: antialiased;
}

/* Apple's type scale. Sizes/weights/letter-spacing/line-heights are theirs verbatim. */
.sd-v2 .sd-t-body   { font-size: 17px; font-weight: 400; letter-spacing: -.022em; line-height: 1.4705882353; }
.sd-v2 .sd-t-small  { font-size: 14px; font-weight: 400; letter-spacing: -.016em; line-height: 1.4285914286; }
.sd-v2 .sd-t-fine   { font-size: 12px; font-weight: 400; letter-spacing: -.01em;  line-height: 1.3333733333; }

/* ---- section frame ------------------------------------------------------- */

.sd-v2 .sd-section { margin-block-end: 40px; }

.sd-v2 .sd-section__title {
    font-size: 24px;
    font-weight: 600;
    letter-spacing: .009em;
    line-height: 1.1666666667;
    color: var(--sd-ink);
    margin: 0 0 4px;
}

.sd-v2 .sd-section__hint {
    font-size: 14px;
    font-weight: 400;
    letter-spacing: -.016em;
    line-height: 1.4285914286;
    color: var(--sd-ink-2);
    margin: 0 0 18px;
}

.sd-v2 .sd-section__value { font-weight: 600; color: var(--sd-ink); }

/* ---- the selectable tile -------------------------------------------------
   Apple's .form-selector-label, rebuilt on a <button>. -------------------- */

.sd-v2 .sd-cards { display: grid; gap: 10px; }
.sd-v2 .sd-cards--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sd-v2 .sd-cards--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.sd-v2 .sd-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    inline-size: 100%;
    min-block-size: 78px;               /* Apple: 4.8823529412rem */
    padding: 15px;
    border: 1px solid var(--sd-ink-3);
    border-radius: var(--sd-radius-tile);
    background-color: var(--sd-surface);
    color: var(--sd-ink);
    font-family: var(--sd-font);
    font-size: 17px;
    font-weight: 400;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    cursor: pointer;
    transition: border-color .18s var(--sd-ease), background-color .18s var(--sd-ease);
}

.sd-v2 .sd-card:hover:not(.is-disabled) { border-color: var(--sd-ink); }

.sd-v2 .sd-card.is-selected {
    /* Apple's trick: border grows 1px, padding shrinks 1px -> the tile never shifts. */
    border-width: 2px;
    border-color: var(--sd-blue);
    padding: 14px;
}

.sd-v2 .sd-card.is-disabled {
    background-color: #00000003;
    border-color: #86868b6b;
    color: var(--sd-ink-2);
    cursor: not-allowed;
}

.sd-v2 .sd-card:focus-visible {
    outline: 2px solid var(--sd-blue);
    outline-offset: 3px;
}

.sd-v2 .sd-card__label {
    display: block;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: inherit;
}

.sd-v2 .sd-card__meta {
    display: block;
    margin-block-start: 3px;
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.3333733333;
    color: var(--sd-ink-2);
}

/* "Most popular" pill */
.sd-v2 .sd-pill {
    display: inline-block;
    margin-inline-start: 6px;
    padding: 2px 8px;
    border-radius: var(--sd-radius-pill);
    background: var(--sd-blue);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: -.01em;
    line-height: 1.45;
    vertical-align: middle;
}

.sd-v2 .sd-pill--muted { background: var(--sd-surface-2); color: var(--sd-ink-2); }

/* ---- monthly value - the only money these sections show ------------------ */

.sd-v2 .sd-monthly {
    display: block;
    margin-block-start: 6px;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: var(--sd-ink);
}

.sd-v2 .sd-monthly small {
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-monthly-was {
    margin-inline-end: 6px;
    font-size: 13px;
    font-weight: 400;
    text-decoration: line-through;
    color: var(--sd-ink-2);
}

/* ---- condition ----------------------------------------------------------- */

.sd-v2 .sd-condition__grade {
    display: inline-block;
    margin-inline-start: 6px;
    padding: 1px 8px;
    border: 1px solid var(--sd-line);
    border-radius: var(--sd-radius-pill);
    background: var(--sd-surface-2);
    font-size: 11px;
    font-weight: 400;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-used-banner {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 12px 16px;
    border-radius: var(--sd-radius-tile);
    background: var(--sd-surface-2);
    color: var(--sd-ink);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -.016em;
}

.sd-v2 .sd-used-banner svg { flex: none; color: var(--sd-ink-2); }

/* ---- locked state ---------------------------------------------------------
   "Choose how to pay" stays inert until the trade-in question is answered: a
   trade-in credit changes the financed principal, so the monthly figures are
   provisional until the customer has said whether they have one.
   detail-configurator.js (initPaymentGate) toggles this, and also drops the
   controls out of the tab order - pointer-events alone leaves them reachable by
   keyboard. Applied only when the trade-in section is actually present. */

/* Reads as unavailable rather than just faint: the whole block is greyed and desaturated, the
   cards lose their white fill, and the hint states why. A bare opacity drop was too subtle to
   register as "you cannot use this yet". */
.sd-v2 .sd-section.is-locked {
    pointer-events: none;
    user-select: none;
    position: relative;
}

.sd-v2 .sd-section.is-locked .sd-methods {
    opacity: .4;
    filter: grayscale(1);
    transition: opacity .25s var(--sd-ease), filter .25s var(--sd-ease);
}

.sd-v2 .sd-section.is-locked .sd-section__title { color: var(--sd-ink-3); }

/* Only rendered visible while locked; there is no standing hint under the heading. */
.sd-v2 .sd-section__locked { display: none; }

.sd-v2 .sd-section.is-locked .sd-section__locked {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 0 0 18px;
    padding: 8px 14px;
    border-radius: var(--sd-radius-tile);
    background: var(--sd-surface-2);
    color: var(--sd-ink-2);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -.016em;
}

.sd-v2 .sd-section.is-locked .sd-section__locked::before {
    content: "";
    flex: none;
    inline-size: 14px;
    block-size: 14px;
    /* padlock, inlined so it needs no asset */
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17 10h-1V7a4 4 0 1 0-8 0v3H7a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2zm-7-3a2 2 0 1 1 4 0v3h-4V7z'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17 10h-1V7a4 4 0 1 0-8 0v3H7a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2zm-7-3a2 2 0 1 1 4 0v3h-4V7z'/%3E%3C/svg%3E") center / contain no-repeat;
}


/* ---- payment method cards -------------------------------------------------
   Apple's .rf-po-bfe-dimension-base-label: full-width, LEFT-aligned, content pushed
   apart with space-between, padding 22px 18px, and the same 1px -> 2px border /
   padding-compensation trick as the tiles. Term tiles nest inside the selected card.
   -------------------------------------------------------------------------- */

/* margin-block-start restores the breathing room the section hint used to provide: it was removed
   from this section, leaving the heading's 4px sitting straight on top of the cards. */
.sd-v2 .sd-methods { display: grid; gap: 12px; margin-block-start: 20px; }

/* And a clear break before whatever follows the payment section (the order summary). */
.sd-v2 #sdPaymentSection { margin-block-end: 56px; }

.sd-v2 .sd-method {
    border: 1px solid var(--sd-ink-3);
    border-radius: var(--sd-radius-card);
    background: var(--sd-surface);
    overflow: hidden;
    transition: border-color .18s var(--sd-ease), box-shadow .18s var(--sd-ease);
}

/* --only is a panel, not a control: it must not react to the pointer. */
.sd-v2 .sd-method:hover:not(.is-selected):not(.sd-method--only) { border-color: var(--sd-ink); }

.sd-v2 .sd-method.is-selected {
    border-width: 2px;
    border-color: var(--sd-blue);
}

.sd-v2 .sd-method__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    inline-size: 100%;
    padding: 22px 18px;
    border: 0;
    background: transparent;
    color: inherit;
    font-family: var(--sd-font);
    text-align: start;
    cursor: pointer;
}

/* Border grows 1px on selection, so padding drops 1px and the card never shifts. */
.sd-v2 .sd-method.is-selected .sd-method__head { padding: 21px 17px; }

.sd-v2 .sd-method__head:focus-visible { outline: 2px solid var(--sd-blue); outline-offset: -4px; }

/* The radio dot was removed per request - selection is carried by the card's blue 2px border
   alone, the same way the capacity and term tiles indicate it. */

.sd-v2 .sd-method__text { flex: 1 1 auto; min-inline-size: 0; }

.sd-v2 .sd-method__title {
    display: block;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: var(--sd-ink);
}

.sd-v2 .sd-method__desc {
    display: block;
    margin-block-start: 3px;
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.3333733333;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-method__from {
    flex: none;
    align-self: center;
    font-size: 14px;
    font-weight: 400;
    letter-spacing: -.016em;
    color: var(--sd-ink-2);
    white-space: nowrap;
}

.sd-v2 .sd-method__from b { font-weight: 600; color: var(--sd-ink); }

/* ---- single option: stated, not offered ----------------------------------
   With one payment method there is nothing to choose between, so the card loses
   its selector chrome - no blue selected border, no radio semantics, no
   expand/collapse. It becomes a plain titled panel. Same for a lone term below.
   -------------------------------------------------------------------------- */

.sd-v2 .sd-method--only,
.sd-v2 .sd-method--only.is-selected {
    border-width: 1px;
    border-color: var(--sd-line);
}

.sd-v2 .sd-method__head--static {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    inline-size: 100%;
    padding: 20px 18px 4px;
    cursor: default;      /* nothing to click */
}

.sd-v2 .sd-method--only.is-selected .sd-method__head--static { padding: 20px 18px 4px; }

/* A method whose term is stated on the row itself. No body to expand, so the head owns the full
   padding and the term + price read as one value on the end edge. */
.sd-v2 .sd-method--flat .sd-method__head { padding-block: 20px; }

/* One line: "12 months from $69/mo.". These were display:block, which stacked the duration, the
   amount and the /mo. suffix into three rows. Everything here is inline and the whole line is
   nowrap so the amount can never be split from its suffix. */
.sd-v2 .sd-method__from { white-space: nowrap; }

.sd-v2 .sd-method__from b { display: inline; font-weight: 600; color: var(--sd-ink); }

.sd-v2 .sd-method__from-price {
    display: inline;
    margin-inline-start: 5px;
    font-size: 13px;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-method__from-price small { font-size: 12px; }

.sd-v2 .sd-method__body { padding: 0 18px 20px; }
.sd-v2 .sd-method.is-selected .sd-method__body { padding: 0 17px 19px; }

/* The 1px compensation above pairs with a border that grows on selection. --only keeps a 1px
   border throughout, so it must keep its padding too - otherwise picking a term nudges the whole
   panel a pixel. (It can pick up .is-selected: setMode() marks the method card after a refetch.) */
.sd-v2 .sd-method--only.is-selected .sd-method__body { padding: 0 18px 20px; }

/* ---- lease disclosures ---------------------------------------------------- */

.sd-v2 .sd-lease-terms {
    margin-block-start: 16px;
    padding: 18px 20px;
    border-radius: var(--sd-radius-card);
    background: var(--sd-surface-2);
}

.sd-v2 .sd-lease-terms h4 {
    margin: 0 0 10px;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -.016em;
    color: var(--sd-ink);
}

.sd-v2 .sd-lease-terms ul { margin: 0; padding: 0; list-style: none; }

.sd-v2 .sd-lease-terms li {
    position: relative;
    margin-block-end: 8px;
    padding-inline-start: 16px;
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.3333733333;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-lease-terms li::before {
    content: "";
    position: absolute;
    inset-inline-start: 4px;
    inset-block-start: 7px;
    inline-size: 3px;
    block-size: 3px;
    border-radius: 50%;
    background: var(--sd-ink-3);
}

.sd-v2 .sd-lease-terms li:last-child { margin-block-end: 0; }

/* ---- buttons -------------------------------------------------------------
   Apple's pill button. ---------------------------------------------------- */

.sd-v2 .sd-btn,
.sd-stickybar .sd-btn {
    display: inline-block;
    padding: 12px 22px;
    border: 1px solid var(--sd-blue);
    border-radius: var(--sd-radius-pill);
    background: var(--sd-blue);
    color: #fff;
    font-family: var(--sd-font);
    font-size: 17px;
    font-weight: 400;
    letter-spacing: -.022em;
    line-height: 1.1764805882;
    text-align: center;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color .18s var(--sd-ease), border-color .18s var(--sd-ease);
}

.sd-v2 .sd-btn:hover:not(:disabled),
.sd-stickybar .sd-btn:hover:not(:disabled) {
    background: var(--sd-blue-hover);
    border-color: var(--sd-blue-hover);
}

/* Both scopes, like the :hover and :focus-visible rules around it. The sticky bar sits OUTSIDE
   .sd-v2 (it is position:fixed and must not inherit the section's reveal state), so a .sd-v2-only
   rule left #sdStickyApply looking like a live blue button while it was disabled - the summary's
   Apply greyed out, its twin in the bar did not. */
.sd-v2 .sd-btn:disabled,
.sd-stickybar .sd-btn:disabled { opacity: .42; cursor: not-allowed; }

.sd-v2 .sd-btn:focus-visible,
.sd-stickybar .sd-btn:focus-visible { outline: 2px solid var(--sd-blue); outline-offset: 3px; }

.sd-v2 .sd-btn--ghost {
    background: transparent;
    color: var(--sd-blue);
    border-color: var(--sd-blue);
}

.sd-v2 .sd-btn--ghost:hover:not(:disabled) {
    background: rgba(0, 113, 227, .06);
    border-color: var(--sd-blue);
    color: var(--sd-blue-hover);
}

.sd-v2 .sd-btn--link {
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--sd-blue);
    font-family: var(--sd-font);
    font-size: 14px;
    letter-spacing: -.016em;
    cursor: pointer;
}

.sd-v2 .sd-btn--link:hover { text-decoration: underline; }

/* ---- trade-in ------------------------------------------------------------- */

.sd-v2 .sd-tradein__credit {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-block-start: 16px;
    padding: 12px 16px;
    border-radius: var(--sd-radius-tile);
    background: var(--sd-surface-2);
    color: var(--sd-ink);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -.016em;
}

.sd-v2 .sd-tradein__caveats { margin: 14px 0 0; padding: 0; list-style: none; }

.sd-v2 .sd-tradein__caveats li {
    position: relative;
    margin-block-end: 6px;
    padding-inline-start: 14px;
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.3333733333;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-tradein__caveats li::before {
    content: "";
    position: absolute;
    inset-inline-start: 3px;
    inset-block-start: 7px;
    inline-size: 3px;
    block-size: 3px;
    border-radius: 50%;
    background: var(--sd-ink-3);
}

/* ---- order summary -------------------------------------------------------- */

/* Apple's rf-bfe-summary / rf-po-bfe-purchaseoptionssummary: a full-width #f5f5f7 panel with a
   15px radius and 20px 24px padding, laid out as a flex row rather than a narrow sidebar card.
   The recap rows sit on the start edge, the total and the CTA on the end edge. */
/* =============================================================================
   Order summary - Apple's rf-bfe-summary-section-fullWidth
   -----------------------------------------------------------------------------
   Two columns: the device presented on the start edge (headline, subheadline,
   large product shot), and a white price box on the end edge with the CTA under
   it. Full width, above the FAQ.
   ============================================================================= */

.sd-v2 .sd-summary {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    align-items: center;
    gap: 40px;
    padding: 40px 44px;
    border-radius: 18px;
    background: #e8e8ed;
}

/* ---- left: the device, presented ---- */

.sd-v2 .sd-summary__hero { text-align: center; }

.sd-v2 .sd-summary__headline {
    margin: 0;
    font-size: 28px;
    font-weight: 600;
    letter-spacing: .007em;
    line-height: 1.1428571429;
    color: var(--sd-ink);
}

.sd-v2 .sd-summary__subheadline {
    margin: 4px 0 0;
    font-size: 17px;
    font-weight: 400;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-summary__hero-media {
    margin-block-start: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.sd-v2 .sd-summary__hero-img {
    max-inline-size: 100%;
    max-block-size: 260px;
    inline-size: auto;
    block-size: auto;
    object-fit: contain;
    transition: opacity .22s var(--sd-ease);
}

/* Held while detail-configurator.js swaps the src and waits for the new bitmap to decode, so the
   fade reveals the image rather than an empty box. */
.sd-v2 .sd-summary__hero-img.is-swapping { opacity: 0; }

/* ---- right: the price box ---- */

.sd-v2 .sd-summary__panel { min-inline-size: 0; }

.sd-v2 .sd-summary__box {
    padding: 28px 30px 24px;
    border-radius: 18px;
    background: var(--sd-surface);
    display: flex;
    flex-direction: column;

    /* The box sits on the #e8e8ed panel. A near-invisible lift is what separates the two without
       resorting to a border, which at this size would read as a form field. */
    box-shadow: 0 1px 1px rgba(0, 0, 0, .04), 0 10px 24px -14px rgba(0, 0, 0, .16);
}

/* ---- what you configured ---- */

.sd-v2 .sd-summary__product {
    margin: 0;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2352941176;
    color: var(--sd-ink);
}

.sd-v2 .sd-summary__specs {
    /* min-block-size holds the line before a colour is resolved, so the figure below it does not
       shift the moment the first spec appears. */
    margin: 3px 0 0;
    min-block-size: 19px;
    font-size: 13px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.4615384615;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-summary__spec { display: inline; }

/* Separator drawn only between two VISIBLE specs - the sibling combinator is what makes that work,
   since the first visible spec has no visible spec before it and so gets no leading middot. A fixed
   separator inside each span would strand one the moment its neighbour hides, and these hide
   constantly. */
.sd-v2 .sd-summary__spec:not([hidden]) ~ .sd-summary__spec:not([hidden])::before {
    content: "·";
    margin-inline: 7px;
    color: var(--sd-ink-3);
}

/* ---- the monthly figure ----
   One slot, two mutually exclusive occupants: the prompt or the price. The floor is on this slot
   rather than on the box, so the fact rows and the Apply button below never move - the figure
   resolves in place. */
.sd-v2 .sd-summary__figure {
    display: flex;
    align-items: center;
    min-block-size: 104px;
    margin-block-start: 18px;
}

.sd-v2 .sd-summary__empty {
    margin: 0;
    max-inline-size: 24ch;
    font-size: 15px;
    font-weight: 400;
    letter-spacing: -.016em;
    line-height: 1.3333733333;
    color: var(--sd-ink-3);
}

.sd-v2 .sd-summary__price { display: block; }

.sd-v2 .sd-summary__price-verb {
    display: block;
    font-size: 13px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.2307692308;
    color: var(--sd-ink-2);
}

/* The display figure. tabular-nums is the detail that matters most here: the amount is rewritten
   on every term change, and proportional digits make the whole line twitch as it does. */
.sd-v2 .sd-summary__price-amount {
    display: block;
    margin-block-start: 3px;
    font-size: 44px;
    font-weight: 600;
    letter-spacing: -.021em;
    line-height: 1.0454545455;
    color: var(--sd-ink);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* Raised and lightened, the way a price tag sets its currency - it is a unit, not a digit. */
.sd-v2 .sd-summary__price-cur {
    font-size: .5em;
    font-weight: 500;
    letter-spacing: 0;
    vertical-align: .52em;
    margin-inline-end: 1px;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-summary__price-amount small {
    margin-inline-start: 2px;
    font-size: 15px;
    font-weight: 400;
    letter-spacing: -.016em;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-summary__price-term {
    display: block;
    margin-block-start: 5px;
    font-size: 14px;
    font-weight: 400;
    letter-spacing: -.016em;
    line-height: 1.2857742857;
    color: var(--sd-ink-2);
}

/* ---- the terms behind the figure ---- */

.sd-v2 .sd-summary__facts { margin: 18px 0 0; }

/* Each row owns its own top hairline. On the list instead, it would survive every row hiding and
   leave a rule floating under the figure. */
.sd-v2 .sd-summary__fact {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding-block: 10px;
    border-block-start: 1px solid var(--sd-line);
    font-size: 13px;
    letter-spacing: -.01em;
    line-height: 1.3846153846;
}

.sd-v2 .sd-summary__fact dt {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 400;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-summary__fact dd {
    margin: 0;
    font-weight: 500;
    color: var(--sd-ink);
    text-align: end;
}

.sd-v2 .sd-summary__fact--credit dd { font-weight: 600; color: var(--sd-green); }
.sd-v2 .sd-summary__fact--credit dd b { font-weight: inherit; }

/* Tick on the trade-in row. Sized to the 13px label it sits in, not to the 15px it was when this
   was a standalone note block. */
.sd-v2 .sd-summary__note-icon {
    flex: none;
    inline-size: 14px;
    block-size: 14px;
    border-radius: 50%;
    background: var(--sd-green);
    position: relative;
}

.sd-v2 .sd-summary__note-icon::after {
    content: "";
    position: absolute;
    inset-inline-start: 4.5px;
    inset-block-start: 3px;
    inline-size: 4px;
    block-size: 6.5px;
    border: solid #fff;
    border-width: 0 1.5px 1.5px 0;
    transform: rotate(45deg);
}

.sd-v2 .sd-summary__cta { margin-block-start: 20px; }
.sd-v2 .sd-summary__cta .sd-btn { inline-size: 100%; padding-block: 14px; font-size: 17px; }

/* =============================================================================
   FAQ accordion - Apple's buy-flow FAQ
   Built on <details>/<summary>: keyboard support, screen-reader semantics and
   find-in-page all come for free. Chevron + open animation are CSS only.
   ============================================================================= */

.sd-v2 .sd-faq { margin-block-start: 12px; }

.sd-v2 .sd-faq__list { border-block-start: 1px solid var(--sd-line); }

.sd-v2 .sd-faq__item { border-block-end: 1px solid var(--sd-line); }

.sd-v2 .sd-faq__q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 18px 2px;
    cursor: pointer;
    list-style: none;                 /* kill the native marker... */
    font-size: 17px;
    font-weight: 400;
    letter-spacing: -.022em;
    line-height: 1.4705882353;
    color: var(--sd-ink);
    transition: color .18s var(--sd-ease);
}

.sd-v2 .sd-faq__q::-webkit-details-marker { display: none; }   /* ...Safari's too */

.sd-v2 .sd-faq__q:hover { color: var(--sd-blue); }
.sd-v2 .sd-faq__q:focus-visible { outline: 2px solid var(--sd-blue); outline-offset: 2px; }

.sd-v2 .sd-faq__q-text { flex: 1 1 auto; }

.sd-v2 .sd-faq__chevron {
    flex: none;
    display: inline-flex;
    color: var(--sd-ink-2);
    transition: transform .3s var(--sd-ease), color .18s var(--sd-ease);
}

.sd-v2 .sd-faq__item[open] .sd-faq__chevron { transform: rotate(180deg); color: var(--sd-blue); }
.sd-v2 .sd-faq__item[open] .sd-faq__q { color: var(--sd-ink); font-weight: 600; }

.sd-v2 .sd-faq__a {
    padding: 0 2px 20px;
    max-inline-size: 62ch;
}

.sd-v2 .sd-faq__a p {
    margin: 0;
    font-size: 14px;
    font-weight: 400;
    letter-spacing: -.016em;
    line-height: 1.5714;
    color: var(--sd-ink-2);
}

/* Answers slide open. Only applied where the browser can animate to height:auto
   (interpolate-size), so nowhere else does it clip content. */
@supports (interpolate-size: allow-keywords) {
    .sd-v2 .sd-faq__item::details-content {
        block-size: 0;
        overflow: hidden;
        transition: block-size .32s var(--sd-ease), content-visibility .32s allow-discrete;
    }
    .sd-v2 .sd-faq__item[open]::details-content { block-size: auto; }
}

@media (max-width: 575.98px) {
    .sd-v2 .sd-faq__q { font-size: 15px; padding: 15px 2px; }
    .sd-v2 .sd-faq__a { padding-block-end: 16px; }
    .sd-v2 .sd-faq__a p { font-size: 13px; }
}

/* =============================================================================
   Sticky bar - Apple's .rf-bfe-stickybar
   Fixed to the top, slides down from translateY(-100%) once the main CTA has
   scrolled out of view. pointer-events are off on the container so it never
   swallows clicks while hidden.
   ============================================================================= */

.sd-stickybar {
    position: fixed;

    /* The site header (.sticky-bar.stick) is permanently position:fixed at top:0 - "stick" is in
       the markup, not added on scroll.

       --sd-bar-top is THIS bar's own offset, and it is not the same as the header height: the
       header withdraws exactly when this bar appears, so the bar takes its place at 0. It only
       parks below the header while it is hidden (sliding up behind the nav rather than poking
       out above it). Using the header height here left the bar floating a header down the page.
       detail-configurator.js keeps it current; 0 is only the pre-JS value. */
    inset-block-start: var(--sd-bar-top, 0px);
    inset-inline-start: 0;
    inline-size: 100%;

    /* Deliberately below the site header's z-index:1000, so the bar slides up BEHIND the nav when
       it hides instead of poking out above it. */
    z-index: 999;
    pointer-events: none;
    font-family: var(--sd-font);
}

/* While the product bar is showing, the global header withdraws upward so the two never stack.
   Only a transform - the header keeps its layout box and every nav handler stays bound, so it
   slides straight back when the bar hides. */
header.sticky-bar.sd-header-withdrawn,
.sticky-bar.sd-header-withdrawn {
    transform: translateY(-100%);
    transition: transform .4s ease-in-out;
}

header.sticky-bar,
.sticky-bar {
    transition: transform .4s ease-in-out;
}

.sd-stickybar__content {
    /* Opaque white, NOT the translucent blur it had before: the selection chips are #f5f5f7, and
       against rgba(255,255,255,.92) that is a ~2% difference - the chips read as white and the
       colour looked like it had never been applied. A solid backdrop is what makes them visible. */
    background-color: #fff;
    border-block-end: 1px solid var(--sd-line);
    transform: translateY(-100%);
    transition: transform .5s ease-in-out;
}

.sd-stickybar.is-visible .sd-stickybar__content {
    transform: translateY(0);
    pointer-events: auto;
}

/* Apple's .rf-bfe-container: one gutter shared by both rows so name, price and the strip below
   line up on the same left edge. */
/* Mirrors the global header's frame exactly, so this bar's content lines up with the nav above
   it rather than sitting inset from it.
   Source: assets/css/header-revamp.css -> .header--nm .container
       max-width 1280px, padding-inline 16px, dropping to 0 at >=1280px.
   The previous 1180px + permanent 16px gutter left the title and Apply button roughly 66px
   inboard of the header's logo and account links. Keep these two in step if the header changes. */
.sd-stickybar__container {
    max-inline-size: 1280px;
    inline-size: 100%;
    margin-inline: auto;
    padding-inline: max(16px, env(safe-area-inset-left)) max(16px, env(safe-area-inset-right));
}

@media (min-width: 1280px) {
    .sd-stickybar__container {
        padding-inline: max(0px, env(safe-area-inset-left)) max(0px, env(safe-area-inset-right));
    }
}

/* ---- row 1: header ---- */

.sd-stickybar__header .sd-stickybar__container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding-block: 11px;
}

.sd-stickybar__title {
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: var(--sd-ink);
    margin: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sd-stickybar__price {
    font-size: 14px;
    font-weight: 400;
    letter-spacing: -.016em;
    line-height: 1.4285914286;
    color: var(--sd-ink-2);
    margin: 1px 0 0;
    white-space: nowrap;
}

.sd-stickybar__price b { font-weight: 600; color: var(--sd-ink); }

.sd-stickybar__actions { display: flex; align-items: center; gap: 12px; flex: none; }

.sd-stickybar .sd-btn { padding: 8px 18px; font-size: 14px; letter-spacing: -.016em; }

/* Apple's -withdimensionselected modifier. Once a configuration exists the bar carries two rows,
   so the header tightens to keep the whole thing from eating the viewport. */
.sd-stickybar__content.is-dimension-selected .sd-stickybar__header .sd-stickybar__container {
    padding-block: 8px;
}

/* ---- row 2: fulfillment scroller (Apple's .rf-bfe-stickybar-fulfillment) ----
   A hairline separates it from the header row, and the strip scrolls horizontally with paddlenav
   arrows either side. The scrollbar itself is hidden: the paddles and the edge fades are the
   affordance, exactly as on Apple's bar. -------------------------------------- */

.sd-stickybar__fulfillment {
    border-block-start: 1px solid var(--sd-line);
}

.sd-stickybar__scroller-crop {
    position: relative;
    display: flex;
    align-items: center;
}

.sd-stickybar__scroller-content {
    flex: 1 1 auto;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;              /* Firefox */
    -ms-overflow-style: none;           /* legacy Edge */
    scroll-behavior: smooth;
}

.sd-stickybar__scroller-content::-webkit-scrollbar { display: none; }

.sd-stickybar__platter {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-block: 8px;
    inline-size: max-content;
}

/* Selection chips: same fill as the order summary, so the two surfaces that recap the
   configuration read as one material. #e8e8ed rather than Apple's #f5f5f7 - against the white
   bar, their grey was invisible. */
.sd-stickybar__cell {
    flex: none;
    padding: 4px 12px;
    border: 1px solid transparent;
    border-radius: var(--sd-radius-pill);
    background: #e8e8ed;
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.3333733333;
    color: var(--sd-ink-2);
    white-space: nowrap;
}

/* The chosen configuration reads as the primary information; delivery options sit behind it.
   Distinguished by weight and ink now that both share the same fill. */
.sd-stickybar__cell--dimension {
    font-weight: 500;
    color: var(--sd-ink);
}

/* ---- paddlenav ---- */

.sd-paddlenav {
    position: relative;
    flex: none;
    display: none;                      /* only meaningful once the strip overflows */
}

.sd-stickybar__scroller-crop.has-overflow .sd-paddlenav { display: block; }

.sd-paddlenav__arrow {
    inline-size: 28px;
    block-size: 28px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--sd-ink-2);
    cursor: pointer;
    transition: color .18s var(--sd-ease), opacity .18s var(--sd-ease);
}

.sd-paddlenav__arrow:hover:not(:disabled) { color: var(--sd-ink); }
.sd-paddlenav__arrow:disabled { opacity: .28; cursor: default; }
.sd-paddlenav__arrow:focus-visible { outline: 2px solid var(--sd-blue); outline-offset: 2px; }

/* Chevrons drawn in CSS - no icon font or SVG dependency, and they flip under RTL for free
   because the border box is rotated rather than pointing at a fixed direction. */
.sd-paddlenav__arrow::before {
    content: "";
    display: block;
    inline-size: 8px;
    block-size: 8px;
    margin-inline: auto;
    border-block-start: 1.5px solid currentColor;
    border-inline-end: 1.5px solid currentColor;
}

.sd-paddlenav--prev .sd-paddlenav__arrow::before { transform: rotate(-135deg); margin-inline-start: 12px; }
.sd-paddlenav--next .sd-paddlenav__arrow::before { transform: rotate(45deg);   margin-inline-end: 12px; }

/* Edge fades, so a cell scrolling out of view dissolves instead of being cut off. */
.sd-stickybar__scroller-crop.has-overflow::before,
.sd-stickybar__scroller-crop.has-overflow::after {
    content: "";
    position: absolute;
    inset-block: 0;
    inline-size: 24px;
    pointer-events: none;
    z-index: 1;
}

.sd-stickybar__scroller-crop.has-overflow::before {
    inset-inline-start: 28px;
    background: linear-gradient(to right, rgba(255,255,255,.92), rgba(255,255,255,0));
}

.sd-stickybar__scroller-crop.has-overflow::after {
    inset-inline-end: 28px;
    background: linear-gradient(to left, rgba(255,255,255,.92), rgba(255,255,255,0));
}

[dir="rtl"] .sd-stickybar__scroller-crop.has-overflow::before {
    background: linear-gradient(to left, rgba(255,255,255,.92), rgba(255,255,255,0));
}

[dir="rtl"] .sd-stickybar__scroller-crop.has-overflow::after {
    background: linear-gradient(to right, rgba(255,255,255,.92), rgba(255,255,255,0));
}

/* Screen-reader-only label on the paddle buttons. */
.sd-visuallyhidden {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* =============================================================================
   Trade-in - inline widget
   -----------------------------------------------------------------------------
   Port of Apple's .rf-bfe-tradeup-* / .rf-tradeupinline-* module. Replaced the
   modal wizard: the whole flow, condition questionnaire included, now lives in
   the page. Two radios side by side, a drawer spanning both beneath them, and
   one titled <select> per question inside it.
   ============================================================================= */

.sd-v2 .sd-tradeup__header { margin-block-end: 18px; }

/* Apple sets the section name and the credit range in ONE heading, the range in a
   lighter weight - not a title with a separate subtitle beneath it. */
.sd-v2 .sd-tradeup__title {
    margin: 0;
    font-size: 24px;
    font-weight: 600;
    letter-spacing: .009em;
    line-height: 1.1666666667;
    color: var(--sd-ink);
}

.sd-v2 .sd-tradeup__sub {
    font-weight: 400;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-tradeup__row { display: grid; grid-template-columns: 1fr; gap: 24px; }

/* Single column stacked: options, then the drawer, then the info card. Explicit rows so the
   drawer follows the options it belongs to instead of being pushed below the info card. */
.sd-v2 .sd-tradeup__left { grid-row: 1; }
.sd-v2 .sd-tradeup__drawer { grid-row: 2; }

@media (min-width: 992px) {
    /* Single column since the "How does trade-in work?" card was removed - the two options and the
       drawer both span the full width now. Restoring that card means putting the second track
       (minmax(0, 300px)) back here and giving .sd-tradeup__right grid-column: 2. */
    .sd-v2 .sd-tradeup__row {
        grid-template-columns: minmax(0, 1fr);
        column-gap: 32px;
        row-gap: 20px;
        align-items: start;
    }

    /* Options and the info card share row 1; the drawer takes the whole of row 2, so it runs the
       full width of the widget rather than stopping at the left column. */
    .sd-v2 .sd-tradeup__left { grid-column: 1 / -1; grid-row: 1; }
    .sd-v2 .sd-tradeup__drawer { grid-column: 1 / -1; grid-row: 2; }
}

/* ---- the two options ----
   The drawer is no longer in here - it is a child of .sd-tradeup__row so it can span the full
   width of the widget. This grid holds only the two radio tiles. */
.sd-v2 .sd-tradeup__selectors {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

@media (max-width: 575.98px) {
    .sd-v2 .sd-tradeup__selectors { grid-template-columns: minmax(0, 1fr); }
}

/* The radio itself is visually hidden but still focusable, so the label carries the
   selected styling and keyboard focus lands somewhere visible. */
.sd-v2 .sd-tradeup__input {
    position: absolute;
    opacity: 0;
    inline-size: 1px;
    block-size: 1px;
    margin: 0;
}

/* One tile height shared by the two option tiles and the "How does trade-in work?" card beside
   them, so the three read as a single row. Change it here and all three follow.
   92px rather than Apple's 78px: the info card's two lines of copy do not fit in 78, and growing
   the row is better than truncating the sentence to a fragment. */
.sd-v2 .sd-tradeup__row { --sd-tradeup-tile-h: 92px; }

.sd-v2 .sd-tradeup__label {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;      /* centred horizontally - the two tiles read as a pair of choices */
    text-align: center;
    gap: 3px;
    block-size: 100%;
    min-block-size: var(--sd-tradeup-tile-h);
    margin: 0;
    padding: 15px 17px;
    border: 1px solid var(--sd-ink-3);
    border-radius: var(--sd-radius-tile);
    background: var(--sd-surface);
    cursor: pointer;
    transition: border-color .18s var(--sd-ease);
}

.sd-v2 .sd-tradeup__label:hover { border-color: var(--sd-ink); }

/* Apple's border/padding compensation: the border grows 1px, the padding loses 1px,
   so the tile never shifts on selection. */
.sd-v2 .sd-tradeup__input:checked + .sd-tradeup__label {
    border-width: 2px;
    border-color: var(--sd-blue);
    padding: 14px 16px;
}

.sd-v2 .sd-tradeup__input:focus-visible + .sd-tradeup__label {
    outline: 2px solid var(--sd-blue);
    outline-offset: 3px;
}

.sd-v2 .sd-tradeup__label-title {
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: var(--sd-ink);
}

.sd-v2 .sd-tradeup__label-sub {
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.3333733333;
    color: var(--sd-ink-2);
}

/* ---- drawer ---- */

.sd-v2 .sd-tradeup__drawer {
    margin-block-start: 4px;
    padding: 22px;
    border: 1px solid var(--sd-line);
    border-radius: var(--sd-radius-card);
    background: var(--sd-surface-2);
}

/* ---- one module per question ---- */

/* Two questions per row, filling left-to-right then wrapping: device type + brand, then model +
   capacity, then the condition questions two at a time. Modules are appended one at a time as
   each answer comes back, and grid auto-placement puts each new one in the next free cell. */
/* ONE MODULE PER ROW. Model, capacity and each condition question get the full width of the
   widget - they are sequential steps, and pairing two of them side by side reads as though they
   were alternatives rather than an order to work through. */
.sd-v2 .sd-tradeup__modules {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    row-gap: 24px;
    align-items: start;
}

/* Help text now sits UNDER its select rather than beside it - at half width there is no room for
   Apple's side-by-side pairing. min-inline-size:0 so a long option label cannot widen the track. */
.sd-v2 .sd-tradeup__module {
    display: flex;
    flex-direction: column;
    /* Compounds with the title's own bottom margin, so it stays small - the two together are the
       gap between a question and its answer control. */
    gap: 2px;
    min-inline-size: 0;
}

/* Apple pairs the dropdown with its help copy side by side. There is room for that now each
   module owns a full row, so the select takes the start half and the guidance the end half. */
@media (min-width: 768px) {
    .sd-v2 .sd-tradeup__module:not(.sd-tradeup__module--choice) {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        column-gap: 28px;
        align-items: start;
    }

    /* The title spans both columns so the select and its help start on the same line. */
    .sd-v2 .sd-tradeup__module:not(.sd-tradeup__module--choice) .sd-tradeup__module-title {
        grid-column: 1 / -1;
    }
}

.sd-v2 .sd-tradeup__module .sd-tradeup__field { max-inline-size: 420px; }

/* Help copy beside the select - backend-supplied, so it may run to a few paragraphs and a link. */
.sd-v2 .sd-tradeup__module-help {
    font-size: 12px;
    line-height: 1.5;
    letter-spacing: -.01em;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-tradeup__module-help p { margin: 0 0 8px; }
.sd-v2 .sd-tradeup__module-help p:last-child { margin-block-end: 0; }
.sd-v2 .sd-tradeup__module-help a { color: var(--sd-blue); text-decoration: none; }
.sd-v2 .sd-tradeup__module-help a:hover { text-decoration: underline; }

.sd-visuallyhidden {
    position: absolute;
    inline-size: 1px; block-size: 1px;
    padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.sd-v2 .sd-tradeup__module-title {
    /* 8px + the module's 2px row-gap = 10px to the control. Was 16px (too loose, and the deleted
       42px reservation put ~37px under a one-line title); 4px closed it up too far. */
    margin: 0 0 8px;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: var(--sd-ink);
}

/* A two-line min-block-size used to sit here, reserving height so that two selects sharing a row
   ("What are you trading in?" beside "Which brand?") lined up. Both of those steps are gone - the
   wizard opens straight on the model - so under a one-line title it was only ever ~21px of dead
   space between the question and its dropdown. */

.sd-v2 .sd-tradeup__module-help {
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.3333733333;
    color: var(--sd-ink-2);
    margin: 0;
}

/* ---- the select ----
   Native <select>, restyled. A custom listbox would have to reimplement keyboard
   handling, type-ahead and the mobile picker for no gain. */
.sd-v2 .sd-tradeup__field { position: relative; }

.sd-v2 .sd-tradeup__select {
    appearance: none;
    -webkit-appearance: none;
    inline-size: 100%;
    padding: 13px 44px 13px 16px;
    border: 1px solid var(--sd-ink-3);
    border-radius: var(--sd-radius-tile);
    background: var(--sd-surface);
    color: var(--sd-ink);
    font-family: var(--sd-font);
    font-size: 15px;
    font-weight: 400;
    letter-spacing: -.016em;
    line-height: 1.4;
    cursor: pointer;
}

.sd-v2 .sd-tradeup__select:hover { border-color: var(--sd-ink); }

.sd-v2 .sd-tradeup__select:focus-visible {
    outline: 2px solid var(--sd-blue);
    outline-offset: 2px;
}

/* Chevron drawn in CSS, mirrored for RTL by flipping which edge it sits on. */
.sd-v2 .sd-tradeup__field::after {
    content: "";
    position: absolute;
    inset-inline-end: 18px;
    inset-block-start: 50%;
    inline-size: 8px;
    block-size: 8px;
    margin-block-start: -6px;
    border-inline-end: 1.5px solid var(--sd-ink-2);
    border-block-end: 1.5px solid var(--sd-ink-2);
    transform: rotate(45deg);
    pointer-events: none;
}

/* ---- estimate ---- */

/* ---- condition questions: radio tiles -------------------------------------
   Apple's .rf-tradeupinline-question - a two-up grid of .form-selector-label
   tiles, LEFT aligned with a title and optional small print. Dropdowns are used
   only for the device dimensions above; the condition answers carry explanatory
   copy and need to be readable side by side. --------------------------------- */

.sd-v2 .sd-tradeup__module--choice { display: block; }

.sd-v2 .sd-tradeup__module-desc {
    margin: 0 0 12px;
    font-size: 12px;
    line-height: 1.45;
    letter-spacing: -.01em;
    color: var(--sd-ink-2);
    max-inline-size: 62ch;
}

.sd-v2 .sd-tradeup__module-intro { margin: 0 0 6px; font-weight: 500; color: var(--sd-ink); }

.sd-v2 .sd-tradeup__module-desc ul { margin: 0; padding: 0; list-style: none; }

.sd-v2 .sd-tradeup__module-desc li {
    position: relative;
    padding-inline-start: 15px;
    margin-block-end: 4px;
}

.sd-v2 .sd-tradeup__module-desc li::before {
    content: "";
    position: absolute;
    inset-inline-start: 3px;
    inset-block-start: 7px;
    inline-size: 4px;
    block-size: 4px;
    border-radius: 50%;
    background: var(--sd-ink-3);
}

.sd-v2 .sd-tradeup__choices {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

/* Kept at two columns even on mobile: the labels are a single word, so stacking them wastes
   height and makes a binary choice look like a list. */

.sd-v2 .sd-tradeup__choice { position: relative; display: flex; }

/* Visually hidden but still focusable, so the label carries the styling and focus is visible. */
.sd-v2 .sd-tradeup__choice-input {
    position: absolute;
    opacity: 0;
    inline-size: 1px;
    block-size: 1px;
}

/* Bare "Yes" / "No" - the criteria live in the points above, so the tile stays short and two
   genuinely fit on a row. Centred, because a one-word label reads oddly left-aligned in a wide box. */
.sd-v2 .sd-tradeup__choice-label {
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 100%;
    margin: 0;
    padding: 14px 17px;
    border: 1px solid var(--sd-ink-3);
    border-radius: var(--sd-radius-tile);
    background: var(--sd-surface);
    cursor: pointer;
    text-align: start;
    transition: border-color .18s var(--sd-ease);
}

.sd-v2 .sd-tradeup__choice-label:hover { border-color: var(--sd-ink); }

/* Border grows 1px, padding drops 1px - the tile never shifts on selection. */
.sd-v2 .sd-tradeup__choice-input:checked + .sd-tradeup__choice-label {
    border-width: 2px;
    border-color: var(--sd-blue);
    padding: 13px 16px;
}

.sd-v2 .sd-tradeup__choice-input:focus-visible + .sd-tradeup__choice-label {
    outline: 2px solid var(--sd-blue);
    outline-offset: 3px;
}

/* Graded tiles ("Good" / "Damaged") carry their explanation inside, so they align to the start
   and stack title over description - Apple's rf-dimension-text-left. */
.sd-v2 .sd-tradeup__choices--rich .sd-tradeup__choice-label {
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 6px;
    padding: 16px 18px;
    text-align: start;
}

.sd-v2 .sd-tradeup__choices--rich .sd-tradeup__choice-input:checked + .sd-tradeup__choice-label {
    padding: 15px 17px;
}

.sd-v2 .sd-tradeup__choice-desc {
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.3333733333;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-tradeup__choice-title {
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: var(--sd-ink);
}


/* "Done" under the modules - closes the editor and puts the existing result back. Only rendered
   while re-editing an answered trade-in, so it never appears on the first run through. */
.sd-v2 .sd-tradeup__collapse {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    inline-size: 100%;
    margin-block-start: 18px;
    padding-block-start: 14px;
    padding-inline: 0;
    border: 0;
    border-block-start: 1px solid var(--sd-line);
    background: transparent;
    color: var(--sd-blue);
    font-family: var(--sd-font);
    font-size: 14px;
    letter-spacing: -.016em;
    cursor: pointer;
}

/* Chevron pointing up - the control collapses the editor. */
.sd-v2 .sd-tradeup__collapse::after {
    content: "";
    inline-size: 8px;
    block-size: 8px;
    border: solid currentColor;
    border-width: 2px 2px 0 0;
    transform: rotate(-45deg);
    margin-block-start: 3px;
}

.sd-v2 .sd-tradeup__collapse:hover { text-decoration: underline; }
.sd-v2 .sd-tradeup__collapse:focus-visible { outline: 2px solid var(--sd-blue); outline-offset: 3px; }

/* ---- outcome panel: quote or recycle --------------------------------------
   Apple's .rf-tradeupinline-quote - a tick, the headline, the value, and an Edit
   button on the end edge. Replaces the question modules once there is a result.
   --------------------------------------------------------------------------- */

.sd-v2 .sd-tradeup__estimate { margin-block-start: 18px; }

.sd-v2 .sd-tradeup__quote {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 18px 20px;
    border-radius: var(--sd-radius-tile);
    background: var(--sd-surface);
}

.sd-v2 .sd-tradeup__quote-icon {
    flex: none;
    inline-size: 22px;
    block-size: 22px;
    margin-block-start: 1px;
    border-radius: 50%;
    background: var(--sd-green);
    position: relative;
}

/* tick */
.sd-v2 .sd-tradeup__quote-icon--ok::after {
    content: "";
    position: absolute;
    inset-inline-start: 7px;
    inset-block-start: 4px;
    inline-size: 6px;
    block-size: 11px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

/* recycle: neutral, not an error - the device is still useful */
.sd-v2 .sd-tradeup__quote-icon--recycle { background: var(--sd-ink-3); }

.sd-v2 .sd-tradeup__quote-icon--recycle::after {
    content: "";
    position: absolute;
    inset: 5px;
    border: 2px solid #fff;
    border-radius: 50%;
    border-block-start-color: transparent;
}

.sd-v2 .sd-tradeup__quote-body { flex: 1 1 auto; min-inline-size: 0; }

.sd-v2 .sd-tradeup__quote-label {
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: var(--sd-ink);
}

.sd-v2 .sd-tradeup__quote-priceheader {
    margin-block-start: 6px;
    font-size: 13px;
    letter-spacing: -.016em;
    line-height: 1.45;
    color: var(--sd-ink-2);
}

.sd-v2 .sd-tradeup__quote-price {
    margin-block-start: 2px;
    font-size: 24px;
    font-weight: 600;
    letter-spacing: .009em;
    line-height: 1.1666666667;
    color: var(--sd-ink);
}

.sd-v2 .sd-tradeup__quote-edit {
    flex: none;
    border: 0;
    padding: 0;
    background: transparent;
    color: var(--sd-blue);
    font-family: var(--sd-font);
    font-size: 14px;
    letter-spacing: -.016em;
    cursor: pointer;
}

.sd-v2 .sd-tradeup__quote-edit:hover { text-decoration: underline; }

@media (max-width: 575.98px) {
    .sd-v2 .sd-tradeup__quote { padding: 15px 16px; gap: 11px; }
    .sd-v2 .sd-tradeup__quote-label { font-size: 15px; }
    .sd-v2 .sd-tradeup__quote-price { font-size: 21px; letter-spacing: .011em; }
}

/* ---- "How does trade-in work?" card (Apple's .rc-decisionsection) ---- */

/* Same box as an option tile - same height, padding and radius - so it lines up with "No trade-in"
   rather than sitting proud of it. Content is centred for the same reason the tiles centre theirs. */
.sd-v2 .sd-tradeup__info {
    display: flex;
    flex-direction: column;
    justify-content: center;
    block-size: var(--sd-tradeup-tile-h);
    padding: 15px 17px;
    border: 1px solid var(--sd-line);
    border-radius: var(--sd-radius-tile);
    background: var(--sd-surface);
    overflow: hidden;
}

.sd-v2 .sd-tradeup__info-title {
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -.016em;
    line-height: 1.3;
    color: var(--sd-ink);
}

/* Clamped so a long translation cannot push the card past the shared tile height and break the
   alignment the height exists to create. */
.sd-v2 .sd-tradeup__info-desc {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-block-start: 6px;
    font-size: 13px;
    font-weight: 400;
    letter-spacing: -.01em;
    line-height: 1.35;
    color: var(--sd-ink-2);
}


/* =============================================================================
   Legacy payment-plans block
   Superseded by "Choose how to pay". The markup MUST stay in the DOM - detail.js
   drives #paymentPlans / .payment-plans / .plan-button / .tb / setActivePlan and
   repaints it from getPaymentPlans2() on every variant change - so it is hidden
   rather than removed. !important beats the .d-none toggling detail.js does.
   ============================================================================= */

#paymentPlans.sd-legacy-plans { display: none !important; }

/* The standalone Buy button under the colour swatches (rendered when the listing is not
   installment-eligible). Superseded by the Apply button in the order summary, but detail.js
   binds .buyDevice / #buyDevice for the full-payment checkout path, so it is hidden, not removed. */
.sd-legacy-buy { display: none !important; }

/* Its container goes too. Everything inside is hidden now, but detail.css:170 gives .div_btns
   `border-top: 2px solid #EEEEEE; margin-top: 21px; padding-top: 20px`, so an empty one still
   drew a rule and a gap directly under the capacity list. Only the buy-case container is hidden -
   the "interested" and "reserved" cases share the class .div_btns but still show content. */
#buy_device .div_btns.sd-legacy-btns { display: none !important; }

/* Location + map: the map element must stay in the DOM because detail.js initMapD() calls
   new google.maps.Map(document.getElementById("map"), ...) with no null guard. */
.sd-map-hidden { display: none !important; }

/* =============================================================================
   Placement + responsive
   ============================================================================= */

/* Full-width band under the gallery + configuration row. Two columns on desktop:
   payment + trade-in on the left, the order summary parked on the right, which is what
   fills the space the old single-column placement left empty. */

/* No top rule. It spanned the whole container, so it drew a line under the gallery AND under the
   colour swatches beside it - reading as two stray dividers rather than one section break. The
   spacing separates the band from the row above on its own. */
.sd-v2--band {
    margin-block-start: 8px;
    padding-block-start: 40px;
}

/* Single full-width column: trade-in, then payment, then the summary. The summary used to sit
   in a sticky right-hand rail; Apple's rf-bfe-summary is a full-width band above the FAQ, and
   that is what this now is. The sticky rail (and its --sd-summary-top offset) is gone with it. */
.sd-v2 .sd-band { display: block; }

/* =============================================================================
   position:sticky blocker  -  READ BEFORE CHANGING
   -----------------------------------------------------------------------------
   css/custome.css sets:

       #buy_device { overflow: hidden; position: relative; }

   #buy_device wraps this whole page, and an ancestor whose overflow is anything
   other than `visible` becomes the scroll container that sticky positions
   against. That container never scrolls itself, so every sticky descendant has
   zero travel and appears completely dead - which is exactly what happened to
   the order summary.

   `overflow-x: clip` + `overflow-y: visible` is the one combination that fixes
   it without side effects: the horizontal clipping the original rule was there
   for is kept, while the vertical axis stays truly visible and creates no scroll
   container. (Plain `visible` on one axis with `hidden` on the other is NOT an
   option - the spec forces the `visible` side to compute to `auto`, which would
   reintroduce the blocker and add a stray scrollbar. `clip` is the exception the
   spec allows to pair with `visible`.)

   This stylesheet loads at _Layout line 58, after custome.css at line 50, so an
   equal-specificity override is enough - no !important needed.
   ============================================================================= */

#buy_device {
    overflow-x: clip;
    overflow-y: visible;
}


/* =============================================================================
   Hero row - sticky gallery, page-scrolled configuration
   -----------------------------------------------------------------------------
   Apple's behaviour, and the reason this is NOT an inner scroll container:

   The GALLERY sticks. The configuration column beside it is ordinary page
   content that scrolls past it, and when the row ends the gallery releases and
   the page carries on to Trade in.

   An earlier attempt capped the configuration column's height and gave it
   overflow-y:auto. That was wrong on two counts: the wheel gesture felt like a
   nested pane rather than a page, and dragging its scrollbar bypassed the
   sequencing entirely. Sticky has neither problem - there is only ever ONE
   scroller (the page), so the scroll always feels native.

   align-self:flex-start is REQUIRED: Bootstrap's .row is a flexbox and stretches
   its children to full height by default, which silently makes sticky a no-op.

   --sd-pinned-top is the height of whatever chrome is fixed to the top RIGHT
   NOW: the site header at first, then the product bar once it drops in and
   withdraws the header. Offsetting from it is what stops the image sliding
   under either one. detail-configurator.js keeps it current.
   ============================================================================= */

/* ---- gallery width -------------------------------------------------------
   The image is capped by style.css:8312  .product-image-slider { max-width: 500px }.

   DO NOT reduce .galleries' 105px padding-inline-start to gain room. That gutter is
   reserved for the thumbnail rail, which style.css:8268 positions
   `position:absolute; left:0; width:94px` INSIDE the gallery. Removing the padding
   drops the rail straight on top of the main image - that is exactly what happened
   when it was tried. The extra width comes from the column split instead
   (col-lg-8 / col-lg-4 in detail.cshtml).

   min(...,100%) is the guard that matters: a fixed 620px overflows the column on
   narrower viewports and spills over the configuration column beside it.

   Scoped to #buy_device .sd-gallery-col so the shop, home and sell galleries keep
   their own sizing. Slick measures the container when it initialises, and these
   rules land before that, so the slide widths come out right without a refresh.
   -------------------------------------------------------------------------- */

@media (min-width: 992px) {
    #buy_device .sd-gallery-col .product-image-slider {
        max-inline-size: min(620px, 100%);
    }
}

@media (min-width: 992px) {
    #buy_device .sd-gallery-col {
        position: sticky;

        /* --sd-gallery-top is the column's OWN resting position, measured once per layout by
           detail-configurator.js. Because the offset already equals where the column sits at
           scroll 0, sticky engages immediately and the image never moves at all - it holds while
           the configuration column scrolls past it, and releases when the row ends.

           Using --sd-pinned-top here instead (header/bar height) is what made the image drift:
           the column started BELOW that offset, so it scrolled up to meet it first, then jumped
           again when the product bar changed the value mid-scroll. This one never changes while
           scrolling. */
        inset-block-start: var(--sd-gallery-top, 88px);
        align-self: flex-start;

        /* A gallery taller than the space under the pinned chrome would be pinned with its lower
           half permanently off-screen. Bound it to what is actually visible and let the image
           scale down inside, so the whole thing stays on screen instead of being cropped. */
        max-block-size: calc(100vh - var(--sd-pinned-top, 72px) - 32px);
        display: flex;
        flex-direction: column;
    }

    #buy_device .sd-gallery-col .gallery-image {
        min-block-size: 0;          /* lets the flex child actually shrink */
        display: flex;
        flex-direction: column;
    }

    #buy_device .sd-gallery-col .product-image-slider img,
    #buy_device .sd-gallery-col .detail-gallery img {
        /* Reserve for the fav/badge row above and the thumbnail strip below. Loosened from 190px
           so the extra width above is not immediately cancelled out by the height cap - a
           contained image scales on whichever axis binds first. */
        max-block-size: calc(100vh - var(--sd-pinned-top, 72px) - 150px);
        object-fit: contain;
        inline-size: auto;
        margin-inline: auto;
    }
}

@media (max-width: 991.98px) {
    .sd-v2 { margin-block-start: 24px; }
    .sd-v2 .sd-section { margin-block-end: 32px; }
    .sd-v2--band { padding-block-start: 28px; }
}

@media (max-width: 575.98px) {
    .sd-v2 .sd-section__title { font-size: 21px; letter-spacing: .011em; line-height: 1.1904761905; }
    .sd-v2 .sd-section__hint { font-size: 13px; margin-block-end: 14px; }

    .sd-v2 .sd-card { min-block-size: 70px; padding: 12px 8px; }
    .sd-v2 .sd-card.is-selected { padding: 11px 7px; }
    .sd-v2 .sd-card__label { font-size: 15px; }
    .sd-v2 .sd-monthly { font-size: 15px; }
    .sd-v2 .sd-monthly small { display: block; }

    /* Three tappable columns read better than three full-width rows, and keeps the
       monthly values comparable at a glance. */
    .sd-v2 .sd-cards--3 { gap: 7px; }
    .sd-v2 .sd-pill { display: block; margin: 3px 0 0; }

    .sd-v2 .sd-mode-tabs { inline-size: 100%; }
    .sd-v2 .sd-mode-tab { flex: 1; padding-inline: 10px; }

    .sd-v2 .sd-tradein { padding: 18px; }
    .sd-v2 .sd-tradein__head { flex-direction: column; align-items: stretch; gap: 14px; }
    .sd-v2 .sd-tradein__head .sd-btn { inline-size: 100%; }

    .sd-v2 .sd-summary { padding: 22px 18px; }
    .sd-v2 .sd-summary__box { padding: 22px 20px 20px; }
    .sd-v2 .sd-summary__headline { font-size: 24px; letter-spacing: .009em; }
    .sd-v2 .sd-summary__subheadline { font-size: 15px; }

    /* The figure scales with the box, and its slot with it - a 104px floor around a 36px number is
       dead space at this width. */
    .sd-v2 .sd-summary__price-amount { font-size: 36px; letter-spacing: -.019em; }
    .sd-v2 .sd-summary__figure { min-block-size: 92px; }

    .sd-stickybar__header .sd-stickybar__container { padding-block: 9px; gap: 12px; }
    .sd-stickybar__platter { padding-block: 6px; gap: 6px; }
    .sd-stickybar__cell { padding: 3px 10px; font-size: 11px; }
    .sd-stickybar__title { font-size: 14px; }
    .sd-stickybar__price { font-size: 12px; }
    .sd-stickybar .sd-btn { padding: 7px 14px; font-size: 13px; }

    .sd-v2 .sd-tradeup__title { font-size: 21px; letter-spacing: .011em; }
    .sd-v2 .sd-tradeup__drawer { padding: 16px; }
}

@media (max-width: 359.98px) {
    .sd-v2 .sd-cards--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* =============================================================================
   Storage + colour selectors  (LEGACY MARKUP, restyled in place)
   -----------------------------------------------------------------------------
   These chips are rendered by detail.cshtml and driven by detail.js
   (.gb.storage[data-value], #relatedItemColor .phone-color-box, the out-of-stock
   SVG cross, the "n/a" hiding). None of that is touched - this is presentation
   only, scoped to #buy_device so it cannot leak to the shop or home pages.

   Follows Apple's capacity picker: full-width stacked ROWS, label on the start
   edge, price/meta on the end edge (their .rf-po-bfe-...-right-rail variant uses
   flex-flow:row wrap + justify-content:space-between), 12px radius, 1px #86868b
   border, and the 2px-border / -1px-padding compensation when selected.
   ============================================================================= */

/* =============================================================================
   Sticky gallery
   -----------------------------------------------------------------------------
   Apple's buy page pins the product image while the configuration column beside
   it scrolls, then lets the whole page move on once that column runs out.

   No JS and no end coordinate needed: a sticky element is bounded by its
   containing block, which here is its own .col-lg-6. Bootstrap's .row is a flex
   container with align-items: stretch, so that column is as tall as the taller
   one beside it - the configuration column - and the image therefore releases
   precisely when the configuration runs out.

   Two things this depends on, both true today, but worth knowing if the gallery
   ever stops sticking:
     - no ancestor between .row and .gallery-image may set overflow to anything
       but visible; any value creates a new scroll container and sticky silently
       dies against it
     - .row must keep align-items: stretch, or the column collapses to the height
       of the image and there is nowhere left to travel
   ============================================================================= */

@media (min-width: 992px) {
    #buy_device .gallery-image {
        position: sticky;
        /* Parks under whatever is pinned at the top. --sd-pinned-top is the live height of the
           site header, or of the product bar once it has taken over. (--sd-summary-top was the old
           name from when the summary was a sticky rail; that rail is gone.) */
        inset-block-start: calc(var(--sd-pinned-top, 72px) + 16px);
    }
}

/* Colour above capacity.
   Reordered in CSS rather than in the markup: detail.cshtml renders the capacity chips first and
   detail.js binds both groups plus the "select the first available storage" bootstrap in that DOM
   order. Flipping the source would risk that; `order` changes only what the eye sees. */
#buy_device .deviceRelatedItemsContainer {
    display: flex;
    flex-direction: column;
}

#buy_device .deviceRelatedItemsContainer > #relatedItemColor { order: 1; }
#buy_device .deviceRelatedItemsContainer > .choose_right { order: 2; }

#buy_device .deviceRelatedItemsContainer {
    --sd-ink: #1d1d1f;
    --sd-ink-2: #6e6e73;
    --sd-ink-3: #86868b;
    --sd-line: #d2d2d7;
    --sd-blue: #0071e3;
    --sd-ease: cubic-bezier(.4, 0, .6, 1);
    font-family: "SF Pro Text", "SF Pro Display", -apple-system, BlinkMacSystemFont,
                 "Helvetica Neue", Helvetica, Arial, sans-serif;
}

#buy_device .deviceRelatedItemsContainer .choose_text_title {
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: var(--sd-ink);
    margin-block-end: 12px;
}

/* ---- capacity rows ---- */

/* The "demo details" marker that used to render here was removed per request. The
   .sd-mock-details class is still applied by detail-configurator.js, so the marker can be
   reinstated by restoring a ::after rule on this selector. */

/* Two capacities per row. minmax(0, 1fr) rather than 1fr so a long price line shrinks the tile
   instead of blowing the track out past the grid. */
/* One capacity per row: each row carries a label AND a "From $X/mo." figure, which two
   columns cramped. Full-width rows also match Apple's capacity picker. */
#buy_device .deviceRelatedItemsContainer .gbs {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
    /* Capacity is the last thing in this container, so this is the gap before the price block.
       Trimmed from 28px now the empty .div_btns that used to sit between them is gone. */
    margin-block-end: 4px;
}

/* Grid rather than flex: with three price lines on the end edge, flex children refuse to shrink
   below their content and the row overflows its card. minmax(0, …) lets both columns actually
   give way, so long capacity labels and long price lines both stay inside the border. */
#buy_device .deviceRelatedItemsContainer .gb.storage {
    position: relative;
    display: grid;
    /* Capacity on the start edge, the price stack on the end edge. minmax(0, …) on both tracks is
       what keeps them inside the tile at two-per-row: neither column can refuse to shrink. */
    grid-template-columns: minmax(0, auto) minmax(0, 1fr);
    /* BOTH are needed: align-items centres each cell inside its row, align-content centres the row
       block itself inside the tile. Without the second, the row sits at the top of the min-height
       box and all the slack lands at the bottom - which is what made the top padding look smaller. */
    align-items: center;
    align-content: center;
    column-gap: 12px;
    row-gap: 4px;
    inline-size: 100%;
    /* Three price lines (plus the demo marker) stack in the end column, so the tile needs real
       vertical room - the old 18px/0-min-height box cropped them. */
    min-block-size: 104px;
    margin: 0;
    padding: 20px 22px;
    border: 1px solid var(--sd-ink-3);
    border-radius: 12px;
    background: #fff;
    color: var(--sd-ink);
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    text-align: start;
    cursor: pointer;
    transition: border-color .18s var(--sd-ease);
}

#buy_device .deviceRelatedItemsContainer .gb.storage:hover:not(.out-of-stock) {
    border-color: var(--sd-ink);
}

#buy_device .deviceRelatedItemsContainer .gb.storage.selected {
    border-width: 2px;
    border-color: var(--sd-blue);
    padding: 19px 21px;   /* compensates the extra border - the row never shifts */
}

#buy_device .deviceRelatedItemsContainer .gb.storage.out-of-stock {
    background: #00000003;
    border-color: #86868b6b;
    color: var(--sd-ink-2);
    cursor: not-allowed;
}

/* Capacity on top, the price stack beneath it - Apple's capacity tile. */
#buy_device .deviceRelatedItemsContainer .gb.storage .sd-storage__label {
    grid-column: 1;
    min-inline-size: 0;
    max-inline-size: 100%;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.022em;
    line-height: 1.2353641176;
    color: inherit;
    overflow-wrap: break-word;
}

/* Price lines stacked on the END edge, right-aligned against the capacity label. */
#buy_device .deviceRelatedItemsContainer .gb.storage .sd-storage__meta {
    grid-column: 2;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    min-inline-size: 0;
    max-inline-size: 100%;
    gap: 3px;
    font-size: 13px;
    font-weight: 400;
    letter-spacing: -.016em;
    line-height: 1.4285914286;
    color: var(--sd-ink-2);
    text-align: end;
}

/* Deliberately NOT nowrap: "Lease from $43.64/mo. for 24 mo." cannot fit one line on a narrow
   card, and forcing it to try is what pushed the text outside the border. Wrapping is the
   graceful failure; the balance hint keeps a two-line wrap from leaving one orphan word. */
#buy_device .deviceRelatedItemsContainer .gb.storage .sd-storage__price {
    max-inline-size: 100%;
    overflow-wrap: break-word;
    text-wrap: balance;
}

/* The buy price leads, so it carries the weight; the financing lines sit quieter beneath it. */
#buy_device .deviceRelatedItemsContainer .gb.storage .sd-storage__price:first-child {
    font-weight: 600;
    color: var(--sd-ink);
}

#buy_device .deviceRelatedItemsContainer .gb.storage.selected .sd-storage__meta { color: var(--sd-ink); }

/* The "demo pricing" marker that used to render here was removed per request. The
   data-sd-mock attribute is still set by detail-configurator.js, so a marker can be
   reinstated by restoring a ::after rule on this selector if it is ever wanted again. */

/* Two tiles per row stop fitting once the column gets narrow - drop to one. */
@media (max-width: 600px) {
    #buy_device .deviceRelatedItemsContainer .gbs {
        grid-template-columns: minmax(0, 1fr);
    }

    #buy_device .deviceRelatedItemsContainer .gb.storage { padding: 16px 18px; }
    #buy_device .deviceRelatedItemsContainer .gb.storage.selected { padding: 15px 17px; }
}

/* The legacy out-of-stock cross is a full-bleed SVG; Apple just dims the row instead. */
#buy_device .deviceRelatedItemsContainer .gb.storage .cross-overlay { display: none; }

/* A grid item now, so it is pinned across both columns instead of landing in whichever cell
   happens to be free and squeezing the price stack. */
#buy_device .deviceRelatedItemsContainer .gb.storage.out-of-stock::after {
    grid-column: 1 / -1;
    content: attr(data-oos-label);
    font-size: 12px;
    font-weight: 400;
    letter-spacing: -.01em;
    color: var(--sd-ink-2);
}

/* ---- colour swatches ---- */

#buy_device #relatedItemColor { margin-block-end: 28px; }

/* The selected swatch's ring is drawn OUTSIDE its 28px box (0 0 0 4px). With no room around the
   swatch the first one's ring sat flush against the list edge and read as clipped.
   The room is given to each <li> rather than to the <ul>: padding on the list plus a negative
   margin to cancel it just moves the problem, because the overhang then lands outside the list
   box where an ancestor's overflow can still clip it. Inside an li nothing can clip it.
   gap drops 12px -> 4px so the spacing between swatches is unchanged: 4 (li) + 4 (gap) + 4 (li). */
#buy_device #relatedItemColor ul {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin: 0;
    padding: 0;
    list-style: none;
}

#buy_device #relatedItemColor ul li {
    display: flex;
    padding: 4px;
    margin: 0;
}

/* custom-rtl.css sets `.phone-color-box { margin-left: 10px }` unscoped, which indents the first
   swatch and knocks the whole row out of line with the capacity tiles above. Spacing here comes
   from the list gap, so the margin is zeroed. (Its `margin-right: unset !important` resolves to 0
   anyway, so nothing is being fought over.) */
#buy_device #relatedItemColor .phone-color-box {
    display: block;
    margin: 0;
    inline-size: 28px;
    block-size: 28px;
    border-radius: 50%;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12);
    cursor: pointer;
    transition: box-shadow .18s var(--sd-ease), transform .18s var(--sd-ease);
}

#buy_device #relatedItemColor .phone-color-box:hover { transform: scale(1.06); }

/* Apple rings the selected swatch rather than outlining it - 2px gap, then the blue ring. */
#buy_device #relatedItemColor .phone-color-box.selected {
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12),
                0 0 0 2px #fff,
                0 0 0 4px var(--sd-blue);
}

/* A colour with no purchasable capacity. This used to be inline styling applied by the JS that built
   the swatches; they are server-rendered now, so the rule has to live here or a sold-out colour is
   indistinguishable from an available one.

   A struck-through circle rather than the capacity tiles' cross-overlay svg: at 28px a two-line cross
   reads as noise, and one diagonal is unmistakable. */
#buy_device #relatedItemColor .phone-color-box.disabled {
    position: relative;
    opacity: .4;
    cursor: not-allowed;
}

#buy_device #relatedItemColor .phone-color-box.disabled:hover { transform: none; }

#buy_device #relatedItemColor .phone-color-box.disabled::after {
    content: "";
    position: absolute;
    inset-inline-start: -2px;
    inset-inline-end: -2px;
    inset-block-start: 50%;
    block-size: 2px;
    background: #d0021b;
    border-radius: 2px;
    transform: rotate(-45deg);
    transform-origin: center;
}

@media (max-width: 575.98px) {
    /* Stacked at this width, so the tile grows to its content instead of holding a floor height. */
    #buy_device .deviceRelatedItemsContainer .gb.storage {
        padding: 16px 16px;
        font-size: 15px;
        min-block-size: 0;
    }
    #buy_device .deviceRelatedItemsContainer .gb.storage.selected { padding: 15px 15px; }
    #buy_device .deviceRelatedItemsContainer .gbs { gap: 8px; margin-block-end: 22px; }
}

/* =============================================================================
   Scroll reveal
   Applied by detail-configurator.js adding .is-revealed. Fails OPEN: the class is
   added immediately when IntersectionObserver is missing or the user asked for
   reduced motion, so content is never left invisible.
   ============================================================================= */

.sd-v2 [data-sd-reveal] {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity .6s var(--sd-ease), transform .6s var(--sd-ease);
    will-change: opacity, transform;
}

.sd-v2 [data-sd-reveal].is-revealed { opacity: 1; transform: none; }

/* Stagger children so a section assembles rather than snapping in. */
.sd-v2 [data-sd-reveal] .sd-card,
.sd-v2 [data-sd-reveal] .sd-summary__box > * {
    opacity: 0;
    transform: translateY(10px);
    transition: opacity .45s var(--sd-ease), transform .45s var(--sd-ease);
}

.sd-v2 [data-sd-reveal].is-revealed .sd-card,
.sd-v2 [data-sd-reveal].is-revealed .sd-summary__box > * { opacity: 1; transform: none; }

.sd-v2 [data-sd-reveal].is-revealed .sd-card:nth-child(1) { transition-delay: .06s; }
.sd-v2 [data-sd-reveal].is-revealed .sd-card:nth-child(2) { transition-delay: .12s; }
.sd-v2 [data-sd-reveal].is-revealed .sd-card:nth-child(3) { transition-delay: .18s; }
.sd-v2 [data-sd-reveal].is-revealed .sd-card:nth-child(4) { transition-delay: .24s; }

.sd-v2 [data-sd-reveal].is-revealed .sd-summary__box > *:nth-child(2) { transition-delay: .05s; }
.sd-v2 [data-sd-reveal].is-revealed .sd-summary__box > *:nth-child(3) { transition-delay: .10s; }
.sd-v2 [data-sd-reveal].is-revealed .sd-summary__box > *:nth-child(4) { transition-delay: .15s; }
.sd-v2 [data-sd-reveal].is-revealed .sd-summary__box > *:nth-child(5) { transition-delay: .20s; }


/* Motion is decoration here, never the only way to see content. */
@media (prefers-reduced-motion: reduce) {
    .sd-v2 [data-sd-reveal],
    .sd-v2 [data-sd-reveal] .sd-card,
    .sd-v2 [data-sd-reveal] .sd-summary__box > * {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
    .sd-stickybar__content { transition: none !important; }
    .sd-v2 .sd-summary__hero-img { transition: none !important; }
    .sd-v2 .sd-summary__hero-img.is-swapping { opacity: 1 !important; }
}

/* ---- utility ------------------------------------------------------------- */

.sd-v2 [hidden], .sd-stickybar [hidden] { display: none !important; }

.sd-v2 .is-busy { position: relative; pointer-events: none; opacity: .5; }

.sd-sr {
    position: absolute;
    inline-size: 1px; block-size: 1px;
    padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

@media (max-width: 767.98px) {
    .sd-v2 .sd-summary { grid-template-columns: minmax(0, 1fr); gap: 26px; padding: 26px 20px; }
    .sd-v2 .sd-summary__hero-img { max-block-size: 190px; }

    /* The floor stops the fact rows and the CTA jumping when the figure resolves. Keep it - but
       only as much of it as the smaller figure actually needs. */
    .sd-v2 .sd-summary__figure { min-block-size: 84px; margin-block-start: 16px; }
}

/* ---- step cascade ----------------------------------------------------------
   Colour -> capacity -> condition -> trade-in -> payment. Each step is inert
   until the one above it has been chosen; detail-configurator.js owns which.

   Deliberately NOT scoped under .sd-v2: the colour and capacity blocks are
   legacy markup living outside that wrapper, so every custom property used
   here carries a literal fallback. The .sd-section steps get .is-locked as
   well and keep the payment gate's existing treatment.
   -------------------------------------------------------------------------- */

[data-sd-step].is-step-locked {
    pointer-events: none;
    user-select: none;
}

/* Grey the CONTROLS, not the heading. A greyed-out title reads as "this section
   is broken"; a greyed-out control set reads as "not yet". */
[data-sd-step].is-step-locked .gbs,
[data-sd-step].is-step-locked > ul,
[data-sd-step].is-step-locked .sd-tradeup__row,
[data-sd-step].is-step-locked .sd-tradeup__module,
[data-sd-step].is-step-locked .sd-methods {
    opacity: .4;
    filter: grayscale(1);
    transition: opacity .25s var(--sd-ease, ease), filter .25s var(--sd-ease, ease);
}

/* The hint under a locked step - the same padlock chip .sd-section__locked uses,
   restated so it stands up outside .sd-v2. Only ever visible while locked. */
.sd-step__hint { display: none; }

[data-sd-step].is-step-locked > .sd-step__hint {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 0 0 12px;
    padding: 8px 14px;
    border-radius: var(--sd-radius-tile, 12px);
    background: var(--sd-surface-2, #f5f5f7);
    color: var(--sd-ink-2, #6e6e73);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -.016em;
}

[data-sd-step].is-step-locked > .sd-step__hint::before {
    content: "";
    flex: none;
    inline-size: 14px;
    block-size: 14px;
    /* padlock, inlined so it needs no asset */
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17 10h-1V7a4 4 0 1 0-8 0v3H7a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2zm-7-3a2 2 0 1 1 4 0v3h-4V7z'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17 10h-1V7a4 4 0 1 0-8 0v3H7a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2zm-7-3a2 2 0 1 1 4 0v3h-4V7z'/%3E%3C/svg%3E") center / contain no-repeat;
}
