/* XYZ Prints — wizard styles.
   Extracted from templates/xyz-print-wizard.php on 2026-06-08.
   Wizard-scoped --xw-* tokens live here; the canonical --fs-* type-scale
   ladder stays in assets/xyz-master.css :root (single source). */

/* ── Layout ── */
.xw-wrap{max-width:1040px;margin:0 auto;padding:60px 24px 100px;overflow-x:hidden;
  font-family:-apple-system,BlinkMacSystemFont,'Helvetica Neue','Inter',Arial,sans-serif;
  color:#1a1a1a;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}
.xw-wrap p,.xw-wrap span,.xw-wrap div,.xw-wrap label,.xw-wrap td,.xw-wrap th,
.xw-wrap input,.xw-wrap button,.xw-wrap textarea,.xw-wrap select,.xw-wrap a{font-family:inherit;}
/* Panel-title font-family is set in the typography normalization block at the
   bottom of this stylesheet — kept single-source. */
@media(max-width:600px){.xw-wrap{padding:32px 16px 80px;}}

/* ── Language switcher ── (the wizard is the site's only multilingual surface) */
.xw-lang-bar{display:flex;justify-content:center;margin:0 0 28px;}
@media(max-width:600px){.xw-lang-bar{margin:0 0 20px;}}

/* ── Step indicator ── */
.xw-steps{
  display:flex;align-items:flex-start;
  /* Fixed height prevents layout reflow when active state changes between steps */
  height:72px;
  margin-bottom:40px;
  overflow:visible;
}
.xw-step-item{
  display:flex;flex-direction:column;align-items:center;
  gap:6px;position:relative;flex:1;
  /* Fixed height on each item so the row never shifts vertically */
  height:72px;
}
.xw-step-item:not(:last-child)::after{
  content:'';position:absolute;top:16px;left:calc(50% + 20px);
  right:calc(-50% + 20px);height:1px;background:#d0c8bc;z-index:0;}
.xw-step-item.done:not(:last-child)::after{background:#1a1a1a;}
.xw-step-num{
  width:32px;height:32px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-size:12px;font-weight:500;
  border:1.5px solid #d0c8bc;background:transparent;color:#b8a898;
  position:relative;z-index:1;
  /* Scope transition to colour only — prevents any accidental size animation */
  transition:border-color .2s,background .2s,color .2s;
  font-family:inherit;
  flex-shrink:0;
}
.xw-step-item.active .xw-step-num{border-color:#1a1a1a;background:#1a1a1a;color:#f5f0e8;}
.xw-step-item.done .xw-step-num{border-color:#1a1a1a;background:#1a1a1a;color:#f5f0e8;}
.xw-step-label{
  font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  color:#b8a898;font-weight:500;white-space:nowrap;
  /* Fixed-height label so the row height is always the same regardless of text */
  height:16px;line-height:16px;
  transition:color .2s;
}
.xw-step-item.active .xw-step-label,.xw-step-item.done .xw-step-label{color:#1a1a1a;}
.xw-step-item.done,.xw-step-item.active,.xw-step-item.reachable{cursor:pointer;}

/* ── Shared typography tokens ── */
:root{
  --xw-serif:'EB Garamond',Georgia,serif;
  --xw-sans:-apple-system,BlinkMacSystemFont,'Helvetica Neue','Inter',Arial,sans-serif;
  --xw-text:#1a1a1a;
  --xw-muted:#8a8a8a;
  --xw-border:rgba(26,26,26,.14);
  --xw-accent:#1a1a1a;
  --xw-h:32px;
  /* Type scale (--fs-title/body/meta/caps + the full ladder) is now
     defined ONCE, site-wide, in assets/xyz-master.css :root — injected
     on every page by the Style Guard mu-plugin. Do NOT redefine sizes
     here; a local redefinition is exactly what made the wizard drift
     from the rest of the store. The wizard's compact look is preserved
     by the wizard aliases over there (title 22 / body 13 / meta 12 /
     caps 10), so this change is pixel-identical. */
  --fw-default:400;
  --fw-emph:500;
}

/* ── Panel ── */
.xw-panel{display:none;animation:xwFade .22s ease;}
.xw-panel.active{display:block;}
@keyframes xwFade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.xw-panel-title{
  font-size:22px;font-weight:500;color:var(--xw-text);margin:0 0 6px;
  font-family:var(--xw-serif);letter-spacing:0;}
.xw-panel-sub{font-size:13px;color:var(--xw-muted);margin:0 0 32px;line-height:1.6;}

/* ── Upload drop zone ── */
.xw-drop{
  border:1.5px solid rgba(26,26,26,0.2);border-radius:2px;padding:64px 32px;
  text-align:center;cursor:pointer;transition:border-color .15s,background .15s;
  background:transparent;position:relative;}
.xw-drop:hover,.xw-drop.over{border-color:#1a1a1a;background:rgba(26,26,26,0.02);}
.xw-drop input[type=file]{position:absolute;inset:0;opacity:0;cursor:pointer;width:100%;height:100%;}
/* The icon/label/hint sit on top of the invisible file input. Without this,
   clicks landing on them (e.g. WP's emoji <img> that replaces the ⬆ glyph)
   never reach the input, so the file dialog only opens from the bare padding —
   making the drop area feel like it needs many clicks. Let every click through. */
.xw-drop-icon,.xw-drop-label,.xw-drop-hint,.xw-drop-icon *{pointer-events:none;}
.xw-drop-icon{font-size:32px;margin-bottom:16px;display:block;color:#1a1a1a;opacity:.3;}
.xw-drop-label{font-size:15px;font-weight:500;color:#1a1a1a;margin:0 0 8px;}
.xw-drop-hint{font-size:12px;color:#aaa;margin:0;letter-spacing:.04em;}
.xw-file-preview{
  display:none;align-items:center;gap:16px;padding:16px 20px;
  background:#f5f5f5;border-radius:4px;margin-top:16px;}
.xw-file-preview.show{display:flex;}
.xw-file-thumb{width:52px;height:52px;object-fit:cover;border-radius:3px;background:#e0e0e0;}
.xw-file-info{flex:1;min-width:0;}
.xw-file-name{font-weight:600;color:#111;font-size:14px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.xw-file-meta{font-size:12px;color:#888;margin-top:3px;}
/* 40×40 hit area (the visible × stays 18px) — the 28px box failed the
   ~44px touch-target guideline on phones; flex-centring keeps the glyph
   put and the card row is 52px tall so it doesn't grow the layout. */
.xw-file-remove{background:none;border:none;color:#aaa;cursor:pointer;font-size:18px;
  line-height:1;flex:0 0 auto;width:40px;height:40px;padding:0;
  display:flex;align-items:center;justify-content:center;}
.xw-file-remove:hover{color:#8B0404;}
.xw-upload-progress{height:3px;background:#e0e0e0;border-radius:2px;margin-top:8px;overflow:hidden;}
.xw-upload-progress-bar{height:100%;background:#8B0404;width:0;transition:width .3s;}

/* ── Paper selection ── */
.xw-paper-preview{display:none;max-width:100%;max-height:340px;width:auto;height:auto;
  margin:0 auto 28px;border-radius:4px;}
.xw-paper-preview.show{display:block;}
@media(max-width:600px){.xw-paper-preview{max-height:240px;}}
.xw-cat-pills{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:28px;}
.xw-cat-pill{background:transparent;border:1.5px solid #d0d0d0;padding:7px 13px;
  cursor:pointer;font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  color:#444;border-radius:2px;transition:all .15s;font-family:inherit;}
.xw-cat-pill:hover{border-color:#8B0404;color:#8B0404;}
.xw-cat-pill.on{background:#8B0404;border-color:#8B0404;color:#fff;}
.xw-papers{display:grid;grid-template-columns:1fr;gap:1px;border:1px solid #ebebeb;}
.xw-paper-row{
  display:flex;gap:20px;align-items:center;padding:20px 24px;
  background:#fff;cursor:pointer;transition:background .12s;border:2px solid transparent;}
.xw-paper-row:hover{background:#fafafa;}
.xw-paper-row.selected{border-color:#8B0404;background:#fff9f9;}
.xw-paper-img{width:72px;height:52px;object-fit:cover;border-radius:3px;flex-shrink:0;}
.xw-paper-name{font-size:15px;font-weight:600;color:#111;margin:0 0 3px;}
.xw-paper-type{font-size:12px;color:#999;text-transform:uppercase;letter-spacing:.05em;margin:0 0 2px;}
.xw-paper-group{margin:2px 0 3px;font-size:11px;letter-spacing:.03em;line-height:1.4;}
/* Underline via text-decoration (not border-bottom) so the padded hit area
   below can grow to a tappable height without the dotted line detaching
   from the glyphs. Negative margin cancels the padding so the compact card
   rhythm is visually unchanged; font stays 11px (compact tier). */
.xw-paper-group a{color:#6b7c8d;display:inline-block;
  text-decoration:underline dotted #c0c0c0;text-underline-offset:2px;
  padding:6px 4px;margin:-6px -4px;transition:color .15s,text-decoration-color .15s;}
.xw-paper-group a:hover{color:#8B0404;text-decoration-color:#8B0404;}
.xw-paper-group a::after{content:' ↗';font-size:10px;opacity:.55;margin-left:1px;}
.xw-paper-size{font-size:13px;color:#666;margin:0;}
.xw-paper-price{font-size:11px;letter-spacing:.04em;color:#8a8a8a;margin:6px 0 0;}
.xw-paper-price strong{color:#1a1a1a;font-weight:600;}
.xw-paper-check{margin-left:auto;width:24px;height:24px;border-radius:50%;
  border:2px solid #ddd;flex-shrink:0;display:flex;align-items:center;
  justify-content:center;transition:all .15s;}
.xw-paper-row.selected .xw-paper-check{background:#8B0404;border-color:#8B0404;}
.xw-paper-check::after{content:'✓';color:#fff;font-size:13px;font-weight:700;display:none;}
.xw-paper-row.selected .xw-paper-check::after{display:block;}
.xw-no-papers{color:#aaa;font-size:14px;font-style:italic;padding:24px 0;}
.xw-paper-row.xw-backorder{opacity:.55;cursor:not-allowed;}
.xw-paper-row.xw-backorder:hover{background:#fff;}
.xw-paper-row.xw-backorder .xw-paper-check{visibility:hidden;}
.xw-paper-instore{display:inline-block;margin-top:6px;font-size:11px;letter-spacing:.04em;
  text-transform:uppercase;color:#8B0404;border:1px solid #8B0404;
  padding:2px 6px;border-radius:2px;font-weight:600;}

/* ── Size ── */
.xw-sizes{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:10px;margin-bottom:20px;}
.xw-size-card{
  border:1.5px solid #e0e0e0;border-radius:4px;padding:18px 16px;
  cursor:pointer;transition:all .15s;text-align:center;background:#fff;}
.xw-size-card:hover{border-color:#8B0404;}
.xw-size-card.selected{border-color:#8B0404;background:#fff9f9;}
.xw-size-group{
  grid-column:1/-1;
  margin:14px 0 2px;
  font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.08em;
  color:var(--xw-muted,#6b7c8d);
  border-bottom:1px solid rgba(26,26,26,.10);
  padding-bottom:6px;
}
.xw-size-group:first-child{margin-top:0;}
.xw-size-name{font-size:15px;font-weight:700;color:#111;margin:0 0 4px;}
.xw-size-dims{font-size:12px;color:#888;margin-bottom:4px;}
.xw-size-dpi{font-size:11px;font-weight:600;margin-top:5px;display:flex;align-items:center;justify-content:center;gap:4px;}
.xw-size-match{font-size:10px;color:#2e7d32;letter-spacing:.04em;margin-top:3px;text-transform:uppercase;font-weight:700;}

/* ── DPI tooltip ── */
.xw-dpi-info{
  display:inline-flex;align-items:center;justify-content:center;
  width:14px;height:14px;border-radius:50%;border:1.5px solid currentColor;
  font-size:9px;font-weight:700;cursor:help;flex-shrink:0;
  position:relative;line-height:1;
}
/* Tooltips for every .xw-dpi-info[data-tip] icon are rendered by JS into a
   single #xwTip element fixed to the viewport, so they can never be clipped
   by the wizard's overflow-x:hidden wrapper or the responsive size grid
   (the old ::after approach was cut off for right-column cards). */
#xwTip{
  position:fixed;z-index:10001;
  background:#111;color:#fff;
  padding:10px 13px;border-radius:4px;
  font-size:12px;font-weight:400;line-height:1.55;
  max-width:320px;white-space:pre-line;text-align:left;
  box-shadow:0 4px 12px rgba(0,0,0,.25);
  opacity:0;pointer-events:none;transition:opacity .12s;
}
#xwTip.show{opacity:1;}
/* ── Size step: mode toggle (recommended vs custom) ── */
.xw-size-mode{display:flex;gap:4px;margin-bottom:24px;}
.xw-custom-note{
  display:none;
  font-size:11px;letter-spacing:.04em;color:#8a8a8a;
  margin:8px 0 0;font-style:italic;}
.xw-custom-note.show{display:block;}
.xw-size-error{
  margin:8px 0 0;font-size:12px;font-weight:600;
  letter-spacing:.02em;color:#8B0404;line-height:1.45;}
.xw-size-error[hidden]{display:none;}
.xw-custom-size.has-error input{border-color:#8B0404;}
.xw-custom-dpi{
  margin-top:12px;
  font-size:11px;font-weight:500;letter-spacing:.04em;
  display:flex;align-items:center;gap:6px;
}
.xw-mode-btn{
  background:transparent;border:1px solid var(--xw-border);border-radius:2px;
  height:var(--xw-h);padding:0 16px;
  font-family:var(--xw-sans);font-size:11px;font-weight:500;
  letter-spacing:.09em;text-transform:uppercase;color:#666;
  cursor:pointer;transition:all .15s;}
.xw-mode-btn:hover{border-color:var(--xw-text);color:var(--xw-text);}
.xw-mode-btn.on{background:var(--xw-text);border-color:var(--xw-text);color:#f5f0e8;}
/* Fixed two-up grid — Width | Height on the top row, Resolution full-width
   below — held in EVERY language and width so the box never reflows on label
   length (the ×/@ inline layout used to deform in ES/PT/FR/IT). Drops to a
   single column only on a very narrow box via the container query further down. */
.xw-custom-size{display:none;
  grid-template-columns:1fr 1fr;column-gap:20px;row-gap:18px;align-items:center;
  padding:20px;background:#f9f9f9;border:1.5px solid #e0e0e0;border-radius:4px;margin-top:8px;}
.xw-custom-size.show{display:grid;}
.xw-custom-size label{font-size:13px;color:#555;font-weight:600;min-width:0;}
.xw-custom-size input{
  flex:0 1 80px;min-width:54px;padding:8px 10px;border:1.5px solid #d0d0d0;border-radius:3px;
  font-size:14px;font-family:inherit;text-align:center;}
.xw-custom-size input:focus{border-color:#8B0404;outline:none;}
.xw-size-unit{font-size:13px;color:#888;}

/* ── Size picker modal — size controls reused inside the dark MF-style modal ── */
.xw-size-overlay .xw-mf-modal{width:min(640px,94vw);}
.xw-size-overlay .xw-size-mode{margin-bottom:20px;}
.xw-size-overlay .xw-mode-btn{
  border-color:rgba(245,240,232,.3);color:rgba(245,240,232,.7);}
.xw-size-overlay .xw-mode-btn:hover{border-color:#f5f0e8;color:#f5f0e8;}
.xw-size-overlay .xw-mode-btn.on{
  background:#f5f0e8;border-color:#f5f0e8;color:#1a1a1a;}
/* Trailing space inside the scroll area so the last size card scrolls fully
   clear of the sticky Done button + its upward shadow (otherwise the bottom
   card was half-swallowed by the fade at max scroll). */
.xw-size-overlay .xw-sizes{margin-bottom:0;padding-bottom:24px;}
.xw-size-overlay .xw-size-group{
  color:rgba(245,240,232,.65);border-bottom-color:rgba(245,240,232,.15);}

/* ── Size picker modal — manual W×H entry (respects paper limits) ── */
.xw-size-manual{
  margin:0 0 22px;padding:16px 18px;
  border:1px solid rgba(245,240,232,.18);border-radius:4px;
  background:rgba(245,240,232,.04);
}
.xw-size-manual-or{
  display:flex;align-items:center;gap:10px;
  font-size:11px;font-weight:500;letter-spacing:.09em;text-transform:uppercase;
  color:rgba(245,240,232,.6);margin:0 0 14px;
}
.xw-size-manual-or::before,.xw-size-manual-or::after{
  content:"";flex:1;height:1px;background:rgba(245,240,232,.15);
}
.xw-size-manual-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
.xw-msm-pair{display:flex;align-items:center;gap:6px;}
.xw-msm-pair label{font-size:12px;font-weight:600;color:rgba(245,240,232,.7);}
.xw-msm-x{color:rgba(245,240,232,.5);font-size:14px;}
.xw-size-manual .xw-size-unit{color:rgba(245,240,232,.6);}
.xw-size-manual input{
  width:74px;padding:8px 10px;border-radius:3px;
  border:1.5px solid rgba(245,240,232,.25);
  background:rgba(0,0,0,.25);color:#f5f0e8;
  font-size:14px;font-family:inherit;text-align:center;
}
.xw-size-manual input:focus{border-color:#f5f0e8;outline:none;}
/* Cream-on-dark so it reads as the action on the #1a1a1a modal (a plain
   primary button is #1a1a1a-on-#1a1a1a — invisible). Mirrors the active
   mode toggle's treatment. Scoped under .xw-size-overlay so it beats the
   later, equal-specificity .xw-btn-primary rule. */
.xw-size-overlay .xw-msm-apply,
.xw-size-overlay .xw-msm-apply:hover{
  margin-left:auto;width:auto;height:var(--xw-h);padding:0 22px;
  font-size:11px;letter-spacing:.09em;text-transform:uppercase;
  background:#f5f0e8;border-color:#f5f0e8;color:#1a1a1a;
}
.xw-size-overlay .xw-msm-apply:hover{background:#fff;border-color:#fff;}
.xw-size-overlay .xw-msm-apply:disabled{background:rgba(245,240,232,.25);border-color:transparent;color:rgba(245,240,232,.5);cursor:not-allowed;}
.xw-size-manual-dpi{
  margin-top:12px;font-size:11px;font-weight:500;letter-spacing:.04em;
  display:none;align-items:center;gap:6px;
}
.xw-size-manual .xw-msm-error{margin-top:10px;color:#ff8a80;}
/* Operator disabled custom dimensions → no manual entry in the picker either. */
.xw-size-manual[hidden]{display:none;}

/* Each pair fills its grid cell: label left, input centred, unit right. */
.xw-cs-pair{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;}
/* The decorative × / @ separators have no place in the fixed grid. */
.xw-cs-x{display:none;}
/* Resolution gets its own full-width row beneath Width & Height. */
.xw-cs-pair:has(#xwCDPI){grid-column:1 / -1;}
/* The recommended-size hint "i" is redundant with the Browse-sizes button below
   and has no clean slot in the grid — hidden in every language and width. */
#xwCustomHint{display:none;}

/* Container query — only a very narrow box (small phones, or a tight review
   column) drops Width & Height onto their own rows. Above this the layout is
   byte-for-byte identical across languages; it never depends on label length. */
.xw-option-group:has(.xw-custom-size){container-type:inline-size;}
@container (max-width:340px){
  .xw-custom-size.show{grid-template-columns:1fr;}
}

/* ── Options ── */
.xw-option-group{margin-bottom:28px;}
/* Breathing room between the preview (incl. its Sheet / Image area dims
   block) and the white-border selector that follows directly below it. */
#xwReviewPreview{margin-bottom:20px;}
/* .xw-option-label is defined once, later in this stylesheet ("Option label — harmonised"). */
/* Segmented control — shared border, no size shift on active */
.xw-radio-row{display:flex;flex-wrap:wrap;gap:4px;}
.xw-radio-card{
  border:1px solid var(--xw-border);border-radius:2px;
  height:var(--xw-h);padding:0 12px;
  display:inline-flex;align-items:center;justify-content:center;
  cursor:pointer;font-size:11px;letter-spacing:.04em;text-transform:uppercase;
  color:#666;transition:background .12s,color .12s,border-color .12s;
  background:transparent;font-weight:500;white-space:nowrap;}
.xw-radio-card:hover{border-color:var(--xw-text);color:var(--xw-text);}
.xw-radio-card.on{background:var(--xw-text);border-color:var(--xw-text);color:#f5f0e8;}
.xw-radio-card input{display:none;}
/* Border selector specifically (#xwBorder is the only .xw-radio-row): keep all
   five choices — No border · 1 · 2 · 4 · Custom — on ONE row across the widest
   range. flex:1 fills the half-width column on desktop as a tidy segmented
   control, and the trimmed padding + slightly tighter caps tracking shrink each
   card's minimum enough to stay single-row down to ~360px phones. Below that the
   inherited flex-wrap drops them to a second row gracefully (layout can't fit). */
#xwBorder{gap:3px;}
#xwBorder .xw-radio-card{flex:1 1 auto;padding:0 6px;letter-spacing:.06em;}

/* ── Mounting cards ── */
.xw-mount-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:6px;margin-top:0}
.xw-mount-card{
  border:1px solid var(--xw-border);border-radius:2px;cursor:pointer;
  transition:border-color .15s,background .15s;background:transparent;}
.xw-mount-card:hover{border-color:var(--xw-text);}
.xw-mount-card.on{border-color:var(--xw-text);background:rgba(26,26,26,.03);}
.xw-mount-card-inner{padding:16px;}
.xw-mount-name{font-size:14px;font-weight:500;color:var(--xw-text);margin:0 0 4px;}
.xw-mount-desc{font-size:12px;color:var(--xw-muted);line-height:1.5;margin:0 0 10px;}
.xw-mount-price{font-size:12px;font-weight:600;color:var(--xw-text);margin:0;}

/* ── Framing notice ── */
.xw-framing-notice{
  display:flex;gap:16px;align-items:flex-start;
  padding:20px;border:1px solid var(--xw-border);border-radius:2px;
  background:rgba(26,26,26,.02);opacity:.65;}
.xw-framing-icon{font-size:24px;flex-shrink:0;margin-top:2px;}
.xw-framing-title{font-size:14px;font-weight:500;color:var(--xw-text);margin:0 0 6px;}
.xw-framing-desc{font-size:13px;color:var(--xw-muted);line-height:1.6;margin:0 0 10px;}
.xw-framing-link{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--xw-text);text-decoration:none;font-weight:500;}
.xw-framing-link:hover{text-decoration:underline;}

/* Mounting / framing dropdown */
.xw-mount-select{
  width:100%;max-width:320px;
  height:var(--xw-h);padding:0 10px;
  border:1px solid var(--xw-border);border-radius:2px;
  background:transparent;font-family:var(--xw-sans);
  font-size:12px;color:var(--xw-text);cursor:pointer;
  -webkit-appearance:none;appearance:none;
}
.xw-mount-select:focus{outline:none;border-color:var(--xw-text);}
.xw-mount-select:disabled{opacity:.35;cursor:not-allowed;background:#f5f0e8;}
/* Step-3 "quick paper change" dropdown — match the full width of the print-size
   box directly above it (the generic .xw-mount-select caps at 320px, which left
   it visibly narrower), and add an explicit chevron so it reads as a clickable
   menu rather than a plain bordered box (appearance:none strips the native one). */
#xwPaperSelect{
  max-width:none;
  padding-right:34px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%231a1a1a' stroke-width='1.5' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 12px center;
}
/* Greyed-out "coming soon" option group */
.xw-option-group--muted .xw-option-label{opacity:.4;}
.xw-coming-soon{
  font-size:9px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:#fff;background:#aaa;border-radius:2px;padding:2px 5px;margin-left:6px;
  vertical-align:middle;
}
/* ── Combined options + review grid ── */
/* minmax(0,1fr) — without it the auto min-content allows a tall portrait image
   (intrinsic pixel width 3000+) to blow out the left column and crush the right. */
/* Preview column gets the larger share — the artwork preview benefits from the
   room more than the options form (which is mostly fixed-width controls). */
.xw-or-grid{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);
  gap:48px;align-items:start;margin-bottom:8px;}
.xw-or-grid > *{min-width:0;}
.xw-or-left{}
.xw-or-right{position:sticky;top:24px;}
@media(max-width:720px){
  .xw-or-grid{grid-template-columns:1fr;}
  /* On mobile preview comes first (visual), options second */
  .xw-or-right{order:-1;position:static;}
}

/* Review table + price row styling lives in a single block lower in this file
   (search "── Review table ──"). The duplicates that used to live here were
   silently overriding the canonical declarations — removed. */

/* ── Review preview ── */
.xw-preview-outer{
  padding:24px;border-radius:6px;background:transparent;
  display:flex;align-items:center;justify-content:center;
  margin-bottom:16px;
  /* Hard cap so panoramic prints don't push navigation off screen.
     min-height is set dynamically by pinPreviewHeight() (portrait orientation),
     but never exceeds this maximum. */
  max-height:min(700px, 74vh);
  overflow:visible;   /* keep mat drop-shadow visible */
}
@media(max-width:720px){
  .xw-preview-outer{padding:20px 16px;}
}

/* Frame wrapper — always present, drop shadow always on */
.xw-frame{
  width:100%;max-width:560px;
  /* Panoramic prints: never let the mat grow taller than the capped container */
  max-height:min(660px, 70vh);
  display:flex;align-items:center;justify-content:center;
  border-radius:3px;box-sizing:border-box;
  transition:padding .25s ease;}

/* Oak profile applied via inline styles in JS — no CSS class needed */

/* ── Mount/Frame modal ── */
.xw-mf-overlay{
  display:none;
  position:fixed;inset:0;
  background:rgba(0,0,0,.72);  /* stronger scrim */
  z-index:9999;
}
.xw-mf-overlay.open{display:block;}
.xw-mf-modal{
  position:fixed;
  top:50%;left:50%;
  transform:translate(-50%,-50%);
  z-index:10000;
  background:#1a1a1a;     /* dark modal — no light-on-light problem */
  color:#f5f0e8;
  border:1px solid rgba(255,255,255,.12);
  border-radius:3px;
  padding:36px 40px 32px;
  width:min(480px, 92vw);
  max-height:88vh;overflow-y:auto;
  box-shadow:0 16px 60px rgba(0,0,0,.6);
}
.xw-mf-title{
  font-family:'EB Garamond',Georgia,serif;font-size:22px;font-weight:500;
  margin:0 0 28px;color:#f5f0e8;
}
/* Keep Confirm reachable without scrolling inside a tall modal on small
   viewports — pin it to the bottom of the scroll area. */
.xw-mf-confirm{
  width:100%;
  position:sticky;
  bottom:-32px;            /* cancel the modal's 32px bottom padding */
  margin-top:28px;
  padding-bottom:14px;
  background:#1a1a1a;      /* match modal so scrolled content hides behind */
  box-shadow:0 -16px 18px 6px #1a1a1a;
}
.xw-mf-close{
  position:absolute;top:16px;right:18px;
  background:none;border:none;cursor:pointer;
  font-size:20px;line-height:1;color:rgba(245,240,232,.5);
  padding:4px;
}
.xw-mf-close:hover{color:#f5f0e8;}
/* Labels and selects inside modal — override wizard defaults for dark bg */
.xw-mf-modal .xw-option-label{color:rgba(245,240,232,.6);}
.xw-mf-modal .xw-mount-select{
  background:#2a2a2a;
  color:#f5f0e8;
  border-color:rgba(255,255,255,.15);
}
.xw-mf-modal .xw-mount-select:focus{border-color:rgba(255,255,255,.4);outline:none;}
.xw-mf-modal .xw-mount-select:disabled{opacity:.35;}
.xw-mf-modal .xw-coming-soon{background:rgba(255,255,255,.15);color:#f5f0e8;}

/* ── Native-size choice dialog (resize sheet vs keep sheet) ── */
.xw-native-modal{width:min(440px,92vw);}
.xw-native-modal .xw-mf-title{margin-bottom:16px;}
.xw-native-body{
  margin:0 0 24px;font-size:14px;line-height:1.55;color:rgba(245,240,232,.85);
}
.xw-native-actions{display:flex;flex-direction:column;gap:10px;}
/* Cream-on-dark primary — same #1a1a1a-on-#1a1a1a trap as the size-modal
   Apply; scoped so it beats the later, equal-specificity .xw-btn-primary. */
.xw-native-modal .xw-btn-primary,
.xw-native-modal .xw-btn-primary:hover,
.xw-native-modal .xw-btn-primary:focus{
  background:#f5f0e8;border-color:#f5f0e8;color:#1a1a1a;width:100%;
}
.xw-native-modal .xw-btn-primary:hover{background:#fff;border-color:#fff;}
/* Secondary stays outlined but must read on the dark card (and keep its own
   background on hover/focus — the Astra neutraliser blanks it otherwise). */
.xw-native-modal .xw-btn:not(.xw-btn-primary),
.xw-native-modal .xw-btn:not(.xw-btn-primary):hover,
.xw-native-modal .xw-btn:not(.xw-btn-primary):focus{
  background:transparent;border:1.5px solid rgba(245,240,232,.4);color:#f5f0e8;width:100%;
}
.xw-native-modal .xw-btn:not(.xw-btn-primary):hover{border-color:#f5f0e8;}

/* "Add Mount or Frame" trigger button */
.xw-mf-trigger{
  display:flex;align-items:center;justify-content:center;
  width:100%;margin-top:20px;margin-bottom:24px;
  /* min-height (not a fixed height) so the button keeps its single-line size in
     EN but grows for languages whose label wraps to two lines (PT/FR/IT) —
     a fixed height crushed the wrapped lines together. */
  min-height:var(--xw-h);
  padding:8px 14px;
  background:transparent;
  border:1px solid var(--xw-border);
  border-radius:2px;
  font-family:var(--xw-sans);font-size:10px;font-weight:500;
  letter-spacing:.09em;text-transform:uppercase;line-height:1.35;
  text-align:center;
  color:var(--xw-accent);
  cursor:pointer;
  transition:border-color .15s,color .15s;
}
/* background:transparent re-asserted on hover — Astra's generic button:hover
   injects background:var(--ast-global-color-1) (dark red) otherwise, landing
   behind this outline button's dark text. .is-on / .is-on:hover are more
   specific and keep the engaged filled look. */
.xw-mf-trigger:hover{background:transparent;border-color:var(--xw-accent);color:var(--xw-accent);opacity:.8;}
/* :focus / :active — after a click the button keeps focus with no hover, and
   Astra's generic button:focus/:active leaves the theme's WHITE text on our
   transparent button, making the label disappear (e.g. "Set native file image
   size" went invisible post-click). Re-assert the outline-button colours so the
   text stays readable. Mirror :hover for the base, and keep the filled inverted
   text for the engaged (.is-on) variant. */
.xw-mf-trigger:focus,
.xw-mf-trigger:focus-visible,
.xw-mf-trigger:active{background:transparent;border-color:var(--xw-accent);color:var(--xw-accent);outline:none;}
.xw-mf-trigger.is-on:focus,
.xw-mf-trigger.is-on:focus-visible,
.xw-mf-trigger.is-on:active{background:var(--xw-text);border-color:var(--xw-text);color:#f5f0e8;}
.xw-mf-trigger.has-selection{color:var(--xw-text);border-color:var(--xw-text);}
/* Engaged toggle (e.g. Fill sheet on) — matches the wizard's selected-control
   look (radio cards / mode buttons): filled, inverted text. */
.xw-mf-trigger.is-on{background:var(--xw-text);border-color:var(--xw-text);color:#f5f0e8;}
.xw-mf-trigger.is-on:hover{opacity:.9;color:#f5f0e8;}
/* Pair the "set native size" button tightly under the browse-sizes trigger
   (they're two halves of the same size control, not separate sections). */
#xwSizeBrowseTrigger{margin-bottom:8px;}
.xw-mf-trigger.xw-set-native{margin-top:0;}

/* ── Hover action icons — modernist / purist ── */
.xw-frame{position:relative;}

.xw-hover-actions{
  position:absolute;
  bottom:16px;
  left:50%;transform:translateX(-50%);
  display:flex;gap:10px;
  opacity:0;pointer-events:none;
  transition:opacity .2s ease;
  z-index:20;
}
.xw-frame:hover .xw-hover-actions{
  opacity:1;pointer-events:auto;
}
.xw-ha-btn{
  width:40px;height:40px;
  border-radius:3px;
  background:rgba(10,10,10,.72);
  border:none;
  cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  color:#fff;
  transition:background .12s;
  padding:0;
}
/* Defend the background in the :focus/:active states. Astra/WP ship a global
   reset `button,button:hover,button:focus{background-color:transparent}`
   (specificity 0,1,1) that outranks .xw-ha-btn (0,1,0). Clicking a button
   leaves it focused, so with the mouse off it the reset wiped the pill to
   transparent — white icon on the white sheet ("background disappears after
   clicking, unless hovering"; only :hover was beating the reset). These rules
   (0,2,0) win it back. */
.xw-ha-btn:focus,.xw-ha-btn:focus-visible,.xw-ha-btn:active{background:rgba(10,10,10,.72);}
.xw-ha-btn:hover{background:rgba(10,10,10,.92);}
.xw-ha-btn.on{background:rgba(180,30,30,.85);}
.xw-ha-btn svg{width:22px;height:22px;display:block;overflow:visible;}

/* Mat: shadow always on, regardless of frame state */
.xw-preview-mat{
  width:100%;background:#fff;
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 6px 28px rgba(0,0,0,.20), 0 2px 8px rgba(0,0,0,.10);
  position:relative;z-index:1;}
.xw-preview-img-slot{
  position:relative;overflow:hidden;
  flex-shrink:0;touch-action:none;}
.xw-preview-img-slot.draggable{cursor:grab;}
.xw-preview-img-slot.draggable:active{cursor:grabbing;}
.xw-preview-img-slot img{
  display:block;
  position:absolute;top:50%;left:50%;
  transform-origin:center center;
  /* Safety: cap to slot before JS sets explicit pixel sizes — prevents
     intrinsic image width from forcing the grid column to overflow. */
  max-width:100%;max-height:100%;
  /* No object-fit: JS sizes the img box proportionally to the actually-loaded
     image's naturalWidth/Height (see imgDimsAt) so the box aspect always
     matches the image aspect — default `fill` is then a visual no-op. */
  /* No CSS transitions — JS rAF loop handles animation */
  will-change:transform,width,height;}
.xw-preview-placeholder{
  width:100%;aspect-ratio:1/1.414;background:#e8e8e8;
  display:flex;align-items:center;justify-content:center;
  color:#aaa;font-size:13px;}
.xw-preview-controls{
  display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:28px;
  max-width:100%;min-width:0;}
/* ── All buttons share height + font ── */
.xw-preview-btn,
.xw-btn {
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  height:var(--xw-h);padding:0 16px;
  font-size:10px;letter-spacing:.09em;text-transform:uppercase;font-weight:500;
  font-family:var(--xw-sans);
  border:1px solid var(--xw-border);border-radius:2px;
  background:transparent;color:var(--xw-text);
  cursor:pointer;transition:border-color .15s,background .15s,color .15s;
  white-space:nowrap;flex-shrink:0;
}
/* background:transparent re-asserted on hover so Astra's generic
   button:hover (background:var(--ast-global-color-1), dark red) can't fill
   these outline buttons behind their dark text. .xw-btn-primary:hover (later,
   equal specificity) re-sets its own #000; .xw-preview-btn.on stays filled. */
.xw-preview-btn:hover,.xw-btn:hover{background:transparent;border-color:var(--xw-text);}

/* Preview control buttons — slightly smaller */
.xw-preview-btn{height:28px;padding:0 12px;font-size:10px;color:#555;border-color:#ccc;}
.xw-preview-btn.on{background:var(--xw-text);border-color:var(--xw-text);color:#f5f0e8;}

/* Primary nav button */
.xw-btn-primary{background:var(--xw-text);border-color:var(--xw-text);color:#f5f0e8;}
.xw-btn-primary:hover{background:#000;border-color:#000;}
.xw-btn-primary:disabled{background:#c8bfb2;border-color:#c8bfb2;color:#f5f0e8;cursor:not-allowed;}

/* Secondary nav button */
.xw-btn-secondary{color:var(--xw-muted);border-color:#d0c8bc;}
.xw-btn-secondary:hover{border-color:var(--xw-text);color:var(--xw-text);}

/* Qty stepper */
.xw-qty-wrap{display:inline-flex;align-items:center;border:1px solid var(--xw-border);border-radius:2px;overflow:hidden;width:fit-content;}
.xw-qty-btn{
  width:var(--xw-h);height:var(--xw-h);border:none;background:transparent;
  cursor:pointer;font-size:16px;display:flex;align-items:center;justify-content:center;
  color:var(--xw-text);transition:background .12s;}
.xw-qty-btn:hover{background:rgba(26,26,26,.06);}
.xw-qty-val{
  min-width:40px;height:var(--xw-h);
  border-left:1px solid var(--xw-border);border-right:1px solid var(--xw-border);
  /* Use flexbox centering — immune to line-height overrides from the
     typography normalisation block. */
  display:flex;align-items:center;justify-content:center;
  font-size:14px;font-weight:500;color:var(--xw-text);}

.xw-border-custom{display:none;margin-top:12px;flex-direction:column;gap:8px;}
.xw-border-custom.show{display:flex;}
/* 2×2 grid: Top / Right / Bottom / Left */
.xw-border-sides{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:8px;
  max-width:240px;
}
.xw-border-side{
  display:flex;flex-direction:column;gap:4px;
}
.xw-border-side label{
  font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--xw-muted);
  font-weight:500;
}
.xw-border-custom input{
  width:64px;height:var(--xw-h);padding:0 10px;
  border:1px solid var(--xw-border);border-radius:2px;
  font-size:13px;font-family:var(--xw-sans);text-align:center;
  color:var(--xw-text);background:transparent;}
.xw-border-custom input:focus{border-color:var(--xw-text);outline:none;}
.xw-border-unit{font-size:11px;color:var(--xw-muted);letter-spacing:.03em;}

/* Per-file client note textarea — matches the border inputs' look. */
.xw-note-input{
  width:100%;box-sizing:border-box;min-height:56px;resize:vertical;
  padding:8px 10px;border:1px solid var(--xw-border);border-radius:2px;
  font-size:13px;font-family:var(--xw-sans);line-height:1.5;
  color:var(--xw-text);background:transparent;}
.xw-note-input:focus{border-color:var(--xw-text);outline:none;}
.xw-note-input::placeholder{color:var(--xw-muted);}

/* Print size info — replaces inline styles */
.xw-size-info{
  margin:0 0 20px;padding:12px 16px;
  background:rgba(26,26,26,.03);
  border-left:2px solid var(--xw-border);
  border-radius:0;}
.xw-size-info-label{
  font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--xw-muted);font-weight:500;margin-right:8px;}
.xw-size-info-value{
  font-size:13px;color:var(--xw-text);font-weight:500;}
.xw-size-info-sub{
  font-size:11px;color:var(--xw-muted);margin-top:3px;letter-spacing:.02em;}

.xw-roll-ok{color:#2e7d32;font-size:11px;font-weight:500;}
.xw-roll-warn{color:#c62828;font-size:11px;font-weight:500;}

/* Option label — harmonised */
.xw-option-label{
  font-size:10px;font-weight:500;letter-spacing:.1em;
  text-transform:uppercase;color:var(--xw-muted);
  margin:0 0 8px;display:block;}

/* ── Review table ──
   - table-layout:fixed so column widths actually hold
   - file row uses single-line ellipsis (full name already shown under preview)
   - other rows can wrap if needed
*/
.xw-review-table{width:100%;border-collapse:collapse;margin-bottom:28px;table-layout:fixed;}
.xw-review-table tr{border-bottom:1px solid rgba(26,26,26,.06);}
.xw-review-table td{padding:10px 0;font-size:13px;}
.xw-review-table td:first-child{color:var(--xw-muted);width:120px;font-size:11px;text-transform:uppercase;letter-spacing:.06em;}
.xw-review-table td:last-child{color:var(--xw-text);font-weight:500;}
/* File cell: never wrap — truncate with ellipsis. Hover shows full name via title attr. */
.xw-review-table td#rv-file{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.xw-print-row td{padding-top:14px!important;border-top:1.5px solid rgba(26,26,26,.12)!important;}
.xw-print-row td:last-child,
.xw-mount-row td:last-child,
.xw-vat-row td:last-child{font-weight:500;}
.xw-vat-row td{border-bottom:1px solid rgba(26,26,26,.06)!important;}
.xw-price-row td{padding-top:10px!important;border-top:none!important;}
.xw-price-row td:first-child{font-weight:600;color:var(--xw-text)!important;}
.xw-price-row td:last-child{font-size:20px;font-weight:600;font-family:var(--xw-serif);letter-spacing:0;}
.xw-vat-note{margin:6px 0 0;font-size:11px;color:var(--xw-muted);text-align:right;letter-spacing:.02em;}
.xw-vat-note:empty{display:none;}
.xw-price-err{font-size:13px;font-weight:500;color:var(--xw-accent);font-family:var(--xw-sans);letter-spacing:0;}
.xw-price-retry{background:none;border:0;padding:0;font:inherit;color:var(--xw-accent);text-decoration:underline;cursor:pointer;}

/* ── Navigation row ── */
.xw-nav{display:flex;justify-content:space-between;align-items:center;
  margin-top:36px;padding-top:24px;border-top:1px solid rgba(26,26,26,.08);}
/* Step 3 action bar — pinned so the live Total + the single canonical CTA
   stay reachable while the long options column is scrolled. position:fixed
   (not sticky) on purpose: .xw-wrap has overflow-x:hidden, which makes it a
   scroll container and would break bottom-sticky relative to the viewport.
   Only renders on Step 3 because the inactive .xw-panel is display:none.
   .xw-nav-step1 (upload) and .xw-nav-step2 (paper) share the exact same
   pinned-bar treatment so the "Next" CTA stays put while the long file
   queue / paper list is scrolled — same display:none-when-inactive trick. */
.xw-nav-step1,
.xw-nav-step2,
.xw-nav-step3{
  position:fixed; left:12px; right:12px; bottom:12px; z-index:40;
  margin:0 auto; max-width:860px; box-sizing:border-box;
  background:#f5f0e8; border:1px solid var(--xw-border);
  border-radius:14px;
  box-shadow:0 8px 24px rgba(26,26,26,.10);
  padding:10px 16px;
}
.xw-sticky-price{
  font-family:var(--xw-serif); font-size:18px; font-weight:600;
  color:var(--xw-text); white-space:nowrap; margin:0 12px; flex:0 0 auto;}
/* Reserve space so the review table + VAT/exemption note (last in-flow
   content) is never hidden behind the fixed bar when scrolled to the end. */
.xw-panel[data-panel="0"],
.xw-panel[data-panel="1"],
.xw-panel[data-panel="2"]{padding-bottom:88px;}
/* The action bar is viewport-pinned (position:fixed), so at the very bottom of
   the page it overlapped the site footer — the last ~65px of the black footer
   vanished behind the cream bar. Nothing downstream reserved room because the
   footer lives outside .xw-wrap. Reserve a bar's-worth of space below the whole
   page while Step 3 is active so the footer always clears the bar. :has() scopes
   it to Step 3 — other steps and every other page keep their normal bottom edge. */
body:has(.xw-panel[data-panel="0"].active),
body:has(.xw-panel[data-panel="1"].active),
body:has(.xw-panel[data-panel="2"].active){padding-bottom:88px;}
/* While a size / mount modal is open its scrim is only 72% opaque, so the cream
   action bar bled through at the bottom of the dimmed screen (looked brighter
   than the rest of the page behind the scrim). The modal owns the screen — hide
   the bar until it closes. */
body:has(.xw-mf-overlay.open) .xw-nav-step1,
body:has(.xw-mf-overlay.open) .xw-nav-step2,
body:has(.xw-mf-overlay.open) .xw-nav-step3{display:none;}
@media(max-width:600px){
  .xw-nav-step1,
  .xw-nav-step2,
  .xw-nav-step3{left:8px;right:8px;bottom:8px;padding:8px 12px;}
  .xw-sticky-price{font-size:16px;margin:0 8px;}
  /* iOS minimum touch target — the bar's CTA measured 40px tall on phones. */
  .xw-nav-step1 button,
  .xw-nav-step2 button,
  .xw-nav-step3 button{min-height:44px;}
}
.xw-btn-ghost{background:transparent;color:#1a1a1a;padding-left:0;border:none;}
.xw-error{background:#fff2f2;border:1px solid #ffcccc;border-radius:4px;
  padding:12px 16px;font-size:14px;color:#c00;margin-bottom:16px;display:none;}
.xw-error.show{display:block;}

/* ──────────────────────────────────────────────────────────────────────────────
   TYPOGRAPHY NORMALIZATION — collapses the wizard onto 4 sizes.
   Single source of truth: --fs-title / --fs-body / --fs-meta / --fs-caps.
   Loaded LAST so it wins over older per-rule declarations.
   ────────────────────────────────────────────────────────────────────────────── */

/* base — everything is body-sized 13px regular by default */
.xw-wrap, .xw-wrap p, .xw-wrap span, .xw-wrap label,
.xw-wrap td, .xw-wrap th, .xw-wrap input, .xw-wrap button,
.xw-wrap a, .xw-wrap div{
  font-size:var(--fs-body); font-weight:var(--fw-default); line-height:1.55;
  letter-spacing:0;
}

/* serif panel titles — the ONLY display size */
.xw-wrap .xw-panel-title{
  font-family:var(--xw-serif); font-size:var(--fs-title);
  font-weight:var(--fw-emph); line-height:1.2; letter-spacing:0; margin:0 0 8px;
}

/* sub copy under titles */
.xw-wrap .xw-panel-sub,
.xw-wrap .xw-drop-hint,
.xw-wrap .xw-file-meta,
.xw-wrap .xw-paper-size,
.xw-wrap .xw-size-dims,
.xw-wrap .xw-mount-desc,
.xw-wrap .xw-framing-desc{
  font-size:var(--fs-meta); color:var(--xw-muted); font-weight:var(--fw-default);
}

/* uppercase caps — labels, buttons, step labels, table headers, section tags */
.xw-wrap .xw-step-label,
.xw-wrap .xw-cat-pill,
.xw-wrap .xw-radio-card,
.xw-wrap .xw-btn,
.xw-wrap .xw-preview-btn,
.xw-wrap .xw-label-sm,
.xw-wrap .xw-paper-type,
.xw-wrap .xw-size-match,
.xw-wrap .xw-framing-link,
.xw-wrap .xw-review-table td:first-child{
  font-size:var(--fs-caps); font-weight:var(--fw-emph);
  letter-spacing:.09em; text-transform:uppercase; line-height:1.4;
}

/* body-sized emphasised values (file name, paper name, size name, mount name, framing title, qty, table values) */
.xw-wrap .xw-file-name,
.xw-wrap .xw-drop-label,
.xw-wrap .xw-paper-name,
.xw-wrap .xw-size-name,
.xw-wrap .xw-mount-name,
.xw-wrap .xw-framing-title,
.xw-wrap .xw-qty-num,
.xw-wrap .xw-custom-size input,
.xw-wrap .xw-review-table td:last-child{
  font-size:var(--fs-body); font-weight:var(--fw-emph); color:var(--xw-text);
}

/* DPI quality indicator — small but legible */
.xw-wrap .xw-size-dpi{font-size:var(--fs-caps); font-weight:var(--fw-emph); letter-spacing:.04em;}
.xw-wrap .xw-dpi-info{font-size:9px; font-weight:var(--fw-emph);}

/* price row — same body size & sans as every other value, just bolder */
.xw-wrap .xw-price-row td:last-child{
  font-family:inherit; font-size:var(--fs-body); font-weight:var(--fw-emph);
  letter-spacing:0; text-transform:none; color:var(--xw-text);
}
.xw-wrap .xw-price-row td:first-child{
  font-size:var(--fs-caps); font-weight:var(--fw-emph);
  letter-spacing:.09em; text-transform:uppercase;
}

/* step number circles — unchanged size, just consistent weight */
.xw-wrap .xw-step-num{font-size:var(--fs-meta); font-weight:var(--fw-emph); letter-spacing:0;}

/* ── File queue strip ── */
.xw-queue{display:none;flex-wrap:wrap;gap:10px;margin-top:20px;}
.xw-queue.has-files{display:flex;}
.xw-queue-item{
  position:relative;width:72px;cursor:pointer;
  border:2px solid transparent;border-radius:3px;
  transition:border-color .15s;
  flex-shrink:0;
}
.xw-queue-item:hover{border-color:var(--xw-border);}
.xw-queue-item.active{border-color:var(--xw-text);}
.xw-queue-item.done{opacity:.55;}
.xw-queue-item.done::after{
  content:'✓';
  position:absolute;top:3px;right:4px;
  font-size:11px;font-weight:700;color:#fff;
  background:rgba(0,0,0,.55);border-radius:50%;
  width:16px;height:16px;line-height:16px;text-align:center;
}
.xw-queue-item.error{border-color:#c62828;}
.xw-queue-item.error::after{
  content:'!';
  position:absolute;top:3px;right:4px;
  font-size:11px;font-weight:700;color:#fff;
  background:#c62828;border-radius:50%;
  width:16px;height:16px;line-height:16px;text-align:center;
}
.xw-queue-item.error .xw-queue-name{color:#c62828;}
.xw-skip-note{
  position:relative;margin:0 0 14px;padding:10px 30px 10px 12px;
  background:#fbeaea;border:1px solid #e3b4b4;border-radius:4px;
  color:#7a2222;font-size:12px;line-height:1.45;
}
.xw-skip-note strong{display:block;margin-bottom:4px;font-size:12px;}
.xw-skip-note ul{margin:0;padding-left:16px;}
.xw-skip-note li{margin:1px 0;word-break:break-word;}
.xw-skip-note-x{
  position:absolute;top:6px;right:6px;
  width:20px;height:20px;padding:0;line-height:18px;text-align:center;
  background:transparent;border:none;border-radius:50%;
  color:#7a2222;font-size:16px;cursor:pointer;
}
.xw-skip-note-x:hover{background:rgba(122,34,34,.12);}
.xw-queue-thumb{
  width:72px;height:72px;object-fit:cover;border-radius:2px;
  display:block;background:#e8e8e8;
}
.xw-queue-name{
  font-size:9px;color:var(--xw-muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  margin-top:3px;max-width:72px;letter-spacing:.02em;
}
.xw-queue-remove{
  position:absolute;top:-5px;left:-5px;
  width:16px;height:16px;border-radius:50%;
  background:#fff;border:1px solid #ccc;
  font-size:10px;line-height:14px;text-align:center;
  cursor:pointer;display:none;color:#888;
  z-index:2;
}
.xw-queue-item:hover .xw-queue-remove{display:block;}
.xw-queue-add{
  width:72px;height:72px;border:1.5px dashed var(--xw-border);
  border-radius:2px;display:flex;align-items:center;justify-content:center;
  font-size:22px;color:var(--xw-muted);cursor:pointer;
  transition:border-color .15s,color .15s;flex-shrink:0;
  background:transparent;font-family:inherit;
}
.xw-queue-add:hover{border-color:var(--xw-text);color:var(--xw-text);}
/* Queue progress shown in Steps 2–4 when queue has >1 file */
.xw-queue-badge{
  display:none;
  font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;
  color:var(--xw-muted);margin-bottom:16px;
}
.xw-queue-badge.visible{display:block;}
.xw-added-banner{
  background:#eef3ee;border:1px solid #cfe0cf;border-radius:4px;
  color:#2f5d2f;padding:12px 16px;margin:0 0 22px;
  font-size:13px;line-height:1.5;
}
.xw-added-banner strong{font-weight:600;}
.xw-added-banner[hidden]{display:none;}

/* Elegant "apply previous settings to all" call-to-action */
.xw-apply-all{
  display:inline-flex;align-items:center;justify-content:center;
  margin-top:4px;padding:13px 26px;
  font-family:var(--xw-sans);font-size:11px;font-weight:600;
  letter-spacing:.11em;text-transform:uppercase;
  color:#fff;background:#8B0404;border:0;border-radius:2px;
  cursor:pointer;transition:background .15s,transform .05s,box-shadow .15s;
  box-shadow:0 2px 12px rgba(139,4,4,.28);
}
.xw-apply-all:hover{background:#6d0303;box-shadow:0 3px 16px rgba(139,4,4,.36);}
.xw-apply-all:active{transform:translateY(1px);}
.xw-apply-all:disabled{background:#9a9a9a;box-shadow:none;cursor:default;}

/* Full-screen cover during the bulk "apply to all" sweep so the wizard
   never visibly flips through steps per file. */
.xw-bulk-overlay{
  position:fixed;inset:0;z-index:9999;
  background:#f5f0e8;
  display:flex;align-items:center;justify-content:center;
  animation:xwFade .2s ease;
}
.xw-bulk-overlay[hidden]{display:none;}
.xw-bulk-overlay-inner{text-align:center;padding:24px;max-width:420px;}
.xw-bulk-spinner{
  width:34px;height:34px;margin:0 auto 22px;
  border:2px solid rgba(26,26,26,.16);
  border-top-color:#8B0404;border-radius:50%;
  animation:xwSpin .8s linear infinite;
}
@keyframes xwSpin{to{transform:rotate(360deg)}}
/* Inline spinner shown inside the Add-to-cart button while the server works */
.xw-btn-spinner{
  display:inline-block;width:15px;height:15px;
  margin-right:9px;vertical-align:-2px;
  border:2px solid rgba(245,240,232,.35);
  border-top-color:#f5f0e8;border-radius:50%;
  animation:xwSpin .8s linear infinite;
}
.xw-bulk-overlay-title{
  font-family:var(--xw-serif,'EB Garamond',Georgia,serif);
  font-size:21px;color:var(--xw-text);margin:0 0 8px;
}
.xw-bulk-overlay-sub{
  font-family:var(--xw-sans);font-size:13px;color:var(--xw-muted);margin:0;line-height:1.6;
}
/* Indeterminate "working" bar for the large-file add-to-cart overlay
   (#xwAddOverlay). The add is server-side work with no measurable byte
   progress, so the bar animates to show activity, not a real percentage. */
.xw-add-progress{
  margin:20px auto 0;width:240px;max-width:80%;height:6px;
  background:rgba(26,26,26,.12);border-radius:3px;overflow:hidden;
}
.xw-add-progress span{
  display:block;height:100%;width:40%;border-radius:3px;background:#8B0404;
  animation:xwAddSlide 1.15s ease-in-out infinite;
}
@keyframes xwAddSlide{0%{transform:translateX(-110%)}100%{transform:translateX(360%)}}
/* Persistent (non-blocking) caution shown during the sweep when one or more
   mounted prints are too big for standard shipping — survives sub-text updates. */
.xw-bulk-overlay-warn{
  font-family:var(--xw-sans);font-size:12.5px;line-height:1.6;
  color:#8a6d00;margin:14px auto 0;max-width:30em;
}
.xw-bulk-cancel{
  margin-top:22px;background:none;border:0;padding:6px 10px;cursor:pointer;
  font-family:var(--xw-sans);font-size:12px;color:var(--xw-muted);
  text-decoration:underline;text-underline-offset:3px;
}
/* Own the hover background — Astra paints bare buttons dark-red otherwise. */
.xw-bulk-cancel:hover{color:var(--xw-text);background:none;}

/* Inline checkboxes shown inside the "added" banner above the apply-all CTA.
   The user ticks which of paper / size / mount to copy onto the rest before
   clicking the button. Self-contained box rendering (appearance:none + drawn
   border/check) so a theme rule can't hide them. */
.xw-bulk-apply .xw-apply-opts{
  display:flex;flex-wrap:wrap;gap:14px 18px;
  margin:0 0 12px;
  font-family:var(--xw-sans);font-size:13px;color:var(--xw-text);
}
.xw-bulk-apply .xw-apply-opts-label{
  font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--xw-muted);margin-right:4px;align-self:center;
}
.xw-bulk-apply .xw-apply-opts label{
  display:inline-flex;align-items:center;gap:8px;
  cursor:pointer;user-select:none;
}
.xw-bulk-apply .xw-apply-opts input[type=checkbox]{
  -webkit-appearance:none;appearance:none;
  width:18px;height:18px;min-width:18px;flex:0 0 18px;
  margin:0;padding:0;
  border:1.5px solid #8B0404;border-radius:3px;background:#fff;
  box-sizing:border-box;cursor:pointer;position:relative;
  display:inline-block;vertical-align:middle;
}
.xw-bulk-apply .xw-apply-opts input[type=checkbox]:checked{background:#8B0404;}
.xw-bulk-apply .xw-apply-opts input[type=checkbox]:checked::after{
  content:'';position:absolute;left:4px;top:0;
  width:6px;height:11px;border:solid #fff;border-width:0 2px 2px 0;
  transform:rotate(45deg);
}
.xw-bulk-apply .xw-apply-opts input[type=checkbox]:focus-visible{
  outline:2px solid #8B0404;outline-offset:2px;
}
/* Paper checkbox is always on — shown checked but locked (it must travel, or a
   swept file has no product to add). Grey it out so it reads as non-interactive
   rather than an active red tick the user could toggle. */
.xw-bulk-apply .xw-apply-opts label.xw-opt-locked{cursor:default;color:var(--xw-muted);}
.xw-bulk-apply .xw-apply-opts input[type=checkbox]:disabled{
  cursor:default;border-color:#b9b3a8;
}
.xw-bulk-apply .xw-apply-opts input[type=checkbox]:disabled:checked{
  background:#b9b3a8;
}

/* Dropdown variant (Pedro 2026-06-11): paper / size / mounting are full
   <select> pickers defaulting to the last-added file's choice, not copy/skip
   checkboxes. Lay them out as labelled fields that sit side-by-side on desktop
   and stack on narrow screens. */
.xw-bulk-apply .xw-apply-opts--menus{
  display:flex;flex-wrap:wrap;align-items:flex-end;gap:12px 16px;
}
.xw-bulk-apply .xw-apply-opts--menus .xw-apply-opts-label{
  flex:1 0 100%;margin:0 0 2px;
}
.xw-bulk-apply .xw-apply-field{
  display:flex;flex-direction:column;gap:5px;
  flex:1 1 200px;min-width:0;cursor:default;
}
.xw-bulk-apply .xw-apply-field > span{
  font-family:var(--xw-sans);font-size:11px;font-weight:600;
  letter-spacing:.04em;text-transform:uppercase;color:var(--xw-muted);
}
.xw-bulk-apply .xw-apply-field .xw-mount-select{
  width:100%;max-width:none;
  /* appearance:none strips the native chevron — draw one so the field reads as
     a menu, matching the Step-3 quick-change picker. */
  padding-right:34px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%231a1a1a' stroke-width='1.5' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 12px center;
}

/* ── Thumbnail picker — Step 1 when files were pre-uploaded on the home page ── */
#xwPickerGrid{display:none;}
.xw-wrap.xw-picker-on #xwDrop,
.xw-wrap.xw-picker-on #xwProgress,
.xw-wrap.xw-picker-on #xwFilePreview,
.xw-wrap.xw-picker-on #xwFileQueue,
.xw-wrap.xw-picker-on .xw-panel[data-panel="0"] .xw-nav{display:none !important;}
.xw-wrap.xw-picker-on #xwPickerGrid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  gap:14px;margin-top:8px;
}
.xw-pick{
  position:relative;border:1px solid #e3ddd1;background:#fff;cursor:pointer;
  padding:0;text-align:left;font-family:inherit;display:flex;flex-direction:column;
  transition:border-color .15s,box-shadow .15s,transform .1s;
}
.xw-pick:hover{border-color:var(--xw-text);box-shadow:0 4px 14px rgba(0,0,0,.08);}
.xw-pick:active{transform:translateY(1px);}
.xw-pick-thumb{width:100%;aspect-ratio:1/1;object-fit:cover;background:#ece7dc;display:block;}
.xw-pick-name{
  font-size:var(--fs-meta);line-height:1.35;color:var(--xw-text);
  padding:8px 10px;word-break:break-word;
}
.xw-pick.is-done{opacity:.6;}
.xw-pick-badge{
  position:absolute;top:8px;left:8px;background:#2f5d2f;color:#fff;
  font-size:10px;font-weight:600;letter-spacing:.04em;padding:3px 7px;border-radius:2px;
}
.xw-pick.is-uploading{pointer-events:none;}
.xw-pick.is-uploading::after{
  content:'Uploading…';position:absolute;inset:0;display:flex;
  align-items:center;justify-content:center;background:rgba(255,255,255,.72);
  font-size:11px;letter-spacing:.05em;color:var(--xw-muted);
}
.xw-pick-add{
  border:1.5px dashed #cbc3b2;background:transparent;color:var(--xw-muted);
  display:flex;align-items:center;justify-content:center;aspect-ratio:1/1;
  font-size:13px;cursor:pointer;font-family:inherit;
  transition:border-color .15s,color .15s;
}
.xw-pick-add:hover{border-color:var(--xw-text);color:var(--xw-text);}

/* drop-zone icon stays as a glyph, not text */
.xw-wrap .xw-drop-icon{font-size:28px;}

/* qty +/- buttons */
.xw-wrap .xw-qty-btn{font-size:15px; font-weight:var(--fw-default); letter-spacing:0;}

/* error message */
.xw-wrap .xw-error{font-size:var(--fs-body);}

/* ──────────────────────────────────────────────────────────────────────────────
   MOBILE RESPONSIVE PASS
   Single consolidated block — later rules win the cascade, no !important needed.
   ────────────────────────────────────────────────────────────────────────────── */

/* Touch devices: reveal the hover-only rotate/flip/fit-to-frame buttons over
   the print preview. Without this they are completely unreachable on phones
   and tablets. */
@media (hover: none) {
  .xw-hover-actions{opacity:1;pointer-events:auto;}
}

@media (max-width:600px){
  /* Tap targets — override one token, cascades to qty buttons, radio cards,
     mode buttons, mount dropdown, custom-size inputs, qty-val cell. */
  .xw-wrap{--xw-h:40px;}
  .xw-preview-btn{height:36px;padding:0 14px;}

  /* Step indicator — trim label letter-spacing rather than stacking
     (the fixed-height row contract from lines 83-84 / 91-92 must hold). */
  .xw-steps{height:64px;margin-bottom:28px;}
  .xw-step-item{height:64px;}
  .xw-step-label{font-size:9px;letter-spacing:.06em;}
  .xw-step-item:not(:last-child)::after{
    left:calc(50% + 18px);right:calc(-50% + 18px);
  }

  /* DPI tooltip is JS-rendered (#xwTip, viewport-clamped) — no per-breakpoint
     pseudo-element rules needed. */

  /* Custom-size editor keeps the Width|Height-on-top / Resolution-below grid on
     mobile; the container query handles dropping to one column on tiny boxes.
     Only the padding is tightened here. */
  .xw-custom-size{padding:16px;}

  /* Category pills — lift from a 30px box to the 40px (--xw-h) touch target. */
  .xw-cat-pill{min-height:var(--xw-h);display:inline-flex;align-items:center;padding:0 13px;}

  /* Size-step mode toggle — three buttons (CUSTOM SIZE / RECOMMENDED /
     CHOOSE FROM LIST) overflow a 360 px row. Wrap to two rows and let each
     button shrink to fit; allow auto height so labels in any language don't
     get clipped by the fixed --xw-h cap. */
  .xw-size-mode{flex-wrap:wrap;}
  .xw-mode-btn{
    flex:1 1 calc(50% - 4px); min-width:0;
    height:auto; min-height:var(--xw-h);
    padding:8px 10px; white-space:normal; line-height:1.2;
  }

  /* File queue — horizontal scroll strip with edge-bleed (iOS Photos pattern)
     instead of a multi-row wrap pile at 5+ files. */
  .xw-queue{
    flex-wrap:nowrap;
    overflow-x:auto;overflow-y:hidden;
    -webkit-overflow-scrolling:touch;
    scroll-snap-type:x proximity;
    padding-bottom:6px;
    margin-left:-16px;margin-right:-16px;
    padding-left:16px;padding-right:16px;
  }
  .xw-queue-item,.xw-queue-add{scroll-snap-align:start;}

  /* Step indicator — force each item to share viewport equally so all
     4 (Upload/Paper/Size/Options) fit on screen. The default `flex:1`
     keeps `min-width:auto` which prevents shrinking below content width
     and pushes step 4 off-screen. */
  .xw-step-item{min-width:0;flex:1 1 0;}
  .xw-step-num{width:24px;height:24px;font-size:11px;}
  .xw-step-item:not(:last-child)::after{
    left:calc(50% + 14px);right:calc(-50% + 14px);
  }

  /* Dropzone — full-bleed inside the wrap. The 64px side padding was
     designed for desktop and squeezes label/hint text on phones. */
  .xw-drop{padding:40px 16px;}
  .xw-drop-label{font-size:14px;}

  /* Buttons — allow text to shrink instead of overflowing the viewport.
     Desktop sets white-space:nowrap; on phones we allow wrap and let the
     button auto-size, so "Next — Choose Paper" can break into two lines. */
  .xw-btn{
    white-space:normal;
    padding:0 12px;
    font-size:10px;
    line-height:1.2;
    min-width:0;
  }

  /* Step 1 "Next" button row — make the single button take full width
     so it never gets clipped by viewport edge. */
  .xw-panel[data-panel="0"] .xw-nav .xw-btn{flex:1;}

  /* Belt-and-braces: lock the wrap and its descendants to viewport width.
     The wrap already has overflow-x:hidden, but something inside is
     reporting wider intrinsic width — force every block to box-sizing
     border-box and cap at 100% of the wrap. */
  .xw-wrap, .xw-wrap *{box-sizing:border-box;}
  .xw-wrap{max-width:100vw;}
  .xw-panel, .xw-panel-sub, .xw-panel-title{max-width:100%;}
}

/* Astra's fixed scroll-to-top button (#ast-scroll-top, z-index:99) sits at
   the bottom-right of the viewport and, on phone-class viewports where this
   wizard's own fixed action bar (.xw-nav-step3, z-index:40) is effectively
   full-width, lands on top of the primary CTA ("Update cart" / "Add to
   cart") and obscures it. The wizard already has its own bottom nav + step
   indicator, so the theme arrow is redundant here.

   The collision must be killed on BOTH axes: a portrait phone is narrow
   (max-width) but a phone in LANDSCAPE is ~800px wide yet only ~360–430px
   tall, so a width-only query misses it (this was the landscape regression).
   max-height:600px catches landscape phones without catching tablets in
   landscape (≥768px tall) or desktop, where the 860px bar is centred with
   margins and the arrow sits clear. This <style> renders only on the wizard
   page, so the global Astra scroll-to-top is untouched everywhere else. */
@media (max-width:600px), (max-height:600px){
  #ast-scroll-top{display:none!important;}
}

/* Short viewports (landscape phones): the site header + the 72px step
   indicator + 60px top padding pushed almost all wizard content below the
   fold. Reclaim ~55px by trimming the top padding and the step-row margin.
   No circle/connector resize here, so the step-indicator geometry is
   untouched. Portrait phones are tall (>600px) so they never match this. */
@media (max-height:600px){
  .xw-wrap{padding-top:24px;}
  .xw-steps{margin-bottom:20px;}
}

@media (max-width:380px){
  .xw-step-label{font-size:var(--fs-3xs);letter-spacing:.04em;}
  .xw-drop{padding:32px 12px;}
  .xw-step-item:not(:last-child)::after{
    left:calc(50% + 12px);right:calc(-50% + 12px);
  }
}

/* ── Step-3 "actual size" loupe ─────────────────────────────────────────────── */
.xw-loupe{
  position:fixed;
  z-index:99999;
  width:240px;height:240px;          /* must match LSIZE in wizard.js */
  border-radius:50%;
  background-color:#fff;
  border:2px solid rgba(255,255,255,.92);
  box-shadow:0 6px 28px rgba(0,0,0,.38), 0 0 0 1px rgba(0,0,0,.22);
  pointer-events:none;               /* never block pan-drag / hover icons */
  display:none;
  overflow:hidden;
}
/* Inner layer holds the magnified background and rotates to match the on-screen
   image; the circle (.xw-loupe) clips it and the label sits above, upright. */
.xw-loupe-img{
  position:absolute;inset:0;
  background-repeat:no-repeat;
  background-color:#fff;
  transform-origin:center center;
  will-change:transform, background-position;
}
.xw-loupe-label{
  position:absolute;z-index:2;left:50%;bottom:10px;transform:translateX(-50%);
  background:rgba(0,0,0,.6);color:#fff;
  font-size:10px;letter-spacing:.04em;line-height:1;
  padding:3px 9px;border-radius:10px;white-space:nowrap;
}
/* Hint the lens on hover (suppressed in fill mode, which uses grab) */
.xw-preview-img-slot:not(.draggable){cursor:zoom-in;}

/* Quiet one-line affordance telling the customer the preview is zoomable.
   Hidden where the loupe can't fire — touch / coarse pointers with no hover. */
.xw-loupe-hint{
  display:flex;align-items:center;justify-content:center;gap:5px;
  margin:6px 0 0;
  font-size:11px;line-height:1.2;color:#aaa;
  letter-spacing:.01em;
  user-select:none;
}
.xw-loupe-hint svg{flex:none;opacity:.75;}
@media (hover:none),(pointer:coarse){ .xw-loupe-hint{display:none;} }
