    /* --- Configurator base layout (restored: lost in inline-style -> external split) --- */
    :root {
      --ivory: #FBF8F1;
      --shadow: 0 24px 70px rgba(22, 18, 11, .10);
      --soft-muted: #9A9A9A;
      /* black-stage photo feather (#2 edge-blend, 2026-07-22). We do the melt ON OUR SIDE:
         our real photos are RAW (light studio backdrops), so this mask fades every photo's
         edges into the black stage instead of relying on the photo being shot on black.
         Owner-chosen curve 2026-07-22 ("#3 + corner vignette"): two edge-feathers that are
         SHARP at the very border then trail off with a long, imperceptible tail (so the
         feather can reach toward the card with no visible line — .88 alpha by 3%, full by
         34%), INTERSECTED with a soft radial vignette that darkens ONLY the far corners
         (the bright reflective floor) without dimming the centered card. Single-homed: used
         by BOTH the main preview stage (.ref-preview-wrap img) and the selector-view stage
         (.cfg-selector-view .csv-photo-slot img); consumers also set mask-composite:intersect
         (-webkit-mask-composite:source-in) + a border-radius for rounded corners. Tune here.

         ⛔ CLAIMED SURFACE — CHECK BEFORE YOU RETUNE (owner-approved 2026-07-24).
         This look is tuned BY EYE across sessions, and three configurator chats have already
         reworked it independently and left it in three different states — the owner saw the
         live page disagree with a `?stagever=original` reconstruction AND with the tuning
         playground, and asked why the original looked wrong. Nothing broke; the cost was his
         confusion and the rework, because no single chat owned the treatment.

         So before changing these values: open PLANNING.md § "CLAIMED DESIGN SURFACES", confirm
         this row is unclaimed, write your name + date into it, commit path-scoped and PUSH
         (the push is the claim — it is what the next session sees), then tune. Clear the row
         when you close. If it is already claimed by another chat, do not retune it: say so and
         take something else.

         This comment is the TRIPWIRE (you are reading it at edit-time); the PLANNING table is
         the REGISTER (it answers "what is claimed right now"). Both, deliberately — a rule
         living only where nobody re-reads it at act-time does not fire.

         Tuning tool: www/configurator-stage-playground.php (live dials for feather width +
         corner vignette). Owner is consulting Henry on the final numbers as of 2026-07-24 —
         the MECHANISM is settled, the exact values are not. */
      --stage-feather-mask:
        radial-gradient(ellipse 80% 80% at 50% 46%, #000 56%, rgba(0,0,0,.3) 100%),
        linear-gradient(to right, transparent 0, rgba(0,0,0,.88) 3%, #000 34%, #000 66%, rgba(0,0,0,.88) 97%, transparent 100%),
        linear-gradient(to bottom, transparent 0, rgba(0,0,0,.88) 3%, #000 34%, #000 66%, rgba(0,0,0,.88) 97%, transparent 100%);
    }

    .btn-ghost {
      background: #fff;
      color: #151515;
      border: 1px solid var(--line);
      box-shadow: 0 8px 20px rgba(22,18,11,.05);
    }

    .tool-title-bar {
      max-width: 1280px;
      margin: 0 auto;
      padding: 32px 28px 8px;
    }
    .tool-title-inner {
      display: grid;
      grid-template-columns: 1fr 360px;
      gap: 28px;
      align-items: end;
    }
    .breadcrumb {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      color: var(--soft-muted);
      font-size: 12px;
      font-weight: 700;
      margin-bottom: 18px;
    }
    .breadcrumb span:last-child { color: var(--gold); }
    .tool-main-title {
      font-size: clamp(24px, 3vw, 42px);
      letter-spacing: -.035em;
      text-transform: none;
      color: var(--ink);
      margin-bottom: 0;
      line-height: 1.05;
    }
    .tool-title-inner p {
      margin-top: 12px;
      color: #3D3D3D;
      font-size: 16px;
      max-width: 660px;
    }

    .workspace {
      max-width: 1280px;
      margin: 0 auto;
      padding: 18px 28px 80px;
      display: grid;
      grid-template-columns: 470px minmax(0, 1fr);
      gap: 28px;
      align-items: start;
    }

    .preview-panel {
      position: sticky;
      top: 92px;
      /* cap to the viewport so the Card Total + Add to Cart are ALWAYS visible (owner);
         the summary scrolls internally if the panel would otherwise overflow. */
      max-height: calc(100vh - 104px);
      display: flex;
      flex-direction: column;
      border-radius: var(--radius-lg);
      background: rgba(255,255,255,.82);
      border: 1px solid rgba(231,227,218,.9);
      box-shadow: var(--shadow);
      overflow: hidden;
    }
    /* Inside the capped sticky panel: the SPECS (summary) + Card Total are the
       priority and stay fully visible; the decorative card preview shrinks to make
       room (and only the summary scrolls, as a last resort on very short windows). */
    .preview-panel .preview-stage { flex: 0 1 auto; min-height: 0; }      /* override the 460px min so it can shrink */
    .preview-panel .card-scene { height: 160px; margin: 14px auto 10px; } /* smaller mockup so specs fit */
    .preview-panel .preview-summary { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
    .preview-panel .preview-summary .summary-grid { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
    .preview-panel .preview-summary .price-box { flex: 0 0 auto; }        /* pinned at the bottom, always in view */
    .preview-stage {
      min-height: 460px;
      padding: 28px;
      background:
        radial-gradient(circle at 70% 10%, rgba(201,169,110,.28), transparent 28%),
        linear-gradient(150deg, #151515 0%, #28241E 45%, #101010 100%);
      color: #fff;
      position: relative;
      overflow: hidden;
    }
    .preview-stage::after {
      content: "";
      position: absolute;
      left: -120px;
      bottom: -130px;
      width: 300px;
      height: 300px;
      border-radius: 50%;
      background: radial-gradient(circle, rgba(0,194,255,.16), transparent 65%);
    }
    .preview-label {
      position: relative;
      z-index: 2;
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 20px;
    }
    .preview-label h2 {
      font-size: 28px;
      line-height: 1.05;
      letter-spacing: -.04em;
    }
    .preview-label p {
      color: rgba(255,255,255,.64);
      font-size: 14px;
      margin-top: 8px;
    }
    .preview-badge {
      border: 1px solid rgba(255,255,255,.15);
      background: rgba(255,255,255,.08);
      color: rgba(255,255,255,.82);
      border-radius: 999px;
      padding: 8px 11px;
      font-size: 11px;
      font-weight: 900;
      white-space: nowrap;
    }
    .card-scene {
      position: relative;
      z-index: 2;
      height: 250px;
      margin: 36px auto 22px;
    }
    .mock-card {
      position: absolute;
      width: 82%;
      aspect-ratio: 1.78 / 1;
      left: 8%;
      top: 42px;
      border-radius: 23px;
      background: linear-gradient(135deg, #070707, #222 62%, #111);
      border: 1px solid rgba(255,255,255,.13);
      box-shadow: 0 34px 90px rgba(0,0,0,.44);
      transform: rotate(-8deg);
      overflow: hidden;
    }
    .mock-card.back {
      left: 13%;
      top: 62px;
      opacity: .42;
      transform: rotate(-8deg) translate(18px, 18px);
    }
    .foil-mark {
      position: absolute;
      left: 34px;
      top: 31px;
      width: 58px;
      height: 58px;
      background: linear-gradient(120deg, #8E6B2F, #FFF0B4 38%, #B98C45 68%, #F7D98B);
      clip-path: polygon(50% 0,100% 38%,50% 100%,0 38%);
      box-shadow: 0 0 30px rgba(232,201,154,.36);
    }
    .foil-name {
      position: absolute;
      left: 34px;
      bottom: 58px;
      color: rgba(255,255,255,.92);
      font-size: 26px;
      font-weight: 900;
      letter-spacing: -.04em;
    }
    .foil-line {
      position: absolute;
      left: 34px;
      right: 34px;
      bottom: 36px;
      height: 5px;
      border-radius: 999px;
      background: linear-gradient(90deg, #8E6B2F, #FFF0B4, #B98C45);
    }
    .preview-summary {
      padding: 24px 26px 26px;
      background: #fff;
    }
    .summary-grid {
      display: flex;
      flex-direction: column;
      gap: 0;
    }
    .summary-cell {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: 16px;
      padding: 11px 0;
      border-bottom: 1px solid var(--line);
    }
    .summary-cell:last-child { border-bottom: 0; }
    .summary-cell .label {
      color: var(--muted);
      font-size: 10px;
      font-weight: 900;
      letter-spacing: .14em;
      text-transform: uppercase;
      flex-shrink: 0;
      white-space: nowrap;
    }
    .summary-cell .value {
      color: var(--ink);
      font-size: 13px;
      font-weight: 600; /* lighter — owner: left panel text too bold vs original (2026-06-08) */
      letter-spacing: -.01em;
      line-height: 1.35;
      text-align: right;
      word-break: break-word;
    }
    .summary-cell.empty {
      display: none;
    }
    /* categorized summary (A1): section eyebrows + per-line cost accent */
    .sum-cat-title {
      color: var(--gold-dark, #8a6d1f);
      font-size: 10px;
      font-weight: 900;
      letter-spacing: .16em;
      text-transform: uppercase;
      padding: 14px 0 4px;
      border-bottom: 1px solid var(--line);
    }
    .summary-grid > .sum-cat-title:first-child { padding-top: 0; }
    .sumline .value { font-weight: 600; }
    /* Design Help pill → pulse the Design / ArtWork row it scrolls to */
    .cfg-pulse { animation: cfgPulse 1.2s ease-in-out 2; }
    @keyframes cfgPulse {
      0%, 100% { box-shadow: none; }
      50% { box-shadow: 0 0 0 5px rgba(31, 63, 176, .28); }
    }
    .sumline-cost {
      font-style: normal;
      font-weight: 800;
      color: #8a6d1f;
      background: #f6edd4;
      border-radius: 999px;
      padding: 1px 8px;
      margin-left: 8px;
      font-size: 11px;
      white-space: nowrap;
    }
    .price-box {
      margin-top: 18px;
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 18px;
      align-items: center;
      padding: 18px;
      border-radius: 18px;
      background: var(--ivory);
      border: 1px solid var(--line);
    }
    .price-label { font-size: 12px; color: var(--muted); font-weight: 800; }
    .price-value { font-size: 26px; font-weight: 900; letter-spacing: -.04em; }
    .price-fine {
      color: var(--muted);
      font-size: 10.5px;
      font-weight: 700;
      letter-spacing: .01em;
      margin-top: 4px;
    }
    /* Branded button base (v1.45 .btn / .btn-dark) — used by the sidebar
       Add-to-Cart and the review bar; not defined site-wide on header-v2 chrome. */
    .cfg-step .btn, .price-box .btn, .review-bar .btn {
      border: 0; border-radius: 999px; padding: 14px 20px;
      font: 900 13px/1 var(--font, inherit); cursor: pointer;
      display: inline-flex; align-items: center; justify-content: center; gap: 8px;
      white-space: nowrap; transition: transform .2s ease, box-shadow .2s ease;
    }
    .btn-dark { background: #101010; color: #fff; box-shadow: 0 14px 30px rgba(0,0,0,.12); }
    .btn-dark:hover { transform: translateY(-1px); }
    /* Emboss/Deboss 1-layer through-effect micro on the placement card (owner point 2) */
    .cfg-ed-areagrid .placement .cfg-ed-thru { color: var(--blue-dark, #0090c4); font-weight: 800; }
    /* Finish card: give the NAME the first row; let price + admin Edit pill wrap to a
       second row only when the name needs the width (short-name cards stay inline).
       Fixes the squeezed "Emboss / Deboss" title (owner point 3). */
    .accordion:not(.base_accordion) > dt.cfg-finish-row { flex-wrap: wrap; row-gap: 6px; }
    .cfg-finish-row .cfg-finish-copy { flex: 1 1 auto; min-width: 96px; }
    .cfg-finish-row .check-container { order: 9; margin-left: auto; }
    .cfg-finish-row .option_parent_price { order: 10; }
    .cfg-finish-row a[href*="productoption.php?action=edit"] { order: 11; }
    .btn-ghost { background: #fff; color: #151515; border: 1px solid var(--line); box-shadow: 0 8px 20px rgba(22,18,11,.05); }
    .btn-ghost:hover { transform: translateY(-1px); }
    /* per-item price mirrored from the engine's .total-price--split */
    .price-per-item { color: var(--muted); font-size: 12px; font-weight: 700; margin-top: 2px; }
    .price-per-item:empty { display: none; }
    /* stacked actions: Request Quotation (when TBD) above Add to Cart */
    .price-box-actions { display: flex; flex-direction: column; gap: 10px; align-items: stretch; }
    .price-box .cfg-sidebar-atc, .price-box .cfg-sidebar-quote { width: 100%; }
    .price-box-actions .d-none { display: none !important; }

    .builder {
      background: rgba(255,255,255,.86);
      border: 1px solid rgba(231,227,218,.9);
      border-radius: var(--radius-lg);
      box-shadow: var(--shadow);
      overflow: hidden;
    }
    .builder-column {
      display: flex;
      flex-direction: column;
    }
    /* Sticky builder head — Step-by-step label + Progress + Design Help pill. Travels with the customer as they scroll. */
    .builder-head {
      position: sticky;
      top: 80px;        /* flush under the 81px sticky nav — no gap for content to peek through */
      z-index: 30;      /* decisively above the scrolling step content (was 12 → content overlapped) */
      padding: 14px 20px;
      margin-bottom: 24px;
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 20px;
      align-items: center;
      /* distinct CONTRAST background so the progress bar stands out from the white
         build panel and doesn't get lost (owner 2026-06-08 — "more contrast"). */
      background: linear-gradient(180deg, #2a2d34 0%, #20232a 100%);
      border: 1px solid #2a2d34;
      border-radius: var(--radius-md);
      box-shadow: 0 8px 24px rgba(22,18,11,.22);
    }
    /* light text on the dark bar */
    .builder-head .eyebrow { color: #fff !important; }
    .builder-head .progress-top span { color: #c9cdd6; }
    .builder-head .progress-top span#cfg-progress-count { color: #fff; }
    .builder-head .progress-track { background: rgba(255,255,255,.16); }
    .builder-head-info {
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 24px;
      align-items: center;
    }
    .builder-head .eyebrow {
      margin-bottom: 0;
      white-space: nowrap;
      color: #232323; /* charcoal — high contrast vs the low-contrast gold (owner 2026-06-08) */
    }
    .helper-pill {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      background: linear-gradient(135deg, rgba(255,255,255,.95), rgba(251,248,241,.95));
      border: 1px solid rgba(201,169,110,.32);
      border-radius: 999px;
      padding: 7px 16px 7px 7px;
      font-size: 12px;
      font-weight: 900;
      color: var(--ink);
      cursor: pointer;
      transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
      white-space: nowrap;
      letter-spacing: -.005em;
    }
    .helper-pill:hover {
      transform: translateY(-1px);
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .helper-pill-dot {
      width: 24px;
      height: 24px;
      border-radius: 50%;
      background: var(--gold-soft);
      border: 1px solid rgba(201,169,110,.32);
      box-shadow: inset 0 0 0 4px rgba(255,255,255,.55);
      flex: 0 0 auto;
      transition: background .2s ease, border-color .2s ease, box-shadow .2s ease;
    }
    .helper-pill:hover .helper-pill-dot {
      background: var(--blue);
      border-color: rgba(0,194,255,.55);
      box-shadow: inset 0 0 0 4px rgba(255,255,255,.55), 0 0 0 3px rgba(0,194,255,.18);
    }
    .progress {
      width: 190px;
    }
    .progress-top {
      display: flex;
      justify-content: space-between;
      color: var(--muted);
      font-size: 11px;
      font-weight: 900;
      margin-bottom: 8px;
    }
    .progress-track {
      height: 8px;
      border-radius: 999px;
      background: #E9E3D7;
      overflow: hidden;
    }
    .progress-fill {
      height: 100%;
      width: 20%;
      background: linear-gradient(90deg, var(--blue), var(--gold));
      border-radius: inherit;
    }

    /* ===== Build Context — dynamic titling block (replaces former Step 1 selection) ===== */
    .build-context {
      padding: 28px 32px;
      border-bottom: 1px solid var(--line);
      background:
        linear-gradient(135deg, rgba(247,240,226,.55), rgba(251,248,241,.85));
      position: relative;
    }
    .build-context-inner {
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 20px;
      align-items: center;
    }
    .build-context-copy .eyebrow {
      margin-bottom: 8px;
    }
    .build-context-title {
      font-size: clamp(30px, 3.4vw, 44px);
      line-height: 1.02;
      letter-spacing: -.05em;
      color: var(--ink);
      font-weight: 900;
    }
    .build-context-change {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      background: rgba(255,255,255,.85);
      border: 1px solid var(--line);
      border-radius: 999px;
      padding: 11px 18px;
      font-size: 12px;
      font-weight: 900;
      letter-spacing: .02em;
      color: var(--ink);
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease;
      white-space: nowrap;
    }
    .build-context-change:hover {
      border-color: var(--blue);
      background: #F4FCFF;
      transform: translateY(-1px);
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .build-context-change span { font-weight: 900; }
    /* ── Admin edit affordances (only render when $_IS_SITE_ADMIN) ──────────────
       The engine (inc/page/product-form.php) emits per-option "edit" links as
       <a href="…productoption.php?action=edit…"><i class="far fa-flask-potion"></i></a>.
       FontAwesome is NOT loaded on the v2 (header-v2) configurator chrome, so that
       glyph renders empty/invisible. We brand these into a visible gold pill (and
       hide the dead FA <i>), and match the product-level button (.cfg-admin-edit)
       we add in build-context. Branded, not the muted legacy look. */
    .cfg-admin-edit,
    a[href*="productoption.php?action=edit"] {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      background: var(--gold-soft);
      color: #7A5A1E !important;
      border: 1px solid var(--gold);
      border-radius: 999px;
      padding: 5px 11px;
      font-size: 11px;
      font-weight: 800;
      letter-spacing: .02em;
      line-height: 1;
      text-decoration: none;
      white-space: nowrap;
      transition: background .18s ease, box-shadow .18s ease, transform .18s ease;
    }
    .cfg-admin-edit:hover,
    a[href*="productoption.php?action=edit"]:hover {
      background: #F1E3C4;
      box-shadow: 0 6px 16px rgba(201,169,110,.22);
      transform: translateY(-1px);
    }
    /* hide the empty FontAwesome glyph and label the engine's option links */
    a[href*="productoption.php?action=edit"] > i { display: none; }
    /* …but NOT our own .cfg-admin-option link, which already carries its full label in
       textContent ("✎ Edit Foil — option #281"). Without this exclusion it renders twice. */
    a[href*="productoption.php?action=edit"]:not(.cfg-admin-option)::after {
      content: "\270E\A0 Edit"; /* ✎ + nbsp + "Edit" — trailing space terminates the hex escape so it can't eat "Ed" */
    }
    /* the product-level button (build-context, right column) sits a touch larger */
    .cfg-admin-product {
      padding: 8px 14px;
      font-size: 12px;
      justify-self: end;
    }
    .cfg-admin-edit-ico { font-size: 13px; line-height: 1; }
    /* per-option link, rendered as the first child of each finish panel by the rail builder.
       The engine's own copy of this link is unreachable here — the rail re-parents its <dt>
       out from under `.accordion > dt.cfg-finish-row`, so that rule stops matching. */
    /* `a.` not `.` — the shared base rule above is `a[href*="…"]` (0,1,1), which outbids a
       bare class (0,1,0), so a plain `.cfg-admin-option` loses white-space and never wraps. */
    a.cfg-admin-option {
      align-self: start;
      margin: 0 0 12px;
      max-width: 100%;
      white-space: normal;
    }
    /* child options — same pill, smaller and lighter so the parent still reads as the primary */
    .cfg-admin-subopts {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
      margin: -6px 0 14px;
    }
    a.cfg-admin-subopt {
      margin: 0;
      padding: 4px 9px;
      font-size: 10px;
      font-weight: 700;
      background: #FCF8F0;
    }

    .build-context-picker {
      margin-top: 24px;
      padding-top: 22px;
      border-top: 1px solid var(--line);
    }
    .build-context-picker[hidden] { display: none; }
    .picker-prompt {
      color: var(--muted);
      font-size: 13px;
      font-weight: 700;
      margin-bottom: 14px;
      letter-spacing: -.005em;
    }

    .step {
      padding: 30px 32px;
      border-bottom: 1px solid var(--line);
    }
    .step:last-child { border-bottom: 0; }
    .step-title {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 20px;
      margin-bottom: 18px;
    }
    .step-title h3 {
      font-size: 25px;
      line-height: 1.1;
      letter-spacing: -.04em;
    }
    .step-title p {
      color: var(--muted);
      font-size: 14px;
      margin-top: 6px;
      max-width: 620px;
    }
    .step-num {
      width: 34px;
      height: 34px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border-radius: 50%;
      background: var(--blue-soft);
      border: 1px solid rgba(0,194,255,.28);
      color: #00698B;
      font-size: 13px;
      font-weight: 900;
      margin-right: 10px;
      vertical-align: top;
    }
    .recommend {
      background: #fff;
      border: 1px solid var(--line);
      border-radius: 999px;
      padding: 8px 11px;
      color: var(--gold);
      font-size: 11px;
      font-weight: 900;
      white-space: nowrap;
    }

    .choice-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 12px;
    }
    .choice-grid.two { grid-template-columns: repeat(2, 1fr); }
    .card-type-grid {
      grid-template-columns: repeat(4, 1fr);
    }
    .card-type-grid .choice {
      min-height: 82px;
      padding: 15px;
    }
    .choice {
      position: relative;
      background: #fff;
      border: 1px solid #DDD8CE;
      border-radius: 16px;
      padding: 16px;
      min-height: 92px;
      cursor: pointer;
      transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease, background .2s ease;
    }
    .choice:hover {
      transform: translateY(-1px);
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .choice.active {
      background: linear-gradient(180deg, #F4FCFF, #FFFFFF);
      border-color: var(--blue);
      box-shadow: inset 0 0 0 1px rgba(0,194,255,.15), 0 13px 30px rgba(0,194,255,.10);
    }
    .choice.active::after {
      content: "✓";
      position: absolute;
      top: 12px;
      right: 12px;
      width: 22px;
      height: 22px;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: 50%;
      background: var(--blue);
      color: #071015;
      font-size: 13px;
      font-weight: 900;
    }
    .choice strong {
      display: block;
      font-size: 14px;
      line-height: 1.25;
      margin-bottom: 6px;
    }
    .choice span {
      display: block;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.45;
      max-width: 92%;
    }
    .card-shape {
      height: 36px;
      border-radius: 7px;
      border: 1px solid #CFC9BE;
      background: linear-gradient(135deg, #F8F6F0, #E8E1D3);
      margin-bottom: 12px;
    }
    .card-shape.slim { width: 80%; }
    .card-shape.square { width: 48px; }
    .card-shape.standard { width: 88%; }
    .card-shape.custom {
      width: 68%;
      border-style: dashed;
      background: linear-gradient(135deg, #FFFFFF, #F2EDE3);
    }
    .size-grid {
      grid-template-columns: repeat(3, 1fr);
      align-items: stretch;
    }
    .size-choice {
      display: flex;
      flex-direction: column;
      justify-content: center;
      min-height: 78px;
      padding: 18px;
    }
    .size-choice strong {
      font-size: 18px;
      letter-spacing: -.02em;
      margin-bottom: 4px;
    }
    .size-choice span {
      font-size: 12px;
      color: var(--muted);
      letter-spacing: .01em;
    }
    .custom-size-row {
      grid-column: 1 / -1;
      display: grid;
      grid-template-columns: 1fr 2fr;
      gap: 12px;
      align-items: stretch;
    }
    .custom-size-row .choice {
      min-height: 92px;
    }
    .custom-size-inline {
      background: #fff;
      border: 1px dashed rgba(201,169,110,.48);
      border-radius: 16px;
      padding: 14px 16px;
      display: flex;
      align-items: center;
      gap: 12px;
    }
    .custom-size-inline label {
      display: flex;
      flex-direction: column;
      gap: 5px;
      color: var(--muted);
      font-size: 10px;
      font-weight: 900;
      text-transform: uppercase;
      letter-spacing: .08em;
      flex: 1;
    }
    .custom-size-inline input {
      width: 100%;
      height: 44px;
      border: 1px solid #DDD8CE;
      border-radius: 10px;
      background: #fff;
      padding: 0 10px;
      font-weight: 900;
      color: var(--ink);
    }
    .custom-size-inline > span {
      padding-top: 18px;
      color: var(--muted);
      font-weight: 900;
    }

    .thickness-line {
      width: 92%;
      height: 7px;
      border-radius: 999px;
      background: #C7C2B7;
      margin-bottom: 14px;
    }
    .thickness-line.thick { height: 11px; background: #A9A397; }
    .thickness-line.ultra { height: 15px; background: #8D877B; }

    .step-sub {
      margin-top: 26px;
    }
    .step-sub:first-of-type { margin-top: 6px; }
    .step-sub-head {
      display: flex;
      align-items: center;
      gap: 10px;
      margin-bottom: 14px;
    }
    .sub-num {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 28px;
      height: 28px;
      background: var(--gold-soft);
      border: 1px solid rgba(201,169,110,.32);
      border-radius: 50%;
      font-size: 11px;
      font-weight: 900;
      color: #8A6428;
      letter-spacing: -.01em;
    }
    .step-sub-head strong {
      font-size: 16px;
      font-weight: 900;
      letter-spacing: -.02em;
      color: var(--ink);
    }
    .sub-meta {
      color: var(--muted);
      font-weight: 700;
      margin-left: 4px;
    }
    .stock-grid {
      grid-template-columns: repeat(4, 1fr);
    }
    .stock-grid .choice {
      min-height: 82px;
      padding: 15px;
    }
    .thickness-grid {
      grid-template-columns: repeat(3, 1fr);
    }

    .foil-detail-block {
      display: flex;
      flex-direction: column;
      gap: 16px;
    }
    .foil-count-strip {
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 18px;
      align-items: center;
      background: linear-gradient(135deg, #FFFFFF, var(--ivory));
      border: 1px solid rgba(201,169,110,.25);
      border-radius: 20px;
      padding: 18px;
    }
    .foil-count-copy strong {
      display: block;
      font-size: 15px;
      margin-bottom: 4px;
    }
    .foil-count-copy span {
      display: block;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.5;
      max-width: 560px;
    }
    .foil-count-options {
      display: flex;
      gap: 8px;
      background: rgba(255,255,255,.75);
      border: 1px solid var(--line);
      border-radius: 999px;
      padding: 6px;
    }
    .count-btn {
      width: 42px;
      height: 36px;
      border: 0;
      border-radius: 999px;
      background: transparent;
      font-weight: 900;
      cursor: pointer;
      color: var(--muted);
    }
    .count-btn.active {
      background: var(--blue);
      color: var(--ink);
      box-shadow: 0 8px 18px rgba(0,194,255,.18);
    }
    .foil-color-tabs {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
    }
    .foil-tab {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      border: 1px solid var(--line);
      background: #fff;
      border-radius: 999px;
      padding: 10px 14px;
      font-size: 13px;
      font-weight: 900;
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease;
    }
    .foil-tab:hover {
      transform: translateY(-1px);
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .foil-tab.active {
      border-color: var(--blue);
      background: #F4FCFF;
    }
    .foil-tab.add {
      color: var(--blue-dark);
      border-style: dashed;
    }
    .foil-setup-card {
      background: #fff;
      border: 1px solid var(--line);
      border-radius: 22px;
      padding: 20px;
      box-shadow: 0 14px 32px rgba(22,18,11,.05);
    }
    .foil-setup-head {
      display: flex;
      justify-content: space-between;
      gap: 16px;
      align-items: flex-start;
      padding-bottom: 16px;
      margin-bottom: 16px;
      border-bottom: 1px solid var(--line);
    }
    .foil-setup-head h4 {
      margin: 0;
      font-size: 24px;
      line-height: 1;
      letter-spacing: -.04em;
    }
    .setup-status {
      background: var(--gold-soft);
      color: #8A6428;
      border: 1px solid rgba(201,169,110,.28);
      border-radius: 999px;
      padding: 7px 11px;
      font-size: 11px;
      font-weight: 900;
    }
    .foil-group {
      background: rgba(251,248,241,.55);
      border: 1px solid var(--line);
      border-radius: 18px;
      padding: 18px;
      margin-top: 12px;
    }
    .clean-group:first-of-type { margin-top: 0; }
    /*
      Signature Finish sub-section header pattern (canonical):
      Cyan vertical bar (left) + ink UPPERCASE letterspaced title.
      Used by .sub-header (sub-section selectors inside any Signature Finish setup card)
      AND by .mini-label (setup card eyebrows like "FOIL 1 SETUP", "ADDITIONAL SERVICES")
      so the pattern is visually consistent across all Signature Finish sub-config UI.
      Gold is no longer used to carry instructional text.
    */
    .mini-label,
    .sub-header {
      display: flex;
      align-items: center;
      gap: 12px;
      margin-bottom: 12px;
      font-size: 12px;
      font-weight: 900;
      letter-spacing: .16em;
      text-transform: uppercase;
      color: var(--ink);
      line-height: 1.1;
    }
    .mini-label::before,
    .cfg-edge-kind::before,
    .sub-header-bar {
      content: "";
      display: inline-block;
      width: 4px;
      height: 18px;
      background: var(--blue);
      border-radius: 2px;
      box-shadow: 0 0 12px rgba(0,194,255,.32);
      flex: 0 0 auto;
    }
    .sub-header-title {
      font: inherit;
      letter-spacing: inherit;
      color: inherit;
      text-transform: inherit;
    }
    .compact-grid .choice {
      min-height: 78px;
      padding: 14px;
    }
    .foil-swatch-grid {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 10px;
    }
    .foil-swatch {
      display: flex;
      align-items: center;
      gap: 9px;
      border: 1px solid #DDD8CE;
      background: #fff;
      border-radius: 13px;
      padding: 11px;
      font-size: 12px;
      text-align: left;
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease;
    }
    .foil-swatch:hover {
      transform: translateY(-1px);
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .foil-swatch.active {
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: inset 0 0 0 1px rgba(0,194,255,.13);
    }
    .foil-type-grid {
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      gap: 12px;
    }
    .foil-type {
      border: 1px solid #DDD8CE;
      background: #fff;
      border-radius: 14px;
      padding: 10px;
      cursor: pointer;
      text-align: center;
      font-size: 11px;
      font-weight: 900;
      transition: border-color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease;
    }
    .foil-type:hover {
      transform: translateY(-1px);
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .foil-type.active {
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: inset 0 0 0 1px rgba(0,194,255,.13);
    }
    /* .foil-texture colour comes from window.cfgFoilIcon in configure.php (one recipe, the foil's own
       colour). The five gold-only .foil-texture.<type> backgrounds were deleted 2026-09-22 — do not re-add. */
    .foil-texture {
      display: block;
      height: 76px;
      border-radius: 9px;
      margin-bottom: 8px;
      border: 1px solid rgba(0,0,0,.08);
    }
    .foil-placement-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 12px;
    }
    .placement {
      position: relative;
      border: 1px solid #DDD8CE;
      background: #fff;
      border-radius: 14px;
      padding: 18px 14px 16px;
      cursor: pointer;
      text-align: center;
      transition: border-color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease, opacity .2s ease;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 10px;
    }
    .placement:hover {
      transform: translateY(-1px);
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .placement-diagram {
      display: block;
      width: 110px;
      height: 48px;
      filter: drop-shadow(0 2px 4px rgba(30,24,12,.10));
    }
    .placement .layer-top-face { fill: #FFFAEB; transition: fill .25s ease; }
    .placement .layer-top-front { fill: #F5EFE2; transition: fill .25s ease; }
    .placement .layer-mid-face { fill: #FFFAEB; transition: fill .25s ease; }
    .placement .layer-mid-front { fill: #F5EFE2; transition: fill .25s ease; }
    .placement .layer-bot-face { fill: #FFFAEB; transition: fill .25s ease; }
    .placement .layer-bot-front { fill: #F5EFE2; transition: fill .25s ease; }
    .placement .layer-stroke { stroke: #1A1A1A; stroke-width: .55; fill: none; }
    /* A PLACEMENT ICON'S HIGHLIGHT IS BLUE, PICKED OR NOT (owner 2026-10-01: "change all
       highlights to blue"). It was gold until the card was picked and blue after; now the
       icon only says WHICH layer the card means, and the card's own border and tick say it
       is picked. Same rule on the three-bar icon (.mini-layer-icon) of the foil, Spot UV and
       die-cut screens' cards, and the plies on a choice card (.cfg-ply). */
    .placement.front-side .layer-top-face { fill: #6FDDFF; }
    .placement.front-side .layer-top-front { fill: #00C2FF; }
    .placement.mid-layer .layer-mid-face { fill: #6FDDFF; }
    .placement.mid-layer .layer-mid-front { fill: #00C2FF; }
    .placement.back-side .layer-bot-face { fill: #6FDDFF; }
    .placement.back-side .layer-bot-front { fill: #00C2FF; }
    .placement-check {
      display: block;
      width: 22px;
      height: 22px;
      border: 1.5px solid #BFB8AC;
      border-radius: 5px;
      background: #fff;
      position: relative;
      transition: background .2s ease, border-color .2s ease;
    }
    .placement.active .placement-check {
      background: var(--blue);
      border-color: var(--blue);
    }
    .placement.active .placement-check::after {
      content: "✓";
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #fff;
      font-weight: 900;
      font-size: 14px;
      line-height: 1;
    }
    .placement-label {
      font-size: 14px;
      font-weight: 800;
      color: var(--ink);
      letter-spacing: -.01em;
      margin: 0;
      line-height: 1.2;
    }
    .placement.active {
      border-color: var(--blue);
      background: #F4FCFF;
    }
    .placement.locked {
      background: #FAF7F0;
      opacity: .9;
    }
    .placement.locked:hover {
      opacity: 1;
      border-color: var(--blue);
      background: #F4FCFF;
    }
    /* a locked card's own layer is grey, whichever layer it is (blue would read as available) */
    .placement.front-side.locked .layer-top-face,
    .placement.mid-layer.locked .layer-mid-face,
    .placement.back-side.locked .layer-bot-face { fill: #CFCABF; }
    .placement.front-side.locked .layer-top-front,
    .placement.mid-layer.locked .layer-mid-front,
    .placement.back-side.locked .layer-bot-front { fill: #A29D93; }
    .placement.locked .placement-check { display: none; }
    .placement-lock {
      display: none;
      width: 28px;
      height: 28px;
      border-radius: 50%;
      background: #DCD6CA;
      color: #5F594C;
      align-items: center;
      justify-content: center;
      font-size: 14px;
      font-weight: 900;
    }
    .placement.locked .placement-lock { display: inline-flex; }
    .placement-micro {
      display: block;
      font-size: 11px;
      line-height: 1.4;
      color: #7B7466;
      font-style: italic;
      margin-top: -2px;
      padding: 0 4px;
      letter-spacing: 0;
    }
    /* 2026-09-03: the reason moved OUT of the card to one .cfg-place-note under the grid,
       so the micro line ('inner ply') stays visible — hiding it left a locked card with
       nothing but a label and a padlock. */
    .placement.locked .placement-label { color: #5F594C; }
    /* W4 — Through-cut placement (die cut): cuts through the whole stack, so it
       highlights all three layer faces (blue, picked or not — see the highlight rule above). */
    .placement.through-cut .layer-top-face,
    .placement.through-cut .layer-mid-face,
    .placement.through-cut .layer-bot-face { fill: #6FDDFF; }
    .placement.through-cut .layer-top-front,
    .placement.through-cut .layer-mid-front,
    .placement.through-cut .layer-bot-front { fill: #00C2FF; }
    /* W4 — the engine's placement checkboxes are enhanced into .placement cards by
       configure.php's W4 JS. The wrapper is the engine's div.radio-group.checkbox-group;
       its raw input + original <label> are hidden, the card content is injected. */
    .cfg-placement-grid { margin-top: 10px; }

    /* ONE NOTE UNDER THE GRID (owner-directed 2026-09-03: "lock with one note").
       Replaces the sentence that used to be printed inside every locked card — die cut on a
       one-ply stock repeated it three times. Written by window.cfgPlaceNote, which NAMES the
       stocks that unlock the placement by reading the picker, so it cannot promise a
       "32pt or 48pt" the product does not sell (the old hardcoded copy did, on every card
       whose layered stock is a Cotton 45pt or a Laid 24pt).
       Quiet by design: it explains a card the buyer cannot click, so it must not compete with
       the ones they can. #6B6B6B on white measures AA at this size. */
    .cfg-place-note {
      margin: 10px 0 0;
      font-size: 12.5px;
      line-height: 1.5;
      color: #6B6B6B;
    }
    /* THE NOTE IS NOT DRAWN IN THE PAGE; IT OPENS FROM THE LOCKED CARD (owner 2026-10-01: "hide
       that text behind an (i) icon or upon hover over the middle card"). It sat flush against
       the panel's edge in the foil screen (0px, the heading 22px in) and ran two lines under
       every grid with a locked card. The note element stays where each caller puts it — it is
       what the bubble reads — and the script beside cfgPlaceNote shows its words in #cfg-tip
       when a locked card is pointed at, focused or tapped. The edge screen's straight-edge
       note explains the whole screen, not one locked card, and stays in the page. */
    .cfg-place-note:not(.cfg-edge-straight-note) { display: none; }
    .placement.locked,
    .cfg-selector-view .placement-tab.is-locked,
    .cfg-selector-view .placement-card.is-locked { cursor: help; }
    .placement.locked::after,
    .cfg-selector-view .placement-tab.is-locked::after,
    .cfg-selector-view .placement-card.is-locked::after {
      content: "i";
      position: absolute; top: 5px; right: 5px;
      width: 16px; height: 16px; box-sizing: border-box;
      border: 1.5px solid #3C4650; border-radius: 50%;
      color: #3C4650; background: #fff;
      font: italic 700 11px/13px Georgia, 'Times New Roman', serif;
      text-align: center;
    }
    /* the bubble: one element on <body>, placed by the script in window coordinates */
    #cfg-tip {
      position: fixed; z-index: 1400; box-sizing: border-box;
      padding: 10px 12px; border-radius: 10px;
      background: #11151A; color: #fff;
      font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 12.5px; line-height: 1.45; font-weight: 500;
      box-shadow: 0 10px 28px rgba(0,0,0,.24);
      opacity: 0; visibility: hidden; pointer-events: none;
      transition: opacity .12s ease;
    }
    #cfg-tip.is-open { opacity: 1; visibility: visible; }
    #cfg-tip::before {
      content: ""; position: absolute; left: var(--cfg-tip-x, 50%); top: -5px;
      width: 10px; height: 10px; margin-left: -5px; background: #11151A; transform: rotate(45deg);
    }
    #cfg-tip.is-above::before { top: auto; bottom: -5px; }

    /* A placement no stock on THIS product could ever reach is not drawn at all (owner:
       "It shouldn't even be an option on plastic"). Hidden by CLASS, never the `hidden`
       property: an authored display rule beats the UA's [hidden] and the card keeps
       rendering — the standing lesson from the 3D-proofer preset tabs. */
    .placement.cfg-place-off { display: none !important; }
    .placement > input[type="checkbox"] { display: none; }
    .placement > label[for] { display: none; }
    /* W4 — finish accordion headers decorated into card rows (icon + name + desc +
       toggle) by configure.php JS, matching the mockup's .finish-card. Decoration
       only: the engine's checkbox (finish on/off) + accordion expand are untouched. */
    .accordion:not(.base_accordion) > dt.cfg-finish-row {
      display: flex;
      align-items: center;
      gap: 14px;
      padding: 14px 16px;
      margin: 8px 0;
      border: 1px solid var(--line, #E7E2D8);
      border-radius: 14px;
      background: #fff;
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease, box-shadow .2s ease, transform .2s ease;
    }
    .accordion:not(.base_accordion) > dt.cfg-finish-row:hover {
      transform: translateY(-1px);
      border-color: var(--blue, #00C2FF);
      background: #F4FCFF;
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .accordion:not(.base_accordion) > dt.cfg-finish-row:has(input.type-checker:checked),
    .accordion:not(.base_accordion) > dt.cfg-finish-row.active {
      border-color: var(--blue, #00C2FF);
      background: #F4FCFF;
    }
    .cfg-finish-row .finish-icon {
      width: 42px; height: 42px; flex: 0 0 auto;
      border-radius: 12px;
      background: var(--gold-soft, #F8F1E3);
      border: 1px solid rgba(201,169,110,.24);
      color: var(--gold, #C9A96E);
      display: flex; align-items: center; justify-content: center;
      font-weight: 900; font-size: 13px; letter-spacing: -.01em;
    }
    .cfg-finish-row .cfg-finish-copy {
      flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px;
      font-size: 14px; font-weight: 800; color: var(--ink, #111);
    }
    .cfg-finish-row .cfg-finish-desc { font-weight: 500; font-size: 12px; color: #7B7466; }
    /* keep the engine's checkbox (check-container) at the right as the toggle */
    .cfg-finish-row .check-container { order: 9; margin-left: auto; }
    .cfg-finish-row .option_parent_price { order: 8; }
    /* #3 — 2-up finish grid (v1.45 Image 1): lay the finish cards two per row,
       with the active/expanded panel (dd) spanning full width below. The engine
       sets collapsed dds to display:none, so they leave grid flow; grid-auto-flow
       dense backfills the right-column card when a left card expands (no hole).
       Scoped via :has(> dt.cfg-finish-row) to the FINISHES accordion only — never
       base_accordion (steps 1/3/4) nor the lone ArtWork accordion (no finish-row). */
    .accordion:not(.base_accordion):has(> dt.cfg-finish-row) {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      grid-auto-flow: row dense;
      gap: 12px;
    }
    .accordion:not(.base_accordion):has(> dt.cfg-finish-row) > .cfg-accordion-title {
      grid-column: 1 / -1; margin-bottom: 0;
    }
    .accordion:not(.base_accordion):has(> dt.cfg-finish-row) > dt.cfg-finish-row { margin: 0; }
    .accordion:not(.base_accordion):has(> dt.cfg-finish-row) > dd { grid-column: 1 / -1; }
    @media (max-width: 640px) {
      .accordion:not(.base_accordion):has(> dt.cfg-finish-row) { grid-template-columns: 1fr; }
    }
    /* W4/skin — clean up the engine's option radio lists (Backside Print, ArtWork):
       drop the default <ul>/<li> bullets, lay the options out inline, accent the
       radios in brand blue. CSS-only — no markup/JS change. */
    .cfg-step ul.optionRadio {
      list-style: none; margin: 8px 0 0; padding: 0;
      display: flex; flex-wrap: wrap; gap: 10px 22px;
    }
    .cfg-step ul.optionRadio > li {
      margin: 0; display: inline-flex; align-items: center; gap: 8px;
      font-size: 14px; color: var(--ink, #111); cursor: pointer;
    }
    .cfg-step ul.optionRadio input[type="radio"] {
      accent-color: var(--blue, #00C2FF);
      width: 16px; height: 16px; margin: 0; cursor: pointer; flex: 0 0 auto;
    }
    /* Custom "Other …" reveal inputs (quantity/sets/paper/size) — the engine
       renders raw browser text boxes; brand them to match v1.45's field style. */
    .cfg-step .optioninput input.optionselect,
    .cfg-step input.optionselect_half {
      border: 1px solid #DDD8CE; border-radius: 10px;
      padding: 10px 12px; background: #fff;
      font: 700 14px/1 var(--font, inherit); color: var(--ink, #111);
      box-sizing: border-box;
    }
    .cfg-step .optioninput input.optionselect { width: 100%; max-width: 280px; }
    .cfg-step .optioninput input.optionselect:focus,
    .cfg-step input.optionselect_half:focus {
      outline: none; border-color: var(--blue, #00C2FF);
      box-shadow: 0 0 0 3px rgba(0,194,255,.14);
    }
    .cfg-step .optioninput label { font-size: 12px; font-weight: 800; color: var(--muted, #6F6F6F); }
    /* The Quantity and "Number of sets" cards are MOVED out of #cfg-step-3 (into the
       inline config panel), so the .cfg-step-scoped rules above never reached their
       custom "Other …" inputs — measured 2026-09-02: #other_format and #other_quantity
       rendered at full browser default (2px inset border, 13.3px, no radius), which is
       the unbranded spinner the owner reported. Key the treatment to the CARD instead,
       so it travels with the control wherever the skin re-homes it. */
    .order-field-card .optioninput input.optionselect,
    .order-field-card input.optionselect_half {
      border: 1px solid #DDD8CE; border-radius: 10px;
      padding: 10px 12px; background: #fff;
      font: 700 14px/1 var(--font, inherit); color: var(--ink, #111);
      box-sizing: border-box; width: 100%; max-width: 280px;
    }
    .order-field-card .optioninput input.optionselect:focus,
    .order-field-card input.optionselect_half:focus {
      outline: none; border-color: var(--blue, #00C2FF);
      box-shadow: 0 0 0 3px rgba(0,194,255,.14);
    }
    .order-field-card .optioninput { margin-top: 8px; }
    .order-field-card .optioninput label { display: block; margin-bottom: 5px; font-size: 12px; font-weight: 800; color: var(--muted, #6F6F6F); }
    /* Drop the OS stepper arrows on these two — type="number" keeps its native spinner
       however the box is styled, and the arrows are the thing that reads as raw. The
       field stays type="number", so the engine's numeric validation is unchanged. */
    .order-field-card input.optionselect[type="number"] { -moz-appearance: textfield; appearance: textfield; }
    .order-field-card input.optionselect[type="number"]::-webkit-outer-spin-button,
    .order-field-card input.optionselect[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

    /* ── (D) Brand bare engine radio/checkbox sub-option lists ─────────────────
       Lists like Die Cut shapes, ArtWork (files/design), Rounded-corner radius
       render as <ul><li id="li_option_…"> WITHOUT the optionRadio class, so they
       kept default bullets. Placement children are div#li_option_… (not <li>), so
       targeting li[id^=li_option_] leaves the placement cards untouched. */
    #shoppingform ul:has(> li[id^="li_option_"]) {
      list-style: none; margin: 8px 0 0; padding: 0;
      display: flex; flex-wrap: wrap; gap: 10px 22px;
    }
    #shoppingform li[id^="li_option_"] {
      list-style: none; margin: 0; display: inline-flex; align-items: center; gap: 8px;
      font-size: 14px; color: var(--ink, #111);
    }
    #shoppingform li[id^="li_option_"] > input[type="radio"],
    #shoppingform li[id^="li_option_"] > input[type="checkbox"] {
      accent-color: var(--blue, #00C2FF); width: 16px; height: 16px; margin: 0; flex: 0 0 auto;
    }

    /* ── (C) Engine price + action buttons (form-summary) → HIDDEN ─────────────
       The legacy engine renders the running total + per-item + Request Quotation /
       Add to Cart / submit at the bottom of the form. This duplicated the sidebar
       price-box, so we HIDE it and let the sidebar be the single price+action
       surface. The buttons stay in the DOM (display:none) — the sidebar mirrors the
       total + per-item + quote-visibility and drives these hidden buttons via
       .click(), so checkform() validation + the /cart.php submit path are unchanged. */
    #shoppingform .form-summary { display: none !important; }

    .foil-group.pending { display: none; }
    .foil-group .foil-summary { display: none; }
    .foil-group.collapsed > .foil-swatch-grid,
    .foil-group.collapsed > .foil-type-grid,
    .foil-group.collapsed > .foil-placement-grid { display: none; }
    .foil-group.collapsed > .foil-summary {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      margin-top: 6px;
      padding: 6px 2px 0;
    }
    .foil-summary-row {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      font-size: 14px;
      flex: 1;
      min-width: 0;
    }
    .summary-mini {
      font-size: 10px;
      font-weight: 900;
      letter-spacing: .14em;
      text-transform: uppercase;
      color: #8A8576;
      flex-shrink: 0;
    }
    .summary-swatch {
      width: 18px;
      height: 18px;
      border-radius: 4px;
      border: 1px solid rgba(16,16,16,.08);
      display: inline-block;
      flex-shrink: 0;
    }
    .summary-value {
      font-size: 14px;
      font-weight: 900;
      color: var(--ink);
      letter-spacing: -.01em;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .foil-change-btn {
      background: transparent;
      border: none;
      color: var(--blue-dark);
      font-size: 12px;
      font-weight: 900;
      cursor: pointer;
      padding: 5px 12px;
      text-decoration: underline;
      text-underline-offset: 3px;
      letter-spacing: -.01em;
      border-radius: 8px;
      transition: background .2s ease, color .2s ease;
      flex-shrink: 0;
    }
    .foil-change-btn:hover {
      color: var(--blue);
      background: rgba(0,194,255,.08);
    }
    /* .signature-finish-stack retired in v1.32 — setup cards now inline inside .finish-row */
    .foil-group.shape-hidden { display: none; }
    /* PMS Ink +/- add-remove-line UI (owner design 2026-06-04): the engine's
       "Number of PMS Ink" count select is replaced by per-line code entry +
       add/remove buttons (the count is driven behind the scenes). Each engine
       instance div (suboptioncontent_*) becomes a line-card; the forced Color
       Calibration sub-option is already engine-hidden and rides along (setup fee). */
    .cfg-pms-counthide { display: none !important; }      /* the replaced count select/row */
    .pms-line {
      position: relative;
      margin: 0 0 10px;
      padding: 12px 44px 12px 14px;
      border: 1px solid var(--line);
      border-radius: 12px;
      background: #fff;
    }
    .pms-line .optioninput, .pms-line input.variabledata { width: 100%; }
    .pms-line input.variabledata {
      padding: 11px 12px;
      border: 1px solid var(--line);
      border-radius: 10px;
      background: #fff;
      font-size: 14px;
      font-weight: 700;
      color: var(--ink);
      font-family: inherit;
    }
    .pms-line input.variabledata:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(0,194,255,.16); }
    .pms-line-remove {
      position: absolute; top: 50%; right: 10px; transform: translateY(-50%);
      width: 28px; height: 28px; padding: 0;
      border: 1px solid var(--line); border-radius: 8px;
      background: #fff; color: #B4291F; font-size: 17px; font-weight: 800; line-height: 1;
      cursor: pointer; transition: border-color .2s ease, background .2s ease;
    }
    .pms-line-remove:hover:not(:disabled) { border-color: #E0584E; background: #FDF3F2; }
    .pms-line-remove:disabled { opacity: .35; cursor: not-allowed; }
    .pms-add-line {
      display: inline-flex; align-items: center; gap: 7px; margin: 2px 0 4px;
      padding: 9px 16px;
      border: 1px dashed var(--blue); border-radius: 999px;
      background: #F4FCFF; color: var(--blue);
      font-size: 12px; font-weight: 800; cursor: pointer;
      transition: background .2s ease, border-color .2s ease;
    }
    .pms-add-line:hover:not(:disabled) { background: #E4F8FF; }
    .pms-add-line:disabled { opacity: .4; cursor: not-allowed; }
    /* #2b multisub multi-select rows (foil colors / spot UV / die cut) */
    .cfg-multi-row {
      position: relative;
      border: 1px solid var(--line);
      border-radius: 12px;
      padding: 14px 46px 14px 14px;
      margin: 0 0 12px;
    }
    .cfg-multi-rowhead {
      font-size: 10px; font-weight: 900; letter-spacing: .12em;
      text-transform: uppercase; color: var(--muted); margin-bottom: 10px;
    }
    .cfg-multi-remove {
      position: absolute; top: 12px; right: 12px;
      width: 28px; height: 28px; padding: 0;
      border: 1px solid var(--line); border-radius: 8px;
      background: #fff; color: #B4291F; font-size: 17px; font-weight: 800; line-height: 1;
      cursor: pointer; transition: border-color .2s ease, background .2s ease;
    }
    .cfg-multi-remove:hover:not(:disabled) { border-color: #E0584E; background: #FDF3F2; }
    .cfg-multi-remove:disabled { opacity: .35; cursor: not-allowed; }
    /* #2b foil: COLOR → PATTERNS → PLACEMENTS custom panel (engine instances hidden) */
    .cfg-foil-panel { }
    .cfg-foil-hint { font-size: 12px; color: var(--muted); margin: 0 0 12px; }
    .cfg-foil-colorgrid, .cfg-foil-patterngrid { margin-bottom: 4px; }
    /* color card = .foil-swatch + a charge badge + remove × + selected/focused rings */
    .cfg-color-card { position: relative; padding-right: 30px; }
    .cfg-color-card .cfg-color-name { flex: 1; }
    .cfg-color-card.selected { border-color: var(--blue); background: #F4FCFF; }
    .cfg-color-card.focused { box-shadow: 0 0 0 2px var(--blue); }
    .cfg-color-badge {
      position: absolute; bottom: 8px; right: 9px;
      min-width: 20px; height: 20px; padding: 0 6px;
      border-radius: 999px; background: var(--blue); color: #fff;
      font-size: 11px; font-weight: 800; line-height: 20px; text-align: center;
    }
    /* pattern card = .foil-type + remove × + selected/focused rings */
    .cfg-pattern-card { position: relative; }
    .cfg-pattern-card.selected { border-color: var(--blue); background: #F4FCFF; }
    .cfg-pattern-card.focused { box-shadow: 0 0 0 2px var(--blue); }
    .cfg-card-x {
      position: absolute; top: 6px; right: 7px;
      width: 20px; height: 20px; border-radius: 6px;
      background: rgba(255,255,255,.85); color: #B4291F;
      font-size: 15px; font-weight: 800; line-height: 20px; text-align: center;
      cursor: pointer;
    }
    .cfg-card-x:hover { background: #FDF3F2; }
    /* Kill the instance-flash glitch: once a finish panel is decorated, its engine
       charge-carrier instances are hidden via CSS so a newly-cloned instance (added by
       the count change on each selection) is born hidden — no one-frame flash before the
       JS hideEngine() catches it. Scoped to the decorated dd (data-attr) so it's a safe
       fallback: if the decorator never runs, the raw instances still show. */
    [data-cfg-foil-panel] div[id^="suboptioncontent_281-"],
    [data-cfg-uv-panel]   div[id^="suboptioncontent_23-"],
    [data-cfg-dc-panel]   div[id^="suboptioncontent_229-"] { display: none !important; }
    /* Spot UV custom panel (reuses .cfg-foil-panel): 3 UV types, Front/Middle/Back placement */
    .cfg-uv-typegrid { grid-template-columns: repeat(3, 1fr); }
    .cfg-uv-areagrid { grid-template-columns: repeat(3, 1fr); }
    /* Die Cut custom panel: shape methods = roomy v1.45 vertical tiles (icon over label,
       not the cramped horizontal chip) + 4-spot placement. High specificity so the tile
       sizing wins over the base .swatch/.foil-swatch rules defined later in the file. */
    .cfg-dc-shapegrid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
    .cfg-dc-areagrid { grid-template-columns: repeat(2, 1fr); }
    .cfg-dc-shapegrid .cfg-color-card {
      flex-direction: column; align-items: center; justify-content: center; text-align: center;
      gap: 9px; padding: 16px 12px; min-height: 104px;
    }
    .cfg-dc-shapegrid .cfg-color-card .cfg-dc-swatch {
      background: transparent !important; width: 64px; height: 40px; border-radius: 0; padding: 0; flex: none; display: inline-flex;
    }
    .cfg-dc-shapegrid .cfg-color-card .cfg-dc-icon { width: 64px; height: 40px; display: block; }
    .cfg-dc-shapegrid .cfg-color-card .cfg-color-name { flex: none; font-size: 13px; }
    .cfg-dc-shapegrid .cfg-color-card .cfg-color-badge { bottom: auto; top: 8px; left: 8px; right: auto; }

    /* Make a SELECTED card unmistakable (owner: hard to tell what's selected). A 2px blue
       inner ring + tinted gradient + lift, applied to every choosable card type. Inner ring
       via box-shadow = no layout shift. The panel cards (.cfg-color-card/.cfg-pattern-card)
       already carry a count badge + ×, so they get the ring/bg only; the standalone swatch
       cards also get a ✓ corner mark. */
    .edge-swatch.active, .foil-swatch.active, .foil-type.active,
    .cfg-color-card.selected, .cfg-pattern-card.selected {
      border-color: var(--blue) !important;
      background: linear-gradient(180deg,#E7F8FF,#FFFFFF) !important;
      box-shadow: inset 0 0 0 2px var(--blue), 0 8px 20px rgba(0,194,255,.18) !important;
    }
    .edge-swatch, .foil-type { position: relative; }
    .edge-swatch.active::after, .foil-type.active::after {
      content: "✓"; position: absolute; top: 6px; right: 7px;
      width: 18px; height: 18px; border-radius: 50%;
      background: var(--blue); color: #fff; font-size: 11px; font-weight: 800; line-height: 18px; text-align: center;
    }
    /* the FOCUSED panel card (the one whose patterns/placements are open) keeps an extra
       outer glow on top of the selected inner ring, so it stays distinct from siblings. */
    .cfg-color-card.focused, .cfg-pattern-card.focused {
      box-shadow: inset 0 0 0 2px var(--blue), 0 0 0 3px rgba(0,194,255,.40), 0 8px 20px rgba(0,194,255,.18) !important;
    }
    .pms-form-row {
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
      gap: 14px;
      align-items: end;
    }
    .pms-field label {
      display: block;
      font-size: 10px;
      font-weight: 900;
      letter-spacing: .12em;
      text-transform: uppercase;
      color: var(--muted);
      margin-bottom: 7px;
    }
    .pms-field select,
    .pms-field input {
      width: 100%;
      padding: 11px 12px;
      border: 1px solid var(--line);
      border-radius: 10px;
      background: #fff;
      font-size: 14px;
      font-weight: 700;
      color: var(--ink);
      font-family: inherit;
    }
    .pms-field select:focus,
    .pms-field input:focus {
      outline: none;
      border-color: var(--blue);
      box-shadow: 0 0 0 3px rgba(0,194,255,.16);
    }
    .finish-card .finish-card-pills {
      display: none;
      grid-column: 1 / -1;
      gap: 6px;
      flex-wrap: wrap;
      margin-top: 8px;
      padding-top: 8px;
      border-top: 1px dashed var(--line);
    }
    .finish-card.configured .finish-card-pills { display: flex; }
    .pill {
      display: inline-flex;
      align-items: center;
      padding: 4px 10px;
      border-radius: 99px;
      font-size: 11px;
      font-weight: 800;
      letter-spacing: -.01em;
      line-height: 1.2;
    }
    .pill-configured {
      background: var(--blue);
      color: #fff;
    }
    .pill-value {
      background: #F1EDE3;
      color: #5F594C;
      border: 1px solid var(--line);
    }
    .pill-add {
      background: #fff;
      color: var(--blue-dark);
      border: 1px dashed var(--blue);
      cursor: pointer;
      transition: background .2s ease, border-color .2s ease, color .2s ease;
    }
    .pill-add:hover {
      background: #F4FCFF;
      border-style: solid;
      color: var(--blue);
    }
    .setup-status.setup-needed {
      background: #FFF1D8;
      color: #8A6428;
      border: 1px solid rgba(201,169,110,.45);
    }
    .foil-setup-card .setup-subtitle {
      font-size: 12px;
      color: #6B6557;
      margin: 8px 0 4px;
      font-weight: 500;
    }
    .setup-card-footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
      margin-top: 22px;
      padding-top: 18px;
      border-top: 1px dashed var(--line);
    }
    .setup-card-helper {
      font-size: 11px;
      color: #8A8576;
      font-style: italic;
      flex: 1;
      line-height: 1.4;
    }
    .setup-card-actions {
      display: flex;
      gap: 8px;
      /* may shrink (configurator 43, 2026-09-22): the Save label is "Save <admin option name>", and
         "Save Hole Punch / Standard Die Cut (Included)" (hang tags) measured 303px on one line —
         with flex-shrink:0 it pushed Remove 58px out past the card's left edge on a 387px rail.
         Now the label wraps onto two lines instead. Short labels are unaffected. */
      flex-shrink: 1;
      min-width: 0;
      align-items: center;   /* a one-line Remove keeps its own height beside a two-line Save */
    }
    .setup-card-actions .btn-save { min-width: 0; }
    .btn-remove {
      padding: 10px 16px;
      border: 1px solid var(--line);
      background: #fff;
      color: var(--ink);
      border-radius: 999px;
      font-size: 12px;
      font-weight: 800;
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease;
    }
    .btn-remove:hover {
      border-color: #C9C4BA;
      background: #FAF7F0;
    }
    .btn-save {
      padding: 10px 18px;
      border: 1px solid var(--blue);
      background: var(--blue);
      color: #fff;
      border-radius: 999px;
      font-size: 12px;
      font-weight: 900;
      cursor: pointer;
      transition: background .2s ease, border-color .2s ease, opacity .2s ease;
    }
    .btn-save:hover:not(:disabled) {
      background: var(--blue-dark);
      border-color: var(--blue-dark);
    }
    .btn-save:disabled {
      opacity: .45;
      cursor: not-allowed;
    }
    /* force-hide the raw engine selects that the edge pills/swatches drive — the
       engine re-shows the dependent code select on method change, so !important
       (beats inline style) is required. The value still submits to the cart. */
    select.cfg-edge-rawhide { display: none !important; }
    .edge-method-row {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }
    .edge-method {
      padding: 9px 15px;
      border: 1px solid var(--line);
      background: #fff;
      border-radius: 999px;
      font-size: 12px;
      font-weight: 800;
      color: var(--ink);
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease, color .2s ease;
    }
    .edge-method:hover {
      border-color: var(--blue);
      background: #F4FCFF;
    }
    .edge-method.active {
      background: var(--blue);
      border-color: var(--blue);
      color: #fff;
    }
    .edge-palette-wrap { margin-top: 14px; }
    .edge-palette {
      display: none;
      grid-template-columns: repeat(6, 1fr);
      gap: 10px;
    }
    .edge-palette.active { display: grid; }
    .edge-palette-empty {
      font-size: 12px;
      color: var(--muted);
      font-style: italic;
      padding: 14px 4px 4px;
    }
    .edge-swatch {
      background: #fff;
      border: 1px solid #DDD8CE;
      border-radius: 12px;
      padding: 10px 6px 8px;
      text-align: center;
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease, transform .2s ease;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 6px;
    }
    .edge-swatch:hover {
      transform: translateY(-1px);
      border-color: var(--blue);
      background: #F4FCFF;
    }
    .edge-swatch.active {
      border-color: var(--blue);
      background: #F4FCFF;
    }
    .edge-swatch-color {
      width: 32px;
      height: 32px;
      border-radius: 50%;
      border: 1px solid rgba(0,0,0,.1);
    }
    .edge-swatch strong {
      font-size: 10px;
      font-weight: 700;
      line-height: 1.25;
      color: var(--ink);
    }
    /* .signature-finish-stack.has-content retired in v1.32 */
    .signature-finish-card {
      display: none;
      grid-column: 1 / -1;
      margin: 6px 0 4px;
      position: relative;
      scroll-margin-top: 140px;
    }
    .signature-finish-card.active {
      display: block;
      animation: foilGroupReveal .28s ease both;
    }
    .signature-finish-card.active::before {
      content: "";
      position: absolute;
      top: -8px;
      left: 28px;
      width: 16px;
      height: 16px;
      border-left: 1px solid rgba(0,194,255,.36);
      border-top: 1px solid rgba(0,194,255,.36);
      background: #fff;
      transform: rotate(45deg);
      z-index: 1;
    }
    .signature-finish-card .foil-setup-card {
      border: 1px solid rgba(0,194,255,.36);
      background: linear-gradient(180deg, #FFFFFF 0%, #F8FDFF 100%);
      box-shadow: 0 16px 38px rgba(0,194,255,.09);
      position: relative;
      z-index: 0;
    }
    .scope-grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 12px;
    }
    .radius-grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));   /* minmax(0,…): a track may shrink below its content, so 3-up never overflows a narrow rail (owner-caught 2026-09-01: the 9mm card ran off the panel) */
      gap: 12px;
    }
    /* the card's picture scales with its track instead of pinning it at 110px — the SVGs carry a viewBox */
    .radius-grid .config-option,
    .scope-grid .config-option { min-width: 0; }
    .radius-grid .config-option-diagram,
    .radius-grid .placement-diagram { width: 100%; max-width: 110px; height: auto; aspect-ratio: 110 / 52; }
    .radius-grid .config-option { padding-left: 8px; padding-right: 8px; }
    .config-option {
      position: relative;
      border: 1px solid #DDD8CE;
      background: #fff;
      border-radius: 14px;
      padding: 18px 14px 16px;
      cursor: pointer;
      text-align: center;
      transition: border-color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 10px;
    }
    .config-option:hover {
      transform: translateY(-1px);
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .config-option.active {
      border-color: var(--blue);
      background: #F4FCFF;
    }
    .config-option-diagram {
      display: block;
      width: 110px;
      height: 48px;
      filter: drop-shadow(0 2px 4px rgba(30,24,12,.10));
    }
    .config-option-diagram .corner-shape {
      fill: #FFFAEB;
      stroke: #1A1A1A;
      stroke-width: 0.6;
      transition: fill .25s ease, stroke .25s ease;
    }
    .config-option.active .config-option-diagram .corner-shape {
      fill: #F4FCFF;
      stroke: var(--blue-dark);
      stroke-width: 0.9;
    }
    .config-option-check {
      display: block;
      width: 22px;
      height: 22px;
      border: 1.5px solid #BFB8AC;
      border-radius: 5px;
      background: #fff;
      position: relative;
    }
    .config-option.active .config-option-check {
      background: var(--blue);
      border-color: var(--blue);
    }
    .config-option.active .config-option-check::after {
      content: "✓";
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #fff;
      font-weight: 900;
      font-size: 14px;
      line-height: 1;
    }
    .config-option-label {
      font-size: 14px;
      font-weight: 800;
      color: var(--ink);
      letter-spacing: -.01em;
      margin: 0;
      line-height: 1.2;
    }
    .config-option-micro {
      display: block;
      font-size: 11px;
      line-height: 1.4;
      color: #7B7466;
      font-style: italic;
      margin-top: -2px;
      padding: 0 4px;
    }
    .add-foil-pill-wrap {
      display: none;
      justify-content: center;
      margin-top: 22px;
      padding-top: 18px;
      border-top: 1px dashed var(--line);
    }
    .add-foil-pill-wrap.ready {
      display: flex;
      animation: foilPillAppear .45s ease;
    }
    @keyframes foilPillAppear {
      from { opacity: 0; transform: translateY(8px); }
      to { opacity: 1; transform: translateY(0); }
    }
    .foil-group.collapsed,
    .foil-group:not(.pending) {
      animation: foilGroupReveal .3s ease;
    }
    @keyframes foilGroupReveal {
      from { opacity: 0; transform: translateY(6px); }
      to { opacity: 1; transform: translateY(0); }
    }
    .add-foil-pill {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      padding: 11px 20px;
      border: 1.5px dashed var(--blue);
      background: #fff;
      border-radius: 999px;
      color: var(--blue-dark);
      font-size: 13px;
      font-weight: 900;
      letter-spacing: -.01em;
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease;
    }
    .add-foil-pill:hover {
      border-color: var(--blue);
      background: #F4FCFF;
      transform: translateY(-1px);
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .add-foil-pill .pill-plus {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 20px;
      height: 20px;
      border-radius: 50%;
      background: var(--blue);
      color: #fff;
      font-size: 14px;
      font-weight: 900;
      line-height: 1;
    }
    .copper { background: #D88942; }
    .red { background: #F20B0B; }
    .pink { background: #F08BB2; }
    .teal { background: #008C89; }
    .purple { background: #7D3FA0; }
    .green { background: #079849; }
    .other { background: #fff; }

    .finish-row {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 12px;
    }
    .finish-services-group {
      margin-top: 26px;
      padding-top: 22px;
      border-top: 1px solid var(--line);
    }
    .finish-services-group .mini-label {
      margin-bottom: 12px;
    }
    .finish-card {
      background: #fff;
      border: 1px solid #DDD8CE;
      border-radius: 18px;
      padding: 18px;
      display: grid;
      grid-template-columns: 46px 1fr auto;
      gap: 14px;
      align-items: center;
      cursor: pointer;
      transition: all .2s ease;
    }
    .finish-card:hover {
      transform: translateY(-1px);
      border-color: var(--blue);
      background: #F4FCFF;
      box-shadow: 0 10px 22px rgba(0,194,255,.10);
    }
    .finish-card.active { border-color: var(--blue); background: #F4FCFF; }
    .finish-icon {
      width: 46px;
      height: 46px;
      border-radius: 14px;
      background: var(--gold-soft);
      border: 1px solid rgba(201,169,110,.24);
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: 900;
      font-size: 13px;
      letter-spacing: -.01em;
      color: var(--gold);
      flex: 0 0 auto;
    }
    .finish-copy strong { display: block; font-size: 14px; margin-bottom: 3px; }
    .finish-copy span { color: var(--muted); font-size: 12px; line-height: 1.4; }
    .toggle {
      width: 22px;
      height: 22px;
      border-radius: 6px;
      border: 1px solid #CFC9BE;
      background: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: 900;
      font-size: 12px;
      color: transparent;
    }
    .finish-card.active .toggle { background: var(--blue); border-color: var(--blue); color: #071015; }

    .color-pills {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
    }
    .color-pill {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      background: #fff;
      border: 1px solid #DDD8CE;
      padding: 10px 14px;
      border-radius: 999px;
      font-size: 13px;
      font-weight: 900;
      cursor: pointer;
    }
    .color-pill.active { border-color: var(--blue); background: #F4FCFF; }
    .swatch {
      width: 17px;
      height: 17px;
      border-radius: 50%;
      border: 1px solid rgba(0,0,0,.12);
      display: inline-block;
    }
    .gold { background: linear-gradient(135deg, #936D2D, #FFF0B4, #B98C45); }
    .silver { background: linear-gradient(135deg, #8D9399, #FFFFFF, #A7ADB3); }
    .rose { background: linear-gradient(135deg, #B47665, #FFE0D8, #C98A78); }
    .black { background: #111; }
    .blue { background: #0D3B72; }

    .order-fields {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 12px;
    }
    .order-field-card {
      background: #fff;
      border: 1px solid #DDD8CE;
      border-radius: 18px;
      padding: 18px;
      display: grid;
      grid-template-columns: 1fr 190px;
      align-items: center;
      gap: 18px;
      box-shadow: 0 10px 24px rgba(22,18,11,.04);
    }
    .order-field-card label {
      color: var(--ink);
      font-size: 15px;
      font-weight: 900;
      letter-spacing: -.01em;
    }
    .order-field-card select {
      height: 46px;
      border: 1px solid #DDD8CE;
      border-radius: 12px;
      background: #fff;
      padding: 0 14px;
      font-weight: 900;
      color: var(--ink);
      cursor: pointer;
    }

    .artwork-path {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 12px;
    }
    .path-card {
      background: #fff;
      border: 1px solid #DDD8CE;
      border-radius: 18px;
      padding: 20px;
      min-height: 150px;
      cursor: pointer;
      transition: all .2s ease;
    }
    .path-card:hover { border-color: rgba(0,194,255,.55); box-shadow: 0 12px 26px rgba(0,194,255,.08); }
    .path-card.recommended { border-color: rgba(201,169,110,.45); background: linear-gradient(180deg, #FFFDF8, #FFFFFF); }
    .path-icon {
      width: 42px;
      height: 42px;
      border-radius: 14px;
      background: var(--ivory);
      border: 1px solid var(--line);
      display: flex;
      align-items: center;
      justify-content: center;
      margin-bottom: 14px;
      color: var(--gold);
      font-weight: 900;
    }
    .path-card strong { display: block; font-size: 15px; line-height: 1.25; margin-bottom: 7px; }
    .path-card span { color: var(--muted); font-size: 12px; line-height: 1.5; }

    /* ---- Backside Print branded card grid (configurator skin) ---- */
    .cfg-print-grid {
      display: grid;
      /* minmax(0,…) — the GOTCHAS #377 fix, applied to its sibling (configurator 43, 2026-09-22):
         plain 1fr will not shrink below a card's 76px swatch + padding (102px), so at a 1181–~1300px
         desktop the 387px rail ran the third Backside Print card 17px past its grid, on every product */
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 12px;
    }
    .cfg-print-grid .config-option { min-width: 0; }
    /* the generic sub-choice card skin (configure.php, 2026-09-01) hides the engine's raw
       radio list by CLASS so the build summary can still read the checked radio — it skips
       inline-hidden inputs on purpose. Keep this a class rule, never an inline style. */
    .cfg-sub-hidden { display: none !important; }
    /* the two-menu card skin (configure.php, 2026-09-29): a heading's cards, then the next
       group — groups sit one grid gap apart (they measured 0px), a following heading gets more
       space above it than below */
    .cfg-pair-cards .cfg-sub-grid + .cfg-sub-grid { margin-top: 12px; }
    .cfg-pair-cards .cfg-sub-grid + .sub-header { margin-top: 20px; }
    .cfg-pair-cards + .optioninput { margin-top: 12px; }
    /* the engine's own free-text box for an "other" choice (Premium Die Cut) — the values of
       .cfg-freetext-input, so it reads like the edge and stock pickers' custom field */
    .cfg-pair-cards + .optioninput input.optionselect { width: 100%; max-width: none; box-sizing: border-box; padding: 11px 12px; border: 1px solid var(--line, #E4E7EB); border-radius: 10px; background: #fff; font-size: 14px; font-weight: 700; color: var(--ink, #11151A); font-family: inherit; }
    .cfg-pair-cards + .optioninput input.optionselect:focus { outline: none; border-color: var(--blue, #00C2FF); box-shadow: 0 0 0 3px rgba(0,194,255,.16); }
    .cfg-print-card { padding: 16px 12px 14px; }
    .cfg-print-swatch {
      display: block;
      width: 100%;                 /* scales with its track (#377) — 76px at full width, as before */
      max-width: 76px;
      height: 44px;
      border-radius: 9px;
      border: 1px solid rgba(16,16,16,.14);
      box-shadow: 0 2px 5px rgba(30,24,12,.10);
    }
    .cfg-print-card.active .cfg-print-swatch { box-shadow: 0 4px 10px rgba(0,194,255,.18); }
    .cfg-print-blank { background: #fff; border: 1px dashed #C4BDB0; box-shadow: none; }
    /* ONE SHARED CHOICE CARD (configure.php, 2026-09-01): the pictures the family recipe can
       put on a .config-option — the die-cut icon (sized only inside the die-cut wizard's own
       swatch grid before), the plies / card outline (whose fills lived under .placement). */
    .config-option .cfg-dc-icon { display: block; width: 64px; height: 40px; filter: drop-shadow(0 2px 4px rgba(30,24,12,.10)); }
    .config-option .placement-diagram { width: 104px; height: 46px; }
    .config-option .placement-diagram .cfg-ply { fill: #FFFAEB; transition: fill .25s ease; }
    .config-option .placement-diagram .cfg-ply-front { fill: #F5EFE2; transition: fill .25s ease; }
    .config-option .placement-diagram .cfg-ply.cfg-on { fill: #6FDDFF; }         /* blue, picked or not (owner 2026-10-01) */
    .config-option .placement-diagram .cfg-ply-front.cfg-on { fill: #3FC6F0; }

    /* ---- Design / ArtWork path cards (2-up) + "I Need A Design" intake ---- */
    .cfg-design-grid { grid-template-columns: repeat(2, 1fr); }
    .cfg-design-card { display: flex; flex-direction: column; align-items: flex-start; text-align: left; }
    .cfg-design-card.active { border-color: var(--blue); background: #F4FCFF; }
    .cfg-design-fee { color: var(--blue-dark); font-weight: 800; margin-left: 4px; }

    /* the engine's intake <dl> (project / contact / specifics + file boxes) */
    .cfg-design-dd:not(.cfg-need-design) .cfg-hicd { display: none; }
    /* the prompts are an inner accordion (collapsed by the engine) — force every
       field open when "I Need A Design" is active, so all prompts show at once. */
    .cfg-design-dd.cfg-need-design .cfg-hicd dd { display: block !important; }
    .cfg-hicd { margin: 18px 0 0; }
    .cfg-hicd dt {
      font-size: 13px;
      font-weight: 700;
      color: var(--ink);
      margin: 16px 0 7px;
      letter-spacing: -.01em;
    }
    .cfg-hicd dt b { display: none; }
    .cfg-hicd dd { margin: 0; }
    .cfg-hicd textarea.autogrow-500 {
      width: 100%;
      border: 1px solid #DDD8CE;
      border-radius: 12px;
      padding: 12px 14px;
      font: inherit;
      font-size: 14px;
      color: var(--ink);
      background: #fff;
      resize: vertical;
      transition: border-color .2s ease, box-shadow .2s ease;
    }
    .cfg-hicd textarea.autogrow-500:focus {
      outline: none;
      border-color: var(--blue);
      box-shadow: 0 0 0 3px rgba(0,194,255,.12);
    }
    .cfg-hicd .cart_filebox {
      border: 1px dashed #C4BDB0;
      border-radius: 12px;
      padding: 18px;
      text-align: center;
      color: var(--muted);
      background: #FCFBF8;
      position: relative;
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease;
    }
    .cfg-hicd .cart_filebox:hover { border-color: var(--blue); background: #F4FCFF; }
    .cfg-hicd .cart_filebox input.AttachFiles {
      position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer;
    }
    .cfg-hicd .cart_filebox .fa-plus { color: var(--gold); font-size: 18px; }

    /* THE ENGINE'S INTAKE BLOCKS, WHEREVER THEY ARE DRAWN (2026-09-29, owner-caught on eXp
       Luxury's "Select a Template"). The engine emits two of them as .expand_option > dl —
       the design questions (inc/page/hicd-option.php) and the template details
       (inc/page/template-option.php) — and shows the right one itself. The rules above are
       keyed to the ArtWork panel's own class, so the same blocks inside any OTHER option drew
       as bare headings: each <dd> is an inner accordion the old page opened and this one
       never did. Same values as .cfg-hicd; keyed to the engine's container, so a product
       that draws these blocks needs no entry anywhere.
       !important where the engine writes the value inline (dl margin-top, input width). */
    .expand_option > dl { margin: 18px 0 0 !important; }
    .expand_option > dl > dt {
      font-size: 13px;
      font-weight: 700;
      color: var(--ink);
      margin: 16px 0 7px;
      letter-spacing: -.01em;
    }
    .expand_option > dl > dt:first-child { margin-top: 0; }
    .expand_option > dl > dt b { display: none; }
    .expand_option > dl > dd { display: block !important; margin: 0; }
    .expand_option textarea.autogrow-500,
    .expand_option input[type="text"] {
      display: block;
      width: 100% !important;
      border: 1px solid #DDD8CE;
      border-radius: 12px;
      padding: 12px 14px;
      font: inherit;
      font-size: 14px;
      color: var(--ink);
      background: #fff;
      transition: border-color .2s ease, box-shadow .2s ease;
    }
    .expand_option textarea.autogrow-500 { resize: vertical; }
    .expand_option input[type="text"] + input[type="text"] { margin-top: 8px; }
    .expand_option textarea.autogrow-500:focus,
    .expand_option input[type="text"]:focus {
      outline: none;
      border-color: var(--blue);
      box-shadow: 0 0 0 3px rgba(0,194,255,.12);
    }
    .expand_option .cart_filebox {
      border: 1px dashed #C4BDB0;
      border-radius: 12px;
      padding: 18px;
      text-align: center;
      color: var(--muted);
      background: #FCFBF8;
      position: relative;
      cursor: pointer;
      transition: border-color .2s ease, background .2s ease;
    }
    .expand_option .cart_filebox:hover { border-color: var(--blue); background: #F4FCFF; }
    .expand_option .cart_filebox input.AttachFiles {
      position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer;
    }
    .expand_option .cart_filebox .fa-plus { color: var(--gold); font-size: 18px; }
    .expand_option .filelist { margin-left: 0 !important; }

    /* Two menus of one choice (version, then template; colour family, then colour) sat at
       0px — the second began where the first ended. One gap, in the shared component. */
    .cfg-dd + .cfg-dd { margin-top: 10px; }

    .review-bar {
      padding: 24px 32px;
      background: linear-gradient(135deg, #101010, #27231C);
      color: #fff;
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 20px;
      align-items: center;
    }
    .review-bar h3 { font-size: 22px; line-height: 1.1; letter-spacing: -.035em; margin-bottom: 6px; }
    .review-bar p { color: rgba(255,255,255,.64); font-size: 13px; }
    .review-actions { display: flex; gap: 10px; align-items: center; }

    .note-strip {
      max-width: 1280px;
      margin: 0 auto;
      padding: 0 28px 70px;
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 14px;
    }
    .note {
      background: rgba(255,255,255,.76);
      border: 1px solid var(--line);
      border-radius: 20px;
      padding: 20px;
      box-shadow: 0 10px 24px rgba(22,18,11,.04);
    }
    .note strong { display: block; margin-bottom: 6px; font-size: 14px; }
    .note span { color: var(--muted); font-size: 12px; line-height: 1.55; }

    @media (max-width: 1080px) {
      .workspace { grid-template-columns: 1fr; }
      .preview-panel { position: relative; top: 0; }
      .tool-title-inner { grid-template-columns: 1fr; }
      /* .nav-links mobile drawer is owned by henry_common.css (hamburger) — do NOT hide it here (nav-overhaul fix) */
      .card-type-grid { grid-template-columns: repeat(2, 1fr); }
    }
    @media (max-width: 760px) {
      .nav-inner, .tool-title-bar, .workspace, .note-strip { padding-left: 18px; padding-right: 18px; }
      .step, .review-bar, .build-context { padding: 22px; }
      .builder-head { padding: 14px 16px; }
      .choice-grid, .choice-grid.two, .card-type-grid, .finish-row, .note-strip, .foil-swatch-grid, .foil-type-grid, .foil-placement-grid, .size-grid, .custom-size-row, .order-fields, .order-field-card { grid-template-columns: 1fr; }
      .custom-size-inline { align-items: stretch; }
      .review-bar { grid-template-columns: 1fr; }
      .builder-head { grid-template-columns: 1fr; gap: 12px; }
      .builder-head-info { grid-template-columns: 1fr; gap: 10px; }
      .helper-pill { justify-self: start; }
      .build-context-inner { grid-template-columns: 1fr; align-items: start; }
      .build-context-change { justify-self: start; }
      .progress { width: 100%; }
      .preview-stage { min-height: 390px; }
      .nav-icons { display: none; }
    }

    /* ===================================================================
       PHASE C — Engine integration skin
       Styles the legacy #shoppingform / #widgetcontainer output when
       rendered inside the .cfg-step shells. Deliberately minimal for the
       C0 spike — Half 2 adds full visual treatment.
       =================================================================== */

    /* Hide the engine source container (nodes are moved out by JS). */
    #cfg-engine-source { display: none; }

    /* Step shells: each .cfg-step is a .step card that receives engine nodes. */
    .cfg-step { margin-bottom: 16px; }

    /* The engine wraps everything in #widgetcontainer. Strip its legacy chrome
       when inside a cfg-step so it doesn't double-card. */
    .cfg-step #widgetcontainer { margin: 0; padding: 0; background: transparent; box-shadow: none; border: none; }
    .cfg-step .features-addons--wrapper { background: transparent; border: none; }
    .cfg-step .form-wrapper { padding: 0; }
    .cfg-step .tabs-content { margin: 0; padding: 0; }
    .cfg-step .tabs-content > li.active { display: block; padding: 0; }

    /* Accordion rows — inherit the step card's padding. */
    .cfg-step .accordion.base_accordion,
    .cfg-step .accordion { border: none; background: transparent; }
    .cfg-step .accordion dt { border-bottom: 1px solid var(--line, #E8E4DA); }
    .cfg-step .accordion dt.active { cursor: pointer; }
    .cfg-step .accordion dd { padding: 12px 0; }

    /* Price + Add-to-Cart block — let it sit naturally at bottom of step 3 or
       wherever product-form.php places it (inside step1 because the whole form
       lives there; CSS half 2 will reposition). */
    .cfg-step .form-summary { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line, #E8E4DA); }
    .cfg-step .form-button .action_button {
      background: var(--ink, #101010);
      color: #fff;
      border: none;
      border-radius: 12px;
      padding: 14px 28px;
      font-size: 15px;
      font-weight: 700;
      cursor: pointer;
      transition: background .2s;
      width: 100%;
    }
    .cfg-step .form-button .action_button:hover { background: #2A2A2A; }

    /* Accordion title labels from $accordion_titles */
    .cfg-accordion-title { font-size: 13px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted, #888); margin: 0 0 10px; }

    /* ── Foil progressive wizard (hero "Build your foil setup", owner 2026-06-08) ── */
    /* Hero foil has no on/off toggle row — the step IS the foil build; panel always open. */
    #cfg-step-hero dt[id^="option_title_"] { display: none; }
    #cfg-step-hero dd[id^="option_content_"] { display: block !important; }

    .cfg-foil-setup + .cfg-foil-setup { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 18px; }
    .cfg-foil-setup-head { display: flex; align-items: center; gap: 12px; margin: 2px 0 16px; }
    .cfg-fs-eyebrow { font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
    .cfg-fs-title { font-size: 20px; font-weight: 800; color: var(--ink); margin-right: auto; }
    .cfg-fs-badge { font-size: 12px; font-weight: 700; color: #8a6d1f; background: #f6edd4; border-radius: 999px; padding: 4px 12px; }
    .cfg-fs-remove { font-size: 13px; color: #c0392b; text-decoration: underline; }

    /* saved "COLOR: Gold [change]" rows */
    .cfg-foil-saved { display: flex; align-items: center; gap: 12px; border: 1px solid var(--line); border-radius: 12px; padding: 14px 18px; margin: 0 0 12px; background: #fcfbf8; }
    .cfg-fs-label { font-size: 12px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); min-width: 84px; }
    .cfg-fs-value { font-size: 17px; font-weight: 800; color: var(--ink); display: flex; align-items: center; gap: 8px; }
    .cfg-fs-swatch { width: 20px; height: 20px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); }
    /* branded change/remove links — match .foil-change-btn (v1.45 master) */
    .cfg-fs-change, .cfg-fs-remove { margin-left: auto; font-size: 12px; font-weight: 900; letter-spacing: -.01em; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
    .cfg-fs-change { color: var(--blue-dark); }
    .cfg-fs-change:hover { color: var(--blue); }
    .cfg-fs-remove { color: var(--muted); }
    .cfg-fs-remove:hover { color: #c0392b; }

    /* ── Step redundant-label cleanup (owner 2026-06-08) ── */
    /* Size step already has the step title "Size" — drop the engine's duplicate dt label. */
    #cfg-step-4 dt#option_title_size { display: none; }
    /* Quantity step: drop the orphaned engine group labels ("Cards per set" /
       "Number of sets/names") that rendered as a stray line under the cards. */
    #cfg-step-3 .option_group { display: none; }
    /* Step 1 is already titled "Stock & Thickness" + "Choose your stock" — drop the
       engine's duplicate "Paper Stock" dt label (owner 2026-06-09). */
    #cfg-step-1 dt#option_title_paper { display: none; }

    /* ── Branded option checkboxes (owner 2026-06-09 — native boxes looked unbranded) ──
       The engine renders each finish toggle as label.check-container > input + span.checkmark.
       No legacy .checkmark CSS loads on this v2 page, so the raw native checkbox showed.
       Brand it to match .placement-check (22px, rounded, --blue when checked, white ✓). */
    #shoppingform .check-container { position: relative; display: inline-block; width: 22px; height: 22px; cursor: pointer; flex: 0 0 auto; }
    #shoppingform .check-container input[type=checkbox] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; margin: 0; cursor: pointer; }
    #shoppingform .check-container .checkmark {
      position: absolute; inset: 0;
      background: #fff;
      border: 1.5px solid #BFB8AC;
      border-radius: 5px;
      transition: background .2s ease, border-color .2s ease;
      pointer-events: none;
    }
    #shoppingform .check-container input:checked + .checkmark { background: var(--blue); border-color: var(--blue); }
    #shoppingform .check-container input:checked + .checkmark::after {
      content: "✓";
      position: absolute; inset: 0;
      display: flex; align-items: center; justify-content: center;
      color: #fff; font-weight: 900; font-size: 14px; line-height: 1;
    }

    /* ── Branded dropdowns (owner 2026-06-08 — native selects looked unbranded) ── */
    .cfg-step select {
      appearance: none; -webkit-appearance: none; -moz-appearance: none;
      font: inherit; font-weight: 700; font-size: 15px; color: var(--ink);
      background-color: #fff;
      background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' stroke='%23232323' stroke-width='1.8' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
      background-repeat: no-repeat; background-position: right 14px center; background-size: 12px 8px;
      border: 1px solid var(--line); border-radius: 10px;
      padding: 12px 40px 12px 16px; cursor: pointer; min-width: 130px;
      transition: border-color .15s ease, box-shadow .15s ease;
    }
    .cfg-step select:hover { border-color: var(--gold); }
    .cfg-step select:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(0,194,255,.16); }

    /* ── Branded custom dropdown (desktop; mobile keeps native) ── */
    .cfg-dd { position: relative; min-width: 150px; }
    select.cfg-dd-native { display: none !important; } /* native hidden where the custom dd exists */
    .cfg-dd-btn { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%;
      font: inherit; font-weight: 700; font-size: 15px; color: var(--ink); background: #fff;
      border: 1px solid var(--line); border-radius: 10px; padding: 12px 16px; cursor: pointer;
      transition: border-color .15s ease, box-shadow .15s ease; }
    .cfg-dd-btn:hover { border-color: var(--gold); }
    .cfg-dd.open .cfg-dd-btn { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(0,194,255,.16); }
    .cfg-dd-caret { width: 12px; height: 8px; flex: 0 0 auto; background-repeat: no-repeat; background-position: center; background-size: contain; transition: transform .15s ease; }
    .cfg-dd.open .cfg-dd-caret { transform: rotate(180deg); }
    /* max-height was 280px while the Quantity list needs 374px, so its last two rows —
       "5,000 pcs" and "Other Quantity", the ONLY way to reach a custom amount — sat
       below the edge with no scroll cue, and the list read as 250-4,000 and nothing
       more (owner-reported 2026-09-02; measured scrollHeight 374 / clientHeight 278).
       420px clears every list on the business-card builder. Longer lists still scroll,
       so the bottom fade below is the standing cue that more rows exist: it is painted
       by a `local` background layer, which the browser scrolls WITH the content, so it
       disappears on its own at the end of the list and needs no JS. */
    .cfg-dd-list { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 40;
      background: #fff; border: 1px solid var(--line); border-radius: 12px;
      box-shadow: 0 14px 32px rgba(22,18,11,.16); padding: 6px; max-height: 420px; overflow: auto;
      background-image: linear-gradient(#fff, #fff), linear-gradient(to top, rgba(22,18,11,.13), rgba(22,18,11,0));
      background-position: bottom center, bottom center;
      background-size: 100% 6px, 100% 22px;
      background-repeat: no-repeat;
      background-attachment: local, scroll;
      scrollbar-color: #C9C3B7 #F3F0E9; }
    /* Opened upward when the rail leaves more room above the button than below it
       (set by fit() in configure.php) — see the note above. */
    .cfg-dd-list.up { top: auto; bottom: calc(100% + 6px); }
    /* Applied by fit() ONLY to a list that would otherwise not fit its side of the rail
       — every list that already fits keeps the full row height. Brings the 8-row
       Quantity list from 374px to ~260px so all of it, "Other Quantity" included, is on
       screen without a scroll. */
    .cfg-dd-list.compact .cfg-dd-opt { padding: 7px 14px; font-size: 14px; }
    /* NOTE on the `scrollbar-color` above — it is doing the load-bearing work here, and
       it is deliberately NOT paired with `scrollbar-width: thin`. Setting any
       scrollbar-* standard property makes Chrome ignore ::-webkit-scrollbar rules, and
       `thin` measured at 2px of track — present, unnoticeable. Colour alone gives a
       full-width, ALWAYS-VISIBLE bar instead of the macOS overlay one that only appears
       after you have already scrolled. That overlay is the real reason "Other Quantity"
       read as absent: at a 900px window neither side of the button fits all 8 rows
       (measured: 374px needed, 316px above / 231px below), so the list must scroll, and
       a scroll nobody can see is the same as a missing option. */
    .cfg-dd-opt { padding: 11px 14px; border-radius: 8px; font-weight: 600; font-size: 15px; color: var(--ink); cursor: pointer; }
    .cfg-dd-opt:hover { background: #f4f1ea; }
    .cfg-dd-opt.sel { background: rgba(0,194,255,.10); font-weight: 800; color: var(--blue-dark); }

    /* Custom Size — branded WIDTH × HEIGHT dashed box (v1.45 original) */
    /* 3x2 grid: WIDTH / (gap) / HEIGHT on row 1, input / × / input on row 2. The ×
       is a cell on the input row, so it centres on the inputs with no magic padding.
       Sized to what it holds (two short dimension fields) rather than filling the
       rail — the 560px version read as a large empty box (owner, 2026-09-02). */
    .cfg-custom-size { display: none; grid-template-columns: minmax(0,1fr) auto minmax(0,1fr); column-gap: 12px; row-gap: 6px; align-items: center; margin-top: 14px; padding: 16px 18px; border: 2px dashed var(--line); border-radius: 14px; max-width: 380px; }
    .cfg-cs-label { font-size: 11px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
    .cfg-custom-size input { font: inherit; font-weight: 700; font-size: 16px; color: var(--ink); background: #fff; border: 1px solid var(--line); border-radius: 10px; padding: 11px 13px; width: 100%; min-width: 0; }
    .cfg-custom-size input:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(0,194,255,.16); }
    .cfg-cs-x { font-size: 18px; font-weight: 700; color: var(--muted); text-align: center; }
    /* Inside the size grid it fills the cells left empty beside the Custom Size card
       instead of opening a new full-width row (owner-directed 2026-09-02). The grid's
       own gap provides the spacing, and it stretches to the card's height so the row
       reads as one block. `span 2` re-flows on its own at the 2- and 1-column
       breakpoints, so nothing needs a per-breakpoint override. */
    .size-grid > .cfg-custom-size { grid-column: span 2; max-width: none; margin-top: 0; align-self: stretch; align-content: center; }

    /* "Add another foil color" */
    .cfg-foil-add { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; margin-top: 14px; padding: 14px; border: 2px dashed #9ecbf2; border-radius: 999px; background: transparent; color: #2575d6; font-size: 16px; font-weight: 800; cursor: pointer; }
    .cfg-foil-add:hover { background: #f3f9ff; }
    .cfg-add-plus { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; background: #2575d6; color: #fff; font-weight: 800; }

    /* =====================================================================
       v1.84 LAYOUT SHELL (R1) — Master configurator reskin
       ---------------------------------------------------------------------
       Ported from the committed mockup
         docs/henry_updates/to-build/.../Main Builder/silkcards_master_configurator_MAIN.html
       override <style> blocks:
         v1.63 watch-strap UX  (:root tokens · 70/30 workspace · sticky photo
                                 stage · Manrope typography (was Manrope body /
                                 Montserrat headings until 2026-08-14) · step
                                 + finish/foil restyles)
         v1.67 section-launcher rail  (.main-builder-rail / .main-builder-option
                                 / .required-star / .mini-card* / rating badge)
         v1.80 required-star 2x
         v1.81 YOUR BUILD bottom bar  (.build-bar / .bb-*)
         v1.82 preview-center
       Layered AFTER the v1.45 base above — later-in-file wins the cascade,
       the mockup's own base+override pattern.

       ADAPTATIONS (faithful, not improvised):
        • the mockup's standalone nav is 73px; OUR chrome is header-v2 .site-nav
          (~92px, the proven v1.45 offset above) → sticky offsets use 92px.
        • shared-chrome recolors (.nav/.brand/.nav-links/.topbar) are NOT ported
          — this sheet is page-scoped and must never restyle global chrome.

       R1 = SHELL ONLY. Deliberately NOT ported here:
        • v1.83 slide-up Build Drawer + boxed receipt        → R4
        • per-view selector detail pages                     → R3
        • the rail↔engine-panel RE-HOUSING + Signature-      → R2
          Finishes membership (kept as a static skeleton here)
        • v1.67 `.builder > .step { display:none }` — that would hide the
          working engine wizards; OMITTED so every existing panel keeps
          functioning underneath (the R1 contract).
        • v1.81 `.preview-summary { display:none }` — the v1.45 sticky summary
          SIDEBAR STAYS this slice (retirement is R4); it re-homes to a glass
          card and renders alongside the new bottom bar.
       ===================================================================== */

    /* --- v1.63 :root — body + heading font + rail tokens ---
       v1.63 shipped Manrope BODY / Montserrat HEADINGS, and this page was the only
       surface on the site already running Manrope. On 2026-08-14 Manrope became the
       site-wide face (owner, answering H-09: "manrope replaces montserrat everywhere"),
       so --heading-font moved to Manrope too and the split is gone. --- */
    :root {
      --font: 'Manrope', Helvetica, Arial, sans-serif;
      --heading-font: 'Manrope', Helvetica, Arial, sans-serif;
      --rail-wash: #F8F9FA;
      --rail-line: #E5E8EC;
      --rail-hover: #EEF2F5;
      --rail-selected: #E7ECEF;
      --studio-black: #050505;
    }
    body { font-family: var(--font); }
    h1, h2, h3, h4,
    .step-title h3, .mini-label, .sub-header-title { font-family: var(--heading-font); }

    /* hide this page's own v1.45 chrome that v1.84 replaces (page-local, NOT shared header-v2) */
    .tool-title-bar,
    .builder-head,
    .note-strip { display: none !important; }

    /* --- 70/30 full-bleed workspace --- */
    .workspace {
      max-width: none;
      width: 100%;
      min-height: calc(100vh - 92px);
      padding: 0;
      gap: 0;
      grid-template-columns: minmax(0, 70vw) minmax(390px, 30vw);
      align-items: stretch;
      background: #fff;
    }

    /* --- black sticky photo stage (left) --- */
    .preview-panel {
      position: sticky;
      top: 92px;
      height: calc(100vh - 92px);
      min-height: 660px;
      max-height: none;                 /* release the v1.45 cap */
      display: flex;
      align-items: center;
      justify-content: center;
      background: var(--studio-black) !important;   /* v1.67 pure-black stage */
      border: 0;
      border-radius: 0;
      box-shadow: none;
      overflow: hidden;
      isolation: isolate;
      padding-bottom: 96px;             /* v1.82 — clear the fixed bottom bar */
    }
    .preview-panel .preview-stage { flex: 0 1 auto; }
    .preview-stage {
      width: min(88%, 1060px);
      min-height: 0 !important;
      padding: 0 !important;
      margin: 0 auto;
      background: transparent !important;
      border: 0 !important;
      box-shadow: none !important;
      border-radius: 0 !important;
      overflow: visible !important;
      color: inherit;
      transform: none !important;       /* v1.82 — drop the translateY nudge */
    }
    .preview-stage::after { display: none !important; }           /* kill the v1.45 glow blob */
    .preview-stage .preview-label,
    .preview-stage .card-scene { display: none !important; }      /* v1.45 mock-card hidden; real photo (R5) lives in .ref-preview-wrap */

    /* real product photo swaps in here at R5 (engine optionimage_* decoration) */
    .ref-preview-wrap { width: 100%; }
    /* R5 round-10 (owner: "empty space between the images and the background"):
       Henry's mockup resolved the seam with edge-FEATHERED image variants (the REF
       map's "-feathered.png" names) that fade into the black stage; those files were
       not in the delivery (only plain masters). Replicate the treatment in CSS —
       object-fit:cover at the mockup's 655/560 stage ratio (kills the letterbox the
       old `contain` produced) + a radial mask feathering the edges to transparent
       so the photo melts into the stage like Henry's feathered PNGs. */
    .ref-preview-wrap img {
      display: block;
      width: 100%;
      max-height: calc(100vh - 300px);
      aspect-ratio: 655 / 560;
      object-fit: cover;
      border-radius: 30px;              /* rounded corners (owner 2026-07-22) */
      box-shadow: none;
      background: transparent;
      -webkit-mask-image: var(--stage-feather-mask);
              mask-image: var(--stage-feather-mask);
      -webkit-mask-composite: source-in;   /* intersect the 3 mask layers */
              mask-composite: intersect;
    }
    .ref-preview-cap { display: none !important; }
    /* R5 (2026-07-18): once a real photo is staged, the placeholder yields.
       The engine's raw optionimage_* divs are DATA for the stage decorator
       (their style attr is the swap signal) — never an inline display surface
       inside the rail panels / selector views / drawer. */
    .ref-preview-wrap.has-photo .ref-preview-placeholder { display: none; }
    .main-builder-rail [id^="optionimage_"],
    .cfg-selector-view [id^="optionimage_"],
    .cfg-build-drawer [id^="optionimage_"] { display: none !important; }

    /* R1 default-hero PLACEHOLDER block (image wiring is R5) */
    .ref-preview-placeholder {
      width: 100%;
      aspect-ratio: 1.35 / 1;
      max-height: calc(100vh - 300px);
      margin: 0 auto;
      border-radius: 12px;
      background: linear-gradient(135deg, #1b1b1b, #2c2c2c);
      border: 1px solid rgba(255,255,255,.10);
      box-shadow: 0 34px 52px rgba(0,0,0,.42);
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .ref-preview-placeholder::after {
      content: "Card preview";
      color: rgba(255,255,255,.5);
      font-family: var(--heading-font);
      font-size: 13px;
      font-weight: 800;
      letter-spacing: .2em;
      text-transform: uppercase;
    }

    /* v1.81 rule (mockup-verbatim), pulled forward from R4 per OWNER 2026-07-17 item 1:
       the v1.45 summary card duplicated the YOUR BUILD bar → visually retired.
       DOM STAYS — the bar mirrors #cfg-summary-grid/#configure-price-preview and
       bb-add proxies the (hidden) #cfg-sidebar-atc; programmatic .click() works on
       display:none nodes. Request-Quotation surfacing in the bar = R4 (C1-2). */
    .preview-panel .preview-summary { display: none !important; }
    .preview-panel .preview-summary-GLASS-RETIRED {
      position: absolute;
      right: 24px;
      bottom: 118px;
      z-index: 6;
      width: min(280px, calc(100% - 48px));
      max-height: calc(100vh - 280px);
      margin: 0;
      padding: 16px 16px 14px;
      border-radius: 16px;
      background: rgba(255,255,255,.92);
      border: 1px solid rgba(20,24,29,.12);
      box-shadow: 0 18px 45px rgba(0,0,0,.16);
      backdrop-filter: blur(16px);
      -webkit-backdrop-filter: blur(16px);
      font-family: var(--font);
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }
    .summary-cell.empty { display: none !important; }

    /* ratings badge — bottom-LEFT of the photo box (v1.81 position; graphic is R5) */
    .preview-rating-label {
      position: absolute;
      /* round 9: hug the stage's bottom-left corner (owner). The bottom offset
         clears the fixed YOUR BUILD bar overlaying the frame's bottom edge. */
      left: 12px;
      bottom: 119px;
      z-index: 7;
      line-height: 0;
    }
    .preview-rating-label .rating-placeholder {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 8px 14px;
      border-radius: 999px;
      background: rgba(255,255,255,.14);
      border: 1px solid rgba(255,255,255,.24);
      color: #fff;
      font-family: var(--heading-font);
      font-size: 12px;
      font-weight: 800;
      letter-spacing: .04em;
      line-height: 1;
    }

    /* --- right column: flows with the PAGE (single scroller) ---
       Was an inner scroll region (height:calc(100vh-92px) + overflow-y:auto).
       That created TWO scrollables (body scrolls to the footer, column scrolls
       the rail) — on iPadOS touch the body always won, so the rail could not be
       scrolled at all (owner-reported 2026-07-17). One scroller fixes touch,
       keeps the site footer reachable below the bar, and matches scReCenter,
       which already targets window scroll. The stage stays sticky. */
    .builder-column {
      background: #fff !important;
      border-left: 1px solid #DDE1E6;
      box-shadow: -16px 0 40px rgba(0,0,0,.06);
      padding-bottom: 130px;            /* room above the fixed bottom bar */
    }
    /* .builder min-height:100% removed with the inner-scroll model — under the
       single-scroller Safari resolved the % against the viewport and padded the
       column with blank white below the content (owner iPad item 3, 2026-07-17). */

    /* sticky scrollport fix (R3 live-verify catch, 2026-07-17): the base v1.45
       card rule sets .builder{overflow:hidden}, which makes .builder the sticky
       SCROLLPORT — .build-context pinned top:92 INSIDE a box that never scrolls,
       so it sat permanently displaced +92px over the form (covering the first
       rail row — the 118 foil hero) and never actually stuck on page scroll.
       overflow:clip keeps the rounded-card clipping WITHOUT creating a scroll
       container, so the context sticks to the WINDOW as the single-scroller
       model intends. (Old Safari ignores clip → falls back to the prior state,
       no worse.) */
    .builder { overflow: clip; }

    /* build-context → clean sticky header (title + admin link kept visible; the
       mockup's card-type picker is out of R1 scope) */
    .build-context {
      position: sticky;
      top: 92px;                        /* page-scroll model: sit below the sticky site nav (92px, same offset as the stage) */
      z-index: 35;
      margin: 0;
      padding: 18px 24px;
      border: 0;
      border-bottom: 1px solid var(--rail-line);
      border-radius: 0;
      box-shadow: none;
      background: #fff;
    }

    /* --- existing engine steps: flatten to the v1.84 single-column look so the
           working wizards read coherently in the 30vw column (JS untouched) --- */
    .step {
      margin: 0;
      padding: 0;
      border: 0;
      border-radius: 0;
      box-shadow: none;
      background: #fff;
    }
    .step + .step { border-top: 1px solid var(--rail-line); }
    .step-title {
      position: sticky;
      top: 0;
      z-index: 20;
      min-height: 76px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      padding: 18px 24px;
      margin: 0;
      background: #fff;
      border-bottom: 1px solid var(--rail-line);
    }
    .step-title h3 {
      font-size: 15px;
      line-height: 1.2;
      letter-spacing: -.01em;
      text-transform: none;
      color: #10151A;
    }
    .step-title p, .step-num { display: none !important; }

    .foil-detail-block,
    .step-sub,
    .finish-row,
    .order-fields { padding: 18px 24px 24px; margin: 0; }

    .choice-grid,
    .choice-grid.two,
    .stock-grid,
    .thickness-grid,
    .foil-swatch-grid,
    .foil-type-grid,
    .foil-placement-grid,
    .scope-grid,
    .finish-row,
    .order-fields { grid-template-columns: 1fr !important; gap: 12px; }

    /* =====================================================================
       v1.67 SECTION-LAUNCHER RAIL  (R1 skeleton — R2 re-houses the engine
       panels into these rows + makes membership render-derived per delta #10)
       ===================================================================== */
    .main-builder-rail {
      background: #fff;
      border-top: 1px solid var(--rail-line);
    }
    .main-builder-option {
      min-height: 106px;
      display: grid;
      grid-template-columns: minmax(0, 1fr) 170px;
      align-items: center;
      gap: 18px;
      padding: 22px 24px 22px 28px;
      border-bottom: 1px solid var(--rail-line);
      background: #fff;
      color: #11151A;
      text-decoration: none;
      cursor: pointer;
      transition: background .18s ease, border-color .18s ease;
    }
    .main-builder-option:hover { background: #EAFBFF; }
    .main-builder-option.is-selected { background: #E5E9EE; }
    .main-builder-option.is-expanded { background: #EAFBFF; border-bottom-color: transparent; }
    .main-option-copy { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; row-gap: 1px; min-width: 0; }
    .main-option-copy strong {
      /* was `nowrap` (fixed 2026-08-28, owner-caught). The copy column is 177px and
         "Choose Quantity and Sets" measures 199px, so nowrap made the label OVERFLOW its
         column and pushed the required-star onto a line of its own — measured by
         horizontal position (star.left 0 vs the label's right edge), not by vertical
         offset, because .required-star carries line-height:0 + top:4px and so sits lower
         than the label even when it is on the same line. Normal wrapping breaks at spaces
         only, so the star stays with the last word and nothing overflows. */
      white-space: normal;
      font-family: var(--font);
      font-size: 16.8px;
      line-height: 1.2;
      letter-spacing: -.01em;
      font-weight: 400;
      color: #10151A;
    }
    /* The star now lives INSIDE <strong> (2026-08-28). It used to be its own flex item of
       .main-option-copy, and a flex item is blockified — so the label filled the whole 177px
       column and the star could never share its line, wrapping alone under every label long
       enough to fill it ("Choose Quantity and Sets", "Material and Thickness"). Inside the
       label it simply follows the last word and wraps with it. margin-left replaces the flex
       column-gap that used to separate them. */
    .required-star { color: #E03131; font-size: 15px; font-weight: 900; line-height: 1; margin-left: 5px; }

    .main-builder-section-note {
      /* no min-height since 2026-10-01: the band held a heading and a two-line sentence; the
         sentence is gone (the text sweep, T15) and 108px left the heading floating in 42px of
         empty band above and below it. The padding alone now sets the height (72px, 24px above and below the heading). */
      padding: 24px 28px;
      border-bottom: 1px solid var(--rail-line);
      background: #e3e5e5;               /* the Signature-Finishes divider box (delta #3) */
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: 8px;
    }
    .main-builder-section-note h3 {
      margin: 0;
      font-family: var(--font);
      font-size: 20px;
      line-height: 1.15;
      letter-spacing: -.01em;
      font-weight: 700;
      color: #10151A;
    }
    .main-builder-section-note p {
      margin: 0;
      font-family: var(--font);
      font-size: 13px;
      line-height: 1.45;
      font-weight: 400;
      color: #4B535A;
    }

    .main-option-visual { display: flex; justify-content: flex-end; align-items: center; min-width: 0; }
    .mini-card {
      position: relative;
      width: 148px;
      height: 42px;
      border-radius: 6px;
      background: linear-gradient(135deg, #151515, #262626);
      border: 1px solid #AAB2BA;
      box-shadow: 0 6px 14px rgba(15,18,22,.10);
      overflow: hidden;
    }
    .mini-card i { position: absolute; display: block; }
    /* Henry's 2026-08 icon drop — inline currentColor SVGs (GOTCHAS #293), replacing the
       CSS-art placeholders row by row. Same 148x42 card so row geometry is untouched;
       rows with no delivered icon still render their legacy art above. */
    /* UNBOXED (owner-directed 2026-08-28 — "the boxes take up too much space and draw the
       eye too much for doing nothing"): the frame belonged to the old CSS-art placeholders;
       a real icon stands bare. The slot keeps fixed dimensions so icons align vertically
       across rows, and rows with NO delivered icon (QR, Score/Fold, Grommets, Strings)
       render an empty slot — no lone boxed placeholder among bare icons. */
    .mini-card.mini-ic { display: flex; align-items: center; justify-content: flex-end; background: transparent; border: 0; box-shadow: none; }
    /* branded gold (owner-directed 2026-08-28 — "the gray looks off"), same token the
       design-help start icons use; the SVGs are currentColor so only this line decides */
    /* one identical 44x34 box for EVERY icon; the svg letterboxes itself inside it
       (preserveAspectRatio default) — a fixed HEIGHT alone made wide drawings
       (emboss/deboss/VD) render far larger than the square ones (owner-caught 2026-08-28) */
    .mini-card.mini-ic svg { width: 44px; height: 34px; display: block; color: var(--gold); }
    .main-builder-option .mini-card:not(.mini-ic) { visibility: hidden; }
    .mini-card i:nth-child(1) { left: 13px; top: 12px; width: 31px; height: 6px; border-radius: 99px; background: #D9B35D; }
    .mini-card i:nth-child(2) { left: 13px; bottom: 10px; width: 96px; height: 4px; border-radius: 99px; background: rgba(217,179,93,.78); }
    .mini-card i:nth-child(3) { right: 12px; top: 11px; width: 22px; height: 22px; border-radius: 50%; border: 2px solid rgba(255,255,255,.38); }
    .mini-card-size { background: #fff; }
    .mini-card-size i:nth-child(1) { left: 18px; top: 30px; width: 108px; height: 1px; background: #111; }
    .mini-card-size i:nth-child(2) { left: 18px; top: 24px; width: 1px; height: 13px; background: #111; }
    .mini-card-size i:nth-child(3) { right: 21px; top: 24px; width: 1px; height: 13px; background: #111; border: 0; }
    .mini-card-stock { background: linear-gradient(180deg, #F7F7F5 0 28%, #E7E7E4 28% 45%, #D8D8D4 45% 62%, #C9C9C4 62%); }
    .mini-card-stock i:nth-child(1), .mini-card-stock i:nth-child(2), .mini-card-stock i:nth-child(3) { display: none; }
    .mini-card-spotuv { background: #101010; }
    .mini-card-spotuv i:nth-child(1) { left: 16px; top: 12px; width: 48px; height: 18px; background: linear-gradient(90deg, transparent, rgba(255,255,255,.52), transparent); }
    .mini-card-spotuv i:nth-child(2) { right: 16px; top: 16px; width: 44px; height: 4px; background: rgba(255,255,255,.42); }
    .mini-card-raiseduv { background: #0F1115; }
    .mini-card-raiseduv i:nth-child(1) { left: 15px; top: 12px; width: 50px; height: 18px; background: linear-gradient(180deg, rgba(255,255,255,.64), rgba(255,255,255,.16)); box-shadow: 0 3px 0 rgba(255,255,255,.16); }
    .mini-card-diecut { background: #fff; }
    .mini-card-diecut i:nth-child(1) { left: 12px; top: 11px; width: 24px; height: 20px; border-radius: 50%; border: 2px dashed #111; background: transparent; }
    .mini-card-diecut i:nth-child(2) { left: 48px; top: 19px; width: 76px; height: 2px; background: #C9A96E; }
    .mini-card-edge { background: #111; border-color: #C9A96E; box-shadow: inset 0 -4px 0 #D9B35D; }
    .mini-card-raisedfoil { background: #111; }
    .mini-card-raisedfoil i:nth-child(1) { left: 17px; top: 10px; width: 38px; height: 17px; background: #D9B35D; box-shadow: 0 3px 0 #8F6E27; }
    .mini-card-emboss { background: #F6F6F2; }
    .mini-card-emboss i:nth-child(1) { left: 18px; top: 13px; width: 42px; height: 14px; border: 1px solid #AEB4BB; background: #fff; box-shadow: 0 3px 0 #D4D7DA; }
    .mini-card-pms { background: #fff; }
    .mini-card-pms i:nth-child(1) { left: 12px; top: 10px; width: 22px; height: 22px; border-radius: 50%; background: #00C2FF; }
    .mini-card-pms i:nth-child(2) { left: 40px; top: 10px; width: 22px; height: 22px; border-radius: 50%; background: #C9A96E; }
    .mini-card-pms i:nth-child(3) { left: 68px; top: 10px; width: 22px; height: 22px; border-radius: 50%; background: #E03131; border: 0; }
    .mini-card-corners { border-radius: 18px; background: #fff; }
    .mini-card-corners i:nth-child(1), .mini-card-corners i:nth-child(2), .mini-card-corners i:nth-child(3) { display: none; }
    .mini-card-perf { background: #fff; }
    .mini-card-perf i:nth-child(1) { left: 72px; top: 5px; width: 1px; height: 32px; border-left: 2px dashed #111; background: transparent; }
    .mini-card-perf i:nth-child(2) { left: 16px; top: 19px; width: 42px; height: 3px; background: #C9A96E; }
    .mini-card-quantity { background: #fff; }
    .mini-card-quantity i:nth-child(1) { left: 20px; top: 12px; width: 108px; height: 5px; background: #111; }
    .mini-card-quantity i:nth-child(2) { left: 20px; top: 24px; width: 78px; height: 4px; background: #C9A96E; }

    /* --- v1.80 required-star 2x --- */
    .required-star { font-size: 30px !important; line-height: 0 !important; position: relative; top: 4px; }

    /* =====================================================================
       v1.81 YOUR BUILD bottom information bar (fixed). The slide-up drawer +
       boxed receipt (v1.83) is R4 — this is the flat-cell skeleton only.
       ===================================================================== */
    .build-bar {
      position: fixed;
      left: 0; right: 0; bottom: 0;
      z-index: 80;
      display: grid;
      grid-template-columns: minmax(280px, 420px) minmax(0, 1fr) auto auto;
      align-items: center;
      gap: 26px;
      min-height: 96px;
      padding: 14px 28px 14px 32px;
      background: #F7F8FA;
      border-top: 1px solid #E2E6EA;
      box-shadow: 0 -10px 30px rgba(20,24,29,.07);
      font-family: var(--font);
      color: #11151A;
    }
    .build-bar .bb-label {
      display: block;
      font-family: var(--heading-font);
      font-size: 13.5px;
      font-weight: 900;
      letter-spacing: .14em;
      text-transform: uppercase;
      color: #757F89;
      white-space: nowrap;
    }
    .bb-brand .bb-label { color: #8A93A0; margin-bottom: 3px; }
    .bb-brand strong {
      display: block;
      font-family: var(--heading-font);
      font-size: 23px;
      font-weight: 900;
      letter-spacing: -.02em;
      line-height: 1.1;
      color: #11151A;
    }
    .bb-brand .bb-note { margin-top: 4px; font-size: 15.5px; line-height: 1.3; color: #6D7680; }
    .bb-cells { display: flex; align-items: stretch; justify-content: flex-start; min-width: 0; overflow-x: auto; }
    .bb-cell {
      flex: 0 0 auto;
      padding: 4px 22px;
      border-left: 1px solid #E2E6EA;
      display: flex; flex-direction: column; justify-content: center; gap: 4px;
      white-space: nowrap;
    }
    .bb-cell:first-child { border-left: 0; padding-left: 0; }
    .bb-cell strong { font-size: 17.5px; font-weight: 800; letter-spacing: -.01em; color: #11151A; line-height: 1.15; }
    .bb-price { text-align: right; padding-right: 6px; }
    .bb-price .bb-label { color: #757F89; }
    .bb-price .bb-price-value {
      display: block;
      margin: 3px 0 2px;
      font-family: var(--heading-font);
      font-size: 27px;
      font-weight: 900;
      letter-spacing: -.03em;
      color: #11151A;
      line-height: 1;
    }
    .bb-price .bb-price-fine { font-size: 13.5px; color: #8A93A0; line-height: 1.2; }
    .bb-cta { display: flex; flex-direction: column; align-items: center; gap: 6px; }
    .bb-cta .bb-add {
      min-width: 168px;
      min-height: 52px;
      border: 0;
      border-radius: 999px;
      background: var(--blue, #00C2FF);
      color: #061015;
      font-family: var(--heading-font);
      font-size: 16px;
      font-weight: 900;
      letter-spacing: .01em;
      cursor: pointer;
      transition: filter .16s ease, transform .16s ease;
    }
    .bb-cta .bb-add:hover { filter: brightness(1.07); }
    .bb-cta .bb-save { background: none; border: 0; padding: 0; font-size: 14.5px; font-weight: 800; color: #11151A; cursor: pointer; text-decoration: none; }
    .bb-cta .bb-save:hover { color: var(--blue-dark, #008EBB); text-decoration: underline; }

    /* =====================================================================
       Responsive — ported verbatim for the R1 surfaces (workspace / preview /
       rail / build-bar). The v1.83 drawer/receipt breakpoints are R4.
       ===================================================================== */
    @media (max-width: 1420px) {
      .build-bar { grid-template-columns: minmax(220px, 300px) minmax(0, 1fr) auto auto; gap: 18px; }
      .bb-brand .bb-note { display: none; }
      .bb-cell { padding: 4px 16px; }
    }
    @media (max-width: 1180px) {
      .workspace { grid-template-columns: 1fr; min-height: auto; }
      .preview-panel { position: relative; top: 0; height: auto; min-height: 520px; padding-bottom: 120px; }
      .builder-column { height: auto; overflow: visible; border-left: 0; box-shadow: none; }
      .step-title { top: 0; }
      .main-builder-option { grid-template-columns: 1fr 140px; }
      .mini-card { width: 128px; }
    }
    @media (max-width: 1024px) {
      .build-bar { grid-template-columns: 1fr auto; grid-auto-rows: auto; row-gap: 10px; }
      .bb-cells { grid-column: 1 / -1; order: 3; }
    }
    /* ===================== end v1.84 LAYOUT SHELL (R1) ===================== */

    /* =====================================================================
       v1.84 R2 — rail inline panels + render-derived rows
       The rail is moved INSIDE #shoppingform at runtime; each row's engine
       control lives in its .inline-config-panel (containment contract). Rows
       toggle their panel open (accordion-single + expand-to-center).
       ===================================================================== */
    .inline-config-panel {
      display: none;
      padding: 18px 24px 26px 28px;
      border-bottom: 1px solid var(--rail-line);
      background: #fff;
    }
    .inline-config-panel.is-open { display: block; }
    /* the moved engine <dt>/<dd> read coherently inside the narrow panel:
       flatten the legacy accordion chrome (borders/insets) it carried */
    .inline-config-panel > dt,
    .inline-config-panel > dd { border: 0; margin: 0; background: transparent; }
    .inline-config-panel > dd { padding: 12px 0 0; }
    /* JS slots collapse when empty (hero slot on 143 has no hero finish) */
    #mb-hero-slot:empty, #mb-finish-slot:empty { display: none; }

    /* render-derived rows reuse the .main-builder-option look (R1); a prominent
       hero row (hero_optionids finish, e.g. Foil on 118) sits above basics */
    .main-builder-option.cfg-rail-hero { background: #FCFBF6; }
    .main-builder-option.cfg-rail-hero .main-option-copy strong { font-weight: 700; }

    /* row state pill — engine reality only (selected value / "Configured") */
    .mb-row-pill {
      display: inline-block;
      order: 1;
      margin-left: auto;
      padding: 2px 9px;
      border-radius: 99px;
      font: 700 11px/1.5 var(--font);
      letter-spacing: .01em;
      background: #EAF7EF;
      color: #1E7D46;
      border: 1px solid #BFE6CE;
      vertical-align: middle;
      max-width: 160px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .mb-row-pill[hidden] { display: none; }

    /* engaged finish (Option A, 2026-07-20): ✓ badge + tint + blue value pill.
       Signals "you selected this" ON the row — mirrors the stock cards' ✓. */
    /* ---------------------------------------------------------------
       Spot UV surface gate (2026-08-28) — a finish the CURRENT SURFACE
       cannot carry stays VISIBLE and greys out with its reason (owner's
       choice: hiding it reads as "not offered", greying it tells a buyer
       which one thing to change). Values echo the selector view's own
       .placement-card.is-locked so the two lock states read as one idea.
       --------------------------------------------------------------- */
    /* A required step with only ONE possible value: it still STATES the value (the buyer
       needs it, and it is 1 of 3 required steps) but opens nothing, because there is
       nothing to choose. Not greyed like .is-unavailable — this is satisfied, not blocked. */
    .main-builder-option.is-static { cursor: default; }
    .main-builder-option.is-static:hover { background: inherit; }

    .main-builder-option.is-unavailable { background: #F4F6F8; cursor: not-allowed; }
    .main-builder-option.is-unavailable:hover { background: #F4F6F8; }
    .main-builder-option.is-unavailable .main-option-copy strong { color: #6D7680; }
    .main-builder-option.is-unavailable .main-option-visual { opacity: .45; }
    .main-builder-option .cfg-uv-lock-note {
        display: block; flex-basis: 100%; order: 3;
        font-size: 12px; line-height: 1.3; color: #68727D;
        font-style: italic; font-weight: 400; margin-top: 2px;
    }

    .main-builder-option.is-engaged { background: #EAF6FF; box-shadow: inset 3px 0 0 0 var(--blue); }
    .main-builder-option.is-engaged.is-expanded { background: #EAFBFF; }
    .main-builder-option.is-engaged .main-option-copy strong::before {
      content: "✓";
      display: inline-flex; align-items: center; justify-content: center;
      width: 18px; height: 18px; border-radius: 50%;
      background: var(--blue); color: #062534;
      font-size: 11px; font-weight: 900;
      margin-right: 8px; vertical-align: middle; flex-shrink: 0;
    }
    .main-builder-option.is-engaged .mb-row-pill { background: #E6F1FB; color: #0C447C; border-color: #B5D4F4; }

    /* A REQUIRED STEP drawn with Size / Quantity / Material (configure.php, THE TEMPLATE STEP).
       It is a step, not a finish someone added: no tint, no tick, and the same green value
       label the three rows above it use. While nothing is chosen the label is amber — the
       one row on the rail that still needs the customer. */
    .main-builder-option.cfg-rail-step.is-engaged { background: transparent; box-shadow: none; }
    .main-builder-option.cfg-rail-step.is-engaged.is-expanded { background: #FCFBF6; }
    .main-builder-option.cfg-rail-step.is-engaged .main-option-copy strong::before { content: none; }
    .main-builder-option.cfg-rail-step.is-engaged .mb-row-pill { background: #EAF7EF; color: #1E7D46; border-color: #BFE6CE; }
    .main-builder-option.cfg-rail-step.is-waiting .mb-row-pill { background: #FFF6E0; color: #7A5200; border-color: #EBCF8C; }
    /* A step that is pre-chosen but not yet looked at (Material and Thickness on a template
       product, 2026-09-30): its value stays on the label, with the ask after it. In CSS so the
       rail's own label refresh, which rewrites the text on every change, cannot drop it. */
    .main-builder-option.cfg-step-review .mb-row-pill::after { content: " \00B7  Review"; font-weight: 800; }

    /* generic mini-card for an engine finish with no mapped visual */
    .mini-card-generic { background: #fff; }
    .mini-card-generic i:nth-child(1) { left: 16px; top: 14px; width: 40px; height: 12px; border-radius: 3px; background: #C9A96E; }
    .mini-card-generic i:nth-child(2) { left: 16px; bottom: 12px; width: 70px; height: 4px; border-radius: 99px; background: rgba(201,169,110,.6); }
    .mini-card-generic i:nth-child(3) { right: 14px; top: 13px; width: 18px; height: 18px; border-radius: 50%; border: 2px solid rgba(0,0,0,.12); }

    @media (max-width: 1180px) {
      .inline-config-panel { padding: 16px 18px 22px; }
    }
    /* ===================== end v1.84 R2 ===================== */

    /* =====================================================================
       v1.84 R3 — selector DETAIL VIEWS (D-SEL, in-page)
       Full-viewport modal overlay per selector section (Foil / Material /
       Spot UV / Die Cut / Edge). Shell ported VERBATIM from the committed
       Master selector mockups (70vw black stage + 30vw rail + Back/Confirm),
       namespaced under .cfg-selector-view so it can't leak into the page. The
       view element lives INSIDE #shoppingform (containment); position:fixed
       gives the full-screen render without detaching from the form tree.
       The moved R2 .inline-config-panel (engine dt/dd + decorated wizard) is
       hosted in .csv-body; its raw <dt> is CSS-hidden (rail-head shows title).
       ===================================================================== */
    .cfg-selector-view {
      position: fixed;
      inset: 0;
      z-index: 1200;                 /* above the fixed "YOUR BUILD" bar */
      display: none;
      background: #fff;
      font-family: Manrope, Helvetica, Arial, sans-serif;
      color: #11151A;
      overscroll-behavior: contain;
    }
    .cfg-selector-view.is-open { display: block; }
    body.cfg-view-open { overflow: hidden; }   /* lock page scroll behind the modal */

    .cfg-selector-view .csv-workspace {
      height: 100vh;
      display: grid;
      grid-template-columns: minmax(0, 70vw) minmax(430px, 30vw);
      overflow: hidden;
      background: #fff;
    }
    /* --- black preview stage (left) --- */
    .cfg-selector-view .csv-preview-side {
      position: relative;
      background: #050505;
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
    }
    .cfg-selector-view .csv-preview-side:before {
      content: "";
      position: absolute;
      inset: 0;
      background: radial-gradient(circle at 52% 50%, rgba(255,255,255,.05), rgba(5,5,5,.94) 46%, #000 100%);
    }
    .cfg-selector-view .csv-photo-wrap {
      position: relative;
      z-index: 1;
      width: min(88%, 1080px);
      display: flex;
      align-items: center;
      justify-content: center;
    }
    /* R5 mounts the engine optionimage_* photo here; default = neutral slot */
    /* empty placeholder (before a photo mounts) keeps the neutral slot chrome */
    .cfg-selector-view .csv-photo-slot {
      width: 100%;
      max-width: 620px;
      aspect-ratio: 16 / 10;
      border-radius: 10px;
      background:
        linear-gradient(135deg, rgba(255,255,255,.05), rgba(255,255,255,.015)),
        repeating-linear-gradient(45deg, rgba(255,255,255,.03) 0 10px, transparent 10px 20px);
      box-shadow: 0 34px 42px rgba(0,0,0,.55);
    }
    /* R5 (owner 2026-07-22): match Henry's CFG-03 mockup .photo-wrap img exactly — the
       photo FILLS the stage at its natural aspect (object-fit:contain, no 620px cap, no
       crop) with a soft drop-shadow for depth. Dark-backdrop photos melt into the #050505
       stage by their own background; the drop-shadow gives the lift (this is how the mockup
       gets its "feathered" look — no CSS mask). Was a 620px cover-crop + radial mask that
       diverged from the mockup: too small + a hard edge on bright-backdrop photos. */
    .cfg-selector-view .csv-photo-slot.has-photo {
      width: 100%;
      max-width: none;
      aspect-ratio: auto;
      border-radius: 0;
      background: none;
      box-shadow: none;
    }
    /* Feather the edges into the black stage ON OUR SIDE (owner 2026-07-22): our real
       photos are RAW (light studio backdrops), so we don't rely on the photo being shot
       on black like the mockup — the CSS mask melts every photo's edges into the stage.
       With width:100% + height:auto + contain, the img box hugs the photo's natural aspect
       (no letterbox), so the percentage mask feathers the ACTUAL photo edges. Combines the
       mockup's full-stage SIZE with the feather. Single-homed --stage-feather-mask. */
    .cfg-selector-view .csv-photo-slot img {
      display: block;
      width: 100%;
      height: auto;
      max-height: calc(100vh - 165px);
      object-fit: contain;
      border-radius: 30px;              /* rounded corners (owner 2026-07-22) */
      -webkit-mask-image: var(--stage-feather-mask);
              mask-image: var(--stage-feather-mask);
      -webkit-mask-composite: source-in;
              mask-composite: intersect;
    }

    /* ---- ?stagever=original — the ORIGINAL stage treatment, for the CFG-03 v1/v2 compare.
       Restores the pre-2026-07-22 look: 620px cover-crop slot + the lone radial mask (the
       straight-edge seam version), square corners. Default (no class) = the current
       owner-chosen curve + rounded-corners treatment. Remove this block + the ?stagever
       param once the comparison is settled. */
    html.cfg-stage-orig .ref-preview-wrap img {
      aspect-ratio: 655 / 560;
      object-fit: cover;
      border-radius: 0;
      filter: none;
      -webkit-mask-image: radial-gradient(ellipse 86% 82% at 50% 50%, #000 30%, rgba(0,0,0,.55) 55%, transparent 80%);
              mask-image: radial-gradient(ellipse 86% 82% at 50% 50%, #000 30%, rgba(0,0,0,.55) 55%, transparent 80%);
      -webkit-mask-composite: add;
              mask-composite: add;
    }
    html.cfg-stage-orig .cfg-selector-view .csv-photo-slot.has-photo {
      width: 100%;
      max-width: 620px;
      aspect-ratio: 16 / 10;
      border-radius: 0;
    }
    html.cfg-stage-orig .cfg-selector-view .csv-photo-slot img {
      height: 100%;
      max-height: none;
      object-fit: cover;
      border-radius: 0;
      filter: none;
      -webkit-mask-image: radial-gradient(ellipse 86% 82% at 50% 50%, #000 30%, rgba(0,0,0,.55) 55%, transparent 80%);
              mask-image: radial-gradient(ellipse 86% 82% at 50% 50%, #000 30%, rgba(0,0,0,.55) 55%, transparent 80%);
      -webkit-mask-composite: add;
              mask-composite: add;
    }
    /* owner round-10: Confirm-veto nudge + placement-strip attention pulse */
    .cfg-selector-view .csv-nudge {
      display: none;
      margin: 0 22px 10px;
      padding: 12px 16px;
      border-radius: 12px;
      background: #FFF7E0;
      border: 1px solid #E7C96A;
      color: #4A3A00;
      font-size: 13px;
      font-weight: 700;
      line-height: 1.45;
    }
    .cfg-selector-view .csv-nudge.is-on { display: block; animation: cfgNudgeIn .28s ease; }
    @keyframes cfgNudgeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
    .cfg-selector-view .cfg-attention { animation: cfgAttention 1.3s ease 2; border-radius: 14px; }
    @keyframes cfgAttention {
      0%, 100% { box-shadow: none; }
      45% { box-shadow: 0 0 0 3px rgba(0,178,208,.55); }
    }
    /* selection-card (bottom-right, read-only live engine state) */
    .cfg-selector-view .csv-selection-card {
      position: absolute;
      right: 24px;
      bottom: 24px;
      z-index: 3;
      width: min(330px, calc(100% - 48px));
      background: rgba(255,255,255,.94);
      border: 1px solid rgba(17,21,26,.13);
      border-radius: 16px;
      box-shadow: 0 18px 45px rgba(0,0,0,.16);
      backdrop-filter: blur(16px);
      padding: 15px 16px 14px;
    }
    .cfg-selector-view .csv-selection-card h3 {
      margin: 0 0 10px;
      font-family: Manrope, Helvetica, Arial, sans-serif;
      font-size: 12px;
      font-weight: 900;
      letter-spacing: .13em;
      text-transform: uppercase;
      color: #111;
    }
    .cfg-selector-view .csv-card-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
      padding: 8px 0;
      border-top: 1px solid rgba(17,21,26,.09);
      font-size: 12px;
    }
    .cfg-selector-view .csv-card-row:first-child { border-top: 0; }
    .cfg-selector-view .csv-card-row span {
      font-weight: 900;
      letter-spacing: .12em;
      text-transform: uppercase;
      color: #757F89;
      font-size: 10px;
      flex: 0 0 auto;
    }
    .cfg-selector-view .csv-card-row strong { text-align: right; font-size: 12px; line-height: 1.25; color: #111; max-width: 200px; }

    /* --- rail (right) --- */
    .cfg-selector-view .csv-rail {
      height: 100vh;
      display: flex;
      flex-direction: column;
      background: #fff;
      border-left: 1px solid #E2E6EA;
      overflow: hidden;
    }
    .cfg-selector-view .csv-rail-bar {
      height: 60px;
      background: #050505;
      color: #fff;
      display: flex;
      align-items: center;
      justify-content: center;
      font-family: Manrope, Helvetica, Arial, sans-serif;
      font-size: 16.8px;
      font-weight: 900;
      letter-spacing: .02em;
      flex: 0 0 auto;
    }
    .cfg-selector-view .csv-rail-head {
      padding: 18px 22px 16px;
      border-bottom: 1px solid #E2E6EA;
      background: #fff;
      flex: 0 0 auto;
    }
    /* THE HEADING IS THE SCREEN'S NAME, ONCE ("Foil Setup") — owner 2026-10-01: "change to Foil
       Setup only and make it larger so it fits the space well". The small blue line (13px) over
       a 24px sentence is gone. SIZE: the first pass ran 39px at 1440 and 44px on a wide screen
       and he sent it back the same day ("far too overpowering"), so it sits at the size the
       sentence had and he had lived with — 24px on a laptop, up to 28px on a wide window. */
    .cfg-selector-view .csv-rail-head h1 {
      margin: 0;
      font-family: Manrope, Helvetica, Arial, sans-serif;
      font-size: clamp(24px, 1.8vw, 28px);
      line-height: 1.12;
      letter-spacing: -.02em;
      color: #11151A;
    }
    .cfg-selector-view .csv-rail-head p { margin: 8px 0 0; font-size: 14.4px; line-height: 1.45; color: #66707A; }

    /* body hosts the moved R2 panel (engine dt/dd + decorated wizard) */
    .cfg-selector-view .csv-body {
      flex: 1 1 auto;
      min-height: 0;
      overflow: auto;
      -webkit-overflow-scrolling: touch;
      background: #fff;
      padding: 16px 18px 84px;
    }
    /* force the moved panel visible inside the view; hide its redundant raw <dt>
       (the rail-head shows the section title; finish decorators own on/off,
       GOTCHAS #38/#49) — CSS hide only, node never removed */
    .cfg-selector-view .inline-config-panel { display: block; padding: 0; border: 0; background: transparent; }
    .cfg-selector-view .inline-config-panel > dt { display: none; }
    .cfg-selector-view .inline-config-panel > dd { display: block; padding: 0; }

    /* sticky Back / Confirm */
    .cfg-selector-view .csv-actions {
      position: sticky;
      bottom: 0;
      z-index: 10;
      display: grid;
      grid-template-columns: 1fr 1fr;
      width: 100%;
      min-height: 64px;
      border-top: 1px solid #E2E6EA;
      background: #fff;
      box-shadow: 0 -14px 30px rgba(20,24,29,.08);
      flex: 0 0 auto;
    }
    .cfg-selector-view .csv-actions button {
      border: 0;
      border-radius: 0;
      font-family: Manrope, Helvetica, Arial, sans-serif;
      font-size: 14.4px;
      font-weight: 900;
      text-transform: uppercase;
      letter-spacing: .02em;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .cfg-selector-view .csv-back    { background: #fff; color: #11151A; border-right: 1px solid #E2E6EA; }
    .cfg-selector-view .csv-confirm { background: #050505; color: #fff; }

    /* selector-view responsive: collapse to single column (mockup @1180) */
    @media (max-width: 1180px) {
      /* ONE SCROLLER BELOW 1180px: THE WORKSPACE (2026-10-01, measured with a wheel at 1000x700
         and 375x760 on the foil screen). The screen is a fixed full-window layer. With
         `height: auto` the workspace grew to 2,054px inside it and nothing could scroll it — the
         wheel moved the page behind (scrollY 920) and the colors, at y 1,862, were out of reach.
         At 700px and under the workspace was one window tall and did scroll, but the rail clips
         its overflow, so its row stayed one window tall too (rows 150px + 760px): only the photo
         scrolled away and the rail's lower 745px could not be reached. Now the workspace is one
         window tall at every width under 1180, the rail does not clip, and its row is
         `minmax(min-content, 1fr)`: as tall as its content, and never shorter than the room
         left under the photo, so the whole screen scrolls as one column and Back / Confirm stay
         stuck to the bottom of the window. (The rail's own `min-height: 100vh` had to go: a
         grid row takes an item's stated minimum INSTEAD of its content, which is what held the
         row at one window while the content overflowed it.)
         ASSUMES: nothing under 1180px relies on .csv-rail clipping its content — if a child is
         positioned outside the rail on purpose it shows now. */
      .cfg-selector-view .csv-workspace { grid-template-columns: 1fr; grid-template-rows: auto minmax(min-content, 1fr); height: 100vh; height: 100dvh; min-height: 0; overflow: auto; }
      .cfg-selector-view .csv-preview-side { min-height: 44vh; }
      .cfg-selector-view .csv-rail { height: auto; min-height: 0; border-left: 0; overflow: visible; }
      .cfg-selector-view .csv-body { overflow: visible; }
    }

    /* (item 7) widen the rail pill so common values (e.g. "3.5" x 2") don't clip */
    /* 2026-10-01: a pill is never cut. At 210px with an ellipsis, a two-side finish read
       "Card Front · Card Back · +$9…" (the price is the part that was lost) and admin's own
       size note on the catalog was cut mid-sentence. The pill now takes the row's width and
       wraps onto a second line when it has to. */
    .mb-row-pill { max-width: 100%; white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; border-radius: 12px; }
    /* ===================== end v1.84 R3 ===================== */

    /* =====================================================================
       v1.84 R3b — owner fidelity round (interior transpose + names)
       Presentation-only additions that make the shell + basics + stock
       browser read like the committed Master mockups. The finish-view
       INTERIOR transposes (foil/edge/spotUV/dieCut) ride a render-branch in
       their wizards — deferred to a live-verified slice (see TEARDOWN);
       nothing here touches any engine name=/value or a finish commit path.
       ===================================================================== */

    /* -- (item 7) rail-top BLACK context bar (MAIN v1.84 ~:5445). The R1 fix
          already made .build-context a sticky WHITE header + overflow:clip;
          this reskins the INNER to the mockup's centered black bar. The admin
          Edit-product pill stays visible; the card-type PICKER is the net-new
          customer switcher (owner→Henry) — NOT built here, so no dead control. */
    .build-context { padding: 0 !important; background: #fff !important; border-bottom: 1px solid var(--rail-line, #E2E6EA) !important; }
    .build-context-inner {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 16px;
      min-height: 62px;
      padding: 0 22px;
      background: #000;
      color: #fff;
      border-radius: 0;
    }
    .build-context-copy { display: flex; align-items: baseline; gap: 8px; margin: 0; }
    .build-context-copy .eyebrow {
      margin: 0;
      font-family: Manrope, Helvetica, Arial, sans-serif;
      font-size: 11px;
      font-weight: 900;
      letter-spacing: .16em;
      text-transform: uppercase;
      color: rgba(255,255,255,.62) !important;
    }
    .build-context-title {
      font-family: Manrope, Helvetica, Arial, sans-serif;
      font-size: 15px !important;
      line-height: 1.1;
      letter-spacing: -.01em;
      font-weight: 900;
      color: #fff;
    }
    .cfg-ctx-help {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      font-family: Manrope, Helvetica, Arial, sans-serif;
      font-size: 12px;
      font-weight: 900;
      letter-spacing: .02em;
      color: #fff;
      text-decoration: none;
      border: 1px solid rgba(255,255,255,.34);
      border-radius: 999px;
      padding: 7px 15px;
      white-space: nowrap;
      transition: background .18s ease, border-color .18s ease;
    }
    .cfg-ctx-help:hover { background: rgba(255,255,255,.12); border-color: rgba(255,255,255,.6); color: #fff; }
    /* the admin Edit-product pill inside the black bar → light outline so it reads on black */
    .build-context .cfg-admin-edit { background: rgba(255,255,255,.1); color: #fff; border-color: rgba(255,255,255,.34); }
    .build-context .cfg-admin-edit:hover { background: rgba(255,255,255,.2); color: #fff; }

    /* -- (item 6) MAIN inline basics panels — size + quantity to the mockup grids.
          Fixes the "Cards per setNumber of sets/names" label pile-up: the engine's
          moved <dt>/<dd> husks (option_title_format "Cards per set" + the empty
          quantity/format dds) are CSS-hidden; the real controls live in the moved
          decorated blocks (.order-fields / .size-grid), each with its own label. */
    .inline-config-panel[data-panel="size"] > dt,
    .inline-config-panel[data-panel="quantity"] > dt,
    .inline-config-panel[data-panel="quantity"] > dd { display: none !important; }

    /* size panel → 3-across mockup cards (+ Custom). The .size-grid .choice markup
       (<strong>dim</strong><span>desc</span>) already matches the mockup card body. */
    .inline-config-panel[data-panel="size"] .size-grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 10px;
    }
    .inline-config-panel[data-panel="size"] .size-grid .choice {
      min-height: 72px;
      border: 1px solid #DDE2E7;
      background: #fff;
      border-radius: 10px;
      padding: 14px 16px;
      text-align: left;
      transition: border-color .18s ease, background .18s ease;
    }
    .inline-config-panel[data-panel="size"] .size-grid .choice:hover { background: #EAFBFF; border-color: var(--blue, #00C2FF); }
    .inline-config-panel[data-panel="size"] .size-grid .choice.active {
      background: #F1FBFF; border-color: var(--blue, #00C2FF);
      box-shadow: inset 0 0 0 1px rgba(0,194,255,.26);
    }
    .inline-config-panel[data-panel="size"] .size-grid .choice strong { display: block; font-size: 15px; line-height: 1.15; font-weight: 800; color: #10151A; letter-spacing: -.01em; }
    .inline-config-panel[data-panel="size"] .size-grid .choice span { display: block; margin-top: 5px; font-size: 11px; line-height: 1.2; font-weight: 400; color: #6C7480; }

    /* quantity panel → two labeled control cards ("Quantity" / "Number of sets /
       names"). The .order-field-card already carries label + select. */
    .inline-config-panel[data-panel="quantity"] .order-fields {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 12px;
    }
    .inline-config-panel[data-panel="quantity"] .order-field-card {
      min-height: 88px;
      border: 1px solid #DDE2E7;
      background: #fff;
      border-radius: 12px;
      padding: 16px;
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto;
      align-items: center;
      gap: 14px;
    }
    .inline-config-panel[data-panel="quantity"] .order-field-card label {
      font-size: 14px; line-height: 1.2; font-weight: 700; color: #10151A; letter-spacing: -.01em; margin: 0;
    }
    .inline-config-panel[data-panel="quantity"] .order-field-card select {
      width: 150px; height: 44px; border: 1px solid #DADFE5; border-radius: 8px;
      background: #fff; padding: 0 12px; font-size: 13px; font-weight: 700; color: #10151A;
    }
    @media (max-width: 1180px) {
      .inline-config-panel[data-panel="size"] .size-grid,
      .inline-config-panel[data-panel="quantity"] .order-fields { grid-template-columns: 1fr; }
      .inline-config-panel[data-panel="quantity"] .order-field-card { grid-template-columns: 1fr; }
      .inline-config-panel[data-panel="quantity"] .order-field-card select { width: 100%; }
    }

    /* -- (item 2) STOCK selector-view interior → the Material mockup's 2-col browser
          (family-list + product-panel + material cards). Ported verbatim from
          SilkCards_Master_Material_Stocks_Thickness_configurator_v1.2. The browser is
          built by R3b JS from select[name="paper"] and drives that select exactly as
          the stock decorator does (value + native change). The stock decorator's own
          stacked .cfg-stock-wrap is hidden inside the view (its select is the driver). */
    .cfg-selector-view[data-view="stock"] .cfg-stock-wrap { display: none; }
    .cfg-selector-view[data-view="stock"] .csv-body { padding: 0; }
    .csv-material-browser {
      display: grid;
      grid-template-columns: 132px minmax(0, 1fr);
      min-height: 0;
      height: 100%;
      border-top: 1px solid var(--rail-line, #E2E6EA);
      overflow: hidden;
    }
    .csv-material-browser .csv-family-list { background: #F7F8FA; border-right: 1px solid var(--rail-line, #E2E6EA); overflow: auto; }
    .csv-family-btn {
      width: 100%;
      min-height: 72px;
      border: 0;
      border-bottom: 1px solid var(--rail-line, #E2E6EA);
      background: transparent;
      padding: 12px 10px;
      text-align: center;
      cursor: pointer;
      color: #6A737D;
    }
    .csv-family-btn strong { display: block; font-size: 14.4px; line-height: 1.15; font-weight: 400; letter-spacing: -.01em; color: #6A737D; }
    .csv-family-btn span { display: block; margin-top: 5px; font-size: 12px; font-weight: 400; color: #8B949E; }
    .csv-family-btn.active { background: #E7EBF0; color: #10151A; box-shadow: inset 4px 0 0 var(--blue, #00C2FF); }
    .csv-family-btn.active strong { font-weight: 900; color: #10151A; }
    .csv-family-btn.active span { color: #10151A; }
    .csv-material-panel { min-width: 0; background: #fff; display: flex; flex-direction: column; overflow: auto; }
    .csv-material-head { position: sticky; top: 0; z-index: 4; padding: 14px 16px 12px; border-bottom: 1px solid var(--rail-line, #E2E6EA); background: rgba(255,255,255,.96); backdrop-filter: blur(14px); flex: 0 0 auto; }
    .csv-material-head strong { display: block; font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 15.6px; font-weight: 900; color: #10151A; }
    .csv-material-head span { display: block; margin-top: 3px; font-size: 13.2px; color: #6D7680; line-height: 1.35; }
    .csv-material-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; padding: 14px; }
    /* owner round-12: `display:grid` beat the [hidden] UA rule, so EVERY family's
       thickness cards stacked under whichever family was open — only the selected
       family's real (DB-derived) thicknesses may show */
    .csv-material-grid[hidden] { display: none; }
    /* #6 thickness comparison photo + caption — under the material cards, light rail */
    .csv-thickness-photo { margin: 4px 14px 20px; padding: 0; }
    .csv-thickness-photo img {
      width: 100%; aspect-ratio: 1942 / 809; object-fit: cover; display: block;
      border-radius: 10px; background: #ECEEF1;
    }
    .csv-thickness-photo figcaption {
      text-align: center; margin-top: 10px;
      font: 500 13.5px/1.5 Manrope, Helvetica, Arial, sans-serif;
      letter-spacing: .01em; color: #11151A;
    }
    .csv-thickness-photo .th-accent { color: #008EBB; }
    .csv-thickness-photo.is-empty img { display: none; }
    .csv-thickness-photo.is-empty figcaption { color: #6D7680; font-weight: 400; }
    .csv-material-card {
      min-height: 100px;
      border: 1px solid #D8DEE5;
      background: #fff;
      padding: 9px;
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: 7px;
      text-align: left;
      cursor: pointer;
      transition: border-color .15s ease, background .15s ease;
    }
    .csv-material-card:hover { border-color: #BFC8D2; background: #F8FAFC; }
    .csv-material-card.active { border-color: var(--blue, #00C2FF); background: #F1FBFF; box-shadow: inset 0 0 0 1px rgba(0,194,255,.2); }
    .csv-material-chip { display: block; width: 100%; height: 46px; border-radius: 3px; border: 1px solid rgba(0,0,0,.14); box-shadow: inset 0 1px 0 rgba(255,255,255,.38); background: linear-gradient(135deg, #EEF1F4, #FFFFFF 45%, #DCE3EA); }
    .csv-material-card strong { display: block; color: #5F6973; font-size: 13.2px; line-height: 1.16; font-weight: 400; letter-spacing: -.01em; }
    .csv-material-card em { display: block; margin-top: -2px; color: #69737D; font-size: 10.8px; font-style: normal; font-weight: 400; }
    .csv-material-card.active strong { color: #11151A; font-weight: 900; }
    .csv-material-card.active em { color: #11151A; }
    @media (max-width: 1180px) {
      .csv-material-browser { grid-template-columns: 110px 1fr; height: auto; }
      .csv-material-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    }
    /* ===================== end v1.84 R3b ===================== */

    /* =====================================================================
       v1.84 R3b — finish selector-view INTERIORS (items 1/3/4/5)
       Ported (namespaced under .cfg-selector-view) from the committed Master
       selector mockups: Foil v1.4 / Spot_UV / Die_Cut / Edge_Finishing v1.1.
       Presentation only — the wizards' model/commit paths are untouched; these
       style the render-branch DOM each wizard emits when its panel lives inside
       a .cfg-selector-view. No engine name=/value is touched by any of this.
       ===================================================================== */
    /* finish browsers go edge-to-edge like the mockup rail */
    .cfg-selector-view[data-view="opt-281"] .csv-body,
    .cfg-selector-view[data-view="opt-23"]  .csv-body,
    .cfg-selector-view[data-view="opt-229"] .csv-body,
    .cfg-selector-view[data-view="opt-236"] .csv-body { padding: 0; }
    /* ...and so does ANY view holding the die-cut list (2026-09-30): the rule above names the
       business-card ids, so the same list on postcards (381), hang tags (439) and stickers (37)
       sat 18px in from both rail edges. Keyed by what the view holds, not by another id. */
    .cfg-selector-view .csv-body:has(.cfg-dc-panel) { padding: 0; }
    /* ...and the same for the other three screens the id list names — foil, Spot UV, edges
       (2026-09-30): eXp's own foil (533) and edge (525) screens, and every other product's
       copies, sat 18px in, which cut the foil card's name to "G…". Emboss, corners and
       perforation are not in the list and keep their inset everywhere. */
    .cfg-selector-view .csv-body:has(.cfg-fo-panel),
    .cfg-selector-view .csv-body:has(.cfg-uv-panel),
    .cfg-selector-view .csv-body:has(.cfg-edge-panel) { padding: 0; }
    .cfg-selector-view .cfg-foil-panel { display: block; }

    /* shared cyan-bar section title */
    .cfg-selector-view .cfg-foil-panel .section-title {
      padding: 14px 20px 12px; margin: 0;
      font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 14.4px; font-weight: 900;
      text-transform: uppercase; letter-spacing: .14em; color: #10151A;
      display: flex; align-items: center; gap: 10px;
    }
    .cfg-selector-view .cfg-foil-panel .section-title:before {
      content: ""; width: 4px; height: 17px; border-radius: 99px;
      background: var(--blue, #00C2FF); box-shadow: 0 0 12px rgba(0,194,255,.32); flex: 0 0 auto;
    }

    /* ---- FOIL: placement strip + tabs ---- */
    .cfg-selector-view .placement-strip { border-bottom: 1px solid var(--line, #E2E6EA); background: #FAFBFC; }
    .cfg-selector-view .placement-tabs { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 8px; padding: 0 16px 16px; }
    .cfg-selector-view .placement-tab {
      position: relative; min-height: 108px; border: 1px solid #D5DBE2; background: #fff; padding: 12px 8px 10px;
      cursor: pointer; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 7px;
      text-align: center; transition: border-color .18s ease, background .18s ease, box-shadow .18s ease;
    }
    .cfg-selector-view .placement-tab.active { border-color: var(--blue, #00C2FF); background: #F1FBFF; box-shadow: inset 0 0 0 1px rgba(0,194,255,.22); }
    .cfg-selector-view .placement-tab.is-locked { opacity: .62; background: #F4F6F8; cursor: help; }
    .cfg-selector-view .placement-tab strong { font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 13.2px; font-weight: 900; line-height: 1.1; color: #11151A; }
    .cfg-selector-view .placement-tab > span:not(.mini-layer-icon) { font-size: 12px; line-height: 1.25; color: #68727D; font-style: italic; }
    .cfg-selector-view .mini-layer-icon { width: 54px; height: 32px; display: grid; align-content: center; gap: 4px; }
    .cfg-selector-view .mini-layer-icon i { display: block; height: 5px; border-radius: 99px; background: #E8EDF2; border: 1px solid #AAB4BF; transform: skewX(-25deg); }
    /* each card lights ITS OWN bar, in blue (owner 2026-10-01: "change all highlights to blue and
       highlight the middle [layer] in the middle card"). Before, the top bar was the default, so
       Card Front and Mid Layer drew the same icon, and Card Back's bar was gold. */
    .cfg-selector-view .mini-layer-icon.front i:first-child,
    .cfg-selector-view .mini-layer-icon.mid i:nth-child(2),
    .cfg-selector-view .mini-layer-icon.back i:last-child { background: #65DFFF; border-color: #0AAFE5; }
    .cfg-selector-view .mini-layer-icon.locked.front i:first-child,
    .cfg-selector-view .mini-layer-icon.locked.mid i:nth-child(2),
    .cfg-selector-view .mini-layer-icon.locked.back i:last-child { background: #D5DBE2; border-color: #B9C1CA; }

    /* ---- FOIL browser: family(type) list + color grid ---- */
    .cfg-selector-view .foil-browser { display: grid; grid-template-columns: 122px minmax(0,1fr); border-bottom: 1px solid var(--line, #E2E6EA); }
    .cfg-selector-view .family-list { background: #F7F8FA; border-right: 1px solid var(--line, #E2E6EA); }
    .cfg-selector-view .family-btn { width: 100%; min-height: 68px; border: 0; border-bottom: 1px solid var(--line, #E2E6EA); background: transparent; padding: 12px 10px; text-align: center; cursor: pointer; color: #6A737D; }
    .cfg-selector-view .family-btn strong { display: block; font-family: 'Manrope', Helvetica, Arial, sans-serif; font-size: 14.4px; line-height: 1.15; font-weight: 400; letter-spacing: -.01em; color: #6A737D; }
    .cfg-selector-view .family-btn span { display: block; margin-top: 5px; font-size: 12px; font-weight: 400; color: #8B949E; }
    .cfg-selector-view .family-btn.active { background: #E7EBF0; box-shadow: inset 4px 0 0 var(--blue, #00C2FF); }
    .cfg-selector-view .family-btn.active strong { font-weight: 900; color: #10151A; }
    .cfg-selector-view .family-btn.active span { color: #10151A; }
    .cfg-selector-view .foil-scroll { min-width: 0; background: #fff; display: flex; flex-direction: column; }
    .cfg-selector-view .foil-head { padding: 12px 16px; border-bottom: 1px solid var(--line, #E2E6EA); }
    .cfg-selector-view .foil-head strong { display: block; font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 15.6px; font-weight: 900; color: #10151A; }
    .cfg-selector-view .foil-head span { display: block; margin-top: 3px; font-size: 13.2px; color: #6D7680; }
    /* AT MOST FOUR ACROSS, FEWER WHEN A CARD WOULD BE NARROWER THAN 84px (2026-10-01, the
       gutter census: scratchpad/cfg56-gutter-census.js). The rail is 30vw, so at 1200–1440 wide
       the grid has ~280px and four fixed columns made 63px cards with 45px for the name:
       "Lavender" and "Pearlescent" ran past the card's own border on every builder that sells
       foil. The second term keeps four columns wherever four fit (a wide rail, the owner's
       screen); below that the grid drops to three. The name may also break inside a word as a
       last resort, so no color name can leave its card at any width. */
    .cfg-selector-view .foil-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(max(84px, calc((100% - 30px) / 4)), 1fr)); gap: 10px; padding: 14px; }
    .cfg-selector-view .foil-card strong,
    .cfg-selector-view .foil-card em,
    .cfg-selector-view .edge-card strong { overflow-wrap: anywhere; min-width: 0; max-width: 100%; }
    .cfg-selector-view .foil-card { min-height: 110px; border: 1px solid #D8DEE5; background: #fff; padding: 9px; display: flex; flex-direction: column; gap: 7px; text-align: left; cursor: pointer; transition: border-color .15s ease, background .15s ease; }
    .cfg-selector-view .foil-card:hover { border-color: #BFC8D2; background: #F8FAFC; }
    .cfg-selector-view .foil-card.active { border-color: var(--blue, #00C2FF); background: #F1FBFF; box-shadow: inset 0 0 0 1px rgba(0,194,255,.2); }
    .cfg-selector-view .foil-card strong { display: block; color: #5F6973; font-size: 13.2px; line-height: 1.16; font-weight: 400; letter-spacing: -.01em; }
    .cfg-selector-view .foil-card em { display: block; margin-top: -2px; color: #69737D; font-size: 10.8px; font-style: normal; font-weight: 400; }
    .cfg-selector-view .foil-card.active strong { color: #11151A; font-weight: 900; }
    .cfg-selector-view .foil-card.active em { color: #11151A; }
    .cfg-selector-view .foil-chip { display: block; width: 100%; height: 52px; border-radius: 3px; border: 1px solid rgba(0,0,0,.14); box-shadow: inset 0 1px 0 rgba(255,255,255,.38); }
    .cfg-selector-view .add-foil-action,
    .cfg-selector-view .additional-btn {
      width: 100%; min-height: 54px; border: 0; border-top: 1px solid var(--line, #E2E6EA); background: #F6F8FA; color: #11151A;
      font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: .04em;
      cursor: pointer; display: flex; align-items: center; justify-content: center;
    }
    .cfg-selector-view .add-foil-action:hover,
    .cfg-selector-view .additional-btn:hover { background: #EEF9FD; color: #007EA8; }
    /* the same bar at the TOP of the foil screen (2026-10-01): the line goes under it, not over.
       It stays pinned to the top of the scrolling column: a color is picked far down the grid,
       and the screen keeps its scroll position when it redraws, so a bar that scrolled with the
       page was out of sight at the moment a foil was finished (measured: 81px above the column). */
    .cfg-selector-view .add-foil-action.cfg-fo-add-top,
    .cfg-selector-view .additional-btn.cfg-fo-add-top {   /* the Spot UV and die-cut screens' bar: same place, same pin */
      border-top: 0; border-bottom: 1px solid var(--line, #E2E6EA);
      position: sticky; top: 0; z-index: 3;
    }
    .cfg-selector-view .cfg-foil-panel { scroll-margin-top: 12px; }   /* where the whole screen is the scroller (under 1180px) an added foil starts 12px below the window's top, not against it */

    /* ---- completed-setup summary rows (above the browser) ---- */
    .cfg-selector-view .cfg-fv-summary { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-bottom: 1px solid var(--line, #E2E6EA); background: #FCFDFE; flex-wrap: wrap; }
    .cfg-selector-view .cfg-fv-eyebrow { font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 10px; font-weight: 900; letter-spacing: .14em; text-transform: uppercase; color: #8B949E; }
    .cfg-selector-view .cfg-fv-name { display: flex; align-items: center; gap: 8px; font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 13px; font-weight: 900; color: #11151A; }
    .cfg-selector-view .cfg-fv-chip { display: inline-block; width: 20px; height: 20px; border-radius: 4px; border: 1px solid rgba(0,0,0,.14); }
    .cfg-selector-view .cfg-fv-chip.cfg-fv-dcicon { border: 0; width: 26px; height: 20px; }
    .cfg-selector-view .cfg-fv-dcicon svg { width: 26px; height: 20px; display: block; }
    .cfg-selector-view .cfg-fv-link { margin-left: auto; border: 0; background: transparent; cursor: pointer; font-size: 12px; font-weight: 800; color: var(--blue-dark, #0090c4); text-decoration: underline; padding: 2px 4px; }
    .cfg-selector-view .cfg-fv-remove { color: #9A9A9A; margin-left: 0; }

    /* ---- SPOT UV + DIE CUT: THE FOIL SCREEN'S LOOK (owner 2026-10-02) ----
       "How about making it match the foil look? I like consistency" — then "yes. types first.
       shape cut on its own row." Each browser is ONE COLUMN: a "Browse …" heading, the types as
       picture tiles (the foil color tile's numbers — .foil-card, .foil-chip), then "Where does
       this … go?" with foil's compact cards (.placement-tab's numbers) across the full width.
       Before: a 150–160px type column on the left left each card 70px wide at a laptop width —
       every name on two lines, the layer picture 18px wider than its card. Now 127px, foil's.
       Types come first because both screens need the type first (GOTCHAS #165).
       The same at every width: the phone block below only tightens the side padding. */
    .cfg-selector-view .uv-browser,
    .cfg-selector-view .diecut-browser { display: flex; flex-direction: column; border-bottom: 1px solid var(--line, #E2E6EA); }
    .cfg-selector-view .type-list { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 10px; padding: 0 16px 16px; background: #fff; }
    .cfg-selector-view .type-btn { min-width: 0; min-height: 110px; border: 1px solid #D8DEE5; background: #fff; padding: 9px; display: flex; flex-direction: column; gap: 7px; text-align: left; cursor: pointer; color: #5F6973; transition: border-color .15s ease, background .15s ease; }
    .cfg-selector-view .type-btn:hover { border-color: #BFC8D2; background: #F8FAFC; }
    .cfg-selector-view .type-btn strong { display: block; font-family: 'Manrope', Helvetica, Arial, sans-serif; font-size: 13.2px; line-height: 1.16; font-weight: 400; letter-spacing: -.01em; color: #5F6973; }
    .cfg-selector-view .type-btn > span { display: block; margin-top: -2px; font-size: 10.8px; font-weight: 400; color: #69737D; line-height: 1.25; }
    .cfg-selector-view .type-btn.active { border-color: var(--blue, #00C2FF); background: #F1FBFF; box-shadow: inset 0 0 0 1px rgba(0,194,255,.2); }
    .cfg-selector-view .type-btn.active strong { font-weight: 900; color: #11151A; }
    .cfg-selector-view .type-btn.active > span { color: #11151A; }
    /* a type's picture: a background for a Spot UV type (uvBg), the cut icon for a die cut (cfgDcIcon) */
    .cfg-selector-view .type-chip { display: block; flex: 0 0 auto; width: 100%; height: 52px; border-radius: 3px; border: 1px solid rgba(0,0,0,.14); box-shadow: inset 0 1px 0 rgba(255,255,255,.38); }
    .cfg-selector-view .type-chip.is-icon { border: 0; box-shadow: none; }
    .cfg-selector-view .type-chip svg { display: block; width: 100%; height: 52px; }
    .cfg-selector-view .placement-panel { min-width: 0; background: #FAFBFC; border-top: 1px solid var(--line, #E2E6EA); display: flex; flex-direction: column; }
    .cfg-selector-view .product-head { padding: 16px 20px 14px; border-bottom: 1px solid var(--line, #E2E6EA); background: #fff; }
    /* the "choose a type" line is the last thing in its browser, whose own bottom line closes it */
    .cfg-selector-view .cfg-uv-needtype,
    .cfg-selector-view .cfg-dc-needshape { border-bottom: 0; }
    .cfg-selector-view .product-head strong { display: block; font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 15.6px; font-weight: 900; color: #10151A; }
    .cfg-selector-view .product-head > span { display: block; margin-top: 5px; font-size: 13.2px; color: #6D7680; line-height: 1.35; }
    .cfg-selector-view .product-head .section-title { padding: 0 0 6px; }
    .cfg-selector-view .placement-grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 8px; padding: 0 16px 16px; }
    .cfg-selector-view .placement-card {
      position: relative; min-height: 108px; border: 1px solid #D5DBE2; background: #fff; padding: 12px 8px 10px; cursor: pointer;
      display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 7px; text-align: center;
      transition: border-color .18s ease, background .18s ease, box-shadow .18s ease;
    }
    .cfg-selector-view .placement-card.active { border-color: var(--blue, #00C2FF); background: #F1FBFF; box-shadow: inset 0 0 0 1px rgba(0,194,255,.22); }
    .cfg-selector-view .placement-card.is-locked { opacity: .62; background: #F4F6F8; cursor: help; }
    .cfg-selector-view .placement-card strong { font-family: Manrope, Helvetica, Arial, sans-serif; font-size: 13.2px; font-weight: 900; line-height: 1.1; color: #11151A; }
    .cfg-selector-view .placement-card .micro { font-size: 12px; line-height: 1.25; color: #68727D; font-style: italic; }
    /* SHAPE CUT IS NOT A LAYER: it cuts through the whole card, so its icon lights all three bars
       and it sits on a row of its own, with Front / Middle / Back below it as foil's three cards
       (owner 2026-10-02: "shape cut on its own row"; four in one row left 93px a card). */
    .cfg-selector-view .placement-card .mini-layer-icon.thru i { background: #65DFFF; border-color: #0AAFE5; }
    .cfg-selector-view .placement-card .mini-layer-icon.thru.locked i { background: #D5DBE2; border-color: #B9C1CA; }
    .cfg-selector-view .placement-card.thru { grid-column: 1 / -1; min-height: 0; flex-direction: row; text-align: left; gap: 12px; padding: 12px 14px; }

    /* ---- EDGE: method(family) list + color-dot grid ---- */
    .cfg-selector-view .edge-browser { display: grid; grid-template-columns: 128px minmax(0,1fr); border-bottom: 1px solid var(--line, #E2E6EA); }
    .cfg-selector-view .edge-right .product-head { display: flex; flex-direction: column; gap: 6px; }
    .cfg-selector-view .edge-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(max(84px, calc((100% - 30px) / 4)), 1fr)); gap: 10px; padding: 14px; }   /* same rule as .foil-grid: "Fluorescent - Blue" ran 3px past its card */
    /* NO WORD OF A COLOR NAME SPLITS ACROSS LINES (owner 2026-10-02: "make sure fluorescent stays
       on 1 line" — the cards read "Fluorescen / t - Hot Pink"). The card's narrowest width is 84px;
       at 13.2px with 9px side padding "Fluorescent" and "Pearlescent" were one letter too wide (12
       of the 61 names split, picked or not). 5px side padding + 12.4px fits every word of all 61
       at 1200 / 1440 / 2550, in the regular and the picked weight. overflow-wrap:anywhere (above)
       stays as the last resort for a name longer than any sold today. */
    .cfg-selector-view .edge-card { min-height: 108px; border: 1px solid #D8DEE5; background: #fff; padding: 9px 5px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px; text-align: center; cursor: pointer; transition: border-color .15s ease, background .15s ease; }
    .cfg-selector-view .edge-card:hover { border-color: #BFC8D2; background: #F8FAFC; }
    .cfg-selector-view .edge-card.active { border-color: var(--blue, #00C2FF); background: #F1FBFF; box-shadow: inset 0 0 0 1px rgba(0,194,255,.2); }
    .cfg-selector-view .edge-card strong { display: block; color: #5F6973; font-size: 12.4px; line-height: 1.16; font-weight: 400; letter-spacing: -.01em; }
    .cfg-selector-view .edge-card.active strong { color: #11151A; font-weight: 900; }
    .cfg-selector-view .edge-dot { display: block; width: 42px; height: 42px; border-radius: 50%; border: 1px solid rgba(0,0,0,.12); box-shadow: inset 0 1px 0 rgba(255,255,255,.38); }
    /* configurator 44 — Colored Edges splits into PAINTED and FOIL (owner 2026-09-22). The kind
       heading labels a group of method buttons; it is not a button itself. */
    /* Owner 2026-09-24 ("they blend in too much"), option B of three shown: the configurator's
       own section-heading look — the .sub-header blue bar (shared rule above) + dark bold caps —
       so the kind reads as a heading, not as one more grey option.
       Owner 2026-09-25 ("the double lines look odd … the space between the category and the
       option looks odd"), option B of three shown: in the selector view the heading is its OWN
       ROW — a tint between the list (#F7F8FA) and a picked button (#E7EBF0), closed by the same
       1px line every button carries — so there is ONE line between any two rows, never two, and
       no floating gap above or below the heading. Custom (ungrouped) is set off by an 8px strip
       of the same tint instead of a margin. */
    .cfg-edge-kind { display: flex; align-items: center; gap: 8px; padding: 12px 10px 8px; font-size: 11px; line-height: 1.2; font-weight: 900; letter-spacing: .16em; text-transform: uppercase; color: var(--ink, #11151A); text-align: left; }
    .cfg-edge-kind::before { height: 16px; }
    .cfg-selector-view .family-list .cfg-edge-kind { padding: 9px 10px; background: #EDF0F3; border-bottom: 1px solid var(--line, #E2E6EA); }
    /* the strip before Custom: 8px of heading tint, closed by the row line (an inset shadow sits
       under the border, so the one line is directly above Custom's label) */
    .cfg-selector-view .family-btn.cfg-edge-sub + .family-btn:not(.cfg-edge-sub) { border-top: 8px solid #EDF0F3; box-shadow: inset 0 1px 0 var(--line, #E2E6EA); }
    .cfg-selector-view .family-btn.cfg-edge-sub + .family-btn:not(.cfg-edge-sub).active { box-shadow: inset 4px 0 0 var(--blue, #00C2FF), inset 0 1px 0 var(--line, #E2E6EA); }
    .cfg-edge-method-row + .cfg-edge-kind, .panel-body > .cfg-edge-kind, .cfg-edge-panel > .cfg-edge-kind { padding: 12px 0 8px; }
    /* a foil method while rounded corners / a shaped die cut is on — greyed, with the reason in
       ONE note under the browser (.cfg-edge-straight-note, the .cfg-place-note look) */
    .cfg-selector-view .family-btn.is-locked, .cfg-selector-view .family-btn.is-locked:hover { background: #F4F6F8; cursor: not-allowed; box-shadow: none; }
    .cfg-selector-view .family-btn.is-locked strong { color: #9AA3AC; }
    .cfg-selector-view .family-btn.is-locked span { color: #6D7680; font-style: italic; }
    .edge-method.is-locked, .edge-method.is-locked:hover { background: #F4F6F8; border-color: var(--line); color: #9AA3AC; cursor: not-allowed; }
    .cfg-edge-panel > .cfg-edge-straight-note { padding: 0 14px 12px; }
    /* A FREE-TEXT choice's field (configurator 44) — the edge wizard's Custom colour and the stock
       picker's "other" stock. The engine draws its own box for these ("other" values) inside the
       raw controls the branded pickers hide; the pickers now show this field and write into the
       engine's box. Values ported verbatim from .inline-config-panel.cfg-shell-carded
       input.variabledata (R5b). */
    .cfg-freetext { padding: 4px 14px 16px; }
    .cfg-freetext-label { display: block; margin: 0 0 6px; font-size: 12.5px; font-weight: 700; color: var(--ink, #11151A); }
    .cfg-freetext-input { width: 100%; box-sizing: border-box; padding: 11px 12px; border: 1px solid var(--line, #E4E7EB); border-radius: 10px; background: #fff; font-size: 14px; font-weight: 700; color: var(--ink, #11151A); font-family: inherit; }
    .cfg-freetext-input:focus { outline: none; border-color: var(--blue, #00C2FF); box-shadow: 0 0 0 3px rgba(0,194,255,.16); }
    .cfg-freetext-hint { margin: 8px 0 0; font-size: 12.5px; line-height: 1.5; color: #6B6B6B; }

    /* selector-view finish browsers collapse cleanly on the ported @1180 breakpoint */
    @media (max-width: 1180px) {
      .cfg-selector-view .foil-grid,
      .cfg-selector-view .edge-grid { grid-template-columns: repeat(3, minmax(0,1fr)); }
      /* foil's three placement cards stay three across here too (2026-10-02). They were one per
         row between 701 and 1180px only — 968px wide each at a 1000px window, 340px of height —
         while the phone layout below and the desktop layout above both draw them three across,
         and the Spot UV and die-cut screens now draw the same cards three across at every width. */
    }
    /* ===================== end v1.84 R3b finish interiors ===================== */

    /* =====================================================================
       v1.84 R3c — owner round 3 (2026-07-17): rail-row label hygiene
       ===================================================================== */
    /* the option's short description = its own muted line under the name
       (the row label itself is now the clean option name only) */
    .main-builder-option .mb-row-note{display:block;flex-basis:100%;order:2;font-size:12px;line-height:1.3;color:#6D7680;font-weight:400;margin-top:2px}
    /* an OPEN inline panel's raw engine <dt> duplicated the row label
       ("ArtWork" twice, owner-caught) — hide the duplicated icon/name/price,
       keep the dt's functional controls (on/off checkbox for undedecorated
       finishes) compact + right-aligned */
    .inline-config-panel > dt .finish-icon,
    .inline-config-panel > dt .cfg-finish-copy,
    .inline-config-panel > dt .option_parent_price{display:none!important}
    .inline-config-panel > dt.cfg-finish-row{background:transparent;border:0;box-shadow:none;padding:6px 24px 0;min-height:0}

    /* item 1 (owner round 3): rows showed through the STRIP between the scrolled
       site-nav's bottom and the context bar's sticky pin line (nav height varies
       by viewport; the strip = pin(92) − nav bottom). Mask it with a white cover
       anchored ABOVE the pinned bar: nav (z-80) covers its own region, the mask
       (z-35 with the bar) covers the remainder; at scroll 0 .builder's
       overflow:clip crops the mask to the card, so nothing leaks. */
    .build-context::before{content:'';position:absolute;left:0;right:0;bottom:100%;height:120px;background:#fff}
    /* item 5 (owner round 3) + round 5: the white padding under the last rail
       row read as a dead gray band (owner-circled) — 130→16px helped but the
       residual seam remained: the card's bottom radius + border + drop shadow
       over the column padding still drew a visible edge above the footer. The
       mockup never shows this edge because its column is viewport-locked
       (inner-scroll, retired here for the iPad single-scroller); under page
       flow the card must instead run FLUSH into the footer — no padding, no
       bottom radius/border, and flex-fill so a taller left panel can't reopen
       the gap. */
    .builder-column{padding-bottom:0}
    .builder{flex:1 0 auto;border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom:0}
    /* item 3 (owner round 3): completion state in the foil view — compact card
       + explicit "add another?" ask (restores the progressive wizard's UX) */
    .cfg-selector-view .cfg-fv-addask{margin:18px 22px 22px;padding:18px 20px;border:1px solid var(--line,#E2E6EA);background:#F7F9FA;border-radius:12px}
    .cfg-selector-view .cfg-fv-addask strong{display:block;font-family:Manrope,Helvetica,Arial,sans-serif;font-size:15px;font-weight:800;color:#11151A}
    .cfg-selector-view .cfg-fv-addask > span{display:block;font-size:12.5px;color:#6D7680;margin:4px 0 12px}
    /* The "Add another …?" blocks lost their explanatory sub-line (owner 2026-08-19 —
       Henry: pricing mechanics in the buyer's face is the old site's problem). That
       <span> was carrying the gap between the heading and the button via the rule
       above, so with it gone the two would sit flush. Restored on the exact shape the
       removal creates — a <strong> directly followed by the button — which leaves
       every block that still HAS a sub-line untouched. */
    .cfg-selector-view .cfg-fv-addask strong + .cfg-fv-addask-btn{margin-top:12px}
    .cfg-selector-view .cfg-fv-addask-btn{display:block;width:100%;margin:0 0 8px}
    .cfg-selector-view .cfg-fv-addask-done{display:block;font-size:12px;color:#8B949E;text-align:center}
    /* item 3 (owner round 4): single-instance completion (Edge Finishing) — no
       "add another" button, so the sub-line needs no bottom gap before nothing */
    .cfg-selector-view .cfg-fv-addask-single > span{margin:4px 0 0}
    .cfg-selector-view .cfg-foil-panel > .cfg-finish-card{margin:18px 22px 0}

    /* =====================================================================
       v1.84 R4 — receipt bar (v1.83 boxed) + slide-up Build Drawer
       Ported verbatim (namespaced) from the MAIN mockup `v183-build-drawer`
       block. Bar + drawer data come from the existing summary registry
       (#cfg-summary-grid / #cfg-summary-cats) + the engine total mirror
       (#configure-price-preview) — NO new price math. The drawer is moved
       INSIDE #shoppingform at runtime (containment) + re-homes both engine
       action proxies. The v1.45 sidebar was already retired above
       (.preview-summary display:none).
       ===================================================================== */
    /* --- receipt bar (overrides the R1 flat-cell .build-bar shape) --- */
    .build-bar { display: block !important; grid-template-columns: none !important; gap: 0 !important; padding: 0 !important; min-height: 0 !important; background: rgba(255,255,255,.94) !important; backdrop-filter: blur(22px); }
    .build-bar .bb-inner { display: grid; grid-template-columns: minmax(250px,.9fr) minmax(480px,1.55fr) 240px 180px; gap: 22px; align-items: center; padding: 13px 28px; }
    .bb-title .bb-kicker { font-size: 13px; font-weight: 900; letter-spacing: .18em; color: #8e8e8e; text-transform: uppercase; margin-bottom: 3px; font-family: var(--heading-font); }
    .bb-title > strong { font-size: 21px; letter-spacing: -.025em; display: block; font-family: var(--heading-font); font-weight: 900; color: #11151A; }
    .bb-title .bb-sub { display: block; color: #777; font-size: 13.5px; margin-top: 3px; font-weight: 600; }
    .bb-details-btn { border: 0; background: transparent; padding: 0; font-size: 13.5px; font-weight: 900; color: var(--blue,#00C2FF); cursor: pointer; margin-top: 5px; font-family: var(--heading-font); }
    .bb-details-btn:hover { text-decoration: underline; text-underline-offset: 3px; }
    .bb-receipt { display: grid; grid-template-columns: repeat(5,1fr); border: 1px solid #e3e3e3; border-radius: 14px; overflow: hidden; background: #fafafa; }
    .bb-ritem { padding: 10px 13px; border-right: 1px solid #e3e3e3; min-width: 0; }
    .bb-ritem:last-child { border-right: 0; }
    .bb-ritem > span { display: block; font-size: 12.5px; font-weight: 900; color: #8f8f8f; letter-spacing: .12em; text-transform: uppercase; margin-bottom: 4px; white-space: nowrap; font-family: var(--heading-font); }
    .bb-ritem > strong { display: block; font-size: 15.5px; letter-spacing: -.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: #11151A; }
    .bb-ritem > strong.bb-more { color: #00769a; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-transform: uppercase; font-size: 14px; letter-spacing: .04em; font-weight: 900; }
    .bb-pricebox { justify-self: end; text-align: right; }
    .bb-pricebox .bb-plabel { font-size: 13px; color: #888; font-weight: 900; letter-spacing: .14em; text-transform: uppercase; font-family: var(--heading-font); }
    .bb-pricebox .bb-pvalue { font-size: 27px; font-weight: 900; letter-spacing: -.05em; margin-top: 2px; color: #11151A; font-family: var(--heading-font); line-height: 1.05; }
    .bb-pricebox .bb-pnote { font-size: 13px; color: #777; font-weight: 650; }
    .bb-actions { display: grid; gap: 7px; }
    /* Tighter stack while the quote pair is up, so the bar grows as little as possible
       (see the .bb-quote block below for the measured before/after). */
    .bb-actions:has(.bb-quote:not(.d-none)) { gap: 5px; }
    .bb-actions .bb-add { height: 52px; border: 0; border-radius: 999px; background: var(--blue,#00C2FF); color: #030303; font-weight: 900; font-size: 15px; box-shadow: 0 14px 28px rgba(0,194,255,.24); cursor: pointer; font-family: var(--heading-font); }
    /* The blue CTA's hover was `filter:brightness(1.07)` — a shade, effectively
       invisible (owner 2026-09-02, "make the hover over the blue CTA more obvious").
       ⛔ THIS IS A PORT, NOT A DESIGN. The site already has one blue-CTA hover and it
       is single-homed at `henry_overview_v2.css:3170` on `.families-build-cta` /
       `.families-sample-cta` / `.cta-glass` — the hero "Build My Card" pair on all five
       overview pages. Values copied verbatim: the blue does NOT change, the signal is a
       4px light-blue halo ring + a deeper blue glow + a 2px lift.
       An earlier version of this rule invented a darken-to-`--blue-dark` treatment
       instead of grepping for the existing one (owner-caught: "I don't like the dark
       blue. why didn't we use what was already built before?"). It also had to keep a
       contrast note, because darkening the background made the label a live question —
       a problem this treatment does not have at all, since the background never moves
       (near-black on `--blue` measures 9.98:1 at rest and on hover).
       Applied to whichever button is the blue pill: Add to Cart on a priceable build,
       Request Quotation on a Price-TBD one — same role, same treatment.
       ⚠️ If the overview rule changes, change this one with it. */
    .bb-actions .bb-add, .bb-actions .bb-quote { transition: background .25s ease, box-shadow .25s ease, border-color .25s ease, color .25s ease, transform .2s ease; }
    .bb-actions .bb-add:hover, .bb-actions .bb-add:focus-visible {
      background: var(--blue,#00C2FF); filter: none;
      box-shadow: 0 0 0 4px rgba(0,194,255,.22), 0 8px 26px rgba(0,194,255,.40);
      transform: translateY(-2px);
    }
    .bb-actions .bb-save { border: 0; background: transparent; color: #555; font-weight: 800; font-size: 14px; cursor: pointer; font-family: var(--font); }
    .bb-actions .bb-save:hover { color: var(--blue-dark,#008EBB); text-decoration: underline; }
    /* Request Quotation sits ABOVE Add to Cart with an OR between them — the old live
       site's pairing (owner-directed 2026-09-02). Both stay visible on a Price-TBD
       build; the pair is d-none at every other time (mirrored from #addtoquote-btn).
       REQUEST QUOTATION IS THE PRIMARY ACTION on a Price-TBD build (owner-directed
       2026-09-02, "Request Quotation is what we want people to do"), so it takes the
       filled-blue pill and Add to Cart drops to a quiet text link beneath it.
       ⛔ The quiet link is ALWAYS VISIBLE, never hover-to-reveal: `hover` does not
       exist on a touch device, so a hover-revealed Add to Cart would be unreachable on
       a phone — and it is a real purchase path, not decoration. Hover only strengthens
       it (darkens + underlines). This still buys back most of the height: the bar
       measured 80px priced / 140px TBD before this, and the text link plus the tighter
       gaps remove ~30px of that jump. */
    .bb-actions .bb-quote { height: 44px; border: 0; border-radius: 999px; background: var(--blue,#00C2FF); color: #030303; font-weight: 900; font-size: 15px; box-shadow: 0 14px 28px rgba(0,194,255,.24); cursor: pointer; font-family: var(--heading-font); }
    /* Same ported overview treatment as .bb-add:hover above — see that block. */
    .bb-actions .bb-quote:hover, .bb-actions .bb-quote:focus-visible {
      background: var(--blue,#00C2FF); filter: none;
      box-shadow: 0 0 0 4px rgba(0,194,255,.22), 0 8px 26px rgba(0,194,255,.40);
      transform: translateY(-2px);
    }
    .bb-actions .bb-or { text-align: center; font-size: 11px; line-height: 1; font-weight: 800; letter-spacing: .16em; color: #A8A29A; font-family: var(--heading-font); }
    /* Only while the quote button is showing. On every priceable build .bb-quote is
       d-none, this rule does not match, and Add to Cart keeps the blue pill it has
       always had — the selector IS the state check. Specificity (0,3,0) beats the
       compact-desktop media rule's (0,2,0) `.bb-actions .bb-add`, which is what sets
       the 44px height there. */
    .bb-actions .bb-quote:not(.d-none) ~ .bb-add {
      height: 26px; border: 0; border-radius: 0; background: transparent; color: #6F6F6F;
      font-weight: 800; font-size: 13px; box-shadow: none; padding: 0;
      font-family: var(--font); cursor: pointer;
    }
    .bb-actions .bb-quote:not(.d-none) ~ .bb-add:hover { color: #11151A; text-decoration: underline; filter: none; }

    /* --- overlay + slide-up drawer --- */
    .bd-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.42); z-index: 1290; opacity: 0; pointer-events: none; transition: opacity .22s ease; }
    .bd-drawer { position: fixed; left: 0; right: 0; bottom: 0; z-index: 1300; background: #fff; border-radius: 28px 28px 0 0; box-shadow: 0 -34px 90px rgba(0,0,0,.28); transform: translateY(105%); transition: transform .28s ease; max-height: 80vh; display: flex; flex-direction: column; overflow: hidden; font-family: var(--font); }
    body.cfg-drawer-open .bd-overlay { opacity: 1; pointer-events: auto; }
    body.cfg-drawer-open .bd-drawer { transform: translateY(0); }
    .bd-head { display: grid; grid-template-columns: 1fr auto; gap: 20px; align-items: start; padding: 24px 32px 18px; border-bottom: 1px solid #E7E7E7; flex: 0 0 auto; }
    .bd-head .bd-kicker { font-size: 13px; font-weight: 900; letter-spacing: .18em; text-transform: uppercase; color: #999; margin-bottom: 6px; font-family: var(--heading-font); }
    .bd-head h2 { font-size: 26px; letter-spacing: -.04em; margin: 0; font-family: var(--heading-font); font-weight: 900; color: #11151A; }
    .bd-head p { margin: 6px 0 0; color: #676767; font-size: 14.5px; }
    .bd-close { width: 42px; height: 42px; border-radius: 50%; border: 1px solid #ddd; background: #fff; font-size: 26px; line-height: 1; cursor: pointer; flex: 0 0 auto; }
    .bd-body { padding: 24px 32px 32px; overflow: auto; background: #fbfbfa; flex: 1 1 auto; min-height: 0; }
    .bd-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 18px; align-items: start; }
    .bd-panel { background: #fff; border: 1px solid #e7e7e7; border-radius: 20px; box-shadow: 0 12px 28px rgba(0,0,0,.045); overflow: hidden; }
    .bd-panel h3 { font-size: 16.5px; letter-spacing: -.02em; margin: 0; padding: 16px 18px; background: #f5f5f3; border-bottom: 1px solid #e7e7e7; display: flex; justify-content: space-between; gap: 10px; align-items: center; font-family: var(--heading-font); font-weight: 900; color: #11151A; }
    .bd-panel h3 span { font-size: 12.5px; color: #888; letter-spacing: .08em; text-transform: uppercase; font-weight: 900; }
    .bd-row { display: grid; grid-template-columns: 120px 1fr auto; gap: 14px; padding: 13px 18px; border-bottom: 1px solid #efefef; align-items: start; }
    .bd-row:last-child { border-bottom: 0; }
    .bd-row > span { font-size: 12.5px; font-weight: 900; letter-spacing: .11em; text-transform: uppercase; color: #909090; font-family: var(--heading-font); }
    .bd-row > strong { font-size: 15px; line-height: 1.35; color: #11151A; }
    .bd-row small { display: block; color: #777; font-size: 13px; margin-top: 3px; font-weight: 400; }
    .bd-rowact { display: flex; align-items: center; gap: 10px; white-space: nowrap; font-family: var(--font); align-self: center; }
    .bd-row .bd-rowact .bd-edit { color: var(--blue,#00C2FF); font-size: 13px; font-weight: 400; text-transform: lowercase; letter-spacing: 0; cursor: pointer; font-family: var(--font); }
    .bd-row .bd-rowact .bd-edit:hover { color: var(--blue-dark,#008EBB); text-decoration: underline; text-underline-offset: 3px; }
    .bd-vsep { width: 1px; height: 14px; background: #D8DEE5; display: inline-block; }
    .bd-price-sm { font-size: 15px; font-weight: 800; color: #11151A; font-family: var(--font); }
    /* pinned black Price & Action footer */
    .bd-foot { flex: 0 0 auto; background: #fbfbfa; border-top: 1px solid #e7e7e7; padding: 12px 32px 16px; }
    .bd-total { grid-column: 1 / -1; background: #080808; color: #fff; border-color: #080808; border-radius: 16px; }
    .bd-total-h { display: grid; grid-template-columns: 220px 1fr auto; gap: 22px; align-items: center; padding: 14px 18px 16px; }
    .bd-tblock span { display: block; font-size: 12.5px; font-weight: 900; letter-spacing: .11em; text-transform: uppercase; color: #aaa; margin-bottom: 4px; font-family: var(--heading-font); }
    .bd-tblock strong { display: block; color: #fff; font-size: 15px; line-height: 1.35; }
    .bd-tblock .bd-price { font-size: 32px; letter-spacing: -.06em; font-weight: 900; font-family: var(--heading-font); }
    /* re-homed engine action proxies (#cfg-sidebar-atc/quote = .btn) styled as the
       mockup's side-by-side text-link CTAs. display NOT set here so .d-none keeps
       hiding the quote button until the engine flags a Price-TBD (syncQuoteVisibility). */
    .bd-tactions { display: flex; align-items: center; justify-content: flex-end; gap: 0; }
    .bd-tactions .btn { background: none !important; border: 0 !important; border-radius: 0 !important; box-shadow: none !important; height: auto !important; min-height: 0 !important; width: auto !important; min-width: 0 !important; padding: 4px 20px !important; margin: 0 !important; color: #fff !important; font-size: 22px !important; font-weight: 900 !important; font-family: var(--heading-font) !important; cursor: pointer; transition: color .16s ease, transform .16s ease; white-space: nowrap; }
    .bd-tactions .btn:hover { color: var(--blue,#00C2FF) !important; transform: scale(1.07); text-decoration: none !important; filter: none !important; }
    .bd-tactions .cfg-sidebar-quote:not(.d-none) + .cfg-sidebar-atc { border-left: 1px solid rgba(201,205,210,.45) !important; }

    /* $is_no_prices (Pro anonymous): no prices, no dead buttons */
    .build-bar.cfg-bar-noprice .bb-pricebox { visibility: hidden; }
    .bd-drawer.cfg-drawer-noprice [data-bd-estimate] { display: none; }

    /* ported drawer/receipt breakpoints (MAIN v1.83) */
    @media (max-width: 1420px) {
      .build-bar .bb-inner { grid-template-columns: minmax(220px,300px) minmax(0,1fr) auto auto; }
    }
    @media (max-width: 1300px) {
      .build-bar .bb-inner { grid-template-columns: 1fr 1.35fr 200px 155px; }
      .bb-receipt { grid-template-columns: repeat(3,1fr); }
      .bb-ritem:nth-child(3) { border-right: 0; }
      .bb-ritem:nth-child(n+4) { border-top: 1px solid #e3e3e3; }
      .bb-ritem:nth-child(4) { border-right: 1px solid #e3e3e3; }
      .bd-grid { grid-template-columns: 1fr 1fr; }
    }
    @media (max-width: 1024px) {
      .build-bar .bb-inner { grid-template-columns: 1fr auto; grid-auto-rows: auto; row-gap: 12px; padding: 12px 18px; }
      .bb-receipt { grid-column: 1 / -1; order: 3; }
      .bb-pricebox { order: 2; justify-self: start; text-align: left; }
    }
    @media (max-width: 920px) {
      .bd-grid { grid-template-columns: 1fr; }
      .bd-total-h { grid-template-columns: 1fr; gap: 12px; }
      .bd-row { grid-template-columns: 105px 1fr; }
      .bd-row .bd-rowact { grid-column: 1 / -1; justify-content: flex-start; }
    }
    /* ===================== end v1.84 R4 (Build Drawer + receipt bar) ===================== */

    /* =====================================================================
       v1.84 R4c — PHONE layout for the selector views (owner round 4:
       "make sure we know how this works on mobile and we are not squeezed").
       Henry's selector mockups collapse only to ≤1080 (tablet); at phone
       widths the 2-col browsers forced ~515px → horizontal overflow. Below
       700px the view becomes a single scroll column: slim stage, family/type
       lists turn into horizontal chip rows, grids fit the viewport.
       ===================================================================== */
    @media (max-width: 700px){
      .cfg-selector-view .csv-workspace{grid-template-columns:1fr;height:100vh;height:100dvh;overflow-y:auto}
      .cfg-selector-view .csv-preview-side{min-height:150px;max-height:190px}
      .cfg-selector-view .csv-selection-card{position:static;width:auto;margin:10px 14px;box-shadow:none}
      .cfg-selector-view .csv-rail{border-left:0}
      /* browsers: stack — the family column becomes a horizontal chip row
         (the Spot UV and die-cut screens are one column of tiles and cards at every width) */
      .cfg-selector-view .foil-browser,
      .cfg-selector-view .edge-browser,
      .cfg-selector-view .csv-material-browser{display:block}
      .cfg-selector-view .family-list,
      .cfg-selector-view .csv-family-list{display:flex;flex-direction:row;overflow-x:auto;-webkit-overflow-scrolling:touch;border-right:0;border-bottom:1px solid var(--line,#E2E6EA);background:#F7F8FA}
      .cfg-selector-view .family-btn,
      .cfg-selector-view .csv-family-btn{flex:0 0 auto;min-height:0;width:auto;padding:12px 14px;border-bottom:0;border-right:1px solid var(--line,#E2E6EA);text-align:center;white-space:nowrap}
      .cfg-selector-view .family-btn.active,
      .cfg-selector-view .csv-family-btn.active{box-shadow:inset 0 -3px 0 var(--blue,#00C2FF)}
      /* configurator 44: in the horizontal chip row the Painted / Foil heading is a small label chip */
      .cfg-selector-view .family-list .cfg-edge-kind{flex:0 0 auto;align-self:stretch;padding:0 10px 0 12px;white-space:nowrap;border-bottom:0;border-right:1px solid var(--line,#E2E6EA)}
      /* in the sideways chip row the heading chip carries the tint; Custom needs no strip */
      .cfg-selector-view .family-list .family-btn.cfg-edge-sub + .family-btn:not(.cfg-edge-sub){border-top:0;box-shadow:none}
      .cfg-selector-view .family-list .family-btn.cfg-edge-sub + .family-btn:not(.cfg-edge-sub).active{box-shadow:inset 0 -3px 0 var(--blue,#00C2FF)}
      /* grids fit the viewport */
      .cfg-selector-view .foil-grid{grid-template-columns:repeat(auto-fill,minmax(96px,1fr));padding:0 14px 16px}
      .cfg-selector-view .edge-grid{grid-template-columns:repeat(auto-fill,minmax(88px,1fr))}
      .cfg-selector-view .placement-grid,
      .cfg-selector-view .type-list{padding:0 14px 16px}
      .cfg-selector-view .placement-card:not(.thru){padding:10px 6px}
      .cfg-selector-view .placement-tabs{width:100%;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
      .cfg-selector-view .placement-tab{min-width:0;padding:10px 6px}
      .cfg-selector-view .placement-strip{padding:0}   /* 2026-10-01: 12px 14px here pushed "Where does this foil go?" to 34px and its cards to 30px while the next heading sat at 20px and the screen's own heading at 16px; the title and the cards carry their own padding */
      .cfg-selector-view .csv-rail-head{padding:14px 16px 12px}
      .cfg-selector-view .cfg-fv-addask{margin:14px 14px 18px}
      .cfg-selector-view .cfg-foil-panel > .cfg-finish-card{margin:14px 14px 0}
    }
    /* page-level phone driver (owner round 4): .build-context-inner's grid had a
       ~513px min-content (nowrap title + pills) — it widened the WHOLE layout
       viewport at phone widths, defeating every other mobile rule. Let it wrap. */
    @media (max-width: 700px){
      .build-context-inner{display:flex;flex-wrap:wrap;gap:8px 10px;min-width:0}
      .build-context-inner > *{min-width:0}
      .build-context .build-context-title, .build-context strong{white-space:normal}
    }

    /* =====================================================================
       v1.84 R5a — inline-panel PARITY: mockup setup-card shell
       Wraps the 8 non-selector-view finish panels' existing dt/dd (Emboss/
       Deboss, PMS Ink, Rounded Corners, Perforate, Variable Data, Backside
       Print, ArtWork/Design, Custom QR — whichever a given product actually
       offers) in the MAIN mockup's `.foil-setup-card` shell. The classes
       `.foil-setup-card / .foil-setup-head / .mini-label / .setup-subtitle /
       .setup-status / .setup-card-footer / .btn-save / .btn-remove /
       .pms-form-row / .pms-field` are ALREADY ported verbatim (namespaced to
       this page-scoped sheet, no site-chrome rules) earlier in this file —
       this block only adds the small amount of NESTING-CONTEXT glue the new
       markup (built in configure.php) needs once dt/dd move from being direct
       children of .inline-config-panel to being direct children of the new
       inner .foil-setup-card (their .next()-adjacency to each other, which
       accordion-expand.js + the rail's own toggle() rely on, is unchanged —
       only their common ancestor changes). Scoped to .cfg-shell-carded so it
       never touches the size/quantity/selector-view panels.
       ===================================================================== */
    .inline-config-panel.cfg-shell-carded { padding: 12px 16px 16px; }
    /* re-hide the raw engine dt (a checkbox-toggle finish OR a required
       radio-only option's bare "<b></b> Name" label — either way it is now
       redundant with the card's own head) — checkbox/hidden input stays in
       the DOM/form, just not rendered. */
    .inline-config-panel.cfg-shell-carded .foil-setup-card > dt { display: none; }
    /* re-apply the legacy-chrome normalization the panel's own
       "> dt, > dd" rule (above, R2) no longer reaches once dd nests one level
       deeper inside .foil-setup-card; no extra top padding — .foil-setup-head's
       own border-bottom + margin already separate head from content. */
    .inline-config-panel.cfg-shell-carded .foil-setup-card > dd { border: 0; margin: 0; background: transparent; padding: 0; }
    @media (max-width: 700px){
      .inline-config-panel.cfg-shell-carded .foil-setup-head { flex-wrap: wrap; }
      .inline-config-panel.cfg-shell-carded .setup-card-footer { flex-wrap: wrap; }
      .inline-config-panel.cfg-shell-carded .setup-card-actions { width: 100%; }
      .inline-config-panel.cfg-shell-carded .setup-card-actions .btn-remove,
      .inline-config-panel.cfg-shell-carded .setup-card-actions .btn-save { flex: 1 1 auto; }
    }
    /* R5b (owner round 6): option-card grids inside carded panels are 2-UP,
       matching the mockup. The ported v163 "watch-strap" block above forces
       every grid to 1fr !important — but Henry's OWN later fix blocks (v177
       source-style panels, v178 emboss inline panel) re-widen .scope-grid to
       2 columns, and the owner wants that treatment on ALL the inline finish
       panels (emboss/deboss, rounded corners, perforate flagged by name).
       Placement-card groups (.foil-placement-grid, one .radio-group wrapper
       per card) get the same 2-up so no group renders full-width stacked. */
    .inline-config-panel.cfg-shell-carded .scope-grid,
    .inline-config-panel.cfg-shell-carded .foil-placement-grid {
      display: grid !important;
      grid-template-columns: repeat(2, minmax(0,1fr)) !important;
      gap: 12px !important;
    }
    .inline-config-panel.cfg-shell-carded .foil-placement-grid > .radio-group { display: contents; }
    @media (max-width: 700px){
      .inline-config-panel.cfg-shell-carded .scope-grid,
      .inline-config-panel.cfg-shell-carded .foil-placement-grid { grid-template-columns: 1fr !important; }
    }
    /* R5b: brand the bare data fields (Variable Data "Enter Data", Custom QR)
       like the mockup's .pms-field input — the engine ships them native/unstyled. */
    .inline-config-panel.cfg-shell-carded input.variabledata,
    .inline-config-panel.cfg-shell-carded input.optioninput[type="text"] {
      width: 100%;
      box-sizing: border-box;
      padding: 11px 12px;
      border: 1px solid var(--line, #E4E7EB);
      border-radius: 10px;
      background: #fff;
      font-size: 14px;
      font-weight: 700;
      color: var(--ink, #11151A);
      font-family: inherit;
    }
    .inline-config-panel.cfg-shell-carded input.variabledata:focus,
    .inline-config-panel.cfg-shell-carded input.optioninput[type="text"]:focus {
      outline: none;
      border-color: var(--blue, #00C2FF);
      box-shadow: 0 0 0 3px rgba(0,194,255,.16);
    }
    /* R5b: the footer's helper line was internal design annotation (removed in
       the shell script) — with only the actions left, keep them right-aligned. */
    .inline-config-panel.cfg-shell-carded .setup-card-footer { justify-content: flex-end; }
    /* R5c (owner round 7): the size cards rendered ONE-PER-ROW at every width —
       the element carries BOTH .choice-grid and .size-grid, and the ported v163
       block's `.choice-grid{grid-template-columns:1fr !important}` (unscoped)
       beat the non-important 3-across rule since R3b (importance > specificity).
       Match importance: 3-across on wide desktop, 2-across on narrow/iPad rails,
       1-col only on phones. */
    .inline-config-panel[data-panel="size"] .size-grid { grid-template-columns: repeat(3, minmax(0,1fr)) !important; }
    @media (max-width: 1520px){
      .inline-config-panel[data-panel="size"] .size-grid { grid-template-columns: repeat(2, minmax(0,1fr)) !important; }
    }
    @media (max-width: 760px){
      .inline-config-panel[data-panel="size"] .size-grid { grid-template-columns: 1fr !important; }
    }

    /* =====================================================================
       v1.86 R5c — FRAMED FLOATING SHELL (desktop / fine-pointer only)
       ---------------------------------------------------------------------
       Ported from the committed mockup's <style id="v186-framed-shell">
         .../Main Builder/silkcards_master_configurator_MAIN.html (~:7498)
       "v1.86 — FRAMED FLOATING SHELL, Henry mock 2026-07-11": the whole
       configurator (stage + rail + YOUR BUILD bar) floats as a rounded
       16px white card on a cool-gray canvas. Site nav/topbar stay full-
       width ABOVE the frame — untouched (page-scoped sheet, no shared-
       chrome edits).

       ADAPTATIONS (faithful, not improvised):
        • the mockup computes frame height against its OWN standalone 70px
          nav; OUR real chrome (header-v2 topbar + .site-nav) is the 92px
          offset ALREADY used everywhere else in this file for the same
          purpose (.preview-panel/.build-context `top:92px` above, and the
          scReCenter offset comment in configure.php) — substituted below,
          never the mockup's bare 70px.
        • GATE: (min-width:1181px) and (pointer:fine) ONLY. The mockup's
          own block reverts <=1180 to full-bleed ("framed shell is a
          desktop treatment"); we ADD the (pointer:fine) leg on top so a
          TOUCH device at a desktop-class width (iPad landscape, 1376px)
          never enters this block. That exact case is the two-scrollables
          bug the R2 single-scroller model fixed (owner-reported
          2026-07-17, see the R2 comment block above) — re-enabling
          frame-mode's internal rail scroll for a coarse/touch pointer
          would regress it. Nothing NOT matching this query (any touch
          width, or <=1180 desktop) needs a re-declaration here — it
          falls through to the existing unconditional R1/R2/R5 rules
          above unchanged.
        • Under this gate the RAIL becomes the scroll container again
          (.builder-column, internal overflow-y:auto) instead of the
          window — the one mode where that is true. scReCenter() in
          configure.php branches on the SAME media query (JS,
          window.matchMedia, evaluated at call time — never cached) so it
          scrolls the column, not the window, here.
        • .build-context::before's 120px white mask (added above for the
          page-flow model, to cover rows peeking through the gap between
          the window-sticky pin and the real nav) needs no override here:
          pinned at `top:0` inside .builder-column's OWN scrollport, the
          mask sits entirely above y=0 of that scrollport and is clipped
          by the column's own overflow — inert by construction, not by an
          extra rule.
        • .builder-column's existing unconditional `padding-bottom:0` +
          .builder's flush bottom-radius/border (the R5 "flush footer"
          fix) are NOT overridden here either — inside the frame the
          column's bottom IS the frame's clipped edge, so "flush, no
          padding" is the same correct shape for the opposite structural
          reason (no site footer inside this scrollport to flow into).
        • Selector VIEWS (.cfg-selector-view, position:fixed;inset:0) and
          the Build Drawer (.bd-overlay/.bd-drawer, position:fixed) sit
          OUTSIDE any transform/filter/perspective/contain ancestor — this
          block adds none to .workspace — so they keep rendering as a
          true viewport-covering overlay (z-index 1200/1290/1300, all
          above .build-bar's 80) regardless of the frame's own
          overflow:clip, which only clips normal-flow/absolute content,
          never position:fixed descendants. No CSS needed for that
          contract; verified structurally, confirm live on open/close.
       ===================================================================== */
    @media (min-width: 1181px) and (min-height: 760px) and (pointer: fine) {
      :root {
        --shell-canvas: #E8E9EE;
        --shell-gx: clamp(24px, 9vw, 240px);
        --shell-gt: clamp(20px, 7.5vh, 108px);
        --shell-gb: clamp(20px, 7vh, 96px);
        --shell-radius: 16px;
      }
      html, body { background: var(--shell-canvas) !important; }

      .workspace {
        width: calc(100% - (var(--shell-gx) * 2));
        max-width: none;
        /* 133px = the 121px chrome at rest (topbar 40 + nav 81, live-measured)
           + a 12px TUCK (owner-directed 2026-08-21): the chrome's real height
           drifts a few px with zoom/OS metrics, and at exactly-121 the frame
           poked out BELOW the fixed bar as a black strip. Undershooting keeps
           the frame's bottom edge behind the bar in every case — the bar's own
           rounded corners are the visible bottom, so the tuck is invisible. */
        height: calc(100vh - 133px - var(--shell-gt) - var(--shell-gb));
        /* NO min-height floor: on short screens a floor pushed the frame's
           bottom PAST the fixed bar (owner round 8 — the black/white strip
           under the bar on a 14" screen). TWO floors existed: the frame's own
           620px AND the R1 base `.workspace{min-height:calc(100vh - 92px)}` —
           both neutralized; short viewports (<760px) get full-bleed via the
           media gate instead. */
        min-height: 0;
        margin: var(--shell-gt) auto 0;
        border-radius: var(--shell-radius);
        overflow: clip;                    /* clips corners WITHOUT creating a scroll container */
        box-shadow: 0 18px 44px rgba(15,19,24,.12), 0 2px 8px rgba(15,19,24,.06);
        background: #fff;
      }

      /* stage: fills the now-bounded frame instead of window-sticky */
      .preview-panel {
        position: relative;
        top: 0;
        height: 100%;
        min-height: 0;
      }
      /* Hero image/placeholder never exceeds the shorter framed stage
         (v186, adapted to OUR 92px chrome offset). */
      .ref-preview-wrap img,
      .ref-preview-placeholder {
        max-height: calc(100vh - 133px - var(--shell-gt) - var(--shell-gb) - 190px); /* tracks the tucked frame height above */
      }

      /* rail: internal scroll INSIDE the frame (v186's model) — the ONE
         mode where the column, not the window, is the scroller. */
      .builder-column {
        height: 100%;
        overflow-y: auto;
      }
      /* .build-context pins to the COLUMN's own scrollport top here — the
         92px window/nav offset used in page-flow mode is moot once the
         column is its own bounded scroll container starting at y:0. */
      .build-context { top: 0; }

      /* YOUR BUILD bar: still fixed/always-visible (position:fixed is set
         in the base R1 rule, untouched), but sized+positioned to the
         frame with rounded bottom corners so it reads as the frame's own
         bottom edge (v186, verbatim). */
      .build-bar {
        left: 50%;
        right: auto;
        bottom: var(--shell-gb);
        width: calc(100% - (var(--shell-gx) * 2));
        transform: translateX(-50%);
        border-radius: 0 0 var(--shell-radius) var(--shell-radius);
        overflow: clip;   /* round 8 item 6: bar content can never spill past the frame edge */
      }

      /* ---- R5d (owner round 8) ---- */
      /* item 1: ONE scroll surface — the page itself never scrolls in frame
         mode (the rail is the scroller; a JS wheel-forwarder routes wheels
         from the stage/canvas into it). The footer is hidden here — it made
         the page a second scroller; it stays on every other mode/page. */
      html, body { overflow: hidden; }
      /* round 9: the fixed bar OVERLAYS the frame's bottom ~110-135px — without
         scroll clearance the last rail rows max out UNDER it (owner: "can't
         scroll past this"). Padding = bar height + breathing room. */
      .builder-column { padding-bottom: 150px; }
      .site-footer, .sc-scroll-anchor { display: none; }
      /* items 2+5: the FRAME is the card now — the inner .builder card's own
         30px top radius drew a rounded notch + gap against the stage
         (owner image 2), and its border/shadow doubled the frame's. */
      .builder { border-radius: 0; border: 0; box-shadow: none; }
    }

    /* R5d (owner round 8, items 3+6): 14"-class desktops — same frame, tighter
       canvas gaps + a compact YOUR BUILD bar so the stage keeps its height and
       the bar's content stays inside the frame. Below 760px viewport height
       (or 1181px width, or any touch device) the page is full-bleed instead. */
    @media (min-width: 1181px) and (max-width: 1680px) and (min-height: 760px) and (pointer: fine) {
      :root {
        --shell-gx: clamp(20px, 4vw, 72px);
        --shell-gt: clamp(14px, 3.5vh, 44px);
        --shell-gb: clamp(14px, 3.5vh, 40px);
      }
      .build-bar .bb-inner {
        grid-template-columns: minmax(170px, .8fr) minmax(0, 1.6fr) auto auto;
        gap: 14px;
        padding: 9px 18px;
      }
      .bb-inner > * { min-width: 0; }
      .bb-title .bb-kicker { font-size: 11px; margin-bottom: 1px; }
      .bb-title strong { font-size: 15px; line-height: 1.15; display: block; }
      .bb-title .bb-details-btn { font-size: 12.5px; }
      .bb-receipt .bb-ritem span { font-size: 10px; }
      .bb-receipt .bb-ritem strong { font-size: 12.5px; }
      .bb-pricebox .bb-plabel { font-size: 11px; }
      .bb-pricebox .bb-pvalue { font-size: 21px; }
      .bb-pricebox .bb-pnote { font-size: 11px; }
      .bb-actions .bb-add { height: 44px; font-size: 14px; padding: 0 18px; }
      .builder-column { padding-bottom: 120px; }   /* round 9: compact bar is ~80-107px tall */
      .preview-rating-label { bottom: 94px; }      /* round 9: hug the corner above the compact bar */
    }
    /* ===================== end v1.86 R5c FRAMED SHELL ===================== */

    /* round-13 BRANDED POP-UPS moved to henry_common.css on 2026-09-02 (owner: "check all
       alerts") — header-v2.php now loads the alert library on every v2 page, so the one
       treatment lives in the one sheet every v2 page loads. */

    /* round-13: stock BASE-COLOR chip — "cards start white/black/silver" indication
       on the stock cards + the stock view head (the delivered photos show black
       designs; the chip says what the blank stock actually looks like) */
    .cfg-stock-base {
      display: flex;
      align-items: center;
      gap: 7px;
      margin-top: 7px;
      font-size: 11.5px;
      font-weight: 700;
      color: #5A6570;
      font-style: normal;
    }
    .cfg-stock-base i {
      width: 13px; height: 13px;
      border-radius: 50%;
      border: 1px solid rgba(17,21,26,.28);
      display: inline-block;
      flex: 0 0 auto;
    }

/* =========================================================================
   SERVICE PRODUCT SCREEN (.cfg-service) — the is_service order step
   (product 111 "Design Help", $99). Round 3 (owner 2026-08-21): INHERIT the
   card configurator's own v1.84 shell wholesale — 70/30 workspace, black
   sticky stage panel, frame mode, the 1180 collapse breakpoint — instead of
   round 2's capped custom frame (which mis-matched the fixed bar's geometry:
   the black strip under the bar was the capped workspace poking out).
   Only the CONTENT differs from a card page: the 3D canvas fills the stage
   at the same size as the card page's photo canvas (.preview-stage is
   already min(88%,1060px), centered in the black panel), and the right rail
   carries the design-brief form instead of the builder rows.
   The Design Help pitch copy is OFF the stage (parked — owner round 3).
   Greys: #6B6B6B on white/cream, #9C9C9C on the dark stage (both measured
   WCAG AA on their own backgrounds) — never #8A8A8A on white.
   ========================================================================= */

    /* THE 3D CANVAS — the same footprint the card page gives its photo:
       full .preview-stage width, the photo canvas's 655/560 shape, capped
       like .ref-preview-wrap img. No border — it IS the stage now. */
    .cfg-svc-3d {
      width: 100%;
      aspect-ratio: 655 / 560;
      max-height: calc(100vh - 300px);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 16px;
      border: 0;
      padding: 0;
      box-sizing: border-box;
    }
    .cfg-svc-3d .proofer-mount { display: none; width: 100%; flex: 1 1 auto; min-height: 0; }
    .cfg-svc-3d .proofer-mount iframe { width: 100%; height: 100%; border: 0; border-radius: 14px; display: block; }
    .cfg-svc-3d[data-proofer-state="ready"] .proofer-mount { display: flex; }
    .cfg-svc-3d[data-proofer-state="ready"] .cfg-svc-3d-card { display: none; }
    /* Static sample card — the fallback while loading / failed / single-column. */
    .cfg-svc-3d-card {
      width: min(72%, 480px);
      aspect-ratio: 3.5 / 2;
      border-radius: 12px;
      background: linear-gradient(145deg, #2C2C2C 0%, #1C1C1C 55%, #242424 100%);
      box-shadow: 0 22px 44px rgba(0,0,0,.5);
      border: 1px solid rgba(255,255,255,.08);
    }
    .cfg-svc-3d-note { margin: 0; text-align: center; font-size: 12.5px; line-height: 1.5; color: #9C9C9C; }
    /* The caption explains the SLOT while the static fallback shows; the live
       viewer carries its own chrome, so the line hides and its height goes to
       the 3D canvas. */
    .cfg-svc-3d[data-proofer-state="ready"] .cfg-svc-3d-note { display: none; }

    /* 3D PROOF IN THE BUILD STUDIO — slice 1 (2026-09-22). The viewer overlays the
       photo stage and only shows once ProoferEmbed reports READY; until then (and on
       failure) the photo underneath is untouched. The stage gets the placeholder's own
       shape while 3D is up so it can never collapse to 0 height. */
    /* ONE VIEWER FOR THE WHOLE PAGE (owner 2026-09-22: "keep 1 3dproofer open the whole
       time"). configure.php moves .cfg-3d-stage to <body> ONCE, before the viewer mounts,
       and then only re-POSITIONS it over whichever stage is on screen — the page's
       .preview-panel content box, or the open option selector's .csv-preview-side (the
       WHOLE grey area since 2026-09-25, flush top and bottom, 16px in at the sides for the
       rail's gap; the rating badge and the Current Selection card show THROUGH the
       transparent canvas — the JS block says why). Two rules from the
       proofer lane, both load-bearing: never move the element in the DOM after mount (an
       iframe that moves RELOADS, ~10s cold paint, GOTCHAS #335), and never hide it with
       display:none (a zero-size canvas can flash on return) — it fades on opacity.
       Why <body> and not the stage it covers: .preview-panel is sticky + isolation:isolate,
       a stacking context, so nothing inside it can ever paint above the selector view
       (z-index 1200). JS sets position/top/left/width/height and z-index per mode. */
    .cfg-3d-stage { position: absolute; left: 0; top: 0; width: 0; height: 0; z-index: auto;
                    opacity: 0; pointer-events: none; transition: opacity .35s ease; }
    .cfg-3d-stage .proofer-mount { width: 100%; height: 100%; overflow: hidden; background: transparent; }
    .cfg-3d-stage .proofer-mount iframe { width: 100%; height: 100%; border: 0; display: block; }
    .cfg-3d-stage[data-proofer-state="ready"] { opacity: 1; pointer-events: auto; }
    /* NOT SHOWN IN 3D (2026-09-30): one quiet line naming the picks the card cannot draw.
       Information, never a warning — nothing is wrong with the order. It sits on the viewer
       (top-left, clear of the proofer's right rail, the rating badge and the selector's
       Current Selection card) and never takes a click. The [hidden] rule is explicit
       because an authored display would beat the browser's own (GOTCHAS: a hidden flag
       that still renders). */
    .cfg-3d-note { position: absolute; left: 16px; top: 16px; z-index: 1; display: block;
                   max-width: min(440px, calc(100% - 128px)); padding: 8px 12px; border-radius: 10px;
                   background: rgba(0,0,0,.42); color: #e9ebee; font-size: 12px; line-height: 1.45;
                   font-weight: 500; pointer-events: none; }
    .cfg-3d-note[hidden] { display: none; }
    /* ONE SURFACE, NO DOUBLE BOX (owner 2026-09-22: "the whole preview area turns the grey
       while the 3D is showing"). body.cfg-3d-ready is set by configure.php while the viewer
       is READY; the whole stage turns #2a2e33 edge to edge and the viewer is transparent
       over it. ⛔ Never transparent-on-BLACK instead: measured 2026-09-22, that erases a
       near-black card's outline. Back to black the moment the photo shows again. */
    .preview-panel, .cfg-selector-view .csv-preview-side { transition: background-color .35s ease; }
    body.cfg-3d-ready .preview-panel { background: #2a2e33 !important; }
    body.cfg-3d-ready .cfg-selector-view .csv-preview-side { background: #2a2e33; }
    body.cfg-3d-ready .cfg-selector-view .csv-preview-side:before { display: none; }
    body.cfg-3d-ready .preview-stage { aspect-ratio: 16 / 10; }   /* never collapse under the viewer */
    body.cfg-3d-ready .preview-stage > .ref-preview-wrap,
    body.cfg-3d-ready .cfg-selector-view .csv-photo-slot { visibility: hidden; }

    /* RIGHT RAIL: the brief form in the card page's own 390px-30vw column.
       The v1.84 shell styles .build-context as the black context bar — the
       service rail uses the approved cream "You're ordering" box instead. */
    .cfg-service .builder {
      background: #fff; border: 0; border-radius: 0; box-shadow: none;
      overflow: visible;
      padding: 0 28px 150px;
      box-sizing: border-box;
    }
    .cfg-service .build-context {
      position: sticky; top: 92px; z-index: 5;
      background: #fff;
      padding: 22px 0 14px; margin: 0; border-bottom: 0;
      /* ⚠️ THE TOP PAD NEEDS !important, AND ONLY BECAUSE IT IS ANSWERING ONE (owner-caught
         2026-09-03: "add a little space above the your ordering box").
         The card page's rail-top reskin at ~:3456 sets `.build-context { padding: 0 !important }`,
         so the 22px on the line above computed to 0 and the cream "You're ordering" box sat
         flush against the top of the column — measured: 0px from the column's own top edge.
         Specificity cannot answer an !important, so this is a targeted counter, not an
         escalation; it is scoped to .cfg-service and touches no card page.
         ⛔ Put the space INSIDE this sticky box, never as a margin on .cfg-svc-ctx: the box's
         overflow is `visible`, so a child margin COLLAPSES THROUGH and moves the sticky header
         itself — it looks identical at rest and then goes flush again the moment the rail
         scrolls and the header sticks to top:0. Measured both ways. As padding the band is part
         of the header, so the form scrolls UNDER it and the gap survives sticking. */
      padding-top: 22px !important;
    }
    @media (min-width: 1181px) and (min-height: 760px) and (pointer: fine) {
      .cfg-service .build-context { top: 0; }
    }
    .cfg-svc-ctx { display: flex; flex-direction: column; gap: 2px; padding: 16px 18px; background: #F6F3EC; border-radius: 14px; }
    .cfg-svc-ctx-eyebrow { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: #6B6B6B; font-weight: 700; }
    .cfg-svc-ctx-name { font-size: 17px; font-weight: 700; color: #161616; }

    /* The engine's own intake, styled to the approved look — the HICD dl
       (inc/page/hicd-option.php markup, unmoved). The base_accordion is
       hidden single-value inputs only; collapse its box chrome. */
    .cfg-svc-form { padding-top: 10px; }
    /* Hide the basics dl ONLY while it holds no real control — a service's
       single-value dims render as hidden inputs (no <dt>). If admin ever gives
       a service a second paper/size, its <dt> appears and this rule stands
       down, honoring the ASSUMES block in configure.php (show unstyled rather
       than suppress; design-review 2026-08-21 must-fix 2). :has() is already
       relied on elsewhere in this sheet. */
    .cfg-svc-form .base_accordion:not(:has(dt)) { display: none; }
    .cfg-svc-form .accordion { border: 0; background: none; padding: 0; margin: 0; }
    .cfg-svc-form .accordion > dl,
    .cfg-svc-form dl { margin: 0; display: grid; gap: 26px; }
    .cfg-svc-form dt { font-size: 15px; font-weight: 700; color: #161616; line-height: 1.35; padding: 0; cursor: default; }
    .cfg-svc-form dt b { display: none; }                    /* the engine's accordion arrow slot */
    .cfg-svc-form dd { margin: -18px 0 0; padding: 0; border-bottom: 0 !important; }

    /* THE RAIL'S LEFT EDGE — owner-caught 2026-09-03: "spacing is weird, too close to the
       right". Measured at 1440: the column's content box is 979-1354 (28px gutters), and the
       cream "You're ordering" box used all of it — but every question and every input started
       40px and 60px further right, so nothing lined up and the whole brief sat shoved toward
       the right edge (left gutter 88px vs right gutter 28px).
       TWO causes, neither of them this screen's own CSS, which is why the existing
       `.cfg-svc-form dd { padding: 0 }` above did not catch it:
         1. `ul.tabs-content` is a bare <ul>, so it inherits the BROWSER's default
            `padding-inline-start: 40px` (verified against a probe <ul>: identical value,
            nothing authored). The card path never sees it because the rail re-parents the
            engine's dt/dd out of that list; the service screen leaves the engine's own
            output standing, so the list is still the wrapper.
         2. `.features-addons--wrapper .accordion dd` (features-addons--wrapper.css) sets
            `padding-left: 20px` at (0,3,1) and out-specifies our (0,1,1) rule above.
       Both are zeroed HERE rather than at their source: those sheets are the legacy engine's
       and are shared with the card path, where the indents are correct. */
    .cfg-svc-form ul.tabs-content { padding-inline-start: 0; padding-left: 0; }
    .cfg-service .cfg-svc-form .accordion dd { padding-left: 0; }
    /* ^ border-bottom:0 — the engine draws a 1px #d1d1d1 rule under every dd,
       which sat flush against the drop boxes (owner round 3: "too close");
       the 26px grid gap is the separation here, so the rule goes. */
    .cfg-svc-form textarea {
      width: 100%;
      box-sizing: border-box;
      margin-top: 10px;
      padding: 12px 14px;
      border: 1px solid #DCD6CA;
      border-radius: 12px;
      font: inherit;
      font-size: 15px;
      line-height: 1.5;
      color: #161616;
      background: #fff;
      resize: vertical;
    }
    .cfg-svc-form textarea:focus { outline: none; border-color: #161616; box-shadow: 0 0 0 3px rgba(22,22,22,.08); }
    /* Keyboard focus on a file drop mirrors the textarea treatment — the input
       itself is the opacity:0 overlay, so the ring goes on the visible box. */
    .cfg-svc-form .cart_filebox:focus-within { border-color: #161616; box-shadow: 0 0 0 3px rgba(22,22,22,.08); }
    /* JS-injected helper line under a question (approved mockup copy). */
    .cfg-svc-hint { display: block; margin-top: 4px; font-size: 13px; color: #6B6B6B; font-weight: 400; line-height: 1.45; }
    .cfg-svc-form textarea::placeholder { color: #A8A8A8; }

    /* File drops: the engine's .cart_filebox, restyled (input stays the
       click/drop target the upload script binds — never replaced). The "+"
       is drawn in CSS: this page does not load the icon font the engine's
       fa-plus glyph needs, so the circle rendered empty. */
    .cfg-svc-form .cart_filebox {
      position: relative;
      margin-top: 10px;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 22px 16px;
      border: 1.5px dashed #D2CBBD;
      border-radius: 12px;
      background: #FBF8F1;
      color: #6B6B6B;
      font-size: 14px;
      cursor: pointer;
    }
    .cfg-svc-form .cart_filebox input.AttachFiles { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
    .cfg-svc-form .cart_filebox > div { display: flex; align-items: center; gap: 10px; pointer-events: none; }
    .cfg-svc-form .cart_filebox > div br { display: none; }
    .cfg-svc-form .cart_filebox .fa-plus {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 24px; height: 24px;
      border-radius: 50%;
      background: #161616;
      color: #fff;
      font-size: 15px;
      line-height: 1;
      font-weight: 700;
      font-style: normal;
    }
    .cfg-svc-form .cart_filebox .fa-plus::before { content: "+"; font-family: inherit; }
    .cfg-svc-form .filelist { margin: 6px 0 0 !important; font-size: 13.5px; color: #444; }

    /* Purchase bar: same fixed .build-bar shell, three cells instead of the
       card page's five-cell receipt (which all read "—" for a service). */
    .build-bar.cfg-svc-bar .bb-inner { grid-template-columns: 1fr auto auto; gap: 26px; }
    .cfg-svc-bar .bb-pricebox { text-align: right; }
    .cfg-svc-bar .bb-pvalue .cfg-svc-cur { font-size: 13px; font-weight: 700; color: #6B6B6B; letter-spacing: 0; }

    /* Tablet: the flat-fee note is the widest thing in the price cell —
       yield it before the bar crowds (the card page steps its bar down from
       1420; this bar's 3 cells only pinch in the 641-1024 band). */
    @media (max-width: 1024px) {
      .cfg-svc-bar .bb-pnote { display: none; }
      .build-bar.cfg-svc-bar .bb-inner { gap: 16px; }
    }

    /* Compact phone bar (the desktop three-cell bar wrapped into a ~200px
       block on a 375px screen): title+price one row, full-width CTA under;
       the flat-fee note yields its space (desktop keeps it). */
    @media (max-width: 640px) {
      .build-bar.cfg-svc-bar .bb-inner {
        grid-template-columns: 1fr auto;
        grid-template-areas: "title price" "cta cta";
        row-gap: 10px;
        padding: 12px 16px;
      }
      .cfg-svc-bar .bb-title { grid-area: title; }
      .cfg-svc-bar .bb-title strong { font-size: 17px; }
      .cfg-svc-bar .bb-pricebox { grid-area: price; align-self: center; }
      .cfg-svc-bar .bb-pvalue { font-size: 21px; }
      .cfg-svc-bar .bb-pnote { display: none; }
      .cfg-svc-bar .bb-actions { grid-area: cta; }
      .cfg-svc-bar .bb-actions .bb-add { width: 100%; height: 46px; }
    }

    /* =====================================================================
       PHONES: THE YOUR BUILD BAR IS ONE ROW (owner 2026-10-04: "go with A")
       ---------------------------------------------------------------------
       At <=760px the bar was 339px of a 375x634 screen (name, button, price,
       five summary boxes), which left 166px for the card. Now: price + the
       details link on the left, the button(s) on the right, about 72px. The
       five boxes, the kicker and the product name are not drawn here; the
       same build is in the panel the details link opens (.bd-drawer).
       The design service's bar (.cfg-svc-bar) has its own phone rules above.
       ASSUMES: .bb-details-btn opens the build drawer, which lists size,
       stock, quantity, sets and finishes — if that panel goes, a phone has
       no build summary.
       ===================================================================== */
    @media (max-width: 760px) {
      .build-bar:not(.cfg-svc-bar) .bb-inner { grid-template-columns: minmax(0,1fr) auto; grid-template-areas: "price cta" "more cta"; row-gap: 1px; column-gap: 14px; align-items: center; padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px)); }
      .build-bar:not(.cfg-svc-bar) .bb-receipt,
      .build-bar:not(.cfg-svc-bar) .bb-title .bb-kicker,
      .build-bar:not(.cfg-svc-bar) .bb-title > strong,
      .build-bar:not(.cfg-svc-bar) .bb-pricebox .bb-plabel,
      .build-bar:not(.cfg-svc-bar) .bb-pricebox .bb-pnote { display: none; }
      .build-bar:not(.cfg-svc-bar) .bb-pricebox { grid-area: price; order: 0; justify-self: start; text-align: left; }
      .build-bar:not(.cfg-svc-bar) .bb-pricebox .bb-pvalue { font-size: 23px; margin-top: 0; }
      .build-bar:not(.cfg-svc-bar) .bb-title { grid-area: more; min-width: 0; }
      .build-bar:not(.cfg-svc-bar) .bb-details-btn { margin-top: 0; white-space: nowrap; }
      .build-bar:not(.cfg-svc-bar) .bb-actions { grid-area: cta; }
      .build-bar:not(.cfg-svc-bar) .bb-actions .bb-add { height: 46px; padding: 0 22px; }
      /* THE OPTIONS PEEK ABOVE THE BAR, AND THEIR HEADER IS SQUARE (owner 2026-10-05:
         "hard to tell that you need to scroll down to select the options"; "black bar
         with rounded tops looks odd with the square white corners"). The card area was
         the whole screen down to the bar (min-height 520px), so nothing said there was
         more below. At 52% of the screen's height the black "You're building" header and
         the top of the first option row show above the bar (375x634: 104px of them).
         The header's 22px corners sat on the white column behind it; flush under the
         card area they are square. */
      .preview-panel { min-height: 300px; height: 52vh; height: 52svh; padding-bottom: 0; }
      .builder, .builder-head { border-top-left-radius: 0; border-top-right-radius: 0; }
      /* THE CURRENT SELECTION CARD READS ON A PHONE (owner 2026-10-05, the stock screen:
         "see odd item"). Its rows were label and value side by side; in the 190px card
         beside the photo, "Material & Thickness" took 140px and the value got 43px, four
         clipped lines running off the screen (the strip measured 384px in a 375px
         window). Here each row is the label with its value under it, and the photo box
         and the card share the strip's width. */
      .cfg-selector-view .csv-preview-side .csv-photo-wrap { flex: 0 0 44%; min-width: 0; }
      .cfg-selector-view .csv-selection-card { flex: 1 1 0; min-width: 0; margin: 10px 12px 10px 0; padding: 12px 14px; overflow-y: auto; align-self: stretch; }
      .cfg-selector-view .csv-selection-card .csv-card-row { flex-direction: column; align-items: flex-start; gap: 2px; }
      .cfg-selector-view .csv-selection-card .csv-card-row > strong { text-align: left; overflow-wrap: anywhere; }
    }
    /* AN OPTION SCREEN IS NEVER WIDER THAN THE PHONE (sweep 2026-10-05, 375px). The row of
       family tabs is meant to scroll sideways by itself, but its column had no width limit,
       so the tabs' total width became the whole screen's: Edge Finishing 783px, the hang
       tags' stock screen 747px, Suede's stock screen 384px — with Confirm off the screen.
       The column is held to the screen and the tab row scrolls inside it. */
    @media (max-width: 700px){
      .cfg-selector-view .csv-workspace { grid-template-columns: minmax(0, 1fr); }
      .cfg-selector-view .csv-rail,
      .cfg-selector-view .csv-preview-side,
      .cfg-selector-view .foil-browser,
      .cfg-selector-view .edge-browser,
      .cfg-selector-view .csv-material-browser { min-width: 0; max-width: 100vw; }
      .cfg-selector-view .family-list,
      .cfg-selector-view .csv-family-list { max-width: 100vw; }
    }

    /* PHONES: THE 3D CARD STAYS ON SCREEN, AND THE OPTION SCREEN'S STRIP IS ALL CARD
       (owner 2026-10-05, his phone: "initial area also needs the 3d card to be visible at
       all times"; "remove the current selection box from the 3D area. You want as much
       space for the 3D card").
       1. The card area sticks under the site header while the options scroll beneath it.
          It is 36% of the screen's height (was 52%) so the options keep most of the screen.
          configure.php's place() holds the viewer fixed while the panel is stuck.
       2. On an option screen the Current Selection card is not drawn at phone width; the
          strip is the 3D card alone. The same choice shows in the list below it.
       ASSUMES: --cfg-phone-header is set by configure.php to the sticky header's height —
       if it is missing the card area sticks at 0 and sits under the header. */
    @media (max-width: 760px) {
      .preview-panel { position: sticky; top: var(--cfg-phone-header, 0px); z-index: 30; height: 36vh; height: 36svh; min-height: 200px; }
      .cfg-selector-view .csv-selection-card { display: none; }
      .cfg-selector-view .csv-preview-side .csv-photo-wrap { flex: 1 1 auto; }
      /* The black "You're building" header was sticky at 92px and slid over the pinned card
         area. On phones it scrolls with the options: pinned, it would leave them about
         200px of a 634px screen (header 69 + card 228 + this 63 + price bar 71). */
      .build-context { position: static; }
      /* THE VIEWER PAINTS ABOVE THE PINNED CARD AREA (owner 2026-10-05, his phone: the card
         "takes a long time to load or doesn't load at all"). The card area got z-index 30
         when it was pinned; the viewer is a child of <body> with no z-index, so the area's
         own dark background covered it. 31 is above the area and below the header and the
         price bar (80). On an option screen configure.php sets 1201 itself. */
      .cfg-3d-stage { z-index: 31; }
      /* The reviews pill sat 94px up for the old tall bar's padding; in the short pinned
         area that is the middle (owner: "move that to the bottom where it should be"). */
      .preview-rating-label { bottom: 12px; }
    }

    /* PHONES, TWO MORE FROM THE OWNER'S PHONE (2026-10-05)
       1. "the options have a huge card, but they're all hard to see in one go": inside the
          option list the placement cards (Card Front / Mid Layer / Card Back) were one per
          row, each about 135px tall. Three across, the way the foil screen draws them.
       2. "3d image is missing from the foil setup screen when scrolling": an option screen is
          one scrolling column on a phone and its 3D strip scrolled away with it. The strip
          sticks to the top; configure.php's place() already follows the strip's box. */
    @media (max-width: 700px){
      .inline-config-panel.cfg-shell-carded .foil-placement-grid { grid-template-columns: repeat(3, minmax(0,1fr)) !important; gap: 8px !important; }
      .inline-config-panel.cfg-shell-carded .foil-placement-grid .cfg-placement-card { padding: 10px 4px; min-height: 0; }
      .cfg-selector-view .csv-preview-side { position: sticky; top: 0; z-index: 5; }
      /* The step BEFORE the placement cards was still one per row (owner, same day: "emboss
         is still stacked on top of each other. shouldn't they be able fit side by side?"):
         the Emboss / Deboss effect cards, 317x166 each at 393px. Two across. */
      .inline-config-panel.cfg-shell-carded .scope-grid { grid-template-columns: repeat(2, minmax(0,1fr)) !important; gap: 8px !important; }
    }
