/* =============================================================================
   Ring builder — mobile redesign
   Figma: "[Mobile UI] PDP ring builder refresh"  (file Ex10uQ9OY3OuzSPi4g2hPb,
   section 14463:32244, 25 frames authored at 390px).

   WHY THIS IS A SEPARATE FILE, LOADED AFTER simple-select.css
   ----------------------------------------------------------
   simple-select.js carries 214 distinct selector strings and several pieces of
   logic that read the DOM rather than a state object -- the engraving value is
   gated on `$('.ssq_eng_field').css('display') != "none"`, the setting price is
   scraped from the Affirm tag's data-amount, the progress bar maps step NAMES to
   step NUMBERS by DOM index, and the default stone is `.eq(0)` "because PHP
   prints it first". Rewriting simple-select.css in place would make every one of
   those a silent regression risk with no visual tell.

   That is exactly how the FedEx bug shipped (PR #276): a checkout redesign
   dropped ten hidden inputs with no visual role, `update_checkout_fedex_shipping()`
   was gated on one of them being in $_POST, and every counter-pickup order
   quietly became a home delivery for six weeks. Nothing errored.

   So: this file only ever ADDS declarations, scoped to mobile. Desktop is
   untouched by construction, and a rollback is deleting one enqueue line.

   EVERY VALUE HERE COMES FROM THE FIGMA REST API. Nothing is eyeballed or
   rounded -- letter-spacing really is -0.20999999344348907px in the source, and
   is written here as -0.21px.
   ============================================================================= */

@media (max-width: 991px) {

  /* ---------------------------------------------------------------------------
     1. TOKENS
     Counts below are node-level occurrences across the 25 frames, excluding
     hidden layers. They are kept as a record of why each value earned a token.
     --------------------------------------------------------------------------- */
  body.ringbuilder-product #simple-select-quiz,
  #simple-select-quiz {

    /* --- colour ------------------------------------------------------------ */
    --rb-text-primary:      #0F0E0D;   /* 911 uses, all 25 screens */
    --rb-text-secondary:    #3E3C39;   /* 475 -- body copy, meta, spec labels   */
    --rb-border-subtle:     #E4DED8;   /* 566 -- hairlines, unselected chips    */
    --rb-surface-card:      #FFFFFF;   /* 422 -- cards, drawers, sheets         */
    --rb-surface-page:      #FAF3ED;   /* 397 -- page ground; also text-on-green */
    --rb-surface-raised:    #FCF8F7;   /* 7   -- grouped block tint             */
    --rb-surface-input:     #FDFAF8;   /* 2   -- engraving textarea             */
    --rb-brand-green:       #27423B;   /* 323 -- primary CTA, selected border   */
    --rb-brand-sage:        #D8DDCA;   /* 52  -- selected chip fill, promo card */
    --rb-brand-sage-strong: #C2CEB2;   /* 15  -- selected carat button          */
    --rb-grey-disabled:     #D0D0D0;   /* 71  -- inactive dots, disabled icons  */
    --rb-accent-heart:      #C65858;   /* 26  -- favourite icon                 */
    --rb-badge-sale:        #FF0B39;   /* 23  -- sale badge ground              */
    --rb-ink-navy:          #142037;   /* 7   -- info icon ground               */
    --rb-accent-gold:       #C69858;   /* 6   -- decorative vector stroke       */

    /* metal swatch dots -- exact values, these read as product data */
    --rb-metal-yellow-gold: #DCB84E;
    --rb-metal-rose-gold:   #E9C1B1;
    --rb-metal-platinum:    #B9B9B9;
    --rb-metal-white-gold:  #A3A3A3;

    /* the only shadow colour in the entire board */
    --rb-shadow-base: rgba(0, 0, 0, 0.25);

    /* the single gradient, used 3x */
    --rb-gradient-shimmer: linear-gradient(90deg, #E4DED8 0%, #FFFAF5 52%, #E4DED8 100%);

    /* --- type -------------------------------------------------------------- */
    /* Three families only. Founders Grotesk 400/500 (1,346 nodes), Canela 300
       display (137), SF Pro Text (status-bar chrome only -- NOT reproduced,
       that is the phone mockup, not our UI). */
    --rb-font-body:    'FoundersGrotesk', sans-serif;
    --rb-font-display: 'Canela', serif;

    /* Letter-spacing is one of two values almost everywhere. */
    --rb-ls-tight:  -0.21px;   /* the -0.20999999344348907px the API returns */
    --rb-ls-wide:   -0.5px;

    /* --- radii ------------------------------------------------------------- */
    --rb-radius-sm:   4px;     /* 770 uses -- the default for nearly everything */
    --rb-radius-md:   8px;
    --rb-radius-lg:   10px;
    --rb-radius-xl:   24px;
    --rb-radius-pill: 100px;

    /* --- stroke ------------------------------------------------------------ */
    --rb-stroke:       1px;    /* 759 uses */
    --rb-stroke-thick: 2px;
  }

}

/* =============================================================================
   FULL-SCREEN BUILDER  --  applies at EVERY width, so deliberately outside the
   max-width:991px block below.

   The builder is a full-screen flow on both phone and desktop: no promo bar and
   no site navigation. simple-select.js already hides the PDP's own sections
   (js:643-645) but leaves the site header and the notification bar up.

   body.rb_quiz_open is set by simple-select-redesign.js from the quiz's real
   visibility, so it covers every entry point (button, ?ssq deep link, the
   affordable-ER path) and clears on close without needing to know about any of
   them.

   visibility:hidden + zero height rather than display:none, on purpose:
   main.js and sidecart.js measure the header (its height feeds the sidecart's
   top offset), and display:none would report 0 and shift the drawer. This keeps
   the box measurable while taking it out of view.
   ============================================================================= */
/* `.da-promo` is the live promo bar (header-promo.php) and the one the customer
   actually sees: 1728 x 43 welded to the top of the page, still fully visible
   with body.rb_quiz_open set, because this list only ever named
   `.site-wide-notification` -- a bar this theme no longer renders on the PDP.
   Measured at 1728 before this: div.da-promo at 0,0 1728x43, visibility
   `visible`, while body.rb_quiz_open WAS present. The class was right, the
   selector was wrong. */
body.rb_quiz_open .da-promo,
body.rb_quiz_open .site-wide-notification,
body.rb_quiz_open header#masthead {
    visibility: hidden !important;
    height: 0 !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    overflow: hidden !important;
}

/* ...and the gap the collapsed chrome leaves behind.  Hiding the bars is not
   enough on its own: product-single.css:1 / :577 pad the PDP's content area
   down off them -- `.single-product .content-area { padding-top: 14px }`, 36px
   from 992 up -- so with the bars gone that padding is just a band of empty
   page the exact height the promo bar used to be, sitting above the builder.
   Measured on dev-0 with the bars already hidden: the quiz started at y36 at
   1728 and y14 at 390.

   Gated on rb_quiz_open, so the PDP keeps its own spacing everywhere else --
   this is the builder taking the full view, not a change to the product page.
   The selector is one class weaker than the source's, hence !important. */
body.rb_quiz_open #primary.content-area,
body.rb_quiz_open .single-product .content-area {
    padding-top: 0 !important;
}

/* the header is sticky/fixed on some breakpoints -- make sure the collapsed box
   cannot keep reserving space or intercept taps once it is hidden */
body.rb_quiz_open header#masthead {
    position: absolute !important;
    top: 0;
    left: 0;
    right: 0;
    pointer-events: none;
}

/* the quiz sits under the header's offset on the PDP; with the header gone it
   starts at the top of the viewport */
body.rb_quiz_open section#simple-select-quiz {
    margin-top: 0 !important;
    padding-top: 0 !important;
}

/* ---- first step has no "back" ------------------------------------------------
   Stone is step 1 and the entry point, so there is nowhere to go back to. The
   close control remains, which is the way out of the flow.
   `.rb_at_first` is set on the quiz root by the redesign JS.
   Not display:none -- the element is a real <button> the JS binds to, and
   collapsing it keeps the header's three-column balance intact. */
section#simple-select-quiz.rb_at_first .rb_back {
    visibility: hidden !important;
    pointer-events: none;
}

/* =============================================================================
   THE RING SECTION ALWAYS SHOWS THE RING

   `.quiz-left .quiz-image-conatiner` is the ring section. It holds two boxes:
   `.quiz-image` (the ring preview + its metal/shape pills) and, right under it,
   a second `.quiz-handpicked-image` -- a big STONE photo with its own
   image/video thumb strip.

   simple-select.js swaps one for the other the moment a handpicked stone is
   confirmed. js:1567-1570, the DESKTOP half of that branch:

       } else {                                  // desktop
           $('.quiz-handpicked-image').show();   // stone photo in
           $('.quiz-image').hide();              // ring section out
           $('.desktop-stone-details').hide();
       }

   That block is inside the `ssqChange` handler (js:1437), so it re-fires on
   EVERY step change while a handpicked stone is held -- picking the stone,
   walking to Size, and walking back to Stone each run it again. The customer
   comes back to Stone and finds stone info sitting where the ring belongs.
   diamond-search.js:2725-2726 and :2825-2826 do the same swap from the search
   preview, and js:1985-1986 does it again on popstate.

   WHY CSS AND NOT A JS RE-ASSERT
   ------------------------------
   A re-assert in simple-select-redesign.js would have to win a race it cannot
   reliably win. Only the `ssqChange` half is ordered (our handler is bound
   after the legacy one, so it runs after it); the other three writers are a
   popstate listener, a `.browse_more` click handler and a diamond-search click
   handler, none of which fire `ssqChange` afterwards. We would be chasing four
   call sites, re-hiding an element the legacy had just shown -- one repaint of
   visible flicker every time -- and any fifth call site added later would
   silently reopen the bug with no visual tell until a customer hit it.

   A stylesheet `!important` has no ordering, no race and no flicker: jQuery's
   `.show()` writes `style="display: block"`, and an author `!important`
   declaration outranks a non-important inline one, so the rule holds no matter
   how many times or from where the legacy runs. This is the same technique
   redesign/_stone-desktop.css:492 already uses to keep `.quiz-image` itself
   open against js:1569's inline `display:none`, and the same one the file
   header describes for `.ssq_all_stone_options` and `.simple-quiz-carat-filter`.

   display:none is allowed on THIS element specifically. Nothing in the legacy
   reads its display or its geometry: every live reference is a write --
   js:1578-1579 set the img/iframe `src`, js:2403-2419 toggle its children, and
   the one geometry read that ever existed (js:2414-2415, clientWidth from
   `> img:visible`) is commented out. The node stays in the DOM, so all of those
   writes keep landing.

   SCOPE -- the stone photo still has a home. The markup prints
   `.quiz-handpicked-image` TWICE: this one, and a second copy inside
   `.ssq_picked_selection` in the options column (simple-select-quiz.php:419).
   That second copy is the stone-confirmation card, where the stone photo is the
   subject and is correct; it is not inside `.quiz-left`, so this rule never
   touches it. `.quiz-left .quiz-handpicked-image` is the exact scoping
   simple-select.js:1563 itself uses for its mobile branch -- the mobile half is
   already correct, and this rule makes the desktop half behave the same way at
   every width, which also covers the width-blind `.show()` at js:1986.
   ============================================================================= */
#simple-select-quiz .quiz-left .quiz-handpicked-image {
    display: none !important;
}

/* The other half of the same swap: diamond-search.js:2725 and :2825 hide the
   ring panel itself (`$('.sss-metal-image').hide()`) so the stone photo above
   can take its place in the ring section. With the photo gone that would leave
   an empty ring section, so the panel is pinned open too.

   Those two are the ONLY hide sites for `.sss-metal-image` in either legacy
   file (js:1666 and :1929 only ever show it again), so pinning costs nothing
   anywhere else. `display:block` is the value it already computes to at both
   widths -- `.ssq-grid` (js:1467) only sets grid-template-columns; its
   `display: grid` is commented out in simple-select.css:1035-1039.

   Scoped inside `.quiz-image` on purpose: `.sss-metal-image` is also a class on
   the review-step confirmation card (simple-select-quiz.php:158), which the
   legacy legitimately hides and which is NOT inside `.quiz-image`. */
#simple-select-quiz .quiz-left .quiz-image .sss-metal-image {
    display: block !important;
}

/* AND THE OTHER HALF OF `.ssq-grid`, WHICH THIS FILE HAD ONLY HALF-ANSWERED.
   simple-select.js:1903 puts `.ssq-grid` on `.sss-metal-image` for the STONE
   step, and simple-select.css:1043 shrinks the photo to `width/height: 85%`
   for it -- the legacy two-up layout, where the spare 15% made room for
   `.desktop-stone-details` beside the ring. The redesign zero-boxes that panel
   (next section), so the 15% is given up for nothing.

   ONLY VISIBLE AFTER A POPSTATE, which is why it lasted. The server prints the
   plain stone step and the class is only added by the slide-change handler, so
   a fresh quiz never has it; browser Back out of the advanced search fires that
   handler and it arrives. MEASURED at 1728, opening the search and pressing
   Back with no stone chosen: the ring photo went 604 x 503 -> 513 x 428 inside
   an unchanged 764 x 503 frame, i.e. it shrank and sat in white space.

   The base is `.sss-metal-image img { width: 100%; height: 100% }`
   (simple-select.css:25) resolved against the 604 x 503 crop, so restoring the
   pair is the whole fix -- `.ssq-grid`'s `grid-template-columns` is already
   inert (its `display: grid` is commented out at simple-select.css:1035). */
#simple-select-quiz .quiz-left .quiz-image .sss-metal-image.ssq-grid > .sss-image-crop > img {
    width: 100%;
    height: 100%;
}

/* =============================================================================
   RING SLOT, PILLS AND LABELS  --  both breakpoints, so outside the media block.
   ============================================================================= */

/* ---- 1. the ring slot holds the RING, nothing else -------------------------
   `.desktop-stone-details` is a SIBLING of `.sss-image-crop` INSIDE
   `.sss-metal-image` (simple-select-quiz.php:133-143), so when
   simple-select.js:1469 / :1927 calls .show() on it the whole "Stone Details /
   Cut / Color / Clarity / Certificate / Polish / Fluorescence / Carat Weight"
   block renders directly under the ring image -- and returning to Stone leaves it
   there. `.quiz-handpicked-image` is the same problem with the loose-stone photo.

   Zero-boxed rather than display:none, deliberately: simple-select.js toggles
   both with .show()/.hide() and reads them back, and js:1470 writes the details
   HTML into `.desktop_simple_details_content`. display:none would make
   :visible tests answer false and change behaviour; this only stops them
   painting and taking space. */
#simple-select-quiz .quiz-image .sss-metal-image > .desktop-stone-details,
#simple-select-quiz .quiz-image > .quiz-handpicked-image {
    visibility: hidden !important;
    height: 0 !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    overflow: hidden !important;
    pointer-events: none;
}

/* ---- 2. the metal / shape label is not bold -------------------------------
   simple-select.css:662-663 sets `.select_metal_shape span { font-weight: bold }`.
   It only bites AFTER a selection, because js:859 / :869 re-render the pill label
   as `$('.metal_current_option').html(selected_metal_html + dropdown_icon)` and
   that generated markup wraps the name in a <span> the original markup did not
   have. So the pill looked right until you picked something, then went bold. */
#simple-select-quiz .select_metal_shape span,
#simple-select-quiz .select_metal_shape .metal_current_option span,
#simple-select-quiz .select_metal_shape .shape_current_option span {
    font-weight: 400;
}

/* ---- 3. the whole pill is the click target --------------------------------
   The handler is delegated to `.select_metal_option` / `.select_shape_option`
   (simple-select.js:979 and :1005), and in the closed pill that element is the
   label inside `.metal_current_option`. It only spanned its own text, so the
   rest of the 144x36 pill -- including the chevron and the padding -- did
   nothing when tapped. Stretch the current-option wrapper and its child to fill
   the pill so the entire control is live. */
#simple-select-quiz .quiz-image .metal_dropdown_ssq > .metal_current_option,
#simple-select-quiz .quiz-image .shape_dropdown_ssq > .shape_current_option {
    display: flex;
    align-items: center;
    width: 100%;
    height: 100%;
    cursor: pointer;
}
#simple-select-quiz .quiz-image .metal_dropdown_ssq > .metal_current_option > .select_metal_option,
#simple-select-quiz .quiz-image .shape_dropdown_ssq > .shape_current_option > .select_shape_option {
    display: flex;
    align-items: center;
    align-self: stretch;
    gap: 8px;
    flex: 1 1 auto;
    cursor: pointer;
}

/* Making the whole pill clickable is done in simple-select-redesign.js, not here.
   A stretched `::after` overlay was tried first and is the obvious CSS answer, but
   `inset: 0` resolves against the nearest POSITIONED ancestor, and the desktop sheet
   positions these elements differently -- the shape pill's overlay ended up covering
   the metal pill, measured as 0/9 hit points on the metal control at 1728. A
   delegated click that forwards to the pill's own option element is independent of
   which ancestor happens to be positioned at a given breakpoint. */

/* =============================================================================
   FULL SCROLL — 100px of clear space under everything in the builder
   -----------------------------------------------------------------------------
   Reported as "scrollability till end is not there". Measured, the last PAINTED
   element lands exactly on the viewport bottom at 1728x720, 1512x780, 1280x700,
   390x844 and 390x667 — so nothing is clipped, but the last row sits flush
   against the bottom edge with nothing under it, which reads as "it won't
   scroll any further" and leaves no room to scroll past on a trackpad.

   A tail of empty space below the content fixes that at every height without
   touching any layout above it: the page simply has 100px more to scroll
   through, and the final row clears the bottom edge.

   On padding rather than margin so it cannot collapse with a child's margin,
   and on the quiz root so it applies to every step — stone, size, engraving,
   review, and the advanced search panel inside it.

   The mobile sticky bar is position:fixed and so is not in this flow; the tail
   sits under the content it was covering, which is the point.
   ============================================================================= */
/* AND IT HAS TO CLEAR THE FIXED FOOTER, NOT JUST GIVE A TAIL.
   Owner: *"i cannot scroll towards end of any PDP in BYR flow ... i wanna be
   able to scroll to last of every PDP, which i currently cannot"*.

   `.ssq_bottom_nav` is `position: fixed` at z-index 99 and nothing in the
   document accounts for the band it covers. MEASURED at 1728x900 on the in-flow
   stone PDP: the nav is [0,780,1728,120], document scrollHeight 1022 against a
   900 viewport, so max scrollTop is 122 -- and at that scroll the left column's
   bottom edge sat at viewport y=800, i.e. 20px BELOW the nav's top. The photo
   thumbnail row was sliced in half and the last row of Details & Dimensions
   could not be brought into view at all.

   THIS IS THE RULE THAT DECIDES IT. `redesign/_stone-desktop.css:143` asks for
   163px and `redesign/_stone.css:66` for 129px -- both on a bare
   `#simple-select-quiz` (1,0,0), and both have been DEAD since this rule was
   written, because `section#simple-select-quiz` is (1,0,1) and outranks them at
   every width. The effective reserve has always been this flat 100, which is
   20px short of the desktop band. Fixed here rather than by !important-ing the
   partials, so there is still exactly one rule that decides the number.

   `--rb-nav-reserve` is written by simple-select-redesign.js from the nav's
   RENDERED height, and only while it is actually `position: fixed`. It is not a
   constant: 120 at >=992, 129 on the SIZE slide at <=991, and 0 on the slides
   `_stone.css:2029` collapses the bar on. +24 is the clearance between the last
   row of content and the band.

   `max()` keeps the original 100px trackpad tail as a floor -- see the note
   above, and it is what the states with no fixed bar keep. The 100px fallback
   inside the var() is the no-JS answer: unchanged from what shipped. */
/* ...AND THE CLEARANCE COMES DOWN 40%. Owner: *"the sticky button space -- in
   the bottom there's a lot of gap between the last button and the end of the
   screen. PDP RING BUILDER (mobile). Reduce the padding further by 40% -- rest
   is good! But check it can be responsive properly and does not cut off on some
   phones."*

   THE RESERVE IS NOT PADDING TO SPEND. MEASURED at 390 on both slides, the band
   is `position: fixed`, 129 tall, sitting on the viewport's bottom edge; the
   page's padding was 153 on SIZE and 137 on STONE. Take 40% off the whole 153
   and it becomes 92 -- less than the band -- and the last row of content
   disappears underneath it, which is the "cut off on some phones" the owner
   asked me to watch for. `--rb-nav-reserve` is that 129, measured live from the
   band's own rendered height by simple-select-redesign.js, and it is what keeps
   this responsive: 120 at >=992, 129 here, 0 where the bar is collapsed.

   So the 40% comes off the CLEARANCE, which is the only part that is empty
   space: 24 -> 14 here and 8 -> 5 on the stone slide, with the no-fixed-bar
   floor going 100 -> 60 by the same ratio. */
section#simple-select-quiz {
    padding-bottom: max(60px, calc(var(--rb-nav-reserve, 0px) + 14px));
}

/* Accordion body, per the customer's own rule. `display: none` is the closed
   state; whatever opens it sets display itself. */
.accordion-text {
    padding-left: 45px;
    padding-top: 15px;
    overflow: hidden;
    display: none;
}

/* =============================================================================
   THE FILTER RAIL MUST NOT CHAIN ITS SCROLL INTO THE OVERLAY BEHIND IT

   MEASURED on the results step, both breakpoints, the rail sits inside a second
   scroll box:
     390:   #ssq_diamond_search            fixed [0,0 390x900]    dy 16244
            └ .search_filters              fixed [0,900 390x900]  dy 438
     1728:  .ssq_diamond_search            fixed [0,0 1728x1000]  dy 10121
            └ .col-lg-3.search_filters_container  sticky [78,198 385x800] dy 370

   Both of those pairs are the DESIGN, not a defect to unpick. At 390 the inner
   box is the filter drawer, parked a full viewport BELOW the fold at y=900 --
   it is a DOM descendant of the overlay but never a visual one, and it only
   covers the overlay once it is opened. At 1728 `_advanced-search-desktop.css`
   :374 spells the intent out -- "the rail scrolls independently of the grid",
   because 14468:43528 draws the rail its OWN 6px scrollbar at x=457 -- and the
   rail is a `position: sticky` column inside the results scroller by
   construction. Flattening either pair would take the drawer's scroll away on
   mobile or unpin the rail on desktop, and desktop is finished work.

   What IS worth fixing is the only behaviour the nesting can actually be felt
   through: scroll chaining, where flicking past the end of the rail grabs the
   results list underneath and throws the customer's place away. `.search_filters`
   already had `overscroll-behavior: contain` at <=991 (_advanced-search.css:1759);
   the desktop container never got it. Added here for both.

   NOTE ON CASCADE: this sheet loads BEFORE the `redesign/_*.css` partials, so it
   cannot outrank them at equal specificity. It does not need to -- no partial
   declares `overscroll-behavior` on either of these two selectors, so there is
   nothing to outrank. If one ever does, it wins, and this block goes quiet
   rather than fighting it.
   ============================================================================= */
#ssq_diamond_search .col-lg-3.search_filters_container,
#ssq_diamond_search .search_filters {
    overscroll-behavior: contain;
}

/* =============================================================================
   PRIMARY CTA, LOCKED -- no stone chosen yet.

   The stone step used to open with Lab Diamond pre-selected (a `active` class
   printed by simple-select-quiz-stones.php plus an `.eq(0).trigger('click')` on
   every entry to the step). That was harmless while Stone was slide 3 and
   nobody landed on it; the Figma order makes Stone slide 1, so it read as "the
   builder opened with a stone already configured". Both defaults are gone.

   What that leaves is a live "Choose This Stone" button pointing at nothing:
   simple-select.js:1413 falls through to `.sss-next`, and
   set_stone_ssq_ringbuilder() bails at its own `.ssq-simple-selection.active`
   guard -- the shopper reaches Ring Size with no stone and Review prices one
   anyway. simple-select-redesign.js stamps this class until a row is picked.

   `pointer-events: none` rather than a `disabled` attribute because the node is
   an <a>, which has no disabled state, and because it stops the click before
   EITHER bound handler runs -- no bind-order question between the two sheets'
   JS. Colours are the existing disabled token, not a new one.
   ============================================================================= */
/* SPECIFICITY: this sheet loads BEFORE the `redesign/_*.css` partials, so at
   equal weight the partials win. `_stone.css` / `_stone-desktop.css` paint the
   CTA at `#simple-select-quiz .ssq_all_stone_confirmations .ssq_finalize_button`
   = (1,2,1); measured, a (1,1,1) rule here landed `pointer-events` but left the
   button full jade green. Matching their descendant chain and adding the state
   class takes it to (1,3,1), which wins without `!important`. */
#simple-select-quiz .ssq_all_stone_confirmations .ssq_finalize_button.rb_cta_locked {
    /* NOT `pointer-events: none`. An inert grey button with nothing on screen
       explaining it reads as a missing control -- reported as "no next button".
       It stays hittable; simple-select-redesign.js catches the click in the
       capture phase, blocks the step, and scrolls the stone cards into view. */
    cursor: pointer;
    background: var(--rb-grey-disabled, #D0D0D0);
    border-color: var(--rb-grey-disabled, #D0D0D0);
    color: #FFFFFF;
}

/* The arrow glyph `_stone.css` draws on the CTA is decorative; it should read as
   inert too rather than staying full-strength on a greyed button. */
#simple-select-quiz .ssq_all_stone_confirmations .ssq_finalize_button.rb_cta_locked::after {
    opacity: 0.6;
}


/* The flash the locked CTA puts on the first stone card, so the tap points
   somewhere instead of dying silently. Short, one card, no layout shift --
   outline rather than border, which would move everything below it. */
#simple-select-quiz .ssq-simple-selection.rb_needs_pick {
    outline: 2px solid var(--rb-brand-green, #27423B);
    outline-offset: 2px;
    transition: outline-color 200ms ease-out;
}
@media (prefers-reduced-motion: reduce) {
    #simple-select-quiz .ssq-simple-selection.rb_needs_pick { transition: none; }
}

/* =============================================================================
   THE BUILDER SLIDES IN FROM THE LEFT
   -----------------------------------------------------------------------------
   Owner: *"this change of, you know, on Build Your Ring CTA the whole thing
   slides from the left instead of just appearing -- that makes it look smooth
   too."*

   Keyed on the inline `display: block` simple-select.js writes when the CTA is
   pressed, because that IS the open state -- the section carries no open class
   and the body carries no marker either (MEASURED: `display: none` -> inline
   `display: block`, class unchanged at `rb_at_first`). The same
   `[style*="display: block"]` hook the metal and shape drawers in this build
   already hang off, so it is a pattern here rather than a new trick.

   NO `animation-fill-mode`, and that is the load-bearing detail. The quiz holds
   SIX `position: fixed` descendants -- the footer bar, the header band and the
   drawer sheets among them -- and a transform on an ancestor makes it their
   containing block. `both` would keep the final keyframe's `translateX(0)`
   forever, which is still a transform, and every one of those six would start
   positioning against the section instead of the viewport. With no fill the
   computed transform returns to `none` the instant the animation ends and they
   go back to behaving normally. During the 380ms they travel with the panel,
   which is what "the whole thing slides" means.
   ============================================================================= */
/* DIRECTION AND TIMING, to the owner's spec:
     in    from the RIGHT edge toward the left, 320ms cubic-bezier(.22,1,.36,1)
     out   back out to the RIGHT, 250ms ease-in -- closing a touch quicker
     reduced motion   no slide at all, a 150ms fade both ways
   The section was sliding in from the LEFT on an earlier pass; only the sign of
   the translate and the curve change here, the fill-mode reasoning above is
   untouched and still load-bearing. */
@keyframes rbQuizSlideIn {
    from { transform: translateX(100%); opacity: 0; }
    to   { transform: translateX(0);    opacity: 1; }
}
@keyframes rbQuizSlideOut {
    from { transform: translateX(0);    opacity: 1; }
    to   { transform: translateX(100%); opacity: 0; }
}
@keyframes rbQuizFadeIn  { from { opacity: 0; } to { opacity: 1; } }
@keyframes rbQuizFadeOut { from { opacity: 1; } to { opacity: 0; } }

#simple-select-quiz[style*="display: block"] {
    animation: rbQuizSlideIn 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
/* `both` is correct HERE and wrong on the way in -- see the fill-mode note
   above. On close the panel must HOLD its off-screen final frame for the whole
   250ms, or it would snap back to translateX(0) and sit there visible until the
   script hides it. The class is removed the moment the hide lands
   (simple-select-redesign.js, rbQuizCloseAnim), so the lingering transform
   never outlives the animation and the fixed descendants get their viewport
   containing block back. */
#simple-select-quiz.rb-quiz-closing[style*="display: block"] {
    animation: rbQuizSlideOut 250ms ease-in both;
}
@media (prefers-reduced-motion: reduce) {
    #simple-select-quiz[style*="display: block"] {
        animation: rbQuizFadeIn 150ms linear;
    }
    #simple-select-quiz.rb-quiz-closing[style*="display: block"] {
        animation: rbQuizFadeOut 150ms linear both;
    }
}


/* ===========================================================================
   RING DETAILS -- MEASURED COLLAPSE, AT EVERY BREAKPOINT
   ---------------------------------------------------------------------------
   Owner: *"ring details, the way it opens and closes is not smooth."*

   Both `.rb_details_bar` rules (mobile _stone.css, desktop _stone-desktop.css)
   animate `height: 40px/48px -> auto` and lean on `interpolate-size:
   allow-keywords` to make `auto` interpolable. That property is Chromium-only:
   in Safari -- which is what the report came from -- `auto` is not an
   animatable value, so the 260ms is skipped and the bar snaps open and shut.

   simple-select-redesign.js now measures the open height and drives the bar
   through it with an inline `height`, which every engine can interpolate. The
   CSS keyword path is left exactly as it was: where `interpolate-size` IS
   supported it is still what runs if the script has not loaded, and the inline
   value simply overrides it while a toggle is in flight.

   This class is set around the measuring reflow only. Measuring means reading
   the bar at `height: auto` with `.is-open` applied, and a forced style recalc
   in that state would start the chevron's 260ms rotate from the wrong end and
   let the panel's visibility transition fire. Nothing may animate while the
   tape measure is out.
   =========================================================================== */
#simple-select-quiz .rb_details_bar.rb-details-measuring,
#simple-select-quiz .rb_details_bar.rb-details-measuring * {
    transition: none !important;
    animation: none !important;
}
