/* =============================================================================
   Ring builder — mobile redesign — DRAWERS, POPUP and REVIEW
   Figma file Ex10uQ9OY3OuzSPi4g2hPb, section 14463:32244:

     14463:36461  [Drawer] Select Metal       390 x 1050  (sheet `Metal`      14463:36569, 390 x 805)
     14463:36719  [Drawer] Select Shape       390 x 1050  (sheet `Shape`      14463:36866, 390 x 805)
     14463:33997  [Drawer] Select Gemstone    390 x 1011  (sheet `gemstones`  14463:34189, 390 x 934)
     14463:32459  [POPUP] Talk to gemologist  390 x  855  (card `POPUP SHARE` 14463:32624, 390 x 549)
     REVIEW       -- NO FRAME ON EITHER BOARD.  See section 5.

   Loaded after simple-select.css and after simple-select-redesign.css (which
   defines the --rb-* tokens). Additive only, scoped to max-width:991px, so
   desktop is untouched by construction.

   COORDINATE NOTE. Every y in SPEC.md is measured inside a frame whose first
   46 px are the iPhone status-bar MOCKUP (`phone-ui`, SF Pro, black bar). That
   is phone chrome, not our UI, so every SPEC y quoted below has 46 subtracted;
   SPEC's own number is given in parentheses.

   THESE ARE BOTTOM SHEETS, NOT CENTRED MODALS (flows/OVERLAYS.md). Figma parks
   all three sheets at relY 1053, below the frame's bottom edge, and slides them
   up 809 px over a full-bleed `black mask`. Corner radii are
   rectangleCornerRadii [8, 8, 0, 0] on all three -- 8 px top, square bottom,
   flush to the viewport floor. None of the four has a drag handle: no pill,
   grabber or notch node exists above any sheet header, and swipe-to-dismiss is
   not modelled.

   SCRIM. flows/OVERLAYS.md finds four scrims at three opacities: 0.50 on the
   gemstone frame, 0.70 on Metal, Shape and the gemologist popup, and 0.50 on
   the parked masks whose FRAME opacity is 0 (inert -- they are the closed
   state, not a colour decision). Of the scrims that actually render, three of
   four are 0.70, so 0.70 is used everywhere.

   SPECIFICITY. _stone.css:459 already claims
   `#simple-select-quiz .quiz-image .shape_dropdown_ssq_options` (top / left /
   width / radius for the old 144px flyout). The metal and shape rules below
   match that selector exactly and win on load order -- da-general.php:4355
   enqueues _drawers after _stone -- rather than by adding !important
   (brief rule 4).

   THE OPEN-STATE HOOKS -- what the JS actually does, re-verified this pass:

     METAL / SHAPE -- NO STATE CLASS EXISTS. simple-select.js:985 and :1011
     toggle the container with jQuery .hide()/.show(), i.e. an INLINE `display`.
     Nothing below ever sets `display` on .metal_dropdown_ssq_options or
     .shape_dropdown_ssq_options; they are styled in place and jQuery keeps
     ownership of visibility. Setting `display` here would either pin them open
     or make .show() a no-op.

     GEMSTONE -- .popup-modal-container.gemstone_selection_modal, gated
     additionally on :has(.modal-gemstone-selection). Modal (assets/js/main.js
     :565) is a SINGLETON: gemstoneModal.addClass('gemstone_selection_modal')
     at simple-select.js:2583 is never undone (removeAllClasses() is not called
     on this path), so once the gemstone modal has opened once the class stays
     on the shared element for every later modal -- the video modal, the
     "Change of Heart?" modal, everything. .modal-gemstone-selection is the
     container simple-select.js:2491 writes into #modal-content, and Modal.close
     / handleOutsideClick both blank #modal-content, so :has() is true only
     while the gemstone list is really on screen.

     TALK TO A GEMOLOGIST -- the only counterpart is #contact_modal_popup
     (components/contact-modal). It too is driven by an inline `display`
     (assets/js/main.js:223 / :233), so no `display` is set on it either; the
     reachable hook is aria-expanded="true", which the same handler writes.
     Scoped so it applies only while the builder is the active surface -- see
     section 4.

   HARD RULE 1 -- nothing simple-select.js reads is display:none'd anywhere in
   this file. In particular .metal_current_option / .shape_current_option keep
   their box and their parent-child relationship: simple-select.js:989 and
   :1016 test `$(this).parent('.metal_current_option').length === 0` to tell
   "clicked the current chip" from "clicked a new option", so flattening either
   with display:contents, or hiding it, turns every metal and shape click into
   a no-op. This file does not touch them at all.

   EVERY VALUE COMES FROM THE FIGMA REST API. Letter-spacing really is
   -0.20999999344348907px in the source and is written -0.21px. Where the
   design has no value for something the markup contains, or the markup has no
   node for something the design draws, that is stated in a comment rather than
   invented.
   ============================================================================= */

@media (max-width: 991px) {

  /* ===========================================================================
     0.  LOCAL TOKENS
     ---------------------------------------------------------------------------
     simple-select-redesign.css declares --rb-* on `#simple-select-quiz`. Two of
     the four surfaces in this file live OUTSIDE that element -- Modal appends
     .popup-modal-container to <body> (main.js:614) and #contact_modal_popup is
     printed by header.php -- so the tokens do not inherit into them. They are
     re-declared here on those two roots with byte-identical values, and the
     drawer-specific geometry is added for all three surfaces. Nothing is
     redefined to a different value.
     =========================================================================== */
  .popup-modal-container,
  #contact_modal_popup,
  #simple-select-quiz {
    /* colour -- identical to simple-select-redesign.css section 1 */
    --rb-text-primary:   #0F0E0D;
    --rb-text-secondary: #3E3C39;
    --rb-border-subtle:  #E4DED8;
    --rb-surface-card:   #FFFFFF;
    --rb-surface-page:   #FAF3ED;
    --rb-brand-green:    #27423B;
    --rb-grey-disabled:  #D0D0D0;
    --rb-font-body:      'FoundersGrotesk', sans-serif;
    --rb-font-display:   'Canela', serif;
    --rb-ls-tight:       -0.21px;
    --rb-ls-wide:        -0.5px;
    --rb-radius-sm:      4px;
    --rb-radius-md:      8px;
    --rb-stroke:         1px;
    --rb-stroke-thick:   2px;

    /* drawer geometry, this file only */

    /* The one scrim value -- see the file header. `black mask` 14463:36568 /
       14463:36826 / 14463:32623, #000000 at paint alpha 0.699999988079071. */
    --rb-scrim: rgba(0, 0, 0, 0.699999988079071);

    /* Metal / Shape open at relY 244 in a 1050 frame -> 198 once the 46px
       status-bar mockup is removed. That is the top inset the sheet must never
       rise above. */
    /* 198 IS THE TALL-PHONE INSET, NOT A CONSTANT. Owner: *"the drawer length
       when I click on metal or shape can be bigger to accommodate all the tiles
       in the viewport."*
       The sheet is capped at `100vh - inset`, so a fixed 198 leaves only
       100vh-198 for content -- MEASURED at 390x667: the cap fell to 469 against
       559 of content and BOTH sheets began scrolling, putting the tile rows
       under the fold on exactly the phones that can least afford it. At 844 it
       is unchanged.
       580 is the sheets' own content height (559) plus a 21px breath, so the
       inset only gives way once the screen is genuinely too short for it. The
       24px floor keeps the sheet from ever reaching the very top edge. */
    --rb-sheet-top-inset: clamp(24px, calc(100vh - 580px), 198px);
    /* gemstones opens at relY 83 in a 1011 frame -> 37. */
    --rb-gem-top-inset: 37px;

    /* All three sheets: pad 21/24/20/24, radius [8,8,0,0], fill #FFFFFF,
       stroke #E4DED8 w1 INSIDE. */
    --rb-sheet-pad-top: 21px;
    --rb-sheet-pad-inline: 24px;
    --rb-sheet-pad-bottom: 20px;

    /* Above .popup-modal-container's own 99999 (main.css:3099) is not needed --
       the gemstone sheet IS that element. The metal/shape sheets have to clear
       the stone screen's fixed 129px CTA block, which _stone.css puts at 100. */
    --rb-sheet-z: 1000;
  }


  /* ===========================================================================
     1.  METAL + SHAPE BOTTOM SHEETS
     `Metal` 14463:36569 / `Shape` 14463:36866 -- both 390 x 805, AL:VERTICAL
     gap 40, pad 21/24/20/24, fill #FFFFFF, stroke #E4DED8 w1 INSIDE,
     r=[8,8,0,0], open at relY 244 (198 after the status bar), slide 809px in
     400ms SMART_ANIMATE / EASE_IN_AND_OUT.

     The DOM equivalent is the option list itself. There is no wrapper, header,
     preview image, close x or footer inside it -- see the NOT BUILT note at
     the end of this section.
     =========================================================================== */

  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options {
    /* Reset the desktop flyout geometry from simple-select.css:691 / :726
       (position:absolute; top:28px; left:45-46px; width:150px; 1px border). */
    position: fixed;
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    /* THE SHEET WAS 144px WIDE UNTIL THIS LINE EXISTED. _stone.css:481 pins
       `max-width: 144px` on these two containers at the SAME specificity
       (1-2-0) to make them match the 144px metal/shape pill they drop out of on
       the stone screen, and it loads BEFORE this file, so its `width: 100%` was
       beaten by the `width: auto` above but its max-width was never contested.
       A 144px sheet clamps the whole bottom sheet to the pill: the 342 x 262
       ring preview, the 4 x 2 swatch grid and the footer all overflow it, which
       is exactly what "the drawer is broken / the ring image is missing" looks
       like on a phone. `none` -- not a number -- because the sheet is
       left:0/right:0 and takes the viewport width at every size. */
    max-width: none;
    z-index: var(--rb-sheet-z);
    box-sizing: border-box;

    /* `display` is DELIBERATELY ABSENT -- jQuery owns it (file header). */

    background: var(--rb-surface-card);
    border: 0;
    border-radius: var(--rb-radius-md) var(--rb-radius-md) 0 0;

    /* Height. The Figma sheet is a fixed 805, but its own auto-layout content
       only reaches 559 (21 + 436 body + 40 gap + 42 footer + 20), leaving 246px
       of empty white -- an artefact of a fixed-height frame inside a
       fixed-height mock. Two of the three body blocks (the 342x262 ring preview
       and the 42px footer) have no DOM counterpart here, so a literal 805 would
       be mostly void. The sheet hugs its content instead and is capped so it can
       never rise above the designed 198px top inset. */
    height: auto;
    max-height: calc(100vh - var(--rb-sheet-top-inset));
    max-height: calc(100dvh - var(--rb-sheet-top-inset));
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;

    /* The 1px #E4DED8 sheet stroke is strokeAlign INSIDE, which in Figma is
       painted inside the frame WITHOUT taking layout space -- the 390 sheet
       still has a 342 content box under 24px padding. A real border would eat
       2px of that and drop the shape sheet from five tiles per row to four, so
       it is drawn as an inset shadow.

       THE 100vmax SCRIM SHADOW THAT USED TO BE IN THIS DECLARATION IS GONE.
       `black mask` is now a real element (`.rb_drawer_scrim`, section 1e) for
       two reasons: painting a viewport-sized shadow ON the sheet meant the
       scrim TRANSLATED with the sheet on every open, and the browser had to
       repaint that whole region on each of the 400ms of frames -- which is what
       the "very glitchy" report is. A separate fixed element fades on its own
       compositor-only opacity curve and never moves. */
    box-shadow: inset 0 0 0 var(--rb-stroke) var(--rb-border-subtle);

    /* SLIDE. Figma: SMART_ANIMATE / EASE_IN_AND_OUT / 400ms, travel 809px --
       i.e. the sheet is parked one full sheet-height below the floor and slides
       up to rest.

       TRANSITION, NOT ANIMATION. The previous build used
       `animation: ... both`, which re-fires on every display:none -> block
       flip. load_simple_select_quiz_shapes() (simple-select.js:2038) REWRITES
       both sheets wholesale on every metal/shape commit, and simple-select.js
       :986/:1012 hide-then-show them on each option tap, so the 400ms slide
       restarted mid-flight several times per interaction and the sheet visibly
       jumped. A transition only runs when the property actually changes, so a
       re-render of the CONTENTS cannot restart it.

       `display` is still jQuery's (file header), so the open state is carried
       by `.rb_sheet_open`, which simple-select-redesign.js adds one animation
       frame after it sees jQuery write the inline display -- the frame that
       gives the browser a resolved `translateY(100%)` to transition FROM.
       Transform only: no opacity on the sheet, because cross-fading 16px text
       against the scrim is what made the type shimmer. */
    transform: translateY(100%);
    transition: transform 400ms cubic-bezier(0.42, 0, 0.58, 1);
    will-change: transform;

    font-family: var(--rb-font-body);
    /* font-size:0 kills the whitespace between the inline-block options. The
       container's `display` cannot be changed to flex/grid (jQuery owns it), so
       the grids below are built from inline-block items. Every descendant sets
       its own size. */
    font-size: 0;
    color: var(--rb-text-primary);
    text-align: left;
  }

  /* The rest position. Adding the class is the whole open gesture. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options.rb_sheet_open,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options.rb_sheet_open {
    transform: translateY(0);
  }

  /* Still used by the gemstone sheet (section 2) and the contact popup
     (section 4) -- do not delete. */
  @keyframes rb-sheet-slide-up {
    from { transform: translateY(100%); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
  }

  /* --- 1e. THE SCRIM --------------------------------------------------------
     `black mask` 14468:39613 / 14468:39870 -- a full-frame 390 x 1050 rect,
     #000000 at paint alpha 0.699999988079071, sitting ABOVE the dimmed page
     header and BELOW the sheet. It has no DOM counterpart, so
     simple-select-redesign.js appends one `<span class="rb_drawer_scrim">` to
     #simple-select-quiz (a <span> among block children: inert for every
     `:nth-of-type` selector in this file and in _stone.css).

     It is hit-tested and closing -- tapping the dim closes the sheet. That is
     new: the old shadow-scrim deliberately let taps through to the pill because
     the sheet had no close control. It has two now (the X and DONE), so the
     scrim can behave like a scrim. */
  #simple-select-quiz .rb_drawer_scrim {
    position: fixed;
    inset: 0;
    z-index: calc(var(--rb-sheet-z) - 1);
    background: var(--rb-scrim);
    opacity: 0;
    pointer-events: none;
    /* Matches the sheet's 400ms so the dim and the travel land together. */
    transition: opacity 400ms cubic-bezier(0.42, 0, 0.58, 1);
  }
  #simple-select-quiz .rb_drawer_scrim.rb_scrim_on {
    opacity: 1;
    pointer-events: auto;
  }

  /* Sheet padding. Metal and Shape differ ONLY in padding-bottom / padding-right
     and only because of how each grid's trailing margin is absorbed; both land
     on the designed 21/24/20/24 box. See each grid below. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options {
    padding: var(--rb-sheet-pad-top) var(--rb-sheet-pad-inline) var(--rb-sheet-pad-bottom);
  }
  /* FALLBACK ONLY. The five 55px tiles carry a 16.5px right margin each (1b);
     in inline layout the fifth tile's trailing margin counts towards the line,
     so 5 x 71.5 = 357.5 does not fit a 342 content box and the row breaks at
     four. Where `:nth-child(of S)` is unavailable, 16.5 of the right padding is
     surrendered to that margin (24 - 16.5 = 7.5) and padding-bottom is dropped
     because the last row's 20px margin already stands in for it. The tiles land
     correctly either way; only the computed padding differs from the metal
     sheet's, which is what the @supports block below repairs. */
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options {
    padding: var(--rb-sheet-pad-top) 7.5px 0 var(--rb-sheet-pad-inline);
  }
  /* 14463:36866 and the metal sheet 14463:36566 are the SAME box: both are
     390 x 805, pad 21/24/20/24, gap 40, r [8,8,0,0], #FFFFFF with a 1px
     #E4DED8 INSIDE stroke. Only the title and the payload differ. The two
     sheets must therefore compute the same padding, which means the row's
     trailing margins have to be zeroed instead of absorbed.
       - `:nth-child(5n of <tiles that are not antique-cut>)` ends each visible
         row.  The `of S` form counts only the matching elements, so it does not
         care where the hidden antique-cut tile falls in the source order (it is
         first on this product, but that is an attribute-order accident).
       - the last row's 20px bottom margin is cancelled by a zero-height ::after
         with a -20px top margin, which needs no counting at all.
     Chromium 111+, Safari 9+, Firefox 113+.  Older engines fail the @supports
     test and keep the fallback above. */
  @supports selector(:nth-child(1 of *)) {
    #simple-select-quiz .quiz-image .shape_dropdown_ssq_options {
      padding: var(--rb-sheet-pad-top) var(--rb-sheet-pad-inline) var(--rb-sheet-pad-bottom);
    }
    #simple-select-quiz .quiz-image .shape_dropdown_ssq_options
      .select_shape_option:nth-child(5n of .select_shape_option:not([name="antique-cut"])) {
      margin-right: 0;
    }
    #simple-select-quiz .quiz-image .shape_dropdown_ssq_options::after {
      content: "";
      display: block;
      margin-top: -20px;          /* cancels the last row's itemSpacing margin */
    }
  }

  /* --- sheet title ----------------------------------------------------------
     `Title` 14463:36574 "SELECT YOUR METAL" (196 x 30) and 14463:36871
     "SELECT YOUR SHAPE" (192 x 30) -- Canela 300, 20px / 30px, ls -0.21,
     #0F0E0D, inside a 342 x 24 header row.

     Generated content rather than markup: the containers hold nothing but the
     option divs, and nothing in simple-select.js reads text out of them (it
     reads [name] and .data('friendly') -- see :989, :1016, :2047, :2061). A
     ::before cannot be reached by a selector, by .html()/.text(), or by the
     click delegation, so it cannot break any of that. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options::before,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options::before {
    display: block;
    font-family: var(--rb-font-display);
    font-weight: 300;
    font-size: 20px;
    line-height: 30px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-primary);
    /* THE ROW IS 24, THE TEXT BOX IS 30. `Frame 1171276588` is 342 x 24 at
       y265; `Frame 38529` inside it is 196 x 30 at y262, i.e. the type box
       overshoots the row by 3px top and bottom. Reproduced literally: a 24px
       block box with a 30px line-height, so the glyphs overhang exactly as
       Figma draws them and the NEXT box starts at y289 + the 4px gap = y293,
       which is the ring preview's designed top. Any height other than 24 moves
       the preview off its y. */
    height: 24px;
    margin: 0;
  }
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options::before { content: "SELECT YOUR METAL"; }
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options::before { content: "SELECT YOUR SHAPE"; }

  /* --- 1a. METAL SWATCHES ---------------------------------------------------
     `Frame 38492` 14463:36578 -- 342 x 130, AL:HORIZONTAL wrap=WRAP,
     itemSpacing 48, counterAxisSpacing 30, eight 48 x 48 circles.
     Four per row: x = 24, 120, 216, 312 (pitch 96 = 48 + 48). Row pitch 78
     (y = 573, 651).

     DEVIATION, stated not hidden: Figma prints the two-character karat ("14k",
     "18k") INSIDE the circle. simple-select.js:2061 prints the full
     data-friendly name ("18k Yellow Gold") as a bare text node beside the dot,
     and there is no element wrapping it, so it cannot be moved into the circle
     or sized independently of the option. It is set below the dot instead. The
     label is NOT suppressed: 14k White Gold and 18k White Gold resolve to the
     same #A3A3A3 dot, so dots alone are ambiguous. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .select_metal_option {
    /* was: display:flex; gap:5px; align-items:center; padding:8px 5px */
    display: inline-block;
    vertical-align: top;
    box-sizing: border-box;
    /* Four columns on the DESIGNED pitch: 48px dot + 48px itemSpacing = 96, so
       x = 24, 120, 216, 312 (MASTER 423) and the row is 4x48 + 3x48 = 336 of
       the 342 content box. Equal 25% (85.5px) columns used to stand here and
       put every dot 12.75-18.75px off its designed x. The label still overflows
       the 48px box, centred, but it now has the full 96px pitch to spread into
       rather than 85.5. */
    width: 48px;
    /* The box is the 48px dot only. The label line overflows downwards INTO the
       30px row gap and sideways past the 48px column, centred -- which is what
       keeps the row pitch at exactly 48 + 30 = 78. */
    height: 48px;
    overflow: visible;
    padding: 0;
    border: 0;
    /* itemSpacing 48 / counterAxisSpacing 30. The trailing margin of the 4th
       item would push the line to 384 and break the row at three, so it is
       zeroed there -- eight swatches, no hidden ones, so 4n is exact. */
    /* itemSpacing 48 / counterAxisSpacing 30 -- EXACT at the authored 390, where
       the 342 content box gives (342 - 4x48) / 3 = 50 and the min() therefore
       picks the designed 48. Below 366 a hard 48 no longer fits four columns and
       the grid was wrapping 2/3/3 at 320; the same min() technique the hero
       already uses (see `width: min(342px, ...)` above) closes the gutter instead
       so the 4 x 2 grid survives. No number above 390 changes. */
    margin: 0 min(48px, calc((100% - 192px) / 3)) 30px 0;
    text-align: center;
    white-space: nowrap;
    /* The positioning context for `.rb_metal_karat`, which the design draws
       INSIDE this circle (14463:36581 sits at 39,582 in a 48x48 ellipse at
       24,573 -- centred on both axes), not under it.
       `font-size: 0` kills every bare text node the option may still carry, so
       nothing but the dot and the absolutely-placed karat can affect the box.
       The box therefore stays exactly 48 tall and the row pitch stays 48 + 30
       = 78, whatever simple-select.js writes into the option. */
    position: relative;
    font-size: 0;
    line-height: 0;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
    cursor: pointer;
  }

  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .select_metal_option:nth-of-type(4n) {
    margin-right: 0;
  }

  /* `Ellipse 52` 14463:36580 -- 48 x 48. The swatch colour is an inline
     `background:` written by simple-select.js:2064, so only the box is set here.
     Overrides simple-select.css:662 (.select_metal_shape span { width:35px }). */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .select_metal_option span.metal_icon {
    display: block;
    /* border-box so the selected ring's 1.5px stroke is painted INSIDE the
       48px ellipse (strokeAlign INSIDE) and the 96px column pitch does not move
       between the selected and unselected states. */
    box-sizing: border-box;
    width: 48px;
    height: 48px;
    margin: 0 auto;
    border-radius: 100px;
    font-weight: 400;
  }

  /* `14k` 14463:36581 -- Founders Grotesk 400 14/30, ls -0.21, #3E3C39, an
     18-wide box at x 39 inside the 48px ellipse at x 24: centred on both axes,
     drawn ON the swatch. simple-select-redesign.js prepends it as a span, so it
     can be lifted out of flow entirely -- which is what keeps the eight dots on
     one 4 x 2 grid regardless of which options carry a karat and which (7 and 8)
     do not.  `top: 9px` is (48 - 30) / 2, the same centring Figma applies. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .select_metal_option .rb_metal_karat {
    position: absolute;
    /* CENTRED BY CONSTRUCTION, NOT BY A CONSTANT. Owner: *"the text is not
       centered."* `top: 9px` is (48 - 30) / 2 -- correct for the PHONE swatch
       and only for it. The desktop swatch is 39, where the same constant leaves
       9 above the 30px line box and 0 below: MEASURED at 1440, icon y719..758,
       label y728..758, i.e. hard on the bottom edge. Centring off the swatch's
       own height is right at 39, at 48, and at whatever a later width asks for. */
    top: 50%;
    transform: translateY(-50%);
    left: 0;
    right: 0;
    /* simple-select.css:662 pins `.select_metal_shape span { width: 35px }`,
       which over-constrains left/right and would leave the karat 35 wide in a
       48 column -- 6.5px off centre. Restated at this specificity. */
    width: 100%;
    height: 30px;
    z-index: 1;
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 14px;
    line-height: 30px;
    letter-spacing: var(--rb-ls-tight);
    text-align: center;
    color: var(--rb-text-secondary);
    pointer-events: none;
  }

  /* The full `data-friendly` name ("14k White Gold"). MASTER 428 draws only the
     karat in the sheet and MASTER 427 leaves swatches 7 and 8 bare, so the name
     is hidden HERE ONLY. It is not removed from the DOM and not touched in
     `.metal_current_option`: simple-select.js:858 / :2067 copy an option's
     outerHTML into the summary pill, where that same span is the pill's only
     label. Scoping the hide to the sheet is what keeps the pill readable. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .select_metal_option .rb_metal_name {
    display: none;
  }

  /* THE SELECTED METAL. DRAWERS.md §1.2: "the ONLY difference is the 1.5px
     #27423B INSIDE stroke on the ellipse, plus the label recolouring #3E3C39 ->
     #27423B." No size change, no fill change, no ring, no checkmark.

     This used to be recorded here as NOT REPRODUCIBLE, and it was: the rendered
     options carry no active class, because load_simple_select_quiz_shapes()
     (simple-select.js:2056-2068) copies the active swatch's outerHTML into
     `.metal_current_option` instead of flagging the matching row, and CSS
     cannot compare [name] across two elements. simple-select-redesign.js now
     does that one comparison and stamps `.rb_selected`. It is a class, never a
     `display`, so nothing simple-select.js reads changes. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .select_metal_option.rb_selected span.metal_icon {
    /* Blink SNAPS a used border-width to whole CSS pixels -- a bare
       `border: 1.5px` renders and reads back as 1px, so the selected ring would
       be the same weight as an unselected one and only the colour would differ.
       The border carries the colour and the layout (border-box, so the 48 and
       the 96 pitch never move) and an inset shadow of the same colour tops it up
       to the designed 1.5. Verified: a probe div with `border:1.5px` reports
       `borderTopWidth: "1px"` at DPR 1 AND DPR 2. */
    /* ...AND THAT IS WHY THE RING READ AS TOO BOLD. Owner: *"the outlines are
       too bold."* Both halves of the workaround above PAINT: Blink snaps the
       1.5px border to a solid 1px AND the inset shadow adds its own 1.5px
       inside it, so the selected swatch wore ~2.5px of green where the design
       asks for 1.5. MEASURED, computed: `border 1px solid` +
       `box-shadow rgb(39,66,59) 0 0 0 1.5px inset`.

       The border stays for GEOMETRY only -- it is what keeps the swatch on the
       same 39/48 outer box as its unselected neighbours under `border-box`, so
       the row does not shift when a selection moves -- and its colour is taken
       off. The shadow is the ring, and it is the one that honours 1.5 exactly. */
    /* ...AND THE TRANSPARENT BORDER IS WHY IT SAT INSIDE THE EDGE. Owner: *"in
       the stone and metal popup drawers the green selection outline is getting
       inside -- align it so the outline is perfectly on the edge of the circle
       or swatch."*

       An inset box-shadow is drawn from the PADDING box inward, not the border
       box. The 1.5px transparent border above (snapped by Blink to a used 1px,
       MEASURED `borderTopWidth: "1px"`) therefore pushed the whole ring a pixel
       in and left a pixel of the disc's own fill showing outside it -- a green
       ring floating inside the circle instead of drawing its outline.

       The border is not needed for the geometry it was kept for: `.metal_icon`
       is `box-sizing: border-box` at a fixed 48, so its outer box is 48 with or
       without one and the row cannot shift. Zeroed, the shadow starts at the
       edge and the ring IS the circle's outline. */
    border-width: 0;
    box-shadow: inset 0 0 0 1.5px var(--rb-brand-green);
  }
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .select_metal_option.rb_selected .rb_metal_karat {
    color: var(--rb-brand-green);
  }

  /* --- 1b. SHAPE TILES ------------------------------------------------------
     `Frame 38498` 14463:36876 -- 342 x 130, AL:VERTICAL itemSpacing 20, two
     rows of five tiles. Tile `Frame 38483` 14463:36878 -- 55 x 55, r4,
     pad 3/0 (4/0 on the oval, cushion and princess tiles), both axes CENTER,
     stroke #E4DED8 w1 INSIDE unselected / #27423B w1.5 selected, holding a
     30px-tall shape vector.
     Row 1 x = 24, 95.5, 167, 238.5, 310 -> pitch 71.5, gutter 16.5.
     Row 2 x = 24, 95, 166, 238, 310 -- the source drifts by up to 1px between
     the two rows; 16.5 is used for both and the drift is recorded, not copied. */
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .select_shape_option {
    /* was: padding:5px; border-bottom:1px solid var(--pearl-dark) */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    vertical-align: top;
    box-sizing: border-box;
    /* FIVE PER ROW AT EVERY WIDTH. 14557:48018 draws two rows of five 55px
       tiles across the sheet's 342 content box: 5 x 55 + 4 x 16.5 = 341, which
       fits 342 and nothing narrower. MEASURED at 360 (content 312): the fifth
       tile wrapped and the run became FOUR rows instead of two.
       Stated as a share of the run so the proportion survives -- 55/342 and
       16.5/342 -- which resolves to exactly 55 and 16.5 at the board's own
       width. `aspect-ratio` keeps the tile square as it narrows, so the shape
       glyph inside never distorts. */
    width: 16.081871345029240%;      /* 55 / 342 */
    height: auto;
    aspect-ratio: 1;
    padding: 3px 0;
    margin: 0 4.824561403508772% 20px 0;   /* 16.5 / 342; itemSpacing 20 */
    border: var(--rb-stroke) solid var(--rb-border-subtle);
    border-radius: var(--rb-radius-sm);
    background: transparent;
    /* The friendly name ("Round", "Oval", ...) is a bare text node beside
       span.icon; the designed tiles are icon-only and there is no wrapper to
       target. font-size:0 collapses it without removing it from the DOM or the
       accessibility tree, and nothing reads it -- simple-select.js uses [name]
       and data-friendly (:1016, :2047). */
    font-size: 0;
    cursor: pointer;
  }

  /* Shape glyphs are 30px tall in every tile (Round_Vector 30 x 30,
     Oval_Vector 20 x 30, Marquise_Vector 16 x 30, ...). The live SVGs are drawn
     in a 50 x 50 viewBox with the glyph spanning roughly 8.25..41.75, i.e. 67%
     of the box, so a 30px <svg> would render a ~20px glyph. 44px of svg renders
     30px of glyph (30 / 0.67) and still clears the tile's 55 - 2x3 = 49px inner
     box. Overrides simple-select.css:666, which sizes these 26 x 26. */
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .select_shape_option span.icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    font-weight: 400;
  }
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .select_shape_option span.icon svg {
    width: 44px;
    height: 44px;
  }
  /* Unselected tiles fill their vector #000000 (14468:39926 and siblings). */
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .select_shape_option span.icon svg path {
    fill: #000000;
  }

  /* THE SELECTED SHAPE. DRAWERS.md §2.2: "the tile stroke goes #E4DED8 1px ->
     #27423B 1.5px, AND the glyph fill goes #000000 -> #27423B." No background,
     no size change, no badge. The tile is already `box-sizing: border-box`, so
     the extra half-pixel of stroke is painted inside the 55 box (strokeAlign
     INSIDE) and the 71.5 pitch does not move. Same `.rb_selected` stamp as the
     metal swatches -- see the note above. */
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .select_shape_option.rb_selected {
    /* Same correction as the metal ellipse above, and here it was drawing the
       ring TWICE: MEASURED, a used `border 1px solid #27423B` with an
       `inset 0 0 0 1.5px #27423B` on top of it -- about 2.5px of green, with
       the shadow's half sitting a pixel inside the border's half. One ring,
       on the edge. The tile is `box-sizing: border-box` at a fixed 55, so
       dropping the border width does not move it or its neighbours. */
    border-width: 0;
    box-shadow: inset 0 0 0 1.5px var(--rb-brand-green);
  }
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .select_shape_option.rb_selected span.icon svg path {
    fill: var(--rb-brand-green);
  }

  /* Unavailable shapes. STATES.md records that no disabled state is designed
     anywhere on this board, so this keeps simple-select.css:707's existing
     intent and only restates it in the board's own disabled grey instead of
     that rule's #a3a3a3 fill. */
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .select_shape_option.disabled {
    background: transparent;
    border-color: var(--rb-grey-disabled);
  }
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .select_shape_option.disabled span.icon svg path {
    fill: var(--rb-grey-disabled);
  }

  /* The Antique tile stays hidden. simple-select.css:701 already does this
     (`.shape_dropdown_ssq_options .select_shape_option[name=antique-cut]
     { display:none }`, specificity 0-3-0), but the display:inline-flex above is
     1-3-0 and outranks it, so the existing behaviour has to be restated here at
     matching specificity or Antique would reappear and break the five-per-row
     grid. This is NOT a new hide: it is the shipped base sheet's own rule, and
     the node is not one of the JS-read elements -- simple-select.js reads
     [name] and .data('friendly') off the SWATCHES (:2044), never off these
     generated options. The ten remaining tiles fall five-and-five exactly as
     the design draws them. */
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .select_shape_option[name="antique-cut"] {
    display: none;
  }

  /* --- 1c. THE SHEET'S CLOSE CONTROL AND HERO IMAGE -------------------------
     Both nodes now ship: simple-select-redesign.js prepends
     `span.rb_drawer_close` and `img.rb_drawer_hero` to each sheet (a <span> and
     an <img> deliberately, so `:nth-of-type` on the option divs keeps
     resolving). Until they were styled they sat in the sheet's INLINE flow --
     `font-size: 0` on the container gave the close span a 12 x 0 box on the
     first line and pushed the first row of swatches and shape tiles right by
     12-13px, which is what broke the 4 x 2 and 5 x 5 grids.

     Both are therefore taken out of that flow: the close is absolutely placed
     against the sheet (which is `position: fixed`, so it is the containing
     block) and the hero is a block. Nothing else in the sheet moves. */

  /* close x `Frame 1171276578` 14463:36575 / 14463:36872 -- 24 x 24 at
     sheet-relative (342, 21), i.e. hard against the 24px padding box on both
     axes, r4, no fill, holding a 10 x 10 vector stroked #0F0E0D at w0.75.
     Chromium reports a USED border/stroke width, so 0.75 is declared here and
     will read back rounded at DPR 1 -- the declaration is the spec value. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_close,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_close {
    position: absolute;
    top: var(--rb-sheet-pad-top);
    right: var(--rb-sheet-pad-inline);
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: var(--rb-radius-sm);
    background: transparent;
    color: var(--rb-text-primary);
    font-size: 0;
    line-height: 0;
    z-index: 2;
    cursor: pointer;
  }
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_close svg,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_close svg {
    display: block;
    width: 10px;
    height: 10px;
    /* Declared on the SVG, not the path: `stroke` and `stroke-width` are
       inherited SVG properties, so the path picks them up, and the spec's 0.75
       is then readable off the element the design calls the vector. The markup
       carries NO stroke presentation attributes for exactly this reason (see
       RB_DRAWER_CLOSE_SVG in simple-select-redesign.js) -- a presentation
       attribute would beat this declaration. */
    stroke: var(--rb-text-primary);
    stroke-width: 0.75px;   /* 14468:39621 */
    fill: none;
  }
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_close svg path,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_close svg path {
    stroke: inherit;
    stroke-width: inherit;
  }

  /* hero `image` 14468:39622 (metal) / 14468:39919 (shape) -- a RECTANGLE with
     an IMAGE fill, 342 x 262 at x24 y293, cornerRadius 4, scaleMode STRETCH.
     Both frames carry the SAME imageRef (7685833b...), and that ref is also the
     page's own ring thumbnail: DRAWERS.md Q1 settles that this slot is the RING
     for the current variation, never a loose-stone photo.

     ONE SOURCE OF TRUTH. simple-select-redesign.js mirrors the src straight off
     `.quiz-image .sss-metal-image img` -- the preview the customer is already
     looking at -- and re-mirrors it on every src write, so the sheet cannot
     disagree with the page. No second asset, no invented URL.

     The JS gives it `hidden` at >= 992px because the desktop popup draws its
     own 594 x 495 photo in the Container, not in the picker panel, so the
     [hidden] guard below has to outrank the display. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options img.rb_drawer_hero,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options img.rb_drawer_hero {
    display: block;
    box-sizing: border-box;
    /* was width: 342px -- the design is authored at 390, so a fixed 342 overflowed every narrower phone. min() keeps 342 at 390 and shrinks below. */
    width: min(342px, calc(100vw - 48px));
    /* 342, NOT 262. Owner: *"in the BYR flow the metal and shape trigger a popup
       -- on phone the ring image is too small, make the height longer, increase
       image size."*

       262 was never the photo's shape: the asset is 342 x 342 and the box is 342
       wide, so a square image was being letterboxed into a landscape box and
       rendered at ~77% of the size it could have been. Square gives the ring the
       whole box.

       It fits: MEASURED at 390 x 844 the sheet is 559 of content under a 646 cap,
       so there are 87 spare and this spends 80 of them -- 639, still short of the
       cap and still with no scroll inside the sheet. On a shorter screen the
       `max-height` below takes over exactly as it did before; it is the guard
       that makes raising this safe. */
    height: 342px;
    /* ...AND IT GIVES THE HEIGHT BACK WHEN THE SCREEN IS SHORT, SO NOTHING
       SCROLLS. Owner: *"make the drawer long enough that there's no need to
       scroll inside it -- we shouldn't have to scroll down to get to Done."*

       The sheet is capped at `100dvh - var(--rb-sheet-top-inset)` and its
       content is a fixed 559: a 262 hero plus 277 of close, tiles, Done and the
       padding between them. The inset already collapses from 198 to 24 as the
       screen shrinks (:136), but once it is on the floor the cap keeps falling
       with the viewport while the content does not -- MEASURED: 580 of visible
       height caps the sheet at 556 against 559 of content, 540 caps it at 516,
       and the overflow lands on the LAST thing in the sheet, which is Done.

       Everything except the photo is a control, so the photo is the only thing
       that may shrink. 297 is the 277 it cannot have back plus the hero's own
       20 of margin; `max()` keeps a 96px floor so a very short screen gets a
       small photo rather than none, and the sheet's `overflow-y: auto` is left
       as the last resort below that. `object-fit: contain` already letterboxes,
       so a shorter box shows a smaller ring, never a cropped one. */
    max-height: max(96px, calc(100vh - var(--rb-sheet-top-inset) - 297px));
    max-height: max(96px, calc(100dvh - var(--rb-sheet-top-inset) - 297px));
    /* top 4  = `Frame 1171276613` itemSpacing 4 (title row -> image)
       bottom 16 = `Frame 38580` itemSpacing 16 (image -> option row). */
    margin: 4px 0 16px;
    border-radius: var(--rb-radius-sm);
    /* `contain`, not the `cover` that Figma's scaleMode implies. The mock's
       placeholder is authored to exactly fill this box, so FILL/STRETCH looks
       right there; the real product photographs have a different aspect ratio,
       and `cover` visibly cut the ring off. Showing the whole ring beats
       matching a scaleMode that was only ever true of the mock asset. */
    object-fit: contain;
  }
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options img.rb_drawer_hero[hidden],
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options img.rb_drawer_hero[hidden] {
    display: none;
  }
  /* WITH NO HERO the title has to carry the gap the hero's margins would have.
     Only reachable when the page preview has no src yet. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options:not(:has(> img.rb_drawer_hero:not([hidden])))::before,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options:not(:has(> img.rb_drawer_hero:not([hidden])))::before {
    margin-bottom: 16px;
  }
  /* The METAL option row `Frame 38492` 14468:39623 is a FIXED 342 x 130 box
     holding 48 + 30 + 48 = 126 of rows with counterAxisAlignItems CENTER, so it
     centres them and the first row starts at y573, 2px inside the frame's own
     y571. The SHAPE row `Frame 38498` 14468:39920 is 130 of 130 and has no such
     slack, which is why this 2px is metal-only. It is added to whichever box
     precedes the swatches in the inline flow -- the hero, or the title. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options img.rb_drawer_hero {
    margin-bottom: 18px;
  }
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options:not(:has(> img.rb_drawer_hero:not([hidden])))::before {
    margin-bottom: 18px;
  }

  /* --- 1c. THE SHEET FOOTER STRIP -------------------------------------------
     `Frame 1171276612` 14463:36601 (metal) / 14463:36909 (shape) -- 342 x 42 at
     y 741, i.e. the last child of the sheet, 20px above its padding edge. It
     holds one two-line text run:

       metal  "14K White Gold\nSetting:  $680 "   Title 14463:36604, 120 x 42
       shape  "Round\nSetting:  $680 "            Title 14463:36912, 120 x 42

     Founders Grotesk 16/21, ls -0.21, #3E3C39, align LEFT/BOTTOM. Both nodes
     carry characterStyleOverrides that put line 1 on weight 500 and line 2 on
     the 400 base (override table entries 26 and 25) -- so the two spans
     simple-select-redesign.js:1555 builds map 1:1 onto the two runs.

     The strip's own `seperator` VECTOR (14463:36602 / 14463:36910) is
     visible:false in the source and is correctly not drawn.

     WHY THIS NEEDS A FONT-SIZE AT ALL. The sheet is `font-size: 0` (see the
     container rule above) -- that is what kills the whitespace between the
     inline-block options. The footer is a normal block child of that sheet, so
     it inherits 0 and computed 342 x 0 with the right textContent inside it.
     Every type property is therefore restated here rather than inherited.

     THE DONE CTA NOW SHIPS. `CTA` 14468:39656 / 14468:39955 -- 90 x 40 at x276
     y742 (1px below the 42px row top, which is what counterAxisAlignItems
     CENTER produces for a 40 in a 42), fill #27423B, cornerRadius 4, label
     `DONE` 40 x 19 Founders Grotesk 400 16/19 ls -0.21 #FAF3ED, textCase
     ORIGINAL. It was previously left out as a gap on the grounds that it would
     be a dead control; it is not dead -- the sheets commit on option click, so
     DONE is exactly "I am finished here", i.e. the same close the X performs.
     simple-select-redesign.js wires it to the sheet's own .hide(), the one
     simple-select.js:986 already uses. No new open/close model. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_footer,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_footer {
    /* `Frame 1171276611`: HORIZONTAL, SPACE_BETWEEN, itemSpacing 40,
       counterAxisAlignItems CENTER, 342 x 42. */
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 40px;
    box-sizing: border-box;
    width: 100%;                   /* Frame 1171276611 is FILL -> the 342 box */
    /* The row is 42 in the design and the two-line text measures exactly 42
       (2 x 21). min-height rather than height so a metal name long enough to
       wrap grows the row instead of clipping, and so the row still stands at 42
       on the products where rbSettingPrice() has no figure and line 2 is
       empty. */
    min-height: 42px;
    /* The U+000A between the two runs is a real newline in the text node
       (the JS builds it with .text(), not innerHTML), so it needs pre-line to
       break -- and pre-line still collapses the leading indentation whitespace
       the template would otherwise contribute. Declared on the row so it
       inherits into the text box below. */
    white-space: pre-line;
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 16px;
    line-height: 21px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
    text-align: left;
  }
  /* The left-hand TEXT node, `Title` 14468:39653 / 14468:39957 -- FIXED 120 x
     42, align LEFT / BOTTOM, holding both runs. It is a real <span> that
     simple-select-redesign.js wraps the two existing run spans in, because the
     120 is a FIXED width in the source and a flex row cannot size an anonymous
     item. `flex: 0 0 120px` reproduces it exactly; 120 + 40 gap + 90 CTA = 250
     of the 342 row, and SPACE_BETWEEN puts the rest between them. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_footer_text,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_footer_text {
    display: block;
    flex: 0 0 120px;
    width: 120px;
    /* align LEFT / BOTTOM inside the 42 box; with both 21px lines present the
       two are identical, and with only line 1 the run sits on the baseline the
       design puts it on. */
    align-self: flex-end;
    min-height: 42px;
    font-size: 16px;
    line-height: 21px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
    text-align: left;
  }

  /* `CTA` 14468:39656 / 14468:39955 -- 90 x 40, fill #27423B, cornerRadius 4,
     clip=true, HORIZONTAL, primary CENTER, counter CENTER. Label `DONE`
     40 x 19, Founders Grotesk 400 16/19, ls -0.21, #FAF3ED, textCase ORIGINAL
     -- the string is ALREADY upper-case, so `text-transform` is explicitly
     `none`: the characters are the source of truth, not a CSS transform. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_done,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_done {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 90px;
    box-sizing: border-box;
    width: 90px;
    height: 40px;
    /* padding t12 r0 b12 l0 in Figma; the 19px label in a 40px box centred is
       the same result and survives a font fallback. */
    padding: 0;
    margin: 0;
    border: 0;
    border-radius: var(--rb-radius-sm);
    background: var(--rb-brand-green);
    overflow: hidden;              /* clipsContent: true */
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 16px;
    line-height: 19px;
    letter-spacing: var(--rb-ls-tight);
    text-transform: none;
    text-align: center;
    /* the row is `white-space: pre-line`; the CTA label is a single run. */
    white-space: nowrap;
    color: var(--rb-surface-page);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
  }

  /* Line 1 -- the current selection. styleOverrideTable[26] is
     `fontWeight: 500`.
     KNOWN GAP, same one _stone-desktop.css §10 records: assets/fonts ships
     FoundersGrotesk-Medium.otf but main.css registers only the Regular face, so
     this resolves to Regular until a 500 @font-face is added there. Declared at
     the designed weight anyway -- the moment main.css grows the face this is
     correct with no edit here. Restated because the base sheet gives spans
     inside the drawer weight 700. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_footer_sel,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_footer_sel {
    font-family: var(--rb-font-body);
    font-weight: 500;
    font-size: 16px;
    line-height: 21px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
  }
  /* Line 2 -- "Setting:  $680 ", styleOverrideTable[25], the 400 base. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_footer_price,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_footer_price {
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 16px;
    line-height: 21px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
  }

  /* Before a selection exists the JS leaves both run spans empty (it will not
     borrow the first option's values). This used to remove the whole strip from
     flow; it no longer can, because the strip now also carries the DONE CTA and
     the sheet's only other exit is the 24px X. The TEXT BOX collapses instead
     and the CTA keeps its place at the right-hand end of the row. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_footer:has(.rb_drawer_footer_sel:empty) .rb_drawer_footer_text,
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_footer:has(.rb_drawer_footer_sel:empty) .rb_drawer_footer_text {
    visibility: hidden;
  }

  /* THE GAP ABOVE THE STRIP. Both sheets are AL:VERTICAL gap 40 and the strip
     is the child after the swatch/tile grid, but the two grids leave different
     trailing margins behind, so the top-up differs -- the same absorption the
     two sheets' `padding` already has to account for above.
       METAL  last row of dots ends at 699 (grid frame 571..701 with the 2px of
              counter=CENTER slack), footer at 741 -> 42 of clear air. Each
              .select_metal_option carries margin-bottom 30, and an inline-block's
              MARGIN box sets the line-box height, so 30 of that 42 is already
              on the page. 12 tops it up.
       SHAPE  last row of tiles ends at 701, footer at 741 -> 40. Each
              .select_shape_option carries margin-bottom 20, so 20 tops it up.
     The theme gives <p> a 16px bottom margin; the strip is the last child and
     the sheet's own 20px padding-bottom is the designed space below it, so that
     margin is zeroed rather than added to. */
  #simple-select-quiz .quiz-image .metal_dropdown_ssq_options .rb_drawer_footer {
    margin: 12px 0 0;
  }
  #simple-select-quiz .quiz-image .shape_dropdown_ssq_options .rb_drawer_footer {
    margin: 20px 0 0;
  }
  /* The ::after in the @supports block above exists to cancel the last tile
     row's 20px bottom margin, which used to be the sheet's last box. With the
     strip appended that margin is no longer trailing -- it is the top half of
     the 40px gap measured above -- so the correction has to stand down, or it
     eats the sheet's 20px padding-bottom instead. */
  @supports selector(:nth-child(1 of *)) {
    #simple-select-quiz .quiz-image .shape_dropdown_ssq_options:has(> .rb_drawer_footer)::after {
      margin-top: 0;
    }
  }


  /* ===========================================================================
     2.  GEMSTONE BOTTOM SHEET
     `gemstones` 14463:34189 -- 390 x 934, AL:VERTICAL gap 30, pad 21/24/20/24,
     fill #FFFFFF, stroke #E4DED8 w1 INSIDE, r=[8,8,0,0], open at relY 83
     (37 after the status bar). SMART_ANIMATE / EASE_OUT / 300ms.

     Hook: .popup-modal-container.gemstone_selection_modal gated on
     :has(.modal-gemstone-selection) -- see the file header for why the gate is
     required. `display` is never set: Modal.open() / close() write it inline
     (main.js:617, :628).
     =========================================================================== */

  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) {
    /* main.css:3089 already gives this fixed inset-0 at z 99999. Only the scrim
       colour changes: the base sheet uses rgb(0 0 0 / 50%), the board uses 0.70.
       This one IS a real element, and Modal.handleOutsideClick (main.js:643)
       dismisses on a tap that lands on it -- so unlike the metal/shape sheets
       it can and should be hit-tested. */
    background: var(--rb-scrim);
    animation: rb-scrim-in 300ms ease-out both;
  }
  @keyframes rb-scrim-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .flyout {
    /* Reset main.css:3104, which centres a 90%/425px card vertically. */
    position: absolute;
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    transform: none;
    margin: 0;
    width: 100%;
    /* simple-select.js:2615 writes an INLINE `max-width` (the site container
       width, ~366 at 390) straight onto this element. An inline declaration can
       only be beaten by !important -- this is the one place in the file where
       it is unavoidable. The sheet is full-bleed 390 in the design. */
    max-width: none !important;
    /* 934 tall in a 1011 frame at relY 83; 37 once the status-bar mockup is
       removed. Bottom-anchored, so the sheet keeps that 37px inset at any
       viewport height. */
    max-height: calc(100% - var(--rb-gem-top-inset));
    height: auto;
    overflow-y: auto;
    box-sizing: border-box;
    padding: var(--rb-sheet-pad-top) var(--rb-sheet-pad-inline) var(--rb-sheet-pad-bottom);
    background: var(--rb-surface-card);
    border-radius: var(--rb-radius-md) var(--rb-radius-md) 0 0;
    /* stroke #E4DED8 w1 INSIDE -- drawn as an inset shadow so it does not eat
       2px of the 342 content box (same reasoning as section 1). */
    box-shadow: inset 0 0 0 var(--rb-stroke) var(--rb-border-subtle);
    animation: rb-sheet-slide-up 300ms ease-out both;
  }

  /* Header `Frame 1171276588` 14463:34191 -- 342 x 24, SPACE_BETWEEN,
     counter CENTER. Frame 1171276614 puts a 12px gap under it. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .modal_header {
    padding: 0;
    margin: 0 0 12px;
    border-bottom: 0;              /* main.css:3132 draws a 1px #000 rule */
    align-items: center;
    min-height: 24px;
  }

  /* `Title` 14463:34193 "GEMSTONES" -- Canela 300, 20/30, ls -0.21, #0F0E0D.
     COPY NOTE: simple-select.js:2584 sets "GEMSTONES | 0.5 Carat"; the design
     reads "GEMSTONES" alone. Text only, not fixable from CSS. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) #modal-title {
    margin: 0;
    font-family: var(--rb-font-display);
    font-weight: 300;
    font-size: 20px;
    line-height: 30px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-primary);   /* base: simple-select.css:1152 var(--jade) */
    text-transform: none;
  }

  /* Close x `Frame 1171276578` 14463:34194 -- 24 x 24, r4, with a hidden
     #0F0E0D @0.4 fill and a 10 x 10 glyph. In Figma that glyph is a VECTOR
     stroked #0F0E0D at weight 0.75 and carries NO interaction; here the same
     10px box is a filled path on a button that really does close the modal
     (main.js:620), which is strictly better. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .modal_close {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 24px;
    height: 24px;
    border-radius: var(--rb-radius-sm);
  }
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .modal_close svg {
    width: 10px;
    height: 10px;
  }
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .modal_close svg path {
    fill: var(--rb-text-primary);
  }

  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) #modal-content {
    padding: 0;                    /* main.css:3141 sets 0 15px + 20px top */
    margin: 0;
  }

  /* `Frame 38807` 14463:34196 -- AL:VERTICAL itemSpacing 10. Setting `display`
     here is safe: .modal-gemstone-selection is built by simple-select.js:2491
     and never shown/hidden -- the modal's own container is what toggles. */
  .popup-modal-container.gemstone_selection_modal .modal-gemstone-selection {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

  /* Row `Frame 38805` 14463:34202 -- 342 x 64, AL:HORIZONTAL gap 23,
     pad 14/13/14/13, fill #FFFFFF, stroke #E4DED8 w1 INSIDE, r4.
     ROW COUNT: the design draws 8 rows (14463:34197 .. 14463:34238). The live
     list is generated from the `data-variations` payload on
     .simple_gemstone.ssq-simple-selection (simple-select.js:2494), so the count
     is product data, not layout -- the rules below are per-row and hold for any
     number. */
  .popup-modal-container.gemstone_selection_modal .modal-gemstone-selection .ssq-gemstone_option {
    display: flex;
    align-items: center;
    box-sizing: border-box;
    min-height: 64px;
    margin: 0;
    padding: 14px 13px;
    background: var(--rb-surface-card);
    border: 0;
    border-radius: var(--rb-radius-sm);
    /* stroke #E4DED8 w1 strokeAlign INSIDE. Drawn as an inset shadow, not a
       border: a real 1px border would add 2px to the 64px row and push the
       39px thumbnail off the designed x=37. */
    box-shadow: inset 0 0 0 var(--rb-stroke) var(--rb-border-subtle);
    color: var(--rb-text-primary);
  }
  /* Selected row 14463:34197 -- stroke #0F0E0D at weight 2.0, strokeAlign
     INSIDE. Drawn as border + 1px inset shadow so the box does not shift by a
     pixel when the class lands.
     REACHABLE BUT NOT VISIBLE IN PRACTICE: simple-select.js:2660 adds .active
     and then :2679 triggers .modal_close, so the modal is gone in the same
     tick. The state is styled because the class is real; making it linger needs
     a JS change. */
  .popup-modal-container.gemstone_selection_modal .modal-gemstone-selection .ssq-gemstone_option.active {
    /* stroke #0F0E0D at weight 2.0, strokeAlign INSIDE -- so it must not move
       the box by a pixel when the class lands. */
    box-shadow: inset 0 0 0 var(--rb-stroke-thick, 2px) var(--rb-text-primary);
    color: var(--rb-text-primary);   /* base: simple-select.css:1148 var(--jade) */
  }

  /* `Frame 38806` 14463:34203 -- SPACE_BETWEEN across the full row. */
  .popup-modal-container.gemstone_selection_modal .modal-gemstone-selection .stone_option.gemstone {
    display: flex;
    align-items: center;
    gap: 23px;                     /* `Frame 38805` itemSpacing 23 */
    width: 100%;
    min-width: 0;
    padding: 0;
    text-align: left;
  }
  /* `image` 14463:34205 -- 39 x 36, r4, scaleMode FIT. */
  .popup-modal-container.gemstone_selection_modal .modal-gemstone-selection .ssq_stone_image {
    flex: none;
    width: 39px;
    height: 36px;
    max-width: none;
    border-radius: var(--rb-radius-sm);
    overflow: hidden;
  }
  .popup-modal-container.gemstone_selection_modal .modal-gemstone-selection .ssq_stone_image img {
    width: 100%;
    height: 100%;
    object-fit: contain;           /* scaleMode FIT */
    transform: none;               /* base: simple-select.css:1129 scale(0.90) */
  }
  /* The name / price pair. Base (simple-select.css:1155) makes this a two-column
     grid; the design has the name left and the price hard right on the row. */
  .popup-modal-container.gemstone_selection_modal .modal-gemstone-selection .ssq_stone_text {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;                     /* `Frame 38806` itemSpacing 12 */
    flex: 1 1 auto;
    min-width: 0;
    grid-template-columns: none;
  }
  /* `Lab Created Blue Sapphire` 14463:34200 -- Founders Grotesk 400, 14/18,
     ls -0.5, #0F0E0D. */
  .popup-modal-container.gemstone_selection_modal .modal-gemstone-selection p.ssq_type {
    margin: 0;
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 14px;
    line-height: 18px;
    letter-spacing: var(--rb-ls-wide);
    color: var(--rb-text-primary);
  }
  /* `+ $580` 14463:34201 -- same type, fill #000000 (the design really does use
     pure black here and #0F0E0D on the name; both are reproduced).
     .details_display_price is on the never-hide list -- it keeps a full box. */
  .popup-modal-container.gemstone_selection_modal .modal-gemstone-selection p.details_display_price {
    flex: none;
    margin: 0;
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 14px;
    line-height: 18px;
    letter-spacing: var(--rb-ls-wide);
    text-align: right;
    color: #000000;
  }

  /* --- 2a. THE GEMSTONE FOOTER STRIP ----------------------------------------
     `Frame 1171276612` 14463:34244 -- 342 x 42 at y 752, the sheet's last child,
     30 below the list (the `gemstones` frame's own itemSpacing 30: the last row
     ends at 722) and 20 above the padding edge. Inside it `Title` 14463:34246
     is a HUG 174 x 42 two-line run:

       "Lab Created Blue Sapphire\nStone: + $580 | 0.5 Carats"

     Founders Grotesk 16/21, ls -0.21, #3E3C39, align LEFT/BOTTOM, with
     characterStyleOverrides putting line 1 on weight 500 (override 28) and
     line 2 on 400 (override 27) -- the two spans
     simple-select-redesign.js:1656 builds, in that order.

     WIDTH. The Title node is HUG, so `width: max-content` is what reproduces
     it: it measures the wider of the two lines, ~174 for the string above, and
     grows with a longer stone name up to the 342 content box. The strip has no
     fill and the text is left-aligned, so a 342-wide block would paint
     identically -- but the HUG box is what the design actually specifies and it
     is what a measurement of this node should return.

     NOT BUILT, stated rather than faked: the 90 x 40 #27423B r4 `DONE` CTA
     14463:34247. GAPS G-26 -- and it bites hardest here, because in the live
     flow the CHOICE is the dismissal: simple-select.js:2660 sets .active and
     :2679 immediately triggers .modal_close, so a DONE button would never be
     reachable. Making it real needs a JS change to defer that close, not a
     rule in this file. Everything above is the half that has markup. */
  /* THE TITLE AND THE DONE BAR STAY PUT; THE LIST SCROLLS BETWEEN THEM.
     Owner: *"on the BYR flow, gemstone popup, on phone this needs to be done --
     fixed title bar and bottom CTA of done, and the bit in there should scroll,
     so the bottom bar and title are always visible."*

     The scrollport was the WHOLE FLYOUT: `.flyout` is `overflow-y: auto` with a
     `max-height: calc(100% - 37px)`, so once the list is longer than the screen
     the heading and the DONE row scroll away with it. MEASURED at 390 the list
     is 656 in an 807 flyout -- it only fits because this catalogue is short, and
     it stops fitting the moment a gemstone is added.

     So the flyout becomes a column and the LIST becomes the scrollport. The
     unnamed <div> between them is the modal's own content wrapper (it carries no
     class, hence `> div`), and it has to pass the height through or the flex
     chain breaks at it -- `min-height: 0` on both, because a flex item's default
     `min-height: auto` refuses to shrink below its content and the overflow
     never engages. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .flyout {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .flyout > .modal_header {
    flex: 0 0 auto;
  }
  /* `:not(.modal_header)` -- the header is a <div> too, so a bare `> div` turned
     it into a COLUMN as well: MEASURED, the title and the close stacked, the
     header grew 30 -> 54 and the close landed at x183, dead centre. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .flyout > div:not(.modal_header) {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
  }
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .modal-gemstone-selection {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* NO VISIBLE SCROLLBAR. Owner: *"the scrollable slit in between shows a
       scrollbar during scroll -- I don't need that, remove it."* The list still
       scrolls; only its track is hidden. The sticky header and DONE row are what
       tell the shopper there is more, and on a phone the bar is a 2px artefact
       over the tiles rather than a control anyone drags.

       Both syntaxes, because they are different engines: `scrollbar-width` is
       the standard one (Firefox and Chromium 121+), `::-webkit-scrollbar` is
       what older WebKit/Blink reads. */
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .modal-gemstone-selection::-webkit-scrollbar {
    width: 0;
    height: 0;
  }
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_footer {
    flex: 0 0 auto;
  }

  /* THE ROW IS THE TEXT **AND** THE CTA -- 14557:45775 `Frame 1171276611`.
     342 x 42, HORIZONTAL, itemSpacing 40: a 174 x 42 two-line selection run and
     a 90 x 40 DONE button. Only the run was ever built, which is the owner's
     *"where is DONE in the gemstone drawer on phone"*. The <p> becomes the flex
     row the frame draws; the text keeps the `pre-line` treatment on its own
     span, because `white-space` on a flex CONTAINER does not reach the item. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 40px;                     /* itemSpacing 40 */
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    /* No height, for the same reason as the drawer strip: HUG on the text, so
       two lines measure the designed 42 and one line does not leave a void. */
    /* `gemstones` itemSpacing 30 above; the flyout's own 20px padding-bottom is
       the designed space below, so the theme's 16px <p> bottom margin goes. */
    margin: 30px 0 0;
    /* The U+000A between the two runs is a real newline in the text node
       (built with .text(), not innerHTML). Unlike the metal / shape sheets
       #modal-content is not font-size:0, but it does inherit `normal`
       white-space, which collapsed the newline and drew the two lines as one
       17.6px-tall run. */
    white-space: pre-line;
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 16px;
    line-height: 21px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
    text-align: left;
  }
  /* The two text runs, as ONE item of that row. `Frame 1171276611`'s first
     child is 174 wide and HUGs its two lines; `min-width: 0` lets it give way
     before the CTA does, and the newline between the runs is a real U+000A in
     the text node, so the pre-line lives here rather than on the flex row. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_footer_text {
    flex: 0 1 auto;
    min-width: 0;
    white-space: pre-line;
  }

  /* `CTA` 14557:45775 -- 90 x 40, fill #27423B, r4, label DONE 40 x 19 #FAF3ED.
     Identical numbers to the metal/shape sheets' DONE at :883, because it is the
     same control drawn on a different sheet. `flex: 0 0 90px` so the text run
     above is what shrinks on a narrow phone, never the button. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_done {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 90px;
    box-sizing: border-box;
    width: 90px;
    height: 40px;
    padding: 0;
    /* PINNED RIGHT. Both boards put the CTA at the row's trailing edge -- phone
       14557:45775 has it at x276 of a 342 row, desktop 14393:48111 at x1270 of
       1326 -- and `space-between` only delivers that while the text run is
       there. MEASURED with no gemstone picked yet, where the run is collapsed:
       the lone CTA fell to the row's LEFT at x24. An auto start-margin holds the
       trailing edge whether or not the text is drawn. */
    margin: 0 0 0 auto;
    border: 0;
    border-radius: var(--rb-radius-sm);
    background: var(--rb-brand-green);
    overflow: hidden;
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 16px;
    line-height: 19px;
    letter-spacing: var(--rb-ls-tight);
    text-transform: none;
    text-align: center;
    white-space: nowrap;
    color: var(--rb-surface-page);
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
  }
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_done:focus-visible {
    outline: var(--rb-stroke-thick) solid var(--rb-brand-green);
    outline-offset: 2px;
  }

  /* No .active row yet -> both spans empty (the JS will not borrow row 1's
     values). The TEXT collapses, not the row.

     This used to hide the whole `.rb_gem_footer`, which was right while the
     footer was only a line of text -- an empty 42px void above the sheet's
     padding edge is worse than nothing. It is wrong now that the row also
     carries DONE: MEASURED after adding the button, the footer computed
     `display: none` on open and the CTA had a 0 x 0 box, so the control the
     owner asked for was present in the DOM and invisible until a gemstone was
     picked. The board draws the CTA unconditionally, so only the run that has
     nothing to say is collapsed. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_footer:has(.rb_gem_footer_name:empty) .rb_gem_footer_text {
    display: none;
  }

  /* Line 1, the stone name -- styleOverrideTable[28], weight 500. Same
     FoundersGrotesk-Medium gap recorded on the drawer strip above: main.css
     registers only the Regular face, so 500 resolves to Regular today. */
  /* THE TWO RUNS ARE TWO LINES, stated as blocks rather than as a newline
     inside a pre-line run. `Title` 14557:52479 is one text box, 174 x 42 --
     2 x 21 -- carrying two styled runs: styleOverrideTable[28]
     FoundersGrotesk-Medium 500 for the stone name, [27] Regular 400 for
     "Stone: + $580 | 0.5 Carats". Reproducing that with the newline plus
     `white-space: pre-line` MEASURED 63px: the break opened an EMPTY line
     between the two runs, so the block drew three. Widening it to 964px left it
     at 63, which is what ruled out wrapping. Two block lines give exactly 42. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_footer_name,
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_footer_meta {
    display: block;
    white-space: normal;
  }
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_footer_name {
    font-family: var(--rb-font-body);
    font-weight: 500;
    font-size: 16px;
    line-height: 21px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
  }
  /* Line 2, "Stone: + $580 | 0.5 Carats" -- styleOverrideTable[27], the 400
     base. Both spans are empty until a row carries .active, and an empty
     max-content strip collapses to 0 x 42 rather than drawing an empty band. */
  .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .rb_gem_footer_meta {
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 16px;
    line-height: 21px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
  }

  /* Also NOT reproduced: the design's own close x is dead (no interaction);
     ours is not. */


  /* ===========================================================================
     3.  [POPUP] TALK TO GEMOLOGIST -- MOVED OUT OF THIS SHEET
     ---------------------------------------------------------------------------
     The card used to be built here, scoped to `body.ssq-active` and to the
     `:has(section#simple-select-quiz[style*="display: block"])` click-through
     form -- i.e. inside the builder and nowhere else. But the control that
     opens it, `button.contact_link.dsq_cta_link`, is emitted by the SHARED
     diamond-search CTA band, which also renders on /lab-grown-diamonds and the
     other stone archives and on the stone PDP's sticky band. On those two
     surfaces this sheet is not loaded, so the popup fell back to the header's
     dark drawer -- the owner's *"not the current one"*.

     It now lives in components/contact-modal/contact-modal.css, the only sheet
     loaded on all three surfaces, keyed on `#contact_modal_popup.is-gemologist`
     (main.js stamps it from the opening button's `data-contact-variant`) and
     measured against the newer frame 14557:44258, which adds the sub-line and
     the hours footer this copy left unbuilt.

     Nothing is scoped here any more on purpose: two implementations of one card
     in two sheets, with this one loading later and winning inside the drawer,
     is how the drawer and the archive drifted apart in the first place.
     =========================================================================== */

  /* ===========================================================================
     4.  REVIEW STEP -- #ssq_confirmation
     ---------------------------------------------------------------------------
     STYLED BY INFERENCE. There is NO Figma frame for this step on either the
     mobile board (section 14463:32244, 25 frames -- the flow ends at
     1.3 Engraving 14463:35118) or the desktop board (section 14465:38712, 8
     frames). Nothing below is a measurement; every value is either a token from
     simple-select-redesign.css or a type/box value lifted verbatim from a
     NAMED node on an adjacent screen, and each is cited so it can be replaced
     the moment a Review frame exists.

     Borrowed from:
       card + radius       `Setting details` 14463:36327 -- r4, pad 10/9,
                           fill #E4DED8 @0.60
       section heading     sheet titles 14463:36574 -- Canela 300, 20/30, -0.21
       line items          sheet footer 14463:36604 -- Founders 400, 16/21, -0.21,
                           #3E3C39, with the emphasised half at weight 500
       divider             `seperator` 14463:36602 -- #E4DED8 @0.40, w1
       primary CTA         `CONTINUE TO RING SIZE` 14463:33709 -- 346 x 44,
                           #27423B, r4, Founders 400 16/19 -0.21 UPPER #FAF3ED
       perks line          14463:36340 -- Founders 400, 12/19, -0.21, CENTER,
                           #3E3C39

     `display` is not set on #ssq_confirmation or on any slide: simple-select.js
     drives those through the .active class on .simple-select-slide.
     =========================================================================== */

  #simple-select-quiz #ssq_confirmation {
    margin: 0;
    padding: 0 22px;                 /* the sheet-wide 22px gutter (_stone.css) */
    box-sizing: border-box;
    text-align: left;
    font-family: var(--rb-font-body);
    color: var(--rb-text-primary);
  }

  /* --- price summary card -------------------------------------------------- */
  #simple-select-quiz #ssq_confirmation .simple-select-subtotals {
    box-sizing: border-box;
    margin: 0 0 20px;                /* base: 30px 0 */
    padding: 10px 9px;
    background: rgba(228, 222, 216, 0.6000000238418579);
    border-radius: var(--rb-radius-sm);
  }
  #simple-select-quiz #ssq_confirmation .simple-select-subtotals h3 {
    margin: 0 0 10px;
    font-family: var(--rb-font-display);
    font-weight: 300;
    font-size: 20px;
    line-height: 30px;
    letter-spacing: var(--rb-ls-tight);
    text-transform: uppercase;
    color: var(--rb-text-primary);
  }
  #simple-select-quiz #ssq_confirmation p.selected_setting_info,
  #simple-select-quiz #ssq_confirmation p.selected_stone_info {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    margin: 0 0 2px;                 /* `Setting details` itemSpacing 2 */
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 16px;
    line-height: 21px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
  }
  /* The two line LABELS take the Ring-Details accordion's expanded-row label
     tier -- Founders Grotesk 400 14/19, #3E3C39 (MASTER 385/386, traced from
     14463:36338).  The row above sets 16/21 for the whole line, which is two
     type tiers up from the row the assertion traces to; only the label spans
     are stepped back, because no assertion gives the mobile price a size and
     inventing one is not on. */
  #simple-select-quiz #ssq_confirmation .selected_setting_title,
  #simple-select-quiz #ssq_confirmation .selected_stone_title {
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 14px;
    line-height: 19px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
  }

  #simple-select-quiz #ssq_confirmation .totals {
    margin-top: 10px;
    padding-top: 10px;
    /* base: 1px dashed var(--pearl-dark). The board's only sheet divider is
       `seperator` 14463:36602: solid #E4DED8 at paint opacity 0.40, weight 1. */
    border-top: var(--rb-stroke) solid rgba(228, 222, 216, 0.4000000059604645);
  }
  #simple-select-quiz #ssq_confirmation p.ssq_total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    margin: 0;
    font-family: var(--rb-font-body);
    font-weight: 500;                /* the emphasised half of 14463:36604 */
    font-size: 16px;
    line-height: 21px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-primary);
  }

  /* --- affirm + shipping strap + CTA --------------------------------------- */
  #simple-select-quiz #ssq_confirmation .simple-select-slide-content {
    padding: 0;
    text-align: center;
  }
  /* .affirm-as-low-as-pending is where Affirm injects .affirm-tag and
     #learn-more. It is on the never-hide list and keeps a full box; only type
     is set. */
  #simple-select-quiz #ssq_confirmation .affirm-as-low-as-pending {
    margin: 0 0 8px;
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 14px;
    line-height: 19px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
  }
  #simple-select-quiz #ssq_confirmation .simple-select-slide-content > p {
    margin: 0 0 16px;
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 12px;
    line-height: 19px;
    letter-spacing: var(--rb-ls-tight);
    color: var(--rb-text-secondary);
  }
  #simple-select-quiz #ssq_confirmation .ssq_add_to_cart {
    display: flex;
    justify-content: center;
    margin: 0;
  }
  #simple-select-quiz #ssq_confirmation a.ssq_finale {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    box-sizing: border-box;
    /* was width: 346px -- the design is authored at 390, so a fixed 346 overflowed every narrower phone. min() keeps 346 at 390 and shrinks below. */
    width: min(346px, calc(100vw - 44px));
    max-width: 100%;
    height: 44px;
    padding: 0;
    background: var(--rb-brand-green);
    border: 0;
    border-radius: var(--rb-radius-sm);
    font-family: var(--rb-font-body);
    font-weight: 400;
    font-size: 16px;
    line-height: 19px;
    letter-spacing: var(--rb-ls-tight);
    text-transform: uppercase;
    text-decoration: none;
    color: var(--rb-surface-page);
  }
  #simple-select-quiz #ssq_confirmation a.ssq_finale span {
    display: inline-flex;
    align-items: center;
    margin: 0;
  }
  #simple-select-quiz #ssq_confirmation a.ssq_finale svg {
    width: 16px;
    height: 16px;
  }
  #simple-select-quiz #ssq_confirmation a.ssq_finale svg path {
    stroke: var(--rb-surface-page);
  }


  /* ===========================================================================
     5.  MOTION PREFERENCE
     Figma specifies SMART_ANIMATE transitions of 300-400ms; users who ask for
     reduced motion get the end state with no travel. The sheets still appear --
     only the movement is dropped.
     =========================================================================== */
  @media (prefers-reduced-motion: reduce) {
    #simple-select-quiz .quiz-image .metal_dropdown_ssq_options,
    #simple-select-quiz .quiz-image .shape_dropdown_ssq_options,
    .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection),
    .popup-modal-container.gemstone_selection_modal:has(.modal-gemstone-selection) .flyout {
      animation: none;
    }
    /* The metal/shape sheets are a transition now, not a keyframe animation, so
       `animation: none` above no longer reaches their slide. Zero DURATION
       rather than `transition: none`: simple-select-redesign.js waits for
       `transitionend` before it calls .hide(), and a 0s transition still fires
       that event, so the close path keeps working with no travel. */
    #simple-select-quiz .quiz-image .metal_dropdown_ssq_options,
    #simple-select-quiz .quiz-image .shape_dropdown_ssq_options,
    #simple-select-quiz .rb_drawer_scrim {
      transition-duration: 0s;
    }
  }

}

/* ===========================================================================
   [Flow 3] THE PAGE BEHIND AN OPEN SHEET DOES NOT MOVE
   ---------------------------------------------------------------------------
   Owner: *"when I click on stone or metal a popup happens -- then the
   background is moving."*

   `position: fixed`, not `overflow: hidden`: iOS Safari honours the first and
   ignores the second, and this was reported on a phone. The scroll offset is
   parked on `top` by simple-select-redesign.js (rbLockPage) and restored when
   the sheet closes, because fixing the body resets the document scroll to 0.

   Not scoped to a width -- a sheet dims the page at every size, and a scrim
   that can be scrolled behind is wrong at all of them.
   =========================================================================== */
body.rb-page-locked {
    position: fixed;
    left: 0;
    right: 0;
    width: 100%;
    overflow: hidden;

}
