@import './shared/styles/tokens.css';

/* This used to hardcode its own --fc-accent/--fc-border/--fc-bg/--fc-font
   instead of using the shared tokens .chargeforms-wrap already defines (the
   builder page is always rendered inside .chargeforms-wrap — see
   class-builder-page.php) — a second, slightly-different color/shadow
   language living next to the one used by every other admin screen is
   exactly why the builder read as visually disconnected from the rest of
   the plugin's design-revamp pass. Re-pointing --fc-accent* at the real
   --fc-primary* tokens means every var(--fc-accent...) reference below
   picks up the same color, shadow, and motion system as the rest of the
   admin without needing to touch each of the ~40 places that reference it. */
.chargeforms-app-root * {
	font-family: inherit;
}
.chargeforms-app-root .dashicons {
	font-family: dashicons !important;
}
.fc-app.is-fullscreen {
	position: fixed;
	inset: 0;
	z-index: 100000;
	border-radius: 0;
	overflow-y: auto;
	margin: 0;
}

.fc-builder-alert {
	margin: 12px 16px 0;
	padding: 10px 12px;
	border: 1px solid var(--fc-danger);
	border-radius: 8px;
	background: #fcf0f1;
	color: #8a2424;
	display: flex;
	gap: 10px;
	align-items: center;
	justify-content: space-between;
}
.fc-builder-alert-draft {
	border-color: #dba617;
	background: #fff8e5;
	color: #6f5200;
}
.fc-builder-alert button {
	border: 1px solid currentColor;
	border-radius: 6px;
	background: #fff;
	color: inherit;
	cursor: pointer;
	padding: 4px 8px;
}

/* .fc-back-link and .fc-icon-btn's real layout (size/border/hover/focus/
   icon sizing) lives in one place further down this file, alongside the
   rest of the toolbar — search "Every icon button carries a Dashicon at
   the same visual weight". Only the two properties genuinely unique to
   this early spot stay here: cursor (buttons don't get it for free) and
   the disabled state (never redeclared anywhere else). */
.fc-back-link,
.fc-icon-btn {
	cursor: pointer;
}
.fc-icon-btn:disabled {
	opacity: 0.35;
	cursor: default;
}
.fc-topbar-actions .button-primary {
	background: #6c4ef5;
	border-color: #6c4ef5;
	border-radius: 7px;
	padding: 9px 16px;
	font-size: 13px;
	font-weight: 600;
	line-height: 1.2;
	box-shadow: none;
	text-shadow: none;
	transition: background 0.2s var(--fc-ease, ease);
}
.fc-topbar-actions .button-primary:hover {
	background: #5638d8;
	border-color: #5638d8;
	box-shadow: none;
	transform: none;
}

.fc-settings h4 {
	margin: 0 0 16px;
	font-size: 16px;
	font-weight: 700;
	letter-spacing: -0.01em;
	color: var(--fcb-ink);
}

/* Canvas */

.fc-canvas-slot {
	position: relative;
}

/* Insert points stay visually quiet until the slot they belong to is
   hovered (or the popover they open is active) — with several fields on
   the canvas, a permanently-visible "+" dot above every single one reads
   as visual clutter rather than a clear affordance. A thin line still
   marks the gap at all times so the insert points remain discoverable. */
.fc-canvas-dropline {
	position: relative;
	height: 16px;
	margin: -8px 0;
	border-radius: 4px;
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 1;
}
.fc-canvas-dropline::before {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 1px;
	background: var(--fc-border);
	opacity: 0;
	transition: opacity 0.15s ease;
}
.fc-canvas-slot:hover .fc-canvas-dropline::before {
	opacity: 1;
}
/* Always visible at rest, not hover-only — every the reference product reference
   screenshot shows this "+" as a permanent, discoverable part of the
   canvas (one even labels it "Add In Place" with an arrow pointing at
   it), not something a first-time user has to already know to hover for.
   Kept at a muted, low-contrast gray by default so it doesn't compete
   with actual form content — full brand-accent color + scale-up is
   reserved for hover/focus/open, so there's still a clear "this is now
   interactive" signal. */
.fc-insert-btn {
	width: 22px;
	height: 22px;
	border-radius: 50%;
	border: none;
	background: var(--fc-muted-light, #a3acba);
	color: #fff;
	font-size: 15px;
	line-height: 1;
	cursor: pointer;
	opacity: 0.55;
	transform: scale(0.85);
	transition: background var(--fc-motion-fast) var(--fc-ease), transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1), opacity var(--fc-motion-fast) var(--fc-ease), box-shadow var(--fc-motion-fast) var(--fc-ease);
}
.fc-canvas-slot:hover .fc-insert-btn,
.fc-insert-btn:focus-visible,
.fc-insert-btn.is-active {
	opacity: 1;
	transform: scale(1);
}
.fc-insert-btn:hover,
.fc-insert-btn.is-active {
	background: var(--fc-accent);
	transform: scale(1.25);
	box-shadow: 0 2px 8px rgba(26, 126, 251, 0.35);
}
.fc-canvas-dropline.is-active {
	background: var(--fc-accent-soft);
	box-shadow: inset 0 0 0 1px var(--fc-accent);
}
.fc-canvas-dropline.is-active .fc-insert-btn {
	opacity: 1;
	transform: scale(1);
}
/* The floating toolbar renders directly above a selected field, in the
   same space this insert point's "+" occupies when hovered — keep it
   hidden while the toolbar is there instead of letting the two overlap.
   See FloatingToolbar.js. */
.fc-canvas-dropline.is-toolbar-covered .fc-insert-btn {
	opacity: 0 !important;
	pointer-events: none;
}
/* The trailing insert point (after the last field, or the only one on an
   empty form) isn't wrapped in a .fc-canvas-slot to hover, so it stays
   visible on its own — same "always-there way to add the next field"
   affordance most builders keep at the bottom of the canvas. */
.fc-canvas > .fc-canvas-dropline:last-child .fc-insert-btn {
	opacity: 1;
	transform: scale(1);
}
.fc-canvas > .fc-canvas-dropline:last-child::before {
	opacity: 1;
}

/* Quick-add popover — opened by clicking a "+" insert point. Positioned by
   QuickAddMenu.js in real viewport coordinates (`position: fixed`, portaled
   to <body>) so it can flip above its trigger when there's no room below —
   matching the reference product's real editor-inserter.vue flip behavior — instead of
   always opening downward and risking clipping near the canvas bottom. */
.fc-quick-add {
	/* Real bug found live: this popover is portaled straight to
	   document.body (see QuickAddMenu.js's doc comment on why), which
	   sits OUTSIDE .chargeforms-wrap — the element these --fc-* custom
	   properties are actually scoped to (admin.css), and outside .fc-app
	   too (tokens.css's --fcb-* scope). Neither var() ever resolved for a
	   portaled node, so the background/border silently fell through to
	   fully transparent: the popover's own content (search box, category
	   pills, field grid) rendered directly on top of whatever canvas
	   content sat behind it, unreadable. Explicit fallbacks matching the
	   real values those tokens resolve to inside their normal scope keep
	   this identical when nested normally and correct when portaled.
	   FloatingToolbar.js's CSS already sidesteps this the same way it was
	   originally built for a portal: literal values, not variables. */
	max-height: 420px;
	overflow-y: auto;
	background: var(--fc-surface, #ffffff);
	border: 1px solid var(--fcb-border-soft, rgba(15, 23, 42, 0.08));
	border-radius: 14px;
	box-shadow: 0 4px 12px rgba(15, 23, 42, 0.06), 0 24px 48px -12px rgba(15, 23, 42, 0.20);
	padding: 14px;
	text-align: left;
}
.fc-quick-add--floating {
	position: fixed;
	z-index: 100000;
	animation: fc-quick-add-in var(--fc-motion-base) var(--fc-ease);
}

/* Right-click context menu on a canvas field — see ContextMenu.js's doc
   comment for why this exists (the reference product's real nested-list.vue has one;
   ChargeForms previously didn't). Same floating/fixed-position/portal
   pattern as .fc-quick-add--floating and FloatingToolbar.js. */
.fc-context-menu {
	position: fixed;
	z-index: 100000;
	/* Same portal-scoping bug as .fc-quick-add above — this also portals
	   to document.body, outside where these tokens are actually defined. */
	background: var(--fc-surface, #ffffff);
	border: 1px solid var(--fcb-border-soft, rgba(15, 23, 42, 0.08));
	border-radius: 10px;
	box-shadow: 0 4px 12px rgba(15, 23, 42, 0.06), 0 24px 48px -12px rgba(15, 23, 42, 0.20);
	padding: 6px;
	animation: fc-quick-add-in var(--fc-motion-fast) var(--fc-ease);
}
.fc-context-menu button {
	display: flex;
	align-items: center;
	gap: 8px;
	width: 100%;
	border: none;
	background: transparent;
	border-radius: 6px;
	padding: 7px 9px;
	font-size: 12.5px;
	font-weight: 500;
	color: var(--fcb-ink);
	cursor: pointer;
	text-align: left;
}
.fc-context-menu button .dashicons {
	font-size: 15px;
	width: 15px;
	height: 15px;
	color: var(--fc-muted);
}
.fc-context-menu button:hover:not(:disabled) {
	background: var(--fc-primary-50);
	color: var(--fc-accent-dark);
}
.fc-context-menu button:hover:not(:disabled) .dashicons {
	color: var(--fc-primary);
}
.fc-context-menu button:disabled {
	opacity: 0.4;
	cursor: not-allowed;
}
.fc-context-menu button.is-danger {
	color: var(--fc-danger, #e5484d);
}
.fc-context-menu button.is-danger:hover:not(:disabled) {
	background: rgba(229, 72, 77, 0.08);
	color: var(--fc-danger, #e5484d);
}
.fc-context-menu button.is-danger:hover:not(:disabled) .dashicons {
	color: var(--fc-danger, #e5484d);
}
.fc-context-menu-sep {
	height: 1px;
	background: var(--fcb-border-soft);
	margin: 5px 2px;
}
@keyframes fc-quick-add-in {
	from { opacity: 0; transform: translateY(-4px) scale(0.98); }
	to { opacity: 1; transform: translateY(0) scale(1); }
}
.fc-quick-add-search {
	display: flex;
	align-items: center;
	gap: 8px;
	border: 1px solid var(--fcb-border-soft);
	border-radius: var(--fcb-radius-control);
	padding: 9px 12px;
	margin-bottom: 12px;
	background: var(--fc-bg);
	transition: border-color var(--fc-motion-fast) var(--fc-ease), box-shadow var(--fc-motion-fast) var(--fc-ease), background var(--fc-motion-fast) var(--fc-ease);
}
.fc-quick-add-search:focus-within {
	border-color: var(--fc-primary);
	background: var(--fc-surface);
	box-shadow: 0 0 0 4px var(--fc-primary-50);
}
.fc-quick-add-search .fc-search-icon {
	display: inline-flex;
	color: var(--fc-muted-light);
	flex-shrink: 0;
	transition: color var(--fc-motion-fast) var(--fc-ease);
}
.fc-quick-add-search:focus-within .fc-search-icon {
	color: var(--fc-primary);
}
.fc-quick-add-search input {
	border: none;
	outline: none;
	flex: 1;
	font-size: 13px;
	padding: 2px 0;
	background: transparent;
	color: var(--fc-text);
}
/* Real bug found live (user screenshot): WP admin's own core CSS sets
   `input[type="text"]:focus { border-color: ...; box-shadow: ...; }`
   in its native admin blue — a selector that beats the unconditional
   (non-:focus) `border: none` above on specificity, so the popover's
   own violet focus ring (:focus-within on the wrapper, above) was
   getting stomped by a blue outline drawn on the input itself the
   instant this autofocused field received focus. Redeclaring `:focus`
   directly on the input, at equal-or-higher specificity, keeps it
   borderless so only the wrapper's violet ring shows. */
.fc-quick-add-search input:focus {
	border: none;
	outline: none;
	box-shadow: none;
}
.fc-quick-add-search input::placeholder {
	color: var(--fc-muted-light);
}
.fc-quick-add-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-bottom: 12px;
}
.fc-quick-add-tabs button {
	border: 1px solid var(--fcb-border-soft);
	background: var(--fc-bg);
	border-radius: var(--fc-radius-full);
	color: var(--fc-muted);
	cursor: pointer;
	font-size: 11.5px;
	font-weight: 600;
	padding: 5px 11px;
	transition: background var(--fc-motion-base) var(--fc-ease), border-color var(--fc-motion-base) var(--fc-ease), color var(--fc-motion-base) var(--fc-ease), transform var(--fc-motion-fast) var(--fc-ease);
}
.fc-quick-add-tabs button:hover:not(.is-active) {
	border-color: var(--fc-primary-100);
	color: var(--fc-accent-dark);
	background: var(--fc-primary-50);
}
.fc-quick-add-tabs button:active {
	transform: scale(0.96);
}
.fc-quick-add-tabs button.is-active {
	background: var(--fc-accent);
	border-color: var(--fc-accent);
	color: #fff;
}
.fc-quick-add-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 8px;
}
.fc-quick-add-empty {
	grid-column: 1 / -1;
	font-size: 12px;
	color: var(--fc-muted-light);
	padding: 10px 4px;
	margin: 0;
}
/* Bordered card, icon left of label — matches the user's own design bundle
   (design_handoff_chargeforms/README.md, "the design authority" per its own
   rule 3) — a 2-column grid of real card buttons, not the 3-column
   icon-above-label chip list this used to be matched to an older the reference product
   reference screenshot instead. */
.fc-quick-add-item {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: flex-start;
	gap: 8px;
	padding: 10px 12px;
	border: 1px solid var(--fcb-border-soft);
	border-radius: var(--fcb-radius-control);
	background: var(--fc-surface);
	font-size: 12.5px;
	font-weight: 600;
	color: var(--fcb-ink);
	cursor: pointer;
	text-align: left;
	transition: background var(--fc-motion-fast) var(--fc-ease), color var(--fc-motion-fast) var(--fc-ease), border-color var(--fc-motion-fast) var(--fc-ease);
}
.fc-quick-add-item:hover,
.fc-quick-add-item:focus-visible {
	background: var(--fc-primary-50);
	color: var(--fc-accent-dark);
	border-color: var(--fc-primary-100);
	outline: none;
}
.fc-quick-add-item-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	flex-shrink: 0;
	transition: transform var(--fc-motion-fast) var(--fc-ease);
}
.fc-quick-add-item:hover .fc-quick-add-item-icon {
	transform: scale(1.08);
}
.fc-quick-add-item .dashicons {
	font-size: 20px;
	width: 20px;
	height: 20px;
	flex-shrink: 0;
	color: var(--fc-muted);
	transition: color var(--fc-motion-fast) var(--fc-ease);
}
.fc-quick-add-item:hover .dashicons {
	color: var(--fc-primary);
}
/* Pro-only palette items: visible (so the gap is honest, not hidden) but
   dimmed and non-inserting — clicking opens the pro-lock modal instead of
   the plain hover-lift/insert treatment above. */
.fc-quick-add-item.is-pro {
	opacity: 0.55;
}
.fc-quick-add-item.is-pro:hover,
.fc-quick-add-item.is-pro:focus-visible {
	opacity: 0.85;
	background: var(--fc-bg);
	color: var(--fcb-ink);
	transform: none;
}
.fc-quick-add-item.is-pro:hover .fc-quick-add-item-icon {
	transform: none;
}
.fc-quick-add-item.is-pro:hover .dashicons {
	color: var(--fc-muted);
}
.fc-pro-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	margin-left: auto;
	width: 16px;
	height: 16px;
	flex-shrink: 0;
}
.fc-pro-badge .dashicons {
	font-size: 13px;
	width: 13px;
	height: 13px;
	color: var(--fc-muted);
}
.fc-canvas-field-section_break,
.fc-canvas-field-page_break {
	background: var(--fc-bg);
	border-style: dashed;
	border-color: var(--fc-border);
}
.fc-canvas-field:hover .fc-canvas-field-toolbar,
.fc-canvas-field.is-active .fc-canvas-field-toolbar {
	opacity: 1;
	pointer-events: auto;
}
.fc-drag-handle {
	cursor: grab;
	color: var(--fc-muted, #7a8290);
	font-size: 14px;
	display: inline-flex;
	align-items: center;
}
.fc-canvas-field-toolbar .fc-canvas-field-action-label {
	border: none;
	background: none;
	cursor: pointer;
	color: var(--fc-accent-dark);
}
.fc-canvas-field-toolbar .fc-canvas-field-action-label:hover {
	color: var(--fc-accent);
}

/* Live field previews (non-interactive, disabled inputs). padding-top
   reserves space for the corner drag-handle chip (.fc-canvas-field-toolbar,
   position:absolute at top:6/left:6) whether or not it's currently
   visible — without it, the toolbar only appeared on hover/select, so a
   selected field's own label rendered PARTIALLY HIDDEN behind the drag
   handle the instant you clicked it ("Name" reading as "ame"). Reserving
   the space unconditionally means no layout shift when the toolbar
   fades in, and the label is never at risk of being covered. */
.fc-canvas-field-body {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding-top: 22px;
}
.fc-preview-label {
	display: flex;
	align-items: center;
	gap: 7px;
	font-size: 14px;
	font-weight: 600;
	letter-spacing: -0.005em;
	color: var(--fcb-ink);
	margin-bottom: 2px;
}
.fc-preview-label-icon {
	font-size: 14px;
	width: 14px;
	height: 14px;
	color: var(--fc-accent);
	opacity: 0.75;
	flex-shrink: 0;
}
.fc-preview-label .req,
.fc-preview-inline .req {
	color: #e5484d;
	margin-left: 2px;
}
.fc-canvas-field-body input,
.fc-canvas-field-body select,
.fc-canvas-field-body textarea {
	font: inherit;
	font-size: 13px;
	padding: 8px 10px;
	border: 1px solid var(--fc-border);
	border-radius: 5px;
	background-color: var(--fc-bg);
	width: 100%;
	box-sizing: border-box;
	color: var(--fc-muted);
}
/* Real bug found via the commerce-field audit: these preview controls are
   `disabled` (they're a static representation of the live field, never
   actually editable in the builder), and browsers do not fire/bubble
   click events from a disabled form element — so a click landing on one
   silently did nothing instead of selecting the field, a real dead zone
   right on the most visually prominent part of the field. Confirmed via
   Playwright: clicking the field's label selected it; clicking the
   identical field's disabled input did not. `pointer-events: none` lets
   the click pass through to the field wrapper's own handler — safe here
   specifically because these controls are genuinely non-interactive by
   design, so nothing that used to work on them is lost. */
.fc-canvas-field-body input:disabled,
.fc-canvas-field-body select:disabled,
.fc-canvas-field-body textarea:disabled {
	pointer-events: none;
}
/* WP admin's own core stylesheet gives every <select> a chevron
   background-image; overriding just background-color (not the
   shorthand `background`) above still leaves that image in place, and
   at this field's ~400px preview width — much wider than a typical
   wp-admin <select> — its background-repeat tiled the tiny chevron
   across the FULL width instead of showing once on the right (a wall
   of "⌄⌄⌄⌄⌄⌄⌄⌄" instead of a dropdown). Owning the whole background
   explicitly, with our own single right-aligned chevron matching this
   app's icon language instead of the browser default, fixes the actual
   bug and looks like a deliberately-styled control instead of one that
   merely stopped being broken. */
.fc-canvas-field-body select {
	appearance: none;
	-webkit-appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23909399' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 10px center;
	background-size: 14px 14px;
	padding-right: 30px;
}
.fc-canvas-field-body textarea {
	min-height: 60px;
	resize: none;
}
.fc-preview-choices {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.fc-preview-inline {
	display: flex;
	align-items: center;
	gap: 6px;
	font-size: 13px;
	color: var(--fc-text);
	font-weight: 400;
}
.fc-preview-inline input {
	width: auto;
	accent-color: var(--fc-accent);
}
/* Same dead-zone fix as the text/select/textarea previews above — these
   checkbox/radio previews are disabled too. */
.fc-preview-inline input:disabled,
.fc-preview-standalone-checkbox input:disabled {
	pointer-events: none;
}
/* The standalone Checkbox field — see FieldPreview.js's doc comment on
   why it needs this instead of just inheriting .fc-preview-inline's
   lighter, option-row-appropriate weight. Icon+bold matches every
   sibling card's own label treatment. */
.fc-preview-standalone-checkbox {
	font-weight: 600;
	color: var(--fc-text);
}
.fc-preview-standalone-checkbox input {
	width: 15px;
	height: 15px;
	accent-color: var(--fc-accent);
}
.fc-preview-standalone-checkbox .dashicons {
	font-size: 14px;
	width: 14px;
	height: 14px;
	color: var(--fc-accent);
	opacity: 0.75;
}
/* Terms/GDPR/Consent — the agreement text is often a full sentence, so
   unlike a short checkbox label it needs top-alignment with the checkbox
   and to actually wrap instead of forcing the row wider than the canvas. */
.fc-preview-consent {
	align-items: flex-start !important;
}
.fc-preview-consent input {
	margin-top: 2px;
	flex-shrink: 0;
}
.fc-preview-consent span {
	flex: 1;
}
.fc-preview-html {
	font-size: 13px;
	color: #4b4c4d;
	border: 1px dashed var(--fc-border);
	border-radius: 5px;
	padding: 8px 10px;
	background: var(--fc-bg);
}
.fc-preview-empty {
	color: var(--fc-muted-light);
	font-style: italic;
}
.fc-preview-hidden {
	font-size: 12px;
	color: var(--fc-muted-light);
	font-style: italic;
}
.fc-preview-section h3 {
	margin: 0 0 2px;
	font-size: 15px;
	color: var(--fc-text);
}
.fc-preview-section p {
	margin: 0;
	font-size: 12px;
	color: var(--fc-muted);
}
.fc-preview-pagebreak {
	font-size: 12px;
	font-weight: 600;
	color: var(--fc-accent-dark);
	text-transform: uppercase;
	letter-spacing: 0.03em;
	padding: 4px 0;
	border-top: 1px dashed var(--fc-border);
	border-bottom: 1px dashed var(--fc-border);
}
.fc-preview-payment-item {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 8px 10px;
	background: var(--fc-bg);
	border: 1px solid var(--fc-border);
	border-radius: 5px;
	font-size: 13px;
}
.fc-preview-payment-summary {
	padding: 8px 10px;
	background: var(--fc-accent-soft);
	border-radius: 5px;
	font-size: 13px;
}
.fc-preview-note {
	color: var(--fc-muted);
	font-size: 11px;
	font-style: italic;
}
.fc-preview-payment-item-wrap {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
/* Real, actionable warning (not the muted "just FYI" tone of .fc-preview-note)
   — shown when Payment Item/Custom Amount has no Payment Method field
   anywhere on the form, so the total it builds up is never actually
   charged. Mirrors the admin-only notices class-shortcode.php already
   prints for a missing Stripe/PayPal key, surfaced here while still
   building instead of only after the form is published. */
.fc-preview-note-warning {
	display: flex;
	align-items: flex-start;
	gap: 6px;
	color: #8a6d2f;
	background: #fcf3d9;
	border: 1px solid #f0d78c;
	border-radius: 5px;
	padding: 7px 9px;
	font-size: 11.5px;
	font-style: normal;
	line-height: 1.4;
}
.fc-preview-note-warning .dashicons {
	flex-shrink: 0;
	font-size: 14px;
	width: 14px;
	height: 14px;
	margin-top: 1px;
	color: #c99a2e;
}
.fc-preview-payment-method,
.fc-preview-captcha {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 14px 10px;
	border: 1px dashed var(--fc-border);
	border-radius: 5px;
	font-size: 13px;
	color: var(--fc-muted);
	text-align: center;
}
.fc-preview-payment-method .dashicons,
.fc-preview-captcha .dashicons {
	font-size: 16px;
	width: 16px;
	height: 16px;
	color: var(--fc-muted-light);
}
/* Upload dropzone preview — a real icon + primary instruction + a
   secondary line for the allowed-extensions detail, instead of one
   dense technical-looking line ("File upload — jpg,jpeg,png,pdf,doc,
   docx") that read like debug output rather than a polished field
   preview. */
.fc-preview-upload {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 14px 14px;
	border: 1.5px dashed var(--fc-border);
	border-radius: var(--fc-radius-md);
	background: var(--fc-bg);
}
.fc-preview-upload > .dashicons {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	border-radius: var(--fc-radius-md);
	background: var(--fc-accent-soft);
	color: var(--fc-accent);
	font-size: 18px;
}
.fc-preview-upload-text {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}
.fc-preview-upload-text strong {
	font-size: 13px;
	font-weight: 600;
	color: var(--fc-text);
}
.fc-preview-upload-text span {
	font-size: 11.5px;
	color: var(--fc-muted);
}
.fc-preview-color {
	display: flex;
	align-items: center;
	gap: 10px;
}
.fc-preview-color input[type="color"] {
	width: 40px;
	height: 32px;
	padding: 2px;
	border: 1px solid var(--fc-border);
	border-radius: 6px;
	cursor: default;
}
.fc-preview-color span {
	font-size: 13px;
	color: var(--fc-muted);
	font-family: monospace;
}
.fc-preview-signature {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
/* "Clear" moved inside the pad's own top-right corner (was a separate
   line of text below it) — a real signature widget's clear action lives
   on the pad itself, not floating disconnected underneath it. */
.fc-preview-signature-pad {
	position: relative;
	width: 100%;
	height: 90px;
	border: 1px dashed var(--fc-border);
	border-radius: 6px;
	background: var(--fc-bg) repeating-linear-gradient(to bottom, transparent, transparent 87px, var(--fc-border) 88px);
	display: flex;
	align-items: flex-end;
	justify-content: center;
	padding-bottom: 8px;
	font-size: 12px;
	color: #a8adb5;
	font-style: italic;
}
.fc-preview-signature-clear {
	position: absolute;
	top: 8px;
	right: 10px;
	font-size: 11px;
	font-weight: 600;
	font-style: normal;
	color: var(--fc-muted);
	background: var(--fc-surface);
	border: 1px solid var(--fc-border);
	border-radius: var(--fc-radius-full);
	padding: 2px 9px;
}
.fc-preview-range {
	padding: 4px 2px;
}
.fc-preview-range input[type="range"] {
	width: 100%;
}
.fc-preview-range-bounds {
	display: flex;
	justify-content: space-between;
	font-size: 11px;
	color: var(--fc-muted);
	margin-top: 2px;
}
.fc-preview-stars {
	display: flex;
	gap: 4px;
	font-size: 22px;
	color: var(--fc-muted-light);
}
.fc-preview-nps-scale {
	display: flex;
	justify-content: space-between;
	gap: 2px;
	font-size: 12px;
	color: var(--fc-muted);
}
.fc-preview-nps-scale span {
	flex: 1;
	text-align: center;
	border: 1px solid var(--fc-border);
	border-radius: 3px;
	padding: 4px 0;
}
.fc-preview-nps-labels {
	display: flex;
	justify-content: space-between;
	font-size: 11px;
	color: var(--fc-muted);
	margin-top: 4px;
}
.fc-preview-address {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.fc-preview-address-row {
	display: flex;
	gap: 6px;
}
.fc-preview-address-row input {
	flex: 1;
	min-width: 0;
}
/* Social Media Links canvas preview — rebuilt from six fixed platforms to
   a plain, unlimited add/remove list of URLs (see FieldPreview.js and
   class-shortcode.php's render_social_links_field()); this is just the
   static "what it'll look like" mockup every other field preview here
   uses, not the real interactive Add/Remove. */
.fc-preview-social-links {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.fc-preview-social-links input {
	width: 100%;
	box-sizing: border-box;
}

/* Milestone 5B — Toggle field preview. */
.fc-preview-toggle {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	cursor: default;
}
.fc-preview-toggle input {
	position: absolute;
	opacity: 0;
	pointer-events: none;
}
.fc-preview-toggle-track {
	display: inline-block;
	width: 34px;
	height: 20px;
	border-radius: 999px;
	background: var(--fc-border);
	position: relative;
	flex-shrink: 0;
}
.fc-preview-toggle input:checked + .fc-preview-toggle-track {
	background: var(--fc-accent);
}
.fc-preview-toggle-thumb {
	position: absolute;
	top: 2px;
	left: 2px;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
	transition: left 0.15s ease;
}
.fc-preview-toggle input:checked + .fc-preview-toggle-track .fc-preview-toggle-thumb {
	left: 16px;
}
.fc-preview-toggle-label {
	font-size: 13px;
	color: var(--fc-muted);
}

/* Milestone 5B — Image Choice field preview. */
.fc-preview-image-choice {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
	gap: 8px;
}
.fc-preview-image-choice-item {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
	padding: 8px;
	border: 1px solid var(--fc-border);
	border-radius: 6px;
	font-size: 11px;
	color: var(--fc-muted);
	text-align: center;
}
.fc-preview-image-choice-item input {
	position: absolute;
	opacity: 0;
	pointer-events: none;
}
.fc-preview-image-choice-thumb {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 48px;
	background: var(--fc-bg);
	border-radius: 4px;
	overflow: hidden;
	color: var(--fc-muted-light);
}
.fc-preview-image-choice-thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Milestone 5B — Rich Text settings-panel editor (FieldSettings.js's
   Rich Text section renders this instead of the plain textarea every
   other content-driven field type, e.g. Custom HTML, uses). */
.fc-richtext-editor {
	border: 1px solid var(--fc-border);
	border-radius: 6px;
	overflow: hidden;
	transition: border-color var(--fc-motion-fast) var(--fc-ease), box-shadow var(--fc-motion-fast) var(--fc-ease);
}
/* The textarea's own :focus outline is suppressed below (it would sit
   flush against this wrapper's border, an ugly double-edge) — this is
   the replacement focus indicator, same :focus-within-on-the-wrapper
   pattern already used by .fc-quick-add-search.
   Previously there was NO focus indicator at all when this suppression
   had nothing standing in for it — a real keyboard-accessibility gap. */
.fc-richtext-editor:focus-within {
	border-color: var(--fc-accent);
	box-shadow: 0 0 0 3px var(--fc-primary-50);
}
.fc-richtext-toolbar {
	display: flex;
	gap: 2px;
	padding: 4px;
	background: var(--fc-bg);
	border-bottom: 1px solid var(--fc-border);
}
.fc-richtext-toolbar button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	border: none;
	background: none;
	border-radius: var(--fc-radius-sm);
	cursor: pointer;
	font-size: 12px;
	color: var(--fc-text);
	transition: background var(--fc-motion-fast) var(--fc-ease), color var(--fc-motion-fast) var(--fc-ease);
}
.fc-richtext-toolbar button .dashicons {
	font-size: 14px;
	width: 14px;
	height: 14px;
}
.fc-richtext-toolbar button:hover {
	background: var(--fc-surface);
	color: var(--fc-accent-dark);
}
.fc-richtext-toolbar button:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--fc-primary-50);
}
.fc-richtext-textarea {
	width: 100%;
	border: none;
	padding: 8px 10px;
	font-family: monospace;
	font-size: 12px;
	resize: vertical;
	box-sizing: border-box;
}
.fc-richtext-textarea:focus {
	outline: none;
}

/* Conditional logic */
.fc-conditional {
	margin-top: 4px;
	padding-top: 12px;
	border-top: 1px solid var(--fc-border);
}
.fc-conditional-empty {
	font-size: 12px;
	color: var(--fc-muted);
	margin: 0;
}

/* Rule Builder — replaces the old flat ConditionalLogicEditor with a
   recursive editor driven directly by the engine's LogicNode schema (see
   logic/ui/RuleBuilder.js's header comment). */
.fc-logic-rule-builder {
	margin-top: 8px;
}
.fc-logic-summary {
	font-size: 12.5px;
	font-style: normal;
	font-weight: 500;
	line-height: 1.5;
	color: var(--fc-accent-dark);
	background: var(--fc-accent-soft);
	border: 1px solid var(--fc-primary-100);
	border-radius: var(--fcb-radius-control);
	padding: 10px 13px;
	margin: 0 0 14px;
	word-break: break-word;
}
.fc-logic-validation-list {
	margin: 0 0 14px;
	padding-left: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: 4px;
}
.fc-logic-error {
	display: block;
	font-size: 12px;
	font-weight: 500;
	color: var(--fc-danger);
	background: color-mix(in srgb, var(--fc-danger) 8%, transparent);
	border-radius: 6px;
	padding: 6px 10px;
}

.fc-logic-group {
	border: 1px solid var(--fcb-border-soft);
	border-radius: var(--fcb-radius-control);
	padding: 14px;
	margin-bottom: 12px;
	background: var(--fc-surface);
	box-shadow: var(--fcb-shadow-card);
}
.fc-logic-group.has-error {
	border-color: var(--fc-danger);
}
.fc-logic-group-nested {
	background: var(--fc-bg);
	margin-top: 8px;
}
.fc-logic-group.is-dragging {
	opacity: 0.5;
}
.fc-logic-group-head {
	display: flex;
	align-items: center;
	gap: 6px;
	font-size: 12px;
	color: var(--fc-muted);
	flex-wrap: wrap;
}
.fc-logic-group-label {
	white-space: nowrap;
}
/* Same disclosure-caret pattern as .fc-settings-caret — one glyph that
   rotates, not two glyphs swapped in JSX (which is what this used to do,
   with no CSS transition at all so the change was instant while the
   settings-panel equivalent smoothly rotates; see DESIGN_SYSTEM.md
   Slice 13). */
.fc-logic-collapse-caret {
	transition: transform var(--fc-motion-fast) var(--fc-ease);
}
.fc-logic-collapse-caret.is-open {
	transform: rotate(90deg);
}
.fc-logic-collapse-btn,
.fc-logic-drag-handle {
	border: none;
	background: none;
	cursor: pointer;
	color: var(--fc-muted);
	display: inline-flex;
	align-items: center;
	padding: 0;
}
/* Same dashicons-move glyph and reordering role as the canvas's own
   .fc-drag-handle, which explicitly sizes its icon to 14px — this one
   had no size override at all, so it rendered at the Dashicons-font
   default (~20px), visibly larger than its canvas counterpart for an
   identical "grip to drag" affordance (see DESIGN_SYSTEM.md Slice 13). */
.fc-logic-drag-handle {
	cursor: grab;
	font-size: 14px;
	width: 14px;
	height: 14px;
}
.fc-logic-not-toggle {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	font-size: 11px;
	font-weight: 700;
	color: var(--fc-danger);
	cursor: pointer;
}
.fc-logic-spacer {
	flex: 1;
}
.fc-logic-group-body {
	margin-top: 8px;
	padding-left: 8px;
	border-left: 2px solid var(--fc-border);
}

/* Real bug found during feature-parity verification, not just a fidelity
   nit: with source+field+operator+value selects AND four action buttons
   (reorder up/down, duplicate, remove — ChargeForms has more actions per
   row than the reference product's add/remove-only pair) all fighting for space as
   `flex:1; min-width:0` in the sidebar's ~340px width, the field/value
   selects were measured collapsing to ~20px — genuinely unreadable and
   unusable, not merely "a bit tight." flex-wrap lets controls flow onto a
   second line instead of being crushed below a usable size; a real
   min-width (not 0) is what makes that wrapping actually trigger. */
.fc-logic-condition {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-bottom: 8px;
	align-items: center;
}
.fc-logic-condition.is-dragging {
	opacity: 0.5;
}
/* White background matches the same the reference product-real-values fix already applied
   to the properties-panel inputs (element-variables.scss's white
   el-input__inner default, not a gray-at-rest treatment). Operator gets a
   narrower, roughly-fixed width instead of sharing equal flex with the
   field/value selects — matching the reference product's real editor.scss proportions
   (.condition-field/.condition-value: 30% each, .condition-operator: 85px
   fixed) rather than three equal-width controls, since operator labels
   ("equal", "not equal") never need as much room as a field name or value. */
.fc-logic-condition select,
.fc-logic-condition input {
	font-size: 12.5px;
	padding: 7px 9px;
	border: 1px solid var(--fcb-border-soft);
	border-radius: 6px;
	background: #fff;
	flex: 1 1 100px;
	min-width: 100px;
	transition: border-color 0.15s var(--fc-ease, ease), box-shadow 0.15s var(--fc-ease, ease), background 0.15s var(--fc-ease, ease);
}
.fc-logic-condition .fc-logic-operator-select {
	flex: 0 1 110px;
	min-width: 90px;
}
/* .fc-logic-action-row select, .fc-logic-sample-input input, and
   .fc-attr-row input previously had NO focus state at all (three
   keyboard-inaccessible controls); .fc-logic-condition's own ring was a
   2px variant, inconsistent with the 3px ring every other input in this
   file uses. Consolidated onto one 3px-ring rule covering all of them
   (see DESIGN_SYSTEM.md Slice 13). */
.fc-logic-condition select:focus,
.fc-logic-condition input:focus,
.fc-logic-action-row select:focus,
.fc-logic-sample-input input:focus,
.fc-attr-row input:focus {
	border-color: var(--fc-accent);
	box-shadow: 0 0 0 3px var(--fc-accent-soft);
	outline: none;
}

.fc-logic-group-actions {
	display: flex;
	gap: 6px;
	margin-top: 6px;
}
.fc-logic-empty {
	font-size: 12px;
	color: var(--fc-muted);
	margin: 0 0 6px;
}

.fc-logic-actions {
	margin-top: 10px;
	padding-top: 10px;
	border-top: 1px solid var(--fc-border);
}
.fc-logic-action-row {
	display: flex;
	gap: 4px;
	margin-bottom: 6px;
	align-items: center;
}
.fc-logic-action-row select {
	font-size: 12px;
	padding: 4px 6px;
	border: 1px solid var(--fc-border);
	border-radius: 4px;
	flex: 1;
	min-width: 0;
}

/* Live Preview / Rule Debugger */
.fc-logic-live-preview,
.fc-logic-inspector {
	margin-top: 12px;
	padding-top: 10px;
	border-top: 1px solid var(--fc-border);
}
.fc-logic-sample-inputs {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-bottom: 8px;
}
.fc-logic-sample-input {
	display: flex;
	flex-direction: column;
	gap: 2px;
	font-size: 11px;
	color: var(--fc-muted);
}
.fc-logic-sample-input input {
	font-size: 12px;
	padding: 4px 6px;
	border: 1px solid var(--fc-border);
	border-radius: 4px;
}
.fc-logic-result-banner {
	font-size: 12px;
	font-weight: 600;
	padding: 8px 10px;
	border-radius: 4px;
	margin-bottom: 8px;
}
.fc-logic-result-banner.is-pass {
	background: rgba(0, 163, 92, 0.1);
	color: #00743f;
}
.fc-logic-result-banner.is-fail {
	background: rgba(214, 54, 56, 0.1);
	color: var(--fc-danger);
}
.fc-logic-result-actions {
	font-weight: 400;
	opacity: 0.85;
}
.fc-logic-trace-tree {
	background: var(--fc-bg);
	border-radius: 4px;
	padding: 8px;
	font-size: 11px;
	max-height: 220px;
	overflow-y: auto;
}
.fc-logic-trace-node {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 2px 0;
}
.fc-logic-trace-badge {
	display: inline-block;
	font-size: 9px;
	font-weight: 800;
	letter-spacing: 0.04em;
	border-radius: 3px;
	padding: 1px 5px;
	flex-shrink: 0;
}
.fc-logic-trace-badge.is-pass {
	background: #00a35c;
	color: #fff;
}
.fc-logic-trace-badge.is-fail {
	background: var(--fc-danger);
	color: #fff;
}
.fc-logic-trace-label {
	word-break: break-word;
}
.fc-logic-duration {
	font-size: 10px;
	color: var(--fc-muted);
	margin: 6px 0 0;
}
.fc-logic-cycle-warning {
	color: var(--fc-danger) !important;
	font-weight: 600;
}

.fc-settings-row {
	display: block;
	margin-bottom: 18px;
}
/* Matches the .dc.html mockup's own field-settings label spec exactly
   (12px, muted #606266, weight 600) — a prior pass changed this to
   "the reference product's real .option-fields-section label" (14px, near-black, weight
   500), the wrong design authority per the project's own .dc.html-wins
   rule. */
.fc-settings-row span {
	display: block;
	margin-bottom: 5px;
	color: var(--fc-muted, #606266);
	font-size: 12px;
	font-weight: 600;
	line-height: 1;
}
/* Radius and resting background match Element UI's real defaults, which
   is what the reference product's settings panel actually renders (el-input__inner):
   $--border-radius-base: 4px (element-variables.scss), white background
   at rest — not the 8px radius / gray-until-focus treatment ChargeForms
   had, which reads as a visibly different, more "custom app" input
   style than the reference product's plainer Element UI look. */
.fc-settings-row input[type="text"],
.fc-settings-row input[type="number"],
.fc-settings-row textarea {
	width: 100%;
	border: 1px solid var(--fcb-border-soft);
	border-radius: 4px;
	padding: 11px 14px;
	font-size: 13.5px;
	background: #fff;
	box-sizing: border-box;
	transition: border-color var(--fc-motion-fast) var(--fc-ease), box-shadow var(--fc-motion-fast) var(--fc-ease), background var(--fc-motion-fast) var(--fc-ease);
}
.fc-settings-row input[type="text"]:hover,
.fc-settings-row input[type="number"]:hover,
.fc-settings-row textarea:hover {
	border-color: var(--fc-primary-100);
}
.fc-settings-row input[type="text"]:focus,
.fc-settings-row input[type="number"]:focus,
.fc-settings-row textarea:focus {
	border-color: var(--fc-accent);
	background: var(--fc-surface);
	box-shadow: 0 0 0 4px var(--fc-accent-soft);
	outline: none;
}
/* Was missing entirely — any settings-panel `<select>` (e.g. Math Field's
   Field A/operator/Field B row) fell back to fully unstyled OS-default
   chrome sitting directly beside these tokenized text inputs. No
   `width:100%` here on purpose: unlike the single-column inputs above,
   selects in this panel sometimes sit several-in-a-row (Math Field) and
   need their natural content width (see DESIGN_SYSTEM.md Slice 13). */
.fc-settings-row select {
	border: 1px solid var(--fcb-border-soft);
	border-radius: 4px;
	padding: 9px 12px;
	font-size: 13.5px;
	background: #fff;
	box-sizing: border-box;
	transition: border-color var(--fc-motion-fast) var(--fc-ease), box-shadow var(--fc-motion-fast) var(--fc-ease), background var(--fc-motion-fast) var(--fc-ease);
}
.fc-settings-row select:hover {
	border-color: var(--fc-primary-100);
}
.fc-settings-row select:focus {
	border-color: var(--fc-accent);
	background: var(--fc-surface);
	box-shadow: 0 0 0 4px var(--fc-accent-soft);
	outline: none;
}
.fc-settings-hint {
	margin: 4px 0 0;
	font-size: 11px;
	color: var(--fc-muted);
}
.fc-settings-required-message {
	margin-top: -6px;
	padding-left: 4px;
	border-left: 2px dotted var(--fc-border);
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.fc-settings-required-message input[type="text"]:disabled {
	background: var(--fc-bg);
	color: var(--fc-muted);
	cursor: not-allowed;
}
.fc-settings-row-inline {
	display: flex;
	align-items: center;
	gap: 10px;
	min-height: 28px;
}
/* A real switch, not a checkbox pretending to be one — pure CSS on the
   native input itself (appearance:none + a track/thumb built from
   ::before), so every existing boolean setting across the whole
   properties panel (Required/Read Only/Disabled/Locked/Hidden, Enable
   Conditional Logic, Rule Enabled, ...) gets it for free with no JSX
   changes anywhere. */
/* Sized to Element UI's el-switch--small (_el_customize.scss: 28x16
   track, 12x12 thumb) — the size the reference product actually uses for every boolean
   in its field settings panel. ChargeForms' previous 38x22/18x18 sizing
   was visibly chunkier than the reference product's more compact switches, and this
   control repeats on nearly every settings screen. */
/* Per explicit user request: identical to Global Settings' own toggle
   switch (.chargeforms-switch, assets/css/admin.css) — same 36x20 track /
   16x16 thumb / 2px inset / var(--fc-primary) checked color — rather than
   the Builder running its own distinct, smaller (28x16) switch design.
   Kept as a native <input type="checkbox"> styled via appearance:none
   (not Settings' hidden-checkbox-plus-sibling-spans markup) since that's
   what FieldSettings.js already renders and changing the JSX structure
   isn't needed to match the visual result. */
.fc-settings-row-inline input[type="checkbox"] {
	appearance: none;
	-webkit-appearance: none;
	position: relative;
	width: 36px;
	height: 20px;
	border-radius: var(--fc-radius-full);
	background: var(--fc-border);
	flex-shrink: 0;
	cursor: pointer;
	margin: 0;
	transition: background var(--fc-motion-fast) var(--fc-ease);
}
.fc-settings-row-inline input[type="checkbox"]::before {
	content: '';
	position: absolute;
	top: 2px;
	left: 2px;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
	transition: transform var(--fc-motion-fast) var(--fc-ease);
}
.fc-settings-row-inline input[type="checkbox"]:checked {
	background: var(--fc-primary);
}
.fc-settings-row-inline input[type="checkbox"]:checked::before {
	transform: translateX(16px);
}
.fc-settings-row-inline input[type="checkbox"]:hover {
	background: var(--fc-muted-light);
}
.fc-settings-row-inline input[type="checkbox"]:checked:hover {
	background: var(--fc-primary-dark);
}
.fc-settings-row-inline input[type="checkbox"]:focus-visible {
	outline: 2px solid var(--fc-primary);
	outline-offset: 2px;
}
.fc-settings-row-inline em {
	font-style: normal;
	color: var(--fc-muted);
	font-size: 11px;
}

/* Milestone 5 — Locked/Hidden, always-visible capability toggles above the
   collapsible sections (see FieldSettings.js). */
.fc-settings-capabilities {
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding: 12px 14px;
	margin-bottom: 18px;
	background: var(--fc-bg);
	border: 1px solid var(--fcb-border-soft);
	border-radius: var(--fcb-radius-control);
}
/* Real bug found live (user screenshot): Locked/Hidden's helper text
   wraps to a second line at this panel's width, and the generic
   `.fc-settings-row-inline { align-items: center }` was centering the
   switch against the FULL wrapped-text block's height — leaving it
   floating between the two lines instead of sitting flush with the
   first one, where the eye expects it. Scoped to just these two rows
   (not every `.fc-settings-row-inline` in the panel) since every other
   boolean setting here — Required, Read Only, Enable Conditional
   Logic, ... — is a single line and already centers correctly. */
.fc-settings-capabilities .fc-settings-row-inline {
	align-items: flex-start;
}
.fc-settings-capabilities .fc-settings-row-inline input[type="checkbox"] {
	margin-top: 2px;
}

/* Custom Attributes editor rows (Developer settings). */
.fc-attr-row {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-bottom: 6px;
}
.fc-attr-row input {
	flex: 1;
	min-width: 0;
	border: 1px solid var(--fc-border);
	border-radius: 4px;
	padding: 6px 8px;
}
/* No hover/focus/transition existed at all for this one, despite being a
   destructive action (see DESIGN_SYSTEM.md Slice 13). */
.fc-attr-row-remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	flex-shrink: 0;
	border: 1px solid var(--fc-border);
	background: var(--fc-surface);
	color: var(--fc-danger, #e5484d);
	border-radius: var(--fc-radius-sm);
	cursor: pointer;
	transition: background var(--fc-motion-fast) var(--fc-ease), border-color var(--fc-motion-fast) var(--fc-ease);
}
.fc-attr-row-remove:hover {
	background: color-mix(in srgb, var(--fc-danger, #e5484d) 10%, var(--fc-surface));
	border-color: var(--fc-danger, #e5484d);
}
.fc-attr-row-remove:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--fc-primary-50);
}
/* Canonical "add a row" dashed button — was independently authored twice
   (.fc-attr-add and .fc-logic-add-btn, byte-identical rule sets) with
   neither having a hover/focus state; consolidated into one class here,
   .fc-logic-add-btn's old selector removed (see DESIGN_SYSTEM.md Slice
   13). */
.fc-attr-add {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	border: 1px dashed var(--fc-accent);
	background: var(--fc-surface);
	color: var(--fc-accent-dark);
	border-radius: var(--fc-radius-sm);
	padding: 4px 10px;
	font-size: 12px;
	font-weight: 600;
	cursor: pointer;
	transition: background var(--fc-motion-fast) var(--fc-ease), border-color var(--fc-motion-fast) var(--fc-ease);
}
.fc-attr-add:hover {
	background: var(--fc-accent-soft);
	border-color: var(--fc-accent-dark);
}
.fc-attr-add:focus-visible {
	outline: none;
	border-color: var(--fc-primary);
	box-shadow: 0 0 0 3px var(--fc-primary-50);
}

/* Button-group control (Label Placement) — a tactile row of toggle
   buttons instead of a plain <select>, matching how mature form
   builders present a small, fixed set of layout choices. */
.fc-btn-group {
	display: flex;
	border: 1px solid var(--fc-border);
	border-radius: 6px;
	overflow: hidden;
}
.fc-btn-group button {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	padding: 7px 4px;
	border: none;
	border-right: 1px solid var(--fc-border);
	background: var(--fc-surface);
	font-size: 10px;
	color: var(--fc-muted);
	cursor: pointer;
	transition: background var(--fc-motion-fast) var(--fc-ease), color var(--fc-motion-fast) var(--fc-ease);
}
.fc-btn-group button:last-child {
	border-right: none;
}
.fc-btn-group button .dashicons {
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 15px;
	width: 15px;
	height: 15px;
	line-height: 1;
	/* Without this, the icon rendered visibly darker than the label text
	   directly beneath it in the same button — a WordPress core admin
	   rule sets a default .dashicons color that won a specificity tie
	   against this button's own `color: var(--fc-muted)`, so the glyph
	   never actually inherited the button's text color the way it looked
	   like it should. Forcing currentColor makes the icon and label
	   always match, in every state (rest/hover/active) with no separate
	   color rule to keep in sync. */
	color: currentColor;
}
.fc-btn-group button:hover {
	background: var(--fc-accent-soft);
	color: var(--fc-accent-dark);
}
.fc-btn-group button.is-active {
	background: var(--fc-accent);
	color: #fff;
}
.fc-btn-group button:focus-visible {
	outline: none;
	box-shadow: inset 0 0 0 2px var(--fc-primary-50);
}
/* the reference product's real Label Placement control is plain-text segments, no icons
   (the plugin's internal reference-screenshot archive/builder-create-a-form--06.webp) — a flatter
   row than the icon-stacked default .fc-btn-group treatment. */
.fc-btn-group-plain button {
	flex-direction: row;
	padding: 8px 6px;
	font-size: 12px;
	font-weight: 500;
}

.fc-color-input-row {
	display: flex;
	align-items: center;
	gap: 8px;
}
.fc-color-input-row input[type="color"] {
	width: 40px;
	height: 32px;
	padding: 2px;
	border: 1px solid var(--fc-border);
	border-radius: 6px;
	cursor: pointer;
	flex-shrink: 0;
}
.fc-color-input-row input[type="text"] {
	flex: 1;
	font-family: monospace;
}

/* Matches the .dc.html mockup's own accordion spec: a flat, continuous
   list divided by hairline borders (#f0f0f1) — not individual white cards
   with gaps between them. A prior pass built this as "the reference product's real
   .option-fields-section" (white 8px-radius card per section, 12px gap),
   the wrong design authority per the project's own .dc.html-wins rule. */
.fc-settings-section {
	border-bottom: 1px solid #f0f0f1;
}
.fc-settings-section:last-child {
	border-bottom: none;
}
.fc-settings-section-toggle {
	display: flex;
	align-items: center;
	gap: 8px;
	width: 100%;
	text-align: left;
	background: none;
	border: none;
	padding: 13px 14px;
	font-size: 13px;
	font-weight: 600;
	color: #1e1f21;
	cursor: pointer;
	transition: color var(--fc-motion-fast) var(--fc-ease);
}
/* Active/open title turns accent-colored and bold, per the mockup's own
   titleStyle() (weight 700, color #6c4ef5 when open). */
.fc-settings-section.is-open .fc-settings-section-toggle {
	color: var(--fc-accent);
	font-weight: 700;
}
.fc-settings-section-toggle:hover {
	color: var(--fc-accent-dark);
}
.fc-settings-section-toggle:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--fc-primary-50);
}
/* Every other icon-leading label in the builder (palette items, canvas
   field labels, toolbar buttons) uses a Dashicon at a consistent weight
   — this panel's section headers were plain uppercase text with a
   literal "▸" character for the disclosure triangle, the one place in
   the builder that broke from that icon-forward language entirely (and
   the "▸" glyph had no aria-hidden, so screen readers announced "black
   right-pointing small triangle" before every section title). */
.fc-settings-section-icon {
	flex-shrink: 0;
	font-size: 14px;
	width: 14px;
	height: 14px;
	color: var(--fc-muted-light);
}
.fc-settings-section-title {
	flex: 1;
}
.fc-settings-caret {
	display: inline-flex;
	flex-shrink: 0;
	font-size: 13px;
	width: 13px;
	height: 13px;
	color: var(--fc-muted-light);
	transition: transform var(--fc-motion-fast) var(--fc-ease);
}
.fc-settings-caret.is-open {
	transform: rotate(180deg);
}
.fc-settings-section-body {
	padding: 0 14px 16px;
}

.fc-entries-link {
	font-size: 12px;
	color: var(--fc-accent);
	text-decoration: none;
	padding: 4px 8px;
	border-left: 1px solid var(--fc-border);
}
.fc-entries-link:hover {
	text-decoration: underline;
}

/* Builder shell — this block redeclares
   .chargeforms-app-root/.fc-app/.fc-topbar/.fc-palette/.fc-canvas/etc.
   (23 selectors also declared near the top of this file), and being
   later in the cascade, THIS is the version that actually renders for
   any property both blocks set. It had its own separate hardcoded accent
   color (#1684fc) instead of the shared --fc-primary tokens, so the
   earlier token-unification fix further up this file was silently having
   no visible effect — fixed at the actual point of truth here. Milestone 4
   went further and fixed the token-VALUE drift too (.chargeforms-app-root
   above used to declare its own --fc-muted/--fc-border/--fc-bg as
   independently-chosen colors close to, but not identical to, the shared
   ones — now aliased/inherited, see that block's own comment).
   Remaining, lower-priority: the ~500 lines below still duplicate ~23
   selectors already defined at the top of this file (a redesign pass
   appended without removing the original) — a code-cleanliness issue at
   this point (cascade order already makes this block consistently win,
   so it's not a live visual bug the way the color drift was). Real future
   work, tracked in docs/DESIGN_SYSTEM.md — not attempted blind here, since
   safely merging ~23 overlapping rulesets one-by-one with visual QA at
   each step is a larger, standalone task than this pass's token work. */
.chargeforms-app-root {
	--fc-accent: var(--fc-primary, #6c4ef5);
	--fc-accent-dark: var(--fc-primary-dark, #5636d6);
	--fc-accent-soft: var(--fc-primary-soft, #f2effe);
	margin: 0;
	font-size: 14px;
	font-family: var(--fc-font, "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif);
	/* Milestone 4 design-system consolidation — this block used to
	   independently declare --fc-ink/--fc-muted/--fc-border/--fc-bg/
	   --fc-panel/--fc-soft-panel as their OWN hardcoded colors (a 4th
	   distinct "muted gray" at #64748b, a border/background subtly
	   different from the shared ones) — exactly the "second design
	   language living next to the real one" problem this file's own header
	   comment already describes fixing once, that had crept back in via
	   this later-appended block (see the TODO that used to sit here).
	   .chargeforms-app-root always renders inside .chargeforms-wrap (see
	   class-builder-page.php), so --fc-muted/--fc-border/--fc-bg need no
	   redeclaration at all — they already inherit the real shared values.
	   --fc-ink/--fc-panel/--fc-soft-panel are kept only because ~500 lines
	   below reference those names specifically; each is now an ALIAS onto
	   its real shared-token equivalent instead of a second, drifted value. */
	--fc-ink: var(--fc-text);
	--fc-panel: var(--fc-surface);
	--fc-soft-panel: var(--fc-bg);
}

/* Was declaring background/border/border-radius/padding/box-shadow
   TWICE in this one block (a plain first pass, then a gradient/token
   override a few lines below it in the same ruleset) — the first set was
   dead code, CSS only ever applied the second. Removed the dead
   declarations rather than the real ones (see DESIGN_SYSTEM.md Slice 13). */
.fc-app {
	/* Matches the rest of the plugin's admin screens (.chargeforms-wrap in
	   design-tokens-refine.css) — fully white canvas by explicit request,
	   not the gray app-shell background this used to have. */
	background: #fff;
	border: 0;
	border-radius: 0;
	padding: 0;
	overflow: hidden;
	color: var(--fc-text);
	box-shadow: none;
}

/* Height: pixel-measured off the plugin's internal reference-screenshot archive/
   builder-user-interface--04.webp — the topbar's bottom border sits at a
   consistent y=92-93px across two independent x-samples in that
   2560px-wide capture. Assuming a standard 2x retina doc-screenshot
   capture (consistent with how compact the rest of that reference reads),
   that's ~46px CSS. Vertical padding cut from 14px to 6px to land close
   to that — the 40px-tall Save button/icon-buttons are left as the
   height floor rather than shrinking the controls themselves. */
.fc-topbar {
	display: grid;
	grid-template-columns: minmax(320px, 1fr) auto auto;
	gap: 10px;
	align-items: center;
	margin: 0;
	height: 60px;
	padding: 0 14px;
	background: #fff;
	border-bottom: 1px solid #dadbdd;
}

.fc-topbar-main {
	display: flex;
	align-items: center;
	gap: 14px;
	min-width: 0;
}

.fc-back-link,
.fc-icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	border: 1px solid #dadbdd;
	background: #fff;
	border-radius: 7px;
	width: 32px;
	height: 32px;
	color: #606266;
	transition: color var(--fc-motion-fast) var(--fc-ease), border-color var(--fc-motion-fast) var(--fc-ease), background var(--fc-motion-fast) var(--fc-ease), box-shadow var(--fc-motion-fast) var(--fc-ease);
}
/* Every icon button carries a Dashicon at the same visual weight — mixing
   the font's default 20px with 16-18px SVG icons elsewhere in the
   toolbar (Preview's eye, the shortcode chip's clipboard) read as
   inconsistent sizing rather than a deliberate icon language. */
.fc-back-link .dashicons,
.fc-icon-btn .dashicons {
	font-size: 16px;
	width: 16px;
	height: 16px;
}

.fc-back-link:hover,
.fc-icon-btn:not(:disabled):hover {
	color: var(--fc-accent-dark);
	border-color: var(--fc-primary-100);
	background: var(--fc-accent-soft);
}
.fc-back-link:focus-visible,
.fc-icon-btn:focus-visible {
	outline: none;
	border-color: var(--fc-primary);
	box-shadow: 0 0 0 3px var(--fc-primary-50);
}
.fc-icon-btn.is-active {
	color: var(--fc-accent-dark);
	border-color: var(--fc-primary);
	background: var(--fc-accent-soft);
}

.fc-title-stack {
	display: grid;
	gap: 2px;
	min-width: 170px;
}

.fc-title-stack > span,
.fc-panel-kicker {
	color: var(--fc-muted);
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.fc-title-input {
	width: min(360px, 100%);
	font-size: 18px;
	font-weight: 700;
	color: var(--fc-text);
	padding: 3px 0;
	border: 1px solid transparent;
	background: transparent;
	border-radius: 0;
}

.fc-title-input:hover,
.fc-title-input:focus {
	border-color: transparent;
	background: transparent;
	box-shadow: inset 0 -2px 0 var(--fc-accent);
}

/* Plain underline tabs, not a segmented pill control — the reference product's
   Editor/Settings & Integrations/Entries row
   (the plugin's internal reference-screenshot archive/builder-create-a-form--03.webp) is flat text
   with a 2px underline on the active tab, no pill background or container
   chrome around the group at all. */
.fc-topbar-tabs {
	display: flex;
	align-items: center;
	gap: 24px;
}

.fc-topbar-tabs span,
.fc-topbar-tabs a {
	display: inline-flex;
	align-items: center;
	padding: 4px 0;
	border-bottom: 2px solid transparent;
	font-size: 13px;
	font-weight: 500;
	color: var(--fc-muted);
	text-decoration: none;
	white-space: nowrap;
	transition: color var(--fc-motion-fast) var(--fc-ease), border-color var(--fc-motion-fast) var(--fc-ease);
}
.fc-topbar-tabs a:hover {
	color: var(--fc-text);
}
.fc-topbar-tabs a:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--fc-primary-50);
}
.fc-topbar-tabs span.is-active {
	color: var(--fc-accent-dark);
	font-weight: 600;
	border-bottom-color: var(--fc-accent);
}

.fc-topbar-actions {
	display: flex;
	align-items: center;
	gap: 14px;
	justify-content: flex-end;
}

.fc-logic-budget {
	display: flex;
	gap: 12px;
	flex-wrap: wrap;
	margin: 8px 0 4px;
	color: #667085;
	font-size: 12px;
}

.fc-logic-budget span {
	padding: 4px 8px;
	border: 1px solid #e4e7ec;
	border-radius: 999px;
	background: #f8f9fc;
}

.fc-logic-budget-warning {
	margin: 6px 0 10px;
	color: #b54708;
	font-size: 12px;
}
/* Undo/Redo/History | Shortcode/Preview | Save/Fullscreen — three
   distinct clusters of controls, previously run together in one flat
   row with only an 8px gap telling them apart. A hairline divider
   between clusters (nothing inside one) turns "a lot of buttons" into
   three legible groups at a glance. */
.fc-topbar-action-group {
	display: flex;
	align-items: center;
	gap: 8px;
	padding-left: 14px;
	border-left: 1px solid var(--fc-border);
}
.fc-topbar-action-group:first-child {
	padding-left: 0;
	border-left: none;
}

.fc-preview-btn,
.fc-shortcode-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	border: 1px solid var(--fc-border);
	background: var(--fc-panel);
	color: var(--fc-accent-dark);
	border-radius: var(--fc-radius-md);
	min-height: 32px;
	padding: 0 11px;
	text-decoration: none;
	font-size: 12px;
	font-weight: 700;
	transition: border-color var(--fc-motion-fast) var(--fc-ease), background var(--fc-motion-fast) var(--fc-ease), color var(--fc-motion-fast) var(--fc-ease);
}
.fc-preview-btn:hover {
	border-color: var(--fc-primary-100);
	background: var(--fc-accent-soft);
}
.fc-preview-btn:focus-visible,
.fc-shortcode-btn:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px var(--fc-primary-50);
}
.fc-preview-btn .dashicons {
	font-size: 15px;
	width: 15px;
	height: 15px;
}

.fc-shortcode-btn {
	background: var(--fc-accent-soft);
	padding: 0 11px;
	font-size: 12px;
	font-family: var(--fc-font-mono, ui-monospace, "SFMono-Regular", Consolas, monospace);
	cursor: pointer;
	max-width: 190px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.fc-shortcode-btn .dashicons {
	flex-shrink: 0;
	font-size: 14px;
	width: 14px;
	height: 14px;
	opacity: 0.7;
}
.fc-shortcode-btn:hover {
	border-color: var(--fc-primary-100);
}
.fc-shortcode-btn.is-copied {
	background: var(--fc-success-soft, #e6f7f1);
	border-color: var(--fc-success);
	color: var(--fc-success);
}
.fc-shortcode-btn.is-copied .dashicons {
	opacity: 1;
	color: var(--fc-success);
}

/* Roadmap gap analysis: autosave previously read as a real, silent
   guarantee with no indication it's actually a local-browser-only
   safety net — this microcopy is the honest version of that claim,
   not a rework of the mechanism itself. */
.fc-autosave-hint {
	font-size: 11px;
	color: var(--fc-muted);
	white-space: nowrap;
	cursor: help;
}

.fc-save-btn {
	position: relative;
}
.fc-save-dirty-dot {
	position: absolute;
	top: -3px;
	right: -3px;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--fc-warning, #f0a020);
	border: 1.5px solid var(--fc-panel);
}

/* Three real zones — palette | canvas | properties — instead of the
   canvas sharing the page with a single right-hand slot that used to
   time-share Input Fields/Customize/History behind tabs. A permanently
   visible palette on the left (not one click away behind a tab) plus a
   properties panel that always reflects the current selection (no tab
   to remember to switch to) is the standard drag-and-drop form-builder
   layout — this is a structural fix, not a restyle. */
/* Two columns, not three — the reference product's real builder has no persistent field
   palette (the plugin's internal reference-screenshot archive/builder-create-a-form--03.webp):
   fields are inserted via the canvas's own "+" points (QuickAddMenu),
   so the canvas gets the space a permanent sidebar used to reserve. */
.fc-builder-grid {
	display: grid;
	grid-template-columns: minmax(560px, 1fr) minmax(320px, 380px);
	gap: 12px;
	align-items: start;
	padding: 12px;
	min-height: calc(100vh - 180px);
}
@media (max-width: 960px) {
	.fc-builder-grid {
		grid-template-columns: 1fr;
	}
}

.fc-canvas-column {
	min-width: 0;
}

.fc-side-panel {
	position: sticky;
	top: 48px;
	min-width: 0;
}

/* Responsive preview toggle — Desktop/Tablet/Mobile constrain the canvas
   to that breakpoint's width so a form's layout can actually be checked
   before publishing, not just assumed to "probably look fine." */
.fc-device-toggle {
	display: inline-flex;
	gap: 2px;
	margin-bottom: 12px;
	padding: 3px;
	background: #fff;
	border: 1px solid #dadbdd;
	border-radius: 8px;
	max-width: 100%;
}
/* Below ~480px the three labelled buttons no longer fit the canvas column
   and the control was measured clipping ("Deskt…" cut off at 390px). The
   icons alone are unambiguous (monitor/tablet/phone) and each button keeps
   its `title` for a tooltip, so dropping the text is lossless here rather
   than letting the control overflow its container. */
@media (max-width: 480px) {
	.fc-device-toggle-label {
		display: none;
	}
	.fc-device-toggle button {
		padding: 6px 10px;
	}
}
.fc-device-toggle button {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 6px 13px;
	border: none;
	border-radius: 6px;
	background: none;
	font-size: 12px;
	font-weight: 500;
	color: var(--fc-muted, #64748b);
	cursor: pointer;
	transition: background var(--fc-motion-fast) var(--fc-ease), color var(--fc-motion-fast) var(--fc-ease), box-shadow var(--fc-motion-fast) var(--fc-ease);
}
.fc-device-toggle button .dashicons {
	font-size: 15px;
	width: 15px;
	height: 15px;
}
.fc-device-toggle button:hover {
	color: var(--fc-text);
}
.fc-device-toggle button.is-active {
	background: #6c4ef5;
	color: #fff;
	font-weight: 600;
	box-shadow: none;
}
.fc-device-toggle button:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--fc-primary-50);
}

.fc-canvas-frame {
	transition: max-width var(--fc-motion-slow) var(--fc-ease);
}
.fc-canvas-frame.is-desktop,
.fc-canvas-frame.is-tablet,
.fc-canvas-frame.is-mobile {
	max-width: var(--fc-preview-width);
	margin: 0 auto;
}
.fc-canvas-frame.is-tablet .fc-canvas,
.fc-canvas-frame.is-mobile .fc-canvas {
	border: 1px solid var(--fc-border);
	box-shadow: var(--fc-shadow-md);
}

.fc-canvas {
	background: var(--fc-surface);
	border: 1px solid var(--fcb-border-soft);
	border-radius: var(--fcb-radius-card);
	padding: 12px;
	min-height: 560px;
	box-shadow: var(--fcb-shadow-panel);
}
/* Neutral gray, not another white card — the reference product's sidebar (styles/_var.scss
   $gray: #f5f5f5) is the gray page the white .option-fields-section cards
   sit on top of; a white outer panel around white section-cards would
   erase the card separation entirely. Lives on .fc-side-panel-body (the
   tab bar's content area — see SidePanelTabs.js), not .fc-settings
   directly, since all three tabs (fields/customize/history) share one
   card, not just the customize tab. */
/* Matches the .dc.html mockup's own tabStyle() spec for this panel:
   underline tabs (2px bottom border, accent text/border when active), not
   a segmented-fill control — a prior pass replaced this with "the reference product's
   real .nav-tab-list" (solid gray fill for the active tab), the wrong
   design authority per the project's own .dc.html-wins rule. Still
   sticky/equal-width, which the mockup doesn't contradict. */
.fc-side-panel-tabs {
	display: flex;
	flex-wrap: wrap;
	position: sticky;
	top: 0;
	z-index: 5;
	margin: 0;
	padding: 0;
	list-style: none;
	border-radius: var(--fcb-radius-card) var(--fcb-radius-card) 0 0;
	overflow: hidden;
}
.fc-side-panel-tabs li {
	flex: 1;
	margin: 0;
}
.fc-side-panel-tabs button {
	display: block;
	width: 100%;
	padding: 13px 6px;
	border: none;
	border-bottom: 2px solid transparent;
	background: #fafafa;
	color: var(--fc-muted, #606266);
	font-size: 12.5px;
	font-weight: 500;
	text-align: center;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	cursor: pointer;
}
.fc-side-panel-tabs li.is-active button {
	background: #fff;
	border-bottom-color: var(--fc-accent);
	color: var(--fc-accent);
	font-weight: 700;
}
.fc-side-panel-body {
	background: var(--fc-bg, #ffffff);
	border: 1px solid var(--fcb-border-soft);
	border-top: none;
	border-radius: 0 0 var(--fcb-radius-card) var(--fcb-radius-card);
	padding: 12px;
	min-height: 560px;
	box-shadow: var(--fcb-shadow-panel);
}

/* History — a toolbar popover now (Toolbar.js), not a permanent tab
   sharing space with Properties; see the History icon next to Undo/Redo. */
.fc-history-popover-anchor {
	position: relative;
}
.fc-history-popover {
	position: absolute;
	top: calc(100% + 8px);
	left: 0;
	z-index: 50;
	width: 312px;
	max-height: 380px;
	overflow-y: auto;
	background: var(--fc-surface);
	border: 1px solid var(--fcb-border-soft);
	border-radius: 14px;
	box-shadow: 0 4px 12px rgba(15, 23, 42, 0.06), 0 24px 48px -12px rgba(15, 23, 42, 0.20);
	padding: 16px;
	animation: fc-quick-add-in var(--fc-motion-base) var(--fc-ease);
}
.fc-history-head h3 {
	margin: 0 0 4px;
	font-size: 13px;
}
.fc-history-head p {
	margin: 0 0 10px;
	color: var(--fc-muted);
	font-size: 12px;
	line-height: 1.4;
}
.fc-history-list {
	list-style: none;
	margin: 12px 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.fc-history-list button {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	text-align: left;
	padding: 10px 11px;
	border: none;
	background: none;
	border-radius: var(--fcb-radius-control);
	cursor: pointer;
	font-size: 13px;
	transition: background var(--fc-motion-fast) var(--fc-ease);
}
.fc-history-list button:hover {
	background: var(--fc-primary-50);
}
.fc-history-list button.is-current {
	background: var(--fc-primary-50);
	box-shadow: inset 3px 0 0 var(--fc-primary);
	font-weight: 600;
}
.fc-history-dot {
	width: 6px;
	height: 6px;
	border-radius: var(--fc-radius-circle);
	background: var(--fc-border);
	flex-shrink: 0;
}
.fc-history-list button.is-current .fc-history-dot {
	background: var(--fc-accent, #6c4ef5);
}
.fc-history-label { flex: 1; }
.fc-history-meta { color: var(--fc-muted, var(--fc-muted)); font-size: 12px; }

.fc-title-display {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	background: none;
	border: none;
	cursor: pointer;
	padding: 4px 6px;
	border-radius: 6px;
	max-width: 220px;
}
.fc-title-display:hover {
	/* Decoupled from --fc-bg (now pure white — see its own definition
	   comment): this needs to stay a visible hover tint distinct from the
	   surrounding white surface, not track the page background color. */
	background: var(--fc-bg-soft, #f5f7fa);
}
.fc-title-display .fc-title-text {
	font-size: 15px;
	font-weight: 600;
	color: var(--fc-text);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.fc-title-display .dashicons {
	font-size: 15px;
	width: 15px;
	height: 15px;
	color: var(--fc-muted, var(--fc-muted));
	flex-shrink: 0;
}

/* z-index stays a literal 100000, NOT the documented --fcb-z-modal (1000)
   token — .fc-app.is-fullscreen also hardcodes 100000 (line ~22), and
   this modal has to reliably render above that fullscreen app shell.
   Swapping to the token as-is would put the modal BEHIND fullscreen mode,
   a real regression; reconciling the two hardcoded 100000s onto one
   proper token is real work of its own, flagged in DESIGN_SYSTEM.md
   Slice 13 rather than done as an unverified swap here. */
.fc-modal-overlay {
	position: fixed;
	inset: 0;
	background: rgba(20, 21, 23, 0.55);
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	animation: fc-modal-overlay-in var(--fc-motion-fast) var(--fc-ease);
}
@keyframes fc-modal-overlay-in {
	from { opacity: 0; }
	to { opacity: 1; }
}
.fc-modal {
	width: 100%;
	max-width: 460px;
	/* Same portal-scoping bug as .fc-quick-add/.fc-context-menu above —
	   FieldBrowser.js's Pro-lock modal also portals to document.body,
	   outside where --fc-surface is actually defined. */
	background: var(--fc-surface, #ffffff);
	border-radius: 18px;
	box-shadow: 0 4px 12px rgba(15, 23, 42, 0.06), 0 32px 64px -12px rgba(15, 23, 42, 0.28);
	padding: 32px;
	animation: fc-quick-add-in var(--fc-motion-base) var(--fc-ease);
}
.fc-modal-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 22px;
}
.fc-modal-head h2 {
	margin: 0;
	font-size: 19px;
	font-weight: 700;
	letter-spacing: -0.01em;
	color: var(--fcb-ink);
}
.fc-modal-field {
	display: block;
	margin-bottom: 26px;
}
.fc-modal-field span {
	display: block;
	font-size: 12.5px;
	font-weight: 600;
	color: var(--fc-muted, var(--fc-muted));
	margin-bottom: 7px;
}
.fc-modal-field input {
	width: 100%;
	padding: 11px 14px;
	border: 1px solid var(--fcb-border-soft);
	border-radius: var(--fcb-radius-control);
	background: var(--fc-bg);
	font-size: 14px;
	box-sizing: border-box;
	transition: border-color var(--fc-motion-fast) var(--fc-ease), box-shadow var(--fc-motion-fast) var(--fc-ease), background var(--fc-motion-fast) var(--fc-ease);
}
.fc-modal-field input:focus {
	border-color: var(--fc-accent);
	background: var(--fc-surface);
	box-shadow: 0 0 0 4px var(--fc-accent-soft);
	outline: none;
}
.fc-modal-actions {
	display: flex;
	justify-content: flex-end;
	gap: 10px;
}
/* Matches the reference product's own "field disabled" modal (ItemDisabled.vue): centered
   lock icon, title in .fc-modal-head, description, disabled CTA — see
   FieldBrowser.js's ProFieldModal. */
.fc-pro-modal {
	max-width: 440px;
}
.fc-pro-modal-body {
	text-align: center;
}
.fc-pro-modal-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 64px;
	height: 64px;
	border-radius: 18px;
	background: #fcecc4;
	margin: 0 auto 18px;
}
.fc-pro-modal-icon .dashicons {
	font-size: 28px;
	width: 28px;
	height: 28px;
	color: #8a6d2f;
}
.fc-pro-modal-body p {
	margin: 0 auto 24px;
	max-width: 340px;
	font-size: 13.5px;
	line-height: 1.6;
	color: var(--fc-muted);
}

.fc-pro-modal-body h2 {
	margin: 0 0 8px;
	font-size: 19px;
	font-weight: 700;
	letter-spacing: -0.01em;
	color: #16181d;
}
.fc-pro-modal-footnote {
	margin: 16px 0 0;
	font-size: 11.5px;
	line-height: 1.5;
	color: #a8abb2;
}
.fc-pro-modal-actions {
	display: flex;
	gap: 9px;
	justify-content: center;
}
.fc-pro-modal-secondary {
	border: 1px solid #dadbdd;
	background: #fff;
	border-radius: 8px;
	padding: 11px 18px;
	font-size: 13.5px;
	font-weight: 600;
	color: #606266;
	cursor: pointer;
}
.fc-pro-modal-body .button-primary {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: auto;
	padding: 11px 20px;
	border-radius: 8px;
	font-size: 13.5px;
	font-weight: 600;
	/* Real bug found live: admin.css's violet .button-primary treatment
	   is scoped to `.chargeforms-wrap .button-primary` (a descendant
	   selector), but this modal portals to document.body — outside
	   .chargeforms-wrap's DOM subtree — so that selector never matches
	   here. The button fell back to WordPress core's native blue
	   .button-primary, the one CTA in the whole plugin that wasn't
	   violet. Same fix shape as the --fc-surface/--fcb-border-soft
	   portal bugs above, just for a selector match instead of a custom
	   property: repeat the same treatment explicitly, scoped to this
	   modal specifically rather than depending on .chargeforms-wrap. */
	background: var(--fc-primary, #6c4ef5);
	border-color: var(--fc-primary, #6c4ef5);
	color: #fff;
	box-shadow: none;
	text-shadow: none;
}
.fc-pro-modal-body .button-primary:hover:not(:disabled) {
	background: var(--fc-primary-dark, #5a3ee0);
	border-color: var(--fc-primary-dark, #5a3ee0);
	color: #fff;
}
.fc-pro-modal-body .button-primary:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

.fc-settings h3 {
	margin: 3px 0 6px;
	font-size: 18px;
	line-height: 1.25;
	color: var(--fc-text);
}

.fc-panel-copy,
.fc-settings-empty p {
	margin: 0 0 14px;
	color: var(--fc-muted);
	font-size: 13px;
	line-height: 1.45;
}

.fc-canvas {
	background:
		linear-gradient(90deg, rgba(26, 126, 251, 0.05) 1px, transparent 1px),
		linear-gradient(180deg, rgba(26, 126, 251, 0.05) 1px, transparent 1px),
		var(--fc-surface);
	background-size: 28px 28px;
}

/* Restored to match the .dc.html mockup's own "Start building your form"
   onboarding empty state (a real, deliberate illustration — icon chip,
   headline, description, two CTAs) — a prior pass replaced this with a
   bare dashed box reasoning from "the reference product's real empty-dropzone has no
   icon/title/hint," the wrong design authority per the project's own
   .dc.html-wins rule. */
.fc-canvas-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	border: 1.5px dashed #d9d0fd;
	border-radius: 14px;
	background: #fff;
	padding: 80px 40px;
	max-width: 520px;
	margin: 0 auto;
}
/* Visually hidden — the real InsertPoint/QuickAddMenu still lives here so
   "Add your first field" (which calls setInsertMenuIndex(0)) has a real
   popover to open and anchor to, not a decorative look-alike. */
.fc-canvas-empty-insert-anchor {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
}
.fc-canvas-empty-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 64px;
	height: 64px;
	border-radius: 18px;
	background: var(--fc-accent-soft);
	color: var(--fc-accent);
	margin-bottom: 20px;
}
.fc-canvas-empty-title {
	font-size: 18px;
	font-weight: 700;
	color: #16181d;
	margin-bottom: 9px;
}
.fc-canvas-empty-desc {
	font-size: 13.5px;
	color: var(--fc-muted);
	line-height: 1.6;
	max-width: 340px;
	margin: 0 auto 22px;
}
.fc-canvas-empty-actions {
	display: flex;
	gap: 9px;
	justify-content: center;
}
.fc-canvas-empty-btn-primary {
	background: var(--fc-accent);
	border: none;
	border-radius: 8px;
	padding: 11px 20px;
	font-size: 13.5px;
	font-weight: 600;
	color: #fff;
	cursor: pointer;
}
.fc-canvas-empty-btn-secondary {
	display: inline-block;
	border: 1px solid rgba(15, 23, 42, 0.08);
	background: #fff;
	border-radius: 8px;
	padding: 11px 18px;
	font-size: 13.5px;
	font-weight: 600;
	color: var(--fc-muted);
	cursor: pointer;
	text-decoration: none;
}
.fc-canvas-empty-btn-secondary:hover {
	color: var(--fc-text);
	text-decoration: none;
}
/* Dropping onto the canvas (empty or otherwise) — a real drop-target
   highlight so it's obvious where a palette-item drag will land, instead
   of only finding out after releasing the mouse. */
.fc-canvas.is-drop-target .fc-canvas-empty {
	border-color: var(--fc-accent);
	background: var(--fc-accent-soft);
}

/* Deliberately near-invisible at rest — a border + shadow + background on
   EVERY field, all the time, was the single biggest source of "this looks
   cluttered" (direct user feedback, compared side-by-side against the reference product
   Forms' own builder: their fields carry no card chrome at rest at all,
   just label + input on plain canvas; a container only appears on
   hover/selection). Keeping the same transparent left-border here (rather
   than removing the rule) means hover/active can still transition its
   color smoothly instead of a border suddenly appearing from nothing. */
.fc-canvas-field {
	position: relative;
	border: 1px solid transparent;
	border-left: 3px solid transparent;
	border-radius: 0;
	padding: 14px 24px 14px 22px;
	margin: 0 0 2px;
	min-height: 78px;
	cursor: pointer;
	background: none;
	box-shadow: none;
	transition: background var(--fc-motion-fast) var(--fc-ease), border-color var(--fc-motion-fast) var(--fc-ease), box-shadow var(--fc-motion-fast) var(--fc-ease), transform var(--fc-motion-fast) var(--fc-ease);
	animation: fc-field-insert var(--fc-motion-base) var(--fc-ease);
}
/* Plays once when a field's DOM node is actually inserted (a genuine
   add, or React mounting a fresh node) — NOT on drag-reorder (dnd-kit
   moves the existing node, it doesn't remount it) and not on Undo/Redo
   (RESTORE re-renders with the same field `id` as `key`, so React
   reuses the same DOM node rather than remounting it). A field that
   just appeared should read as "that's new," not just pop into
   existence with zero acknowledgment. */
@keyframes fc-field-insert {
	from { opacity: 0; transform: translateY(-6px) scale(0.98); }
	to { opacity: 1; transform: translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
	.fc-canvas-field {
		animation: none;
	}
}

/* Selected state matches the .dc.html mockup's own explicit spec (Builder
   canvas example field): 2px solid accent border on all sides, 7px
   radius, a light violet-tinted background (#f7f5ff), and a soft colored
   halo (box-shadow 0 0 0 4px #efeafe) — a prior pass replaced this with
   "the reference product's real panel.scss treatment" (flat black wash, left-border-only,
   no halo), the wrong design authority per the project's own rule that
   the .dc.html mockups always win over reasoning about a competitor's
   real source. */
.fc-canvas-field.is-active {
	background: #f7f5ff;
	border: 2px solid var(--fc-accent);
	border-radius: 7px;
	box-shadow: 0 0 0 4px #efeafe;
}

/* Milestone 5 — Locked/Hidden field-instance flags (FieldSettings.js's
   always-visible capability toggles). Locked disables the drag handle via
   useSortable's own `disabled` option (CanvasField.js); this is the
   matching visual treatment. Hidden fields stay fully visible/editable in
   the builder (they're still part of the form) but read as "won't show
   on the live form" via the dashed border + dimmed opacity. */
.fc-canvas-field.is-locked .fc-drag-handle {
	cursor: not-allowed;
	opacity: 0.4;
}
.fc-canvas-field.is-hidden-field {
	opacity: 0.6;
	border-style: dashed;
}
.fc-field-flag {
	font-size: 13px;
	width: 13px;
	height: 13px;
	color: var(--fc-muted);
	margin-left: 4px;
	vertical-align: text-bottom;
}

/* dnd-kit sortable drag state — the row being dragged fades and floats
   above everything else (elevated shadow), while the DragOverlay (see
   fc-drag-ghost below) renders the actual "held" copy that follows the
   cursor/finger, matching how modern drag-and-drop UIs (Notion, Trello,
   Linear) all separate "the gap it left behind" from "the thing you're
   holding" instead of dragging the real DOM node around directly. */
.fc-canvas-field.is-dragging {
	opacity: 0.4;
	box-shadow: 0 16px 32px rgba(15, 23, 42, 0.12);
	z-index: 2;
}

/* The floating ghost DragOverlay renders while dragging (see App.js) — a
   palette-item icon+label chip, or the field's own label when reordering. */
.fc-drag-ghost {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 10px 16px;
	background: var(--fc-surface);
	border: 1px solid var(--fc-accent);
	border-radius: 8px;
	box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18), 0 0 0 3px rgba(26, 126, 251, 0.12);
	font-size: 13px;
	font-weight: 600;
	color: var(--fc-text);
	cursor: grabbing;
}
.fc-drag-ghost .dashicons {
	color: var(--fc-accent);
	font-size: 16px;
	width: 16px;
	height: 16px;
}

/* Small corner grip — drag handle + (containers only) Add Row/Add Column.
   Everything else (Duplicate/Delete/Copy/Paste/Settings) lives in the
   centered dark FloatingToolbar instead; this used to duplicate those same
   actions in a second toolbar stacked at the same position, which is the
   "two toolbars" visual bug this comment now documents having removed. */
.fc-canvas-field-toolbar {
	position: absolute;
	top: -14px;
	left: 14px;
	display: flex;
	align-items: center;
	gap: 6px;
	background: var(--fc-surface);
	border: 1px solid var(--fcb-border-soft);
	border-radius: 8px;
	padding: 4px 8px;
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--fc-motion-fast, 0.12s) ease;
	box-shadow: var(--fcb-shadow-card);
	z-index: 1;
}

.fc-settings-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	color: var(--fc-muted);
	padding: 48px 16px;
}
.fc-settings-empty p {
	margin: 0;
	font-size: 13px;
	max-width: 220px;
}
.fc-empty-state-list {
	display: grid;
	gap: 10px;
	margin-top: 18px;
}

.fc-empty-state-list span {
	display: block;
	background: var(--fc-soft-panel);
	border: 1px solid var(--fc-border);
	border-radius: 7px;
	padding: 10px;
	font-size: 12px;
	line-height: 1.4;
	color: var(--fc-muted);
}

.fc-back-to-fields {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	border: none;
	background: none;
	color: var(--fc-accent-dark);
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
	padding: 6px 0 10px;
	width: 100%;
	justify-content: flex-start;
	background: var(--fc-soft-panel);
	border: 1px solid var(--fc-border);
	border-radius: 7px;
	padding: 9px 10px;
	margin-bottom: 10px;
}

/* App skeleton — replaces the bare spinner+text for the initial "fetching
   this form's data" load (App.js, `status === 'loading'`). A skeleton
   communicates the SHAPE of what's arriving (a real perceived-performance
   win over a spinner, which only communicates "something is happening"),
   built from the exact same tokens the real shell after it renders with
   (--fcb-topbar-height, --fcb-side-panel-width) so there's no visible
   jump in proportions the instant real content replaces it. Reuses the
   plugin-wide shimmer construction already defined for the Forms/Entries
   screens (assets/css/design-tokens-screens.css's `.chargeforms-skeleton-
   row`/`@keyframes chargeforms-shimmer`) rather than inventing a second
   shimmer animation — that rule was defined but had no actual consumer
   anywhere in the codebase (grepped) until this. */
.fc-app-skeleton {
	display: flex;
	flex-direction: column;
	height: 100%;
}
.fc-skeleton-topbar {
	height: var(--fcb-topbar-height);
	flex-shrink: 0;
	display: flex;
	align-items: center;
	gap: var(--fc-space-3);
	padding: 0 var(--fc-space-6);
	border-bottom: 1px solid var(--fcb-border-soft);
	background: var(--fc-surface);
}
.fc-skeleton-block {
	background: linear-gradient(90deg, var(--fc-bg) 25%, var(--fc-surface) 50%, var(--fc-bg) 75%);
	background-size: 200% 100%;
	animation: fc-shimmer 1.2s ease-in-out infinite;
	border-radius: var(--fc-radius-md);
}
.fc-skeleton-topbar .fc-skeleton-block:first-child {
	width: 28px;
	height: 28px;
	border-radius: var(--fc-radius-circle);
}
.fc-skeleton-topbar .fc-skeleton-block:nth-child(2) {
	width: 160px;
	height: 16px;
}
.fc-skeleton-topbar .fc-skeleton-block:last-child {
	width: 92px;
	height: 32px;
	margin-left: auto;
	border-radius: var(--fc-radius-md);
}
.fc-skeleton-body {
	flex: 1;
	display: flex;
	gap: var(--fc-space-6);
	padding: var(--fc-space-6);
	overflow: hidden;
}
.fc-skeleton-canvas {
	flex: 1;
	display: flex;
	flex-direction: column;
	gap: var(--fc-space-4);
	max-width: var(--fcb-canvas-max-width);
	margin: 0 auto;
	width: 100%;
}
/* Three field-card placeholders of decreasing width — mirrors a real
   populated canvas's own natural rhythm (a mix of full-width and
   partial-width fields) rather than three identical bars, which would
   read as more obviously "fake" than a genuine loading state should. */
.fc-skeleton-canvas .fc-skeleton-block:nth-child(1) { height: 64px; }
.fc-skeleton-canvas .fc-skeleton-block:nth-child(2) { height: 64px; width: 85%; }
.fc-skeleton-canvas .fc-skeleton-block:nth-child(3) { height: 64px; width: 70%; }
.fc-skeleton-panel {
	width: var(--fcb-side-panel-width);
	flex-shrink: 0;
	display: flex;
	flex-direction: column;
	gap: var(--fc-space-3);
}
.fc-skeleton-panel .fc-skeleton-block {
	height: 14px;
}
.fc-skeleton-panel .fc-skeleton-block:nth-child(1) { width: 40%; height: 12px; }
.fc-skeleton-panel .fc-skeleton-block:nth-child(2) { width: 100%; }
.fc-skeleton-panel .fc-skeleton-block:nth-child(3) { width: 100%; }
.fc-skeleton-panel .fc-skeleton-block:nth-child(4) { width: 60%; }
@keyframes fc-shimmer {
	0% { background-position: 200% 0; }
	100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
	.fc-skeleton-block {
		animation-duration: 2.4s;
	}
}

/* This breaks on the BROWSER's viewport width, but the actual space the
   topbar has to work with is that minus WordPress's own admin-menu
   sidebar (160px expanded, 36px collapsed) plus its padding — so a
   1280px threshold looks fine in a plain browser tab but was still
   letting the Save Form button run off the edge of the screen on a real
   1366px laptop (1366 - 160px sidebar ≈ 1200px of actual room, well
   under where the old 1280px number assumed unobstructed viewport
   width). Raised to comfortably cover 1366/1440/1536px laptops with the
   sidebar expanded, not just a bare 1280px window. */
@media (max-width: 1500px) {
	.fc-topbar {
		grid-template-columns: 1fr;
		/* Stacking to one column turns fc-topbar-main/tabs/actions into
		   three grid ROWS (default grid-auto-flow), but the base rule's
		   `height: 60px` is sized for the single-row layout — left
		   unset here, the extra two rows still got laid out (proven live:
		   the Save button rendered ~90px below where the container
		   visually ended), just clipped outside the container's claimed
		   height and overlapping whatever came next in the page instead
		   of actually being invisible. */
		height: auto;
		padding-top: 10px;
		padding-bottom: 10px;
		row-gap: 8px;
	}
	.fc-topbar-actions {
		justify-content: flex-start;
		flex-wrap: wrap;
	}
}

/* This 3-value grid-template-columns was leftover from an OLDER
   3-column builder layout (palette | canvas | properties) — the
   redesign noted at .fc-builder-grid's own definition above ("Two
   columns, not three") consolidated the palette into the properties
   panel, but this now-stale override was never removed, and applying
   3 column widths to a 2-child grid just used the first two: canvas
   squeezed to 260px, panel stretched to whatever the second value
   resolved to. It was rendering fine at ≥1281px purely because it
   never fired there; raising the topbar's own breakpoint to 1500px
   (above) newly triggered it at 1366/1440px too and broke the Booking
   Calendar preview card (its fixed-width day-grid plus description no
   longer fit in a 260px canvas). Removed rather than relocated — the
   base rule (minmax(560px, 1fr) minmax(320px, 380px)) already shrinks
   correctly on its own down to the real max-width: 960px stacking
   point below, with no separate mid-range override needed. */

@media (max-width: 860px) {
	.fc-builder-grid {
		grid-template-columns: 1fr;
	}

	.fc-side-panel {
		position: static;
	}

	.fc-topbar-main {
		align-items: flex-start;
		flex-wrap: wrap;
	}

	/* Milestone 2's row columns collapse to a single stack below the
	   builder's own responsive breakpoint (this is the BUILDER app UI at
	   narrow admin widths, not the device-preview switcher — a real visitor
	   sees the column layout via the front-end's own responsive CSS and the
	   column's `responsive` metadata, unrelated to this). */
	.fc-row-columns {
		flex-direction: column;
	}
	.fc-column {
		flex-basis: 100% !important;
		max-width: 100% !important;
	}
}

/* ==========================================================================
   Milestone 2 — Layout engine (section/row/column/container)
   Nested containers reuse the exact same card chrome as a leaf field
   (.fc-canvas-field/.fc-canvas-field-toolbar above) — a Section or Row
   selects, drags, and duplicates exactly like any other node; only its
   *body* differs (ContainerBody's recursive children instead of
   FieldPreview). Rules below style that body plus the column-specific
   width/split/delete chrome.
   ========================================================================== */

/* A container card reads as a "shell" holding other cards — softer
   background and a dashed-when-empty border, rather than the solid white
   leaf-field card, so nesting depth is visually legible at a glance. */
.fc-canvas-field.is-container {
	background: rgba(26, 126, 251, 0.025);
	border-style: dashed;
	border-color: #e4d9fc;
	padding: 20px 12px 12px;
}
.fc-canvas-field.is-container:hover {
	border-color: #cdb8f8;
}
.fc-canvas-field.is-container.is-active {
	border-style: solid;
	background: rgba(26, 126, 251, 0.03);
}
.fc-canvas-field-section {
	padding-top: 24px;
}

/* Container identity badge — "SECTION" / "TABS" / etc, always visible
   (not gated behind hover like the drag-handle toolbar) in the
   top-right corner. Section/Row used to render as two visually
   identical dashed boxes nested inside each other with nothing to tell
   you which was which at a glance; this plus Row's own de-emphasis
   below are the fix. */
.fc-canvas-field-type-badge {
	position: absolute;
	top: 10px;
	right: 12px;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--fc-muted);
	background: var(--fc-bg);
	border: 1px solid var(--fcb-border-soft);
	border-radius: var(--fc-radius-full);
	padding: 3px 9px;
	pointer-events: none;
	z-index: 1;
}
.fc-canvas-field.is-active > .fc-canvas-field-type-badge {
	color: var(--fc-accent-dark);
	border-color: var(--fc-primary-100);
	background: var(--fc-accent-soft);
}

/* Selected-field type-name badge (non-container fields) — per
   design_handoff_chargeforms's builder spec: a small solid-accent pill at
   `top: -11px; left: 8px`, overlapping the field's own top border, shown
   only while selected. Distinct from .fc-canvas-field-type-badge above,
   which is the always-visible container identity badge (SECTION/TABS/…)
   in the opposite corner — the two never render on the same field, since
   isActive-non-container and isContainer are mutually exclusive in
   CanvasField.js. */
.fc-canvas-field-selected-badge {
	position: absolute;
	top: -11px;
	left: 8px;
	font-size: 9.5px;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: #fff;
	background: var(--fc-accent);
	border-radius: 4px;
	padding: 2px 7px;
	pointer-events: none;
	z-index: 2;
}

/* Row is structural, not a shell of its own — its columns already
   provide the visual subdivision (boxes sitting side by side), so
   giving Row the SAME dashed-border/tinted-background treatment as its
   parent Section just produced two near-identical nested boxes. Row is
   invisible at rest (no border/shadow/background of its own) and only
   reveals a boundary on hover/selection, matching the same "quiet
   until you interact with it" principle already used for insert
   points elsewhere on the canvas. */
.fc-canvas-field-row.is-container {
	background: none;
	border-color: transparent;
	border-left-color: transparent;
	box-shadow: none;
	padding: 6px 0 0;
}
.fc-canvas-field-row.is-container:hover {
	background: rgba(26, 126, 251, 0.02);
	border-color: #ede5fd;
}
.fc-canvas-field-row.is-container.is-active {
	background: rgba(26, 126, 251, 0.02);
	border-color: var(--fc-accent);
	border-style: dashed;
}

/* "Add Row" / "Add Column" — a text+icon toolbar button, wider than the
   icon-only Edit/Duplicate/Delete buttons it sits next to. */
.fc-canvas-field-action-label {
	display: inline-flex !important;
	align-items: center;
	gap: 4px;
	width: auto !important;
	padding: 0 8px !important;
	font-size: 11px;
	font-weight: 600;
	white-space: nowrap;
}
.fc-canvas-field-action-label .dashicons {
	font-size: 13px;
	width: 13px;
	height: 13px;
}

/* The droppable+sortable list every container's children render into
   (also what the root canvas conceptually is, one level up). */
.fc-dropzone {
	min-height: 44px;
	border-radius: 6px;
	transition: background 0.12s ease, box-shadow 0.12s ease;
}
.fc-dropzone.is-empty {
	border: 1.5px dashed #e4d9fc;
}
.fc-dropzone.is-drop-target {
	background: var(--fc-accent-soft);
	box-shadow: inset 0 0 0 1.5px var(--fc-accent);
}
.fc-dropzone-empty {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: 10px;
	font-size: 11px;
	font-weight: 600;
	color: var(--fc-muted);
	text-align: center;
}
/* Every drop zone's own click-to-add affordance — dragging a field in is
   no longer the only way to populate a section/row/column/pane. Sits
   below the zone's own fields (or its empty-state message), same
   left-aligned low-emphasis treatment as the corner drag-handle chip so
   it reads as a secondary action, not competing with the fields
   themselves. */
.fc-dropzone-add {
	position: relative;
	padding: 4px 6px;
}
.fc-dropzone-add-btn {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	border: none;
	background: transparent;
	color: var(--fc-muted);
	font-size: 11px;
	font-weight: 600;
	padding: 4px 6px;
	border-radius: var(--fc-radius-sm, 6px);
	cursor: pointer;
}
.fc-dropzone-add-btn .dashicons {
	font-size: 13px;
	width: 13px;
	height: 13px;
}
.fc-dropzone-add-btn:hover {
	background: var(--fc-primary-50);
	color: var(--fc-accent-dark);
}
.fc-dropzone-add-btn:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--fc-primary-50);
}
.fc-dropzone .fc-canvas-field {
	margin: 6px;
}

/* Row = columns laid out left-right, each sized by its own width%. A
   minimum width keeps a narrow column (25% of a narrow builder canvas)
   from becoming unusably thin — it'll still visually read as "smaller than
   its siblings" via flex-basis, just never below a usable floor. */
.fc-row-columns {
	display: flex;
	gap: 12px;
	align-items: stretch;
}
.fc-column {
	display: flex;
	flex-direction: column;
	min-width: 120px;
	flex-grow: 0;
	flex-shrink: 0;
}
.fc-column-head {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-bottom: 6px;
	padding: 3px 6px;
	border-radius: 5px;
	background: #f5f1fe;
}
.fc-column-width-label {
	font-size: 10px;
	font-weight: 700;
	color: var(--fc-accent-dark);
	margin-right: auto;
}
.fc-column-split-btn,
.fc-column-delete-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 18px;
	height: 18px;
	border: none;
	background: transparent;
	color: var(--fc-muted);
	cursor: pointer;
	border-radius: var(--fc-radius-sm);
	transition: background var(--fc-motion-fast) var(--fc-ease), color var(--fc-motion-fast) var(--fc-ease);
}
.fc-column-split-btn:hover,
.fc-column-delete-btn:hover {
	background: var(--fc-surface);
	color: var(--fc-accent-dark);
}
.fc-column-split-btn:focus-visible,
.fc-column-delete-btn:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--fc-primary-50);
}
.fc-column-split-btn .dashicons,
.fc-column-delete-btn .dashicons {
	font-size: 13px;
	width: 13px;
	height: 13px;
}

/* Milestone 5D — Tabs/Accordion pane list in the builder. Every pane's
   fields are shown stacked and directly editable at once (see
   ContainerBody.js's file-level doc comment for why) — this is the
   pane-header chrome (editable title + delete), same shape as
   .fc-column-head above. */
.fc-pane-list {
	display: flex;
	flex-direction: column;
	gap: 10px;
}
.fc-pane {
	border: 1px dashed #e4d9fc;
	border-radius: 7px;
	padding: 10px;
}
.fc-pane-head {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-bottom: 8px;
}
.fc-pane-title-input {
	flex: 1;
	border: 1px solid transparent;
	background: transparent;
	font-size: 12px;
	font-weight: 700;
	color: var(--fc-accent-dark);
	padding: 4px 6px;
	border-radius: 4px;
}
.fc-pane-title-input:hover,
.fc-pane-title-input:focus {
	border-color: var(--fc-border);
	background: #fff;
	outline: none;
}
.fc-pane-delete-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 20px;
	height: 20px;
	border: none;
	background: transparent;
	color: var(--fc-muted);
	cursor: pointer;
	border-radius: var(--fc-radius-sm);
	flex-shrink: 0;
	transition: background var(--fc-motion-fast) var(--fc-ease), color var(--fc-motion-fast) var(--fc-ease);
}
.fc-pane-delete-btn:hover {
	background: var(--fc-surface);
	color: var(--fc-danger, #e5484d);
}
.fc-pane-delete-btn:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--fc-primary-50);
}

/* Column-width preset picker in the settings panel — 6 presets need to
   wrap onto two rows rather than squeezing into the 4-across default
   .fc-btn-group. */
.fc-btn-group-wrap {
	flex-wrap: wrap;
	border-radius: 6px;
}
.fc-btn-group-wrap button {
	flex: 1 1 30%;
	border-bottom: 1px solid var(--fc-border);
}
.fc-btn-group-wrap button:nth-child(3n) {
	border-right: none;
}

/* ==========================================================================
   Milestone 3 — Selection system, multi-select, floating toolbar, drag
   feedback, keyboard focus. See ARCHITECTURE.md's Milestone 3 section for
   the interaction model these rules implement.
   ========================================================================== */

/* Keyboard focus ring — every CanvasField carries tabIndex=0 (App.js/
   CanvasField.js) so Tab and the Up/Down arrow-nav handlers move real DOM
   focus, not just a logical "selected" flag. `:focus-visible` (not
   `:focus`) means this ring appears for keyboard users tabbing/arrowing
   through the canvas but NOT for a mouse click landing on the same
   element — exactly the distinction between "focused" and "selected" the
   milestone brief calls out as two different states. */
.fc-canvas-field:focus-visible {
	outline: 2px solid var(--fc-accent);
	outline-offset: 2px;
}

/* Multi-selected (part of selectedIds, but not the primary/active one) —
   deliberately SUBTLER than .is-active's solid left-edge + shadow (a
   dashed, lower-contrast border instead of a solid accent one) so the
   primary selection unambiguously reads as "the one driving the settings
   panel" at a glance, instead of every selected field looking the same
   strength of "selected" — which is what made it impossible to tell which
   field's settings you were looking at without checking the panel itself. */
.fc-canvas-field.is-selected {
	background: var(--fc-accent-soft);
	border-color: var(--fc-accent-100, var(--fc-primary-100));
	border-style: dashed;
}
.fc-canvas-field.is-selected:hover {
	background: var(--fc-accent-soft);
}

/* The "which one is primary" badge — only rendered when a multi-selection
   is active (CanvasField.js), so a single selected field (already
   unambiguous via .is-active alone) doesn't get a redundant marker. */
.fc-canvas-field-primary-badge {
	position: absolute;
	top: -8px;
	right: 14px;
	display: inline-flex;
	align-items: center;
	gap: 3px;
	padding: 2px 8px;
	border-radius: var(--fc-radius-full);
	background: var(--fc-accent);
	color: #fff;
	font-size: 9.5px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	box-shadow: 0 0 0 2px var(--fc-surface);
}

/* Container drop-target highlighting — a stronger, more saturated
   treatment than a leaf dropzone's tint, since "you're about to drop
   inside this whole section/column" is a bigger commitment than "drop
   between these two fields" and should read as visually distinct. */
.fc-canvas-field.is-container.is-drop-target,
.fc-canvas-field.is-container:has(> .fc-dropzone.is-drop-target) {
	border-color: var(--fc-accent);
	box-shadow: var(--fc-shadow-selection);
}

/* Floating context toolbar — position:fixed in real viewport coordinates
   (see FloatingToolbar.js's doc comment for why), centered above the
   active field. Elevation/radius/motion now pull from the Milestone 4
   design-system scale (docs/DESIGN_SYSTEM.md) instead of one-off values —
   --fc-shadow-lg is the "floating element that tracks a selection" step,
   the same semantic level a Figma-style contextual toolbar sits at. */
/* Background matches the .dc.html mockup's own explicit floating-toolbar
   spec: near-black (#1e1f21), 7px radius — a prior pass changed this to
   "the reference product's real $editor-item-action-bg" (#909399, a medium gray), the
   wrong design authority per the project's own .dc.html-wins rule. */
/* Real z-index bug found live: this used the documented token-scale value
   (--fcb-z-popover, only 10) while every other position:fixed overlay in
   this file (.fc-quick-add--floating, .fc-context-menu, modals) escapes
   the whole scale with a hardcoded 100000 specifically so they always
   render above canvas content. At z-index 10 this toolbar could render
   BEHIND the canvas/quick-add popover — matched to the same 100000 tier
   the rest of this file already uses for the same reason. */
.fc-floating-toolbar {
	position: fixed;
	/* --fc-toolbar-shift is a corrective pixel offset FloatingToolbar.js
	   applies after measuring the rendered toolbar against the viewport
	   edges — 0px (the fallback) whenever the plain -50% centering already
	   fits. See that file's useLayoutEffect for why. */
	transform: translate(calc(-50% + var(--fc-toolbar-shift, 0px)), calc(-100% - 12px));
	z-index: 100000;
	display: flex;
	align-items: center;
	gap: 3px;
	padding: 6px;
	background: #1e1f21;
	border-radius: 7px;
	box-shadow: 0 4px 12px rgba(15, 23, 42, 0.16), 0 16px 40px -8px rgba(15, 23, 42, 0.35), 0 0 0 1px rgba(255, 255, 255, 0.06) inset;
	animation: fc-toolbar-in var(--fc-motion-fast) var(--fc-ease, ease-out);
}
@keyframes fc-toolbar-in {
	from { opacity: 0; transform: translate(calc(-50% + var(--fc-toolbar-shift, 0px)), calc(-100% - 4px)); }
	to { opacity: 1; transform: translate(calc(-50% + var(--fc-toolbar-shift, 0px)), calc(-100% - 10px)); }
}
/* Flipped: the anchor field sits too close to the top of the viewport for
   the toolbar to fit above it (e.g. the first field in the canvas), so it
   renders below the field instead — same logic Notion/Figma use for their
   own selection toolbars near a viewport edge. */
.fc-floating-toolbar.is-flipped {
	transform: translate(calc(-50% + var(--fc-toolbar-shift, 0px)), 10px);
}
/* Multi-select's own dark bar (design_handoff_chargeforms's Interactions
   doc: "Shift-click fields → dark action bar appears") — a darker slate
   than the single-select bar's neutral grey, so a Shift-click selection
   reads as a distinct mode, not just "the same toolbar with more buttons". */
.fc-floating-toolbar.is-multi {
	background: #1e293b;
}
.fc-floating-toolbar.is-multi button:hover:not(:disabled) {
	background: var(--fc-accent);
}
@keyframes fc-toolbar-in-flipped {
	from { opacity: 0; transform: translate(calc(-50% + var(--fc-toolbar-shift, 0px)), 4px); }
	to { opacity: 1; transform: translate(calc(-50% + var(--fc-toolbar-shift, 0px)), 10px); }
}
.fc-floating-toolbar.is-flipped {
	animation-name: fc-toolbar-in-flipped;
}
/* Icon color and hover fill match the reference product's real .item-actions .el-icon /
   .action-menu-item:hover rules — white icons, and hover is a SOLID
   $primary (accent blue) fill, not a translucent white overlay. Delete
   gets the same uniform hover treatment as every other icon in the reference product's
   source (no separate red-danger hover exists there). */
.fc-floating-toolbar button {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border: none;
	border-radius: 8px;
	background: transparent;
	color: #fff;
	cursor: pointer;
	transition: background var(--fc-motion-fast) ease, color var(--fc-motion-fast) ease;
}
.fc-floating-toolbar button svg {
	display: block;
	transition: transform var(--fc-motion-fast) var(--fc-ease);
}
.fc-floating-toolbar button:hover:not(:disabled) {
	background: var(--fc-accent);
	color: #fff;
}
.fc-floating-toolbar button:hover:not(:disabled) svg {
	transform: scale(1.1);
}
.fc-floating-toolbar button:disabled {
	opacity: 0.35;
	cursor: default;
}
.fc-floating-toolbar-sep {
	width: 1px;
	height: 18px;
	background: rgba(255, 255, 255, 0.14);
	margin: 0 2px;
}
.fc-floating-toolbar-count {
	padding: 0 8px 0 4px;
	font-size: 11px;
	font-weight: 700;
	color: #cbd5e1;
	white-space: nowrap;
}

/* Reduced motion — every animation/transition this milestone adds (toolbar
   entrance, drop-target highlight, drag ghost) collapses to an instant
   state change instead of being disabled outright, so the UI is still
   fully usable, just without the motion. */
@media (prefers-reduced-motion: reduce) {
	.fc-floating-toolbar,
	.fc-quick-add,
	.fc-modal-overlay,
	.fc-modal {
		animation: none;
	}
	.fc-canvas-field,
	.fc-dropzone,
	.fc-canvas-empty,
	.fc-insert-btn,
	.fc-drag-ghost,
	.fc-quick-add-search,
	.fc-quick-add-tabs button,
	.fc-quick-add-item,
	.fc-quick-add-item-icon,
	.fc-richtext-editor,
	.fc-toast,
	.fc-tooltip {
		transition-duration: 0.001ms !important;
		animation-duration: 0.001ms !important;
	}
}

/**
 * Toast + Tooltip shared infrastructure (ARCHITECTURE.md "Toast + Tooltip
 * Infrastructure") — see shared/toast/ and shared/tooltip/. Every color,
 * spacing, and shadow value below resolves to an existing --fc- or --fcb-
 * prefixed token, same discipline as the rest of this file (§6 of
 * ARCHITECTURE.md).
 */

.fc-toast-viewport {
	position: fixed;
	right: var(--fc-space-4, 16px);
	bottom: var(--fc-space-4, 16px);
	z-index: var(--fcb-z-toast);
	display: flex;
	flex-direction: column;
	gap: 8px;
	max-width: 360px;
	pointer-events: none;
}
.fc-toast-region {
	display: flex;
	flex-direction: column;
	gap: 8px;
}
.fc-toast {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	padding: 10px 12px;
	background: var(--fc-panel, #fff);
	border: 1px solid var(--fcb-border-soft);
	border-radius: var(--fcb-radius-control);
	box-shadow: var(--fcb-shadow-panel);
	font-size: var(--fc-text-base, 13px);
	color: var(--fcb-ink);
	pointer-events: auto;
	animation: fc-toast-in var(--fcb-motion-base);
}
.fc-toast-success .fc-toast-icon { color: var(--fc-success); }
.fc-toast-error .fc-toast-icon { color: var(--fc-danger); }
.fc-toast-warning .fc-toast-icon { color: var(--fc-warning); }
.fc-toast-info .fc-toast-icon { color: var(--fc-info); }
.fc-toast-icon {
	flex-shrink: 0;
	margin-top: 1px;
}
.fc-toast-message {
	flex: 1;
	line-height: 1.4;
}
.fc-toast-dismiss {
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 20px;
	height: 20px;
	padding: 0;
	border: none;
	background: none;
	color: var(--fc-muted);
	cursor: pointer;
	border-radius: 4px;
}
.fc-toast-dismiss:hover {
	background: var(--fc-primary-50);
	color: var(--fcb-ink);
}
.fc-toast-dismiss:focus-visible {
	outline: none;
	box-shadow: 0 0 0 2px var(--fc-primary-100);
}
@keyframes fc-toast-in {
	from { opacity: 0; transform: translateY(8px); }
	to { opacity: 1; transform: translateY(0); }
}

.fc-tooltip {
	position: fixed;
	z-index: var(--fcb-z-tooltip);
	max-width: 240px;
	padding: 5px 9px;
	background: var(--fcb-ink);
	color: #fff;
	font-size: 11px;
	line-height: 1.4;
	border-radius: 6px;
	box-shadow: var(--fcb-shadow-card);
	pointer-events: none;
	animation: fc-tooltip-in var(--fcb-motion-fast);
}
.fc-tooltip.is-measuring {
	visibility: hidden;
}
@keyframes fc-tooltip-in {
	from { opacity: 0; }
	to { opacity: 1; }
}

/* Error-boundary fallback (ErrorBoundary.js) — the recoverable screen that
   replaces a full blank-page crash. Deliberately plain/calm rather than
   alarming red, matching the rest of this app's restrained error styling
   (.fc-quick-add-empty, etc.). */
.fc-crash-screen {
	min-height: 100vh;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 40px 20px;
	background: var(--fc-bg, #ffffff);
}
.fc-crash-card {
	max-width: 480px;
	width: 100%;
	background: var(--fc-surface, #fff);
	border: 1px solid var(--fcb-border-soft);
	border-radius: var(--fcb-radius-card, 8px);
	box-shadow: var(--fcb-shadow-card);
	padding: 28px;
	text-align: center;
}
.fc-crash-card h2 {
	margin: 0 0 10px;
	font-size: 17px;
	font-weight: 700;
	color: var(--fcb-ink);
}
.fc-crash-card p {
	margin: 0 0 16px;
	font-size: 13.5px;
	color: var(--fc-muted);
	line-height: 1.55;
}
.fc-crash-message {
	margin: 0 0 20px;
	padding: 10px 12px;
	/* Decoupled from --fc-bg (now pure white, same surface as this box's
	   own .fc-crash-card container) — this needs contrast as a distinct
	   code/error block, not to blend into the card around it. */
	background: var(--fc-bg-soft, #f5f7fa);
	border-radius: 6px;
	font-size: 12px;
	font-family: ui-monospace, monospace;
	color: var(--fc-danger, #e5484d);
	text-align: left;
	white-space: pre-wrap;
	word-break: break-word;
	max-height: 120px;
	overflow-y: auto;
}
.fc-crash-actions {
	display: flex;
	gap: 9px;
	justify-content: center;
}

/* Per-device column-width control (FieldSettings.js + fields/classifications.js).
   The hint names the device being edited; the help line explains
   inheritance inline rather than behind a tooltip. */
.fc-settings-device-hint {
	font-style: normal;
	font-weight: 600;
	color: var(--fc-accent-dark);
}
.fc-settings-help {
	margin: 4px 0 0;
	font-size: 11px;
	line-height: 1.45;
	color: var(--fc-muted);
}

/* A selected column - the state that surfaces its Column Width controls in
   FieldSettings. Uses the same accent outline language as a selected field,
   inset so it does not collide with the row's own selection ring. */
.fc-column.is-selected {
	outline: 2px solid var(--fc-accent);
	outline-offset: -2px;
	border-radius: var(--fc-radius-sm);
}
.fc-column > .fc-column-head {
	cursor: pointer;
}
.fc-column:focus-visible {
	outline: 2px solid var(--fc-accent);
	outline-offset: -2px;
}
