/* BUILD 2026-10-05-C1.2 — Mounted Maps configurator + cart drawer styles
   C1.2: gift wrap card replaced by the gift note card (opens/closes, envelope, full-width button). */
@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;800;900&family=IBM+Plex+Mono:wght@400;500&display=swap');

:root { --mm-build: "2026-10-05-C1.2"; }
/* Read it with getComputedStyle(document.documentElement)
   .getPropertyValue('--mm-build'). The comment on line 1 is for the theme
   editor; it is stripped before the CDN serves this file, so it cannot tell
   you whether a deploy actually landed. This can. */

/* Mounted Maps configurator — scoped under .mm.
   Delete the @import above to inherit your theme's fonts instead. */

.mm {
  --paper:#FBFAF7; --ink:#1B1F23; --stone:#E4E1DA; --stone2:#F2F0EB;
  --accent:#5F7D45; --accent-deep:#4C6534; --survey:#5F7D45; --crop:#F2C21A; --muted:#71737A; --line:#D8D5CD;
  background:var(--paper); color:var(--ink);
  font-family:'Archivo', ui-sans-serif, system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing:antialiased; padding-bottom:78px;
}
@media (min-width:941px){ .mm { padding-bottom:0; } }
.mm *, .mm *::before, .mm *::after { box-sizing:border-box; }
.mm-mono { font-family:'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace; }
.mm button { font:inherit; }
.mm-hide { display:none !important; }

/* Nothing inside may push the page wider than the viewport on a phone. */
/* clip, not hidden. Both stop sideways overflow, but `hidden` makes this a
   scroll container, and a sticky child then sticks to THIS box instead of the
   viewport -- which is why the photo column never held still. `clip` does not
   create a scroll container. The `hidden` line stays as a fallback for
   anything too old to know `clip`, which simply ignores the line after it. */
.mm { overflow-x:hidden; overflow-x:clip; max-width:100%; }
.mm-wrap { max-width:1240px; margin:0 auto; padding:0 16px var(--mm-tail,12px); width:100%; }
/* The last thing in the section is Add to cart, and everything below it was
   dead: our own bottom padding, plus whatever padding the theme puts on the
   section wrapper, stacked one on the other. The wrapper is tagged from JS
   (CSS cannot reach a parent) and zeroed here, leaving one gap we control. */
.mm-sec-tight { padding-bottom:0 !important; margin-bottom:0 !important; }
/* The other half of the gap belongs to the section below, which pads its own
   top. Tagged from JS the same way; switch it off in the theme editor if the
   next section needs its breathing room back. */
.mm-sec-tight-top { padding-top:0 !important; margin-top:0 !important; }
.mm-pdp, .mm-gallery, .mm-config { min-width:0; max-width:100%; }
.mm-mapwrap, .mm-sugg, .mm-search { max-width:100%; }
.mm canvas, .mm img { max-width:100%; }
@media (min-width:941px){ .mm-wrap { padding:0 20px var(--mm-tail,20px); } }

.mm-trust { border-top:1px solid var(--line); border-bottom:1px solid var(--line);
  text-align:center; padding:11px 8px; font-size:13px; }
.mm-trust b { font-weight:800; }

.mm-hero { display:none; }
@media (min-width:941px){
  .mm-hero { display:block; padding:40px 0 30px; }
  .mm-h1 { font-weight:900; letter-spacing:-.02em; text-transform:uppercase;
    font-size:clamp(38px,5.4vw,68px); line-height:.92; margin:0; }
  .mm-sub { margin:16px 0 0; max-width:46ch; font-size:15.5px; line-height:1.55; color:var(--muted); }
}

/* Mobile: one column, and `display:contents` on the config lets its children
   become flex items and be reordered independently of the markup. */
.mm-pdp { display:flex; flex-direction:column; gap:22px; padding-top:14px; }
@media (max-width:940px){
  .mm-config { display:contents; }

  /* Photo first, map last.
     Someone arriving on a phone does not yet know what a 3D printed city model
     IS, and opening with a map asks them to start work before they know what
     they are working toward. The product photo answers "what am I buying", the
     size and colour steps answer "which one", and only then does the map ask
     for the one piece of information that needs real thought. It also lets the
     first paint be a single image while the map loads underneath. */
  /* One decision per step, in the order someone actually makes them, ending
     with their own model right above the buy button. */
  .mm-gallery   { order:1; }   /* what am I buying */
  .mm-b-size    { order:2; }
  .mm-b-frame   { order:3; }
  .mm-b-colour  { order:4; }
  .mm-region    { order:5; border-top:none; padding:6px 0; }
  .mm-b-addons  { order:6; }
  /* The render is no longer ordered here -- it lives inside this block, between
     the preview button and Add to cart. */
  .mm-sum       { order:7; }
  /* The map stays. Hiding it removed several hundred pixels from ABOVE the
     preview button at the instant the render started, so the whole page
     collapsed upward and the viewport landed somewhere else entirely. That is
     the jump -- not the keyboard, not the modal, not our scrolling code. */

  /* tighter rhythm: the phone layout was spending a third of the screen on gaps */
  .mm-pdp { gap:12px; padding-top:10px; }
  /* handled by --mm-tail on .mm now; the section no longer pads under the button */
  .mm-trust { padding:8px; font-size:12.5px; }
  .mm-block { padding:14px 0; }
  .mm-bh { margin-bottom:3px; }
  .mm-bd { margin-bottom:10px; font-size:12.5px; }
  .mm-zoomrow { padding:10px 2px 0; }
  .mm-slider { margin-top:6px; }
  .mm-sublabel { margin:12px 0 6px; }
  .mm-sizes { gap:8px; }
  .mm-size { padding:11px; }
  .mm-size-price { margin-top:7px; }
  .mm-addon { margin-bottom:10px; }
  .mm-addon-body { padding:12px 13px 13px; }
  .mm-addon-d { margin:4px 0 10px; }
  .mm-sum { margin-top:14px; }
  .mm-note { margin-top:7px; }
  .mm-gal-thumb { width:62px; height:62px; }
  .mm-mapwrap { height:min(66vw,360px); min-height:260px; }
}
@media (min-width:941px){
  .mm-pdp { display:grid; grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);
    gap:40px; padding-top:26px; align-items:start; }
  /* Photos hold still while the options scroll beside them, and release at the
     bottom of the column so the map and the preview are never trapped behind
     them. The offset is measured from the theme's own sticky header at runtime;
     16px is the fallback when there is not one. */
  .mm-gallery { position:sticky; top:var(--mm-sticky-top,16px); align-self:start; }
  /* Square, and as large as the column allows. A portrait crop was wasting the
     width and making the model look smaller than it is. */
  .mm-gal-main { aspect-ratio:1/1; max-height:min(76vh,700px); }
}

/* product photo gallery */
.mm-gal-main { position:relative; aspect-ratio:4/5; max-height:min(64vh,560px); border-radius:14px;
  overflow:hidden; background:var(--stone2); border:1px solid var(--line); }
@media (max-width:940px){ .mm-gal-main { aspect-ratio:1/1; max-height:none; } }
.mm-gal-main img { width:100%; height:100%; object-fit:cover; display:block; }
.mm-gal-empty { position:absolute; inset:0; display:flex; flex-direction:column; gap:7px;
  align-items:center; justify-content:center; text-align:center; padding:26px;
  font-size:13px; color:var(--muted);
  background:repeating-linear-gradient(45deg,var(--stone2) 0 10px,#fff 10px 20px); }
.mm-gal-empty strong { color:var(--ink); font-size:14px; }
.mm-gal-thumbs { display:flex; gap:8px; margin-top:10px; overflow-x:auto; padding-bottom:4px; }
.mm-gal-thumb { flex:none; width:64px; height:64px; border-radius:12px; overflow:hidden;
  border:1px solid var(--line); background:var(--stone2); cursor:pointer; padding:0;
  display:flex; align-items:center; justify-content:center; font-size:9px; color:var(--muted); }
.mm-gal-thumb img { width:100%; height:100%; object-fit:cover; }
.mm-gal-thumb.is-on { border-color:var(--survey); box-shadow:inset 0 0 0 1px var(--survey); }
.mm-gal-thumb.is-cube { background:#fff; color:var(--survey); border-color:var(--survey); }
.mm-gal-thumb.is-cube:hover { background:var(--stone2); }

/* back to place selection */
.mm-backrow { padding:10px 16px 0; }
.mm-backrow .mm-btn { width:100%; font-weight:600; }

/* search */
.mm-sugg { position:relative; }
.mm-search { display:flex; gap:8px; align-items:center; background:var(--stone2);
  border:1px solid var(--line); border-radius:999px; padding:5px 5px 5px 14px; margin-bottom:12px; }
.mm-search svg { flex:none; opacity:.5; }
.mm-search input { flex:1; min-width:0; font:inherit; font-size:15px; padding:9px 0; border:none;
  background:none; color:inherit; }
.mm-search input:focus { outline:none; }
.mm-locate { flex:none; width:36px; height:36px; border-radius:50%; border:none; cursor:pointer;
  background:#fff; color:var(--ink); display:flex; align-items:center; justify-content:center; }
.mm-locate:hover { background:var(--stone); }
.mm-locate.is-busy { opacity:.5; pointer-events:none; }
.mm-locate.is-busy svg { animation:mm-spin 1.1s linear infinite; }
.mm-sugg-list { border:1px solid var(--line); border-radius:12px; background:#fff; margin-bottom:12px;
  max-height:260px; overflow:auto; box-shadow:0 6px 18px rgba(20,22,26,.09); }
.mm-sugg-item { display:block; width:100%; text-align:left; padding:10px 13px; background:none;
  border:none; border-bottom:1px solid var(--stone2); cursor:pointer; }
.mm-sugg-item:last-child { border-bottom:none; }
.mm-sugg-item { color:var(--ink); }
.mm-sugg-item:hover, .mm-sugg-item.is-active { background:var(--stone2); }
.mm-sugg-name { font-size:13.5px; font-weight:600; }
.mm-sugg-ctx { font-size:11.5px; color:var(--muted); margin-top:1px; }
.mm-sugg-empty { padding:12px 13px; font-size:12.5px; color:var(--muted); }
.mm-sugg-hint { font-size:12px; color:var(--muted); margin:-4px 0 12px; padding:0 4px; line-height:1.45; }

/* maps */
.mm-mapwrap { position:relative; border:1px solid var(--line); border-radius:12px; overflow:hidden;
  background:var(--stone); height:min(62vw,420px); min-height:300px;
  touch-action:none; cursor:grab; }
.mm-mapwrap.is-dragging { cursor:grabbing; }
.mm-mmap { touch-action:none; cursor:grab; }
.mm-mmap.is-dragging { cursor:grabbing; }
.mm-hint { position:absolute; left:50%; bottom:12px; transform:translateX(-50%); z-index:3;
  background:rgba(27,31,35,.82); color:#fff; font-size:11.5px; padding:6px 11px; border-radius:999px;
  pointer-events:none; white-space:nowrap; transition:opacity .25s; }
/* Centred on the map centre by definition, so panning never moves it —
   only zoom changes its size. Cheap enough to update every frame. */
/* On satellite imagery there is no guarantee of a light background behind the
   crop: it might land on a white roof or a black river. The thin dark outline
   inside the yellow keeps the edge readable over both, and the dimming outside
   is a little stronger than it was over a pale street map. */
.mm-crop { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  border:2.5px solid var(--crop); border-radius:6px; z-index:2; pointer-events:none;
  outline:1px solid rgba(20,22,26,.55); outline-offset:-3.5px;
  box-shadow:0 0 0 9999px rgba(20,22,26,.46), 0 0 0 1px rgba(20,22,26,.5);
  will-change:width,height; }
@media (min-width:941px){ .mm-mapwrap { height:430px; } }
/* MapLibre sets position:relative on its container from its own stylesheet,
   which lands after ours and kills inset:0 — so size this explicitly. */
.mm-canvasbox { position:absolute !important; top:0; left:0; width:100%; height:100%; }
.mm-mapwrap .maplibregl-map { width:100%; height:100%; }
.mm-mmap { width:100%; }
.mm-readout { position:absolute; left:9px; bottom:9px; z-index:3; background:rgba(251,250,247,.94);
  border:1px solid var(--line); border-radius:6px; padding:5px 8px; font-size:10px; line-height:1.5;
  pointer-events:none; box-shadow:0 1px 6px rgba(20,22,26,.28); }
.mm-gate { position:absolute; inset:0; z-index:4; display:flex; align-items:center; justify-content:center;
  background:rgba(251,250,247,.86); font-size:13.5px; color:var(--muted); text-align:center; padding:24px; }
.mm-tilewarn { position:absolute; left:50%; top:12px; transform:translateX(-50%); z-index:5;
  background:#23262A; color:#fff; font-size:11.5px; line-height:1.4; padding:7px 11px;
  border-radius:12px; max-width:84%; text-align:center; }

/* MapLibre chrome, toned down to match the page */
.mm .maplibregl-ctrl-attrib { font-size:9.5px; }
.mm .maplibregl-ctrl-bottom-left { display:none; }
.mm .maplibregl-ctrl-group { border-radius:12px; box-shadow:0 1px 3px rgba(20,22,26,.2); }

/* zoom */
.mm-zoomrow { display:flex; align-items:center; gap:12px; padding:14px 2px 2px; }
.mm-zoom-l { flex:1; min-width:0; }
.mm-zoom-t { font-weight:700; font-size:13.5px; }
.mm-zoom-d { font-size:12px; color:var(--muted); margin-top:1px; }
.mm-zoom-v { font-size:13px; font-weight:600; background:var(--stone2); border:1px solid var(--line);
  border-radius:999px; padding:4px 11px; }
.mm-slider { width:100%; margin:10px 0 0; accent-color:#5F7D45; }
.mm-slider:disabled { opacity:.35; }

/* One preview button, in the closing block, on every layout. The rule that used
   to hide it on phones existed because a duplicate lived under the map -- that
   duplicate is gone, so hiding this one left no way to render at all. */
@media (max-width:940px){
  /* The hero is back. Hiding it saved scrolling but left the page opening on a
     row of grey labels -- the product was never actually shown before people
     were asked to configure it. */
  .mm-gal-thumbs { margin-top:8px; }
}
.mm-preview-cta { width:100%; margin-bottom:9px; border:none; border-radius:12px;
  background:var(--accent); color:#fff; cursor:pointer; padding:13px 16px;
  display:flex; flex-direction:column; align-items:center; gap:2px;
  }
.mm-preview-cta:hover { background:#4C6534; }
.mm-preview-cta:disabled { background:var(--stone); color:var(--muted); cursor:not-allowed; }
.mm-cta-main { font-size:15px; font-weight:700; }
.mm-cta-sub { font-size:11.5px; opacity:.82; font-weight:500; }


/* config blocks */
.mm-block { border-top:1px solid var(--line); padding:22px 0; }
.mm-block:first-child { border-top:none; padding-top:6px; }
.mm-block.is-locked { opacity:.42; pointer-events:none; }
.mm-bh { display:flex; align-items:baseline; justify-content:space-between; gap:12px; margin-bottom:5px; }
.mm-bt { font-weight:800; text-transform:uppercase; letter-spacing:.05em; font-size:14px; margin:0; }
.mm-bd { font-size:13px; color:var(--muted); margin:0 0 14px; line-height:1.5; max-width:54ch; }
.mm-link { font-size:12.5px; font-weight:600; color:var(--survey); background:none;
  border:none; cursor:pointer; padding:0; }

/* The size comparison earns a pill rather than a text link. It answers the
   question people leave over -- how big is that really -- and as a bare link
   beside a heading it read as the least important thing in the block. */
.mm-cmp-open { display:inline-flex; align-items:center; gap:6px;
  padding:7px 13px; border-radius:999px;
  background:rgba(95,125,69,.09);
  box-shadow:inset 0 0 0 1px rgba(95,125,69,.28);
  color:var(--accent-deep); font-size:12.5px; font-weight:600;
  transition:background-color .2s var(--ease), box-shadow .2s var(--ease),
             transform .28s var(--ease); }
.mm-cmp-open svg { width:15px; height:15px; flex:none; }
.mm-cmp-open:hover { background:rgba(95,125,69,.15);
  box-shadow:inset 0 0 0 1px rgba(95,125,69,.45); transform:translateY(-1px); }
.mm-cmp-open:active { transform:scale(.97); transition-duration:.09s; }
.mm-cmp-open:focus-visible { outline:none; box-shadow:var(--ring),
  inset 0 0 0 1px rgba(95,125,69,.45); }
/* Open: filled, so it reads as a control that is currently on rather than an
   invitation to press it again. */
.mm-cmp-open.is-open { background:var(--accent); color:#FBFAF7;
  box-shadow:inset 0 0 0 1px var(--accent-deep); }
.mm-cmp-open.is-open:hover { background:var(--accent-deep); }
@media (max-width:480px){
  /* The heading and the pill stop sharing a line before either has to shrink. */
  .mm-b-size .mm-bh { flex-wrap:wrap; }
  .mm-cmp-open { padding:6px 11px; }
}

.mm-sizes { display:grid; grid-template-columns:repeat(2,1fr); gap:9px; }
/* With an odd number of sizes the last card would sit alone in the left column
   with a hole beside it. Spanning it fills the row and gives the biggest size
   the emphasis it deserves. Two routes to the same result: the class is set by
   the JS, the selector works it out positionally if the JS is older. */
.mm-sizes .mm-size-wide,
.mm-sizes .mm-size:last-child:nth-child(odd) { grid-column:1 / -1; }
.mm-size { text-align:left; background:#fff; border:1px solid var(--line); border-radius:12px;
  padding:13px; cursor:pointer; }
.mm-size { color:var(--ink); }
.mm-size:hover { border-color:var(--ink); }
.mm-size.is-on { border-color:var(--survey); box-shadow:inset 0 0 0 1px var(--survey); }
.mm-size-cm { font-weight:800; font-size:18px; letter-spacing:-.01em; }
.mm-size-area { font-size:11.5px; color:var(--muted); margin-top:3px; }
.mm-size-price { font-size:14px; margin-top:10px; font-weight:700; font-variant-numeric:tabular-nums; }
.mm-size-tag { display:inline-block; margin-top:7px; font-size:9.5px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--survey); border:1px solid currentColor; padding:2px 5px; border-radius:6px; }
.mm-compare { margin-top:12px; border:1px solid var(--line); border-radius:12px; background:#fff; padding:16px; }
.mm-compare-row { display:flex; align-items:flex-end; gap:14px; }
.mm-compare-sq { background:var(--stone2); border:1px solid var(--survey); border-radius:6px; }
.mm-compare-lab { font-size:10px; color:var(--muted); text-align:center; margin-top:5px; }

.mm-opts { display:flex; flex-wrap:wrap; gap:8px; }
.mm-opt { background:#fff; border:1px solid var(--line); border-radius:12px; padding:9px 13px;
  cursor:pointer; font-size:13px; display:flex; align-items:center; gap:9px; flex-wrap:wrap; }
.mm-opt { color:var(--ink); }
.mm-opt:hover { border-color:var(--ink); }
.mm-opt.is-on { box-shadow:inset 0 0 0 1px var(--survey); border-color:var(--survey); }
.mm-opt.is-off { opacity:.38; cursor:not-allowed; }
.mm-opt.is-off:hover { border-color:var(--line); }
.mm-lock { color:var(--ink); }
/* a plain on/off option: no swatch, so the label carries it */
.mm-opt.is-plain { padding:10px 16px; font-weight:600; }
.mm-sw { display:flex; border-radius:6px; overflow:hidden; border:1px solid rgba(0,0,0,.15); }
.mm-sw i { width:11px; height:16px; display:block; }
.mm-opt-extra { color:var(--muted); font-weight:600; }
.mm-sw-icon { display:flex; align-items:center; }
.mm-note { font-size:12px; color:var(--muted); margin-top:10px; line-height:1.5; }
.mm-sublabel { font-size:11px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); margin:18px 0 8px; }

/* add-on cards */
.mm-addon { display:flex; background:#fff; border:1px solid var(--line); border-radius:14px;
  overflow:hidden; margin-bottom:14px; }
.mm-addon-img { flex:none; width:120px; background:var(--stone2); display:flex; align-items:center;
  justify-content:center; font-size:9.5px; color:var(--muted); text-align:center; padding:8px; }
@media (min-width:520px){ .mm-addon-img { width:170px; } }
.mm-addon-img img { width:100%; height:100%; object-fit:cover; display:block; }
.mm-addon-body { flex:1; min-width:0; padding:15px 16px 16px; }
.mm-addon-h { display:flex; align-items:baseline; justify-content:space-between; gap:12px; }
.mm-addon-t { font-weight:800; font-size:15.5px; margin:0; }
.mm-addon-p { font-weight:700; font-size:13.5px; white-space:nowrap; font-variant-numeric:tabular-nums; }
.mm-addon-d { font-size:13px; color:var(--muted); line-height:1.45; margin:5px 0 13px; }
.mm-addon-btn { width:100%; border:none; border-radius:12px; background:var(--stone2);
  padding:12px; font-size:14px; font-weight:600; cursor:pointer; }
.mm-addon-btn { color:var(--ink); }
.mm-addon-btn:hover { background:var(--stone); }
.mm-addon.is-added { border-color:var(--survey); box-shadow:inset 0 0 0 1px var(--survey); }
.mm-addon.is-added .mm-addon-btn { background:var(--accent); color:#fff;
  }
.mm-addon.is-added .mm-addon-btn:hover { background:#4C6534; }
.mm-addon-state { display:flex; align-items:center; justify-content:space-between; gap:10px;
  margin-top:9px; font-size:12px; color:var(--muted); }
.mm-addon-remove { background:none; border:none; padding:0; font-size:12px; font-weight:600;
  color:var(--muted); text-decoration:underline; cursor:pointer; }

/* summary */
.mm-sum { border:1px solid var(--line); border-radius:12px; background:#fff; margin-top:26px; }
.mm-lines { padding:6px 16px 10px; }
.mm-line { display:flex; justify-content:space-between; gap:16px; padding:8px 0; font-size:13px;
  border-bottom:1px solid var(--stone2); }
.mm-line:last-child { border-bottom:none; }
.mm-line span:first-child { color:var(--muted); }
.mm-total { display:flex; justify-content:space-between; align-items:baseline; padding:0; }
.mm-total-v { font-weight:900; font-size:25px; letter-spacing:-.02em; font-variant-numeric:tabular-nums; }
.mm-addrow { padding:0; }
.mm-btn { font-size:14px; font-weight:700; padding:13px 18px; border-radius:12px;
  cursor:pointer; border:1px solid var(--ink); background:var(--ink); color:#fff; width:100%; }
/* Scoped twice over so neither my own `.mm button` rule nor a theme rule like
   button[type="button"] can win on specificity. This is the bug that made the
   Add to cart label invisible: black text on a black button. */
.mm .mm-btn { color:#fff; }
.mm .mm-btn.is-ghost { color:var(--ink); }
.mm .mm-preview-cta,
.mm .mm-preview-cta .mm-cta-main,
.mm .mm-preview-cta .mm-cta-sub { color:#fff; }
.mm .mm-preview-cta:disabled,
.mm .mm-preview-cta:disabled .mm-cta-main,
.mm .mm-preview-cta:disabled .mm-cta-sub { color:var(--muted); }
.mm .mm-addon.is-added .mm-addon-btn { color:#fff; }
.mm-btn:hover { background:#000; }
.mm-btn:disabled { opacity:.5; cursor:wait; }
.mm-btn.is-ghost { background:transparent; color:var(--ink); font-weight:600; }
.mm-btn.is-ghost:hover { background:var(--stone2); }
.mm-err { font-size:12.5px; color:#9B2C2C; margin-top:9px; }

.mm-bar { position:fixed; left:0; right:0; bottom:0; z-index:40; background:rgba(251,250,247,.97);
  border-top:1px solid var(--line); padding:10px 16px; display:flex; align-items:center; gap:12px; }
@media (min-width:941px){ .mm-bar { display:none !important; } }
.mm-bar-p { font-weight:900; font-size:19px; }
.mm-gal-thumb.is-cube { color:var(--accent-deep); border-color:var(--accent-deep); }
.mm-bar .mm-btn { width:auto; flex:1; padding:12px; }

/* modal */
.mm-modal { position:fixed; inset:0; background:rgba(20,22,26,.72); z-index:2147483000; display:flex;
  align-items:center; justify-content:center; padding:14px; }
.mm-modal-in { background:var(--paper); border-radius:14px; width:100%; max-width:1280px; max-height:94vh;
  display:flex; flex-direction:column; overflow:hidden; }
.mm-modal-h { padding:14px 18px; border-bottom:1px solid var(--line); display:flex;
  justify-content:space-between; align-items:flex-start; gap:14px; }
.mm-modal-h .mm-btn { width:auto; padding:8px 14px; font-size:13px; }
.mm-modal-t { font-weight:800; font-size:17px; margin:0; }
.mm-modal-s { font-size:13px; color:var(--muted); margin:3px 0 0; }
.mm-modal-f { padding:12px 16px; border-top:1px solid var(--line); display:flex;
  align-items:center; gap:10px; flex-wrap:wrap; }
.mm-modal-f .mm-btn { width:auto; flex:1; min-width:130px; }
.mm-foot-note { font-size:11.5px; color:var(--muted); }

.mm-canvas { flex:1; min-height:340px; background:linear-gradient(180deg,#E9E6DF,#D6D2C9); position:relative; }
.mm-canvas canvas { display:block; width:100%; height:100%; }
.mm-status { position:absolute; inset:0; z-index:6; display:flex; flex-direction:column; align-items:center;
  justify-content:center; gap:12px; text-align:center; padding:30px; font-size:13px; line-height:1.5;
  background:rgba(251,250,247,.8); }
.mm-spin { width:22px; height:22px; border:2px solid var(--line); border-top-color:var(--survey);
  border-radius:50%; animation:mm-spin .8s linear infinite; }
@keyframes mm-spin { to { transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce){ .mm-spin { animation-duration:2.4s; } }

/* marker picker */
.mm-mmap { position:relative; flex:1; min-height:340px; background:var(--stone); }
.mm-mmap .maplibregl-canvas-container { cursor:crosshair; }
.mm-bsearch { position:absolute; right:10px; top:10px; width:min(260px,52%); z-index:5; }
.mm-bsearch input { width:100%; font:inherit; font-size:13px; padding:9px 12px; border-radius:999px;
  border:1px solid var(--line); background:rgba(255,255,255,.96); }
.mm-bsearch-list { margin-top:6px; background:#fff; border:1px solid var(--line); border-radius:12px;
  max-height:190px; overflow:auto; }
.mm-bsearch-list button { display:block; width:100%; text-align:left; font-size:12.5px; padding:9px 11px;
  background:none; border:none; border-bottom:1px solid var(--stone2); cursor:pointer; }
.mm-bsearch-list button { color:var(--ink); }
.mm-bsearch-list button:hover { background:var(--stone2); }
.mm-swatches { display:flex; align-items:center; gap:9px; }
.mm-swatch { width:30px; height:30px; border-radius:50%; border:2px solid rgba(0,0,0,.18);
  cursor:pointer; padding:0; }
.mm-swatch.is-on { border-color:var(--survey); box-shadow:0 0 0 2px rgba(47,93,98,.25); }
.mm-swatch-lab { font-size:11.5px; color:var(--muted); margin-right:2px; }

/* plaque editor */
.mm-plaque-form { padding:18px; display:grid; gap:10px; }
.mm-input { font:inherit; font-size:14px; padding:11px 12px; border:1px solid var(--line);
  border-radius:12px; background:#fff; color:inherit; width:100%; }
.mm-input:focus { outline:2px solid var(--survey); outline-offset:-1px; }
.mm-plaque-prev { margin-top:6px; border:1px solid var(--line); border-radius:12px; padding:14px;
  background:linear-gradient(180deg,#F7F7F5,#DEDEDA); text-align:center; }
.mm-plaque-l1 { font-weight:800; letter-spacing:.1em; text-transform:uppercase; font-size:14px; }
.mm-plaque-l2 { font-size:12px; color:#4A4D52; margin-top:3px; }
.mm-plaque-c { font-size:10.5px; color:#6A6D72; margin-top:6px; }

/* preview progress + colour legend */
.mm-stage { font-size:14px; font-weight:600; }
.mm-prog { width:min(320px,72%); height:6px; border-radius:99px; background:var(--stone);
  overflow:hidden; margin:2px 0 2px; }
.mm-prog i { display:block; height:100%; background:var(--survey); border-radius:99px;
  transition:width .5s ease; }
.mm-legend { position:absolute; left:12px; bottom:12px; z-index:4; display:flex; flex-wrap:wrap;
  gap:5px 12px; max-width:75%; background:rgba(251,250,247,.93); border:1px solid var(--line);
  border-radius:12px; padding:8px 10px; }
.mm-legend span { display:flex; align-items:center; gap:6px; font-size:11px; }
.mm-legend i { width:11px; height:11px; border-radius:6px; border:1px solid rgba(0,0,0,.2); }
@media (max-width:600px){
  .mm-legend { font-size:10px; max-width:calc(100% - 24px); }
  .mm-hint { font-size:10.5px; }
}

/* two-panel preview, matching a product-shot + on-wall pairing */
.mm-pv { position:relative; flex:1; min-height:0; display:grid; gap:12px; padding:14px;
  grid-template-columns:1fr; align-content:start; overflow:auto; }
@media (min-width:760px){ .mm-pv { grid-template-columns:1fr 1fr; } }
/* One pane: a single shot stretched across a two-column grid becomes a very
   wide, very short image. Capped and centred so it keeps its proportions. */
@media (min-width:760px){
  .mm-pv.is-single { grid-template-columns:minmax(0,720px); justify-content:center; }
}
.mm-pv-pane { display:flex; flex-direction:column; gap:7px; min-width:0; }
.mm-pv-shot { position:relative; aspect-ratio:1/1; border-radius:12px; overflow:hidden;
  background-size:cover; background-position:center; cursor:zoom-in; }
.mm-pv-shot.is-plain { background:radial-gradient(125% 105% at 50% 0%,#F4F2EC 0%,#D9D6CE 100%); }
/* width set in JS from the real size against the scene's real width */
/* Light comes from the top right, so shadows go down and to the LEFT.
   Negative X offsets. The desk shot already carries a real cast shadow from
   the 3D scene, so this only adds the tight contact edge underneath. */
.mm-pv-desk { position:absolute; display:block; transform:translate(-50%,-50%);
  filter:drop-shadow(2px 3px 3px rgba(0,0,0,.26))
         drop-shadow(7px 12px 20px rgba(0,0,0,.14)); }
.mm-pv-zoom { position:absolute; right:10px; top:10px; width:30px; height:30px; border-radius:50%;
  background:rgba(255,255,255,.86); color:var(--ink); display:flex; align-items:center;
  justify-content:center; pointer-events:none; }
.mm-pv-room { position:relative; aspect-ratio:1/1; border-radius:12px; overflow:hidden;
  background-size:cover; background-position:center; cursor:zoom-in; }
.mm-pv-room.is-plain { background:linear-gradient(160deg,#46474a 0%,#2b2d30 100%); }
/* width is set in JS from the real size against the wall width */
/* The wall shot has no cast shadow in the render -- the shadow catcher is
   hidden for that camera -- so both layers come from here. drop-shadow traces
   the image's alpha, so it follows the frame silhouette rather than a box. */
.mm-pv-wall { position:absolute; display:block; transform:translate(-50%,-50%);
  filter:drop-shadow(3px 4px 3px rgba(0,0,0,.34))
         drop-shadow(12px 18px 28px rgba(0,0,0,.24)); }

.mm-lightbox { position:fixed; inset:0; z-index:2147483600; background:rgba(16,17,19,.92);
  display:flex; align-items:center; justify-content:center; padding:20px; cursor:zoom-out; }
.mm-lightbox img { max-width:100%; max-height:100%; object-fit:contain; }
.mm-pv-cap { font-size:11.5px; color:var(--muted); text-align:center; }
.mm-pv .mm-status { border-radius:12px; }

.mm-legend.is-inline { position:static; background:none; border:none; padding:0;
  max-width:none; flex:1; }

/* inline render block (mobile) */
.mm-inline { display:flex; flex-direction:column; }
.mm-inline .mm-backrow { padding:0 0 10px; }
.mm-inline .mm-pv { padding:0; gap:8px; grid-template-columns:1fr 1fr; overflow:visible; }
.mm-inline .mm-pv-shot, .mm-inline .mm-pv-room { border-radius:12px; }
.mm-inline .mm-modal-f { padding:10px 0 0; border-top:none; }
.mm-inline .mm-status { position:relative; inset:auto; grid-column:1 / -1;
  background:var(--stone2); border-radius:12px; padding:22px 16px; }
@media (min-width:941px){ .mm-inline { display:none !important; } }


/* ============================ cart popup ============================== */
/* Tuned to fit a single model plus every add-on on one screen at 900px tall.
   Anything that scrolls below the fold here is a section that does not get
   read, and these sections are the whole reason the popup exists. */
html.mm-cart-locked { overflow: hidden; }

.mm-cart-overlay { position: fixed; inset: 0; z-index: 9999;
  background: rgba(24,26,29,0); transition: background .22s ease;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
.mm-cart-overlay.is-open { background: rgba(24,26,29,.46); }

.mm-cart-panel { width: min(700px, 100%); max-height: calc(100vh - 36px);
  background: #F7F5F0; border-radius:22px; overflow-y: auto;
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  box-shadow: 0 24px 70px rgba(0,0,0,.28);
  opacity: 0; transform: scale(.97) translateY(10px);
  transition: opacity .22s ease, transform .22s ease; }
.mm-cart-overlay.is-open .mm-cart-panel { opacity: 1; transform: none; }
/* Nothing dims while the cart syncs. Every control updates optimistically, so
   a busy state would only add a flash and take away the ability to tap twice
   quickly -- which is exactly what people do with a quantity stepper. */

.mm-cart-head { position: sticky; top: 0; z-index: 2; background: #F7F5F0;
  display: flex; align-items: center; justify-content: space-between;
  padding: 15px 20px 8px; }
.mm-cart-head h2 { margin: 0; font-size: 21px; letter-spacing: -.015em; }
.mm-cart-x { background: none; border: 0; font-size: 26px; line-height: 1; cursor: pointer;
  color: #23262A; padding: 0 4px; }

.mm-cart-err { margin: 0 20px 8px; padding: 8px 11px; border-radius:12px;
  background: #FBE9E7; color: #8C2F22; font-size: 12.5px; }
.mm-cart-body { padding: 0 20px; }
.mm-cart-loading, .mm-cart-empty { padding: 44px 20px; text-align: center; color: #6B7076; }

.mm-cart-up { background: #fff; border-radius:16px; padding: 12px 14px; margin-bottom: 10px;
  display: flex; gap: 13px; align-items: center; border: 2px solid transparent; }
.mm-cart-up.is-on { border-color: #0071E3; }
.mm-cart-up-side { margin-left: auto; display: flex; align-items: center; gap: 12px;
  flex: 0 0 auto; }
.mm-cart-up-price { font-size: 15px; white-space: nowrap; }
.mm-inc { color: #9AA0A6; font-size: 12px; }
.mm-cart-up img { width: 52px; height: 52px; object-fit: contain; flex: 0 0 auto; }
.mm-cart-up-txt { flex: 1; min-width: 0; }
.mm-cart-up-txt strong { display: block; font-size: 15px; }
.mm-cart-up-txt p { margin: 2px 0 8px; font-size: 13px; color: #6B7076; line-height: 1.4; }

.mm-cart-btn { background: #16181B; color: #fff; border: 0; border-radius: 999px;
  padding: 9px 17px; font: inherit; font-size: 14px; cursor: pointer; white-space: nowrap; }

.mm-cart-line { display: flex; gap: 14px; padding: 12px 0; align-items: flex-start;
  border-bottom: 1px solid #E4E6E8; }
.mm-cart-thumb { width: 96px; height: 96px; border-radius:14px; overflow: hidden;
  background: #E7E5E0; flex: 0 0 auto; }
.mm-cart-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mm-cart-info { flex: 1; min-width: 0; }
.mm-cart-info h3 { margin: 0; font-size: 17px; letter-spacing: -.01em; }
.mm-cart-sub { margin: 1px 0 5px; font-size: 13px; color: #6B7076; }
/* Three levels of the same fact, each quieter than the last: the place is the
   heading, the spec sits under it, the coordinates under that. */
.mm-cart-geo { margin: 0 0 6px; font-size: 12px; color: #8A9096;
  font-variant-numeric: tabular-nums; }
/* Detail belonging to an add-on row -- the marker count, the plaque wording. */
.mm-cart-break em { display: block; font-style: normal; font-size: 12px;
  color: #8A9096; margin-top: 1px; }
.mm-cart-break { margin: 0; font-size: 13px; color: #4A4F55; }
.mm-cart-break > div { display: flex; gap: 12px; }
.mm-cart-break dt { margin: 0; }
.mm-cart-break dd { margin: 0 0 0 auto; }
.mm-cart-link { background: none; border: 0; padding: 5px 0 0; font: inherit; font-size: 13px;
  color: #0071E3; cursor: pointer; }
.mm-cart-link:hover { text-decoration: underline; }
.mm-cart-side { text-align: right; flex: 0 0 auto; display: flex; align-items: center; gap: 14px; }
.mm-cart-qty { display: inline-flex; align-items: center; background: #EAEBED;
  border-radius: 999px; padding: 3px; user-select: none; -webkit-user-select: none; }
.mm-cart-qty button { width: 30px; height: 30px; border-radius: 50%; border: 0; background: #fff;
  font: inherit; font-size: 15px; line-height: 1; cursor: pointer; color: #23262A;
  box-shadow: 0 1px 2px rgba(0,0,0,.07); transition: transform .12s ease; }
.mm-cart-qty button:active { transform: scale(.9); }
.mm-cart-qty span { min-width: 26px; text-align: center; font-size: 14px;
  font-variant-numeric: tabular-nums; }
.mm-cart-lineprice { font-size: 17px; min-width: 64px; }

/* Themes style their own buttons, and these are buttons -- without an explicit
   colour the headings inside them inherit the theme's link blue. */
.mm-cart-bundle, .mm-prio-opt, .mm-cart-bundle strong, .mm-cart-bundle em,
.mm-prio-opt strong, .mm-prio-opt p, .mm-prio-price { color: #23262A; }
.mm-prio-opt p { color: #5A6068; }
.mm-cart-bundle em { color: #6B7076; }

.mm-cart-bundle { width: 100%; background: #fff; border: 0; border-radius:16px;
  padding: 12px 14px; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; font: inherit; text-align: left; cursor: pointer; margin: 10px 0; }
.mm-cart-bundle strong { display: block; font-size: 15px; }
.mm-cart-bundle em { font-style: normal; font-size: 13px; color: #6B7076; }
.mm-cart-bundle i { width: 34px; height: 34px; border-radius: 50%; background: #16181B;
  color: #fff; font-style: normal; font-size: 19px; display: grid; place-items: center;
  flex: 0 0 auto; }

.mm-cart-prio { background: #fff; border-radius:16px; padding: 13px 14px; }
.mm-cart-prio h4 { margin: 0 0 9px; font-size: 15px; }
.mm-cart-prio-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.mm-prio-opt { position: relative; text-align: left; background: #F1F2F3;
  border: 2px solid transparent; border-radius:14px; padding: 11px 12px; font: inherit;
  cursor: pointer; }
.mm-prio-opt.is-on { border-color: #0071E3; background: #fff; }
.mm-prio-opt strong { display: block; font-size: 14px; margin-bottom: 3px; padding-right: 52px; }
.mm-prio-opt p { margin: 0; font-size: 12.5px; line-height: 1.4; color: #5A6068; }
.mm-prio-price { position: absolute; top: 11px; right: 12px; font-size: 13px; }

/* ------------------------------- gift note (C1.2) --------------------- */
.mm-cart-gift { background: #fff; border-radius:16px; margin-top: 10px;
  border: 2px solid transparent; overflow: hidden; }
.mm-cart-gift.is-on { border-color: #0071E3; }
.mm-cart-gift-bar { display: flex; width: 100%; align-items: center; justify-content: space-between;
  gap: 12px; padding: 14px; background: none; border: 0; margin: 0; cursor: pointer;
  font: inherit; font-size: 13.5px; letter-spacing: .05em; text-transform: uppercase;
  color: #16181B; text-align: left; }
.mm-cart-gift-bar b { font-weight: 800; }
.mm-cart-gift-pm { position: relative; width: 12px; height: 12px; flex: 0 0 auto; }
.mm-cart-gift-pm::before, .mm-cart-gift-pm::after { content: ""; position: absolute; left: 0;
  top: 5.25px; width: 12px; height: 1.5px; background: #16181B; transition: transform .2s; }
.mm-cart-gift-pm::after { transform: rotate(90deg); }
.mm-cart-gift.is-open .mm-cart-gift-pm::after { transform: rotate(0deg); }
.mm-cart-gift-body { display: none; padding: 0 14px 14px; }
.mm-cart-gift.is-open .mm-cart-gift-body { display: block; }
.mm-cart-gift-lede { margin: 0 0 11px; font-size: 12.5px; color: #6B7076; line-height: 1.45; }
.mm-cart-gift-row { display: flex; gap: 12px; align-items: flex-start; }
.mm-cart-gift-env { flex: 0 0 76px; display: flex; flex-direction: column; align-items: center;
  gap: 7px; padding-top: 4px; font-size: 12px; color: #6B7076; white-space: nowrap; }
.mm-cart-gift-env svg, .mm-cart-gift-env img { display: block; width: 76px; height: 52px;
  object-fit: cover; border-radius: 3px; }
.mm-cart-giftmsg { width: 100%; padding: 9px 11px; border: 1px solid #D8DBDE;
  border-radius:12px; font: inherit; font-size: 13.5px; line-height: 1.45; resize: vertical;
  box-sizing: border-box; background: #FAFAFB; }
.mm-cart-gift-row .mm-cart-giftmsg { flex: 1 1 auto; min-height: 92px; margin: 0; }
.mm-cart-giftmsg:focus { outline: none; border-color: #0071E3; background: #fff; }
.mm-cart-giftcount { display: block; text-align: right; font-style: normal; font-size: 12px;
  color: #8A9097; margin: 5px 0 10px; }
.mm-cart-gift .mm-cart-gifttoggle { display: block; width: 100%; padding: 14px 18px;
  font-weight: 700; font-size: 13.5px; letter-spacing: .05em; text-transform: uppercase; }
.mm-cart-gift.is-on .mm-cart-gifttoggle { background: #fff; color: #16181B;
  box-shadow: inset 0 0 0 1.5px #16181B; }

.mm-cart-foot { padding: 14px 20px 18px; }
.mm-cart-foot::before { content: ""; display: block; height: 1px; background: #E1E3E5;
  margin: 0 0 13px; }
.mm-cart-total { display: flex; justify-content: space-between; align-items: baseline; }
.mm-cart-total span { font-size: 19px; }
.mm-cart-total b { font-size: 22px; }
.mm-cart-tax { margin: 1px 0 10px; font-size: 12px; color: #6B7076; }

/* Free shipping progress. A bar rather than a sentence, because the point is
   how close they are, not what the rule is. */
.mm-cart-ship { margin: 0 0 10px; padding: 10px 12px; border-radius: 12px;
  background: rgba(95,125,69,.07); border: 1px solid rgba(95,125,69,.18); }
.mm-cart-ship p { margin: 0 0 7px; font-size: 12.5px; color: #3F5230; }
.mm-cart-ship b { font-weight: 700; }
.mm-cart-ship-bar { display: block; height: 5px; border-radius: 999px;
  background: rgba(95,125,69,.16); overflow: hidden; }
.mm-cart-ship-bar i { display: block; height: 100%; border-radius: 999px;
  background: var(--accent); transition: width .4s var(--ease, ease); }
.mm-cart-ship.is-done { background: rgba(95,125,69,.10);
  border-color: rgba(95,125,69,.28); }
.mm-cart-ship.is-done p { margin: 0; font-weight: 600; }
/* The made-to-order terms. A statement now, not a checkbox: no card, no
   border, no tick. It reads as part of the total block it sits under rather
   than as a form control demanding attention, which is what a disclosure
   should do -- present and legible, not in the way. */
.mm-cart-terms { margin: 0 0 10px; font-size: 12.5px; line-height: 1.5; color: #4A4F55; }
.mm-cart-terms em { display: block; font-style: normal; color: #8A9097; margin-top: 4px; }
.mm-cart-checkout { width: 100%; margin-top: 10px; padding: 14px; border: 0; border-radius:14px;
  /* Literal, NOT var(--accent): that token is #5F7D45, the green the free
     shipping bar uses. This button matches the configurator's blue. */
  background: #0071E3; color: #fff; font: inherit; font-size: 17px;
  cursor: pointer; transition: background .16s ease; }
.mm-cart-checkout:hover { background: #0058B0; }
.mm-cart-checkout:active { background: #004A94; }
.mm-cart-checkout:disabled { opacity: .45; cursor: not-allowed; }
.mm-cart-pay { margin: 12px 0 7px; text-align: center; font-size: 13px; font-weight: 600; }
/* Themes commonly set img { width:100% } globally, which made every payment
   icon a full-width flex item and stacked them one per row. */
.mm-cart-icons { display: flex; flex-wrap: wrap; gap: 5px; justify-content: center;
  align-items: center; }
.mm-cart-icons img { height: 22px; width: auto; max-width: none; flex: 0 0 auto;
  display: block; border-radius:8px; }

@media (max-width: 620px) {
  .mm-cart-overlay { padding: 0; align-items: flex-end; }
  .mm-cart-panel { width: 100%; max-height: 94vh; border-radius:22px 22px 0 0;
    transform: translateY(100%); opacity: 1; }
  .mm-cart-overlay.is-open .mm-cart-panel { transform: none; }
  .mm-cart-head { padding: 14px 16px 8px; }
  .mm-cart-body { padding: 0 16px; }
  .mm-cart-foot { padding: 14px 16px 16px; }
  .mm-cart-thumb { width: 76px; height: 76px; }
  .mm-cart-line { gap: 12px; flex-wrap: wrap; }
  .mm-cart-side { width: 100%; justify-content: space-between; }
  .mm-cart-prio-row { grid-template-columns: 1fr; }
  .mm-cart-info h3 { font-size: 16px; }
  .mm-cart-gift-env { flex-basis: 64px; }
  .mm-cart-gift-env svg, .mm-cart-gift-env img { width: 64px; height: 44px; }

  /* Checkout stays reachable without scrolling to the end of a long cart, and
     clears the iPhone home indicator. */
  /* Sticky footer, kept to the smallest useful height: total, button, icons.
     A soft shadow here smeared over the card above it, so it is a hairline. */
  .mm-cart-foot { position: sticky; bottom: 0; background: #F7F5F0;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid #E1E3E5; }
  .mm-cart-foot::before { display: none; }
  .mm-cart-total span { font-size: 16px; }
  .mm-cart-total b { font-size: 19px; }
  .mm-cart-tax { margin: 0 0 8px; font-size: 11px; }
  .mm-cart-checkout { margin-top: 0; padding: 13px; font-size: 16px; border-radius:14px; }
  .mm-cart-pay { margin: 8px 0 4px; font-size: 11px; font-weight: 500; color: #7C838A; }
  .mm-cart-icons { gap: 4px; }
  .mm-cart-icons img { height: 16px; border-radius:6px; }

  /* Upsell: the image and the button were each claiming a row of their own. */
  .mm-cart-up { gap: 10px; padding: 10px 12px; margin-bottom: 8px; align-items: center; }
  .mm-cart-up img { width: 38px; height: 38px; }
  .mm-cart-up-txt strong { font-size: 14px; }
  .mm-cart-up-txt p { margin: 1px 0 0; font-size: 12px; line-height: 1.35; }
  /* Control on the right, text on the left -- the button used to drop onto its
     own line and cost a row of height. */
  .mm-cart-up { flex-wrap: nowrap; }
  .mm-cart-up .mm-cart-btn { padding: 8px 13px; font-size: 13px; align-self: center;
    flex: 0 0 auto; margin-left: auto; }
  .mm-cart-up-side { gap: 8px; }
  .mm-cart-up-price { font-size: 14px; }

  /* Line: quantity tucks up under the text instead of taking a full row. */
  .mm-cart-line { padding: 10px 0; }
  .mm-cart-side { margin-top: 8px; gap: 10px; }
  .mm-cart-qty { padding: 2px; }
  .mm-cart-qty button { width: 32px; height: 32px; }
  .mm-cart-lineprice { font-size: 16px; }
  .mm-cart-sub { margin: 0 0 3px; }
  .mm-cart-geo { margin: 0 0 4px; font-size: 11.5px; }
  .mm-cart-break { font-size: 12.5px; }
  .mm-cart-break em { font-size: 11.5px; }
  .mm-cart-link { padding-top: 3px; font-size: 12.5px; }

  .mm-cart-bundle { padding: 10px 12px; margin: 8px 0; }
  .mm-cart-bundle strong { font-size: 14px; }
  .mm-cart-bundle em { font-size: 12px; }
  .mm-cart-bundle i { width: 30px; height: 30px; font-size: 17px; }

  .mm-cart-prio { padding: 11px 12px; }
  .mm-cart-prio h4 { margin-bottom: 7px; font-size: 14px; }
  .mm-cart-prio-row { gap: 8px; }
  .mm-prio-opt { padding: 9px 11px; }

  .mm-cart-gift { margin-top: 8px; }
  .mm-cart-gift-bar { padding: 12px; }
  .mm-cart-gift-body { padding: 0 12px 12px; }
  .mm-cart-giftmsg { font-size: 13px; }
  .mm-cart-terms { font-size: 11.5px; margin: 0 0 8px; }
}

/* A grab handle, so the sheet reads as something you can dismiss. */
@media (max-width: 620px) {
  .mm-cart-head::before { content: ""; position: absolute; top: 6px; left: 50%;
    transform: translateX(-50%); width: 36px; height: 4px; border-radius:6px;
    background: #D2D5D8; }
  .mm-cart-head { position: sticky; padding-top: 16px; }
}

/* Shown under the preview only when the mirror finish is selected. */
.mm-mirror-note { flex-basis: 100%; margin: 0 0 10px; padding: 11px 14px;
  border-radius: 14px; background: #EEF2F7; border-left: 3px solid #5B87AC;
  color: #2B3947; font-size: 13px; line-height: 1.5; font-weight: 500; }
.mm-mirror-note strong { display: block; font-weight: 700; margin-bottom: 1px; }
/* No water in the crop: the finish has been paid for and will do nothing. That
   is a warning, not a note, and should not look like one. */
.mm-mirror-note.is-warn { background: #FBF3E4; border-left-color: #C89A2B;
  color: #4A3A16; }
@media (max-width: 560px) { .mm-mirror-note { font-size: 12.5px; } }


/* ===================== option cards (size / frame / colour) ============== */
/* Two-up cards with the choice named and the difference shown, rather than a
   row of chips. Comparing four colour schemes needs to be possible at a glance,
   which small dots never allowed. */
.mm-cards { display:grid; gap:10px; }
.mm-cards-2 { grid-template-columns:1fr 1fr; }
/* The colour schemes only. Meadow spans the row because it is the one with
   four materials to show, and a full-width swatch bar reads as a paint chart
   rather than a stripe. Scoped to this grid so the two frame cards, which are
   a genuine pair, keep sitting side by side. */
.mm-cards-cw .mm-card:first-child { grid-column:1 / -1; }
.mm-card { position:relative; display:flex; flex-direction:column; gap:9px;
  background:#fff; border:2px solid #E3E1DC; border-radius:16px; padding:13px 14px;
  font:inherit; text-align:left; cursor:pointer; color:#23262A;
  transition:border-color .15s ease, background .15s ease; }
.mm-card:hover { border-color:#C9C5BD; }
.mm-card.is-on { border-color:#5F7D45; background:#F7FAF4; }
.mm-card-top { display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
.mm-card-name { font-size:15px; font-weight:600; }
.mm-card-extra { font-size:13px; color:#6B7076; white-space:nowrap; }
.mm-card-frame { flex-direction:row; align-items:center; justify-content:space-between; }
.mm-card-dot { width:26px; height:26px; border-radius:50%; border:1px solid rgba(0,0,0,.14);
  flex:0 0 auto; }
/* the swatch bar reads like a paint chart: the actual materials, to proportion */
.mm-card-bar { display:flex; height:20px; border-radius:999px; overflow:hidden;
  border:1px solid rgba(0,0,0,.08); }
.mm-card-bar i { flex:1 1 0; display:block; }

/* ============================== add-on cards ============================= */
/* Images were each a different height, so the cards jittered down the page.
   A fixed square that the photo fills keeps the rhythm even. */
/* Wrapping, because the plaque editor is appended as a third child. Without it
   the panel became a column beside the photo and the description was squeezed
   to one letter per line. The image and body keep the first row; anything
   flagged full-width drops to its own row beneath. */
.mm-addon { display:flex; flex-wrap:wrap; gap:0; align-items:stretch; background:#fff;
  border:1px solid #E3E1DC; border-radius:16px; padding:0; overflow:hidden;
  margin-bottom:10px; }
/* Absolutely positioned inside a relative box. Themes routinely set
   img { height:auto }, which beat height:100% and left the photo floating in a
   grey panel instead of filling it. */
.mm-addon-img { position:relative; width:38%; max-width:190px; flex:0 0 38%;
  align-self:stretch; min-height:138px; background:#EFEDE8; overflow:hidden;
  display:flex; align-items:center; justify-content:center;
  font-size:11px; color:#8A8F95; }
.mm-addon-img img { position:absolute; inset:0; width:100%; height:100%;
  max-width:none; object-fit:cover; display:block; }
.mm-addon-body { flex:1 1 0; min-width:0; padding:12px 14px; display:flex;
  flex-direction:column; gap:5px; }
.mm-addon-h { display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
.mm-addon-t { margin:0; font-size:15px; }
.mm-addon-p { font-size:14px; white-space:nowrap; }
.mm-addon-d { margin:0; font-size:13px; line-height:1.45; color:#6B7076; }
.mm-addon-btn { align-self:flex-start; margin-top:auto; background:#F1EFEA; border:0;
  border-radius:999px; padding:8px 16px; font:inherit; font-size:13.5px; cursor:pointer;
  color:#23262A; }
.mm-addon.is-added { border-color:#5F7D45; }
.mm-addon.is-added .mm-addon-btn { background:#5F7D45; color:#fff; }

@media (max-width:940px){
  .mm-cards { gap:8px; }
  .mm-card { padding:11px 12px; border-radius:14px; }
  .mm-card-name { font-size:14px; }
  .mm-addon-img { width:36%; flex:0 0 36%; min-height:118px; }
  /* Left padding restored: the card's flex gap is gone now, so zeroing this
     put the text hard against the photograph. */
  .mm-addon-body { padding:10px 12px; }
  .mm-addon-t { font-size:14px; }
  .mm-addon-d { font-size:12.5px; }
  .mm-addon-btn { padding:7px 14px; font-size:13px; }
}


/* ======================= inline comparison panels ======================= */
/* Opens directly beneath its own heading rather than below the options, so the
   thing being compared is still on screen when the photos appear. */
/* The comparison row is the picker, not an illustration of it. Cells are
   buttons: they show the selection, they take a press, and they go quiet when
   the option behind them is unavailable. */
.mm-cmp { margin:0 0 14px; }
.mm-cmp-row { display:grid; gap:10px; grid-auto-flow:column; grid-auto-columns:minmax(0,1fr);
  padding-bottom:2px; }
.mm-cmp-cell { display:flex; flex-direction:column; gap:7px; min-width:0;
  padding:0; border:0; background:none; font:inherit; cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  transition:transform .28s var(--ease), opacity .2s var(--ease); }
.mm-cmp-cell img, .mm-cmp-blank { width:100%; aspect-ratio:1/1; object-fit:cover;
  border-radius:14px; display:block; background:#EFEDE8;
  box-shadow:0 0 0 1px rgba(27,31,35,.08), var(--sh-1);
  transition:box-shadow .28s var(--ease); }
.mm-cmp-lab { font-size:12.5px; color:var(--muted); text-align:center;
  transition:color .2s var(--ease); }

.mm-cmp-cell:hover img, .mm-cmp-cell:hover .mm-cmp-blank {
  box-shadow:0 0 0 1px rgba(27,31,35,.16), var(--sh-2); }
.mm-cmp-cell:hover { transform:translateY(-2px); }
.mm-cmp-cell:active { transform:scale(.985); transition-duration:.09s; }

/* Selected: a ring in the accent, and the label promoted. Two signals, because
   on a row of photographs a border alone is easy to miss. */
.mm-cmp-cell.is-on img, .mm-cmp-cell.is-on .mm-cmp-blank {
  box-shadow:0 0 0 2px var(--accent), var(--sh-2); }
.mm-cmp-cell.is-on .mm-cmp-lab { color:var(--ink); font-weight:600; }

.mm-cmp-cell.is-off { opacity:.38; cursor:not-allowed; }
.mm-cmp-cell.is-off:hover { transform:none; }
.mm-cmp-cell:focus-visible { outline:none; }
.mm-cmp-cell:focus-visible img, .mm-cmp-cell:focus-visible .mm-cmp-blank {
  box-shadow:var(--ring), var(--sh-2); }
.mm-bh { display:flex; align-items:baseline; justify-content:space-between; gap:12px; }
.mm-bh .mm-link { flex:0 0 auto; }

@media (max-width:940px){
  .mm-cmp-row { grid-auto-columns:minmax(0,1fr); gap:6px; }
  .mm-cmp-lab { font-size:11.5px; }
}


/* Close control on the zoomed scene. */
.mm-lb-close { position:fixed; left:50%; bottom:max(18px, env(safe-area-inset-bottom, 0px));
  transform:translateX(-50%); background:#fff; color:#23262A; border:0; border-radius:999px;
  padding:11px 26px; font:inherit; font-size:15px; cursor:pointer;
  box-shadow:0 6px 20px rgba(0,0,0,.28); z-index:2; }


/* ========================= engraved plaque panel ======================== */
/* Expands inside the add-on card. Typing and seeing the result belong in the
   same place -- a modal would cover the model the plaque is being made for. */
/* Its own row across the full width of the card. */
.mm-plq { flex:0 0 100%; width:100%; box-sizing:border-box; order:9;
  border-top:1px solid #E9E6E0; padding:14px; display:flex; flex-direction:column;
  gap:12px; }
.mm-plq.mm-hide { display:none; }
.mm-plq-field { display:flex; flex-direction:column; gap:5px; }
.mm-plq-lab { font-size:11px; letter-spacing:.09em; text-transform:uppercase; color:#8A8F95; }
.mm-plq-row { position:relative; display:flex; align-items:center; }
.mm-plq-input { flex:1; padding:11px 62px 11px 13px; border:1px solid #D8DBDE;
  border-radius:14px; font:inherit; font-size:15px; background:#fff; box-sizing:border-box;
  min-width:0; }
.mm-plq-input:focus { outline:none; border-color:#5F7D45; }
.mm-plq-count { position:absolute; right:13px; font-size:12px; color:#9AA0A6;
  pointer-events:none; font-variant-numeric:tabular-nums; }

/* 40 x 10 mm, held to that ratio so the engraving is judged at its real shape */
.mm-plq-plate { aspect-ratio:4/1; width:100%; border-radius:8px; display:flex;
  align-items:center; gap:12px; padding:0 12px; box-sizing:border-box; overflow:hidden;
  background:linear-gradient(100deg,#C9CBCD 0%,#EDEEF0 22%,#D5D7D9 46%,#F2F3F4 68%,#CDCFD1 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7), inset 0 -1px 0 rgba(0,0,0,.14); }
.mm-plq-brand { flex:0 1 auto; min-width:0; display:flex; align-items:center;
  max-width:42%; font-weight:400; font-size:clamp(7px,1.9vw,9.5px); letter-spacing:.14em;
  text-transform:uppercase; line-height:1.2; color:#3A3E43; }
.mm-plq-brand img { max-height:52%; max-width:100%; width:auto; height:auto; display:block; }
.mm-plq-text { flex:1 1 auto; display:flex; flex-direction:column; justify-content:center;
  min-width:0; border-left:1px solid rgba(0,0,0,.22); padding-left:12px; }
/* The title sits in a <b>, so it was inheriting bold. Engraving is cut, not
   printed -- the line has an even weight throughout and gets its presence from
   spacing rather than thickness. Light weight, generous tracking, small caps
   sizing: that is what reads as metal rather than as a label. */
.mm-plq-t1 { font-weight:400; font-size:clamp(10px,2.7vw,13px); letter-spacing:.16em;
  text-transform:uppercase; color:#23262A;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.mm-plq-t2 { font-style:normal; font-weight:400; font-size:clamp(8px,2vw,10px);
  letter-spacing:.13em; text-transform:uppercase; color:#5A6068; margin-top:2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.mm-plq-dim { margin:0; font-size:12px; color:#8A8F95; text-align:center; }

@media (max-width:940px){
  .mm-plq { padding:12px; gap:10px; }
  .mm-plq-input { font-size:14px; padding:10px 58px 10px 12px; }
  .mm-plq-plate { padding:0 12px; gap:10px; }
  .mm-plq-text { padding-left:10px; }
}


/* =================== preview header, footer and skeleton ================ */
/* Square panes once there is something to show; collapsed entirely while the
   model builds, so the progress card fills the space instead of a line of text
   floating in a tall empty box. */
.mm-inline { margin:12px 0; }
.mm-inline .mm-pv-shot, .mm-inline .mm-pv-room { aspect-ratio:1/1; }
/* Collapse the two panes and their captions while the model builds -- but NOT
   the container, because the progress card lives inside it. Hiding .mm-pv took
   the status message down with the panes and left the whole block blank, which
   looked exactly like a render that never started. */
.mm-inline.mm-pv-loading .mm-pv-pane { display:none; }
.mm-inline.mm-pv-loading .mm-pv { display:block; gap:0; }
.mm-inline.mm-pv-loading .mm-backrow { display:none; }
.mm-cmp-shot img { width:100%; height:auto; display:block; border-radius:16px; }


/* The closing block: what it is, what it costs, then see it, then buy it. */
.mm-total-n { font-size:17px; font-weight:600; }
.mm-total-v { font-size:22px; font-weight:600; }

/* The preview is the bigger ask of the two -- it is what convinces someone the
   model is theirs, and it costs nothing to press. Given more weight than the
   buy button beneath it. */
/* The card itself has no padding -- the title row and the button row each add
   their own 16px. Anything sitting directly in the card has to match that by
   margin, or it runs to the edges while everything else stays inset.
   width:auto rather than 100%: a flex container fills its parent minus its own
   margins, whereas 100% measures the parent and then adds the margins on top. */
/* The card carries the padding now, not each child. Chasing per-child margins
   meant every new element had to remember the inset, and a stale mobile rule
   could quietly undo it -- which is exactly what kept happening. With the
   padding in one place, plain width:100% is correct everywhere. */
.mm-sum { padding:16px; margin-top:14px; }
.mm-sum .mm-preview-cta { width:100%; margin:14px 0 0;
  padding:20px 16px; border-radius:16px; gap:4px; box-sizing:border-box; }

/* Once the render is building, it takes the button's place -- the button has
   done its job and leaving it there invites a second press mid-render. */
.mm-pdp.is-rendering .mm-sum .mm-preview-cta { display:none; }
.mm-sum .mm-preview-cta .mm-cta-main { font-size:19px; }
.mm-sum .mm-preview-cta .mm-cta-sub { font-size:13px; }
/* Between the two buttons. */
.mm-sum .mm-inline { margin:14px 0 0; }
/* Small and quiet: this is how you dismiss the render and get the button back,
   not a primary action competing with Add to cart. */
.mm-inline .mm-backrow { margin:0 0 10px; }
.mm-inline .mm-backrow .mm-btn.is-ghost { width:auto; padding:7px 12px; font-size:13px;
  border:0; font-weight:600; }
.mm-sum .mm-addrow { margin-top:12px; }
.mm-sum .mm-addrow .mm-btn { width:100%; padding:16px; font-size:17px;
  border-radius:16px; box-sizing:border-box; }

@media (max-width:940px){
  .mm-total-n { font-size:15px; }
  .mm-total-v { font-size:20px; }
  .mm-sum { padding:14px; margin-top:10px; }
  /* Sections were spending 44px of every screen on their own top and bottom
     padding, which on a phone is most of a thumb-scroll of nothing. */
  .mm-block { padding:16px 0; }
  .mm-b-addons { padding-bottom:6px; }
  .mm-sum .mm-preview-cta { padding:18px 14px; margin:12px 0 0; width:100%; }
  .mm-sum .mm-preview-cta .mm-cta-main { font-size:18px; }
  .mm-sum .mm-inline { margin:12px 0 0; }
  .mm-sum .mm-addrow .mm-btn { padding:15px; font-size:16px; }
}


/* iOS zooms the whole page whenever a focused input is under 16px. Every text
   field in here goes to 16px on touch layouts -- it is the only reliable way to
   stop it, and the zoom never returns on its own afterwards. */
@media (max-width:940px){
  .mm-input, .mm-plq-input, .mm-cart-giftmsg, .mm-bsearch input,
  .mm-search input, input[type="text"].mm-input, input[type="email"].mm-input {
    font-size:16px;
  }
}

/* The crop square, drawn on the marker map so it is obvious which buildings
   will actually make it onto the plate. */
.mm-mmap .mm-crop-hint { position:absolute; left:12px; bottom:12px; z-index:2;
  background:rgba(24,26,29,.78); color:#fff; font-size:11.5px; padding:5px 9px;
  border-radius:999px; pointer-events:none; }


/* ================= render block: the render and nothing else ============ */
/* The footer's class is mm-modal-f, not the mm-pv-foot I had guessed at, which
   is why the legend and geometry counts kept surviving. The legend repeats a
   colourway chosen two sections earlier and the counts were my diagnostics, not
   the customer's information -- both still go to the console. */
.mm-inline .mm-modal-f,
.mm-inline .mm-legend,
.mm-inline .mm-foot-note,
/* Shown inline too. It was hidden here to save space, which meant the one
   explanation of why the water is black only ever appeared in the pop-out --
   and most people never open that. Someone who has paid for a mirror finish
   and is looking at a black river needs this in front of them. */

/* Free shipping, at the moment of deciding. Quiet by default, and it earns a
   tick only once the threshold is actually met. */
.mm-ship-note { flex-basis: 100%; margin: 8px 0 0; font-size: 12.5px;
  color: var(--muted); text-align: center; }
.mm-ship-note.is-done { color: var(--accent-deep); font-weight: 600; }
.mm-ship-note.is-done::before { content: '\2713\00a0'; }

/* The one thing on the page that takes money. */
.mm-sum .mm-addrow .mm-btn { font-weight: 800; letter-spacing: .01em; }


/* ============== preview vs finished model, drag to compare ============== */
/* A real button, not a text link buried in a caption -- it was invisible. */
/* One wide target rather than a caption and a small pill. The split thumbnail
   does the explaining: half render, half photograph, divided down the middle,
   which is exactly what opens when it is pressed. */
.mm-pv-example { display:flex; align-items:center; gap:14px; width:100%;
  margin:0 0 14px; padding:12px 14px; text-align:left; cursor:pointer;
  background:#fff; border:1px solid var(--line); border-radius:16px;
  font:inherit; color:var(--ink); }
.mm-pv-example-thumb { position:relative; flex:0 0 auto; width:56px; height:56px;
  border-radius:12px; overflow:hidden; background:var(--stone2); }
.mm-pv-example-thumb img { position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; display:block; }
/* the render on the left half, the real thing on the right */
.mm-pv-example-thumb .is-prev { clip-path:inset(0 50% 0 0); }
.mm-pv-example-thumb .is-real { clip-path:inset(0 0 0 50%); }
.mm-pv-example-split { position:absolute; top:0; bottom:0; left:50%; width:2px;
  margin-left:-1px; background:rgba(255,255,255,.9); }
.mm-pv-example-txt { flex:1 1 auto; min-width:0; display:flex; flex-direction:column;
  gap:2px; }
.mm-pv-example-txt strong { font-size:14.5px; font-weight:700; letter-spacing:-.005em; }
.mm-pv-example-txt em { font-style:normal; font-size:12.5px; color:var(--muted); }
.mm-pv-example-go { flex:0 0 auto; display:inline-flex; align-items:center; gap:2px;
  font-size:13.5px; font-weight:600; color:var(--accent); }
.mm-pv-example-go svg { width:16px; height:16px; transition:transform .28s var(--ease); }
.mm-pv-example:hover { border-color:rgba(95,125,69,.45); background:rgba(95,125,69,.04); }
.mm-pv-example:hover .mm-pv-example-go svg { transform:translateX(2px); }
@media (max-width:520px){
  /* the words go, the target does not -- the chevron alone still reads as
     "there is more here" once the thumbnail has said what it is */
  .mm-pv-example-go { font-size:0; gap:0; }
  .mm-pv-example-go svg { width:20px; height:20px; }
  .mm-pv-example-txt strong { font-size:14px; }
}

.mm-cmpx { --mm-x:50%; position:relative; width:100%; aspect-ratio:4/3;
  border-radius:16px; overflow:hidden; background:#E7E5E0; cursor:ew-resize;
  user-select:none; -webkit-user-select:none; touch-action:pan-y; }
.mm-cmpx-side { position:absolute; inset:0; }
.mm-cmpx-side img { width:100%; height:100%; object-fit:cover; display:block;
  max-width:none; pointer-events:none; }
/* The preview half is clipped to the handle, so the two align pixel for pixel
   instead of sitting side by side as separate pictures. */
.mm-cmpx-prev { clip-path:inset(0 calc(100% - var(--mm-x)) 0 0); }
.mm-cmpx-lab { position:absolute; bottom:14px; background:rgba(30,32,35,.72); color:#fff;
  font-size:14px; padding:8px 14px; border-radius:12px; white-space:nowrap; }
.mm-cmpx-lab.is-left { left:14px; }
.mm-cmpx-lab.is-right { right:14px; }
.mm-cmpx-handle { position:absolute; top:50%; left:50%; width:56px; height:56px;
  transform:translate(-50%,-50%); border-radius:50%; background:#fff;
  box-shadow:0 4px 18px rgba(0,0,0,.28); display:grid; place-items:center;
  font-size:19px; color:#23262A; cursor:ew-resize; }
.mm-cmpx-handle::before { content:""; position:absolute; top:-1000px; bottom:-1000px;
  left:50%; width:2px; background:rgba(255,255,255,.9); transform:translateX(-50%);
  box-shadow:0 0 6px rgba(0,0,0,.25); }
.mm-cmpx-handle span { position:relative; z-index:1; letter-spacing:2px; }

@media (max-width:940px){
  .mm-cmpx { aspect-ratio:1/1; }
  .mm-cmpx-lab { font-size:12.5px; padding:6px 11px; bottom:11px; }
  .mm-cmpx-lab.is-left { left:11px; }
  .mm-cmpx-lab.is-right { right:11px; }
  .mm-cmpx-handle { width:48px; height:48px; font-size:17px; }
}


/* The compare link belongs to a finished render, not a building one. */
.mm-inline.mm-pv-loading .mm-pv-example { display:none; }


/* ===================== zoomable preview lightbox ======================= */
/* touch-action:none so the browser hands us the pinch instead of zooming the
   whole page underneath; overscroll-behavior stops a drag at the edge turning
   into a pull-to-refresh mid-inspection. */
.mm-lightbox { touch-action:none; overscroll-behavior:contain; overflow:hidden; }
.mm-lb-stage { transform-origin:50% 50%; will-change:transform; cursor:zoom-in;
  display:flex; align-items:center; justify-content:center; }
.mm-lb-stage > * { pointer-events:auto; }
/* Once zoomed, the backdrop should not read as "tap anywhere to close" -- the
   Close button is the way out, and taps on the image belong to the image. */
.mm-lightbox.is-zoomed { cursor:default; }
.mm-lb-hint { position:fixed; left:50%; top:max(18px, env(safe-area-inset-top, 0px));
  transform:translateX(-50%); background:rgba(20,22,25,.62); color:#fff;
  font-size:12.5px; padding:6px 13px; border-radius:999px; pointer-events:none;
  z-index:2; transition:opacity .3s ease; }
.mm-lightbox.is-zoomed .mm-lb-hint { opacity:0; }


/* The overlay covers the viewport and contains its own scrolling, so the page
   behind it never needed locking -- and locking it was what moved the page. */
.mm-modal { overscroll-behavior:contain; }


/* ========================= product gallery ============================== */
/* Every photo is cropped to the same frame regardless of what is uploaded --
   object-fit does the cropping, so portrait and landscape shots sit in an
   identical box instead of the page reflowing between them. */
.mm-gal-main { aspect-ratio:1/1; width:100%; border-radius:14px;
  border:1px solid var(--line); background:var(--stone2); overflow:hidden; }
.mm-gal-main img { width:100%; height:100%; object-fit:cover; display:block;
  max-width:none; }

.mm-gal-thumbs { display:flex; gap:8px; overflow-x:auto; padding:0 0 4px;
  scrollbar-width:none; -webkit-overflow-scrolling:touch; }
.mm-gal-thumbs::-webkit-scrollbar { display:none; }
.mm-gal-thumb { flex:0 0 auto; width:66px; height:66px; border-radius:14px;
  overflow:hidden; border:2px solid transparent; background:var(--stone2);
  cursor:pointer; padding:0; position:relative; }
.mm-gal-thumb img { width:100%; height:100%; object-fit:cover; display:block;
  max-width:none; }
.mm-gal-thumb.is-on { border-color:var(--survey); }

@media (max-width:940px){
  /* No negative-margin full-bleed: the horizontal padding on this page comes
     from the theme's wrapper, not from here, so any value guessed at would be
     wrong on some themes and produce a sideways scroll. The hero fills the
     column it is given, which is the whole width on a phone anyway. */
  .mm-gal-main { aspect-ratio:4/3; border-radius:14px; }
  .mm-gal-thumbs { padding:10px 0 4px; }
  .mm-gal-thumb { width:62px; height:62px; }
}


/* ============ no scroll compensation when the render appears ============ */
/* Browsers "anchor" the scroll position to an element and silently adjust
   scrollTop when something above it changes height. Hiding the preview button
   and inserting the render block is exactly that kind of change, so the browser
   was scrolling the page on our behalf -- which is the movement that kept
   coming back after every fix to our own scrolling code. */
.mm, .mm-pdp, .mm-config, .mm-sum, .mm-inline { overflow-anchor: none; }

/* The swap is height-neutral at the moment it happens: the render block starts
   at least as tall as the button it replaces, so nothing below it jumps up into
   the gap and then back down again a frame later. */
.mm-inline { min-height: 96px; }
.mm-inline.mm-hide { min-height: 0; }


/* Swipeable hero: horizontal gestures belong to the gallery, vertical ones stay
   with the page, and the image never gets picked up as a drag target. */
.mm-gal-main { touch-action: pan-y; }
.mm-gal-main img { -webkit-user-drag: none; user-select: none; }
/* The selected thumbnail is scrolled into view within its own strip only --
   nearest, and inline, so the page itself never moves. */
.mm-gal-thumbs { scroll-behavior: smooth; }


/* The map's + / - buttons sat at MapLibre's default grey-on-grey, which reads as
   disabled next to the rest of the page. Full contrast, and a real tap target. */
.mm .maplibregl-ctrl-group { background:#fff; border:1px solid var(--line); }
.mm .maplibregl-ctrl-group button { width:34px; height:34px; opacity:1;
  background:#fff; }
.mm .maplibregl-ctrl-group button:not(:disabled) .maplibregl-ctrl-icon {
  opacity:1; filter:none; }
.mm .maplibregl-ctrl-group button:hover { background:var(--stone2); }
.mm .maplibregl-ctrl-group button + button { border-top:1px solid var(--line); }
/* Only a genuinely unavailable control should look unavailable -- at max or min
   zoom MapLibre disables the button, and that state stays visible. */
.mm .maplibregl-ctrl-group button:disabled { opacity:.35; }

/* ==========================================================================
   Apple-esque pass.

   Geometry, elevation and motion only. The palette and the typefaces are the
   brand and are deliberately untouched: Archivo, matcha #5F7D45, paper
   #FBFAF7. What changes is how surfaces sit and how controls respond.

   Three ideas, applied consistently:
     - weight comes from a soft shadow, not a hard border line
     - selection is a quiet tinted fill, not a heavy ring
     - every control acknowledges a press

   Appended last on purpose, so it layers over the rules above without
   needing !important to win.
   ========================================================================== */

.mm {
  /* Two elevations. Resting is almost imperceptible -- just enough to lift a
     card off the paper. Raised is for hover and open panels. */
  --sh-1: 0 1px 2px rgba(27,31,35,.045), 0 1px 1px rgba(27,31,35,.03);
  --sh-2: 0 6px 18px rgba(27,31,35,.08), 0 2px 5px rgba(27,31,35,.05);
  --sh-3: 0 22px 60px rgba(27,31,35,.16), 0 4px 12px rgba(27,31,35,.08);
  --ring: 0 0 0 4px rgba(95,125,69,.16);
  /* Decelerating, never bouncing. A curve that overshoots reads as a toy. */
  --ease: cubic-bezier(.22,.61,.36,1);
  --tint: rgba(95,125,69,.06);
}

/* --- choice cards ------------------------------------------------------- */

.mm-size, .mm-addon, .mm-card, .mm-opt, .mm-prio-opt {
  box-shadow: var(--sh-1);
  border-color: rgba(27,31,35,.09);
  transition: box-shadow .28s var(--ease), transform .28s var(--ease),
              border-color .2s var(--ease), background-color .2s var(--ease);
}
.mm-size:hover, .mm-card:hover, .mm-opt:hover, .mm-prio-opt:hover {
  box-shadow: var(--sh-2);
  transform: translateY(-1px);
  border-color: rgba(27,31,35,.14);
}
.mm-size:active, .mm-card:active, .mm-opt:active, .mm-prio-opt:active {
  transform: scale(.985);
  transition-duration: .09s;
}
/* Selected: the fill carries it, so the border can stay quiet. */
.mm-size.is-on, .mm-card.is-on, .mm-opt.is-on, .mm-prio-opt.is-on {
  background: var(--tint);
  border-color: var(--survey);
  box-shadow: var(--sh-1), inset 0 0 0 1px var(--survey);
}

/* --- buttons ------------------------------------------------------------ */

/* The primary action is a pill. It is the single most recognisable control
   shape in this idiom, and it is the one place worth spending that. */
.mm-btn, .mm-cart-checkout, .mm-cart-btn, .mm-preview-cta, .mm-addon-btn {
  border-radius: 999px;
  transition: transform .28s var(--ease), box-shadow .28s var(--ease),
              background-color .2s var(--ease), opacity .2s var(--ease);
}
.mm-btn { box-shadow: var(--sh-1); }
.mm-btn:hover:not(:disabled) { box-shadow: var(--sh-2); transform: translateY(-1px); }
.mm-btn:active:not(:disabled) { transform: scale(.98); transition-duration: .09s; }
.mm-cart-checkout:active, .mm-cart-btn:active, .mm-addon-btn:active {
  transform: scale(.98); transition-duration: .09s;
}

/* --- inputs ------------------------------------------------------------- */

.mm-search, .mm-input, .mm-plq-input, .mm-cart-giftmsg {
  transition: box-shadow .2s var(--ease), border-color .2s var(--ease);
}
.mm-search:focus-within, .mm-input:focus, .mm-plq-input:focus,
.mm-cart-giftmsg:focus {
  box-shadow: var(--ring);
  border-color: var(--survey);
  outline: none;
}

/* Keyboard focus stays visible everywhere, without following a mouse around. */
.mm :focus-visible { outline: none; box-shadow: var(--ring); }

/* --- panels and overlays ------------------------------------------------ */

/* Frosted rather than flat black. The page stays legible behind the sheet,
   which is what makes a modal feel like it is on top of the page rather than
   instead of it. */
.mm-modal, .mm-lightbox, .mm-cart-overlay {
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  background: rgba(27,31,35,.28);
}
.mm-modal-in, .mm-cart-panel, .mm-sugg-list {
  box-shadow: var(--sh-3);
  border-color: rgba(27,31,35,.08);
}
/* Panels carry a larger radius than the cards inside them. Keeping them the
   same makes a sheet look like an oversized button. */
.mm-modal-in { border-radius: 20px; }
.mm-sugg-list { border-radius: 16px; }
.mm-sugg-item { transition: background-color .14s var(--ease); }

/* --- small parts -------------------------------------------------------- */

.mm-size-tag, .mm-sw, .mm-swatch-lab, .mm-inc, .mm-plq-count {
  border-radius: 999px;
}
.mm-gal-thumb, .mm-cart-thumb, .mm-pv-shot, .mm-pv-room, .mm-cmp-shot {
  overflow: hidden;
}
.mm-gal-thumb { transition: transform .28s var(--ease), box-shadow .28s var(--ease); }
.mm-gal-thumb:hover { transform: translateY(-1px); box-shadow: var(--sh-2); }

/* Nobody should be made motion sick by a shop. */
@media (prefers-reduced-motion: reduce) {
  .mm *, .mm *::before, .mm *::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
  }
  .mm-size:hover, .mm-card:hover, .mm-opt:hover, .mm-prio-opt:hover,
  .mm-btn:hover:not(:disabled), .mm-gal-thumb:hover { transform: none; }
}
