/**
 * Product Designer - New Builder studio.
 *
 * Loads after the Semantic UI stylesheet, which the designer engine still needs
 * for its dropdowns, popups and modals, and restyles the studio on top of it.
 *
 * Everything is namespaced under .pdr-nt so a theme stylesheet can target any
 * part of the studio, and every colour is a custom property so a theme can
 * rebrand the page without overriding rules one by one.
 *
 * @since 7.0.0
 */

/*
 * The tokens, and everything they have to reach.
 *
 * Semantic detaches a modal and a flowing popup to a dimmer on the body when it
 * opens one, so those surfaces sit outside .pdr-nt and inherit nothing from it.
 * Declaring the palette on them too is what makes the studio's colours, radii
 * and shadows available to the parts of the studio the library has carried off.
 */
.pdr-nt,
.pdr-nt-engine-modal,
.pdr-nt-popup {
	--pdr-nt-accent: #3b82f6;
	--pdr-nt-accent-hover: #2563eb;
	--pdr-nt-accent-soft: #eff6ff;
	/* Text drawn on top of the accent and the dark fill. */
	--pdr-nt-on-accent: #ffffff;
	/* Text drawn on the dark fill, which no theme repaints. */
	--pdr-nt-on-dark: #ffffff;
	--pdr-nt-dark: #0f172a;
	--pdr-nt-dark-hover: #1e293b;
	--pdr-nt-ink: #111827;
	--pdr-nt-ink-2: #374151;
	--pdr-nt-muted: #6b7280;
	--pdr-nt-muted-2: #9ca3af;
	--pdr-nt-line: #e5e7eb;
	--pdr-nt-line-soft: #f3f4f6;
	--pdr-nt-surface: #ffffff;
	--pdr-nt-surface-2: #f9fafb;
	--pdr-nt-canvas-bg: #f3f4f6;
	--pdr-nt-success: #059669;
	/*
	 * The colour a price is stated in. Already the colour of every price on the
	 * page that had one - the top bar pill, the product card, the panel fees -
	 * written out seven times over; named here so the prices that were grey can
	 * join them without a second green appearing beside the first. Darker than
	 * --pdr-nt-success on purpose: these are 8 to 14px figures, several of them
	 * on the soft green ground, and they need the contrast.
	 */
	--pdr-nt-price: #15803d;
	--pdr-nt-success-soft: #f0fdf4;
	--pdr-nt-success-line: #bbf7d0;
	--pdr-nt-danger: #ef4444;
	--pdr-nt-radius: 8px;
	--pdr-nt-radius-lg: 12px;
	--pdr-nt-shadow: 0 10px 30px rgba(0, 0, 0, .14);
	--pdr-nt-shadow-lg: 0 24px 64px rgba(0, 0, 0, .2);
	--pdr-nt-rail-w: 64px;
	--pdr-nt-panel-w: 262px;
	--pdr-nt-props-w: 272px;
	--pdr-nt-topbar-h: 64px;
	--pdr-nt-bottombar-h: 72px;
	/*
	 * How tall the studio may be. The whole viewport when it owns the page,
	 * which is the usual case. With Show Header & Footer set to From Theme the
	 * theme's own header sits above it and the viewport is no longer what it
	 * has, so the studio measures the room left below that header and writes
	 * what it found here.
	 */
	--pdr-nt-shell-h: 100vh;
}

.pdr-nt {
	/*
	 * Positioned so the studio, rather than the screen, is what the popups that
	 * belong to it are placed against - see .pdr-nt-dropdown-designs. Nothing
	 * else changes by it: every absolutely positioned part of the studio already
	 * resolves against the main area or the canvas, and position: relative does
	 * not affect a fixed descendant.
	 */
	position: relative;
	display: flex;
	flex-direction: column;
	height: var(--pdr-nt-shell-h);
	max-height: var(--pdr-nt-shell-h);
	overflow: hidden;
	font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
	font-size: 13px;
	line-height: 1.45;
	color: var(--pdr-nt-ink);
	background: var(--pdr-nt-canvas-bg);
	-webkit-font-smoothing: antialiased;
}

.pdr-nt *,
.pdr-nt *::before,
.pdr-nt *::after {
	box-sizing: border-box;
}

.pdr-nt button {
	font-family: inherit;
}

/*
 * Themes routinely pad every button — the one on this store adds .618em/1.416em —
 * and the studio's icon buttons inherit it. In a flex row that padding is added
 * to each button's minimum width, so the row overflows its panel instead of the
 * buttons sharing the space. These all size themselves from their own width,
 * height or flex, so they want no padding, and min-width: 0 lets them shrink.
 *
 * Buttons that do want padding, such as .pdr-nt-btn, declare their own and are
 * deliberately left out of this list.
 */
.pdr-nt-toggle-btn,
.pdr-nt-segment,
.pdr-nt-layer-filter,
.pdr-nt-filter,
.pdr-nt-stepper-btn,
.pdr-nt-square-btn,
.pdr-nt-zoom-btn,
.pdr-nt-objectbar-btn,
.pdr-nt-float-btn {
	min-width: 0;
	padding: 0;
}

.pdr-nt [hidden] {
	display: none !important;
}

/* ── Carried over from the Classic Builder stylesheet ───────────── */

/*
 * pdr.css is not enqueued on this page. Almost all of it was Classic Builder page
 * chrome, and the parts that reached shared markup fought this stylesheet. What
 * follows is the remainder the designer engine actually depends on: the resting
 * state of three controls it reveals at runtime with .show(), one defensive body
 * width, and the width of the filter sliders. The canvas centring it also
 * provided now sits with the canvas rules.
 */

/*
 * The engine reveals each of these once there is something to act on: a colour
 * to clear, a background to clear, an object on the clipboard to paste. Without
 * a resting state they would all read as available from the moment the page
 * loads. The engine toggles them inline, which outranks this either way.
 */
.pdr-nt .pdr-clear-bg,
.pdr-nt #pdr-clear-bg-image,
.pdr-nt .pdr-paste-object-tools {
	display: none;
}

/*
 * Nothing may make the page wider than the screen it is on.
 *
 * Semantic's reset carries a min-width on the body, and its own scripts rewrite
 * that rule at runtime with a pixel width taken from the page as it stood at the
 * time. On a phone that frozen figure was far wider than the screen, so the body
 * - and the studio filling it - was held at that width: the design, the bottom
 * bar and the last rail tabs all sat off the right of the screen with no way to
 * reach them. The studio sizes itself to the viewport and needs the body to do
 * the same, so the floor is taken off for the whole of the designer page rather
 * than only while a dimmer happens to be up.
 */
body.pdr-designer-body,
body.dimmable {
	min-width: 0;
}

/* The filter sliders fill their column in the object filters popup. */
.pdr-nt .pdr-object-filter-range {
	width: 100%;
}

.pdr-nt-visually-hidden {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.pdr-nt :focus-visible,
.pdr-nt-engine-modal :focus-visible,
.pdr-nt-popup :focus-visible {
	outline: 2px solid var(--pdr-nt-accent);
	outline-offset: 2px;
	border-radius: 4px;
}

.pdr-nt-muted {
	color: var(--pdr-nt-muted-2);
	font-size: 12px;
	margin: 0;
}

.pdr-nt-icon {
	flex-shrink: 0;
}

.pdr-nt-notice {
	margin: 24px;
	padding: 14px 16px;
	border-radius: var(--pdr-nt-radius);
	background: #fffbeb;
	border: 1px solid #fcd34d;
	color: #92400e;
}

/* ── Buttons ─────────────────────────────────────────────── */

.pdr-nt-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	height: 36px;
	padding: 0 14px;
	border: 1.5px solid transparent;
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-ink-2);
	font-size: 13px;
	font-weight: 500;
	line-height: 1;
	white-space: nowrap;
	text-decoration: none;
	cursor: pointer;
	transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.pdr-nt-btn-lg {
	height: 40px;
	padding: 0 20px;
	font-size: 14px;
	font-weight: 700;
}

.pdr-nt-btn-block {
	width: 100%;
}

.pdr-nt-btn-ghost {
	border-color: var(--pdr-nt-line);
}

.pdr-nt-btn-ghost:hover {
	background: var(--pdr-nt-surface-2);
	border-color: #d1d5db;
}

.pdr-nt-btn-primary {
	background: var(--pdr-nt-accent);
	border-color: var(--pdr-nt-accent);
	color: var(--pdr-nt-on-accent);
	font-weight: 600;
}

.pdr-nt-btn-primary:hover {
	background: var(--pdr-nt-accent-hover);
	border-color: var(--pdr-nt-accent-hover);
}

.pdr-nt-btn-dark {
	background: var(--pdr-nt-dark);
	border-color: var(--pdr-nt-dark);
	color: var(--pdr-nt-on-dark);
}

.pdr-nt-btn-dark:hover {
	background: var(--pdr-nt-dark-hover);
	border-color: var(--pdr-nt-dark-hover);
}

.pdr-nt-icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	padding: 0;
	border: none;
	border-radius: 6px;
	background: transparent;
	color: var(--pdr-nt-muted-2);
	cursor: pointer;
}

.pdr-nt-icon-btn:hover {
	background: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-ink-2);
}

.pdr-nt-link {
	padding: 0;
	border: none;
	background: none;
	color: var(--pdr-nt-accent);
	font-size: 12px;
	font-weight: 500;
	cursor: pointer;
	text-align: left;
}

.pdr-nt-link:hover {
	color: var(--pdr-nt-accent-hover);
}

/* ── Top bar ─────────────────────────────────────────────── */

.pdr-nt-topbar {
	display: flex;
	align-items: center;
	flex-shrink: 0;
	gap: 0;
	height: var(--pdr-nt-topbar-h);
	padding: 0 20px;
	background: var(--pdr-nt-surface);
	border-bottom: 1px solid var(--pdr-nt-line);
}

.pdr-nt-logo {
	display: flex;
	align-items: center;
	gap: 9px;
	margin-right: 14px;
	flex-shrink: 0;
	text-decoration: none;
	color: inherit;
}

.pdr-nt-logo-img {
	display: block;
	max-height: 34px;
	max-width: 150px;
	width: auto;
}

.pdr-nt-logo-text {
	font-size: 15px;
	font-weight: 700;
}

.pdr-nt-divider {
	width: 1px;
	height: 20px;
	margin-right: 12px;
	background: var(--pdr-nt-line);
	flex-shrink: 0;
}

.pdr-nt-menus {
	display: flex;
	align-items: center;
	gap: 1px;
}

.pdr-nt-menu {
	position: relative;
}

/*
 * Except the saved designs, whose panel is a popup centred on the studio rather
 * than a menu hanging off its trigger. Relative here made this menu item the box
 * that popup was placed and sized against - 98px of it - so "centred" meant
 * centred on the button. Static, and the studio is what it answers to.
 */
.pdr-nt-menu[data-pdr-menu="my-designs"] {
	position: static;
}

.pdr-nt-menu-trigger {
	display: flex;
	align-items: center;
	gap: 4px;
	height: 32px;
	padding: 0 10px;
	border: none;
	border-radius: 7px;
	background: transparent;
	color: var(--pdr-nt-ink-2);
	font-size: 13px;
	font-weight: 500;
	cursor: pointer;
}

.pdr-nt-menu-trigger:hover,
.pdr-nt-menu-trigger[aria-expanded="true"] {
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-topbar-spacer {
	flex: 1;
}

.pdr-nt-topbar-actions {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-shrink: 0;
}

.pdr-nt-price-pill {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 5px 12px;
	border: 1px solid var(--pdr-nt-success-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-success-soft);
	color: var(--pdr-nt-price);
	font-size: 14px;
	font-weight: 700;
}

.pdr-nt-price-pill .amount,
.pdr-nt-price-pill bdi {
	color: inherit;
}

/* ── Dropdowns ───────────────────────────────────────────── */

.pdr-nt-dropdown {
	position: absolute;
	top: calc(100% + 4px);
	left: 0;
	z-index: 31;
	width: 210px;
	padding: 4px;
	background: var(--pdr-nt-surface);
	border: 1px solid var(--pdr-nt-line);
	border-radius: 10px;
	box-shadow: var(--pdr-nt-shadow);
	display: flex;
	flex-direction: column;
	gap: 1px;
}

.pdr-nt-dropdown-print {
	width: 276px;
	gap: 12px;
	padding: 14px;
	border-radius: var(--pdr-nt-radius-lg);
}

.pdr-nt-dropdown-item {
	display: flex;
	align-items: center;
	gap: 9px;
	width: 100%;
	height: 36px;
	padding: 0 12px;
	border: none;
	border-radius: 7px;
	background: transparent;
	color: var(--pdr-nt-ink-2);
	font-size: 13px;
	font-weight: 500;
	text-align: left;
	cursor: pointer;
}

.pdr-nt-dropdown-item:hover {
	background: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-ink);
}

.pdr-nt-dropdown-actions {
	display: flex;
	gap: 8px;
}

.pdr-nt-dropdown-actions .pdr-nt-btn {
	flex: 1;
	font-weight: 600;
}

.pdr-nt-segmented {
	display: flex;
	gap: 2px;
	padding: 3px;
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-segment {
	flex: 1;
	height: 28px;
	border: none;
	border-radius: 6px;
	background: transparent;
	color: var(--pdr-nt-muted);
	font-size: 12px;
	font-weight: 600;
	cursor: pointer;
}

.pdr-nt-segment.active {
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-ink);
	box-shadow: 0 1px 2px rgba(0, 0, 0, .08);
}

/* ── Form primitives ─────────────────────────────────────── */

.pdr-nt-field {
	display: flex;
	flex-direction: column;
	gap: 6px;
	min-width: 0;
}

.pdr-nt-field-row {
	display: flex;
	gap: 8px;
}

.pdr-nt-field-row .pdr-nt-field {
	flex: 1;
}

.pdr-nt-label {
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .8px;
	text-transform: uppercase;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-input,
.pdr-nt-select {
	width: 100%;
	height: 36px;
	padding: 0 12px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-ink);
	font-family: inherit;
	font-size: 13px;
	font-weight: 500;
	outline: none;
}

.pdr-nt-input:focus,
.pdr-nt-select:focus {
	border-color: var(--pdr-nt-accent);
	background: var(--pdr-nt-surface);
}

/*
 * The text field is a textarea, so it cannot take the fixed 36px height and
 * zero vertical padding the single line inputs share: it grows with the lines
 * typed into it. It starts at two lines' worth, which is enough to show that a
 * second line is allowed, and can be dragged taller for a longer message.
 * Horizontal resizing is off, the panel column being the width it is.
 */
.pdr-nt-text-input {
	height: auto;
	min-height: 60px;
	padding: 9px 12px;
	line-height: 1.45;
	resize: vertical;
}

.pdr-nt-select-wrap {
	position: relative;
}

.pdr-nt-select {
	padding-right: 32px;
	appearance: none;
	cursor: pointer;
}

.pdr-nt-select-wrap .pdr-nt-icon {
	position: absolute;
	top: 50%;
	right: 11px;
	transform: translateY(-50%);
	color: var(--pdr-nt-muted-2);
	pointer-events: none;
}

.pdr-nt-file {
	font-size: 12px;
	color: var(--pdr-nt-muted);
}

.pdr-nt-stack {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.pdr-nt-stepper {
	display: flex;
	align-items: center;
	gap: 6px;
}

.pdr-nt-stepper-unit {
	font-size: 12px;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-switch-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	cursor: pointer;
}

.pdr-nt-switch-title {
	display: block;
	font-size: 13px;
	font-weight: 500;
	color: var(--pdr-nt-ink);
}

.pdr-nt-switch-hint {
	display: block;
	margin-top: 2px;
	font-size: 11px;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-switch {
	position: absolute;
	opacity: 0;
	width: 0;
	height: 0;
}

.pdr-nt-switch-track {
	position: relative;
	flex-shrink: 0;
	width: 40px;
	height: 22px;
	border-radius: 11px;
	background: #d1d5db;
	transition: background-color .15s ease;
}

.pdr-nt-switch-knob {
	position: absolute;
	top: 3px;
	left: 3px;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
	transition: transform .15s ease;
}

.pdr-nt-switch:checked ~ .pdr-nt-switch-track {
	background: var(--pdr-nt-accent);
}

.pdr-nt-switch:checked ~ .pdr-nt-switch-track .pdr-nt-switch-knob {
	transform: translateX(18px);
}

.pdr-nt-switch:focus-visible ~ .pdr-nt-switch-track {
	outline: 2px solid var(--pdr-nt-accent);
	outline-offset: 2px;
}

/* ── Main area ───────────────────────────────────────────── */

.pdr-nt-main {
	display: flex;
	flex: 1;
	min-height: 0;
	overflow: hidden;
}

/* ── Left rail ───────────────────────────────────────────── */

.pdr-nt-rail {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	flex-shrink: 0;
	width: var(--pdr-nt-rail-w);
	padding: 8px 0;
	overflow-y: auto;
	background: var(--pdr-nt-surface);
	border-right: 1px solid var(--pdr-nt-line);
}

.pdr-nt-rail-btn {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 3px;
	width: 54px;
	padding: 8px 2px;
	border: none;
	border-radius: var(--pdr-nt-radius);
	background: transparent;
	color: var(--pdr-nt-muted);
	cursor: pointer;
	transition: background-color .15s ease, color .15s ease;
}

.pdr-nt-rail-btn:hover {
	background: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-ink-2);
}

.pdr-nt-rail-btn.active {
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

.pdr-nt-rail-label {
	font-size: 9px;
	font-weight: 500;
	line-height: 1.2;
	text-align: center;
}

.pdr-nt-rail-divider {
	width: 32px;
	height: 1px;
	margin: 4px 0;
	background: var(--pdr-nt-line);
	flex-shrink: 0;
}

/* ── Tool panel ──────────────────────────────────────────── */

.pdr-nt-toolpanel {
	display: flex;
	flex-direction: column;
	flex-shrink: 0;
	width: var(--pdr-nt-panel-w);
	overflow: hidden;
	background: var(--pdr-nt-surface);
	border-right: 1px solid var(--pdr-nt-line);
}

.pdr-nt.is-panel-collapsed .pdr-nt-toolpanel,
.pdr-nt.is-left-collapsed .pdr-nt-rail,
.pdr-nt.is-left-collapsed .pdr-nt-toolpanel {
	display: none;
}

.pdr-nt.is-right-collapsed .pdr-nt-properties {
	display: none;
}

.pdr-nt-toolpanel-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-shrink: 0;
	height: 48px;
	padding: 0 12px 0 16px;
	border-bottom: 1px solid var(--pdr-nt-line-soft);
}

.pdr-nt-toolpanel-title {
	font-size: 14px;
	font-weight: 600;
}

.pdr-nt-toolpanel-body {
	flex: 1;
	overflow-y: auto;
	padding: 16px;
}

/* ==========================================================================
   Sheet grip
   --------------------------------------------------------------------------
   The bar a phone sheet is resized by. Both the tool panel and the layers list
   carry one; neither is a sheet on a wider screen, where the panel is a column
   and the list a section in it, so it is hidden here and revealed by the sheet
   blocks in the media queries.

   Declared here rather than beside them, because a media query carries no
   specificity of its own: this same rule sitting after those blocks beat them
   on source order and hid the grip at every width.
   ========================================================================== */
.pdr-nt-sheet-grip {
	display: none;
}

/*
 * ── The panels use the whole width on every device ──
 *
 * A panel's body scrolls, and a browser with classic scrollbars takes the room
 * for that scrollbar out of the content box - so everything inside the panel
 * stops short of the right edge and the gutter reads 16px on the left against
 * 26px on the right. Which browsers do that is the "some devices" in this: iOS
 * and most of Android draw an overlay scrollbar that costs nothing, while a good
 * many Android WebViews, Firefox and the desktop engines reserve a gutter - so
 * the same panel was flush on one device and inset on the next.
 *
 * At every width, not only the phone's. This was written for the phone layout,
 * and a tablet, a phone held in landscape, or any mobile browser reporting a
 * viewport over 782px takes the wider layout and had the gap back.
 *
 * The scrollbars are hidden rather than the padding adjusted, because the gutter
 * is only there on some devices and adjusting for it would put the gap on the
 * others instead. Both properties are needed: scrollbar-width is the standard
 * one and the ::-webkit- rule covers the engines that predate it, which are
 * exactly the ones drawing the scrollbar that costs room. The panels still
 * scroll by wheel, touch and keyboard.
 */
.pdr-nt-toolpanel-body,
.pdr-nt-properties,
.pdr-nt-layers .pdr-layers-wrapper,
.pdr-nt-designs-grid {
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.pdr-nt-toolpanel-body::-webkit-scrollbar,
.pdr-nt-properties::-webkit-scrollbar,
.pdr-nt-layers .pdr-layers-wrapper::-webkit-scrollbar,
.pdr-nt-designs-grid::-webkit-scrollbar {
	width: 0;
	height: 0;
}

/* The engine toggles .hidden on these panes. */
.pdr-nt-panel.hidden {
	display: none;
}

/* ── Canvas ──────────────────────────────────────────────── */

.pdr-nt-canvas {
	position: relative;
	flex: 1;
	min-width: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	background: var(--pdr-nt-canvas-bg);
}

.pdr-nt-canvas-stage {
	position: relative;
	max-width: 100%;
	max-height: 100%;
}

.pdr-nt-canvas-stage .canvas-container {
	max-width: 100%;
	/* Centres fabric's wrapper in the stage, which pdr.css used to do. */
	margin: 0 auto;
}

.pdr-nt-canvas-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	max-width: 320px;
	padding: 28px;
	text-align: center;
	background: var(--pdr-nt-surface);
	border: 1.5px dashed #cbd5e1;
	border-radius: var(--pdr-nt-radius-lg);
	color: var(--pdr-nt-muted);
}

.pdr-nt-loader.ui.loader {
	font-family: inherit;
	font-weight: 600;
}

.pdr-nt-collapse {
	position: absolute;
	top: 50%;
	z-index: 7;
	transform: translateY(-50%);
	width: 18px;
	height: 54px;
	padding: 0;
	border: 1px solid var(--pdr-nt-line);
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-muted-2);
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
}

.pdr-nt-collapse-left {
	left: 0;
	border-left: none;
	border-radius: 0 7px 7px 0;
}

/*
 * Above the phone layout the left handle is the tool panel's, so it is not
 * drawn for a studio that has no tool panel - it is rendered for the phone's
 * view drawer, which is a different job at a different width.
 */
@media (min-width: 783px) {
	.pdr-nt:not(.has-tool-panel) .pdr-nt-collapse-left {
		display: none;
	}
}

.pdr-nt-collapse-right {
	right: 0;
	border-right: none;
	border-radius: 7px 0 0 7px;
}

.pdr-nt-collapse:hover {
	color: var(--pdr-nt-ink-2);
}

/*
 * The chevron points at the panel it will close, and away from it once that
 * panel is closed, so the button always shows what pressing it does. Flipped
 * rather than swapped for a second icon, which would put two SVGs in the button
 * to draw one arrow.
 */
.pdr-nt.is-left-collapsed .pdr-nt-collapse-left .pdr-nt-icon,
.pdr-nt.is-right-collapsed .pdr-nt-collapse-right .pdr-nt-icon {
	transform: scaleX(-1);
}

.pdr-nt-canvas-history {
	position: absolute;
	top: 16px;
	left: 16px;
	z-index: 5;
	display: flex;
	align-items: center;
	gap: 6px;
}

/*
 * What the one view of a single view product costs. A label rather than a
 * control: it is the only place that price is named now that such a product
 * has no view switcher, and there is nothing here to press.
 */
.pdr-nt-view-price-chip {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	height: 32px;
	padding: 0 11px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-muted);
	font-size: 11px;
	line-height: 1;
	white-space: nowrap;
}

.pdr-nt-view-price-name {
	font-weight: 500;
}

.pdr-nt-view-price-sep {
	color: var(--pdr-nt-muted-2);
}

/*
 * Green, like every other price in the studio.
 *
 * This chip is only drawn for a product base with one view, which is why it was
 * missed when the prices were brought onto a single colour - neither base on a
 * typical install renders it, so it kept the ink grey it started with and was
 * the one figure on the page not stating itself as money. The view's name
 * beside it stays a label and keeps the chip's own muted colour.
 */
.pdr-nt-view-price-value {
	font-weight: 600;
	color: var(--pdr-nt-price);
}

/* The amount arrives as WooCommerce's own price markup. */
.pdr-nt-view-price-value .amount,
.pdr-nt-view-price-value bdi {
	font-size: inherit;
	font-weight: inherit;
	color: inherit;
}

.pdr-nt-canvas-save {
	position: absolute;
	top: 16px;
	right: 16px;
	z-index: 5;
	/* A row, so the switch view button sits before the save button in it. */
	display: flex;
	align-items: center;
	gap: 8px;
}

/*
 * The close button on a popup. Only the phone layout turns a panel or a menu
 * into a popup, so this is the phone's control and stays out of the way at
 * every other width - where the same panel is a column and the same menu drops
 * out of a trigger that is still beside it.
 */
.pdr-nt-popup-close {
	display: none;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	border: none;
	border-radius: 7px;
	background: transparent;
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
}

.pdr-nt-popup-close:hover {
	background: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-ink);
}

/*
 * The outside of the phone's edge drawers, and nothing at all anywhere else.
 *
 * It is a button in the markup and a flex item of the main area, so with no rule
 * of its own outside the phone block it stayed in the flow at every width: an
 * empty 37px column at the right end of the row, showing the shell's grey
 * against the white of the properties column beside it - which read as an extra
 * border down the right of the designer page. The phone block below is what
 * positions it and reveals it, and only while a drawer is open.
 */
.pdr-nt-drawer-scrim {
	display: none;
}

/*
 * The corner clusters over the design. History sits top left, Switch View and
 * Save top right, and the layers button bottom right - the one corner the zoom
 * bar, which takes the bottom left, leaves free.
 *
 * It is built as the same card the zoom bar is, with the same padding, radius,
 * ground and shadow, so the two controls at the two bottom corners read as one
 * pair sitting at the same height rather than as two unrelated buttons of
 * different sizes. The button inside it is therefore bare, the way the zoom
 * buttons inside that bar are.
 */
.pdr-nt-canvas-layers {
	position: absolute;
	right: 18px;
	bottom: 18px;
	z-index: 5;
	display: none;
	padding: 3px;
	border-radius: 10px;
	background: rgba(255, 255, 255, .92);
	box-shadow: 0 2px 10px rgba(0, 0, 0, .1), 0 0 0 1px rgba(0, 0, 0, .05);
}

.pdr-nt-layers-btn {
	border: none;
	border-radius: 7px;
	background: transparent;
}

.pdr-nt-layers-btn:hover {
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-float-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border: 1px solid rgba(0, 0, 0, .09);
	border-radius: 7px;
	background: rgba(255, 255, 255, .92);
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
}

.pdr-nt-float-btn:hover {
	background: #fff;
}

.pdr-nt-float-btn[disabled] {
	opacity: .45;
	cursor: default;
}

.pdr-nt-float-btn-primary {
	border-color: var(--pdr-nt-accent);
	background: var(--pdr-nt-accent);
	color: var(--pdr-nt-on-accent);
}

.pdr-nt-float-btn-primary:hover {
	background: var(--pdr-nt-accent-hover);
}

/*
 * The switch view button belongs to the phone layout, where the view switcher
 * is a popup rather than a column standing open beside the canvas. Above that
 * width the switcher is on screen in its own right and a button to open it
 * would only point at something already visible.
 *
 * After .pdr-nt-float-btn rather than before it: both are one class, so the
 * later display is the one that applies and declaring this first only had the
 * button drawn at every width.
 */
.pdr-nt-switch-view-btn {
	display: none;
}

/*
 * The label rides with the icon on the phone buttons that carry one. Hidden
 * here rather than declared there, so a float button is icon-only unless it
 * says otherwise.
 */
.pdr-nt-float-btn-label {
	display: none;
}

/*
 * Paste rides along the top left cluster so it survives the selection: the
 * engine reveals it on the first copy and nothing about deselecting or changing
 * view puts it away again. It rests hidden through the shared
 * .pdr-paste-object-tools rule, which the engine lifts with an inline display
 * of block - re-asserted as flex here so the divider and the button stay on one
 * line. Labelled rather than icon only, because unlike undo and redo it is only
 * ever on screen when there is something to paste, and the word says so.
 */
.pdr-nt-canvas-clipboard {
	align-items: center;
	gap: 6px;
}

.pdr-nt-canvas-clipboard[style*="block"],
.pdr-nt-canvas-clipboard[style*="flex"] {
	display: flex !important;
}

.pdr-nt-canvas-clipboard-divider {
	width: 1px;
	height: 18px;
	background: var(--pdr-nt-line);
}

.pdr-nt-paste-btn {
	width: auto;
	gap: 6px;
	padding: 0 10px;
}

.pdr-nt-paste-label {
	font-size: 12px;
	font-weight: 500;
	line-height: 1;
	white-space: nowrap;
}


/*
 * The object toolbar only means anything once an object is selected, and
 * nothing is selected while the page is loading, so it rests hidden. The
 * layout it takes when the engine shows it is declared here too, and the
 * inline-display rules below re-assert it as flex.
 *
 * It sits above the rest of the chrome over the canvas rather than among it,
 * because Semantic re-parents the image filters popup to sit beside its own
 * trigger, which is a button in here. That makes this bar the popup's stacking
 * context and its level the popup's ceiling, however high the popup asks to be:
 * at the level of the other floating bars the image quick edit bar, the
 * selection badge and the collapse arrows all painted over the popup and cut
 * pieces out of it.
 */
.pdr-nt-objectbar {
	display: none;
	position: absolute;
	top: 50%;
	/*
	 * Clear of the collapse arrow rather than 2px on top of it. Both are pinned
	 * to the middle of the same edge, so at 16px the bar always covered the last
	 * sliver of the 18px arrow - and being the higher of the two, it took the
	 * presses meant for it. 18 for the arrow and 8 to sit off it.
	 */
	left: 26px;
	/* Above the crop overlay at 8, below the page chrome and the modals. */
	z-index: 9;
	transform: translateY(-50%);
	flex-direction: column;
	gap: 1px;
	padding: 4px;
	border-radius: 10px;
	background: var(--pdr-nt-surface);
	box-shadow: 0 2px 10px rgba(0, 0, 0, .1), 0 0 0 1px rgba(0, 0, 0, .05);
}

/*
 * The grip the bar is dragged by, and the only part of it that is not a control
 * acting on the selection. touch-action, so a drag on a phone moves the bar
 * instead of scrolling the page out from under it.
 */
.pdr-nt-objectbar-grip {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 16px;
	padding: 0;
	border: none;
	border-radius: 6px;
	background: transparent;
	color: var(--pdr-nt-muted-2);
	cursor: grab;
	touch-action: none;
}

.pdr-nt-objectbar-grip:hover {
	background: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-ink-2);
}

.pdr-nt-objectbar.is-dragging .pdr-nt-objectbar-grip {
	cursor: grabbing;
}

/*
 * While it is being dragged, and once it has been. The studio writes the
 * position, so the resting rule's own left, top and centring transform have to
 * give way to it - and it is lifted over the crop veil for the drag, the way
 * the image bar is, so it does not disappear under a wash halfway across.
 */
.pdr-nt-objectbar.is-moved,
.pdr-nt-contextbar.is-moved {
	transform: none;
}

/*
 * The grip on a contextual bar. That bar is a horizontal strip, so its grip is
 * a narrow column at the near end of it rather than a strip across the top.
 */
.pdr-nt-contextbar-grip {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 14px;
	align-self: stretch;
	padding: 0;
	border: none;
	border-radius: 6px;
	background: transparent;
	color: var(--pdr-nt-muted-2);
	cursor: grab;
	touch-action: none;
}

.pdr-nt-contextbar-grip:hover {
	background: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-ink-2);
}

.pdr-nt-contextbar.is-dragging .pdr-nt-contextbar-grip {
	cursor: grabbing;
}

.pdr-nt-contextbar.is-dragging {
	z-index: 11;
	user-select: none;
}

.pdr-nt-objectbar.is-dragging {
	z-index: 11;
	box-shadow: 0 8px 24px rgba(0, 0, 0, .18), 0 0 0 1px rgba(0, 0, 0, .06);
	user-select: none;
}

.pdr-nt-objectbar-group {
	display: flex;
	flex-direction: column;
	gap: 1px;
}

.pdr-nt-objectbar-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border: none;
	border-radius: 6px;
	background: transparent;
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
}

.pdr-nt-objectbar-btn:hover {
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

.pdr-nt-objectbar-divider {
	height: 1px;
	margin: 1px 0;
	background: var(--pdr-nt-line-soft);
}

/*
 * The contextual bars sit over the canvas, so their width is whatever the
 * canvas column happens to be. On a 1280 or 1366 wide screen the text bar's
 * thirteen controls are wider than that column, and a single line with
 * overflow-x hid the last four of them behind an edge with no scrollbar to
 * suggest they were there — the alignment, letter case and style buttons read
 * as missing rather than as scrolled away. The bar wraps to a second row
 * instead, so every tool stays where the customer can click it.
 */
.pdr-nt-contextbar {
	position: absolute;
	top: 16px;
	left: 50%;
	z-index: 6;
	transform: translateX(-50%);
	display: none;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 4px 2px;
	padding: 5px 7px;
	border-radius: 10px;
	background: var(--pdr-nt-surface);
	box-shadow: 0 8px 28px rgba(0, 0, 0, .16), 0 0 0 1px rgba(0, 0, 0, .06);
	/*
	 * An absolutely positioned wrapping flex box shrinks to fit rather than
	 * filling the room it has, and would wrap while the space for one line is
	 * still there. max-content asks for the single line and the max-width takes
	 * it back, so the bar only wraps once the canvas column is genuinely too
	 * narrow for it.
	 */
	width: max-content;
	/*
	 * The reserve has to clear the corner chrome, not just the canvas edges. The
	 * bar is centred, so half of what is taken off comes off each side: at 120
	 * that left 60px a side, and the history buttons sit 16px in and run to 86 -
	 * so on a narrow column the bar covered the last 26px of Redo and, sitting
	 * above it, took the presses meant for it. 100 a side clears the history on
	 * the left and the save button on the right, and the bar wraps to a second
	 * row rather than growing into either of them.
	 */
	max-width: calc(100% - 200px);
}

/* A divider that lands at the end of a wrapped row separates nothing. */
.pdr-nt-contextbar-divider:last-child {
	display: none;
}

/*
 * The engine toggles these bars with jQuery show()/hide(), which writes an
 * inline display value. Re-assert flex so the bar lays out correctly when shown.
 */
.pdr-nt-contextbar[style*="block"],
.pdr-nt-contextbar[style*="flex"],
.pdr-nt-objectbar[style*="block"],
.pdr-nt-objectbar[style*="flex"] {
	display: flex !important;
}

.pdr-nt-contextbar-label {
	padding: 0 6px;
	font-size: 11px;
	font-weight: 600;
	color: var(--pdr-nt-muted-2);
	text-transform: uppercase;
	letter-spacing: .6px;
	white-space: nowrap;
}

.pdr-nt-contextbar-group {
	display: flex;
	align-items: center;
	gap: 2px;
}


.pdr-nt-contextbar-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 30px;
	height: 34px;
	padding: 0 6px;
	border: none;
	border-radius: 6px;
	background: transparent;
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
}

.pdr-nt-contextbar-btn:hover {
	background: var(--pdr-nt-line-soft);
}

/* ── Text bar, to the design ─────────────────────────────── */

/*
 * Placed by the studio over the selected object, not by this rule: the top and
 * left are written on every selection and every move of it, and are only a
 * starting point for the moment before the first measurement lands. The
 * translate keeps the badge centred on whatever left it is given, and
 * pointer-events, because it now floats over the design and must not take a
 * click meant for the object underneath it.
 */
.pdr-nt-sel-badge {
	position: absolute;
	top: 12px;
	left: 50%;
	z-index: 7;
	transform: translateX(-50%);
	pointer-events: none;
	padding: 2px 8px;
	border-radius: 5px;
	background: var(--pdr-nt-accent);
	color: var(--pdr-nt-on-accent);
	font-size: 9px;
	font-weight: 600;
	letter-spacing: .7px;
	text-transform: uppercase;
	box-shadow: 0 2px 6px rgba(59, 130, 246, .35);
	white-space: nowrap;
}

/*
 * The bar keeps its own place. It used to be pushed down to clear the badge,
 * which stood above it at the top of the column; the badge is on the object
 * now, so there is nothing up here for the bar to make room for.
 */

.pdr-nt-textbar-size {
	display: flex;
	align-items: center;
	flex-shrink: 0;
	padding: 1px;
	border-radius: 7px;
	background: #f4f5f7;
}

.pdr-nt-textbar-step {
	width: 26px;
	height: 32px;
	padding: 0;
	border: none;
	border-radius: 5px;
	background: transparent;
	color: var(--pdr-nt-muted);
	font-size: 17px;
	font-weight: 300;
	line-height: 1;
	cursor: pointer;
}

.pdr-nt-textbar-step:hover {
	background: var(--pdr-nt-surface);
}

/*
 * The engine's own font size field, sitting between the two steppers. It reads
 * as the number in a stepper pill rather than as a form input: no border, no
 * spinners - the steppers either side are the spinners - and wide enough for
 * three digits, which is past any size a print area has room for.
 */
.pdr-nt-textbar-size-field {
	width: 40px;
	height: 32px;
	padding: 0;
	border: none;
	border-radius: 5px;
	background: transparent;
	color: var(--pdr-nt-ink);
	font-family: inherit;
	font-size: 13px;
	font-weight: 600;
	text-align: center;
	outline: none;
	-moz-appearance: textfield;
}

/* Qualified for the same reason as the quantity stepper below. */
.pdr-nt input.pdr-nt-textbar-size-field {
	-moz-appearance: textfield;
	appearance: textfield;
}

.pdr-nt input.pdr-nt-textbar-size-field::-webkit-outer-spin-button,
.pdr-nt input.pdr-nt-textbar-size-field::-webkit-inner-spin-button {
	margin: 0;
	-webkit-appearance: none;
	appearance: none;
}

.pdr-nt-textbar-size-field:focus {
	background: var(--pdr-nt-surface);
}

.pdr-nt-contextbar-divider {
	width: 1px;
	height: 24px;
	margin: 0 3px;
	background: #e8eaed;
	flex-shrink: 0;
}

.pdr-nt-glyph {
	font-size: 13px;
	font-weight: 600;
	line-height: 1;
}

.pdr-nt-glyph-bold { font-weight: 800; }
.pdr-nt-glyph-italic { font-style: italic; }
.pdr-nt-glyph-underline { text-decoration: underline; }
.pdr-nt-glyph-overline { text-decoration: overline; }
.pdr-nt-glyph-strike { text-decoration: line-through; }

.pdr-nt-color-chip {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 34px;
	border-radius: 6px;
	cursor: pointer;
}

.pdr-nt-color-chip:hover {
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-color-chip input[type="color"] {
	width: 22px;
	height: 22px;
	padding: 0;
	border: 1px solid rgba(0, 0, 0, .12);
	border-radius: 5px;
	background: none;
	cursor: pointer;
}

.pdr-nt-zoombar {
	position: absolute;
	bottom: 18px;
	left: 18px;
	z-index: 5;
	display: flex;
	align-items: center;
	gap: 2px;
	padding: 3px;
	border-radius: 10px;
	background: rgba(255, 255, 255, .92);
	box-shadow: 0 2px 10px rgba(0, 0, 0, .1), 0 0 0 1px rgba(0, 0, 0, .05);
}

.pdr-nt-zoom-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border: none;
	border-radius: 7px;
	background: transparent;
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
}

.pdr-nt-zoom-btn:hover {
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-zoom-value {
	min-width: 48px;
	text-align: center;
	font-size: 12px;
	font-weight: 600;
	color: var(--pdr-nt-ink-2);
}

.pdr-nt-zoom-divider {
	width: 1px;
	height: 18px;
	margin: 0 2px;
	background: var(--pdr-nt-line);
}

/* A mode reads as a pressed tool - pan, the object lock, crop - and pan mode
   takes a grab cursor on the stage with it. */
.pdr-nt-zoom-btn.is-active,
.pdr-nt-objectbar-btn.is-active,
.pdr-nt-contextbar-btn.is-active {
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

/* The lit tool keeps its colour under the cursor rather than dropping back to
   the plain hover grey, which read as the mode having switched itself off. */
.pdr-nt-contextbar-btn.is-active:hover {
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

/*
 * The crop veil is a 9999px shadow spread from the crop box, and at z-index 8 it
 * is painted over everything below it. The image bar sits at 6 and the selection
 * badge above it at 7, so the one bar the mode exists for - the bar carrying
 * Cancel and Apply - was shown through a 45% dark wash along with the layer's
 * name. Both buttons still worked, the veil taking no pointer events, but
 * neither read as a live control and hovering one barely changed it.
 *
 * Both are lifted over the veil for as long as the veil is up, and drop back to
 * their own levels the moment crop ends. Only for that moment: the object
 * toolbar at 9 is the ceiling for the image filters popup Semantic re-parents
 * into it, and outside crop mode these two belong below that.
 */
.pdr-nt.is-cropping .pdr-nt-imagebar,
.pdr-nt.is-cropping .pdr-nt-sel-badge {
	z-index: 9;
}

.pdr-nt-objectbar-btn:disabled {
	opacity: .4;
	cursor: default;
}

.pdr-nt-objectbar-btn:disabled:hover {
	background: transparent;
	color: var(--pdr-nt-ink-2);
}

/*
 * A locked selection. The object bar stays on screen with its lock button live,
 * because that button is the only way to hand the object back, and every other
 * tool on it is disabled from the studio script. What the script cannot do is
 * hide the contextual bars: the engine shows those from its own selection
 * handler, which runs after the studio's, so an inline display would be written
 * back over anything set there. They are taken off here instead, where the class
 * on the studio root out-ranks that inline style.
 *
 * The text, image and shape bars and the print quality readout all edit or
 * report on the selected layer, which is exactly what a lock is asking them not
 * to do.
 */
.pdr-nt.has-locked-selection .pdr-nt-contextbar,
.pdr-nt.has-locked-selection .pdr-nt-quality {
	display: none !important;
}

/* The lock reads as the one live control rather than as another dimmed one. */
.pdr-nt.has-locked-selection .pdr-nt-objectbar-btn.is-active {
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

.pdr-nt-canvas-stage.pdr-nt-is-panning,
.pdr-nt-canvas-stage.pdr-nt-is-panning canvas {
	cursor: grab;
}

.pdr-nt-canvas-stage.pdr-nt-is-panning:active,
.pdr-nt-canvas-stage.pdr-nt-is-panning canvas:active {
	cursor: grabbing;
}

/* ── Print quality indicator ─────────────────────────────── */

.pdr-nt-quality {
	position: absolute;
	bottom: 62px;
	left: 50%;
	z-index: 5;
	transform: translateX(-50%);
	display: flex;
	align-items: center;
	gap: 8px;
	max-width: calc(100% - 32px);
	padding: 6px 12px;
	border-radius: 999px;
	background: rgba(255, 255, 255, .94);
	box-shadow: 0 2px 10px rgba(0, 0, 0, .1), 0 0 0 1px rgba(0, 0, 0, .05);
	font-size: 12px;
	white-space: nowrap;
}

.pdr-nt-quality-dot {
	flex: 0 0 auto;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--pdr-nt-muted-2);
}

.pdr-nt-quality-label {
	color: var(--pdr-nt-muted);
}

.pdr-nt-quality-label::after {
	content: ':';
}

.pdr-nt-quality-value {
	margin-left: 4px;
	font-weight: 600;
	color: var(--pdr-nt-ink);
}

.pdr-nt-quality-hint {
	overflow: hidden;
	color: var(--pdr-nt-muted-2);
	text-overflow: ellipsis;
}

.pdr-nt-quality[data-pdr-quality="excellent"] .pdr-nt-quality-dot,
.pdr-nt-quality[data-pdr-quality="good"] .pdr-nt-quality-dot {
	background: var(--pdr-nt-success);
}

.pdr-nt-quality[data-pdr-quality="fair"] .pdr-nt-quality-dot {
	background: #f59e0b;
}

.pdr-nt-quality[data-pdr-quality="low"] .pdr-nt-quality-dot {
	background: var(--pdr-nt-danger);
}

.pdr-nt-quality[data-pdr-quality="low"] .pdr-nt-quality-value {
	color: var(--pdr-nt-danger);
}

/* The hint is the long half, so it goes first when the canvas is narrow. */
@media (max-width: 1100px) {
	.pdr-nt-quality-hint {
		display: none;
	}
}

/* ── My Designs menu ─────────────────────────────────────── */

/*
 * The saved designs open in the middle of the page: a titled header, then a
 * three column grid of cards that scrolls. The cards themselves are the
 * engine's, so the rules below restyle its Semantic card markup in place.
 *
 * A panel this size hung off its trigger in the top bar reached a long way down
 * the left of the screen and covered the tools while the customer read it, and
 * where the bar had wrapped it opened from wherever the trigger had been pushed
 * to. In the middle it is the one thing being looked at, which is what opening
 * it is for.
 *
 * The second shadow is the dim behind it - a spread of 100vmax covers the
 * screen without an element to cover it with, and it takes no clicks, so a tap
 * outside still lands on what is under it and the studio's own outside-click
 * closes the menu.
 */
.pdr-nt-dropdown-designs {
	/*
	 * Centred on the studio, not on the screen. As position: fixed it was placed
	 * against the viewport, which is the same thing only while the studio fills
	 * it: with Show Header & Footer set to From Theme the studio is a band in the
	 * middle of a longer page, and the popup opened 176px above its own trigger,
	 * over the theme's navigation and outside the studio altogether.
	 */
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: 40;
	width: min(92%, 460px);
	/* Of the studio, for the same reason. 78vh could overflow a short shell. */
	max-height: 78%;
	padding: 0;
	gap: 0;
	transform: translate(-50%, -50%);
	border-radius: var(--pdr-nt-radius-lg);
	overflow: hidden;
	box-shadow: 0 18px 48px rgba(0, 0, 0, .28), 0 0 0 100vmax rgba(15, 23, 42, .45);
}

/* The way out, now that the trigger is no longer beside it. */
.pdr-nt-designs-close {
	display: flex;
}

/* The grid takes the height the popup has, rather than a menu's 280px. */
.pdr-nt-dropdown-designs .pdr-nt-designs-grid {
	max-height: none;
	flex: 1;
}

.pdr-nt-designs-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	padding: 12px 14px;
	border-bottom: 1px solid var(--pdr-nt-line-soft);
}

.pdr-nt-designs-title {
	font-size: 14px;
	font-weight: 700;
	color: var(--pdr-nt-ink);
}

.pdr-nt-designs-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 8px;
	max-height: 280px;
	padding: 10px 12px;
	overflow-y: auto;
}

/* The engine renders each design as a Semantic card inside an anchor. */
.pdr-nt-designs-grid .card.pdr-my-design-card,
.pdr-nt-designs-grid > .card {
	display: block;
	width: auto;
	min-height: 0;
	margin: 0;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	box-shadow: none;
	overflow: hidden;
	cursor: pointer;
	transition: border-color .15s ease;
}

.pdr-nt-designs-grid > .card:hover {
	border-color: var(--pdr-nt-accent);
	box-shadow: none;
}

.pdr-nt-designs-grid > .card > .image {
	display: block;
	width: 100%;
	height: 62px;
	padding: 0;
	border: none;
	border-radius: 0;
	background: var(--pdr-nt-surface);
}

.pdr-nt-designs-grid > .card > .image img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.pdr-nt-designs-grid .pdr-my-design-meta {
	position: relative;
	display: block;
	padding: 5px 7px;
	border-top: 1px solid var(--pdr-nt-line-soft);
	background: none;
}

.pdr-nt-designs-grid .pdr-my-design-name {
	display: block;
	overflow: hidden;
	font-size: 10px;
	font-weight: 600;
	color: var(--pdr-nt-ink);
	text-overflow: ellipsis;
	white-space: nowrap;
}

.pdr-nt-designs-grid .pdr-my-design-date {
	display: block;
	font-size: 9px;
	font-weight: 400;
	color: var(--pdr-nt-muted-2);
}

/*
 * Deleting is the engine's, and the design has no other home, so the control
 * stays. It sits over the thumbnail as a small circle rather than the full
 * width button Semantic renders, which no longer fits a card this size.
 */
.pdr-nt-designs-grid .pdr-my-design-delete.button {
	position: absolute;
	top: -56px;
	right: 4px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 18px;
	height: 18px;
	min-height: 0;
	margin: 0;
	padding: 0;
	border-radius: 50%;
	background: var(--pdr-nt-danger) !important;
	color: #fff !important;
	font-family: inherit;
	font-size: 0;
	line-height: 1;
	opacity: 0;
	transition: opacity .15s ease;
}

.pdr-nt-designs-grid > .card:hover .pdr-my-design-delete.button {
	opacity: 1;
}

/* The label is replaced by a cross, so the word itself is not needed. */
.pdr-nt-designs-grid .pdr-my-design-delete.button::before {
	content: '\00d7';
	font-size: 13px;
	font-weight: 700;
}

.pdr-nt-designs-empty {
	margin: 0;
	padding: 14px;
	color: var(--pdr-nt-muted);
	font-size: 12px;
	text-align: center;
}

/* The engine's own no-designs notice, kept quiet in the menu. */
.pdr-nt-dropdown-designs .pdr-popup-error-message.message {
	margin: 10px 12px;
	padding: 10px 12px;
	border: 1px dashed var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	box-shadow: none;
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-muted);
	font-family: inherit;
	font-size: 12px;
	text-align: center;
}

.pdr-nt-dropdown-designs .pdr-popup-error-message .header {
	font-family: inherit;
	font-size: 12px;
	font-weight: 500;
	color: inherit;
}

/* ── Popups ──────────────────────────────────────────────── */

.pdr-nt-popup.ui.popup {
	padding: 14px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius-lg);
	box-shadow: var(--pdr-nt-shadow);
	font-family: inherit;
	font-size: 13px;
	min-width: 260px;
}

.pdr-nt-popup-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 14px;
}

/*
 * Four columns wide enough for the longest filter name to sit on one line at
 * 10px — "Kodachrome" and "Technicolor" are the two that decide it. The popup
 * is given a matching floor, because Semantic sizes it from its content and
 * would otherwise settle narrower than the names need.
 */
.pdr-nt-popup.ui.popup.pdr-object-filters-view {
	min-width: 316px;
}

.pdr-nt-filters {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 8px;
	max-width: 352px;
}

.pdr-nt-filter {
	text-align: center;
	cursor: pointer;
}

.pdr-nt-filter-img {
	display: block;
	width: 100%;
	border: 1.5px solid var(--pdr-nt-line);
	border-radius: 6px;
}

.pdr-nt-filter-img:hover {
	border-color: var(--pdr-nt-accent);
}

/*
 * The selected filter is state rather than decoration, so it keeps a definite
 * marker: the accent border doubled by a ring, and its label in the accent too.
 * The ring is a shadow, so selecting a filter never shifts the grid.
 */
.pdr-nt-filter-img.pdr-object-filter-selected {
	border-color: var(--pdr-nt-accent);
	box-shadow: 0 0 0 1.5px var(--pdr-nt-accent);
}

.pdr-nt-filter-label {
	display: block;
	margin-top: 3px;
	overflow: hidden;
	font-size: 10px;
	color: var(--pdr-nt-muted);
	/* One line, trimmed rather than broken mid-word. */
	white-space: nowrap;
	text-overflow: ellipsis;
}

.pdr-object-filter-selected + .pdr-nt-filter-label {
	color: var(--pdr-nt-accent-hover);
	font-weight: 600;
}

.pdr-nt-filter-ranges {
	margin-top: 12px;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.pdr-nt-filter-range {
	display: grid;
	/* The first column holds names as long as "Saturation" in uppercase. */
	grid-template-columns: 92px 34px minmax(0, 1fr) 28px;
	align-items: center;
	gap: 6px;
}

.pdr-nt-filter-range > .pdr-nt-label {
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

/* ── Properties panel ────────────────────────────────────── */

.pdr-nt-properties {
	display: flex;
	flex-direction: column;
	flex-shrink: 0;
	width: var(--pdr-nt-props-w);
	overflow-y: auto;
	padding: 16px;
	gap: 14px;
	background: var(--pdr-nt-surface);
	border-left: 1px solid var(--pdr-nt-line);
}

.pdr-nt-section {
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	overflow: hidden;
}

.pdr-nt-section-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	height: 34px;
	padding: 0 10px;
	border: none;
	border-bottom: 1px solid var(--pdr-nt-line);
	background: #f8f9fa;
	color: var(--pdr-nt-ink);
	cursor: pointer;
}

.pdr-nt-section-head .pdr-nt-icon {
	transition: transform .15s ease;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-section-head[aria-expanded="false"] .pdr-nt-icon {
	transform: rotate(-90deg);
}

/*
 * A following sibling rather than the next one: the views section carries a
 * close button for its phone popup between the head and the body, and with the
 * adjacent combinator that button was enough to stop a collapsed section from
 * collapsing. A section has exactly one body, so the two read the same
 * everywhere else.
 */
.pdr-nt-section-head[aria-expanded="false"] ~ .pdr-nt-section-body {
	display: none;
}

.pdr-nt-section-title {
	font-size: 12px;
	font-weight: 600;
}

.pdr-nt-section-body {
	padding: 10px;
}

/*
 * View switcher. Two chips are visible at a time; the studio measures a chip and
 * writes the viewport height into --pdr-nt-views-height, so the strip always
 * stops on a chip boundary rather than cutting one in half. The fallback height
 * keeps the panel from jumping before that measurement lands.
 */
.pdr-nt-views-scroller {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.pdr-nt-views-viewport {
	max-height: var(--pdr-nt-views-height, 188px);
	overflow: hidden;
	scrollbar-width: none;
}

.pdr-nt-views-viewport::-webkit-scrollbar {
	display: none;
}

/* Only scrollable once the arrows are there to drive it. */
.pdr-nt-views-scroller.is-scrollable .pdr-nt-views-viewport {
	overflow-y: auto;
}

.pdr-nt-views-arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 22px;
	padding: 0;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
}

.pdr-nt-views-arrow:hover:not(:disabled) {
	border-color: var(--pdr-nt-accent);
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

/*
 * Kept in place rather than hidden at the ends of the strip, so the chips below
 * them never shift as the customer scrolls.
 */
.pdr-nt-views-arrow:disabled {
	opacity: .35;
	cursor: default;
}

.pdr-nt-views {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.pdr-nt-view {
	display: block;
	width: 100%;
	padding: 6px;
	border: 1.5px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-ink-2);
	font-size: 10px;
	font-weight: 600;
	text-align: center;
	cursor: pointer;
}

.pdr-nt-view:hover {
	border-color: #d1d5db;
}

.pdr-nt-view.active {
	border-color: var(--pdr-nt-accent);
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

.pdr-nt-view-price:empty {
	display: none;
}

.pdr-nt-view-price {
	display: inline-block;
	margin-top: 8px;
	padding: 2px 8px;
	border-radius: 999px;
	background: var(--pdr-nt-success-soft);
	color: var(--pdr-nt-price);
	font-size: 11px;
	font-weight: 600;
}

/*
 * Layer rows are generated by the engine; this is the design's layer list built
 * around that markup. The design orders a row eye, thumbnail, name, then select,
 * lock and delete. The engine emits the thumbnail and name first and gathers all
 * six icons into one wrapper afterwards, so that wrapper is given
 * display: contents to dissolve its box, which lets the two visibility icons be
 * ordered ahead of the thumbnail and puts the row in the design's order without
 * touching the engine's markup.
 */
.pdr-nt-layers .pdr-layer-wrapper {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 5px 8px;
	/*
	 * The actions are direct children of the row - the wrapper around them is
	 * display: contents - so the row's own 6px gap fell between every icon as
	 * well as around them, and four controls that belong together read as four
	 * separate things. They are pulled in below; the gap stays for the parts of
	 * the row that are genuinely separate.
	 */
	border-bottom: 1px solid var(--pdr-nt-line-soft);
	background: var(--pdr-nt-surface);
	cursor: pointer;
}

.pdr-nt-layers .pdr-layer-wrapper:last-child {
	border-bottom: none;
}

.pdr-nt-layers .pdr-layer-wrapper:hover {
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-layers .pdr-layer-wrapper.active {
	background: var(--pdr-nt-accent-soft);
}

.pdr-nt-layers .pdr-layer-actions-wrapper {
	display: contents;
}

/*
 * Edit, lock and delete as one cluster. The eye keeps the row's gap on its own
 * side: it sits at the head of the row, away from these three.
 *
 * Matched against .pdr-layer-actions-wrapper i, which zeroes the margin these
 * icons arrive with and outranks a two class rule by its type selector.
 */
.pdr-nt-layers .pdr-layer-actions-wrapper i.pdr-layer-edit-action,
.pdr-nt-layers .pdr-layer-actions-wrapper i.pdr-layer-lock-action,
.pdr-nt-layers .pdr-layer-actions-wrapper i.pdr-layer-unlock-action,
.pdr-nt-layers .pdr-layer-actions-wrapper i.pdr-layer-delete-action {
	margin-left: -5px;
}

.pdr-nt-layers .pdr-layer-hide-action,
.pdr-nt-layers .pdr-layer-show-action {
	order: -1;
}

/*
 * The row's internals, also engine-rendered. These used to inherit their layout
 * from the Classic Builder stylesheet, which sized the three columns as 10/58/30
 * percent; the studio's row is a flex line, so they size themselves instead.
 */
.pdr-nt-layers .pdr-layer-image {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 26px;
	height: 26px;
	overflow: hidden;
	border: 1px solid var(--pdr-nt-line);
	border-radius: 4px;
	background: var(--pdr-nt-surface);
}

.pdr-nt-layers .pdr-layer-wrapper.active .pdr-layer-image {
	border-color: #bfdbfe;
}

/*
 * The design dims a hidden layer's thumbnail as well as swapping its eye, so
 * the list reads at a glance. The row carries the class from the studio, since
 * visibility lives on the fabric object rather than in the engine's markup.
 */
.pdr-nt-layers .pdr-layer-wrapper.is-hidden .pdr-layer-image {
	opacity: .45;
}

/*
 * A locked row says so before it is pressed. The icons stay clickable rather
 * than being taken out of the event stream, because a press that silently does
 * nothing is what this looked like before; pressing one now explains itself.
 */
.pdr-nt-layers .pdr-layer-wrapper.is-locked .pdr-layer-edit-action,
.pdr-nt-layers .pdr-layer-wrapper.is-locked .pdr-layer-delete-action {
	opacity: .35;
	cursor: not-allowed;
}

.pdr-nt-layers .pdr-layer-wrapper.is-locked .pdr-layer-name-text {
	cursor: default;
}

.pdr-nt-layers .pdr-layer-wrapper.is-hidden .pdr-layer-name-text {
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-layers .pdr-layer-image img,
.pdr-nt-layers .pdr-layer-image canvas {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.pdr-nt-layers .pdr-layer-image i {
	margin: 0;
	font-size: 13px;
	color: var(--pdr-nt-muted);
}

.pdr-nt-layers .pdr-layer-name-wrapper {
	flex: 1;
	min-width: 0;
}

/* Two compact lines, so a row sits at the design's height. */
.pdr-nt-layers .pdr-layer-name {
	display: flex;
	align-items: center;
	gap: 4px;
	min-width: 0;
}

.pdr-nt-layers .pdr-layer-name-text {
	overflow: hidden;
	font-size: 11px;
	font-weight: 500;
	line-height: 1.3;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/*
 * What this layer adds to the price, and only when it adds something - the
 * engine renders no badge at all for a layer that costs nothing, so there is no
 * empty box to allow for here. The row is a flex line with a gap, so the gap
 * goes with the badge and the name keeps its place either way.
 *
 * Green, like every other price in the studio. This badge used to be neutral,
 * on the reasoning that the figure is a fact about the layer rather than good
 * news - but it is the only price on the page that said so, and a customer
 * reading down a list of layers for what each one costs should not have to
 * learn a second colour for it. Tabular figures so the badge does not change
 * width as the digits do.
 */
.pdr-nt-layers .pdr-layer-price {
	flex-shrink: 0;
	padding: 0 5px;
	border: 1px solid var(--pdr-nt-success-line);
	border-radius: 999px;
	background: var(--pdr-nt-success-soft);
	color: var(--pdr-nt-price);
	font-size: 9px;
	font-weight: 700;
	line-height: 15px;
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
	font-feature-settings: 'tnum' 1;
}

.pdr-nt-layers .pdr-layer-price .amount,
.pdr-nt-layers .pdr-layer-price bdi {
	color: inherit;
}

.pdr-nt-layers .pdr-layer-object-name {
	font-size: 9px;
	font-style: italic;
	line-height: 1.3;
	color: var(--pdr-nt-muted-2);
}

/*
 * Each toggle is a pair of icons with the inactive half marked .hidden — show
 * against hide, lock against unlock. Without this both halves of both pairs
 * show at once and the row carries six icons instead of four.
 *
 * Deliberately not !important: the engine reveals the other half of a pair with
 * .show(), which writes an inline display, and an !important rule here would
 * outrank it and leave a hidden or locked layer with no way back.
 */
.pdr-nt-layers .pdr-layer-actions-wrapper .hidden {
	display: none;
}

.pdr-nt-layers .pdr-layer-actions-wrapper i {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 22px;
	height: 22px;
	margin: 0;
	border-radius: 5px;
	font-size: 12px;
	color: var(--pdr-nt-muted-2);
	cursor: pointer;
}

/* The design tints each control by what it does. */
.pdr-nt-layers .pdr-layer-hide-action:hover,
.pdr-nt-layers .pdr-layer-show-action:hover {
	background: #eef0f2;
	color: var(--pdr-nt-ink-2);
}

.pdr-nt-layers .pdr-layer-edit-action:hover,
.pdr-nt-layers .pdr-layer-lock-action:hover,
.pdr-nt-layers .pdr-layer-unlock-action:hover {
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

.pdr-nt-layers .pdr-layer-delete-action:hover {
	background: #fef2f2;
	color: var(--pdr-nt-danger);
}

/*
 * The two empty states of the layer list. The engine's "no layers yet" notice
 * arrives as a Semantic warning message, which paints a yellow alert box in a
 * panel where nothing is wrong; the studio restates it as a quiet empty state,
 * and the filter's own notice is given the same shape so the panel never
 * changes character between them.
 *
 * The Semantic selector is matched class for class and then one more, because
 * .ui.warning.message would otherwise outrank a plain descendant rule and keep
 * its own padding, margin, colours and font.
 */
.pdr-nt-layers .pdr-no-layers-message,
.pdr-nt-layers .ui.warning.message.pdr-no-layers-message,
.pdr-nt-layers [data-pdr-layer-empty] {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 9px;
	margin: 10px;
	padding: 20px 14px;
	border: 1px dashed var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	box-shadow: none;
	color: var(--pdr-nt-muted);
	font-family: inherit;
	font-size: 11.5px;
	font-weight: 400;
	line-height: 1.5;
	text-align: center;
}

/*
 * Declaring a display above outranks the browser's own [hidden] rule, and the
 * filter notice is toggled through that attribute, so restate it here.
 */
.pdr-nt-layers [data-pdr-layer-empty][hidden] {
	display: none;
}

/*
 * A layers glyph over the message, drawn from the same icon set as the rest of
 * the chrome. Inline rather than an image request, and on a pseudo element so
 * the engine's own markup is left alone.
 */
.pdr-nt-layers .pdr-no-layers-message::before,
.pdr-nt-layers [data-pdr-layer-empty]::before {
	content: "";
	width: 26px;
	height: 26px;
	opacity: .6;
	background: center / contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m12 3 9 5-9 5-9-5 9-5Z'/%3E%3Cpath d='m3 12 9 5 9-5M3 16l9 5 9-5'/%3E%3C/svg%3E");
}

/* Semantic's message adds a heading gap through its first-child rules. */
.pdr-nt-layers .pdr-no-layers-message > :first-child,
.pdr-nt-layers .pdr-no-layers-message > :last-child {
	margin: 0;
}

/*
 * jQuery reveals the notice with .show(), which writes display: block and would
 * drop the icon back onto its own line beside a full-width label.
 */
.pdr-nt-layers .pdr-no-layers-message[style*="block"] {
	display: flex !important;
}

/* ── Bottom bar ──────────────────────────────────────────── */

.pdr-nt-bottombar {
	display: flex;
	align-items: center;
	gap: 18px;
	flex-shrink: 0;
	min-height: var(--pdr-nt-bottombar-h);
	padding: 10px 20px;
	background: var(--pdr-nt-surface);
	border-top: 1px solid var(--pdr-nt-line);
}

.pdr-nt-bottombar-divider {
	width: 1px;
	height: 38px;
	background: var(--pdr-nt-line);
	flex-shrink: 0;
}

.pdr-nt-bottombar-spacer {
	flex: 1;
}



/*
 * The two flexible sections of the bar.
 *
 * Both used to refuse to shrink, and the row was kept in bounds by a media
 * query that narrowed them below a 1200px window. A media query asks the
 * viewport, and the studio is not always the viewport: with Show Header &
 * Footer set to From Theme it is rendered inside the theme's content container,
 * so on a 1536px screen the studio was 931px wide, the query never fired, and
 * the row asked for 980px - putting Add to Cart 49px past the studio's edge
 * where the shell's overflow clipped it in half.
 *
 * They shrink by their own nature instead, so the bar fits whatever width it is
 * given without anything having to know how wide the window is. The quantity
 * stepper is not in this: there is no useful smaller version of it.
 */
.pdr-nt-bottombar-product {
	display: flex;
	align-items: center;
	gap: 12px;
	flex-shrink: 1;
	min-width: 0;
}

.pdr-nt-thumb {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	overflow: hidden;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: #f1f3f5;
	flex-shrink: 0;
}

.pdr-nt-thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.pdr-nt-bottombar-product-meta {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

.pdr-nt-bottombar-product-name {
	font-size: 14px;
	font-weight: 600;
	line-height: 1.3;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	max-width: 190px;
}

.pdr-nt-bottombar-label {
	font-size: 12px;
	font-weight: 500;
	color: var(--pdr-nt-muted-2);
	white-space: nowrap;
}

.pdr-nt-bottombar-options,
.pdr-nt-bottombar-qty {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-shrink: 0;
}

.pdr-nt-bottombar-options {
	flex-shrink: 1;
	min-width: 0;
	/*
	 * At most this much of the bar, so a product with a long list of attributes
	 * cannot push the total and the two actions out of it. The cap lives here
	 * rather than on the chip row inside, because a percentage resolves against
	 * the parent: on the row that meant 46% of this section, and this section is
	 * sized by its own content - so the cap capped itself to 154px of a 282px row
	 * and the chips scrolled inside a bar 1536px wide with 325px of it empty.
	 * Here the parent is the bar, which is what "a share of the bar" has to mean.
	 */
	max-width: 46%;
}

/*
 * One line that scrolls, rather than wrapping. A product base can configure any
 * number of attributes and every one of them has a chip here now, so wrapping
 * grew the bar a row at a time and pushed the design up; the row keeps its
 * height and the chips past the end are scrolled to.
 */
.pdr-nt-option-summary {
	display: flex;
	align-items: center;
	gap: 5px;
	flex-wrap: nowrap;
	/*
	 * As wide as the bar can spare. The row used to stop at 340px whatever the
	 * window was, so on a wide screen the chips scrolled inside a third of the
	 * bar while the empty spacer beside them took the rest - the options are
	 * what a customer checks before buying and they were the one part of the
	 * bar not given the room. It still gives way first when the bar is short:
	 * the shrink rules further down are what decide that.
	 *
	 * The share the row may take is set on .pdr-nt-bottombar-options above, which
	 * is the child of the bar. It used to be set here as 46vw - measured against
	 * a window the studio does not always fill - and the row simply fills the
	 * room that section is given.
	 */
	overflow-x: auto;
	scrollbar-width: thin;
}

/* Chips keep their size when the row is narrower than they are. */
.pdr-nt-option-summary > .pdr-nt-chip {
	flex-shrink: 0;
}

/* The attribute's name, quiet beside the answer to it. */
.pdr-nt-chip-key {
	font-weight: 500;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-chip {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	height: 26px;
	padding: 0 10px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: 13px;
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-ink);
	font-size: 11px;
	font-weight: 600;
	white-space: nowrap;
	cursor: pointer;
}

.pdr-nt-chip-ghost {
	border-style: dashed;
	color: var(--pdr-nt-muted);
	background: var(--pdr-nt-surface);
}

.pdr-nt-chip:hover {
	border-color: var(--pdr-nt-accent);
	color: var(--pdr-nt-accent);
}

.pdr-nt-chip-swatch {
	width: 12px;
	height: 12px;
	border-radius: 50%;
	border: 1px solid rgba(0, 0, 0, .15);
	flex-shrink: 0;
}

.pdr-nt-stepper-group {
	display: flex;
	align-items: center;
	height: 34px;
	overflow: hidden;
	border: 1px solid var(--pdr-nt-line);
	border-radius: 7px;
	background: var(--pdr-nt-surface-2);
}

.pdr-nt-stepper-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	/* Fixed track, so the two buttons never squash while the field will not. */
	flex: 0 0 32px;
	width: 32px;
	height: 100%;
	border: none;
	background: transparent;
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
}

.pdr-nt-stepper-btn:hover {
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-stepper-value {
	/*
	 * A flex item's min-width:auto resolves to its content based minimum, and
	 * for a number input that is its default character width - far wider than
	 * the 46px asked for here, which the floor then overrides. Without the
	 * min-width:0 the stepper renders several times its intended width and
	 * shoulders the rest of the bottom bar along.
	 */
	flex: 0 0 46px;
	min-width: 0;
	width: 46px;
	height: 100%;
}

/*
 * The cell between the two buttons: the stepper's middle, not a field of its
 * own, and no native spinner - the buttons either side are the way to change
 * the quantity.
 *
 * Two foreign rules dress a number input on this page, and this is ranked over
 * both of them. A theme's own input[type="number"] scores 0,1,1, and Semantic's
 * .ui.form input[type="number"] scores 0,3,1; the pair below score 0,2,1 and
 * 0,4,1. Under them the bottom bar's stepper wore the theme's grey inset field
 * and the Product panel's - the one stepper that sits inside a Semantic form -
 * wore Semantic's white rounded box, so the same control in two places matched
 * neither the other nor the design.
 *
 * appearance matters most in that panel. Semantic declares none, which is not
 * the same thing as textfield: Firefox draws the spin buttons for none and
 * hides them only for textfield, and knows nothing of the ::-webkit-
 * pseudo-elements below - so that quantity field carried the native arrows
 * alongside its own two buttons, two sets of controls on one field.
 */
.pdr-nt input.pdr-nt-stepper-value,
.pdr-nt .ui.form input.pdr-nt-stepper-value {
	-moz-appearance: textfield;
	appearance: textfield;
	padding: 0;
	border: none;
	border-left: 1px solid var(--pdr-nt-line);
	border-right: 1px solid var(--pdr-nt-line);
	border-radius: 0;
	box-shadow: none;
	background: transparent;
	text-align: center;
	font-family: inherit;
	font-size: 13px;
	font-weight: 600;
	line-height: normal;
	color: var(--pdr-nt-ink);
	outline: none;
}

.pdr-nt input.pdr-nt-stepper-value::-webkit-outer-spin-button,
.pdr-nt input.pdr-nt-stepper-value::-webkit-inner-spin-button,
.pdr-nt .ui.form input.pdr-nt-stepper-value::-webkit-outer-spin-button,
.pdr-nt .ui.form input.pdr-nt-stepper-value::-webkit-inner-spin-button {
	-webkit-appearance: none;
	appearance: none;
	margin: 0;
}

.pdr-nt-total {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	flex-shrink: 0;
}

.pdr-nt-total-label {
	display: flex;
	align-items: center;
	gap: 4px;
	font-size: 10px;
	font-weight: 400;
	letter-spacing: .6px;
	text-transform: uppercase;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-total-value {
	font-size: 20px;
	font-weight: 700;
	letter-spacing: -.5px;
	color: var(--pdr-nt-success);
}

.pdr-nt-total-value .amount,
.pdr-nt-total-value bdi {
	color: inherit;
}

.pdr-nt-breakdown {
	position: absolute;
	right: 0;
	bottom: calc(100% + 10px);
	z-index: 40;
	width: 256px;
	padding: 14px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius-lg);
	background: var(--pdr-nt-surface);
	box-shadow: 0 12px 32px rgba(0, 0, 0, .16);
	text-align: left;
}

.pdr-nt-breakdown-title {
	display: block;
	margin-bottom: 9px;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .7px;
	text-transform: uppercase;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-breakdown-row {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 10px;
	margin-bottom: 7px;
	font-size: 12px;
}


.pdr-nt-breakdown-total {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-top: 9px;
	padding-top: 9px;
	border-top: 1px solid var(--pdr-nt-line-soft);
	font-size: 13px;
	font-weight: 700;
}

/* ── Footnote ────────────────────────────────────────────── */

/*
 * The mockup's shell is exactly one viewport with the bottom bar last. The
 * plugin also has a configurable footer line, so it rides inside the shell as a
 * slim strip rather than as a block below it, which would push the bottom bar
 * off screen. Hide it in Studio Layout for the mockup's exact look.
 */
.pdr-nt-footnote {
	flex-shrink: 0;
	padding: 6px 20px;
	border-top: 1px solid var(--pdr-nt-line-soft);
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-muted-2);
	font-size: 11px;
	text-align: center;
}

.pdr-nt-footnote p {
	margin: 0;
}

.pdr-nt-footnote a {
	color: var(--pdr-nt-muted);
}

/* ── Modals ──────────────────────────────────────────────── */

.pdr-nt-modal {
	position: fixed;
	inset: 0;
	z-index: 9000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 20px;
}

.pdr-nt-modal-backdrop {
	position: absolute;
	inset: 0;
	background: rgba(0, 0, 0, .6);
}

.pdr-nt-modal-dark .pdr-nt-modal-backdrop {
	background: rgba(0, 0, 0, .78);
}

.pdr-nt-modal-dialog {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	width: 480px;
	max-width: 95vw;
	max-height: 90vh;
	overflow: hidden;
	border-radius: 16px;
	background: var(--pdr-nt-surface);
	box-shadow: var(--pdr-nt-shadow-lg);
}

.pdr-nt-modal-dialog-preview {
	width: auto;
	max-width: 92vw;
	background: transparent;
	box-shadow: none;
	align-items: center;
}

.pdr-nt-modal-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 18px 20px 14px;
	border-bottom: 1px solid var(--pdr-nt-line-soft);
}

.pdr-nt-modal-title {
	margin: 0;
	font-size: 16px;
	font-weight: 700;
	color: var(--pdr-nt-ink);
}

.pdr-nt-modal-body {
	padding: 20px;
	overflow-y: auto;
}

/*
 * Sits directly above the footer, so the reason the button did nothing is next
 * to the button that did nothing.
 */
.pdr-nt-modal-error {
	margin: 0 20px 4px;
	padding: 11px 13px;
	border: 1px solid #fecaca;
	border-radius: var(--pdr-nt-radius);
	background: #fef2f2;
	color: #b91c1c;
	font-size: 12px;
	line-height: 1.5;
}

.pdr-nt-modal-error[hidden] {
	display: none;
}

.pdr-nt-modal-error-lead {
	margin: 0;
	font-weight: 600;
}

.pdr-nt-modal-error-list {
	margin: 5px 0 0;
	padding-left: 17px;
	list-style: disc;
}

.pdr-nt-modal-error-list li {
	margin: 2px 0 0;
}

.pdr-nt-modal-foot {
	display: flex;
	gap: 10px;
	padding: 14px 20px;
	background: var(--pdr-nt-surface-2);
	border-top: 1px solid var(--pdr-nt-line-soft);
}

.pdr-nt-modal-foot .pdr-nt-btn:first-child {
	flex: 1;
}

.pdr-nt-modal-foot .pdr-nt-btn:last-child {
	flex: 2;
}

.pdr-nt-modal-close-float {
	position: absolute;
	top: -44px;
	right: 0;
	color: #fff;
}

.pdr-nt-modal-close-float:hover {
	background: rgba(255, 255, 255, .16);
	color: #fff;
}

.pdr-nt-checkout-body {
	display: flex;
	gap: 20px;
	align-items: flex-start;
}

/*
 * The design, one thumbnail per view that has been worked on. A single view
 * fills the column as it always did; several share it two abreast, which at
 * this dialog's width keeps each one big enough to recognise the design on.
 */
.pdr-nt-checkout-preview {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	align-items: center;
	justify-items: center;
	gap: 10px;
	width: 150px;
	min-height: 140px;
	padding: 14px;
	flex-shrink: 0;
	border-radius: 10px;
	background: #f8f9fa;
}

.pdr-nt-checkout-preview.has-many {
	grid-template-columns: repeat(2, minmax(0, 1fr));
	width: 208px;
}

.pdr-nt-checkout-view {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
	min-width: 0;
	max-width: 100%;
}

.pdr-nt-checkout-preview img {
	max-width: 100%;
	height: auto;
	display: block;
	border-radius: 6px;
	background: #fff;
}

/* Which side of the product this one is. */
.pdr-nt-checkout-view-name {
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .2px;
	color: var(--pdr-nt-muted);
}

.pdr-nt-checkout-details {
	flex: 1;
	display: flex;
	flex-direction: column;
	gap: 13px;
	min-width: 0;
}

.pdr-nt-checkout-name {
	font-size: 16px;
	font-weight: 700;
}

/*
 * Each name against its own value.
 *
 * The rows were flex lines with space-between, which on a 270px column put a
 * 25px name at one end and a 32px value at the other with 210px of nothing
 * across the middle - so pairing "Size" with "20PX" meant reading across the
 * whole panel, and a list of five of them read as two unrelated columns.
 *
 * A two column grid instead: the names take exactly the width the longest of
 * them needs and every value starts just after it, which also lines the values
 * up with each other so the list can be scanned down.
 */
.pdr-nt-checkout-rows {
	display: grid;
	grid-template-columns: max-content minmax(0, 1fr);
	/*
	 * Room between what was asked and what was answered. At 14px the two columns
	 * read as one run of words - "Untitled Tesy" - rather than as a question and
	 * its answer, which is the whole job of this list: the customer is checking
	 * that each value is against the right name before they buy.
	 */
	gap: 8px 24px;
	margin: 0;
	align-items: baseline;
}

/*
 * The row wrapper steps aside so its name and value are the grid's own items -
 * and so does the container the studio fills with a row per option, which is
 * itself a child of the list. Left as a block it took one cell of the grid and
 * laid its own rows out inside it, so the options fell out of the two columns
 * while the fixed rows stayed in them.
 */
.pdr-nt-checkout-row,
.pdr-nt-checkout-rows [data-pdr-checkout-options] {
	display: contents;
}

.pdr-nt-checkout-row dt {
	font-size: 13px;
	color: var(--pdr-nt-muted);
}

.pdr-nt-checkout-row dd {
	margin: 0;
	font-size: 13px;
	font-weight: 600;
	text-align: left;
	overflow-wrap: anywhere;
}

/*
 * The order block: how many, then how much. Ruled off from the list of choices
 * above it, because these two lines are about what is being bought rather than
 * about what the design looks like.
 */
.pdr-nt-checkout-order {
	display: flex;
	flex-direction: column;
	gap: 9px;
	padding-top: 13px;
	border-top: 1px solid var(--pdr-nt-line-soft);
}

/*
 * Quantity reads as the total's own line, not as an attribute: the same two
 * column shape as the total under it, a size down, so the eye takes the pair
 * together and lands on the figure that matters.
 */
.pdr-nt-checkout-qty {
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-size: 13px;
	color: var(--pdr-nt-muted);
}

.pdr-nt-checkout-qty-value {
	font-weight: 600;
	color: var(--pdr-nt-ink);
	font-variant-numeric: tabular-nums;
}

/*
 * The rule now belongs to the block above, which holds both lines - it used to
 * be here, where it separated the total from a quantity row that was itself
 * still part of the attribute list.
 */
.pdr-nt-checkout-total {
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-size: 13px;
	color: var(--pdr-nt-muted);
}

.pdr-nt-preview-stage {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 20px;
	border-radius: var(--pdr-nt-radius-lg);
	background: var(--pdr-nt-surface);
	min-width: 240px;
	min-height: 240px;
}

.pdr-nt-preview-stage img {
	max-width: 100%;
	max-height: 78vh;
	display: block;
}

/* ── Engine modal restyle ────────────────────────────────── */

/*
 * Semantic carries these off to a dimmer on the body, so they are outside the
 * studio and inherit the theme's typography rather than the studio's. Stated
 * here, and only here: the palette they draw from is declared with the tokens
 * at the top of this file.
 */
.pdr-nt-engine-modal.ui.modal {
	border-radius: 16px;
	font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
	font-size: 13px;
	line-height: 1.45;
	color: var(--pdr-nt-ink);
}

.pdr-nt-engine-modal.ui.modal *,
.pdr-nt-engine-modal.ui.modal *::before,
.pdr-nt-engine-modal.ui.modal *::after {
	box-sizing: border-box;
}

.pdr-nt-engine-modal.ui.modal [hidden] {
	display: none !important;
}

.pdr-nt-engine-modal.ui.modal > .header {
	font-family: inherit;
	font-size: 16px;
	font-weight: 700;
	color: var(--pdr-nt-ink);
	border-bottom: 1px solid var(--pdr-nt-line-soft);
	/* Room at the end of the line for the close control, which sits over it. */
	padding-right: 56px;
}

/*
 * The close control, brought in off the dimmer.
 *
 * Semantic hangs it above the top right corner, outside the dialog, in white -
 * which on a pale page is a cross floating on the backdrop with no dialog edge
 * near it to say what it closes. It is given the studio's icon button instead,
 * inside the corner it belongs to.
 */
.pdr-nt-engine-modal.ui.modal > .close.icon {
	top: 12px;
	right: 12px;
	width: 30px;
	height: 30px;
	padding: 0;
	line-height: 30px;
	text-align: center;
	border-radius: var(--pdr-nt-radius);
	color: var(--pdr-nt-muted);
	opacity: 1;
	transition: background .15s ease, color .15s ease;
}

.pdr-nt-engine-modal.ui.modal > .close.icon:hover {
	background: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-ink);
}

.pdr-nt-engine-modal.ui.modal > .scrolling.content {
	padding: 18px 20px 20px;
	background: var(--pdr-nt-surface);
	border-bottom-left-radius: 16px;
	border-bottom-right-radius: 16px;
}

/* ── Product base picker ─────────────────────────────────── */

/*
 * Two columns: the categories, and the grid of whatever the chosen one holds.
 * The categories keep a fixed measure so the grid gets every pixel the dialog
 * has left, which is what decides how many cards fit across it.
 */
.pdr-nt-base-picker.ui.modal {
	width: 1000px;
	max-width: calc(100vw - 40px);
	margin: 0;
}

.pdr-nt-picker {
	display: grid;
	grid-template-columns: 188px minmax(0, 1fr);
	gap: 22px;
	align-items: start;
}

.pdr-nt-picker-cats {
	display: flex;
	flex-direction: column;
	gap: 8px;
	/* The grid is the part that scrolls; the categories stay in view beside it. */
	position: sticky;
	top: 0;
}

.pdr-nt-picker-cats-title {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-picker-cat-list {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.pdr-nt-picker-cat {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	width: 100%;
	min-height: 32px;
	/* Stated against a theme that pads every button on the page. */
	padding: 6px 10px;
	margin: 0;
	border: 0;
	border-radius: var(--pdr-nt-radius);
	background: transparent;
	font-family: inherit;
	font-size: 13px;
	line-height: 1.3;
	text-align: left;
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
	transition: background .15s ease, color .15s ease;
}

.pdr-nt-picker-cat:hover {
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-ink);
}

.pdr-nt-picker-cat.is-active {
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
	font-weight: 600;
}

.pdr-nt-picker-cat-name {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.pdr-nt-picker-cat-count {
	flex: 0 0 auto;
	min-width: 20px;
	padding: 1px 6px;
	border-radius: 999px;
	background: var(--pdr-nt-line-soft);
	font-size: 11px;
	font-weight: 600;
	text-align: center;
	color: var(--pdr-nt-muted);
}

.pdr-nt-picker-cat.is-active .pdr-nt-picker-cat-count {
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-accent);
}

.pdr-nt-picker-main {
	display: flex;
	flex-direction: column;
	gap: 14px;
	min-width: 0;
}

/*
 * What the grid is showing, stated over it. The count is the part that answers
 * "is this everything?" - it says how many are on screen, and while a search is
 * narrowing them, how many of how many.
 */
.pdr-nt-picker-info {
	display: flex;
	flex-direction: column;
	gap: 3px;
	padding-bottom: 11px;
	border-bottom: 1px solid var(--pdr-nt-line-soft);
}

.pdr-nt-picker-info-head {
	display: flex;
	align-items: baseline;
	gap: 8px;
}

.pdr-nt-picker-info-title {
	font-size: 14px;
	font-weight: 700;
	color: var(--pdr-nt-ink);
}

.pdr-nt-picker-info-count {
	font-size: 12px;
	color: var(--pdr-nt-muted);
}

.pdr-nt-picker-info-desc {
	margin: 0;
	font-size: 12px;
	line-height: 1.5;
	color: var(--pdr-nt-muted);
}

.pdr-nt-picker-search {
	height: 36px;
}

/*
 * The cards were a Semantic four-across row, which meant four across at every
 * width - four 55px slivers on a phone, each name broken one letter to a line.
 * The grid asks for a card measure instead and fits as many as the dialog can
 * hold, so the same rule serves the phone and the desktop.
 */
.pdr-nt-picker-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
	gap: 14px;
	align-content: start;
	min-height: 60px;
}

/*
 * One card shape for every base, whatever shape its photo is. The image sits in
 * a box of a fixed height and is contained inside it, so a mug and a t-shirt
 * come out the same size and every name in the grid lands on the same line -
 * where before each card was as tall as its own picture and the names stepped
 * up and down the row.
 */
.pdr-nt-base-picker .pdr_popup_card {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	margin: 0;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius-lg);
	background: var(--pdr-nt-surface);
	box-shadow: none;
	color: var(--pdr-nt-ink);
	text-decoration: none;
	transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.pdr-nt-base-picker .pdr_popup_card:hover,
.pdr-nt-base-picker .pdr_popup_card:focus-visible {
	border-color: var(--pdr-nt-accent);
	box-shadow: var(--pdr-nt-shadow);
	transform: translateY(-2px);
	color: var(--pdr-nt-ink);
	text-decoration: none;
}

.pdr-nt-base-picker .pdr_popup_card > .image {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 132px;
	padding: 10px;
	border: 0;
	border-radius: 0;
	background: var(--pdr-nt-surface-2);
}

.pdr-nt-base-picker .pdr_popup_card > .image img {
	width: auto;
	max-width: 100%;
	max-height: 100%;
	border-radius: 0;
	object-fit: contain;
}

.pdr-nt-base-picker .pdr_popup_card > .extra {
	padding: 9px 11px;
	border-top: 1px solid var(--pdr-nt-line-soft);
	font-size: 12px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--pdr-nt-ink);
	/* A long name is trimmed rather than allowed to grow the card past its row. */
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
}

.pdr-nt-picker-empty {
	margin: 0;
}

/*
 * Narrow: the categories give up their column and become a row of chips above
 * the grid. Nothing is dropped - the whole list is still there, scrolling
 * sideways - and the grid gets the dialog's full width, which is what a small
 * screen has least of.
 */
@media (max-width: 900px) {
	.pdr-nt-picker {
		grid-template-columns: minmax(0, 1fr);
		gap: 14px;
	}

	.pdr-nt-picker-cats {
		position: static;
		gap: 7px;
	}

	.pdr-nt-picker-cat-list {
		flex-direction: row;
		gap: 7px;
		overflow-x: auto;
		/* Room for the chip outline, which a scroll container would clip. */
		padding-bottom: 2px;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: thin;
	}

	.pdr-nt-picker-cat {
		flex: 0 0 auto;
		width: auto;
		border: 1px solid var(--pdr-nt-line);
		border-radius: 999px;
		padding: 5px 11px;
	}

	.pdr-nt-picker-cat.is-active {
		border-color: var(--pdr-nt-accent);
	}
}

@media (max-width: 767px) {
	/*
	 * Semantic states the dialog's header padding with !important down here, so
	 * the room the close control needs has to be claimed the same way.
	 */
	.pdr-nt-engine-modal.ui.modal > .header {
		padding-right: 52px !important;
	}

	.pdr-nt-engine-modal.ui.modal > .scrolling.content {
		padding: 14px !important;
	}

	.pdr-nt-base-picker.ui.modal {
		max-width: calc(100vw - 24px);
	}

	.pdr-nt-picker-grid {
		grid-template-columns: repeat(auto-fill, minmax(126px, 1fr));
		gap: 10px;
	}

	.pdr-nt-base-picker .pdr_popup_card > .image {
		height: 104px;
	}
}

/* ── Responsive ──────────────────────────────────────────── */

@media (max-width: 1200px) {
	.pdr-nt {
		--pdr-nt-panel-w: 240px;
		--pdr-nt-props-w: 240px;
	}

	/*
	 * The options row stays. It used to be dropped outright at this width, and a
	 * customer zooming the browser in - which is what this width mostly means on
	 * a desktop - watched their options vanish from the bar with the Product
	 * panel possibly collapsed and no other way to see or change them. It gives
	 * up width instead of giving up: the chips scroll inside a narrower row, and
	 * the row is the part of the bar that yields first, so the total and the two
	 * actions at the end of it keep their room.
	 */
	.pdr-nt-bottombar-options {
		flex-shrink: 1;
		min-width: 0;
		gap: 6px;
	}

	/*
	 * The row keeps its "Options" label at this width, the same as at any other:
	 * the bar reads as a row of named sections and dropping one section's name
	 * only where the window is narrow made the chips beside it look like they
	 * belonged to the quantity. The width the label needs comes out of the chips,
	 * which scroll, rather than out of anything that cannot give any.
	 */
	.pdr-nt-option-summary {
		max-width: 220px;
		/*
		 * A floor, or the row is the only thing in the bar that can give and it
		 * gives everything: at 900px it had shrunk to a 33px sliver, so the label
		 * named a set of chips that were no longer there to read. Below this it
		 * stops shrinking and the product name gives way instead, that name being
		 * the one thing in the bar the top bar and the Product panel both repeat.
		 */
		min-width: 120px;
	}

	.pdr-nt-bottombar-product {
		flex-shrink: 1;
		min-width: 0;
	}

	.pdr-nt-bottombar-product-name {
		max-width: 100%;
	}

	.pdr-nt-bottombar {
		gap: 12px;
		padding: 10px 14px;
	}
}

/*
 * Tablets keep the whole properties column as one drawer from the right edge.
 * Phones split it in two - see the phone block below - so these are bounded
 * rather than reaching all the way down.
 *
 * The height bound keeps a phone in landscape out of this: it sits inside this
 * width and takes the phone layout, where the column is display: contents and
 * each half places itself against its own edge. Both rulesets applying left the
 * column positioned as a tablet drawer and its two halves positioned as phone
 * drawers inside it, so the layers list opened off the side of the screen.
 */
@media (min-width: 783px) and (max-width: 960px) and (min-height: 541px) {
	.pdr-nt-properties {
		position: absolute;
		top: var(--pdr-nt-topbar-h);
		right: 0;
		bottom: var(--pdr-nt-bottombar-h);
		z-index: 12;
		box-shadow: -8px 0 24px rgba(0, 0, 0, .12);
	}

	/*
	 * A drawer from this width down, opened by the handle on the right edge.
	 * That handle also marks the column collapsed, and the desktop rule reads
	 * that as "hide it", so the two states cancelled and the drawer could never
	 * be opened at all — which put the Layers panel out of reach.
	 * Down here its visibility is the drawer state's business alone.
	 */
	.pdr-nt.is-right-collapsed .pdr-nt-properties {
		display: flex;
	}

	.pdr-nt:not(.is-properties-open) .pdr-nt-properties {
		display: none;
	}
}

@media (max-width: 960px) {
	.pdr-nt-topbar-actions .pdr-nt-btn span:not(.pdr-nt-icon) {
		display: none;
	}

	.pdr-nt-topbar-actions .pdr-nt-btn {
		padding: 0 12px;
	}
}

/*
 * A short screen cannot give a sheet 58% of itself and still have room above it
 * for the design and the two tool lanes that rise with the sheet. At 568px tall
 * the lanes were pushed up into the undo, redo and zoom controls at the top of
 * the design. The sheet takes a smaller share there; it scrolls inside itself,
 * so nothing in the panel is lost by giving it less.
 */
@media (max-width: 782px) and (max-height: 640px) {
	/* Two classes, so it wins against the phone block's own max-height below
	 * whichever order the two rules end up in. */
	.pdr-nt .pdr-nt-toolpanel {
		max-height: 42%;
	}
}

/*
 * ── The same steps, measured on the studio ───────────────
 *
 * Everything above asks the viewport. That is right while the studio fills the
 * window and wrong the moment it does not: with Show Header & Footer set to
 * From Theme it is rendered inside the theme's content container, so a 1440px
 * screen gives it 931px and none of the steps above fire.
 *
 * These are the same steps keyed to the studio's own measured width, which
 * syncShellWidth() in studio.js writes as a class. They land at the same
 * points as the queries above when the studio does fill the window, so the two
 * agree rather than compete - and they only ever take room away, never give it
 * back, so the phone layout further down is free to overrule them.
 *
 * The bar's own gap and padding are deliberately not here: the phone block sets
 * those with a single class selector, and a rule of this specificity would beat
 * it whatever the order.
 */
.pdr-nt.is-w-lt1200 {
	--pdr-nt-panel-w: 240px;
	--pdr-nt-props-w: 240px;
}

.pdr-nt.is-w-lt1200 .pdr-nt-bottombar-options,
.pdr-nt.is-w-lt1200 .pdr-nt-bottombar-product {
	flex-shrink: 1;
	min-width: 0;
}

.pdr-nt.is-w-lt1200 .pdr-nt-bottombar-options {
	gap: 6px;
}

/*
 * A floor under the options row. It gives way first when the bar is short, and
 * without a floor it gave way to nothing: 57px of scroller around a chip that
 * needed 103, which is a control the customer cannot read and would not think
 * to scroll. Below this the product name yields instead - that name being the
 * one thing in the bar the top bar and the Product panel both repeat.
 */
.pdr-nt.is-w-lt1200 .pdr-nt-option-summary {
	min-width: 132px;
}

.pdr-nt.is-w-lt1200 .pdr-nt-bottombar-product-name {
	max-width: 100%;
}

/*
 * Narrower still, and the two section labels go. "Options" and "Quantity" name
 * controls that say what they are - a row of option chips, a stepper with a
 * number in it - and between them they were spending about 110px of a bar that
 * had none to spare, which came out of the product name and the chips beside
 * them. The controls keep their accessible names.
 */
.pdr-nt.is-w-lt960 .pdr-nt-bottombar-label {
	display: none;
}

/*
 * And the top bar's actions keep their icons only, which is what the viewport
 * query at this width has always done. Packed at full width against the File
 * and Print menus, those labels left the row with no space in it at all.
 */
.pdr-nt.is-w-lt960 .pdr-nt-topbar-actions .pdr-nt-btn span:not(.pdr-nt-icon) {
	display: none;
}

.pdr-nt.is-w-lt960 .pdr-nt-topbar-actions .pdr-nt-btn {
	padding: 0 12px;
}

/*
 * ── Phones ───────────────────────────────────────────────
 *
 * The studio becomes an app rather than a shrunken desktop: the design fills
 * the screen, the tools are a tab bar along the bottom, and a tool's panel
 * arrives as a sheet over the design instead of a column that pushes it out of
 * the way. The bars keep only what is not reachable from a panel, so the canvas
 * gets the room rather than four rows of duplicated chrome.
 *
 * The second query is a phone held sideways. It is wider than the breakpoint and
 * shorter than anything the desktop layout was drawn for - 844x390 on an iPhone
 * 14, 915x412 on a Pixel - and it used to land on the desktop layout, where a
 * 64px top bar, a 72px bottom bar and a vertical rail left the product behind
 * its own toolbars with the rail clipped mid-tab. The width bound keeps a
 * desktop window dragged short out of it; no phone in landscape is that wide.
 * The block below tunes this layout for the little height such a screen has.
 *
 * Kept in step with phoneQuery() in studio.js by hand.
 */
@media (max-width: 782px), (max-width: 1024px) and (max-height: 540px) {
	/*
	 * Out to both edges of the screen, cancelling whatever inset the theme's
	 * content container gives the studio. The two amounts are measured by
	 * fitShellWidth() in studio.js, because they belong to the active
	 * theme rather than to this stylesheet.
	 *
	 * max-width goes with them: it is 100% of the containing block, which is the
	 * inset container itself, so it would clamp the studio straight back to the
	 * width the negative margins had just freed it from.
	 */
	.pdr-nt.is-bleeding {
		max-width: none;
		margin-left: calc(-1 * var(--pdr-nt-bleed-l, 0px));
		margin-right: calc(-1 * var(--pdr-nt-bleed-r, 0px));
	}

	/*
	 * ── The chrome pays for the canvas ──
	 *
	 * Every row of bar on a phone is a row the product does not get, and the
	 * design is the thing the customer came for. The three fixed bars were drawn
	 * at desktop heights - 64px, 62px and 65px, a fifth of an iPhone between them
	 * - so each gives up what it can while keeping its controls at a size a thumb
	 * still hits: the tab bar's buttons stay at 46px against the 44px floor, and
	 * the two action bars lose padding rather than anything pressable.
	 */
	.pdr-nt {
		--pdr-nt-rail-w: 100%;
		--pdr-nt-topbar-h: 52px;
		--pdr-nt-tabbar-h: 56px;
		--pdr-nt-bottombar-h: 56px;
	}

	/*
	 * The design keeps its size, whatever is open over it.
	 *
	 * The tool sheet and the layers sheet are drawn above this column rather than
	 * beside it, and the column is not made smaller to let them in: the product
	 * stays the size the customer has been looking at, and a panel covers the
	 * foot of it while it is up. Reserving the room instead meant the product
	 * shrank and grew as panels came and went - on a small phone down to a third
	 * of itself - and a design you are trying to place something on should not
	 * change size underneath you.
	 *
	 * The lanes the selection puts on this same edge still rise over a raised
	 * sheet, so the tools stay reachable; see --pdr-nt-sheet-h.
	 */

	.pdr-nt-main {
		position: relative;
		flex-direction: column;
	}

	/* The tab bar along the bottom, which is what the rail becomes. */
	.pdr-nt-rail {
		order: 3;
		z-index: 16;
		flex-direction: row;
		width: 100%;
		height: var(--pdr-nt-tabbar-h);
		padding: 3px 8px;
		overflow-x: auto;
		overflow-y: hidden;
		border-right: none;
		border-top: 1px solid var(--pdr-nt-line);
	}

	.pdr-nt-rail-divider {
		flex: 0 0 auto;
		width: 1px;
		height: 32px;
		margin: 0 4px;
	}

	/*
	 * The tabs share the row out between them, however many there are.
	 *
	 * Each one was a fixed 54px, sized for the vertical rail this becomes down
	 * here, so the row was laid out for some other number of tools than the
	 * store has: six of them on a 390px screen left 50px of empty bar at the end
	 * that read as a tab with nothing in it, and the gap moved with every tool a
	 * merchant switched on or off.
	 *
	 * Grow but do not shrink: with room to spare they divide it equally and the
	 * row is full, and a store with more tools than fit keeps its own width per
	 * tab and the row scrolls, which is what it did before. The label ellipsises
	 * rather than pushing its neighbours about - at eight tabs on the narrowest
	 * phone there is not room for "Templates" whatever the layout does.
	 */
	.pdr-nt-rail-btn {
		flex: 1 0 auto;
		width: auto;
		min-width: 44px;
		max-width: 100%;
	}

	.pdr-nt-rail-label {
		max-width: 100%;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	/*
	 * A sheet over the design, rising from the tab bar. In the column layout it
	 * was a block in the flow, so opening a tool squeezed the canvas to a strip;
	 * the design now keeps its size whether a panel is open or not.
	 */
	.pdr-nt-toolpanel {
		order: 2;
		position: absolute;
		left: 0;
		right: 0;
		bottom: var(--pdr-nt-tabbar-h);
		z-index: 15;
		/*
		 * auto, so the two insets above decide how wide this is. It was 100%,
		 * which beats the right inset and measures against the containing block
		 * instead - so anything that left that block narrower than the screen
		 * showed as a band of empty space down the right of the panel.
		 */
		width: auto;
		max-height: 58%;
		border-right: none;
		border-top: 1px solid var(--pdr-nt-line);
		border-radius: var(--pdr-nt-radius-lg) var(--pdr-nt-radius-lg) 0 0;
		box-shadow: 0 -10px 30px rgba(0, 0, 0, .16);
	}

	.pdr-nt {
		--pdr-nt-grip-h: 22px;
	}

	/*
	 * The grip, and the room it takes at the top of a sheet.
	 *
	 * Full width and 44px tall - the whole strip is the target, not just the
	 * bar drawn in it, because a 4px bar is not something a thumb can find.
	 * touch-action: none so dragging it resizes the sheet rather than scrolling
	 * the page behind, which is what a touch browser does with the gesture
	 * otherwise.
	 */
	.pdr-nt-sheet-grip {
		display: flex;
		align-items: center;
		justify-content: center;
		flex-shrink: 0;
		width: 100%;
		height: var(--pdr-nt-grip-h);
		padding: 9px 0;
		border: 0;
		background: none;
		cursor: grab;
		touch-action: none;
		-webkit-tap-highlight-color: transparent;
	}

	.pdr-nt-sheet-grip-bar {
		width: 36px;
		height: 4px;
		border-radius: 999px;
		background: var(--pdr-nt-line);
		transition: background .15s ease;
	}

	.pdr-nt-sheet-grip:hover .pdr-nt-sheet-grip-bar,
	.pdr-nt-sheet-grip:focus-visible .pdr-nt-sheet-grip-bar {
		background: var(--pdr-nt-muted-2);
	}

	/* While a sheet is being dragged nothing should animate or select. */
	.pdr-nt.is-sheet-dragging .pdr-nt-sheet-grip {
		cursor: grabbing;
	}

	.pdr-nt.is-sheet-dragging .pdr-nt-toolpanel,
	.pdr-nt.is-sheet-dragging .pdr-nt-properties > .pdr-nt-section-layers {
		transition: none;
		user-select: none;
	}

	/*
	 * A dragged sheet is given its height inline, and the cap has to give way
	 * for it. The floor keeps the head and the grip reachable, so a sheet can
	 * never be dragged shut - closing is what the close button is for.
	 */
	.pdr-nt-toolpanel[style*="height"],
	.pdr-nt-properties > .pdr-nt-section-layers[style*="height"] {
		max-height: 92%;
		min-height: 96px;
	}

	/* The design takes whatever the bars leave, rather than a fixed floor. */
	.pdr-nt-canvas {
		order: 1;
		flex: 1;
		min-height: 0;
	}

	/*
	 * The floating tools take lanes along the bottom of the design, where a
	 * thumb reaches them, instead of a column down the left and a bar across the
	 * top. Up there the image tools covered both the design and the undo and
	 * redo buttons underneath them, and the object tools floated in the empty
	 * space below the product attached to nothing.
	 *
	 * Each lane spans the width and centres its buttons, so a bar with more
	 * tools than fit wraps rather than being cut off — and nothing here may clip,
	 * because the filters popup opens out of the object bar.
	 */
	/*
	 * The lanes clear the tool sheet rather than sitting under it. The sheet
	 * rises over this same bottom edge, so an object selected while one was up
	 * had its edit bar behind it - and adding a clipart does both at once. The
	 * studio measures the raised sheet into --pdr-nt-sheet-h and it is 0 while
	 * the sheet is down, which is the layout these lanes had before.
	 */
	/*
	 * Zoom is the bottom lane here, so everything that stacks above the foot of
	 * the design clears it by the room it takes: its own 38px and the 8px gap
	 * the lanes keep between themselves. Nothing is reserved where the store has
	 * zoom switched off, because the shell only carries has-zoom when the bar is
	 * actually drawn.
	 */
	.pdr-nt.has-zoom {
		--pdr-nt-zoom-lane: 46px;
	}

	/*
	 * And the lane it was reserving goes back to the design with it - see "The
	 * lanes take turns" below. Without this the bars kept clearing a bar that was
	 * no longer drawn and the room was saved from nobody.
	 */
	.pdr-nt.has-zoom.has-selection,
	.pdr-nt.has-zoom.is-sheet-raised {
		--pdr-nt-zoom-lane: 0px;
	}

	.pdr-nt-contextbar {
		top: auto;
		bottom: calc(56px + var(--pdr-nt-zoom-lane, 0px) + var(--pdr-nt-sheet-h, 0px));
		left: 8px;
		right: 8px;
		width: auto;
		max-width: none;
		transform: none;
	}

	.pdr-nt-objectbar {
		top: auto;
		bottom: calc(8px + var(--pdr-nt-zoom-lane, 0px) + var(--pdr-nt-sheet-h, 0px));
		left: 8px;
		right: 8px;
		width: auto;
		transform: none;
		flex-direction: row;
		flex-wrap: wrap;
		justify-content: center;
	}

	.pdr-nt-objectbar-group {
		flex-direction: row;
	}

	.pdr-nt-objectbar-divider {
		width: 1px;
		height: auto;
		margin: 0 1px;
	}

	/*
	 * Semantic places this popup from the button it belongs to, and on a screen
	 * this narrow its arithmetic put most of it past the right edge. Pinned to
	 * the canvas instead: Semantic keeps deciding how high up it sits, the
	 * screen decides how wide it is.
	 */
	.pdr-nt-popup.ui.popup.pdr-object-filters-view {
		left: 8px !important;
		right: 8px !important;
		width: auto;
		min-width: 0;
		max-width: none;
		margin: 0;
	}

	/*
	 * One scrolling row, not three rows of four.
	 *
	 * The grid is right in the desktop popup, which sits beside the design with
	 * room for all eleven filters at once. Pinned to the width of a phone it
	 * became three rows of tiles standing between the customer and the image
	 * they were filtering, and it pushed the advanced sliders under it out of
	 * reach.
	 *
	 * The layer filter chips are laid out the same way for the same reason: the
	 * row scrolls, the scrollbar is hidden because a touch device draws none of
	 * its own, and the right edge fades so the row reads as carrying on rather
	 * than ending on a clipped tile.
	 */
	.pdr-nt-filters {
		display: flex;
		flex-wrap: nowrap;
		max-width: none;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
		mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
	}

	.pdr-nt-filters::-webkit-scrollbar {
		display: none;
	}

	/*
	 * A tile keeps its width instead of being squeezed to a share of the row,
	 * which is what makes the row scroll at all. 72px shows four and part of a
	 * fifth on the narrowest phone, so there is visibly more to reach.
	 */
	.pdr-nt-filters > .pdr-nt-filter {
		flex: 0 0 72px;
	}

	/*
	 * The badge is not given a lane here. It used to be one, above the
	 * contextual bar at the foot of the design, because it named what that bar
	 * acted on; it is pinned over the object itself now, which is the same place
	 * at every width and needs nothing from this block.
	 */

	/*
	 * Nothing steps in on the left any more: the view drawer's handle used to be
	 * pinned in that band and the lanes and the zoom bar cleared it, and that
	 * handle is gone from this layout along with the drawer it opened.
	 */

	/* The corner is too narrow for the word; the clipboard icon carries it. */
	.pdr-nt-paste-label {
		display: none;
	}

	.pdr-nt-paste-btn {
		width: 32px;
		padding: 0;
	}

	/*
	 * Zoom keeps the bottom left corner it has at every other width, so the
	 * control does not move as the window crosses the breakpoint.
	 *
	 * It rises with the tool sheet the way the lanes below do: the sheet covers
	 * this same edge, and --pdr-nt-sheet-h is 0 while the sheet is down.
	 */
	.pdr-nt-zoombar {
		top: auto;
		right: auto;
		bottom: calc(8px + var(--pdr-nt-sheet-h, 0px));
		left: 8px;
	}

	/*
	 * ── The two edge drawers ──
	 *
	 * The tab bar opens and closes the tool sheet here, so the left handle is
	 * free, and the properties column has two unrelated halves in it. They take
	 * an edge each: the view switcher on the left, the layers list on the right,
	 * each behind the handle on its own side. Stacked in one drawer on a phone
	 * the switcher pushed the layers list off the bottom of it.
	 *
	 * The column is pinned over the main area rather than being dissolved with
	 * display: contents, so each half positions itself against something whose
	 * size is known. contents relied on the browser honouring it - an older
	 * WebView that does not leaves the column a flex item sized for the desktop
	 * layout, and its halves then measured against that instead of against the
	 * studio, which showed as a band of empty space down the right of the sheet.
	 *
	 * It takes no clicks itself, only its halves do, so the pinned box does not
	 * come between the customer and the design underneath it.
	 */
	.pdr-nt-properties {
		position: absolute;
		top: 0;
		right: 0;
		bottom: var(--pdr-nt-tabbar-h);
		left: 0;
		z-index: 12;
		display: block;
		width: auto;
		padding: 0;
		border: none;
		background: none;
		pointer-events: none;
	}

	.pdr-nt-properties > .pdr-nt-section {
		pointer-events: auto;
	}

	.pdr-nt-properties > .pdr-nt-section {
		position: absolute;
		top: 0;
		bottom: var(--pdr-nt-tabbar-h);
		z-index: 12;
		display: none;
		width: min(80%, 320px);
		margin: 0;
		overflow-y: auto;
		overscroll-behavior: contain;
		border: none;
		border-radius: 0;
		background: var(--pdr-nt-surface);
	}

	/*
	 * The view switcher is a popup in the middle of the screen rather than a
	 * drawer off the left edge. As a drawer it was reached only through the bare
	 * chevron on the edge of the design, and it opened over the side of the
	 * product it was there to turn around; in the middle it reads as the one
	 * decision being made, and the Switch View button in the corner is what
	 * opens it.
	 *
	 * Fixed, because the properties column is display: contents here and each
	 * half places itself. The second shadow is the dim behind the popup - a
	 * spread of 100vmax covers the screen without an element to cover it with,
	 * and it takes no clicks, so a tap outside still lands on what is under it.
	 */
	.pdr-nt-properties > .pdr-nt-section[data-pdr-section="views"] {
		position: fixed;
		top: 50%;
		right: auto;
		bottom: auto;
		left: 50%;
		z-index: 30;
		width: min(88vw, 340px);
		max-height: 76vh;
		transform: translate(-50%, -50%);
		border: 1px solid var(--pdr-nt-line);
		border-radius: var(--pdr-nt-radius-lg);
		box-shadow: 0 18px 48px rgba(0, 0, 0, .28), 0 0 0 100vmax rgba(15, 23, 42, .45);
	}

	/* The views panel becomes a popup here, so it gets a close button too. */
	.pdr-nt-properties > .pdr-nt-section[data-pdr-section="views"] .pdr-nt-popup-close {
		display: flex;
	}

	/*
	 * Over the section head, which spans the row as the collapse toggle and has
	 * no room in it for a second control.
	 */
	.pdr-nt-properties > .pdr-nt-section[data-pdr-section="views"] .pdr-nt-popup-close {
		position: absolute;
		top: 7px;
		right: 8px;
		z-index: 1;
	}

	/*
	 * The head is that toggle, and a popup this size has nothing to collapse
	 * into - so it reads as a title with the close button beside it and keeps
	 * its chevron out of the way.
	 */
	.pdr-nt-properties > .pdr-nt-section[data-pdr-section="views"] .pdr-nt-section-head {
		padding-right: 46px;
		pointer-events: none;
	}

	.pdr-nt-properties > .pdr-nt-section[data-pdr-section="views"] .pdr-nt-section-head > .pdr-nt-icon {
		display: none;
	}

	/*
	 * And the body is always shown in it. The head cannot be pressed here, so a
	 * section left collapsed on a wider screen would open as a popup with a
	 * title, a close button and nothing to switch to.
	 */
	.pdr-nt-properties > .pdr-nt-section[data-pdr-section="views"] .pdr-nt-section-body {
		display: block;
	}

	/*
	 * ── The layers list is a sheet, not a side drawer ──
	 *
	 * As a drawer it took min(80%, 320px) off the right edge, and a layer row has
	 * a thumbnail, a name, a price badge and four controls to fit: the name - the
	 * one part that says which layer this is - was the part that gave way, down
	 * to an ellipsised 11px against 26px of thumbnail. It rises from the bottom
	 * over the full width instead, which is where the button that opens it is and
	 * where a row has the room to be read.
	 *
	 * The same shape as the tool sheet, so the two read as one kind of thing.
	 */
	.pdr-nt-properties > .pdr-nt-section-layers {
		/*
		 * Against the pinned column above, which spans the main area, so the
		 * sheet is as wide as the studio whatever the page around it is doing.
		 * Not fixed to the screen: with the theme's header and footer switched on
		 * the studio is a band in the middle of a page that scrolls, and a
		 * screen-fixed sheet would sit over the theme's chrome rather than over
		 * the design.
		 *
		 * auto rather than 100%, so the two insets decide the width - 100% beats
		 * the right inset and measures against the containing block instead.
		 */
		position: absolute;
		top: auto;
		right: 0;
		bottom: 0;
		left: 0;
		width: auto;
		max-height: 58%;
		overflow: hidden;
		border-top: 1px solid var(--pdr-nt-line);
		border-radius: var(--pdr-nt-radius-lg) var(--pdr-nt-radius-lg) 0 0;
		box-shadow: 0 -10px 30px rgba(0, 0, 0, .16);
	}

	/*
	 * A title with a close button, not a collapse toggle. The head spans the row
	 * as a toggle everywhere else, and a sheet has nothing to collapse into - a
	 * section left collapsed on a wider screen would have opened here as a title
	 * over nothing. The views popup is treated the same way for the same reason.
	 */
	.pdr-nt-properties > .pdr-nt-section-layers .pdr-nt-section-head {
		flex-shrink: 0;
		height: 52px;
		padding: 0 56px 0 16px;
		background: var(--pdr-nt-surface);
		pointer-events: none;
	}

	.pdr-nt-properties > .pdr-nt-section-layers .pdr-nt-section-head > .pdr-nt-icon {
		display: none;
	}

	.pdr-nt-properties > .pdr-nt-section-layers .pdr-nt-section-title {
		font-size: 14px;
	}

	.pdr-nt-properties > .pdr-nt-section-layers .pdr-nt-section-body {
		display: flex;
		flex: 1;
		flex-direction: column;
		min-height: 0;
		padding: 0;
	}

	/*
	 * Pinned to the sheet rather than placed after the head, so the grip above
	 * that head does not move it: without the offset the close button sat on
	 * top of the grip and took the presses meant for it.
	 */
	.pdr-nt-properties > .pdr-nt-section-layers .pdr-nt-popup-close {
		position: absolute;
		top: calc(4px + var(--pdr-nt-grip-h, 0px));
		right: 6px;
		z-index: 1;
		display: flex;
		width: 44px;
		height: 44px;
	}

	/* The list scrolls inside the sheet; the filter row above it stays put. */
	.pdr-nt-properties > .pdr-nt-section-layers .pdr-layers-wrapper {
		flex: 1;
		min-height: 0;
		overflow-y: auto;
		overscroll-behavior: contain;
		-webkit-overflow-scrolling: touch;
	}

	/*
	 * A thumb-sized list. The row is built for a mouse at 22px an icon and 26px
	 * a thumbnail, which on a phone is six controls a finger cannot tell apart.
	 * Everything grows, and the full width the sheet gives back is what pays for
	 * it: at 320px of drawer there was no room to grow into.
	 */
	.pdr-nt-layers .pdr-layer-wrapper {
		gap: 10px;
		padding: 8px 12px;
	}

	.pdr-nt-layers .pdr-layer-image {
		width: 44px;
		height: 44px;
		border-radius: 7px;
	}

	.pdr-nt-layers .pdr-layer-actions-wrapper i {
		width: 40px;
		height: 40px;
		font-size: 15px;
	}

	/*
	 * The eye is pulled out to the head of the row by the base rules, so it
	 * keeps the row's own gap; the other three are one cluster, and the negative
	 * margin that tightened them at 22px would overlap 40px targets.
	 */
	.pdr-nt-layers .pdr-layer-actions-wrapper i.pdr-layer-edit-action,
	.pdr-nt-layers .pdr-layer-actions-wrapper i.pdr-layer-lock-action,
	.pdr-nt-layers .pdr-layer-actions-wrapper i.pdr-layer-unlock-action,
	.pdr-nt-layers .pdr-layer-actions-wrapper i.pdr-layer-delete-action {
		margin-left: -8px;
	}

	/*
	 * The name is what says which layer this is, so on a phone it is read at
	 * body size rather than at the 11px the desktop column squeezes it to. It
	 * still ellipsises, but after most of a screen's width instead of after a
	 * few characters.
	 */
	.pdr-nt-layers .pdr-layer-name-text {
		font-size: 14px;
		font-weight: 600;
	}

	.pdr-nt-layers .pdr-layer-object-name {
		font-size: 11px;
	}

	/*
	 * The filter chips, at a thumb's size and on one line. They used to wrap to
	 * two rows of the drawer; across the full width the eight of them fit, and
	 * where they do not - a narrow phone, or a store with every tool on - the row
	 * scrolls sideways rather than taking a second row from the list. Nothing in
	 * this row opens a popup, so there is nothing here for the scroll to clip.
	 */
	.pdr-nt .pdr-nt-section-layers .pdr-nt-layer-filters {
		flex-shrink: 0;
		flex-wrap: nowrap;
		gap: 4px;
		padding: 8px 12px;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		border-bottom: 1px solid var(--pdr-nt-line-soft);
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		/*
		 * Ten chips and a label never fit a phone, so the row always scrolls, and
		 * a scrollbar is hidden on a touch device - which leaves nothing to say
		 * there is more of it. The right edge fades out instead, which reads as
		 * "this carries on" without costing a row. Browsers without mask support
		 * simply get the hard edge and the chip clipped mid-way, which was the
		 * affordance before.
		 */
		-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
		mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
	}

	.pdr-nt .pdr-nt-section-layers .pdr-nt-layer-filters::-webkit-scrollbar {
		display: none;
	}

	.pdr-nt .pdr-nt-section-layers .pdr-nt-layer-filter {
		flex: 0 0 auto;
		width: 40px;
		height: 40px;
	}

	.pdr-nt .pdr-nt-section-layers .pdr-nt-layer-filters-label {
		flex: 0 0 auto;
	}

	/* The empty note is the sheet's whole content when it shows, so it is centred. */
	.pdr-nt-layers .pdr-no-layers-message,
	.pdr-nt-properties > .pdr-nt-section-layers [data-pdr-layer-empty] {
		margin: 16px 12px;
		text-align: center;
	}

	.pdr-nt.is-views-open .pdr-nt-properties > .pdr-nt-section[data-pdr-section="views"],
	.pdr-nt.is-layers-open .pdr-nt-properties > .pdr-nt-section-layers {
		display: flex;
		flex-direction: column;
	}

	/*
	 * ── Neither edge handle survives here ──
	 *
	 * Both were unlabelled 18px chevrons pinned against the sides of the design,
	 * and both are replaced by named buttons in the corners over it: Switch View
	 * at the top right, Layers at the bottom right. The left handle's other job -
	 * collapsing the tool panel - is the tab bar's down here, and the right
	 * handle's was opening the layers list, which the corner button now does.
	 *
	 * Their going takes a run of corrections with them: the lanes, the layers
	 * sheet and the zoom bar all used to stop short of the right edge to keep
	 * clear of a handle that was drawn above them and swallowed their taps.
	 */
	.pdr-nt-collapse-left,
	.pdr-nt-collapse-right {
		display: none;
	}

	/* The layers button, in the corner zoom does not use. */
	.pdr-nt.has-layers .pdr-nt-canvas-layers {
		display: block;
	}

	.pdr-nt-canvas-layers {
		right: 8px;
		bottom: 8px;
	}

	/*
	 * Icon only, and square with it. The word beside it made the one control
	 * sitting over the customer's artwork the widest thing on that edge, and the
	 * icon is the same layers mark the panel it opens is headed with. The button
	 * is named for a screen reader and on long press by its aria-label.
	 *
	 * 44px, which is the face the zoom buttons take at this width - so its card
	 * comes to the same 50px the zoom bar does and the two bottom corners match.
	 */
	.pdr-nt-layers-btn {
		width: 44px;
		height: 44px;
		padding: 0;
	}

	/*
	 * It shares the bottom edge with the lanes the selection puts there, so it
	 * rises with them rather than sitting under them. Zoom is hidden whenever
	 * anything is selected, so the two are never both claiming this corner.
	 */
	.pdr-nt.has-selection .pdr-nt-canvas-layers {
		bottom: calc(8px + var(--pdr-nt-bar-h, 0px) + 65px);
	}

	/* And it steps aside altogether for a raised sheet, which covers this edge. */
	.pdr-nt.is-sheet-raised .pdr-nt-canvas-layers,
	.pdr-nt.is-layers-open .pdr-nt-canvas-layers {
		display: none;
	}

	/* The corner button that opens the switcher popup, with its label. */
	.pdr-nt-switch-view-btn {
		display: flex;
		gap: 6px;
		width: auto;
		padding: 0 10px;
	}

	.pdr-nt-switch-view-btn .pdr-nt-float-btn-label {
		display: inline;
		font-size: 12px;
		font-weight: 600;
	}

	/*
	 * Centred in the design rather than in the column, once a sheet is covering
	 * the foot of that column: on a short screen the sheet's top edge crossed a
	 * handle and, being drawn above it, cut the bottom off the only way to the
	 * drawer behind it.
	 */
	.pdr-nt.is-sheet-raised .pdr-nt-collapse-right {
		top: calc(50% - (var(--pdr-nt-sheet-h, 0px) / 2));
	}

	/*
	 * The top bar used to scroll inside itself so a row too wide for a phone did
	 * not widen the page. Scrolling meant clipping, and the File and Print menus
	 * drop out of this bar: their dropdowns were cut off at its edge and only a
	 * sliver showed. It wraps instead, which keeps every control reachable and
	 * still never widens the page. It also sits above the main area, which is a
	 * positioned element here and would otherwise paint the canvas over an open
	 * dropdown and swallow the taps meant for it.
	 */
	.pdr-nt-topbar {
		position: relative;
		z-index: 20;
		flex-wrap: wrap;
		height: auto;
		min-height: var(--pdr-nt-topbar-h);
		gap: 8px;
		overflow: visible;
	}

	/* A flexible spacer only makes the row wider than the screen. */
	.pdr-nt-topbar-spacer {
		display: none;
	}

	/* Centred at every width; a phone only wants it narrower. */
	.pdr-nt-dropdown-designs {
		width: min(92vw, 420px);
	}

	.pdr-nt-logo,
	.pdr-nt-menus,
	.pdr-nt-topbar-actions {
		flex: 0 0 auto;
	}



	/*
	 * Stop an over-wide child from stretching the column. 100% rather than 100vw,
	 * which counts the scrollbar and would itself overflow by its width.
	 */
	.pdr-nt,
	.pdr-nt-main,
	.pdr-nt-canvas {
		min-width: 0;
		max-width: 100%;
	}

	/*
	 * One action row. It used to wrap to four, taking a fifth of the screen to
	 * repeat what the Product panel already shows: the product, its options and
	 * the quantity all live there, so only the total and the two actions that
	 * have nowhere else to be are kept.
	 */
	.pdr-nt-bottombar {
		gap: 10px;
		padding: 6px 12px;
		min-height: 0;
	}

	.pdr-nt-bottombar-product,
	.pdr-nt-bottombar-options,
	.pdr-nt-bottombar-qty,
	.pdr-nt-bottombar-divider {
		display: none;
	}

	.pdr-nt-bottombar-spacer {
		display: block;
		flex: 1;
	}

	/*
	 * The price breakdown spans the bar instead of hanging off the total.
	 *
	 * It is a 256px panel anchored to the right edge of a total that is 59px
	 * wide and sits at the left end of the bar, so on a phone it opened 175px
	 * off the left of the screen: three quarters of the breakdown was somewhere
	 * the customer could not see, and the row labels - which are the whole point
	 * of it - were the part that went.
	 *
	 * The bar becomes the box it is measured against, which is what makes left
	 * and right here mean the screen: the total gives up its own positioning so
	 * the nearest positioned ancestor is the bar.
	 */
	.pdr-nt-bottombar {
		position: relative;
	}

	.pdr-nt-total {
		position: static;
	}

	.pdr-nt-breakdown {
		left: 8px;
		right: 8px;
		bottom: calc(100% + 6px);
		width: auto;
		min-width: 0;
		max-width: none;
	}

	/*
	 * The top bar keeps what a panel or the bottom bar cannot offer. The price
	 * and Add to Cart are both in the bottom bar, and the logo is a link home
	 * that costs the row more than it is worth on a phone.
	 */
	/*
	 * Add to Cart is the bottom bar's primary action, so the top bar's copy of it
	 * is a second button for the same thing in the row with least room for one.
	 *
	 * The class, not .pdr-cart-button: that class is only on the button the page
	 * renders when the checkout modal is switched off, so with the modal on - the
	 * default - the duplicate was still drawn. On a 320px screen it was the item
	 * that tipped the bar into wrapping, and the second row it opened cost 40px
	 * of the design at the width with the least of it to give.
	 *
	 * Only where the bottom bar is drawing that button, which the shell says: a
	 * store that has hidden the bottom bar, or hidden Add to Cart outright, keeps
	 * the top bar's - that being the only one left on the page.
	 */
	.pdr-nt-logo,
	.pdr-nt-divider,
	.pdr-nt-price-pill,
	.pdr-nt.has-bottombar-cart .pdr-nt-topbar-actions .pdr-nt-btn-primary {
		display: none;
	}

	.pdr-nt-checkout-body {
		flex-direction: column;
		align-items: stretch;
	}

	/*
	 * The design across the width, but not at the cost of everything under it.
	 *
	 * Stacked, the preview takes the full width and its image grows to match -
	 * 336px of a 760px dialog, over half of what the customer could see. What is
	 * underneath is the part they came to check: the product, the quantity, the
	 * total, and the notice naming any option still missing. The image is capped
	 * so all of that is on screen with it, and it keeps its own aspect ratio
	 * inside the cap, so nothing is stretched or cropped.
	 *
	 * The cap is on the image and not on the block around it. Capping the block
	 * only set its height: the thumbnails inside still took the room they needed
	 * and hung out of the bottom of it, because nothing here clips. On a product
	 * base with four views the grid wraps to two rows, wanted 325px of a 227px
	 * box, and that second row of designs was drawn straight over the product
	 * name underneath. Sized by its contents the block cannot overflow, and a
	 * design on every view makes the dialog scroll rather than overlap.
	 */
	.pdr-nt-checkout-preview {
		width: 100%;
	}

	/*
	 * Including the two-abreast version. That one carries its own 208px width for
	 * the desktop dialog, where the preview is a column beside the details; here
	 * it is a band above them, and 208px of a 350px popup left the thumbnails
	 * huddled in the left half with the rest of the row empty - the design
	 * looking like it had been cut off rather than laid out. Two selectors, to
	 * outrank that width rather than merely follow it.
	 */
	.pdr-nt-checkout-preview.has-many {
		width: 100%;
	}

	.pdr-nt-checkout-preview img {
		max-height: 26vh;
		width: auto;
		object-fit: contain;
	}

	/*
	 * ── The footer stacks ──
	 *
	 * Both actions across the width, one above the other. Side by side they were
	 * sized by their own labels and could not shrink, so "Redirect with Changes
	 * to Product Page" - 324px of button in a 350px dialog, beside Edit Design -
	 * pushed the row 104px past the edge of the popup and the primary action was
	 * cut in half by it.
	 *
	 * The label is also allowed to wrap here. Full width is 310px and that label
	 * still wants 324, so stacking alone would only have made the overflow
	 * smaller; a merchant is free to word it however they like, and a phone has
	 * no width to promise. Two lines of button is the cost of saying the whole
	 * thing.
	 */
	.pdr-nt-modal-foot {
		flex-direction: column;
		padding: 12px 16px;
	}

	.pdr-nt-modal-foot .pdr-nt-btn:first-child,
	.pdr-nt-modal-foot .pdr-nt-btn:last-child {
		flex: none;
		width: 100%;
		min-width: 0;
	}

	.pdr-nt-modal-foot .pdr-nt-btn {
		height: auto;
		min-height: 44px;
		padding: 10px 14px;
	}

	.pdr-nt-modal-foot .pdr-nt-btn > span {
		white-space: normal;
	}

	/*
	 * ── Targets a finger can hit ──
	 *
	 * The studio is drawn for a mouse, which lands on a pixel; a fingertip covers
	 * about 9mm, which is why both platform guidelines put the floor at 44px.
	 * Several of the controls that matter most down here were well under it - the
	 * only way to dismiss the tool sheet was 15px square - so they are grown, and
	 * grown by padding out the hit area rather than by inflating the icon, which
	 * would coarsen a layout that reads well as it is.
	 */
	.pdr-nt-toolpanel-head {
		height: 52px;
	}

	.pdr-nt-toolpanel-head .pdr-nt-icon-btn,
	.pdr-nt-popup-close {
		width: 44px;
		height: 44px;
		margin-right: -10px;
	}

	.pdr-nt-zoom-btn {
		width: 44px;
		height: 44px;
	}

	.pdr-nt-objectbar-btn {
		min-width: 40px;
		height: 40px;
	}

	/*
	 * The text bar grows upwards only. Widening its buttons too tipped it from
	 * two wrapped rows to three - 132px of toolbar over a 217px product - and the
	 * row it added cost the design more than the extra 10px of width won back for
	 * the thumb. The height is where a finger misses, so the height is what grows.
	 */
	.pdr-nt-contextbar-btn {
		height: 40px;
	}

	/*
	 * The drawer handles. 18px wide is a target a thumb misses more often than it
	 * finds, and the layers handle is the only way to that list on a phone. The
	 * button keeps its 18px face - a wider tongue against the edge of the design
	 * would read as a panel rather than a handle - and claims the rest as a
	 * transparent margin around it, so the tap lands from three times as far out.
	 */
	.pdr-nt-collapse::after {
		content: '';
		position: absolute;
		top: -8px;
		bottom: -8px;
		left: -14px;
		right: -14px;
	}

	/*
	 * ── The edge drawers dismiss like sheets ──
	 *
	 * Views and Layers open as panels over the design with nothing behind them to
	 * say the rest of the page is still there and nothing to press to get back to
	 * it: the same 18px handle both opened and closed them. A scrim gives them an
	 * outside to tap and dims what they are covering, which is what tells a
	 * customer this is a layer over their design rather than a new screen.
	 *
	 * The layers sheet is not dimmed behind, though. The design keeps its room
	 * above that sheet the way it does above a tool panel, and a customer reading
	 * a list of their layers is reading it against the design those layers are
	 * on - dimming the one to announce the other would be the wrong trade. The
	 * scrim is still there over it, invisible, so a tap on the design closes the
	 * sheet the way a tap outside any sheet should.
	 */

	.pdr-nt-drawer-scrim {
		position: absolute;
		inset: 0 0 var(--pdr-nt-tabbar-h) 0;
		z-index: 11;
		border: none;
		padding: 0;
		background: transparent;
	}

	.pdr-nt.is-views-open .pdr-nt-drawer-scrim,
	.pdr-nt.is-layers-open .pdr-nt-drawer-scrim {
		display: block;
	}

	/*
	 * ── The lanes take turns ──
	 *
	 * Zoom, the contextual bar and the object bar are three lanes across the foot
	 * of the design, and on a 640px phone they came to 234px of a 424px column -
	 * the product was left 171px to be seen in while its own toolbars had more
	 * room than it did.
	 *
	 * Zoom is the one of the three that is not about the selection: it is a view
	 * control, reached between edits rather than during one. So it steps out while
	 * something is selected and comes back the moment the customer taps the design
	 * to deselect, which gives the product a third of that room back. Nothing is
	 * taken away - the control is a tap from returning, and pinch and the wheel
	 * never went anywhere.
	 */
	.pdr-nt.has-selection .pdr-nt-zoombar,
	.pdr-nt.is-sheet-raised .pdr-nt-zoombar {
		display: none;
	}

	/*
	 * The same bargain while a tool sheet is up. Zoom appears when the customer
	 * is looking at their design and steps aside while they are working on it -
	 * and a sheet is the clearest statement there is that they are working. It
	 * was costing the product 46px at exactly the moment the sheet was already
	 * asking for 277px of the same column.
	 */

	/*
	 * ── The bars are not dragged on a phone ──
	 *
	 * Each floating bar carries a grip to drag it by, which is a mouse
	 * affordance, and for a while it was not drawn at all down here: the bars
	 * rest in lanes, and on the object bar the grip took a whole wrapped row of
	 * its own above the buttons while on the text bar it took 20px of the width
	 * that decides whether that bar fits on one row or two.
	 *
	 * The gesture is offered again - a bar resting over the part of the design
	 * being worked on is exactly the case dragging it is for, and it is no less
	 * true on a phone. The cost the note above describes is what the shape here
	 * answers: a narrow handle down the leading edge of the lane rather than a
	 * row above it, so it takes width from the padding and no height at all.
	 */
	.pdr-nt-objectbar-grip,
	.pdr-nt-contextbar-grip {
		display: flex;
		flex-shrink: 0;
		width: 18px;
		height: auto;
		align-self: stretch;
		border-radius: 6px 0 0 6px;
	}

	/* The bar is a row down here, so its grip is drawn lying on its side. */
	.pdr-nt-objectbar-grip .pdr-nt-icon,
	.pdr-nt-contextbar-grip .pdr-nt-icon {
		transform: rotate(90deg);
	}

	/* A bar the customer has moved is theirs, not the lane's. */
	.pdr-nt-objectbar.is-moved,
	.pdr-nt-contextbar.is-moved {
		right: auto;
		width: max-content;
		max-width: calc(100% - 12px);
	}

	/*
	 * The tab bar's own buttons, sized to the shorter bar. 46px keeps them clear
	 * of the 44px floor a fingertip needs, so the 6px the bar gives up comes out
	 * of the padding around them and not out of the target.
	 */
	.pdr-nt-rail-btn {
		height: 46px;
		padding: 5px 2px;
	}

	/*
	 * ── Rows a phone cannot spare ──
	 *
	 * The configurable footer line is a slim strip on a desktop and a whole row
	 * of a phone, sat under the primary action where it is the last thing between
	 * Add to Cart and the bottom of the screen. The design gets that height. It is
	 * still rendered for every other width, and a merchant who wants it gone
	 * everywhere still has the Studio Layout toggle.
	 */
	.pdr-nt-footnote {
		display: none;
	}

}

/*
 * ── The narrowest phones ──
 *
 * 320px, which is an iPhone 4 or an SE held in portrait. The bottom bar's three
 * items measured 343px there - the total, Preview with its word, and Add to
 * Cart - so 23px of the primary action was off the right of the screen and the
 * button read "Add to Car". Nothing in the row could give: both buttons are
 * nowrap and sized by their own labels.
 *
 * Preview gives up its word, which its icon already says and which the modal it
 * opens says again in its title. Add to Cart keeps its label and gives up
 * padding, and is allowed to shrink at all - a flex item's min-width is its
 * content's width until it is told otherwise - with room to ellipsise on a
 * currency or a cart label longer than this one.
 */
@media (max-width: 380px) {
	.pdr-nt-bottombar {
		gap: 8px;
		padding: 10px;
	}

	.pdr-nt-bottombar [data-pdr-open-preview] > span {
		display: none;
	}

	.pdr-nt-bottombar [data-pdr-open-preview] {
		flex-shrink: 0;
		padding: 0 11px;
	}

	.pdr-nt-bottombar .pdr-nt-btn-lg {
		min-width: 0;
		padding: 0 12px;
	}

	.pdr-nt-bottombar .pdr-nt-btn-lg > span {
		overflow: hidden;
		text-overflow: ellipsis;
	}

	/* The figure can be read at this size and the row cannot spare the width. */
	.pdr-nt-total-value {
		font-size: 17px;
	}

	.pdr-nt-total {
		flex-shrink: 0;
	}

	/*
	 * A layer row runs out of width before anything else does. It carries an eye,
	 * a thumbnail, the name and three actions, and at 320px that left the name
	 * 64px - four characters of it, so every text layer in the list read as
	 * "Happy…" and the list could not be used to tell them apart.
	 *
	 * The thumbnail goes. It is the least of the three things that identify a
	 * layer here: a text layer's thumbnail is a glyph of the letter T, which the
	 * row's own type line says in words underneath, while the name is the only
	 * part that says which layer this actually is. Dropping it hands the name
	 * 54px, most of what it was missing.
	 */
	.pdr-nt-layers .pdr-layer-image {
		display: none;
	}

	.pdr-nt .pdr-nt-section-layers .pdr-layer-wrapper {
		gap: 6px;
		padding: 8px 10px;
	}
}

/*
 * ── Phones held sideways ──
 *
 * The app layout above now reaches these, which is the point: they were getting
 * the desktop one. But it was drawn for a screen with height to spend and this
 * has none - 390px on an iPhone 14, 412px on a Pixel - where the top bar, the
 * tab bar and the bottom bar alone came to 191px, leaving under half the screen
 * for the product before a single toolbar opened over it.
 *
 * What such a screen does have is width. So the chrome is flattened - every bar
 * gives up the height it can - and the tool sheet stops being a sheet: it takes
 * the left third as a column beside the design, where width is what it costs.
 * The design keeps the rest, in one piece, which is the whole point of the
 * clearance the studio measures.
 */
@media (max-width: 1024px) and (max-height: 540px) and (min-width: 481px) {
	.pdr-nt {
		--pdr-nt-topbar-h: 48px;
		--pdr-nt-bottombar-h: 52px;
		--pdr-nt-tabbar-h: 52px;

		/*
		 * Read by syncSheetOffset() in studio.js. The tool panel and the
		 * layers list are columns beside the design here rather than sheets under
		 * it, so the lanes the selection puts along the foot of the design do not
		 * have to rise over either: measuring a full-height column as a sheet
		 * would have lifted them clear off the top of the screen.
		 */
		--pdr-nt-sheet-side: 1;

		/*
		 * And with no grip drawn here, nothing has to clear one. The layers
		 * close button is pinned to the top of its drawer and reads this to sit
		 * below the grip in the sheet layout; left at 22px it would hang that
		 * far down a drawer with no grip above it.
		 */
		--pdr-nt-grip-h: 0px;
	}

	/*
	 * And with both of them full-height columns against an edge, there is no
	 * height for a grip to drag: the tool panel runs from the top bar to the tab
	 * bar and the layers drawer from top to bottom. The phone block above turns
	 * the grip on for the sheet layout, so this turns it back off for this one.
	 */
	.pdr-nt-sheet-grip {
		display: none;
	}

	.pdr-nt-topbar {
		min-height: 48px;
		padding: 0 10px;
	}

	.pdr-nt-bottombar {
		min-height: 52px;
		padding: 7px 12px;
	}

	.pdr-nt-rail {
		height: 52px;
		padding: 2px 8px;
	}

	.pdr-nt-rail-btn {
		height: 46px;
	}

	/*
	 * The tool panel as a column rather than a sheet. Across the foot of a screen
	 * this short it would have left the design a strip; down the side it costs
	 * width, which is the one thing here there is enough of.
	 *
	 * It sits above the tab bar rather than beside it, so the tabs stay reachable
	 * with the panel open and the tab that opened it stays visible underneath.
	 */
	.pdr-nt-toolpanel {
		top: 0;
		right: auto;
		bottom: var(--pdr-nt-tabbar-h);
		left: 0;
		width: min(46%, 320px);
		max-height: none;
		border-top: none;
		border-right: 1px solid var(--pdr-nt-line);
		border-radius: 0;
		box-shadow: 8px 0 24px rgba(0, 0, 0, .14);
	}

	/*
	 * ── The bars go beside the design, not under it ──
	 *
	 * In portrait the selected object's bars are lanes across the foot of the
	 * design, and the design is given the height they are not using. That trade
	 * is the wrong way round here: the column is 232px tall and the two lanes
	 * wanted 108px of it, which left a drawstring bag 96px wide and 111px tall -
	 * in a column 844px across. The product was being squeezed by height while
	 * three quarters of the width sat empty either side of it.
	 *
	 * So the bars dock to the right instead, into the width there is plenty of,
	 * and stop taking the height there is none of. They are drawn over the column
	 * rather than shrinking it - the design keeps its size at every width - and
	 * on a screen this wide the product is centred with room to either side of
	 * it, so the corner they take is mostly empty grey.
	 */
	.pdr-nt {
		--pdr-nt-bars-w: min(46%, 420px);
	}

	.pdr-nt-contextbar,
	.pdr-nt-objectbar {
		left: auto;
		right: 8px;
		width: max-content;
		max-width: calc(var(--pdr-nt-bars-w) - 16px);
		transform: none;
	}

	.pdr-nt-contextbar {
		bottom: calc(58px + var(--pdr-nt-zoom-lane, 0px));
	}

	.pdr-nt-objectbar {
		bottom: calc(6px + var(--pdr-nt-zoom-lane, 0px));
	}

	.pdr-nt-zoombar {
		bottom: 6px;
	}

	/*
	 * The layers list stays a column off the right edge here rather than becoming
	 * a sheet: a screen 232px tall has no bottom half to give one. It shares that
	 * edge with the docked bars, and the drawer is drawn above them.
	 */
	.pdr-nt-properties > .pdr-nt-section-layers {
		top: 0;
		bottom: 0;
		left: auto;
		width: min(72%, 380px);
		max-height: none;
		border-top: none;
		border-left: 1px solid var(--pdr-nt-line);
		border-radius: 0;
		box-shadow: -8px 0 24px rgba(0, 0, 0, .12);
	}

	/* Its head goes back to being the section's own collapse toggle. */
	.pdr-nt-properties > .pdr-nt-section-layers .pdr-nt-section-head {
		height: 44px;
	}

	/* Raised or not, the sheet is not over the right handle down here. */
	.pdr-nt.is-sheet-raised .pdr-nt-collapse-right {
		top: 50%;
	}

	/*
	 * Both drawers stop short of the tab bar rather than reaching the foot of the
	 * screen, and the view switcher popup takes what height there is.
	 */
	.pdr-nt-properties > .pdr-nt-section[data-pdr-section="views"] {
		max-height: calc(100vh - 24px);
	}
}

@media (prefers-reduced-motion: reduce) {
	.pdr-nt * {
		transition: none !important;
	}
}

/* ── Text panel ──────────────────────────────────────────── */

.pdr-nt-rule {
	height: 1px;
	margin: 0;
	border: 0;
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-hint {
	margin: 0;
	font-size: 11px;
	line-height: 1.45;
	color: var(--pdr-nt-muted-2);
}

/*
 * A hint that states a rule the customer can break: the formats and sizes an
 * upload has to be, and whatever the merchant set as the text field's own
 * description. Muted grey, these read as decoration and were skipped, and the
 * first the customer heard of a limit was the error alert after picking a file.
 * Given the danger colour and a little weight they read as the conditions they
 * are, before the file is picked rather than after.
 */
/*
 * The constraints a panel states before anything has gone wrong: how much of
 * the character allowance is left, which formats an upload may be in. These
 * were drawn in the palette's error red and then murmured in grey, on the
 * grounds that a panel should not open looking as though it were already
 * complaining about a field nobody had filled in yet.
 *
 * They are red again, by request: the rules a customer has to meet before an
 * upload is accepted are worth reading before they choose a file rather than
 * after it is rejected.
 *
 * Note what this costs, if it is ever revisited. Red no longer separates "here
 * is the rule" from "you have broken it" - the engine's own validation message
 * is the same colour - and on a phone this line sits directly under the field
 * with the sheet's whole width to itself, which makes it the loudest thing in
 * the panel.
 */
.pdr-nt-hint-rule {
	font-weight: 600;
	color: var(--pdr-nt-danger);
}

/*
 * A search that matched nothing. This is an answer to something the customer
 * just typed, so it is stated rather than murmured: the panel would otherwise
 * simply empty, which reads as a panel that has broken rather than as a search
 * with no results.
 */
.pdr-nt-hint-empty {
	padding: 9px 11px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	font-weight: 500;
	color: var(--pdr-nt-ink-2);
}

/* The term itself, quoted back so it is clear what found nothing. */
.pdr-nt-hint-empty .pdr-nt-hint-term {
	font-weight: 700;
	color: var(--pdr-nt-ink);
}

.pdr-nt-price-tag {
	align-self: flex-start;
	padding: 3px 10px;
	border-radius: 999px;
	background: var(--pdr-nt-success-soft);
	border: 1px solid var(--pdr-nt-success-line);
	color: var(--pdr-nt-price);
	font-size: 11px;
	font-weight: 700;
}

.pdr-nt-price-tag .amount,
.pdr-nt-price-tag bdi {
	color: inherit;
}

/* Say it, size it, add it: the three steps read as one block. */
.pdr-nt-add-text-group {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

/*
 * The three size options read as the type scale they produce, so the choice can
 * be made before adding rather than discovered after it.
 */
.pdr-nt-text-sizes .pdr-nt-segment[data-pdr-text-size="title"] {
	font-size: 14px;
	font-weight: 700;
}

.pdr-nt-text-sizes .pdr-nt-segment[data-pdr-text-size="line"] {
	font-size: 12px;
	font-weight: 600;
}

.pdr-nt-text-sizes .pdr-nt-segment[data-pdr-text-size="small"] {
	font-size: 11px;
	font-weight: 500;
}

/*
 * Adding with nothing typed would put an empty box on the product, so the
 * action stays unavailable and says so until there is something to add.
 */
.pdr-nt-btn[disabled],
.pdr-nt-btn[disabled]:hover {
	background: var(--pdr-nt-line-soft);
	border-color: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-muted);
	cursor: not-allowed;
}

.pdr-nt-textarea {
	width: 100%;
	min-height: 74px;
	padding: 10px 12px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-ink);
	font-family: inherit;
	font-size: 13px;
	line-height: 1.5;
	resize: vertical;
	outline: none;
}

.pdr-nt-textarea:focus {
	border-color: var(--pdr-nt-accent);
	background: var(--pdr-nt-surface);
}

.pdr-nt-label-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
}

.pdr-nt-label-value {
	font-size: 12px;
	font-weight: 500;
	color: var(--pdr-nt-ink-2);
}

.pdr-nt-size-row {
	display: flex;
	align-items: center;
	gap: 5px;
}

.pdr-nt-size-row .pdr-nt-input {
	flex: 1;
	font-weight: 600;
}

.pdr-nt-square-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	flex-shrink: 0;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
}

.pdr-nt-square-btn:hover {
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-color-row {
	display: flex;
	align-items: center;
	gap: 8px;
	height: 36px;
	padding: 0 10px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
}

.pdr-nt-color-row input[type="color"] {
	width: 22px;
	height: 22px;
	padding: 0;
	flex-shrink: 0;
	border: 1px solid rgba(0, 0, 0, .12);
	border-radius: 5px;
	background: none;
	cursor: pointer;
}

.pdr-nt-color-value {
	font-size: 13px;
	font-weight: 500;
	text-transform: uppercase;
}

.pdr-nt-btn-row {
	display: flex;
	gap: 5px;
}

.pdr-nt-toggle-btn {
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	height: 36px;
	border: 1.5px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-ink-2);
	cursor: pointer;
}

.pdr-nt-toggle-btn:hover {
	background: var(--pdr-nt-surface-2);
}

.pdr-nt-toggle-btn.active {
	border-color: var(--pdr-nt-accent);
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

.pdr-nt-range {
	width: 100%;
	height: 4px;
	margin: 8px 0;
	border-radius: 4px;
	background: var(--pdr-nt-line);
	appearance: none;
	outline: none;
	cursor: pointer;
}

.pdr-nt-range::-webkit-slider-thumb {
	appearance: none;
	width: 14px;
	height: 14px;
	border: 2px solid var(--pdr-nt-accent);
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 1px 4px rgba(0, 0, 0, .2);
	cursor: pointer;
}

.pdr-nt-range::-moz-range-thumb {
	width: 14px;
	height: 14px;
	border: 2px solid var(--pdr-nt-accent);
	border-radius: 50%;
	background: #fff;
	cursor: pointer;
}

.pdr-nt-disclosure {
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	overflow: hidden;
}

.pdr-nt-disclosure-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	height: 36px;
	padding: 0 12px;
	border: none;
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-ink-2);
	font-size: 13px;
	font-weight: 500;
	cursor: pointer;
}

.pdr-nt-disclosure-head .pdr-nt-icon {
	transition: transform .15s ease;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-disclosure-head[aria-expanded="true"] .pdr-nt-icon {
	transform: rotate(180deg);
}

.pdr-nt-disclosure-body {
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding: 14px 12px;
	border-top: 1px solid var(--pdr-nt-line);
}

/* ── Product panel ───────────────────────────────────────── */

/* The design spaces the product panel's sections 16px apart. */
.pdr-nt-product-panel.pdr-nt-stack {
	gap: 16px;
}

/*
 * Change Product in the design: a 40px primary button with no border and 7px
 * between the package icon and the label.
 */
.pdr-nt-product-panel > .pdr-nt-btn-block {
	height: 40px;
	gap: 7px;
	border: none;
}

/* Colour heading: the attribute name, the chosen colour, and the option count. */
.pdr-nt-attribute-product_color .pdr-nt-colour-heading {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	width: 100%;
}

/*
 * A count stated beside a section title, pushed to the far end of the head so
 * it reads as a note about the section rather than part of its name. The same
 * shape the colour attribute heading uses for the same job.
 */
.pdr-nt-section-count {
	margin-left: auto;
	font-size: 10px;
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
	white-space: nowrap;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-colour-count {
	font-size: 10px;
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-product-card {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	padding: 12px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: 10px;
	background: #f8f9fb;
}

.pdr-nt-product-card-main {
	flex: 1;
	min-width: 0;
}

.pdr-nt-product-card-name {
	display: block;
	font-size: 14px;
	font-weight: 700;
	color: var(--pdr-nt-ink);
}

.pdr-nt-product-card-desc {
	margin-top: 3px;
	font-size: 11px;
	line-height: 1.5;
	color: var(--pdr-nt-muted-2);
	max-height: 84px;
	overflow-y: auto;
}

.pdr-nt-product-card-desc p {
	margin: 0 0 6px;
}

.pdr-nt-product-card-price {
	flex-shrink: 0;
	padding: 5px 8px;
	text-align: center;
	border: 1px solid var(--pdr-nt-success-line);
	border-radius: var(--pdr-nt-radius);
	background: #ecfdf5;
}

.pdr-nt-product-card-price-label {
	display: block;
	font-size: 8px;
	letter-spacing: .4px;
	text-transform: uppercase;
	color: var(--pdr-nt-price);
}

.pdr-nt-product-card-price-value {
	display: block;
	font-size: 14px;
	font-weight: 800;
	color: var(--pdr-nt-price);
}

.pdr-nt-product-card-price-value .amount,
.pdr-nt-product-card-price-value bdi {
	color: inherit;
}

.pdr-nt-product-form.ui.form {
	display: flex;
	flex-direction: column;
	gap: 16px;
	font-family: inherit;
	font-size: 13px;
}

.pdr-nt-search {
	display: flex;
	align-items: center;
	gap: 7px;
	height: 34px;
	padding: 0 10px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-search input,
.pdr-nt-search input[type="search"] {
	flex: 1;
	min-width: 0;
	height: auto;
	padding: 0;
	border: none !important;
	border-radius: 0;
	box-shadow: none !important;
	background: transparent !important;
	outline: none;
	font-family: inherit;
	font-size: 12px;
	color: var(--pdr-nt-ink);
	-webkit-appearance: none;
	appearance: none;
}

.pdr-nt-search input::-webkit-search-decoration,
.pdr-nt-search input::-webkit-search-cancel-button {
	-webkit-appearance: none;
}

/* Attribute markup comes from the engine's renderer; this restyles it. */
.pdr-nt-attribute .field {
	margin: 0 0 10px;
}

.pdr-nt-attribute .field:last-child {
	margin-bottom: 0;
}

/*
 * Semantic's own .ui.form .field > label is three classes and a type, which
 * outranks a two class selector, so every attribute label kept its 12px bold
 * black and the panel showed two label styles at once: the studio's small caps
 * on the Quantity field, Semantic's on the six attributes above it.
 *
 * The .ui.form here is the ancestor form. The selector this replaces looked for
 * one inside .pdr-nt-attribute, which is the wrong way round - the form wraps
 * the attributes - so it never matched anything and never raised the rank it
 * was written to raise.
 */
.pdr-nt-attribute > .field > label,
.ui.form .pdr-nt-attribute .field > label {
	display: block;
	margin-bottom: 6px;
	font-family: inherit;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: .8px;
	text-transform: uppercase;
	color: var(--pdr-nt-muted-2);
}

/*
 * The asterisk on an option that has to be answered.
 *
 * Against the name, not at the end of the line. Where the merchant prices an
 * option the label carries a price tag after the name, and an asterisk trailing
 * that reads as "$20.00*" - which in a shop is the mark of a price with
 * conditions on it, not of a question that has to be answered. So it goes
 * before the tag where there is one, and at the end of the label where there
 * is not.
 *
 * Drawn from the label rather than added to it: the colour heading is rebuilt
 * from script on every price recalculation, so an element inside that label
 * would not survive the next one. The fields carry aria-required, which is
 * where a screen reader looks, so this is left out of the accessibility tree.
 */
/*
 * The label becomes a row so the marker can be placed within it, and the price
 * tag is sent after the marker. The tag's own ::before is not available for
 * this - Semantic draws the tag's pointed end with it.
 *
 * The form is named in the selector to outrank Semantic's own
 * .ui.form .field > label, which sets display: block at the same weight as a
 * three class rule and wins on load order. Without it the label never became a
 * row, order did nothing, and the marker fell to the end of the line - which is
 * the arrangement this replaces.
 */
.ui.form .pdr-nt-attribute.is-required > .field > label,
.pdr-nt-attribute.is-required > .field > label {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 3px;
}

.pdr-nt-attribute.is-required > .field > label > .label,
.pdr-nt-attribute.is-required > .field > label > .tag {
	order: 1;
}

.pdr-nt-attribute.is-required > .field > label::after {
	content: '*';
	color: var(--pdr-nt-danger);
	font-weight: 700;
}

/*
 * The colour attribute's label holds a heading of its own - the name, the
 * chosen colour, and the option count pushed to the far right - so the marker
 * goes inside that heading against the name. Left on the label it would land
 * after the count, at the other end of the row from the thing it marks.
 */
.pdr-nt-attribute-product_color.is-required > .field > label::after {
	display: none;
}

.pdr-nt-attribute-product_color.is-required > .field > label .pdr-nt-colour-heading {
	flex: 1;
	min-width: 0;
}

.pdr-nt-attribute-product_color.is-required .pdr-nt-colour-heading > span:first-child::after {
	content: '*';
	margin-left: 3px;
	color: var(--pdr-nt-danger);
	font-weight: 700;
}

/*
 * The attribute a chip in the bottom bar has just sent the customer to. A ring
 * for a moment and then gone: it is a "here" marker, not a state the field is
 * in, so it fades rather than needing to be dismissed.
 */
.pdr-nt-attribute.is-target {
	position: relative;
	border-radius: var(--pdr-nt-radius);
	box-shadow: 0 0 0 2px var(--pdr-nt-accent), 0 0 0 6px var(--pdr-nt-accent-soft);
	transition: box-shadow .3s ease;
}

/* Colour swatches into the mockup's grid. */
.pdr-nt-attribute-product_color > .field {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 7px;
	align-items: center;
}

/* The heading and the clear link span the full grid, the swatches fill the cells. */
.pdr-nt-attribute-product_color > .field > label,
.pdr-nt-attribute-product_color > .field > .pdr-clear-bg {
	grid-column: 1 / -1;
	margin-bottom: 0;
}

.pdr-nt-attribute-product_color > .field > span {
	display: flex;
	justify-content: center;
}

/* ── Colour families ─────────────────────────────────────── */

/*
 * Grouped swatches. The studio wraps each family in its own row so the heading
 * spans the field and the swatches keep the same six column rhythm they have
 * when the colour set is small enough to stay flat.
 */
.pdr-nt-colour-group {
	grid-column: 1 / -1;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.pdr-nt-colour-group + .pdr-nt-colour-group {
	margin-top: 10px;
}

.pdr-nt-colour-family {
	font-size: 9px;
	font-weight: 600;
	letter-spacing: .6px;
	text-transform: uppercase;
	color: #b0b6be;
}

.pdr-nt-colour-swatches {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 7px;
	align-items: center;
}

.pdr-nt-colour-swatches > span {
	display: flex;
	justify-content: center;
}

.pdr-nt-attribute-product_color span {
	display: inline-flex;
}

.pdr-nt-attribute .ui.label.color-preview,
.pdr-nt-attribute a.color-preview {
	width: 28px !important;
	height: 28px !important;
	min-width: 28px;
	min-height: 28px;
	margin: 0 !important;
	padding: 0 !important;
	border-width: 2px !important;
	border-style: solid !important;
	border-radius: 50% !important;
	box-shadow: 0 0 0 1px rgba(0, 0, 0, .08) inset;
	cursor: pointer;
	transition: transform .12s ease, box-shadow .12s ease;
}

.pdr-nt-attribute a.color-preview:hover {
	transform: scale(1.08);
}

/*
 * The colour swatches fill their grid cell instead of the fixed 28px the other
 * attributes use. This has to sit after the base rule above: both selectors
 * carry four classes, so source order is what decides it.
 */
.pdr-nt-attribute-product_color .ui.label.color-preview,
.pdr-nt-attribute-product_color a.color-preview {
	width: 26px !important;
	height: 26px !important;
	min-width: 26px;
	min-height: 26px;
	/*
	 * The renderer writes border-color: <the colour> inline, which makes a pale
	 * swatch vanish against the panel. A hairline over the top reads as an edge
	 * on every colour, which is what the mockup does.
	 */
	border: 1px solid rgba(0, 0, 0, .08) !important;
	box-shadow: none;
}

/* Matches the specificity of the base swatch rule above, which uses four classes. */
.pdr-nt-attribute .ui.label.color-preview.is-selected,
.pdr-nt-attribute .ui.label.color-preview.active,
.pdr-nt-attribute .ui.label.color-preview.selected,
.pdr-nt-attribute a.color-preview.is-selected {
	box-shadow: 0 0 0 2px var(--pdr-nt-surface), 0 0 0 3.5px var(--pdr-nt-accent);
}

.pdr-nt-attribute .ui.hidden.vertical.divider {
	display: none !important;
}

.pdr-nt-attribute .pdr-clear-bg {
	flex: 0 0 100%;
	font-size: 11px;
	font-weight: 500;
	color: var(--pdr-nt-accent);
	text-decoration: none;
}

/*
 * Radio and checkbox attributes become the mockup's option chips: a row of
 * rounded squares that wrap, each centring its label with the option's price
 * underneath. The renderer wraps every option in its own field, so the
 * attribute's own field is the row and those inner fields are the cells.
 */
.pdr-nt-attribute-radio > .field,
.pdr-nt-attribute-checkbox > .field {
	display: flex;
	flex-wrap: wrap;
	gap: 5px;
}

/* The attribute name and the hidden price carrier span the whole row. */
.pdr-nt-attribute-radio > .field > label,
.pdr-nt-attribute-checkbox > .field > label,
.pdr-nt-attribute-radio > .field > input[type="hidden"],
.pdr-nt-attribute-checkbox > .field > input[type="hidden"] {
	flex: 0 0 100%;
	margin-bottom: 0;
}

.pdr-nt-attribute-radio > .field > .field,
.pdr-nt-attribute-checkbox > .field > .field {
	flex: 1 1 auto;
	min-width: 34px;
	margin: 0;
}

.pdr-nt-attribute .ui.pdr-radio-field.checkbox,
.pdr-nt-attribute .ui.pdr-checkbox-field.checkbox {
	display: flex;
	width: 100%;
	min-height: 0;
	margin: 0;
	vertical-align: top;
}

.pdr-nt-attribute .ui.pdr-radio-field.checkbox > label,
.pdr-nt-attribute .ui.pdr-checkbox-field.checkbox > label {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 2px;
	width: 100%;
	min-width: 34px;
	height: 32px;
	padding: 0 8px;
	margin: 0;
	border: 1.5px solid var(--pdr-nt-line);
	border-radius: 7px;
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-ink-2);
	font-family: inherit;
	font-size: 11px;
	font-weight: 500;
	text-transform: none;
	letter-spacing: 0;
	white-space: nowrap;
	cursor: pointer;
}

/*
 * An attribute that prices its options needs the taller chip, so the price has
 * a line of its own under the label. Set from the studio script, because which
 * options carry a price is the merchant's configuration, not something the
 * markup declares.
 */
.pdr-nt-attribute.is-priced .ui.pdr-radio-field.checkbox > label,
.pdr-nt-attribute.is-priced .ui.pdr-checkbox-field.checkbox > label {
	height: 44px;
}

.pdr-nt-attribute .ui.pdr-radio-field.checkbox > label::before,
.pdr-nt-attribute .ui.pdr-radio-field.checkbox > label::after,
.pdr-nt-attribute .ui.pdr-checkbox-field.checkbox > label::before,
.pdr-nt-attribute .ui.pdr-checkbox-field.checkbox > label::after {
	display: none !important;
}

.pdr-nt-attribute .ui.checkbox input:checked ~ label {
	border-color: var(--pdr-nt-accent);
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent-hover);
	font-weight: 600;
}

.pdr-nt-attribute .ui.checkbox input:focus-visible ~ label {
	outline: 2px solid var(--pdr-nt-accent);
	outline-offset: 2px;
}

/*
 * What an option adds to the price, beside its name and on each of its chips.
 * Green like every other price in the studio - it was the one figure on the
 * page stated in the muted grey the panel uses for hints, so the one number in
 * the Product panel a customer is scanning for read as an aside.
 */
.pdr-nt-attribute .ui.green.tag.label {
	margin: 0;
	padding: 0;
	background: none !important;
	border: none !important;
	color: var(--pdr-nt-price) !important;
	font-size: 8px;
	font-weight: 600;
	line-height: 1;
	border-radius: 0;
}

/*
 * On a chosen chip the ground is the accent's own soft blue. The price keeps
 * its green there rather than turning blue with the chip: it is the same fact
 * whether the option is chosen or not.
 */
.pdr-nt-attribute .ui.checkbox input:checked ~ label .ui.green.tag.label {
	color: var(--pdr-nt-price) !important;
}

.pdr-nt-attribute .ui.green.tag.label::before,
.pdr-nt-attribute .ui.green.tag.label::after {
	display: none;
}

/*
 * Long option labels do not fit a chip, so the attribute becomes the mockup's
 * stacked row list instead. The studio decides this from the labels themselves.
 */
.pdr-nt-attribute.is-rows > .field {
	flex-direction: column;
	gap: 5px;
}

.pdr-nt-attribute.is-rows > .field > .field {
	flex: 0 0 auto;
	width: 100%;
}

.pdr-nt-attribute.is-rows .ui.pdr-radio-field.checkbox > label,
.pdr-nt-attribute.is-rows .ui.pdr-checkbox-field.checkbox > label {
	flex-direction: row;
	align-items: center;
	justify-content: space-between;
	height: auto;
	padding: 8px 10px;
	border-width: 1px;
	font-size: 12px;
	white-space: normal;
	text-align: left;
}

.pdr-nt-attribute.is-rows .ui.checkbox input:checked ~ label {
	border-color: #bfdbfe;
	color: #1e40af;
}

/* Select attributes take the studio input styling. */
.pdr-nt-attribute .ui.selection.dropdown,
.pdr-nt-attribute select {
	min-height: 36px;
	padding: 0 32px 0 12px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	font-family: inherit;
	font-size: 13px;
	font-weight: 500;
	color: var(--pdr-nt-ink);
	line-height: 34px;
}

.pdr-nt-attribute .ui.selection.dropdown:hover {
	border-color: #d1d5db;
}

.pdr-nt-attribute input[type="text"],
.pdr-nt-attribute input[type="number"] {
	height: 36px;
	border: 1px solid var(--pdr-nt-line) !important;
	border-radius: var(--pdr-nt-radius) !important;
	background: var(--pdr-nt-surface-2) !important;
	font-family: inherit;
	font-size: 13px;
}

/*
 * One row: the name on the left, the stepper on the right, which is how the
 * bottom bar lays the same control out.
 *
 * The stepper is 112px wide and never fills the column the way the attribute
 * fields above it do, so as a stacked field it took a line of its own for a
 * label and left 107px of the next line empty - 55px of panel height to ask
 * for a number. Beside its own label it is 34px and the dead space is where
 * the label went. The stepper's own metrics are untouched: it has to stay the
 * same control as the one in the bar.
 */
.pdr-nt-quantity-field {
	flex-direction: row;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
}

/*
 * Compact in the panel. The stepper is sized for the bottom bar, where it is
 * one of five things across the width of the window and 32px buttons are the
 * right target; in a 219px column it is the least important field on the panel
 * and 112px of it - two thirds buttons - is more room than asking for a number
 * deserves. 90px here, still comfortably tappable, and the field it sits in
 * keeps the same height as the attribute controls above it.
 *
 * Only the panel's: the bar's stepper is the one a customer uses at the moment
 * of buying and it keeps its size.
 */
.pdr-nt-quantity-field .pdr-nt-stepper-group {
	height: 30px;
}

.pdr-nt-quantity-field .pdr-nt-stepper-btn {
	flex: 0 0 26px;
	width: 26px;
}

.pdr-nt-quantity-field .pdr-nt-stepper-value,
.pdr-nt .ui.form .pdr-nt-quantity-field input.pdr-nt-stepper-value {
	flex: 0 0 38px;
	width: 38px;
	font-size: 12px;
}

/* Semantic's error message only shows when the engine adds .visible. */
.pdr-nt-product-form .ui.error.message {
	font-family: inherit;
	font-size: 12px;
}

/* ── Font picker ─────────────────────────────────────────── */

.pdr-nt-fontpicker.ui.selection.dropdown {
	min-height: 36px;
	padding: 9px 32px 9px 12px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	font-family: inherit;
	font-size: 13px;
	font-weight: 500;
	color: var(--pdr-nt-ink);
}

.pdr-nt-fontpicker.ui.selection.dropdown .menu {
	border-color: var(--pdr-nt-line);
	border-radius: 0 0 var(--pdr-nt-radius) var(--pdr-nt-radius);
}

.pdr-nt-fontpicker.ui.selection.dropdown .menu > .item {
	padding: 8px 12px !important;
	font-size: 13px;
	border-top: none;
}

/*
 * The same picker on the canvas text bar, where it is one control in a row of
 * them rather than a field in a form: no box of its own, and a fixed width, so
 * a long family name cannot stretch the bar across the design. Semantic gives a
 * selection dropdown a 14em floor, which is what the width has to out-rank.
 */
.pdr-nt-textbar-fontpicker.ui.selection.dropdown {
	width: 132px;
	min-width: 132px;
	min-height: 34px;
	padding: 8px 26px 8px 9px;
	border: none;
	background: transparent;
	white-space: nowrap;
}

.pdr-nt-textbar-fontpicker.ui.selection.dropdown:hover {
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-textbar-fontpicker.ui.selection.dropdown > .text {
	display: block;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.pdr-nt-textbar-fontpicker.ui.selection.dropdown > .dropdown.icon {
	top: 50%;
	right: 8px;
	padding: 0;
	margin: 0;
	transform: translateY(-50%);
}

/* The list is free to be wider than the control that opens it. */
.pdr-nt-textbar-fontpicker.ui.selection.dropdown .menu {
	min-width: 220px;
	border-radius: var(--pdr-nt-radius);
}

/*
 * Everything the text bar does not carry, off its last button. The width is set
 * on the popup; the layout belongs to the wrapper inside it, because Semantic
 * owns the popup's own display - see the note in canvas-popups.php.
 */
.pdr-nt-text-popup.ui.popup {
	min-width: 250px;
	/*
	 * Opening inwards from the bar's right hand end. Semantic picks a side by
	 * asking whether the popup fits the window, and it does - but the button is
	 * at the right hand end of a bar inside the canvas column, which hides what
	 * overflows it, so a popup opening rightwards had a quarter of itself cut
	 * off. Pinned to the bar's own right edge instead, which is inside the
	 * column by definition. Semantic keeps deciding how far down it sits.
	 */
	left: auto !important;
	right: 0 !important;
}

.pdr-nt-text-popup-body {
	display: grid;
	gap: 12px;
}

/* ── Canvas getting-started hint ─────────────────────────── */

.pdr-nt-canvas-hint {
	position: absolute;
	inset: 0;
	z-index: 4;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 6px;
	padding: 16px;
	/* Only the buttons are interactive, so the canvas underneath stays usable. */
	pointer-events: none;
}

.pdr-nt-canvas-hint-title {
	margin-bottom: 3px;
	font-size: 9px;
	font-weight: 600;
	letter-spacing: .7px;
	text-transform: uppercase;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-canvas-hint-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	min-width: 170px;
	height: 32px;
	padding: 0 14px;
	border: 1.5px dashed #cbd5e1;
	border-radius: 7px;
	background: rgba(255, 255, 255, .94);
	color: var(--pdr-nt-ink-2);
	font-family: inherit;
	font-size: 11px;
	font-weight: 500;
	cursor: pointer;
	pointer-events: auto;
}

.pdr-nt-canvas-hint-btn:hover {
	border-color: var(--pdr-nt-accent);
	color: var(--pdr-nt-accent);
}

/* ── Images panel ────────────────────────────────────────── */

.pdr-nt-uploads {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 6px;
	margin: 6px 0 0;
	padding: 0;
	list-style: none;
}

.pdr-nt-uploads > li {
	position: relative;
	height: 72px;
	overflow: hidden;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-line-soft);
	cursor: pointer;
}

.pdr-nt-uploads > li:hover {
	border-color: var(--pdr-nt-accent);
}

.pdr-nt-uploads img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
}

/* ── Asset panels ────────────────────────────────────────── */

/*
 * Templates, cliparts, shapes and backgrounds share one shape in the design: a
 * search field, the category select, then a three column grid of 72px tiles
 * with the price pinned to the tile's bottom right corner. The markup inside
 * comes from the engine's own templates, so these rules restyle those
 * containers rather than replacing them, and any asset panel the plugin gains
 * later picks the look up by using the same container class.
 */
.pdr-nt-search-lg {
	height: 36px;
	padding: 0 12px;
	gap: 8px;
}

.pdr-nt-search-lg input {
	font-size: 13px;
}

.pdr-nt-asset-search {
	margin-bottom: 10px;
}

.pdr-nt-panel .pdr-templates-container,
.pdr-nt-panel .cliparts-container,
.pdr-nt-panel .pdr-shapes-container,
.pdr-nt-panel .pdr-background-images-container {
	display: grid;
	/*
	 * minmax(0, 1fr) rather than 1fr: a tile's artwork carries its own intrinsic
	 * width as the column's minimum, which pushes the first column wide and
	 * squeezes the rest. Zero as the floor keeps the three columns equal.
	 */
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 6px;
	margin-top: 10px;
}

.pdr-nt-panel .pdr-template,
.pdr-nt-panel .cliparts-thumbnail,
.pdr-nt-panel .shape-thumbnail,
.pdr-nt-panel .background-image-thumbnail {
	position: relative;
	height: 72px;
	overflow: hidden;
	border: 1.5px dashed #d1d5db;
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-line-soft);
	cursor: pointer;
	transition: border-color .15s ease, background-color .15s ease;
}

.pdr-nt-panel .pdr-template:hover,
.pdr-nt-panel .cliparts-thumbnail:hover,
.pdr-nt-panel .shape-thumbnail:hover,
.pdr-nt-panel .background-image-thumbnail:hover {
	border-color: var(--pdr-nt-accent);
	background: #f0f7ff;
}

/* The engine wraps every tile's art in a Semantic image, which has to fill it. */
.pdr-nt-panel .pdr-template > .ui.image,
.pdr-nt-panel .cliparts-thumbnail > .ui.image,
.pdr-nt-panel .shape-thumbnail > .ui.image,
.pdr-nt-panel .background-image-thumbnail > .ui.image {
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
}

.pdr-nt-panel .pdr-template img,
.pdr-nt-panel .cliparts-thumbnail img,
.pdr-nt-panel .background-image-thumbnail img,
.pdr-nt-panel .shape-thumbnail .pdr-shape,
.pdr-nt-panel .shape-thumbnail svg {
	display: block;
	width: 100%;
	height: 100%;
	padding: 6px;
	object-fit: contain;
	box-sizing: border-box;
}

/*
 * The price badge. Semantic renders it as a ribbon pinned to the top left with
 * a folded corner, so the corner is removed and it is moved to where the design
 * puts it. A free item takes the green treatment and a priced one the dark, as
 * the design does; the text itself stays whatever the merchant's price settings
 * produce rather than being rewritten to "Free".
 */
.pdr-nt-panel .ui.label.pdr-price-label,
.pdr-nt-panel .ui.right.ribbon.label.pdr-price-label {
	position: absolute;
	top: auto;
	right: 4px;
	bottom: 4px;
	left: auto !important;
	transform: none !important;
	z-index: 1;
	margin: 0;
	padding: 2px 5px;
	border: none;
	border-radius: 6px;
	background: var(--pdr-nt-dark) !important;
	color: #fff !important;
	font-family: inherit;
	font-size: 8px;
	font-weight: 700;
	line-height: 1.3;
}

/* Matching the ribbon selector above, which carries one class more. */
.pdr-nt-panel .ui.label.pdr-price-label.is-free,
.pdr-nt-panel .ui.right.ribbon.label.pdr-price-label.is-free {
	background: var(--pdr-nt-success) !important;
}

/* ── Item 3: asset hover preview ─────────────────────────── */

/*
 * A magnified look at the asset under the pointer. It is appended to the studio
 * root rather than to the tile, because a tile clips its own overflow, and it
 * never takes pointer events so it cannot get between the pointer and the tile.
 */
.pdr-nt-asset-zoom {
	position: fixed;
	z-index: 60;
	display: flex;
	align-items: center;
	justify-content: center;
	/*
	 * Wider than it is tall, and large enough to judge detail on. A square box
	 * wasted most of its width on the landscape artwork most assets are.
	 */
	width: 320px;
	height: 260px;
	padding: 12px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius-lg);
	background: var(--pdr-nt-surface);
	box-shadow: var(--pdr-nt-shadow);
	pointer-events: none;
}

.pdr-nt-asset-zoom img,
.pdr-nt-asset-zoom svg {
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
}

.pdr-nt-panel .ui.label.pdr-price-label::before,
.pdr-nt-panel .ui.label.pdr-price-label::after {
	display: none !important;
}

/* The category select, to the same field metrics as the search above it. */
.pdr-nt-panel .ui.selection.dropdown {
	min-height: 36px;
	padding: 0 10px 0 12px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface-2);
	display: flex;
	align-items: center;
	font-family: inherit;
	font-size: 13px;
	font-weight: 500;
	color: var(--pdr-nt-ink);
}

.pdr-nt-panel .ui.selection.dropdown:hover {
	border-color: #cbd5e1;
}

.pdr-nt-panel .ui.selection.dropdown > .text {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

.pdr-nt-panel .ui.selection.dropdown > .text {
	order: 1;
}

/*
 * Semantic sizes the menu items from its own type scale, so an option read a
 * different size from the field it dropped out of. These match the field.
 */
.pdr-nt-panel .ui.selection.dropdown .menu > .item {
	padding: 8px 12px;
	border: none;
	font-family: inherit;
	font-size: 13px;
	font-weight: 500;
	line-height: 1.4;
	color: var(--pdr-nt-ink-2);
}

.pdr-nt-panel .ui.selection.dropdown .menu > .item:hover {
	background: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-ink);
}

.pdr-nt-panel .ui.selection.dropdown .menu > .item.active.selected,
.pdr-nt-panel .ui.selection.dropdown .menu > .item.selected {
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent-hover);
	font-weight: 600;
}

.pdr-nt-panel .ui.selection.dropdown .menu {
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	box-shadow: var(--pdr-nt-shadow);
}

/* Semantic renders the chevron first, so ordering moves it to the trailing edge. */
.pdr-nt-panel .ui.selection.dropdown > .dropdown.icon {
	order: 2;
	position: static;
	flex-shrink: 0;
	margin: 0;
	padding: 0;
	color: var(--pdr-nt-muted-2);
}

/* An empty category reads as a quiet note, not as an error. */
.pdr-nt-panel .ui.error.message.pdr-no-items-message {
	grid-column: 1 / -1;
	margin: 0;
	padding: 10px 12px;
	border: 1px dashed var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	box-shadow: none;
	background: var(--pdr-nt-surface-2);
	color: var(--pdr-nt-muted);
	font-family: inherit;
	font-size: 12px;
	text-align: center;
}

/* ── Price breakdown rows ────────────────────────────────── */

.pdr-nt-breakdown-row small {
	display: block;
	margin-top: 1px;
	font-size: 10px;
	color: var(--pdr-nt-muted-2);
}

.pdr-nt-breakdown-row > span:last-child {
	font-weight: 600;
	white-space: nowrap;
}

/*
 * The itemised rows. A group's own line is the heading its items sit under, and
 * each item is indented and quieter, so the panel reads as a total made of
 * named parts rather than as one flat list where a group and its members look
 * like they should be added together.
 */
.pdr-nt-breakdown-row.is-heading > span {
	font-weight: 700;
	color: var(--pdr-nt-ink);
}

.pdr-nt-breakdown-row.is-item {
	margin-bottom: 4px;
	padding-left: 10px;
	border-left: 2px solid var(--pdr-nt-line);
	font-size: 11px;
	color: var(--pdr-nt-muted);
}

.pdr-nt-breakdown-row.is-item > span:last-child {
	font-weight: 500;
	color: var(--pdr-nt-ink-2);
}

/*
 * How many went into a grouped figure, beside what the group is rather than
 * under it: "Clipart × 2" is one fact on one line.
 */
.pdr-nt-breakdown-row.is-item small {
	display: inline;
	margin: 0 0 0 5px;
	font-size: 10px;
	color: var(--pdr-nt-muted-2);
}

/*
 * What one item comes to, and then how many of them. These close the list of
 * single item prices above and lead into the total below, so they are ruled off
 * from the parts and weighted between an item row and the total itself.
 */
.pdr-nt-breakdown-row.is-subtotal {
	margin-top: 7px;
	padding-top: 7px;
	border-top: 1px solid var(--pdr-nt-line-soft);
}

.pdr-nt-breakdown-row.is-subtotal + .pdr-nt-breakdown-row.is-subtotal {
	margin-top: 0;
	padding-top: 0;
	border-top: none;
}

.pdr-nt-breakdown-row.is-subtotal > span {
	font-weight: 700;
	color: var(--pdr-nt-ink);
}

/* ── Image tools ─────────────────────────────────────────── */

.pdr-nt-imagebar[hidden] {
	display: none !important;
}

.pdr-nt-imagebar {
	display: flex !important;
}

.pdr-nt-btn-sm {
	height: 30px;
	padding: 0 12px;
	font-size: 12px;
}

.pdr-nt-opacity {
	display: flex;
	align-items: center;
	gap: 7px;
	height: 34px;
	padding: 0 8px;
	color: var(--pdr-nt-muted);
	cursor: pointer;
}

.pdr-nt-opacity-range {
	width: 74px;
	margin: 0;
}

.pdr-nt-opacity-value {
	min-width: 34px;
	font-size: 12px;
	font-weight: 600;
	color: var(--pdr-nt-ink);
}

/* ── Crop overlay ────────────────────────────────────────── */

/* The crop overlay's origin: the drawing area's box is the canvas element's box. */
.pdr-nt-canvas-stage .pdr-drawing-area {
	position: relative;
}

.pdr-nt-crop {
	position: absolute;
	inset: 0;
	z-index: 8;
	/* The shaded area outside the box must not swallow canvas clicks. */
	pointer-events: none;
	touch-action: none;
}

.pdr-nt-crop-box {
	position: absolute;
	border: 1px solid #fff;
	box-shadow: 0 0 0 1px var(--pdr-nt-accent), 0 0 0 9999px rgba(15, 23, 42, .45);
	cursor: move;
	pointer-events: auto;
	touch-action: none;
}

/* Rule-of-thirds guides. */
.pdr-nt-crop-box::before,
.pdr-nt-crop-box::after {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
}

.pdr-nt-crop-box::before {
	background-image: linear-gradient(to right, transparent 33.33%, rgba(255, 255, 255, .45) 33.33%, rgba(255, 255, 255, .45) calc(33.33% + 1px), transparent calc(33.33% + 1px), transparent 66.66%, rgba(255, 255, 255, .45) 66.66%, rgba(255, 255, 255, .45) calc(66.66% + 1px), transparent calc(66.66% + 1px));
}

.pdr-nt-crop-box::after {
	background-image: linear-gradient(to bottom, transparent 33.33%, rgba(255, 255, 255, .45) 33.33%, rgba(255, 255, 255, .45) calc(33.33% + 1px), transparent calc(33.33% + 1px), transparent 66.66%, rgba(255, 255, 255, .45) 66.66%, rgba(255, 255, 255, .45) calc(66.66% + 1px), transparent calc(66.66% + 1px));
}

.pdr-nt-crop-handle {
	position: absolute;
	width: 14px;
	height: 14px;
	background: #fff;
	border: 2px solid var(--pdr-nt-accent);
	border-radius: 3px;
	pointer-events: auto;
	touch-action: none;
}

.pdr-nt-crop-handle[data-pdr-crop-handle="nw"] { top: -7px; left: -7px; cursor: nwse-resize; }
.pdr-nt-crop-handle[data-pdr-crop-handle="ne"] { top: -7px; right: -7px; cursor: nesw-resize; }
.pdr-nt-crop-handle[data-pdr-crop-handle="se"] { bottom: -7px; right: -7px; cursor: nwse-resize; }
.pdr-nt-crop-handle[data-pdr-crop-handle="sw"] { bottom: -7px; left: -7px; cursor: nesw-resize; }

/* ── View chips ──────────────────────────────────────────── */

.pdr-nt-view {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 5px;
}

.pdr-nt-view-thumb {
	display: block;
	width: 100%;
	overflow: hidden;
	border-radius: 5px;
	background: var(--pdr-nt-surface);
}

.pdr-nt-view-thumb img {
	display: block;
	width: 100%;
	height: 58px;
	object-fit: contain;
}

/* Name and price share one centred row under the thumbnail. */
.pdr-nt-view-meta {
	display: flex;
	align-items: baseline;
	justify-content: center;
	gap: 5px;
	width: 100%;
	min-width: 0;
}

.pdr-nt-view-name {
	display: block;
	min-width: 0;
	overflow: hidden;
	font-size: 10px;
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.pdr-nt-view-cost {
	flex-shrink: 0;
	padding: 1px 5px;
	border-radius: 999px;
	background: var(--pdr-nt-success-soft);
	color: var(--pdr-nt-price);
	font-size: 9px;
	font-weight: 700;
	line-height: 1.3;
	white-space: nowrap;
}

/* The selected chip is already tinted, so the price keeps a plain ground. */
.pdr-nt-view.active .pdr-nt-view-cost {
	background: var(--pdr-nt-surface);
}

/* ── Layer filters ───────────────────────────────────────── */

/*
 * The design frames the layers list as its own card: a 34px header strip, then
 * the filter row, then the rows, all inside one rounded border.
 */
.pdr-nt-section-layers .pdr-nt-section-head {
	height: 34px;
	min-height: 34px;
	padding: 0 10px;
	border: 1px solid var(--pdr-nt-line);
	border-bottom: none;
	border-radius: var(--pdr-nt-radius) var(--pdr-nt-radius) 0 0;
	background: #f8f9fa;
}

.pdr-nt-section-layers .pdr-nt-section-head:hover {
	background: var(--pdr-nt-line-soft);
}

.pdr-nt-section-layers .pdr-nt-section-title {
	font-size: 12px;
	font-weight: 600;
	color: var(--pdr-nt-ink);
}

/*
 * The layers list scrolls inside itself.
 *
 * Every box down this column clipped its overflow and none of them scrolled, so
 * a design with more layers than fit simply lost the rest: the section cut them
 * off, the panel around it never grew tall enough to scroll, and there was no
 * way to reach a row past the fold. The section is now a column that is allowed
 * to shrink, and the list inside it takes what room is left and scrolls.
 *
 * min-height: 0 on each link in the chain, because a flex item's floor is its
 * content, and one that will not shrink below its content can never hand a
 * bounded height to the thing that is supposed to scroll.
 */
.pdr-nt-section-layers {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-height: 0;
}

.pdr-nt-section-layers .pdr-nt-section-body {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-height: 0;
	padding: 0;
	overflow: hidden;
	border: 1px solid var(--pdr-nt-line);
	border-radius: 0 0 var(--pdr-nt-radius) var(--pdr-nt-radius);
	background: var(--pdr-nt-surface);
}

/* The filter row keeps its height; only the list gives way. */
.pdr-nt-section-layers .pdr-nt-layer-filters {
	flex-shrink: 0;
}

.pdr-nt-layers .pdr-layers-wrapper {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	/* The page behind must not scroll on once the list reaches its end. */
	overscroll-behavior: contain;
}

/*
 * With the layers list switched off the switcher is the only thing in the
 * column, so it takes the whole of it rather than staying sized for a list that
 * is not there and leaving the rest of the column empty. The studio counts how
 * many view chips fit the room this gives.
 */
.pdr-nt-properties-views-only .pdr-nt-section[data-pdr-section="views"] {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-height: 0;
}

.pdr-nt-properties-views-only .pdr-nt-section[data-pdr-section="views"] .pdr-nt-section-body,
.pdr-nt-properties-views-only .pdr-nt-views-scroller {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	min-height: 0;
}

.pdr-nt-properties-views-only .pdr-nt-views-viewport {
	flex: 1 1 auto;
	min-height: 0;
}


/*
 * A collapsed section is not a section that should still be taking the room, so
 * it stops growing while it is shut. The head carries the state, which is why
 * this reads it from there rather than from a class on the section.
 *
 * It stops holding a floor open too. The layers list is given a minimum height
 * below, so that shrinking it never cuts the list down to nothing, and that
 * floor went on being held after the list was collapsed: the body was hidden
 * and its 210px stayed, leaving the head sitting over an empty box the height
 * of the list that was no longer there.
 */
.pdr-nt-section:has(.pdr-nt-section-head[aria-expanded="false"]) {
	flex: 0 0 auto;
	min-height: 0;
}

/*
 * And the head closes its own card while it is shut.
 *
 * The layers card is drawn as a head with no bottom border and a body that
 * carries the other three sides, so the two make one rounded box. Collapsed,
 * the body is display: none and the head was left as three sides of a box with
 * its bottom edge open, hanging under the title.
 */
.pdr-nt-section-layers .pdr-nt-section-head[aria-expanded="false"] {
	border-bottom: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
}

/*
 * ── Neither section is shrunk into clipping ──────────────
 *
 * .pdr-nt-section hides its overflow, and both sections here could be shrunk by
 * the column's flex - so where the column was shorter than the two of them, each
 * was cut off inside its own box instead of the column scrolling. On a cap, four
 * views and an empty layers list in a 484px column: the view strip lost 43px, so
 * its second chip was sliced through the middle and read as the Layers card
 * sitting on top of Switch View, and the layers list lost 30px, so "No layers
 * found" was cut in half.
 *
 * The switcher keeps its height. Its strip is sized by the studio to a whole
 * number of chips, and shrinking it can only ever cut a chip in half.
 */
.pdr-nt-properties > .pdr-nt-section[data-pdr-section="views"] {
	flex-shrink: 0;
}

/*
 * The layers list keeps enough to be a list: its head, its filter row and a few
 * rows of list under them. It still absorbs whatever room is going spare, and a
 * long list still scrolls inside itself - this is only the point below which
 * shrinking it stops being useful and starts hiding things.
 */
.pdr-nt-properties > .pdr-nt-section-layers {
	min-height: 210px;
}

/*
 * Which together can ask for more than the column has, and that is what the
 * column's own scrolling is for. It reaches this only where a product base has
 * several views and the page has little height to give the studio; the ordinary
 * case still fits without a scrollbar.
 */
.pdr-nt-properties {
	overscroll-behavior: contain;
}

/*
 * The empty note, sized so it fits inside that floor rather than being the
 * reason the floor is not enough. It was a 94px dashed panel for four words.
 */
.pdr-nt-layers .pdr-no-layers-message {
	padding: 14px 12px;
}

.pdr-nt-layer-filters {
	display: flex;
	align-items: center;
	/*
	 * Two groups of filters do not fit one line in a 272px panel, so the row
	 * wraps rather than pushing the last buttons out of reach.
	 */
	flex-wrap: wrap;
	gap: 4px 5px;
	padding: 5px 8px;
	border-bottom: 1px solid var(--pdr-nt-line-soft);
	margin-bottom: 0;
	padding-bottom: 6px;
	border-bottom: 1px solid var(--pdr-nt-line-soft);
}

.pdr-nt-layer-filters-divider {
	flex-shrink: 0;
	width: 1px;
	height: 16px;
	margin: 0 1px;
	background: var(--pdr-nt-line);
}

.pdr-nt-layer-filters-label {
	flex-shrink: 0;
	margin-right: 2px;
	font-size: 10px;
	font-weight: 500;
	color: var(--pdr-nt-muted-2);
}

/* The design's filter buttons: 24x22, outlined, tinted when active. */
.pdr-nt-layer-filter {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 24px;
	height: 22px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: 5px;
	background: var(--pdr-nt-surface);
	color: var(--pdr-nt-muted-2);
	cursor: pointer;
}

.pdr-nt-layer-filter:hover {
	background: var(--pdr-nt-line-soft);
	color: var(--pdr-nt-ink-2);
}

.pdr-nt-layer-filter.active {
	border-color: var(--pdr-nt-accent);
	background: var(--pdr-nt-accent-soft);
	color: var(--pdr-nt-accent);
}

/* ── Layer rename ────────────────────────────────────────── */

.pdr-nt-layers .pdr-layer-name-text {
	cursor: text;
}

.pdr-nt-layer-rename {
	width: 100%;
	max-width: 130px;
	height: 22px;
	padding: 0 6px;
	border: 1px solid var(--pdr-nt-accent);
	border-radius: 4px;
	background: var(--pdr-nt-surface);
	font-family: inherit;
	font-size: 12px;
	color: var(--pdr-nt-ink);
	outline: none;
}

/* ── Images panel ────────────────────────────────────────── */

.pdr-nt-upload-btn {
	/* A label styled as the button; the real input is visually hidden behind it. */
	cursor: pointer;
}

.pdr-nt-upload-rules {
	margin-top: 6px;
}

.pdr-nt-images-panel .pdf_preview:empty {
	display: none;
}

.pdr-nt-uploads > li {
	display: flex;
	align-items: center;
	justify-content: center;
}

/* The engine renders the delete affordance inside each upload. */
.pdr-nt-uploads .pdr-user-uploaded-image-list-delete {
	position: absolute;
	top: 3px;
	right: 3px;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: rgba(15, 23, 42, .72);
	color: #fff;
	font-size: 13px;
	line-height: 1;
	cursor: pointer;
	opacity: 0;
	transition: opacity .12s ease;
}

.pdr-nt-uploads > li:hover .pdr-user-uploaded-image-list-delete,
.pdr-nt-uploads > li:focus-within .pdr-user-uploaded-image-list-delete {
	opacity: 1;
}

/*
 * A control that only appears on hover is a trap on a touch screen: there is no
 * hover to give, so these two stayed invisible - and an invisible button is
 * still a button, so a tap meant for the design or the upload beside it landed
 * on a delete that could not be seen. Both are shown outright where there is no
 * hover to reveal them with, and on a phone-width window for the same reason.
 */
@media (hover: none), (max-width: 782px) {
	.pdr-nt-designs-grid > .card .pdr-my-design-delete.button,
	.pdr-nt-uploads > li .pdr-user-uploaded-image-list-delete {
		opacity: 1;
	}
}

.pdr-nt-uploads .pdr-user-uploaded-image-list-delete:hover {
	background: var(--pdr-nt-danger);
}

/* ── Your Uploads ────────────────────────────────────────── */

.pdr-nt-uploads .pdr-user-uploaded-image-list {
	cursor: pointer;
}

.pdr-nt-uploads .pdr-user-uploaded-image-list:focus-visible {
	outline: 2px solid var(--pdr-nt-accent);
	outline-offset: -2px;
}

.pdr-nt-uploads .pdr-user-uploaded-image-list-delete {
	/* Now a real button, so reset the browser chrome the span never had. */
	padding: 0;
	border: none;
	font-family: inherit;
}

.pdr-nt-uploads .pdr-user-uploaded-image-list-delete:focus-visible {
	opacity: 1;
	outline: 2px solid #fff;
	outline-offset: 1px;
}

.pdr-nt-upload-price {
	position: absolute;
	left: 3px;
	bottom: 3px;
	z-index: 2;
	padding: 1px 5px;
	border-radius: 4px;
	background: var(--pdr-nt-success-soft);
	border: 1px solid var(--pdr-nt-success-line);
	color: var(--pdr-nt-price);
	font-size: 9px;
	font-weight: 700;
	line-height: 1.4;
	pointer-events: none;
}

/* ── QR preview ──────────────────────────────────────────── */

.pdr-nt-qr-preview {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.pdr-nt-qr-preview-frame {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 10px;
	border: 1px solid var(--pdr-nt-line);
	border-radius: var(--pdr-nt-radius);
	background: var(--pdr-nt-surface);
}

.pdr-nt-qr-preview-frame img {
	display: block;
	width: 120px;
	height: 120px;
	image-rendering: pixelated;
}


/* ==========================================================================
   Template colours
   --------------------------------------------------------------------------
   Merged in from template-color.css, which used to load as a sheet of its own
   on every designer page.

   Read this before editing it: the ten schemes below are not scoped to
   anything, so each one overrides the one above it and only the last can ever
   apply. Nothing in the plugin carries a .navbar, .footer or .btn-group class
   either, so as it stands the block styles the active theme's markup, if that
   theme happens to use those names, and nothing of the designer's own.
   ========================================================================== */

/*Multiple color template select css */

/*style-1 (Dark Blue) */

.navbar,
.footer {
	background: #1b00d1;
} 
.btn-group a.active {
	border-bottom: 2px solid #1b00d1;
}

/*style-2 (Gossamer) */

.navbar,
.footer {
	background: #099d84;
} 
.btn-group a.active {
	border-bottom: 2px solid #099d84;
}

/*style-3 (Rio Grande) */

.navbar,
.footer {
	background: #c5d100;
} 
.btn-group a.active {
	border-bottom: 2px solid #c5d100;
}

/*style-4 (Green) */

.navbar,
.footer {
	background: #00d111;
} 
.btn-group a.active {
	border-bottom: 2px solid #00acd1;
}

/*style-5 (Purple) */

.navbar,
.footer {
	background: #69048f;
} 
.btn-group a.active {
	border-bottom: 2px solid #69048f;
}

/*style-6 (Cardinal Pink) */

.navbar,
.footer {
	background: #8f0470;
} 
.btn-group a.active {
	border-bottom: 2px solid #8f0470;
}

/*style-7 (Cherry Pie) */

.navbar,
.footer {
	background: #2f014b;
} 
.btn-group a.active {
	border-bottom: 2px solid #2f014b;
}

/*style-8 (Red) */

.navbar,
.footer {
	background: #ef0000;
} 
.btn-group a.active {
	border-bottom: 2px solid #ef0000;
}

/*style-9 (Corn) */

.navbar,
.footer {
	background: #d7b600;
} 
.btn-group a.active {
	border-bottom: 2px solid #d7b600;
}

/*style-10 (Paprika) */

.navbar,
.footer {
	background: #8f0430;
} 
.btn-group a.active {
	border-bottom: 2px solid #8f0430;
}
