/* ==========================================================================
   ROOM SCENE
   --------------------------------------------------------------------------
   Loaded only on pages carrying [sage_room_scene] (see sage_designer_assets()
   in functions.php).

   Two theme rules restated here, as in designer.css:
   - Nothing may depend on .sage-sec / .sage-btn / .sage-grid-*. Those live in
     homepage.css, gated to the front page, so an interior page using them
     renders unstyled.
   - #sageMain img { max-width:100% } is an ID selector and beats any class
     chain, so image rules are duplicated behind #sageMain.

   The panel is dark glass on purpose. It sits over a photograph: a pale card
   reads as browser chrome dropped onto the image, a dark translucent surface
   reads as part of the scene.
   ========================================================================== */

.sage-rs {
  /* The bar and the zoom cluster are absolutely positioned over the
     photograph, so this is their containing block. */
  position: relative;
  --rs-glass: rgba(22, 24, 20, 0.82);
  --rs-glass-2: rgba(38, 41, 34, 0.9);
  --rs-hair: rgba(255, 255, 255, 0.16);
  --rs-ink: rgba(255, 255, 255, 0.94);
  --rs-ink-dim: rgba(255, 255, 255, 0.62);
}

/* --- top bar -------------------------------------------------------------- */

/* The session actions ride on the photograph rather than sitting in a band
   above it -- CNC's arrangement, and the reason their tool reads as an app
   while a toolbar-over-a-picture reads as a web page. Dark glass for the same
   reason the panels use it: a pale control over a photo looks like browser
   chrome dropped on the image. */
.sage-rs-bar {
  position: absolute;
  top: 0.7rem;
  left: 0.7rem;
  right: 0.7rem;
  z-index: 6;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.6rem;
  pointer-events: none;
}
.sage-rs-tools { display: flex; align-items: center; gap: 0.4rem; pointer-events: auto; }
.sage-rs-tools--right { flex-wrap: nowrap; }

.sage-rs-collections { display: flex; gap: 0.5rem; }

/* A collection is a different room, not a palette filter, so the control shows
   the room rather than naming it. */
.sage-rs-coll {
  position: relative;
  width: 6.5rem;
  padding: 0;
  background: none;
  border: 1px solid var(--greige);
  border-radius: var(--radius-sm);
  overflow: hidden;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.sage-rs-coll img,
#sageMain .sage-rs-coll img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}
.sage-rs-coll-name {
  display: block;
  padding: 0.32rem 0.4rem;
  font-family: var(--font-body);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--olive-900);
  background: var(--bone);
}
.sage-rs-coll:hover { border-color: var(--olive-500); }
.sage-rs-coll:focus-visible { outline: 2px solid var(--olive-500); outline-offset: 2px; }
.sage-rs-coll.is-on { border-color: var(--olive-800); box-shadow: 0 0 0 1px var(--olive-800); }
.sage-rs-coll.is-on .sage-rs-coll-name { background: var(--olive-800); color: var(--bone); }

.sage-rs-tool {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  min-height: 2.1rem;
  padding: 0 0.85rem;
  background: var(--rs-glass);
  backdrop-filter: blur(14px) saturate(1.1);
  border: 1px solid var(--rs-hair);
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  letter-spacing: 0.02em;
  color: var(--rs-ink);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.sage-rs-tool--icon {
  width: 2.1rem;
  padding: 0;
  display: grid;
  place-items: center;
  font-size: 1rem;
  line-height: 1;
}
.sage-rs-tool--icon svg { width: 1rem; height: 1rem; }
.sage-rs-tool:hover { border-color: rgba(255, 255, 255, 0.4); background: var(--rs-glass-2); }
.sage-rs-tool:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* The one control that converts. Champagne on the dark glass rather than
   another grey pill: gold is legible on dark (8.19:1) and nowhere else. */
.sage-rs-tool--cta {
  background: var(--olive-800);
  border-color: transparent;
  color: var(--gold-100, #FEEBAA);
  font-weight: 600;
}
.sage-rs-tool--cta:hover { background: var(--olive-700, #5A5F33); border-color: transparent; }

/* Two labels, one shown at a time: "Start a new design" does not fit beside
   anything else on a 390px bar. */
.sage-rs-lbl-narrow { display: none; }

.sage-rs-caret { width: 0.85rem; height: 0.85rem; opacity: 0.7; }
[aria-expanded="true"] > .sage-rs-caret { transform: rotate(180deg); }

/* Zoom and full screen, riding the photograph bottom-right. */
.sage-rs-viewtools {
  position: absolute;
  right: 0.9rem;
  bottom: 0.9rem;
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 0.1rem;
  padding: 0.3rem;
  border-radius: var(--radius-full);
  background: var(--rs-glass);
  backdrop-filter: blur(14px) saturate(1.1);
  border: 1px solid var(--rs-hair);
}
/* The full-screen control is a different kind of thing from zoom, so a hairline
   separates them rather than leaving four identical circles in a row.

   The rule is on a spacer pseudo-element, not on the button. Putting a
   border-left and a squared-off border-radius on the button itself made it a
   different shape and width from its neighbours, so its pressed state was a
   wide rectangle that overran both the divider and the pill's rounded end.
   Every button is now the same circle; the line is drawn between them. */
/* Three groups, two hairlines: zoom | room actions | full screen. */
.sage-rs-viewtools .sage-rs-vt[data-act="reset"],
.sage-rs-viewtools .sage-rs-vt:last-child { margin-left: 0.3rem; }
.sage-rs-viewtools .sage-rs-vt[data-act="reset"]::before,
.sage-rs-viewtools .sage-rs-vt:last-child::before {
  content: "";
  position: absolute;
  left: -0.3rem;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 1.1rem;
  background: var(--rs-hair);
}
.sage-rs-viewtools .sage-rs-vt[data-act="reset"],
.sage-rs-viewtools .sage-rs-vt:last-child { position: relative; }
.sage-rs-vt {
  width: 1.95rem;
  height: 1.95rem;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  border-radius: 50%;
  color: var(--rs-ink-dim);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
  /* Flatsome styles every <button>: it was applying min-height 38.8px and
     0 18.6px padding here, so the control ignored its own width/height, came
     out wider than it was tall, and stood taller than the readout beside it.
     Height alone cannot win against a min-height. */
  min-height: 0;
  min-width: 0;
  padding: 0;
  margin: 0;
  line-height: 1;
  box-shadow: none;
}
/* Hover, press and focus all stay inside the same circle. Flatsome paints its
   own square background on :active and :focus, which showed as a grey block
   overflowing the pill's rounded end and cutting across the divider -- so those
   states are restated here rather than left to the parent theme. */
.sage-rs-vt:hover,
.sage-rs-vt:active,
.sage-rs-vt:focus { color: var(--rs-ink); }
.sage-rs-vt:hover { background: rgba(255, 255, 255, 0.14); }
.sage-rs-vt,
.sage-rs-vt:active,
.sage-rs-vt:focus,
#sageMain .sage-rs-vt,
#sageMain .sage-rs-vt:active,
#sageMain .sage-rs-vt:focus {
  /* Flatsome sets a 4px radius on every button and wins on specificity, which
     left a visibly square press state inside a round pill. */
  border-radius: 50% !important;
}
.sage-rs-vt:active,
.sage-rs-vt:focus,
#sageMain .sage-rs-vt:active,
#sageMain .sage-rs-vt:focus {
  background: rgba(255, 255, 255, 0.2);
  box-shadow: none;
  outline: 0;
  transform: none;
}
.sage-rs-vt:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.sage-rs-vt svg { width: 1rem; height: 1rem; }
.sage-rs-zoomv {
  min-width: 2.4rem;
  text-align: center;
  font-family: var(--font-body);
  /* Tabular figures so the readout does not shuffle sideways between 100% and
     125% while you are holding the button down. */
  font-variant-numeric: tabular-nums;
  font-size: 0.6875rem;
  letter-spacing: 0.02em;
  color: var(--rs-ink-dim);
  /* The readout is a bare span between two icon buttons. It has to be centred
     against them, and the buttons are not one fixed size -- 1.95rem here, 2rem
     on a phone, 1.85rem in landscape.

     align-self: stretch does not work: the buttons set an explicit height and
     so do not stretch themselves, which left the span taller than the row and
     inflated the whole pill. Inheriting the button height instead keeps the two
     boxes identical at every breakpoint, and a centred grid levels the digits
     inside it. */
  display: grid;
  place-items: center;
  height: 1.95rem;
  line-height: 1;
}

/* The marker toggle swaps eye for eye-with-slash rather than changing colour:
   a control that hides something should say which state it is in. */
.sage-rs-vt--spots .sage-rs-eye-off { display: none; }
.sage-rs-vt--spots[aria-pressed="false"] .sage-rs-eye-on { display: none; }
.sage-rs-vt--spots[aria-pressed="false"] .sage-rs-eye-off { display: block; }

/* --- layout --------------------------------------------------------------- */

/* The kitchen takes the whole width. This was a 1.9fr / 1fr split with a
   column of text beside the photograph -- an instruction paragraph and a list
   of the finishes already visible in the picture. Both are gone, so there is
   no second column to lay out. */
.sage-rs-body { display: block; }

/* Not sticky. The scene was pinned below the header so it stayed in view while
   the column beside it scrolled -- there is no column now, and nothing to
   scroll past. */
.sage-rs-stage { position: relative; z-index: 5; }
.sage-rs-room[hidden] { display: none; }

/* The scene owns its own clipping. The zoom viewport clips the photograph; the
   rail and the panels sit above it and are never scaled by zoom. */
/* No overflow clip here. .sage-rs-view already clips the photograph, and
   clipping at this level cut the left rail in half where it floats over the
   image edge. */
.sage-rs-scene {
  position: relative;
  border-radius: var(--radius-md);
  background: #14150F;
  box-shadow: var(--shadow-md);
}

.sage-rs-view {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-md);
}
/* Zoom is one transform on this element, so the markers ride the same transform
   as the photograph and cannot drift away from what they point at. */
.sage-rs-pan {
  position: relative;
  transform-origin: 50% 50%;
  transition: transform var(--dur-base) var(--ease-out);
  will-change: transform;
}

.sage-rs-frame { position: relative; display: block; }
.sage-rs-bg,
#sageMain .sage-rs-bg { display: block; width: 100%; height: auto; }
.sage-rs-layer,
#sageMain .sage-rs-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

/* --- full screen ---------------------------------------------------------- */

/* The kitchen takes over the window. Fixed positioning rather than the
   Fullscreen API: it behaves identically on iOS Safari, which refuses
   fullscreen on anything but a <video>, and it keeps the page's own theme
   rather than a black host frame. */
.sage-rs.is-full {
  position: fixed;
  inset: 0;
  z-index: 9999;
  margin: 0;
  padding: clamp(0.75rem, 2vw, 1.25rem);
  background: #14150F;
  overflow: auto;
  display: flex;
  flex-direction: column;
}
.sage-rs.is-full .sage-rs-body { grid-template-columns: minmax(0, 1fr); flex: 1; min-height: 0; }
.sage-rs.is-full .sage-rs-panel { display: none; }
.sage-rs.is-full .sage-rs-stage { position: static; height: 100%; }
.sage-rs.is-full .sage-rs-room,
.sage-rs.is-full .sage-rs-scene { height: 100%; }
.sage-rs.is-full .sage-rs-view { height: 100%; display: grid; place-items: center; }
.sage-rs.is-full .sage-rs-bg,
#sageMain .sage-rs.is-full .sage-rs-bg { max-height: 88vh; width: auto; max-width: 100%; }
/* On dark ground the bar's controls have to invert or they vanish. */
.sage-rs.is-full .sage-rs-tool { color: var(--rs-ink); border-color: var(--rs-hair); }
.sage-rs.is-full .sage-rs-tool:hover { background: rgba(255, 255, 255, 0.1); }
.sage-rs.is-full .sage-rs-zoomv { color: var(--rs-ink-dim); }
.sage-rs.is-full .sage-rs-coll { border-color: var(--rs-hair); }
.sage-rs.is-full .sage-rs-coll-name { background: var(--rs-glass-2); color: var(--rs-ink); }
.sage-rs.is-full .sage-rs-coll.is-on .sage-rs-coll-name { background: var(--olive-800); }
body.sage-rs-locked { overflow: hidden; }

/* --- zone rail ------------------------------------------------------------ */

/* Always visible, in a fixed order. The markers are discoverable; the rail is
   reliable, and it is how someone who closed a panel gets back. */
.sage-rs-rail {
  position: absolute;
  /* Inside the photograph's own edge, not straddling it: the rail floats on
     the image the way CNC's does, rather than looking cut into the frame. */
  left: 1rem;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  /* Even padding all round. It was 0.3rem at the sides against a 2.3rem
     button, so a selected item's highlight ran to the rail's own edge and
     read as clipped. */
  padding: 0.45rem;
  border-radius: var(--radius-full);
  background: var(--rs-glass);
  backdrop-filter: blur(14px);
  border: 1px solid var(--rs-hair);
}
.sage-rs-railbtn {
  position: relative;
  width: 2.3rem;
  height: 2.3rem;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  /* A circle, not a stadium: inside a pill rail, radius-full on a square
     button reads as a rounded rectangle jammed against its neighbours. */
  border-radius: 50%;
  color: var(--rs-ink-dim);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.sage-rs-railbtn svg { width: 1.15rem; height: 1.15rem; }
.sage-rs-railbtn:hover { color: var(--rs-ink); background: rgba(255, 255, 255, 0.12); }
.sage-rs-railbtn:focus-visible { outline: 2px solid #fff; outline-offset: -2px; }
.sage-rs-railbtn.is-active { background: var(--olive-700); color: #fff; }

.sage-rs-railtip {
  position: absolute;
  left: calc(100% + 0.5rem);
  top: 50%;
  transform: translateY(-50%);
  padding: 0.26rem 0.6rem;
  border-radius: var(--radius-sm);
  background: var(--rs-glass);
  border: 1px solid var(--rs-hair);
  color: var(--rs-ink);
  font-family: var(--font-body);
  font-size: 0.625rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.sage-rs-railbtn:hover .sage-rs-railtip,
.sage-rs-railbtn:focus-visible .sage-rs-railtip { opacity: 1; }

/* --- markers -------------------------------------------------------------- */

/* Markers off: the room reads as a photograph. The rail below is unaffected,
   so every zone is still one tap away. */
.sage-rs.is-nospots .sage-rs-spot { opacity: 0; pointer-events: none; }

.sage-rs-spot {
  position: absolute;
  transform: translate(-50%, -50%);
  transition: opacity var(--dur-fast) var(--ease-out);
  background: none;
  border: 0;
  /* Padding, not a bigger dot: the marker stays small enough not to hide the
     cabinet it points at while the button clears the 44px touch minimum. */
  padding: 0.4rem;
  cursor: pointer;
  display: grid;
  place-items: center;
  z-index: 2;
}
.sage-rs-spot-dot {
  position: relative;
  width: 2.15rem;
  height: 2.15rem;
  border-radius: var(--radius-full);
  border: 2px solid rgba(255, 255, 255, 0.95);
  background: rgba(28, 28, 24, 0.34);
  backdrop-filter: blur(2px);
  box-shadow: 0 2px 10px rgba(28, 28, 24, 0.4);
  display: grid;
  place-items: center;
  transition: background var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
/* The plus is two bars rather than a glyph, so it stays optically centred at
   any size and needs no icon font. */
.sage-rs-spot-dot::before,
.sage-rs-spot-dot::after {
  content: "";
  position: absolute;
  background: #fff;
  border-radius: 1px;
}
.sage-rs-spot-dot::before { width: 0.9rem; height: 2px; }
.sage-rs-spot-dot::after { width: 2px; height: 0.9rem; }

.sage-rs-spot:hover .sage-rs-spot-dot,
.sage-rs-spot:focus-visible .sage-rs-spot-dot {
  background: var(--olive-800);
  transform: scale(1.12);
}
.sage-rs-spot:focus-visible { outline: none; }
.sage-rs-spot:focus-visible .sage-rs-spot-dot { outline: 2px solid #fff; outline-offset: 3px; }
.sage-rs-spot.is-active .sage-rs-spot-dot { background: var(--olive-800); border-color: var(--olive-800); }

.sage-rs-spot-tip {
  position: absolute;
  bottom: calc(100% + 0.3rem);
  left: 50%;
  transform: translateX(-50%);
  padding: 0.26rem 0.6rem;
  border-radius: var(--radius-sm);
  background: var(--rs-glass);
  color: var(--rs-ink);
  font-size: 0.625rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.sage-rs-spot:hover .sage-rs-spot-tip,
.sage-rs-spot:focus-visible .sage-rs-spot-tip { opacity: 1; }

/* --- the panel ------------------------------------------------------------ */

/* Anchored to the scene's left edge, clear of the rail, and it opens in the
   same place every time: a card that moves to wherever you clicked makes the
   eye re-find the controls on every zone. */
.sage-rs-pop {
  position: absolute;
  left: 3.6rem;
  top: 50%;
  transform: translateY(-50%) scale(0.97);
  z-index: 4;
  /* Wider than it was. At 30rem the picker column came out 224px, which put
     four swatch columns at 33px each -- narrower than the words underneath
     them. The scene is 1300px; the panel can afford this. */
  width: min(40rem, calc(100% - 5rem));
  max-height: calc(100% - 1.4rem);
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  /* The row has to be bounded too, not just the panel. max-height on the panel
     clips, but the implicit row still sizes to content -- so the row grew to
     949px, the scroll area inside it resolved its own 100% against that, and
     nothing ever scrolled: the picker simply ran past the bottom edge and was
     cut off. minmax(0, 100%) makes the row track the panel instead. */
  grid-template-rows: minmax(0, 100%);
  border-radius: var(--radius-md);
  background: var(--rs-glass);
  backdrop-filter: blur(22px) saturate(1.1);
  border: 1px solid var(--rs-hair);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  color: var(--rs-ink);
  opacity: 0;
  pointer-events: none;
  overflow: hidden;
  transition: opacity var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
/* The scrim. Desktop does not need it -- the panel is anchored to one side and
   the room stays legible beside it -- but the element has to exist here so the
   mobile block only has to change opacity, not invent a stacking order. */
.sage-rs-scrim {
  position: absolute;
  inset: 0;
  z-index: 3;              /* under the panel (4), over the rail and markers */
  background: rgba(14, 15, 12, 0.55);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.sage-rs-pop[hidden] { display: none; }
.sage-rs-pop.is-open { opacity: 1; pointer-events: auto; transform: translateY(-50%) scale(1); }
/* Surface zones have no door preview, so they need far less width. */
.sage-rs-pop--plain { grid-template-columns: minmax(0, 1fr); width: min(20rem, calc(100% - 5rem)); }

/* The countertop panel is a slab picker: 96 colours in a single column, and
   each swatch is a wide sheet rather than a square door. It keeps the full
   panel width and drops the preview column, which has nothing to show that the
   grid is not already showing larger. */
.sage-rs-pop[data-zone="Countertop"] { grid-template-columns: minmax(0, 1fr); }
.sage-rs-pop[data-zone="Countertop"] .sage-rs-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.sage-rs-pop-main {
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* Bounded, not just min-height:0. As a grid item this stretches to its
     content by default, so .sage-rs-pop-scroll inside it never had a height to
     scroll against -- it grew to 840px inside a 442px panel and simply ran off
     the bottom of the kitchen. The cap is what makes the overflow scroll. */
  max-height: 100%;
  padding: 0.95rem 1rem 1rem;
}
.sage-rs-pop-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex: none;
  margin-bottom: 0.75rem;
}
.sage-rs-pop-t {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1.05rem;
  font-weight: 400;
  letter-spacing: 0.01em;
  color: var(--rs-ink);
}
.sage-rs-pop-x {
  margin-left: auto;
  width: 1.8rem;
  height: 1.8rem;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  border-radius: var(--radius-full);
  color: var(--rs-ink-dim);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.sage-rs-pop-x svg { width: 0.95rem; height: 0.95rem; }
.sage-rs-pop-x:hover { background: rgba(255, 255, 255, 0.12); color: var(--rs-ink); }
.sage-rs-pop-x:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.sage-rs-pop-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.28) transparent;
}
.sage-rs-pop-scroll::-webkit-scrollbar { width: 6px; }
.sage-rs-pop-scroll::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.28);
  border-radius: 3px;
}

.sage-rs-lbl {
  margin: 0 0 0.5rem;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--rs-ink-dim);
}
.sage-rs-doors + .sage-rs-lbl,
.sage-rs-grid + .sage-rs-lbl { margin-top: 1rem; }

/* Door style tiles. The profile is what distinguishes a series, so the tile is
   the door itself rather than its name in a dropdown. */
.sage-rs-doors {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  /* Row gap is larger than the column gap: the caption is now two lines --
     the door style over CNC's name for it -- and a uniform gap let the
     second line of one row touch the tile below it. */
  gap: 0.85rem 0.45rem;
  margin-bottom: 1rem;
  align-items: start;
}
.sage-rs-door {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.sage-rs-door img,
#sageMain .sage-rs-door img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  object-position: center 62%;
  border-radius: var(--radius-sm);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.18);
  transition: box-shadow var(--dur-fast) var(--ease-out);
}
.sage-rs-door:hover img { box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.5); }
.sage-rs-door.is-on img { box-shadow: 0 0 0 2px var(--gold-300); }
.sage-rs-door:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.sage-rs-door-n {
  display: block;
  margin-top: 0.25rem;
  /* Three tiles across a 30rem panel leaves ~5.5rem each, and "Mitered Flat
     Panel" does not fit that on one line. Slightly tighter type and leading so
     a two-word style sits on two lines rather than three, and the tiles below
     stay on a common baseline. */
  font-size: 0.5625rem;
  line-height: 1.25;
  letter-spacing: 0.02em;
  color: var(--rs-ink-dim);
}
.sage-rs-door.is-on .sage-rs-door-n { color: var(--rs-ink); font-weight: 600; }

/* Quartz slabs, not cabinet doors. A door photo is square and wants its lower
   half; a slab is a wide sheet whose whole point is the veining running across
   it, so it is shown letterboxed and centred instead of cropped to a square. */
.sage-rs-sw-img--slab,
#sageMain .sage-rs-sw-img--slab {
  aspect-ratio: 16 / 9;
  object-position: center center;
}

/* CNC's own name for the line, under the style the customer searched for.
   "Milano" means nothing to a homeowner; "Slab" does. But the CNC name has to
   stay visible, because it is what the quote and CNC's order paperwork say --
   dropping it would leave the customer reading a word on screen they will never
   see again. Dimmer and smaller: present for reference, not competing. */
.sage-rs-door-c {
  display: block;
  /* Set apart from the style above it, or "WIDE SHAKER" over "ELEGANT" reads as
     one three-line phrase rather than a name and its manufacturer's label. */
  margin-top: 0.15rem;
  font-size: 0.5rem;
  line-height: 1.2;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--rs-ink-dim);
  opacity: 0.5;
}
.sage-rs-door.is-on .sage-rs-door-c { opacity: 0.85; }

/* Standard / Plus. A price tier, not a door style -- CNC show one "Elegant" and
   split its colours, which is why these are tabs and not more tiles. */
.sage-rs-tiers {
  display: inline-flex;
  gap: 0.25rem;
  padding: 0.2rem;
  margin-bottom: 0.75rem;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.08);
}
.sage-rs-tier {
  padding: 0.28rem 0.85rem;
  background: none;
  border: 0;
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--rs-ink-dim);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.sage-rs-tier:hover { color: var(--rs-ink); }
.sage-rs-tier.is-on { background: rgba(255, 255, 255, 0.92); color: #1C1C18; }
.sage-rs-tier:focus-visible,
.sage-rs-group:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Countertop filters. Same pill language as the tier tabs, but these wrap:
   MSI's groupings are words like "Marble - Dramatic Veins", not "Standard",
   and there are seven of them. */
.sage-rs-groups {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-bottom: 0.75rem;
}
.sage-rs-group {
  /* Tight enough that five chips fit two rows rather than five, which is what
     pushed the slabs below the fold. */
  padding: 0.26rem 0.6rem;
  white-space: nowrap;
  background: rgba(255, 255, 255, 0.08);
  border: 0;
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  font-size: 0.5875rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--rs-ink-dim);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.sage-rs-group:hover { color: var(--rs-ink); background: rgba(255, 255, 255, 0.14); }
.sage-rs-group.is-on { background: rgba(255, 255, 255, 0.92); color: #1C1C18; }
.sage-rs-tier:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }
.sage-rs-tier[hidden] { display: none; }
.sage-rs-tiers[hidden] { display: none; }

.sage-rs-grid {
  display: grid;
  /* Three columns, not four. At four the cell was 33px wide inside this panel
     while a name like "Evergreen" needs about 70 -- so every label ran well
     past its own swatch and sat against its neighbour's, which is what made
     "Evergreen" and "Linen" read as one word. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-auto-rows: max-content;
  /* Row gap wider than the column gap, and the tiles stretch to a common
     height. Without both, a two-line name like "Adirondack Blue" pushed its
     neighbour's label up alongside it and the two ran together --
     "EVERGREEN" and "LINEN" reading as one word. */
  gap: 0.9rem 0.5rem;
  align-items: stretch;
}
/* The swatch pins to the top of its cell so every image in a row lines up
   however long the names below them run. */
.sage-rs-grid .sage-rs-sw {
  display: flex;
  flex-direction: column;
}
.sage-rs-grid .sage-rs-sw-name { margin-top: auto; padding-top: 0.24rem; }
/* A zone with no swatch art (appliances) stays as labelled chips. Floor and
   backsplash carry swatches cut from the room render, so they take the image
   grid above, three across inside the narrow --plain panel. */
.sage-rs-grid--text { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.sage-rs-sw {
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--font-body);
  text-align: left;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.sage-rs-sw:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.sage-rs-sw[hidden] { display: none; }

/* The finish itself, not its name. A cabinet colour is grain and sheen and the
   way a raised panel catches light; a word conveys none of that. */
.sage-rs-sw-img,
#sageMain .sage-rs-sw-img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  object-position: center 62%;   /* the door panel, below the drawer seam */
  border-radius: var(--radius-sm);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
  transition: box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.sage-rs-sw:hover .sage-rs-sw-img { box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.55); transform: translateY(-1px); }
.sage-rs-sw.is-sel .sage-rs-sw-img { box-shadow: 0 0 0 2px var(--gold-300); }

.sage-rs-sw-name {
  display: block;
  margin-top: 0.24rem;
  font-size: 0.5625rem;
  line-height: 1.3;
  letter-spacing: 0.02em;
  color: var(--rs-ink-dim);
}
.sage-rs-sw.is-sel .sage-rs-sw-name { color: var(--rs-ink); font-weight: 600; }

/* Text chips for the surface zones. */
.sage-rs-grid--text .sage-rs-sw {
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--rs-hair);
  border-radius: var(--radius-sm);
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.sage-rs-grid--text .sage-rs-sw:hover { border-color: rgba(255, 255, 255, 0.45); }
.sage-rs-grid--text .sage-rs-sw.is-sel { background: rgba(255, 255, 255, 0.92); border-color: transparent; }
.sage-rs-grid--text .sage-rs-sw.is-sel .sage-rs-sw-name { color: #1C1C18; }
.sage-rs-grid--text .sage-rs-sw-name { margin-top: 0; }

/* --- preview column ------------------------------------------------------- */

/* The large door and its name. This is what makes the panel read as considered
   rather than as a form -- the swatch grid answers "which", this answers "what
   did I just choose". */
.sage-rs-pop-side {
  display: flex;
  flex-direction: column;
  padding: 0.95rem 1rem 1rem;
  border-left: 1px solid var(--rs-hair);
  background: rgba(0, 0, 0, 0.18);
  min-height: 0;
}
.sage-rs-preview {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  place-items: center;
  margin-bottom: 0.7rem;
}
.sage-rs-preview-img,
#sageMain .sage-rs-preview-img {
  display: block;
  max-width: 100%;
  max-height: 13rem;
  width: auto;
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.14);
}
.sage-rs-preview-n {
  margin: 0 0 0.3rem;
  font-family: var(--font-heading);
  font-size: 1.05rem;
  line-height: 1.25;
  color: var(--rs-ink);
}
.sage-rs-preview-s {
  margin: 0;
  font-size: 0.5875rem;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--rs-ink-dim);
}
.sage-rs-chipm {
  display: inline-block;
  margin-left: 0.3rem;
  padding: 0.14rem 0.5rem;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.14);
  color: var(--rs-ink);
  font-weight: 600;
}

/* Apply-to-all switch. */
.sage-rs-all {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-top: 0.9rem;
  cursor: pointer;
  font-size: 0.625rem;
  letter-spacing: 0.02em;
  color: var(--rs-ink-dim);
}
.sage-rs-all-in {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.sage-rs-all-tr {
  flex: none;
  position: relative;
  width: 2.1rem;
  height: 1.15rem;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.2);
  transition: background var(--dur-fast) var(--ease-out);
}
.sage-rs-all-tr::after {
  content: "";
  position: absolute;
  top: 0.15rem;
  left: 0.15rem;
  width: 0.85rem;
  height: 0.85rem;
  border-radius: var(--radius-full);
  background: #fff;
  transition: transform var(--dur-fast) var(--ease-out);
}
.sage-rs-all-in:checked + .sage-rs-all-tr { background: var(--olive-600); }
.sage-rs-all-in:checked + .sage-rs-all-tr::after { transform: translateX(0.95rem); }
.sage-rs-all-in:focus-visible + .sage-rs-all-tr { outline: 2px solid #fff; outline-offset: 2px; }
.sage-rs-all:hover .sage-rs-all-t { color: var(--rs-ink); }

/* --- summary dropdown ----------------------------------------------------- */

/* Was a permanent column beside the kitchen; now a panel that drops from the
   Summary button. Same content -- every zone, its finish, and a click target
   back into that zone -- but only when asked for. */
.sage-rs-sumwrap { position: relative; pointer-events: auto; }

.sage-rs-summary {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 7;
  width: min(22rem, calc(100vw - 2.8rem));
  max-height: min(26rem, 60vh);
  overflow-y: auto;
  margin: 0;
  padding: 0.4rem 0.9rem 0.7rem;
  border-radius: var(--radius-md);
  background: var(--rs-glass);
  backdrop-filter: blur(22px) saturate(1.1);
  border: 1px solid var(--rs-hair);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  color: var(--rs-ink);
}
.sage-rs-summary[hidden] { display: none; }

.sage-rs-sum-row {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.sage-rs-sum-row:last-child { border-bottom: 0; }
.sage-rs-sum-row dt {
  flex: none;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--rs-ink-dim);
}
.sage-rs-sum-row dd { margin: 0 0 0 auto; text-align: right; }
.sage-rs-sum-btn {
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  color: var(--rs-ink);
  cursor: pointer;
  text-align: right;
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-fast) var(--ease-out);
}
.sage-rs-sum-btn:hover { border-bottom-color: rgba(255, 255, 255, 0.5); }
.sage-rs-sum-btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.sage-rs-cta { margin-top: 1.5rem; }

/* .sage-btn lives in homepage.css, gated to the front page, so it is restated
   here -- the same trap the dealer row and the designer CTA hit. */
.sage-rs-cta .sage-btn {
  display: inline-block;
  padding: 0.95rem 2.1rem;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.sage-rs-cta .sage-btn-primary {
  background: var(--olive-800);
  color: var(--bone);
  border: 1px solid var(--olive-800);
}
.sage-rs-cta .sage-btn-primary:hover,
.sage-rs-cta .sage-btn-primary:focus-visible {
  background: var(--olive-900);
  border-color: var(--olive-900);
  color: #fff;
}

/* Visually hidden but read aloud. */
.sage-rs-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --- narrow --------------------------------------------------------------- */

@media (max-width: 900px), (max-height: 500px) {
  /* On a phone the scene is ~200px tall inside an 844px viewport, so floating
     the chrome over the photograph -- which is what makes this read as an app
     on a desktop -- cannot work: the rail alone is taller than the picture it
     is supposed to sit on. So on mobile the app takes the window instead.
     Same controls, same flow, but the kitchen finally has room to be looked at. */
  /* Only once the app is entered. Inline, it stays a normal block in the page
     so the rest of the page still works around it; JS adds .is-full when a
     kitchen is chosen and moves the element to <body> at the same time, which
     is what actually escapes Flatsome's .section-content stacking context. */
  .sage-rs.is-full {
    position: fixed;
    inset: 0;
    z-index: 9990;
    margin: 0;
    padding: 0;
    background: #14150F;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  /* A column, not a row. The quote CTA is a sibling of the stage inside this
     element, so as a flex row it sat *beside* the kitchen and took two thirds
     of a 390px screen -- which is why the photograph came out 127px wide. */
  .sage-rs.is-full .sage-rs-body { display: flex; flex-direction: column; flex: 1; min-height: 0; }
  /* The CTA is already in the bar as "Get My Quote"; a second copy under the
     kitchen would only steal height the photograph needs. */
  .sage-rs.is-full .sage-rs-cta { display: none; }
  .sage-rs.is-full .sage-rs-stage { position: static; flex: 1; min-height: 0; display: flex; }
  /* Only the visible room is laid out. .sage-rs-room[hidden] is display:none
     globally, but making the stage a flex row put all three in a row anyway
     via the is-on rule below -- so the shown room got a third of the width. */
  .sage-rs.is-full .sage-rs-room { display: none; }
  .sage-rs.is-full .sage-rs-room.is-on { display: flex; flex: 1; min-width: 0; min-height: 0; }
  .sage-rs.is-full .sage-rs-scene {
    flex: 1;
    min-height: 0;
    border-radius: 0;
    box-shadow: none;
    display: flex;
  }
  .sage-rs.is-full .sage-rs-view { flex: 1; min-width: 0; min-height: 0; border-radius: 0; display: grid; place-items: center; }
  .sage-rs.is-full .sage-rs-pan { width: 100%; }
  .sage-rs.is-full .sage-rs-frame { width: 100%; }
  /* The whole kitchen, always. Filling the screen with object-fit: cover threw
     away 72% of a 16:9 render on a 390x844 phone -- you were choosing cabinet
     colours while looking at a quarter of the room. Letterboxing is the lesser
     cost: the photograph is the product, and a partial view of it is worse than
     black bands beside it. Rotating gets you a bigger one, which is why the
     landscape hint exists. */
  /* The frame takes the photograph's own shape rather than the window's, so
     object-fit never has anything to crop or letterbox *inside* the element --
     the black is around the frame, not within it. That matters for more than
     tidiness: the "+" markers are positioned as percentages of the frame, so
     if the frame is 16:9 and the image inside it is not, every marker drifts
     off the thing it points at. */
  .sage-rs.is-full .sage-rs-view { overflow: hidden; place-items: center; }
  /* The markers are percentages of the pan, so the pan has to be the frame's
     size and not the window's -- otherwise a marker lands where the kitchen
     would have been if the photograph were full width, which in landscape is
     off the side of it. */
  .sage-rs.is-full .sage-rs-pan {
    width: auto;
    max-width: 100%;
    display: block;
  }
  .sage-rs.is-full .sage-rs-frame {
    /* Width-led, height-capped. width:100% with an aspect-ratio alone made the
       frame 122% of the screen in landscape -- the bottom of the kitchen was
       cut off and the rail sat on top of it. Whichever dimension runs out
       first wins now, so the whole room is visible either way up. */
    width: 100%;
    max-width: calc((100dvh - var(--rs-chrome, 8rem)) * 16 / 9);
    height: auto;
    max-height: calc(100dvh - var(--rs-chrome, 8rem));
    aspect-ratio: 16 / 9;
  }
  .sage-rs.is-full .sage-rs-bg,
  #sageMain .sage-rs.is-full .sage-rs-bg {
    width: 100%;
    height: 100%;
    object-fit: contain;
  }

  /* The bar becomes a single row across the top, and the labels shorten --
     "Start a new design" does not fit a 390px screen beside anything else. */
  .sage-rs.is-full .sage-rs-bar {
    position: static;
    flex: none;
    padding: 0.55rem 0.6rem;
    gap: 0.4rem;
    background: rgba(0, 0, 0, 0.45);
    border-bottom: 1px solid var(--rs-hair);
    pointer-events: auto;
  }
  .sage-rs.is-full .sage-rs-tools { gap: 0.3rem; }
  .sage-rs.is-full .sage-rs-tool {
    min-height: 2.2rem;
    padding: 0 0.7rem;
    font-size: 0.6875rem;
    background: rgba(255, 255, 255, 0.08);
    backdrop-filter: none;
  }
  /* The summary is one tap from any zone, so it gives up its space in the bar.
     (Reset used to be hidden here too; it is now an icon in the zoom pill,
     available in both layouts rather than desktop-only.) */
  .sage-rs.is-full .sage-rs-lbl-wide { display: none; }
  .sage-rs.is-full .sage-rs-lbl-narrow { display: inline; }

  /* The bar has to fit 390px. Wrapping would push it over the photograph, so
     it scrolls sideways instead and the quote button stays pinned where a
     thumb expects it. */
  .sage-rs.is-full .sage-rs-bar { flex-wrap: nowrap; }
  .sage-rs.is-full .sage-rs-tools--left { min-width: 0; overflow-x: auto; scrollbar-width: none; }
  .sage-rs.is-full .sage-rs-tools--left::-webkit-scrollbar { display: none; }
  .sage-rs.is-full .sage-rs-tools--right { flex: none; }
  .sage-rs.is-full .sage-rs-tool--cta { padding: 0 0.65rem; }

  /* The rail runs along the bottom, where a thumb is, instead of down the side
     of a photograph shorter than the rail itself. */
  .sage-rs.is-full .sage-rs-rail {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    transform: none;
    z-index: 6;
    flex-direction: row;
    justify-content: space-between;
    gap: 0.1rem;
    padding: 0.4rem 0.5rem;
    border-radius: 0;
    border: 0;
    border-top: 1px solid var(--rs-hair);
    background: rgba(10, 11, 9, 0.9);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .sage-rs-rail::-webkit-scrollbar { display: none; }
  .sage-rs.is-full .sage-rs-railbtn { width: 2.6rem; height: 2.6rem; flex: none; }
  /* Eight zones will not fit 390px at a thumb-sized target, so the rail
     scrolls. justify-content: space-between would strand the last button
     off-screen with no way to reach it; start-aligned with padding scrolls. */
  .sage-rs.is-full .sage-rs-rail { justify-content: flex-start; gap: 0.25rem; }
  .sage-rs-railtip { display: none; }

  /* Zoom sits above the rail rather than in the corner of a photo it would
     otherwise cover. */
  .sage-rs.is-full .sage-rs-viewtools {
    right: 0.6rem;
    bottom: 4.2rem;
    padding: 0.15rem;
    gap: 0;
  }
  /* 2.2rem was larger than the desktop control and made a five-item pill read
     as a band of chrome across the photograph. 2rem is still a comfortable
     thumb target, and the row is now one item longer than it was.
     .sage-rs-zoomv inherits the same height, so the two stay level. */
  .sage-rs.is-full .sage-rs-vt,
  .sage-rs.is-full .sage-rs-zoomv { width: 2rem; height: 2rem; }
  .sage-rs.is-full .sage-rs-vt svg { width: 0.95rem; height: 0.95rem; }
  .sage-rs.is-full .sage-rs-zoomv { min-width: 2.4rem; width: auto; font-size: 0.625rem; }

  /* The gate covers the app, not a 200px box inside a scrolling page. */

  /* The summary drops from the bar as a full-width sheet. */
  .sage-rs-summary {
    position: fixed;
    left: 0;
    right: 0;
    top: auto;
    bottom: 0;
    width: auto;
    max-height: 70vh;
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    z-index: 9999;
  }

  /* The finishes are a bottom sheet: the standard phone pattern, with room for
     real swatches and a thumb-reachable close. */
  .sage-rs-pop,
  .sage-rs-pop--plain,
  .sage-rs-pop[data-zone="Countertop"] {
    position: fixed;
    left: 0;
    right: 0;
    top: auto;
    bottom: 0;
    width: auto;
    max-width: none;
    max-height: 78vh;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 100%);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    border-bottom: 0;
    transform: translateY(100%);
    z-index: 9999;
    /* Auto for the preview strip, the rest to the picker -- otherwise both
       rows split the sheet evenly and the preview becomes a tall empty band. */
    grid-template-rows: auto minmax(0, 1fr);
  }
  .sage-rs-pop.is-open { transform: translateY(0); }

  /* The sheet is opaque here, not glass. backdrop-filter is unreliable on a
     position:fixed element inside the re-parented full-screen app -- iOS drops
     it and the 18% bleed-through of --rs-glass stops being a soft wash and
     becomes the rail's own words legible straight through the swatches. An
     opaque panel does not depend on the filter working. */
  .sage-rs-pop,
  .sage-rs-pop--plain,
  .sage-rs-pop[data-zone="Countertop"] {
    background: #191b17;
    backdrop-filter: none;
    box-shadow: 0 -18px 50px rgba(0, 0, 0, 0.55);
  }

  /* And the room dims behind it, so nothing behind the sheet competes with the
     option being chosen. Fixed, to match the sheet: the scene scrolls, the
     sheet does not. */
  .sage-rs-scrim {
    position: fixed;
    /* Above the summary band, which is itself 9999, and below the sheet. The
       sheet is raised to 10000 to keep that order. */
    z-index: 9999;
  }
  .sage-rs-pop,
  .sage-rs-pop--plain,
  .sage-rs-pop[data-zone="Countertop"] { z-index: 10000; }
  .sage-rs.is-popped .sage-rs-scrim { opacity: 1; }
  /* The preview is a strip across the top of the sheet, not a column: on a
     phone it only has to confirm what was just tapped. It was taking a third
     of the sheet's height as empty space, which is height the swatches need. */
  .sage-rs-pop-side {
    order: -1;
    flex: none;
    flex-direction: row;
    align-items: center;
    gap: 0.75rem;
    border-left: 0;
    border-bottom: 1px solid var(--rs-hair);
    padding: 0.6rem 0.85rem;
  }
  .sage-rs-preview { flex: none; margin: 0; }
  .sage-rs-preview-img,
  #sageMain .sage-rs-preview-img { max-height: 4.5rem; }
  .sage-rs-all { margin-top: 0; margin-left: auto; }
  .sage-rs-pop-x { width: 2.2rem; height: 2.2rem; }
  .sage-rs-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  .sage-rs.is-full { padding: 0; }
  .sage-rs.is-full .sage-rs-bg,
  #sageMain .sage-rs.is-full .sage-rs-bg { max-height: none; }
}

@media (prefers-reduced-motion: reduce) {
  .sage-rs.is-full .sage-rs-pan,
  .sage-rs-pop,
  .sage-rs-sw-img,
  .sage-rs-door img,
  .sage-rs-spot-dot,
  .sage-rs-tier,
  .sage-rs-all-tr,
  .sage-rs-all-tr::after { transition-duration: 0.01ms !important; }
}

/* --- the gate: splash and pick-a-kitchen ---------------------------------- */

/* Both opening screens cover the scene rather than replacing it: the room is
   already rendered underneath, so choosing a kitchen is a class change and the
   photograph is there instantly, with nothing to load. */
.sage-rs-gate {
  position: absolute;
  inset: 0;
  z-index: 8;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 2.5rem);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.sage-rs-gate[hidden] { display: none; }

/* The opening kitchen, blurred back so it reads as atmosphere rather than as
   the thing you are being asked to look at. */
.sage-rs-gate-bg {
  position: absolute;
  inset: -3%;
  background-size: cover;
  background-position: center;
  filter: blur(14px) brightness(0.55) saturate(0.9);
}

.sage-rs-gate-card {
  position: relative;
  width: min(46rem, 100%);
  padding: clamp(1.5rem, 4vw, 2.75rem);
  border-radius: var(--radius-md);
  background: var(--rs-glass);
  backdrop-filter: blur(22px) saturate(1.1);
  border: 1px solid var(--rs-hair);
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.5);
  color: var(--rs-ink);
  text-align: center;
}
.sage-rs-gate-card[hidden] { display: none; }
.sage-rs-gate-card--pick { width: min(58rem, 100%); }

.sage-rs-gate-eyebrow {
  margin: 0 0 0.5rem;
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  /* The one surface where the logo's gold is legible: 8.19:1 on this ground. */
  color: var(--gold-100, #FEEBAA);
}
.sage-rs-gate-h {
  margin: 0 0 0.6rem;
  font-family: var(--font-display, var(--font-body));
  font-size: clamp(1.6rem, 3.4vw, 2.4rem);
  line-height: 1.15;
  color: var(--rs-ink);
}
.sage-rs-gate-p {
  max-width: 34rem;
  margin: 0 auto 1.6rem;
  font-size: var(--text-sm);
  line-height: 1.65;
  /* --rs-ink-dim is 3.79:1 on the glass over a bright photo, under the 4.5
     body-text threshold. This is 6.1:1 against the same worst case. */
  color: rgba(255, 255, 255, 0.8);
}
.sage-rs-gate-btn {
  min-height: 2.9rem;
  padding: 0 2rem;
  background: var(--olive-800);
  border: 0;
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--gold-100, #FEEBAA);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.sage-rs-gate-btn:hover { background: var(--olive-700, #5A5F33); transform: translateY(-1px); }
.sage-rs-gate-btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* Three kitchens, answered by looking rather than reading. */
.sage-rs-picks {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.6vw, 1rem);
  margin-top: 1.5rem;
}
.sage-rs-pick {
  padding: 0;
  background: none;
  border: 1px solid var(--rs-hair);
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: pointer;
  text-align: left;
  transition: transform var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.sage-rs-pick img,
#sageMain .sage-rs-pick img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
/* Hovering enlarges the kitchen, as CNC's own cards do -- the photograph is
   the thing being chosen, so it is the thing that should respond. */
.sage-rs-pick:hover,
.sage-rs-pick:focus-visible {
  transform: translateY(-3px) scale(1.02);
  border-color: rgba(255, 255, 255, 0.45);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
  outline: none;
}
.sage-rs-pick:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.sage-rs-pick-body { display: block; padding: 0.7rem 0.85rem 0.85rem; }
.sage-rs-pick-n {
  display: block;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--rs-ink);
}
.sage-rs-pick-s {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.5625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--rs-ink-dim);
}

/* While the gate is up the room's own chrome is inert -- there is nothing to
   reset or summarise until a kitchen has been chosen. */
.sage-rs.is-gated .sage-rs-bar,
.sage-rs.is-gated .sage-rs-rail,
.sage-rs.is-gated .sage-rs-spot,
.sage-rs.is-gated .sage-rs-viewtools { display: none; }

/* The gate's own styles are declared after the 900px block above, so the
   desktop three-column picker outranked the mobile override no matter what the
   media query said. Same rules, restated here where they can win. */
@media (max-width: 900px), (max-height: 500px) {
  /* Three choices stacked down the middle, each a full-width card with its
     kitchen across the top. Three thumbnails side by side on a 390px screen
     give each photograph about 110px, which is not enough to choose a kitchen
     by -- and choosing by the photograph is the point of this screen. */
  .sage-rs-picks {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.5rem;
    margin-top: 0.9rem;
    /* No scroller. Three kitchens are a comparison, and a comparison you have
       to scroll to finish is a list -- the third one may as well not be there.
       They are sized to fit instead. */
    max-height: none;
    overflow: visible;
  }
  .sage-rs-pick { display: block; text-align: left; }
  /* Wide and short: enough of the kitchen to judge it, three times over,
     without pushing the last one off the screen.

     The ratio is capped by height as well as set by aspect-ratio. On a 667px
     screen 21:9 still put the third kitchen 145px below the fold; 32vh each
     keeps all three in view on a short phone and lets them grow on a tall one,
     which is the whole point of showing three at once. */
  .sage-rs-pick img,
  #sageMain .sage-rs-pick img {
    width: 100%;
    aspect-ratio: 21 / 9;
    max-height: 32vh;
    object-fit: cover;
  }
  .sage-rs-pick-body { padding: 0.5rem 0.75rem 0.6rem; }
  .sage-rs-pick-n { font-size: 0.75rem; }
  .sage-rs-pick-s { font-size: 0.5625rem; margin-top: 0.1rem; }

  /* The card gives its height to the kitchens, so the heading tightens. */
  .sage-rs.is-full .sage-rs-gate-card--pick { padding: 1rem 0.9rem 1.1rem; }
  .sage-rs-gate-card--pick .sage-rs-gate-h { font-size: 1.25rem; margin-bottom: 0; }
}

/* On a short phone the name and subtitle move onto the photograph instead of
   sitting under it. Stacked, each card cost 235px -- 139px of kitchen and 96px
   of text -- and three of those overflow a 667px screen by 145px. Overlaid,
   all three fit and nothing has to be scrolled to be compared, which is the
   point of showing three at once.
   Height only, with no width bound. A Pro Max in landscape is 932px wide and
   430px tall: pairing this with max-width: 900px excluded exactly the device
   that needs it most, and the third kitchen ended up 402px off screen. Short
   is short, whatever the width. */
@media (max-height: 750px) {
  .sage-rs-pick { position: relative; }
  .sage-rs-pick-body {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 1.6rem 0.75rem 0.5rem;
    /* Its own scrim: the label has to stay legible over whichever kitchen is
       behind it, and these are photographs, not flat colour. */
    background: linear-gradient(to top,
      rgba(12, 13, 10, 0.92) 0%,
      rgba(12, 13, 10, 0.65) 55%,
      rgba(12, 13, 10, 0) 100%);
  }
  /* Sized from the space that is actually left, not from a guessed fraction of
     the screen. 26vh ignored the fixed overhead above and below the three
     kitchens -- heading, gaps, card padding, safe area -- so on a 553px
     viewport the third card cleared the bottom edge by 9px, which is nothing
     once a real phone's home indicator is there.

     --rs-pick-chrome is that overhead measured: 1.4rem top padding + ~23px
     heading + 0.9rem list margin + two 8px gaps + 1.4rem bottom padding, plus
     the safe area and a little breathing room. Whatever remains is divided
     three ways. */
  .sage-rs-picks { --rs-pick-chrome: calc(9.5rem + env(safe-area-inset-bottom, 0px)); }
  .sage-rs-pick img,
  #sageMain .sage-rs-pick img {
    aspect-ratio: 2 / 1;
    max-height: calc((100svh - var(--rs-pick-chrome)) / 3);
  }

}

/* A wide short phone -- Pro Max in landscape, 932x430 -- gets the single-column
   stack from the block above, because that block keys on
   (max-width: 900px), (max-height: 500px) and 430px tall matches the second
   half. Stacked is wrong here: a third of 430px is 143px per row, and a band
   that wide and that short shows no kitchen at all -- the label scrim covers
   what little there is, which is three empty strips with text on them.

   Wide and short is the one shape where three across is right. Each card gets
   a third of the width and the full height, which is how you compare three
   photographs on a screen like this. */
@media (max-height: 500px) and (min-width: 700px) {
  .sage-rs-picks {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.6rem;
    /* One row, not three: no inter-row gaps to allow for, so the overhead is
       just the heading and the card's own padding. */
    --rs-pick-chrome: calc(6.5rem + env(safe-area-inset-bottom, 0px));
  }
  .sage-rs-pick img,
  #sageMain .sage-rs-pick img {
    aspect-ratio: 4 / 3;
    max-height: calc(100svh - var(--rs-pick-chrome));
  }
}

/* --- the opening screen on a phone --------------------------------------- */

/* These sit at the end of the file for the same reason the picker rules do:
   the gate's own styles are declared after the 900px block, so anything
   restating them has to come later to win.

   The splash is the first thing a visitor sees, and on a phone it was a small
   card floating in the middle of a scrolling page -- which reads as a widget,
   not as opening an app. It takes the screen instead: the kitchen behind it
   edge to edge, the wordmark and the invitation stacked down the middle, and
   the button sitting above the thumb rather than clipped off the bottom. */
@media (max-width: 900px), (max-height: 500px) {
  /* Only once engaged. Fixed from page load would have the splash covering the
     whole site before the visitor has touched anything -- an ad, not an app. */
  .sage-rs.is-full .sage-rs-gate {
    position: fixed;
    inset: 0;
    z-index: 9995;
    border-radius: 0;
    padding: 0;
    /* Not centred: a card centred in a tall screen leaves the button floating
       mid-air. The content sits low, where a thumb already is. */
    place-items: stretch;
  }
  .sage-rs.is-full .sage-rs-gate-bg { inset: 0; filter: blur(10px) brightness(0.42) saturate(0.95); }

  .sage-rs.is-full .sage-rs-gate-card {
    width: 100%;
    max-width: none;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 1.6rem 1.4rem calc(2rem + env(safe-area-inset-bottom, 0px));
    border: 0;
    border-radius: 0;
    background: linear-gradient(to top,
      rgba(12, 13, 10, 0.94) 0%,
      rgba(12, 13, 10, 0.86) 45%,
      rgba(12, 13, 10, 0.45) 100%);
    backdrop-filter: none;
    box-shadow: none;
  }

  .sage-rs.is-full .sage-rs-gate-card--splash .sage-rs-gate-eyebrow { margin-bottom: 0.65rem; }
  .sage-rs.is-full .sage-rs-gate-card--splash .sage-rs-gate-h {
    font-size: clamp(2rem, 10vw, 2.75rem);
    line-height: 1.05;
    margin-bottom: 0.75rem;
  }
  .sage-rs.is-full .sage-rs-gate-card--splash .sage-rs-gate-p {
    font-size: 0.875rem;
    line-height: 1.6;
    margin: 0 0 1.75rem;
    max-width: 26rem;
  }
  /* Full width and tall enough to be a target, not a link. */
  .sage-rs.is-full .sage-rs-gate-btn {
    width: 100%;
    min-height: 3.25rem;
    font-size: 0.9375rem;
  }

  /* The chooser keeps the same full-bleed treatment, but its content sits at
     the top: three cards need the height, and the heading has to stay put. */
  .sage-rs.is-full .sage-rs-gate-card--pick {
    justify-content: flex-start;
    padding: 1.4rem 1rem calc(1.4rem + env(safe-area-inset-bottom, 0px));
    background: rgba(12, 13, 10, 0.92);

    /* Three kitchens do not fit a short phone -- on a 667px screen the third
       sits 145px below the fold -- and the card had no scroller of its own, so
       reaching for it scrolled the page behind the overlay instead. Note that
       body { overflow: hidden } does not prevent this: the gate is
       position: fixed, and a fixed overlay still chains its scroll to the
       document. overscroll-behavior: contain is what actually stops it. */
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  /* Belt and braces: the gate itself must not chain either, for the case where
     the card is short but the gate is the thing being dragged. */
  .sage-rs.is-full .sage-rs-gate { overscroll-behavior: contain; }
}

/* The splash before it is tapped, on a phone.
 *
 * It cannot be full screen here -- that would cover the site before the
 * visitor has touched anything -- but a small card floating in the page reads
 * as a banner. So it fills the width it has, stands as tall as a phone screen
 * is wide, and shows the kitchen it is offering to let you change. */
@media (max-width: 900px), (max-height: 500px) {
  .sage-rs:not(.is-full) .sage-rs-gate {
    position: absolute;
    inset: 0;
    border-radius: var(--radius-md);
    padding: 0;
    place-items: stretch;
  }
  .sage-rs:not(.is-full) .sage-rs-scene { min-height: 78vw; }
  .sage-rs:not(.is-full) .sage-rs-gate-bg {
    inset: 0;
    filter: blur(6px) brightness(0.5) saturate(1);
  }
  .sage-rs:not(.is-full) .sage-rs-gate-card {
    width: 100%;
    max-width: none;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 1.5rem 1.25rem 1.5rem;
    border: 0;
    border-radius: var(--radius-md);
    background: linear-gradient(to top,
      rgba(12, 13, 10, 0.92) 0%,
      rgba(12, 13, 10, 0.7) 55%,
      rgba(12, 13, 10, 0.25) 100%);
    backdrop-filter: none;
    box-shadow: none;
    text-align: left;
  }
  .sage-rs:not(.is-full) .sage-rs-gate-eyebrow { margin-bottom: 0.5rem; }
  .sage-rs:not(.is-full) .sage-rs-gate-h {
    font-size: clamp(1.75rem, 8.5vw, 2.4rem);
    line-height: 1.05;
    margin-bottom: 0.6rem;
  }
  .sage-rs:not(.is-full) .sage-rs-gate-p {
    margin: 0 0 1.4rem;
    font-size: 0.8125rem;
    line-height: 1.55;
    max-width: none;
  }
  .sage-rs:not(.is-full) .sage-rs-gate-btn { width: 100%; min-height: 3.1rem; font-size: 0.9375rem; }
}

/* Last word on hiding. The mobile blocks above set display on the gate cards,
   which outranks the [hidden] rule declared earlier in the file -- so both the
   splash and the chooser rendered at once, stacked. */
.sage-rs-gate-card[hidden],
.sage-rs .sage-rs-gate-card[hidden] { display: none !important; }

/* --- portrait: give the kitchen every pixel -------------------------------- */

@media (max-width: 900px) and (orientation: portrait) {
  /* The chrome tightens so the photograph gets the difference. */
  /* The photograph goes to the top rather than the middle, and the space it
     cannot use becomes the summary: what you have chosen so far, legible while
     you are choosing, in a band that was otherwise empty. On a desktop that
     list is a dropdown because the kitchen needs the width; here the kitchen
     cannot use the height, so the list may as well be open. */
  .sage-rs.is-full .sage-rs-view { align-items: start; }
  /* Clear of the rail below it. The rotate hint used to sit between the two and
     pushed zoom a further 3rem up the screen; with it gone the pill drops back
     down and the summary above gets the height. */
  .sage-rs.is-full .sage-rs-viewtools { top: auto; bottom: 4.6rem; }

  /* Under the photograph, above the controls. It scrolls if the room has more
     zones than the gap can hold. */
  /* The wrapper is position: relative so the dropdown can hang off the button
     on a desktop. Here the panel is not a dropdown at all, so the wrapper has
     to stop being its containing block or the offsets below resolve against a
     31px pill. */
  .sage-rs.is-full .sage-rs-sumwrap { position: static; }
  .sage-rs.is-full .sage-rs-summary {
    position: absolute;
    left: 0.75rem;
    right: 0.75rem;
    top: calc((100vw * 9 / 16) + 4.5rem);
    bottom: 11.5rem; /* clears the zoom pill and the rail below it */
    width: auto;
    max-height: none;
    border-radius: var(--radius-md);
    background: rgba(255, 255, 255, 0.045);
    border-color: rgba(255, 255, 255, 0.1);
    box-shadow: none;
    backdrop-filter: none;
    overflow-y: auto;
  }
  /* Open by default here -- it is filling space rather than covering anything,
     so hiding it behind a tap would only leave the gap blank.

     Except when a sheet is open. The summary is a near-transparent band
     (4% white) sitting at z-index 9999, and in portrait it overlaps the top
     ~190px of the bottom sheet -- so its rows paint straight over the swatches
     and read as the sheet being see-through. It is also redundant at that
     moment: you are choosing the very thing it lists. */
  .sage-rs.is-full:not(.is-popped) .sage-rs-summary[hidden] { display: block; }
  .sage-rs.is-full.is-popped .sage-rs-summary { display: none; }
  .sage-rs.is-full .sage-rs-sum-row { padding: 0.42rem 0; }
  .sage-rs.is-full .sage-rs-sum-row dt { font-size: 0.5625rem; }
  .sage-rs.is-full .sage-rs-sum-btn { font-size: 0.6875rem; }
  /* The button that opened it has nothing left to open. */
  .sage-rs.is-full .sage-rs-tool[data-act="summary"] { display: none; }

  .sage-rs.is-full .sage-rs-bar { padding: 0.4rem 0.5rem; }
  .sage-rs.is-full .sage-rs-tool { min-height: 2rem; }
  .sage-rs.is-full .sage-rs-rail { padding: 0.3rem 0.4rem; }
  .sage-rs.is-full .sage-rs-railbtn { width: 2.4rem; height: 2.4rem; }
  /* Zoom is the one control that earns its place here: it is how you get a
     closer look at a kitchen this size. Back in the corner, over the
     photograph, rather than centred in the gap where the rotate hint used to
     anchor it -- a floating pill across the middle of the screen was reading as
     a band of chrome in its own right. */
  .sage-rs.is-full .sage-rs-viewtools {
    top: auto;
    bottom: 4.6rem;
    right: 0.6rem;
    transform: none;
  }
}

/* In landscape the photograph nearly fills the screen on its own, so the hint
   is not merely unnecessary -- it would be wrong. */
@media (orientation: landscape) and (max-height: 500px) {
  /* Bar + rail. The frame subtracts this from the viewport before deciding how
     large the photograph can be, so the rail sits under the kitchen rather
     than on top of it. */
  /* In landscape height is the scarce dimension and width is not, so the rail
     goes back down the side where it costs nothing. The bar is the only chrome
     taking height, and the photograph gets the rest -- 270px of usable height
     became 320px, and the kitchen grew from 56% of the width to about 90%. */
  .sage-rs.is-full { --rs-chrome: 3.6rem; }
  .sage-rs.is-full .sage-rs-view { padding: 0 4.2rem 0 4.2rem; }

  .sage-rs.is-full .sage-rs-rail {
    left: 0.5rem;
    right: auto;
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
    flex-direction: column;
    justify-content: center;
    width: auto;
    /* Eight buttons stacked come to 516px against 390px of screen, so the rail
       is bounded and scrolls rather than running off both ends. */
    max-height: calc(100dvh - 4.6rem);
    padding: 0.3rem;
    border: 1px solid var(--rs-hair);
    border-radius: var(--radius-full);
    background: var(--rs-glass);
    backdrop-filter: blur(14px);
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: none;
  }
  .sage-rs.is-full .sage-rs-rail::-webkit-scrollbar { display: none; }
  .sage-rs.is-full .sage-rs-railbtn { width: 1.95rem; height: 1.95rem; }
  .sage-rs.is-full .sage-rs-railbtn svg { width: 1rem; height: 1rem; }
  .sage-rs.is-full .sage-rs-bar { padding: 0.3rem 0.5rem; }
  .sage-rs.is-full .sage-rs-tool { min-height: 1.9rem; font-size: 0.625rem; }
  .sage-rs.is-full .sage-rs-rail { padding: 0.25rem 0.4rem; }
  .sage-rs.is-full .sage-rs-railbtn { width: 2.1rem; height: 2.1rem; }
  /* Bottom-right, in the margin the photograph leaves. */
  .sage-rs.is-full .sage-rs-viewtools { bottom: 0.5rem; right: 0.5rem; padding: 0.2rem; }
  .sage-rs.is-full .sage-rs-vt { width: 1.85rem; height: 1.85rem; }
  .sage-rs.is-full .sage-rs-zoomv { height: 1.85rem; }
}

/* --- the capture sheet ---------------------------------------------------
   "Email me this kitchen." Same dark glass as an option panel, because it
   opens over the same photograph for the same reason -- a pale card would read
   as browser chrome dropped onto the image.

   Fixed to the viewport rather than absolute inside .sage-rs-body: the element
   re-parents to <body> in full screen, and a panel positioned against a
   scrolling ancestor lands off screen the moment it does. Fixed is correct in
   both arrangements.

   This block sits at the end of the file deliberately. Declaration order beats
   the media query in this stylesheet, so anything restated for mobile has to
   come after the desktop rule, not merely inside a narrower query. */
.sage-rs-capture {
  position: fixed;
  inset: 0;
  z-index: 10001;          /* over the option sheet (10000) and its scrim */
  display: grid;
  place-items: center;
  padding: 1.25rem;
  background: rgba(14, 15, 12, 0.62);
  /* A fixed overlay does not stop a drag from scrolling the page behind it --
     body{overflow:hidden} does not chain-block either. This is what does. */
  overscroll-behavior: contain;
}
.sage-rs-capture[hidden] { display: none; }

/* The site header sits over this panel and steals its clicks.

   #sageHdr is position:fixed with z-index 400, and the panel is 10001 -- but
   the two are in different stacking contexts, so the numbers never compare and
   the header wins. The close button rendered under the 131px header and a
   click on it landed on a nav link instead, navigating away from a form the
   visitor had already filled in.

   The header is hidden rather than out-z-indexed: raising the panel cannot
   work across stacking contexts, and a fixed header floating over a modal is
   wrong even when it is not intercepting anything.

   Driven by a class on <body> set in openCapture(), not by :has() or a sibling
   combinator -- both depend on where this element happens to sit in the DOM,
   and it moves to <body> in full screen. */
body.sage-rs-capturing #sageHdr,
body.sage-rs-capturing #header,
body.sage-rs-capturing #top-bar {
  opacity: 0;
  pointer-events: none;
}

.sage-rs-cap-main {
  width: min(26rem, 100%);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 1.1rem 1.15rem 1.15rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--rs-hair);
  background: var(--rs-glass);
  backdrop-filter: blur(22px) saturate(1.1);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  color: var(--rs-ink);
}
/* Flatsome again, the same bleed the zoom pill hit: it was forcing 41x43 with
   min-height 42.68px, padding 0 20.49px and a 4px radius onto the close
   button, so the hover state painted a large square grey slab bigger than the
   icon instead of a round hit area. height cannot beat a min-height, and the
   radius needs !important. Values that appear nowhere in this file are the
   tell -- read getComputedStyle, do not assume this file is the one applying. */
.sage-rs-capture .sage-rs-pop-x {
  width: 2rem !important;
  height: 2rem !important;
  min-height: 0 !important;
  min-width: 0 !important;
  padding: 0 !important;
  margin: 0 0 0 auto !important;
  border-radius: var(--radius-full) !important;
  background: none;
  box-shadow: none !important;
  flex: none;
}
.sage-rs-capture .sage-rs-pop-x:hover {
  background: rgba(255, 255, 255, 0.12);
  color: var(--rs-ink);
}

.sage-rs-cap-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.28) transparent;
}
.sage-rs-cap-lede {
  margin: 0 0 0.9rem;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--rs-ink-dim);
}

.sage-rs-fld { display: block; margin-bottom: 0.7rem; }
.sage-rs-fld-l {
  display: block;
  margin-bottom: 0.3rem;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--rs-ink);
}
/* "required"/"optional" carried in the label rather than by an asterisk: the
   visitor is deciding how much to give, and the answer should be readable
   without a legend. */
.sage-rs-fld-l em {
  font-style: normal;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--rs-ink-dim);
}
.sage-rs-fld-h {
  margin: -0.1rem 0 0.4rem;
  font-size: 0.72rem;
  line-height: 1.45;
  color: var(--rs-ink-dim);
}

/* Flatsome styles every input on the site and beats this file on specificity,
   the same trap the zoom buttons hit.

   Restating on the component's class was not enough for email specifically:
   Flatsome ships a rule carrying input[type="email"] that outranked
   .sage-rs-cap-form input[type="email"], so that one field rendered solid
   white with #333 text inside a dark glass panel while tel and text next to it
   were correct. !important is the same justified exception this file already
   makes for the zoom pill's radius -- the tell was a computed
   background of rgb(255,255,255) that appears nowhere in this stylesheet.
   Screenshot caught it; the contrast pass did not, because white-on-dark-grey
   still measures as passing. */
.sage-rs-capture .sage-rs-cap-form input[type="email"],
.sage-rs-capture .sage-rs-cap-form input[type="tel"],
.sage-rs-capture .sage-rs-cap-form input[type="text"] {
  background: rgba(255, 255, 255, 0.07) !important;
  color: var(--rs-ink) !important;
  border: 1px solid var(--rs-hair) !important;
}
.sage-rs-cap-form input[type="email"],
.sage-rs-cap-form input[type="tel"],
.sage-rs-cap-form input[type="text"] {
  width: 100%;
  height: 2.5rem;
  margin: 0;
  padding: 0 0.7rem;
  font-family: inherit;
  /* 16px. Anything smaller and iOS zooms the page on focus, which on a phone
     throws the kitchen off screen behind the keyboard. */
  font-size: 1rem;
  color: var(--rs-ink);
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid var(--rs-hair);
  border-radius: var(--radius-sm, 6px);
  box-shadow: none;
  transition: border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.sage-rs-cap-form input::placeholder { color: rgba(255, 255, 255, 0.4); }
/* Also !important: it has to outrank the base rule above, which needed it. */
.sage-rs-capture .sage-rs-cap-form input:focus {
  outline: 2px solid var(--rs-ink);
  outline-offset: 1px;
  background: rgba(255, 255, 255, 0.12) !important;
  border-color: transparent !important;
}

/* The qualifying dropdowns. Flatsome styles every select on the site and wins
   on specificity, exactly as it does for input[type=email] above -- hence the
   same !important, and the same tell: a computed value that appears nowhere in
   this file.

   appearance:none because the native control paints a light system background
   on dark glass; the chevron is a background image so there is no extra
   element to position. */
.sage-rs-capture .sage-rs-cap-form select.sage-rs-sel {
  width: 100%;
  height: 2.5rem;
  margin: 0;
  padding: 0 2rem 0 0.7rem;
  font-family: inherit;
  /* 16px, or iOS zooms the page on focus and throws the kitchen off screen. */
  font-size: 1rem;
  line-height: 2.5rem;
  color: var(--rs-ink) !important;
  background-color: rgba(255, 255, 255, 0.07) !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-opacity='.7' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: right 0.65rem center !important;
  background-size: 0.85rem !important;
  border: 1px solid var(--rs-hair) !important;
  border-radius: var(--radius-sm, 6px) !important;
  box-shadow: none !important;
  -webkit-appearance: none;
  appearance: none;
}
.sage-rs-capture .sage-rs-cap-form select.sage-rs-sel:focus {
  outline: 2px solid var(--rs-ink);
  outline-offset: 1px;
  background-color: rgba(255, 255, 255, 0.12) !important;
  border-color: transparent !important;
}
/* The drop-down list itself is drawn by the OS, not by this panel: on a dark
   background the options inherit white-on-white in several browsers unless
   both are stated. */
.sage-rs-capture .sage-rs-cap-form select.sage-rs-sel option {
  color: #1c1c17;
  background: #FDFBF6;
}
/* The placeholder row reads as placeholder, not as a chosen answer. */
.sage-rs-capture .sage-rs-cap-form select.sage-rs-sel:invalid {
  color: rgba(255, 255, 255, 0.45) !important;
}

.sage-rs-cap-add {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2.3rem;
  padding: 0 0.85rem;
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--rs-ink);
  background: rgba(255, 255, 255, 0.08);
  border: 1px dashed rgba(255, 255, 255, 0.34);
  border-radius: var(--radius-full);
  cursor: pointer;
}
.sage-rs-cap-add svg { width: 0.85rem; height: 0.85rem; }
.sage-rs-cap-add:hover { background: rgba(255, 255, 255, 0.14); }
.sage-rs-cap-add:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.sage-rs-cap-thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.55rem 0 0;
  padding: 0;
  list-style: none;
}
.sage-rs-cap-thumbs li { position: relative; }
.sage-rs-cap-thumbs img {
  display: block;
  width: 3.1rem;
  height: 3.1rem;
  object-fit: cover;
  border-radius: var(--radius-sm, 6px);
  border: 1px solid var(--rs-hair);
}
.sage-rs-cap-drop {
  position: absolute;
  top: -0.3rem;
  right: -0.3rem;
  width: 1.15rem;
  height: 1.15rem;
  min-height: 0;
  padding: 0;
  display: grid;
  place-items: center;
  font-size: 0.8rem;
  line-height: 1;
  color: #fff;
  background: rgba(14, 15, 12, 0.92);
  border: 1px solid var(--rs-hair);
  border-radius: var(--radius-full) !important;
  cursor: pointer;
}

.sage-rs-cap-err {
  margin: 0.5rem 0 0;
  font-size: 0.75rem;
  line-height: 1.45;
  /* Not Gravity Forms' red: on this glass it measures ~1.7:1, the same failure
     the (Required) markers hit on the olive band. */
  color: #FFB4A8;
}

.sage-rs-cap-go {
  width: 100%;
  min-height: 2.7rem;
  margin-top: 0.9rem;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--bone, #FDFBF6);
  background: var(--olive-800);
  border: 1px solid transparent;
  border-radius: var(--radius-full) !important;
  cursor: pointer;
}
.sage-rs-cap-go:hover { background: var(--olive-700, #5A5F33); }
.sage-rs-cap-go:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.sage-rs-cap-go[disabled] { opacity: 0.6; cursor: default; }

.sage-rs-cap-fine {
  margin: 0.6rem 0 0;
  font-size: 0.68rem;
  line-height: 1.5;
  color: var(--rs-ink-dim);
}
.sage-rs-cap-done {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--rs-ink);
}
.sage-rs-cap-done strong { display: block; margin-bottom: 0.25rem; }

/* Phones and short landscape screens. The breakpoint is an or, and carries no
   width bound on the height half: a Pro Max in landscape is 932x430, so a rule
   written as (max-height:X) and (max-width:900px) would exclude exactly the
   device that needs it most. */
@media (max-width: 900px), (max-height: 500px) {
  .sage-rs-capture { padding: 0.75rem; }
  /* svh, not vh: vh is the viewport with browser chrome hidden, which is the
     one case that does not overflow. The keyboard is why this matters -- it
     takes roughly half the screen the moment the email field is focused. */
  .sage-rs-cap-main { width: 100%; max-height: calc(100svh - 1.5rem); }
}

/* Short screens: the submit button leaves the scroll area and pins to the
   bottom of the panel.

   At 932x430 -- a Pro Max in landscape -- the form is 406px against 430px of
   viewport, so it fits, scrolls internally, and puts "Send me my kitchen"
   below the fold. The visitor has to scroll inside a panel to find the button
   that completes the thing they just asked for, which is where submissions get
   abandoned. Pinned, it is always on screen and the fields scroll behind it.

   No width bound: the height is the whole problem, and adding max-width:900px
   here would exclude the 932px-wide device that needs it. */
@media (max-height: 560px) {
  /* The fields scroll; the submit button does not.

     position:sticky was tried first and is wrong here: it sticks within the
     scrolling ancestor, so a button sitting mid-document parks wherever the
     scroll offset puts it -- it landed on top of the phone field, mid-form,
     rather than at the foot of the panel. What works is giving the fields
     their own overflow inside .sage-rs-cap-fields, which makes the button a
     sibling of the scroll area rather than a child of it. */
  /* Take the height rather than shrink to content. Without this the panel
     sizes to its own content, the scroll area gets whatever is left, and the
     fields collapsed to about a field and a half tall while empty space sat
     below the fine print. */
  .sage-rs-cap-main { height: calc(100svh - 1.5rem); }
  /* Column, not row. As a plain flex container this put the lede and the form
     side by side and the form lost half the panel's width. */
  .sage-rs-cap-scroll {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .sage-rs-cap-form {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
  }
  .sage-rs-cap-fields {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Room for the focus ring, which a plain overflow would clip. */
    padding: 2px;
    margin: -2px;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.28) transparent;
  }
  .sage-rs-cap-go,
  .sage-rs-cap-fine { flex: none; }
  .sage-rs-cap-go { margin-top: 0.6rem; }
  .sage-rs-fld { margin-bottom: 0.5rem; }
  /* The lede costs 51px of a 157px scroll area -- a third of the fields, to
     restate what the panel title and the button already say. The heading
     stays; the sentence goes. */
  .sage-rs-cap-lede { display: none; }
}
