/**
 * Shagun Envelope Studio — storefront styles
 * All selectors are namespaced .ps-sh-* / #ps-sh-* so nothing can collide with
 * the theme. Colours reuse the theme's altcolor variables where available and
 * fall back to the brand maroon/gold.
 */

#ps-sh-tool {
  --ps-sh-maroon: #9c1a33;
  --ps-sh-line: #e7d9d2;
  --ps-sh-ink: #2b2320;
  --ps-sh-muted: #7d6a63;
  --ps-sh-card: #fff;
  /* the foil, as a flat UI colour — one of the envelope gradient's own stops */
  --ps-sh-gold: #c9a227;

  /* Design-thumb caption block: two reserved lines plus the gap above it.
     Reserved so a caption that wraps to two lines cannot leave the row
     ragged - see the note on .ps-sh-thumb .nm. */
  /* Thumb sizes live here because the RESERVED heights below are derived from
     them. Hard-coding the heights separately is how they drift apart. */
  --ps-sh-fontbtn-h: 53px;      /* a font button: 18px Aa + 9.5px name + padding + borders */
  --ps-sh-thumb-w: 108px;       /* design carousel */
  --ps-sh-thumb-ar: 1.289;      /* the t*_4 shots, 450x349 */
  --ps-sh-railthumb-w: 84px;    /* view rail under the preview */

  --ps-sh-cap-lines: 28.75px;   /* 2 lines at 11.5px / 1.25 */
  --ps-sh-cap-gap: 5px;
  /* The rail's own vertical padding, asymmetric so the hidden scrollbar's
     track does not crowd the captions. */
  --ps-sh-rail-pad-t: 2px;
  --ps-sh-rail-pad-b: 10px;
}

/* ------------------------------------------------------------------ controls
   NOTE: the quantity control (#input-quantity, rendered by global_qty) and the
   Add-to-Cart button (#button-cart-open-tool) are deliberately NOT styled here.
   They belong to the module and the theme; restyling them would fight the
   sticky add-to-cart bar that mirrors them.
   --------------------------------------------------------------------------- */

.ps-sh-field { margin-bottom: 16px; }

/* Greeting and name side by side. Each field carries a flex-basis floor, so the
   row wraps on its own when there is not enough width — no hard breakpoint to
   keep in sync with the theme. min-width:0 lets a field shrink below its
   content instead of forcing the row wider. */
.ps-sh-fieldrow {
  display: flex;
  flex-wrap: wrap;
  gap: 0 14px;
  align-items: flex-start;
}
.ps-sh-fieldrow > .ps-sh-field {
  /* 150px floor keeps them side by side on phones too (a 390px screen leaves
     roughly a 360px container). It still wraps below ~315px as a safety net
     rather than squeezing two unusable fields. */
  flex: 1 1 150px;
  min-width: 0;
}
/* the greeting label is the longer of the two — let it wrap rather than
   widening its column */
.ps-sh-fieldrow .ps-sh-label { white-space: normal; }

.ps-sh-label {
  display: block;
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ps-sh-muted);
}

/* refinements on top of the theme's .form-control, not a replacement */
#ps-sh-tool select.ps-sh-input,
#ps-sh-tool input.ps-sh-input {
  /* The theme's .form-control is 16px 32px — 32px of horizontal padding eats
     the field and makes it 58px tall. Trimmed to something proportionate;
     still comfortably above the 44px touch target. */
  padding: 11px 14px;
  height: auto;
  min-height: 46px;
  font-size: 15px;
  line-height: 1.35;
  border-radius: 10px;
  border-color: var(--ps-sh-line);
  transition: border-color .15s, box-shadow .15s, background-color .15s;
}
#ps-sh-tool select.ps-sh-input:focus,
#ps-sh-tool input.ps-sh-input:focus {
  border-color: var(--ps-sh-maroon);
  box-shadow: 0 0 0 .18rem rgba(156, 26, 51, .12);
}
#ps-sh-tool input.ps-sh-input::placeholder { color: #b3a59b; opacity: 1; }

/* ---- validation, at the field it is about ---- */

#ps-sh-tool input.ps-sh-input.is-err {
  border-color: #d32f2f;
  background: #fff7f7;
  box-shadow: 0 0 0 .18rem rgba(211, 47, 47, .14);
}
.ps-sh-err {
  margin-top: 7px;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.35;
  color: #d32f2f;
}
@keyframes ps-sh-shake {
  10%, 90% { transform: translateX(-1px); }
  20%, 80% { transform: translateX(2px); }
  30%, 50%, 70% { transform: translateX(-4px); }
  40%, 60% { transform: translateX(4px); }
}
.ps-sh-shake { animation: ps-sh-shake .5s cubic-bezier(.36, .07, .19, .97) both; }
@media (prefers-reduced-motion: reduce) {
  .ps-sh-shake { animation: none; }
}

.ps-sh-hint {
  margin-top: 6px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--ps-sh-maroon);
}
.ps-sh-warn {
  margin-top: 10px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--ps-sh-maroon);
}
.ps-sh-warn:empty { margin-top: 0; }

/* fonts ------------------------------------------------------------------- */

/* The font buttons are built by JS too, so the row was 0px tall until the
   script ran — 53px of step, measured. One variable drives both the button's
   height and the space kept for it, so they cannot drift apart. */
.ps-sh-fontgrid { display: flex; gap: 8px; flex-wrap: wrap; min-height: var(--ps-sh-fontbtn-h); }
.ps-sh-font {
  flex: 1 1 0;
  min-height: var(--ps-sh-fontbtn-h);
  min-width: 64px;
  max-width: 110px;
  padding: 8px 6px 6px;
  background: #fff;
  border: 2px solid var(--ps-sh-line);
  border-radius: 10px;
  cursor: pointer;
  text-align: center;
  line-height: 1;
  transition: border-color .15s, background-color .15s, transform .08s;
}
.ps-sh-font:hover { border-color: #d8c4bb; }
.ps-sh-font:active { transform: scale(.97); }
.ps-sh-font .aa {
  display: block;
  font-size: 20px;
  color: var(--ps-sh-ink);
}
.ps-sh-font .nm {
  display: block;
  margin-top: 4px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--ps-sh-muted);
}
.ps-sh-font.on {
  border-color: var(--ps-sh-maroon);
  background: #fdf4f6;
}
.ps-sh-font.on .aa,
.ps-sh-font.on .nm { color: var(--ps-sh-maroon); }

/* ------------------------------------------------------------------ quantity
   The VALUES come from the global_qty module (admin-configured series); only
   the look is ours. shagun-tool.js strips the theme's 'form-select ps-select'
   off that same element and adds .ps-sh-qty — the element, its name, its id
   and its options are untouched, so cart/add, ps_sticky_atc and the module's
   own "10+" behaviour all still work.
   --------------------------------------------------------------------------- */

#ps-sh-tool .ps-sh-qtycell { flex: 0 0 108px; max-width: 108px; }

#ps-sh-tool select.ps-sh-qty {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  width: 100%;
  min-height: 52px;                 /* lines up with the Add-to-Cart button */
  padding: 12px 30px 12px 14px;     /* room on the right for the chevron */
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--ps-sh-ink);
  background-color: #fff;
  border: 2px solid var(--ps-sh-line);
  border-radius: 10px;
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
  /* chevron drawn inline so there is no extra request and it follows the ink */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%237d6a63' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 11px 8px;
}
#ps-sh-tool select.ps-sh-qty:hover { border-color: #d8c4bb; }
#ps-sh-tool select.ps-sh-qty:focus {
  outline: none;
  border-color: var(--ps-sh-maroon);
  box-shadow: 0 0 0 .18rem rgba(156, 26, 51, .12);
}
#ps-sh-tool select.ps-sh-qty::-ms-expand { display: none; }

/* ------------------------------------------------------------------- preview
   FM-style swiper: main slider + a thumb rail beneath it. Slides all share one
   aspect ratio so Swiper gets a stable height; the plane inside is absolutely
   positioned so the zoom slide can scale it.
   --------------------------------------------------------------------------- */

#ps-sh-preview { position: relative; }

/* ⚠ Every one of these three boxes is filled by JavaScript, so before the
   script runs they are EMPTY and were 0px tall — the whole page below the
   preview jumped down the moment the slides appeared. On a slow connection
   that is the shift you notice, and it happens whatever the images do.
   Each now reserves the height its content will take, derived from the sizes
   declared above rather than measured once and pasted in. */
.ps-sh-swiper {
  /* exactly a slide: .ps-sh-slide uses the same variable */
  aspect-ratio: var(--ps-sh-frame-ar, 1.85);
  position: relative;
  overflow: hidden;
  border: 1px solid var(--ps-sh-line);
  border-radius: 12px;
  background: #faf6f4;
}

/* ------------------------------------------------- image loading skeleton
   .ps-image-loading-placeholder is the THEME's shimmer (it ships in
   bootstrap.min.css, which this page already loads) — reused rather than
   reinvented, so a loading envelope looks like a loading anything else on the
   site. All that is added here is the positioning and the fade. */
.ps-sh-ph {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
}
/* not left to the theme: [hidden] must win wherever this lands */
.ps-sh-ph[hidden] { display: none !important; }

.ps-sh-img { transition: opacity .25s ease; }
.ps-sh-img.is-loading { opacity: 0; }

/* the thumb boxes need a positioning context for their skeleton */
.ps-sh-phhost { position: relative; }

.ps-sh-slide {
  position: relative;
  overflow: hidden;
  /* the ENVELOPE's aspect, not the padded image's (1.288). Measured across
     all ten designs the envelope is AR 1.85-1.90; framing at 1.85 drops the
     white bands the 1.288 frame was showing. JS keeps this in step via
     --ps-sh-frame-ar. */
  aspect-ratio: var(--ps-sh-frame-ar, 1.85);
  container-type: inline-size;  /* the cqw text sizes resolve against the slide */
  background: #faf6f4;
}

.ps-sh-plane {
  position: absolute;
  top: 0; left: 0;
  transform-origin: 0 0;
  /* NO will-change here. The original tool carries the same warning:
     it promotes the layer, rasterises it at CSS size, then upscales that
     bitmap when the zoom slide applies scale() — which is exactly the blurry
     zoom. Leave it off so the browser re-rasterises at the scaled size. */
}
.ps-sh-plane img.ps-sh-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: fill;
  display: block;
}

/* ---------------------------------------------------------------------------
   ENVELOPE TEXT — copied verbatim from the standalone tool
   (_original_backup/index.html: .env-text / .greet / .name / .gold).
   Only two things are added, both to neutralise the live theme:
     * an explicit `letter-spacing` on the name (the theme ships
       `* { letter-spacing:.05rem }`, which the original never had to fight)
     * the metric-pinning resets below
   shagun-tool.js mirrors these numbers for the canvas proof — change the two
   together, and remember only the canvas copy reaches the order.
   --------------------------------------------------------------------------- */
.ps-sh-text {
  position: absolute;
  transform: translate(-50%, -50%);
  text-align: center;
  line-height: 1.05;
  pointer-events: none;
  user-select: none;
}

/* greeting: Calibri first (a local Windows face), Carlito as the web fallback —
   the order matters, it changes the metrics */
.ps-sh-text .ps-sh-greet {
  font-family: "Calibri", "Carlito", "Segoe UI", sans-serif;
  font-weight: 700;
  letter-spacing: .2px;
  margin-bottom: .23em;   /* paired with GREET_GAP_EM in shagun-tool.js */
  line-height: 1.3;
}
/* name: the face is swapped per font choice by the JS; 1.3 leaves room for
   descenders under the gold clip */
.ps-sh-text .ps-sh-name {
  font-family: "Russo One", sans-serif;
  font-weight: 400;
  letter-spacing: normal;      /* the theme's universal rule would add .8px */
  line-height: 1.3;
}

.ps-sh-text .ps-sh-line {
  display: block;
  white-space: nowrap;
  /* pinned so the theme cannot shift the metrics away from what prints */
  word-spacing: normal;
  font-style: normal;
  font-variant: normal;
  font-stretch: normal;
  font-kerning: normal;
  text-transform: none;
  text-indent: 0;
  text-shadow: none;
  -webkit-text-stroke: 0;
}

/* the exact .gold gradient — the greeting shares it so both are the same shade */
.ps-sh-text .ps-sh-line {
  background: linear-gradient(180deg, #fff4c8 0%, #f0cf7a 24%, #d8b24a 48%, #b8860b 72%, #f2d989 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* the shadow stack sits on the CONTAINER, as in the original, so the greeting
   and the name are lit identically. The first layer — zero offset, .5px — is
   what reads as a stroke. */
.ps-sh-text.tone-light {
  filter: drop-shadow(0 0 .5px rgba(45, 25, 0, .62))
          drop-shadow(0 .5px .5px rgba(45, 25, 0, .5))
          drop-shadow(0 1px 2px rgba(0, 0, 0, .2));
}
.ps-sh-text.tone-dark {
  filter: drop-shadow(0 .5px .5px rgba(0, 0, 0, .4))
          drop-shadow(0 1px 2.5px rgba(0, 0, 0, .33));
}

/* arrows: theme classes carry the chrome; this only sizes/centres them */
/* ------------------------------------------------------------- selection
   These are CONTROLS, not copy. Without this, a second click on an arrow
   counts as a double-click and the browser selects whatever is under and
   around it — the reported symptom was the thumb rail and the product title
   turning highlighter-blue after clicking the preview arrows. Dragging the
   design rail did the same, and the `.is-dragging` rule's comment claimed to
   prevent it while setting no such property.

   Deliberately NOT applied to the labels, the note, the price or the title:
   a customer may well want to copy those. */
.ps-sh-swiper .swiper-button-prev,
.ps-sh-swiper .swiper-button-next,
#ps-sh-thumbrail,
#ps-sh-thumbs,
.ps-sh-fontgrid {
  -webkit-user-select: none;
  user-select: none;
}
/* and the pictures themselves must not start a native image-drag, which
   hijacks the rail's own click-drag */
.ps-sh-thumbrail-item img,
.ps-sh-thumb img,
.ps-sh-bg {
  -webkit-user-drag: none;
  user-drag: none;
}

.ps-sh-swiper .swiper-button-prev,
.ps-sh-swiper .swiper-button-next {
  width: 34px; height: 44px;
  margin-top: -22px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .12);
}
.ps-sh-swiper .swiper-button-prev::after,
.ps-sh-swiper .swiper-button-next::after { font-size: 15px; font-weight: 800; }

/* thumb rail ------------------------------------------------------------- */

/* Horizontal, under the swiper. It was a vertical col-2 rail, which cost the
   preview a sixth of its width — expensive when the frame is 1.85 wide and the
   whole page is about looking at that picture. Three views, so they centre
   rather than fill; it still scrolls if slides are ever added. */
#ps-sh-thumbrail {
  /* One row of rail thumbs. box-sizing is border-box here, so this has to
     include the 10px padding below — measured: reserving without it left the
     rail 16px short and the page still stepped down when the thumbs arrived. */
  min-height: calc((var(--ps-sh-railthumb-w) - 4px) / var(--ps-sh-frame-ar, 1.85)
                   + 4px      /* the thumbs' own 2px borders */
                   + 20px);   /* this row's padding, top + bottom */
  display: flex;
  flex-direction: row;
  justify-content: center;
  gap: 8px;
  padding: 10px;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
#ps-sh-thumbrail::-webkit-scrollbar { width: 0; height: 0; display: none; }
.ps-sh-thumbrail-item {
  display: block;
  flex: 0 0 auto;
  width: var(--ps-sh-railthumb-w);
  padding: 0;
  background: none;
  border: 2px solid var(--ps-sh-line);
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;
  line-height: 0;
  transition: border-color .15s;
}
.ps-sh-thumbrail-item:hover { border-color: #d8c4bb; }
.ps-sh-thumbrail-item.active {
  border-color: var(--ps-sh-maroon);
  box-shadow: 0 0 0 .14rem rgba(156, 26, 51, .12);
}
/* Framed like the slide each one goes to: the ENVELOPE's 1.85, not the
   padded photo's 1.288, so a thumb is a miniature of its slide rather than a
   differently-shaped picture with white bands. object-fit: cover does the
   top/bottom crop, and the zoom thumb carries its slide's magnification about
   the same text anchor — without it Front and Zoom were pixel-identical and
   the rail looked like it had a duplicate. */
.ps-sh-thumbrail-item .th { display: block; aspect-ratio: var(--ps-sh-frame-ar, 1.85); overflow: hidden; }
.ps-sh-thumbrail-item img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(var(--ps-sh-tz, 1));
  transform-origin: var(--ps-sh-tx, 50%) var(--ps-sh-ty, 50%);
}

/* design carousel --------------------------------------------------------- */

/* .ps-sh-chooselbl is gone: the carousel now sits inside the options block and
   uses the same .ps-sh-label as the greeting/name/font steps, so the four
   headings match instead of one shouting in small caps. */
#ps-sh-thumbs {
  /* picture + its 2px borders + the caption block + this rail's padding */
  min-height: calc((var(--ps-sh-thumb-w) - 4px) / var(--ps-sh-thumb-ar)
                   + 4px
                   + var(--ps-sh-cap-gap) + var(--ps-sh-cap-lines)
                   + var(--ps-sh-rail-pad-t) + var(--ps-sh-rail-pad-b));
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding: var(--ps-sh-rail-pad-t, 2px) 2px var(--ps-sh-rail-pad-b, 10px);
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
/* Scrollbar hidden on request. That leaves a touch screen fine (swipe) but a
   DESKTOP MOUSE with no way to move the rail at all: a vertical wheel does
   nothing to a horizontal scroller and dragging does not pan an overflow
   container. So shagun-tool.js adds click-drag and wheel mapping — without
   them designs past the fold were simply unreachable on a PC. (Arrows were
   here too, removed on request; drag and wheel are what keep it usable.) */
#ps-sh-thumbs { scrollbar-width: none; -ms-overflow-style: none; }
#ps-sh-thumbs::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* while a drag is in progress: no snap fighting the pointer */
#ps-sh-thumbs.is-dragging { scroll-snap-type: none; scroll-behavior: auto; cursor: grabbing; }
#ps-sh-thumbs.is-dragging .ps-sh-thumb { pointer-events: none; }

.ps-sh-thumb {
  flex: 0 0 auto;
  width: var(--ps-sh-thumb-w);
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  scroll-snap-align: start;
  text-align: center;
}
.ps-sh-thumb .th {
  display: block;
  border: 2px solid var(--ps-sh-line);
  border-radius: 10px;
  overflow: hidden;
  line-height: 0;
  transition: border-color .15s, transform .08s;
}
.ps-sh-thumb:hover .th { border-color: #d8c4bb; }
.ps-sh-thumb:active .th { transform: scale(.98); }
.ps-sh-thumb .th img { display: block; width: 100%; height: auto; }
.ps-sh-thumb .nm {
  display: block;
  margin-top: var(--ps-sh-cap-gap, 5px);
  font-size: 11.5px;
  line-height: 1.25;
  color: var(--ps-sh-muted);
  /* The theme ships `* { letter-spacing: .05rem }`, which inherits here and
     adds ~13px across a 16-character name — enough to tip "Colorful Mandala"
     onto a second line while its neighbours stay on one, leaving the row
     ragged. Same leak that once pushed the envelope text 98.7px wide. */
  letter-spacing: normal;
  word-spacing: normal;
  /* Reserve two lines regardless. The live theme's face is wider than
     anything reachable from here, so whether a given name wraps cannot be
     settled locally — reserving the space means a wrap costs a second line of
     text, never the alignment of the whole row. */
  min-height: var(--ps-sh-cap-lines, 28.75px);
}
.ps-sh-thumb.active .th {
  border-color: var(--ps-sh-maroon);
  box-shadow: 0 0 0 .16rem rgba(156, 26, 51, .12);
}
.ps-sh-thumb.active .nm { color: var(--ps-sh-maroon); font-weight: 700; }

/* ------------------------------------------------------------------- pricing
   The price itself is the theme's markup (.ps-lp-price / .ps-lp-special, the
   same block product_miniatures_upload.twig uses), so there is nothing to
   style here beyond the note under the options. */

/* The line is reassurance, so it gets no box. A boxed, tinted, accent-barred
   note with a circled "i" is how every UI says *something is wrong* — it read
   as a warning about the product rather than a helpful fact about it.
   What is left is the sentence and a small gold mark, which points at the one
   word that matters: gold. The ornament reinforces the message instead of
   interrupting it. */
.ps-sh-qtynote {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 16px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ps-sh-ink);
}
.ps-sh-qtynote svg {
  /* flex WILL squash an svg without this */
  flex: 0 0 auto;
  width: 13px;
  height: 13px;
  /* sits on the first line's cap height rather than its box top */
  margin-top: 3px;
  color: var(--ps-sh-gold);
}

/* ------------------------------------------------------- added-to-cart
   Takes the PLACE of the quantity + Add to Cart row after a successful add,
   so someone buying a different envelope per family can keep going instead of
   being thrown to the cart.

   Same shape as the theme's own post-add panel (pps-runtime-new.js
   showCartOffer). Its stylesheet is not reused: pps-runtime.css is loaded by
   the pps module only, and this is a custom_template page. */

/* ⚠ `hidden` alone does NOT hide #cart-step-two: it carries Bootstrap's
   `.d-flex { display:flex !important }`, and `[hidden] { display:none
   !important }` loses to it — same specificity (0,1,0), and the utilities come
   later in the sheet. Measured: row.hidden was true while the row stayed on
   screen. An id + attribute selector (1,1,0) settles it. */
#cart-step-two[hidden],
#ps-sh-done[hidden] { display: none !important; }

.ps-sh-done {
  /* No dismiss control: once the add has happened there is no honest way back
     to an "Add to Cart" button for the same design, so the only exits are
     forward. The theme's own panel is the same. */
  order: 3;                 /* the slot #cart-step-two occupies */
  padding: 14px 14px 15px;
  border: 1px solid var(--ps-sh-line);
  border-radius: 11px;
  background: #fbfaf9;
  text-align: center;
}
.ps-sh-done-msg {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  margin: 0 0 2px;
  font-size: 14.5px; font-weight: 700; line-height: 1.35;
  color: #1e7e34;           /* the green the theme's own panel uses */
}
.ps-sh-done-tick { flex: 0 0 auto; width: 18px; height: 18px; }

.ps-sh-done-sub {
  margin: 0 0 13px;
  font-size: 12.5px; line-height: 1.4; color: var(--ps-sh-muted);
}

.ps-sh-done-btns { display: flex; gap: 10px; }
.ps-sh-done-btns > * {
  flex: 1 1 0;
  padding: 12px 10px;
  border-radius: 9px;
  font-size: 13.5px; font-weight: 700;
  text-align: center; text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.ps-sh-done-more {
  border: 1px solid var(--ps-sh-maroon);
  background: #fff;
  color: var(--ps-sh-maroon);
}
.ps-sh-done-more:hover { background: #fdf7f8; }
.ps-sh-done-go {
  border: 1px solid var(--ps-sh-maroon);
  background: var(--ps-sh-maroon);
  color: #fff;
}
.ps-sh-done-go:hover { background: #86162c; color: #fff; }
.ps-sh-done-btns > *:focus-visible {
  outline: none;
  box-shadow: 0 0 0 .2rem rgba(156, 26, 51, .25);
}
/* The theme's own panel stacks under 576px, but its labels are longer
   ("Proceed To Cart"). "Add more" / "Go to cart" still sit side by side in the
   ~160px each a 390px phone gives them, which keeps the panel compact and
   matches desktop. Stack only when that genuinely stops being true. */
@media (max-width: 330px) {
  .ps-sh-done-btns { flex-direction: column; }
}

/* --------------------------------------------------------------- responsive
   Column order and mobile density. The two grid columns are ordered in the
   twig with Bootstrap utilities (preview -> options+cart); the flex `order`
   rules below drop title+price under the options at every width. The design
   carousel is part of the options block now, so it needs no ordering of its
   own. The media queries carry fit and density only. */

/* Title + price sit below the options and directly above Add to Cart at every
   width, so the price is next to the action it commits you to instead of
   interrupting the customisation run. Each block owns its trailing <hr> so the
   rules travel with it.
   The rest of the order needs no rules at all: the natural DOM order already
   gives preview -> greeting+name -> font -> design on a phone, and
   preview beside options on desktop. */
#product > .d-flex.flex-column { display: flex; flex-direction: column; }
#product-page-simple-options { order: 1; }
.ps-sh-head                  { order: 2; }
#cart-step-two               { order: 3; }
.ps-sh-warn                  { order: 4; }
#product > .d-flex.flex-column > hr { order: 5; }
.ps-sh-head hr:first-child { margin-top: 0; }


@media (max-width: 991.98px) {
  /* the row gap would otherwise stack up between the full-width blocks */
  #ps-sh-tool.ps-sh-row { --bs-gutter-y: 0; }
  .ps-sh-swiper { border-radius: 10px; }
  #ps-sh-tool { --ps-sh-railthumb-w: 74px; }
}

@media (max-width: 575.98px) {
  #ps-sh-tool {
    --ps-sh-cap-lines: 27.5px;      /* 2 lines at 11px / 1.25 */
    --ps-sh-railthumb-w: 66px;
    --ps-sh-thumb-w: 92px;
  }
  .ps-sh-thumb .nm { font-size: 11px; }
  .ps-sh-font { min-width: 0; padding: 7px 4px 5px; }
  .ps-sh-font .aa { font-size: 18px; }
  .ps-sh-font .nm { font-size: 9.5px; }
  .ps-sh-field { margin-bottom: 13px; }
  /* keep the qty + CTA on one line even on the narrowest phones */
  #cart-step-two > .col-4 { flex: 0 0 88px; }
}
