/* Configurator design system — shared by the shelf and the bench widgets.
 *
 * Both widgets put `unfn-cfg` on their mount node, so every rule here is
 * scoped under `.unfn-cfg` and neither widget can clobber — or be clobbered
 * by — the Shopify theme it is embedded in. Widget-specific leftovers live in
 * ./widget.css (shelf) and ./bench/widget.css (bench), where the handful of
 * rules that must beat this file are written `.unfn-cfg.unfn-bench …` so the
 * cascade never depends on which stylesheet loaded first.
 *
 * The look, settled 2026-08-19 when the two configurators were reconciled:
 * the SHELF's structure (square canvas card, pill segmented controls, one
 * label/slider/value row, the three-up trust card, the orange pill CTA) in
 * the BENCH's warm palette (warm near-black ink, plywood-toned renders on a
 * #F3F1ED preview ground, white page). Anything that reads as "how the tool
 * is built" comes from the shelf; anything that reads as "what the wood looks
 * like" comes from the bench.
 *
 * The slider progress needs JS: both widgets keep --unfn-fill on each range
 * in sync with its value because WebKit has no ::progress pseudo-element;
 * Firefox gets ::-moz-range-progress instead.
 */
.unfn-cfg {
  /* Surfaces */
  --bg: #ffffff;
  --bg-soft: rgba(21,19,15,0.05);
  --preview: #f3f1ed;          /* warm ground behind every 2D drawing + 3D render */
  /* Ink — warm near-black, from the bench. #101010 read blue-ish next to plywood. */
  --ink: #15130f;
  --ink-soft: rgba(21,19,15,0.62);
  --ink-fade: rgba(21,19,15,0.42);
  --line: rgba(21,19,15,0.10);
  --accent: #f25a38;
  --accent-deep: #d94828;
  --accent-soft: rgba(242,90,56,0.11);
  --green: #1e7a46;
  /* Slider track — the bench's, kept over the shelf's dark two-tone bar: with
     a light groove the orange progress is what the eye follows, where against
     a dark bar the two heavy colours fought each other. */
  --track: rgba(21,19,15,0.13);
  /* Plywood, shared by the 2D drawings and the 3D materials so a build looks
     like the same object whichever view you are in. */
  --wood-top: #eadfce;
  --wood-part: #ddcbb3;
  --wood-line: rgba(21,19,15,0.72);
  --pocket-fill: rgba(242,90,56,0.09);
  --pocket-line: rgba(184,57,32,0.58);
  /* Slider geometry — the mobile block bumps both slightly since fingers are
     blunter than cursors. Deliberately slender: a fat bar with a big solid
     ball read as a toy; the 40px hit strip carries the touch comfort so the
     visible ink can stay refined. */
  --trk-h: 4px;
  --thumb-d: 19px;
  --radius-card: 20px;
  --radius-inner: 12px;
  --shadow-card: 0 1px 2px rgba(21,19,15,0.04), 0 12px 32px rgba(21,19,15,0.07);
  --serif: "Instrument Serif", Georgia, serif;
  --sans: "Instrument Sans", system-ui, -apple-system, sans-serif;
  --mono: "SF Mono", Menlo, Consolas, monospace;

  width: 100%;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
}
.unfn-cfg, .unfn-cfg * { box-sizing: border-box; }
.unfn-cfg button, .unfn-cfg input { font: inherit; }
.unfn-cfg ::selection { background: var(--ink); color: #f2efec; }
.unfn-cfg .unfn-visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.unfn-cfg .unfn-layout { display: grid; grid-template-columns: 1.25fr 0.9fr; gap: 28px; align-items: start; }

/* ---- cards ---- */
/* One card recipe for the canvas, the build panel, the buy panel and the
   trust badges, so the page reads as a family of soft white cards. The
   hairline is an inset shadow rather than a border: the page ground is white
   now, and a real border would change every card's box by 2px. */
.unfn-cfg .unfn-card,
.unfn-cfg .unfn-canvas-card {
  background: var(--bg);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card), inset 0 0 0 1px var(--line);
}

/* ---- stage ---- */
.unfn-cfg .unfn-stage { position: sticky; top: 18px; min-width: 0; }
/* Square: the preview is the product — customers need the render as big as
   the column allows, and a square viewBox fills a square card edge to edge
   (a taller card would just letterbox it into empty margins). */
.unfn-cfg .unfn-canvas-card { padding: 14px 16px 16px; aspect-ratio: 1 / 1; display: flex; flex-direction: column; }
/* Top bar inside the card: 2D|3D segmented control on the left, Front|Top on
   the right (2D only — it hides keeping its space while 3D is up), and the
   first-run orbit hint riding the same row absolutely. */
.unfn-cfg .unfn-cardbar { position: relative; display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 8px; container: unfn-cardbar / inline-size; }
.unfn-cfg .unfn-hidden-pill { visibility: hidden; }

/* The warm ground every preview is painted onto — 2D drawing or 3D canvas. */
.unfn-cfg .unfn-surface {
  width: 100%; flex: 1 1 0; min-height: 0; position: relative;
  background: var(--preview); border-radius: var(--radius-inner);
}
.unfn-cfg .unfn-surface[hidden] { display: none !important; }

/* Segmented pills — the one tab style, used for 2D|3D, Front|Top and in|cm.
   Selected chip = white on the soft groove, iOS-style. */
.unfn-cfg .unfn-tabs, .unfn-cfg .unfn-viewtabs { display: inline-flex; background: var(--bg-soft); border-radius: 999px; padding: 3px; }
.unfn-cfg .unfn-tabs button, .unfn-cfg .unfn-viewtabs button {
  font-family: var(--sans); font-size: 13px; font-weight: 600; letter-spacing: 0.01em;
  border: 0; background: transparent; border-radius: 999px; padding: 6px 16px;
  cursor: pointer; color: var(--ink-soft); transition: color 0.15s ease, background-color 0.15s ease;
}
.unfn-cfg .unfn-tabs button[aria-selected="true"], .unfn-cfg .unfn-viewtabs button[aria-selected="true"] {
  background: var(--bg); color: var(--ink); box-shadow: 0 1px 4px rgba(21,19,15,0.14);
}
.unfn-cfg .unfn-tabs button:focus-visible, .unfn-cfg .unfn-viewtabs button:focus-visible,
.unfn-cfg .unfn-unitsrow button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- panel ---- */
.unfn-cfg .unfn-panel { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

/* Build card — "Your build" + the dimension sliders. */
.unfn-cfg .unfn-buildcard { padding: 18px 18px 20px; }
.unfn-cfg .unfn-cardhead { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
.unfn-cfg .unfn-cardtitle { margin: 0; font-family: var(--serif); font-weight: 400; font-size: 26px; line-height: 1; letter-spacing: -0.01em; color: var(--ink); }
/* in|cm — a mini segmented pill in the card header, next to the values it
   changes (it used to hide in the price card's corner). */
.unfn-cfg .unfn-unitsrow { display: inline-flex; background: var(--bg-soft); border-radius: 999px; padding: 2px; }
.unfn-cfg .unfn-unitsrow button { font-family: var(--sans); font-size: 12px; font-weight: 600; border: 0; background: transparent; border-radius: 999px; padding: 4px 11px; cursor: pointer; color: var(--ink-fade); transition: color 0.15s ease, background-color 0.15s ease; }
.unfn-cfg .unfn-unitsrow button[aria-pressed="true"] { background: var(--bg); color: var(--ink); box-shadow: 0 1px 3px rgba(21,19,15,0.14); }

.unfn-cfg fieldset { border: 0; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 15px; }
/* One row per dimension: label / slider / value box — at every breakpoint.
   The single row is what keeps the card short; the fixed label column keeps
   the sliders left-aligned and the value boxes right-align on the card edge
   so the numbers read as a column. */
.unfn-cfg .unfn-control { display: grid; grid-template-columns: minmax(5.2em, max-content) 1fr auto; grid-template-areas: "label slider value"; align-items: center; column-gap: 12px; }
.unfn-cfg .unfn-control label { grid-area: label; font-size: 15px; font-weight: 600; color: var(--ink); letter-spacing: 0; }
.unfn-cfg .unfn-control input[type=range] { grid-area: slider; }
.unfn-cfg .unfn-control .unfn-valbox { grid-area: value; }
/* The last control on each tool is a different KIND of knob from the
   dimensions above it (the shelf's foot height moves the legs, not the
   stack; the bench's corner radius shapes the top). The divider says so. */
.unfn-cfg .unfn-control.unfn-control-sep { border-top: 1px solid var(--line); padding-top: 12px; }

/* Editable value box — number + quiet unit suffix. type=text with
   inputmode=decimal keeps the fraction display (49¾) while still summoning
   the numeric keypad on mobile. */
.unfn-cfg .unfn-valbox { display: flex; align-items: baseline; justify-content: flex-end; gap: 4px; border: 1px solid rgba(21,19,15,0.24); border-radius: var(--radius-inner); padding: 6px 10px 6px 8px; min-width: 5.2em; background: var(--bg); transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.unfn-cfg .unfn-valbox:hover { border-color: rgba(21,19,15,0.3); }
.unfn-cfg .unfn-valbox:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.unfn-cfg .unfn-val { font-family: var(--sans); font-variant-numeric: tabular-nums; font-size: 16px; font-weight: 600; color: var(--ink); text-align: right; width: 3.1em; padding: 0; border: 0; background: transparent; -webkit-appearance: none; appearance: none; }
.unfn-cfg .unfn-val:focus { outline: none; }
.unfn-cfg .unfn-valunit { font-size: 12.5px; font-weight: 500; color: var(--ink-fade); }
/* While a slider is mid-drag, its value box picks up the accent so the eye
   connects thumb to number (progressive — :has() browsers only). */
.unfn-cfg .unfn-control:has(input[type=range]:active) .unfn-valbox { border-color: var(--accent); }

/* Slider — a slender light groove, orange progress (via --unfn-fill from the
   widget), and an ink puck with a thin white ring for the thumb. Dark reads
   against the white card where a white puck washed out, and the ring keeps
   the puck legible where it sits on top of its own orange fill. The thumb
   scales but does NOT change colour on drag: the fill runs right up to it, so
   an orange puck would dissolve into the bar it is supposed to be leading.
   The input itself is a tall transparent hit strip for easy grabbing (taller
   still on mobile); the visible bar lives on the track pseudos, sized by
   --trk-h / --thumb-d so the mobile block can scale both together.
   touch-action: pan-y — vertical swipes over a slider scroll the page as
   normal; horizontal gestures stay with the widget's touch-grab shim (which
   lets a finger land anywhere on the strip, not just on the puck). */
.unfn-cfg input[type=range] { -webkit-appearance: none; appearance: none; width: 100%; height: 30px; margin: 0; padding: 0; border: 0; background: transparent; cursor: pointer; touch-action: pan-y; }
.unfn-cfg input[type=range]::-webkit-slider-runnable-track {
  height: var(--trk-h); border-radius: 999px;
  background: linear-gradient(90deg, var(--accent) var(--unfn-fill, 0%), var(--track) var(--unfn-fill, 0%));
}
.unfn-cfg input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; box-sizing: border-box; width: var(--thumb-d); height: var(--thumb-d);
  margin-top: calc((var(--trk-h) - var(--thumb-d)) / 2); border-radius: 50%;
  background: var(--ink); border: 2px solid #fff;
  box-shadow: 0 1px 5px rgba(21,19,15,0.28);
  transition: transform 0.15s ease;
}
.unfn-cfg input[type=range]:active::-webkit-slider-thumb { transform: scale(1.08); }
.unfn-cfg input[type=range]::-moz-range-track { height: var(--trk-h); border-radius: 999px; background: var(--track); }
.unfn-cfg input[type=range]::-moz-range-progress { height: var(--trk-h); border-radius: 999px; background: var(--accent); }
.unfn-cfg input[type=range]::-moz-range-thumb {
  box-sizing: border-box; width: var(--thumb-d); height: var(--thumb-d); border-radius: 50%;
  background: var(--ink); border: 2px solid #fff;
  box-shadow: 0 1px 5px rgba(21,19,15,0.28);
  transition: transform 0.15s ease;
}
.unfn-cfg input[type=range]:active::-moz-range-thumb { transform: scale(1.08); }
.unfn-cfg input[type=range]:focus { outline: none; }
.unfn-cfg input[type=range]:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 999px; }

/* ---- buy card — price, warnings, CTA ---- */
.unfn-cfg .unfn-buycard { padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 12px; }
.unfn-cfg .unfn-buyrow { display: flex; justify-content: space-between; align-items: flex-end; gap: 14px; }
.unfn-cfg .unfn-priceline { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.unfn-cfg .unfn-price { font-family: var(--serif); font-size: 46px; line-height: 1; display: flex; align-items: flex-start; }
/* Rolling price (odometer, built by ./price-odometer.js): each digit is a
   0–9 column that slides to the active digit; the cell width eases to the
   target glyph's measured width so the figure breathes as it re-renders. */
.unfn-cfg .unfn-price .unfn-price-char { display: block; height: 1em; }
.unfn-cfg .unfn-price .unfn-price-digit { display: block; height: 1em; overflow: hidden; transition: width 0.28s cubic-bezier(0.22, 0.61, 0.36, 1); }
.unfn-cfg .unfn-price .unfn-price-roll { display: block; transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1); }
.unfn-cfg .unfn-price .unfn-price-roll span { display: block; height: 1em; }
.unfn-cfg .unfn-shipnote { font-family: var(--sans); font-size: 13.5px; font-weight: 600; color: var(--ink-soft); white-space: nowrap; }
.unfn-cfg .unfn-shipnote.unfn-free { color: var(--green); }
/* Derived facts (shelf count, legs, board area; stretcher count) — quiet
   column on the right. */
.unfn-cfg .unfn-readout { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; font-family: var(--sans); font-size: 12.5px; color: var(--ink-soft); text-align: right; }
.unfn-cfg .unfn-readout span { white-space: nowrap; }
.unfn-cfg .unfn-readout b { color: var(--ink); font-weight: 600; }

/* Unbuildable-size message — a soft warning chip above the CTA. */
.unfn-cfg .unfn-warn { display: none; font-size: 13px; font-weight: 500; color: #c03a1d; background: var(--accent-soft); padding: 8px 12px; border-radius: 10px; }
.unfn-cfg .unfn-warn:not(:empty) { display: block; }

/* CTA — orange pill. The MOVING parts (hover slide + working spinner) come
   from theme.css via the theme classes on the button (button--loader/--move/
   .working) so on unfnshed.com they are literally the theme's own animations.
   These rules carry the base look plus a STATIC fallback for non-theme hosts,
   and deliberately declare no animation/transition on the spinner — higher-
   specificity declarations here would beat theme.css and Safari proved
   unwilling to run them from this (cross-origin) sheet. */
.unfn-cfg .unfn-cta {
  position: relative; overflow: hidden; display: block; width: 100%;
  font-family: var(--sans); font-size: 17px; font-weight: 700; letter-spacing: 0.01em; text-transform: none;
  background: var(--accent); color: #fff; border: 1px solid var(--accent); border-radius: 999px;
  padding: 15px; line-height: 1.4; cursor: pointer;
  box-shadow: 0 6px 18px rgba(242,90,56,0.32);
  transition: background-color 175ms linear, border-color 175ms linear, transform 175ms ease, box-shadow 175ms ease, opacity 175ms linear;
}
.unfn-cfg .unfn-cta:hover:not(:disabled) { background: var(--accent-deep); border-color: var(--accent-deep); transform: translateY(-1px); box-shadow: 0 8px 22px rgba(242,90,56,0.38); }
.unfn-cfg .unfn-cta:active:not(:disabled) { transform: translateY(0); }
.unfn-cfg .unfn-cta:disabled { opacity: 0.4; cursor: progress; box-shadow: none; }
.unfn-cfg .unfn-cta.unfn-working { pointer-events: none; opacity: 1; }
.unfn-cfg .unfn-cta__text { display: inline-block; width: 100%; text-align: center; font-weight: 700; }
.unfn-cfg .unfn-cta.unfn-working .unfn-cta__text { opacity: 0; }
.unfn-cfg .unfn-cta__preloader { position: absolute; margin: 0; width: 20px; height: 20px; transform: translate3d(-50%, -50%, 0); top: 50%; left: 50%; display: none; }
.unfn-cfg .unfn-cta.unfn-working .unfn-cta__preloader { display: block; }
.unfn-cfg .unfn-cta__preloader svg { height: 100%; width: 100%; position: absolute; top: 0; left: 0; margin: auto; }
.unfn-cfg .unfn-cta__preloader circle { stroke: #fff; stroke-linecap: round; }
/* Post-submit confirmation, just beneath the CTA inside the buy card. */
.unfn-cfg .unfn-note { font-size: 13px; color: var(--ink-soft); text-align: center; }
.unfn-cfg .unfn-note:empty { display: none; }

/* Trust badges — same three-up card as the product pages' .sh-banner, on the
   shared card recipe so it reads as the third card in the column. The 140px
   cap is deliberate: wide enough that every label holds one line, and it lets
   the three columns span the panel instead of huddling mid-card. Icons are
   decorative (the label says the same thing) — alt="" keeps them out of the
   accessibility tree. */
.unfn-cfg .unfn-badges {
  display: flex; justify-content: space-evenly; gap: 12px; padding: 16px 14px;
  background: var(--bg); border-radius: var(--radius-card);
  box-shadow: var(--shadow-card), inset 0 0 0 1px var(--line);
}
.unfn-cfg .unfn-badge { display: flex; flex-direction: column; align-items: center; text-align: center; flex: 1; min-width: 0; max-width: 140px; }
.unfn-cfg .unfn-badge img { width: 34px; height: 34px; object-fit: contain; margin-bottom: 9px; }
.unfn-cfg .unfn-badge p { margin: 0; font-size: 12.5px; font-weight: 600; line-height: 1.3; color: var(--ink); letter-spacing: -0.2px; }

/* ---- 3D surface (same card as the 2D drawing, swapped by the tabs) ---- */
.unfn-cfg .unfn-view3d { touch-action: none; cursor: grab; overflow: hidden; }
.unfn-cfg .unfn-view3d:active { cursor: grabbing; }
.unfn-cfg .unfn-view3d canvas { display: block; width: 100%; height: 100%; }
.unfn-cfg .unfn-fallback { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--ink-fade); font-family: var(--mono); font-size: 13px; text-align: center; padding: 0 20px; }
/* First-run gesture hint. It rides the cardbar's right edge when space allows,
   using the space Front|Top vacates in 3D without changing the row height. */
.unfn-cfg .unfn-orbithint { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); color: var(--ink-soft); font-size: 12.5px; white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity 320ms ease; }
.unfn-cfg .unfn-orbithint.unfn-hint-on { opacity: 1; }
/* Leaving 3D hides it with no fade — see setMode. */
.unfn-cfg .unfn-orbithint.unfn-hint-instant { transition: none; }
.unfn-cfg .unfn-orbithint-wide { display: flex; align-items: center; gap: 7px; }
.unfn-cfg .unfn-gesture { display: inline-flex; align-items: center; gap: 4px; }
.unfn-cfg .unfn-gesture-icon { width: 14px; height: 14px; flex: none; overflow: visible; }
.unfn-cfg .unfn-gesture-divider { opacity: 0.52; }
/* Once the first-run hint has done its job, this takes the same right-hand
   slot. The bar itself moves above/below the render at the layout breakpoint,
   so the reset stays in the expected corner without a second positioning mode. */
.unfn-cfg .unfn-resetview {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%) translateY(2px);
  display: inline-flex; align-items: center; gap: 5px; min-height: 30px;
  padding: 5px 10px; border: 0; border-radius: 999px;
  background: var(--bg-soft); box-shadow: inset 0 0 0 1px var(--line);
  color: var(--ink-soft); font-family: var(--sans); font-size: 12.5px; font-weight: 600;
  line-height: 1; white-space: nowrap; cursor: pointer;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 180ms ease, transform 180ms ease, background-color 150ms ease, color 150ms ease, box-shadow 150ms ease;
}
.unfn-cfg .unfn-resetview::before { content: ""; position: absolute; inset: -7px -4px; }
.unfn-cfg .unfn-resetview.unfn-reset-on { opacity: 1; visibility: visible; pointer-events: auto; transform: translateY(-50%); }
.unfn-cfg .unfn-resetview:hover { background: rgba(21,19,15,0.09); color: var(--ink); }
.unfn-cfg .unfn-resetview:active { transform: translateY(-50%) scale(0.96); }
.unfn-cfg .unfn-resetview:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.unfn-cfg .unfn-resetview-icon { width: 14px; height: 14px; flex: none; }

/* ---- 2D drawings — plywood tones, shared with the 3D materials ---- */
.unfn-cfg .unfn-scene, .unfn-cfg .unfn-drawing { display: block; overflow: visible; }
/* Dimension text reads as a measured drawing, not as UI: mono, quiet, and
   the same on both tools. Each widget sizes it in its own drawing units. */
.unfn-cfg .unfn-dimlabel, .unfn-cfg .drawing-dimlabel { fill: var(--ink-soft); font-family: var(--mono); font-weight: 400; }
/* No touch-action:none here — the 2D preview is static, so dragging over it
   must still scroll/zoom the page on mobile (only the 3D host captures touch). */
.unfn-cfg .unfn-scene { touch-action: auto; }

@media (prefers-reduced-motion: reduce) {
  .unfn-cfg .unfn-price .unfn-price-digit, .unfn-cfg .unfn-price .unfn-price-roll { transition: none; }
  .unfn-cfg .unfn-orbithint { transition: none; }
  .unfn-cfg .unfn-resetview { transition: none; }
  .unfn-cfg input[type=range]::-webkit-slider-thumb { transition: none; }
  .unfn-cfg input[type=range]::-moz-range-thumb { transition: none; }
  .unfn-cfg input[type=range]:active::-webkit-slider-thumb { transform: none; }
  .unfn-cfg input[type=range]:active::-moz-range-thumb { transform: none; }
  .unfn-cfg .unfn-cta { transition: none; }
  .unfn-cfg .unfn-cta:hover:not(:disabled) { transform: none; }
}

/* Mobile/tablet overrides — placed last so they win over the desktop base
   rules above. Single column: drop the sticky preview (it would pin the
   canvas while the controls scroll over it) and compress the buy card to one
   short row instead — drag any slider and the price rolls right next to the
   CTA, near the thumb. */
@media (max-width: 860px) {
  .unfn-cfg .unfn-layout { grid-template-columns: 1fr; gap: 12px; }
  .unfn-cfg .unfn-stage { position: static; }
  .unfn-cfg .unfn-panel { gap: 12px; }
  .unfn-cfg .unfn-canvas-card { padding: 10px 12px 12px; }
  /* Tabs ride the bottom of the card on mobile — thumbs live at the bottom,
     and it frees the top edge for the drawing. */
  .unfn-cfg .unfn-cardbar { order: 2; margin-bottom: 0; margin-top: 8px; }
  .unfn-cfg .unfn-tabs button, .unfn-cfg .unfn-viewtabs button { font-size: 12px; padding: 6px 13px; }
  .unfn-cfg .unfn-buildcard { padding: 14px 14px 16px; }
  /* Fingers, not cursors: a slightly heavier bar and thumb (--trk-h/--thumb-d
     feed the pseudos), and the whole input grows into a 40px touch strip — the
     visible bar stays centered in it, so the extra height is pure grab area,
     not extra ink. Wider group gaps keep each slider reading as its own unit
     now that the strips are taller. */
  .unfn-cfg { --trk-h: 5px; --thumb-d: 22px; }
  .unfn-cfg input[type=range] { height: 40px; }
  .unfn-cfg fieldset { gap: 19px; }
  /* Controls keep the single label/slider/value row — a tighter label column
     and value box leave the slider a usable travel even at 320px (exact
     numbers go in the value box; the slider is for exploring). */
  .unfn-cfg .unfn-control { grid-template-columns: minmax(4.9em, max-content) 1fr auto; column-gap: 9px; }
  .unfn-cfg .unfn-control label { font-size: 14px; }
  .unfn-cfg .unfn-val { font-size: 15px; width: 2.9em; }
  .unfn-cfg .unfn-valbox { min-width: 4.8em; padding: 5px 9px 5px 7px; border-radius: 10px; }
  .unfn-cfg .unfn-control.unfn-control-sep { padding-top: 15px; }
  /* warn/note lay their own full-width rows only when they have something to
     say (flex + :empty display:none, so hidden ones leave no phantom gaps). */
  .unfn-cfg .unfn-buycard {
    flex-direction: row; flex-wrap: wrap; align-items: center;
    gap: 8px 12px; padding: 12px 14px;
  }
  .unfn-cfg .unfn-buyrow { flex: 0 0 auto; }
  .unfn-cfg .unfn-priceline { flex-direction: column; align-items: flex-start; gap: 1px; }
  .unfn-cfg .unfn-price { font-size: 30px; }
  .unfn-cfg .unfn-shipnote { font-size: 11.5px; }
  .unfn-cfg .unfn-warn:not(:empty) { flex: 1 1 100%; }
  .unfn-cfg .unfn-cta { flex: 1 1 0; width: auto; min-width: 0; padding: 13px 10px; font-size: 15.5px; }
  .unfn-cfg .unfn-note:not(:empty) { flex: 1 1 100%; }
  /* Derived counts are detail — on a phone the price and the dimensions
     themselves earn the space instead. The drawing right above already shows
     the shelf/stretcher count. */
  .unfn-cfg .unfn-readout { display: none; }
}

/* Narrow phones: the three trust labels stay side by side, just tighter. */
@media (max-width: 380px) {
  .unfn-cfg .unfn-badges { gap: 6px; padding: 12px 8px; }
  .unfn-cfg .unfn-badge img { width: 28px; height: 28px; margin-bottom: 7px; }
  .unfn-cfg .unfn-badge p { font-size: 11px; }
}

/* Very narrow phones — after the 860px block so it wins the cascade: the
   single control row would squeeze the slider to a ~70px travel there, so
   stack it full-width under the label+value row instead. No row gap: the
   40px touch strip already pads the bar visually on both sides. */
@media (max-width: 400px) {
  .unfn-cfg .unfn-control { grid-template-columns: 1fr auto; grid-template-areas: "label value" "slider slider"; row-gap: 0; }
}

/* The toolbar changes width independently of the viewport when the render
   stacks above the sliders. Base progressive disclosure on the room that is
   actually available. Hide icons only while all three labels are competing
   for space; restore them as soon as dropping pan makes room again. */
@container unfn-cardbar (max-width: 447px) {
  .unfn-gesture-icon { display: none; }
}

@container unfn-cardbar (max-width: 409px) {
  .unfn-gesture[data-gesture="pan"] { display: none; }
  .unfn-gesture-icon { display: block; }
}

@container unfn-cardbar (max-width: 311px) {
  .unfn-gesture[data-gesture="zoom"] { display: none; }
}
