/*
 * Lyric Opera Website Survey — front-end styles.
 *
 * The LYRIC OPERA THEME block at the end of this file sets Lyric's brand
 * colors and font (Jost) over the base tokens below.
 *
 * Every selector below is scoped under an .lyricws- prefixed class so this
 * stylesheet cannot leak into, or be overridden by, the site's
 * global styles. Colors/spacing are defined as CSS custom properties on
 * .lyricws-root only (not :root) so they never affect anything else on the
 * page. The widget does not bundle font files; it relies on the page
 * loading the brand font and falls back to the system font stack if it
 * isn't loaded.
 *
 * Color, spacing, radius, border-width, shadow, and typography values are
 * reconciled against the Figma design tokens export
 * (Tokens Studio / W3C token format: global, Primitives/Desktop+Mobile,
 * Mapped - Color/light+dark, Mapped - Responsive/*). Only the *light*
 * theme values are applied here — the widget currently has no dark-mode
 * toggle — but the dark-theme token set exists in that export if dark-mode
 * support is wanted later. Named tokens referenced in comments below
 * (e.g. "button", "form-header", "section-title", "input-label",
 * "input-text", "cta-button", "gaps") are the semantic names from that
 * export, not something invented here.
 */

.lyricws-root {
	--lyricws-color-bg: #ffffff;
	--lyricws-color-text: #130b2d;
	--lyricws-color-muted: #51617e;
	--lyricws-color-border: #dadfeb;
	--lyricws-color-accent: #00065c;
	--lyricws-color-accent-contrast: #ffffff;
	--lyricws-color-hover-border: #130b2d;
	--lyricws-color-selected-bg: rgba(220, 239, 255, 0.5);
	--lyricws-color-primary-hover-bg: #130b2d;
	--lyricws-color-icon-btn-hover-bg: rgba(218, 223, 235, 0.5);
	--lyricws-color-icon-btn-hover-border: rgba(81, 97, 126, 0.5);
	--lyricws-color-step-active: #1578d0;
	--lyricws-color-track: #eceef4;
	--lyricws-color-focus: #1578d0;
	--lyricws-color-error: #8b2523;
	--lyricws-color-error-bg: #fbeceb;
	--lyricws-radius: 10px;
	--lyricws-radius-sm: 5px;
	--lyricws-shadow: 1px 3px 12px rgba(19, 11, 45, 0.42);
	--lyricws-font: "Jost";
	--lyricws-z-invite: 999998;
	--lyricws-z-overlay: 999999;
	--lyricws-z-modal: 1000000;

	all: initial;
	font-family: var(--lyricws-font), -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	color: var(--lyricws-color-text);
	line-height: 1.45;
	box-sizing: border-box;
}

.lyricws-root *,
.lyricws-root *::before,
.lyricws-root *::after {
	box-sizing: border-box;
	font-family: inherit;
	line-height: inherit;
}

.lyricws-root input,
.lyricws-root textarea {
	color: inherit;
}

.lyricws-visually-hidden {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ---------------------------------------------------------------------
 * Invitation card
 * ------------------------------------------------------------------- */

.lyricws-invite {
	position: fixed !important;
	right: 20px;
	bottom: 20px;
	z-index: var(--lyricws-z-invite) !important;
	display: block !important;
	isolation: isolate;
	/* Widened per user request (was 320px). */
	width: min(380px, calc(100vw - 32px));
	background: var(--lyricws-color-bg);
	border: 1px solid var(--lyricws-color-border);
	border-radius: var(--lyricws-radius);
	box-shadow: var(--lyricws-shadow);
	/* Per a direct design-context pull of this exact card (node-id=10-1760):
	 * 24px on the sides and bottom, 32px on top — noticeably more breathing
	 * room than the old 16px/16px/14px guess. (The top padding is 32px in
	 * Figma's own data, not a flat 24px on every side — flagged since it's
	 * a real, if small, discrepancy worth knowing about.) */
	padding: 32px 24px 24px;
	animation: lyricws-fade-slide-in 220ms ease-out;
}

/* Right margin reserves room for the close icon per node-id=10-1760's own
 * 32px gap between the text block and the close icon, on top of the
 * card's own 24px right padding — 60px = 32 + 28 (the icon's current
 * 28px size, bumped up from that node's original 24px spec). Bottom
 * margin matches that node's 10px gap between the heading and
 * description. This unconditional rule must stay ABOVE the mobile media
 * query below: at equal specificity, CSS resolves ties by source order,
 * so if this came after the media query's own margin override, this
 * rule's `margin` would win there too and silently reinstate the 60px
 * right margin the mobile rule is trying to remove — exactly the bug a
 * real-device screenshot caught after this file's earlier version
 * shipped (mobile's `text-align: center` was in effect, but the
 * still-active 60px right margin shifted the whole centered box left,
 * so the heading only looked centered relative to a phantom, narrower
 * box — not the actual card). */
.lyricws-invite__heading {
	margin: 0 60px 10px 0;
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 900;
	color: var(--lyricws-color-text);
}

/* Hidden by default (desktop): the deliberate mobile line break after
 * "help" (see buildInviteDescription() in lyricws-public.js) is revealed
 * only inside the mobile media query below, so desktop's own text — which
 * comfortably fits the wider corner card on one line — is never forced to
 * break at this point. This unconditional rule must stay ABOVE the mobile
 * media query below: at equal specificity, CSS resolves ties by source
 * order, so if this came after the media query's own override it would
 * win there too and the break would never show on mobile either. */
.lyricws-invite__description-break {
	display: none;
}

/* Mobile invitation redesign (node-id=58:2048, inside the "initial pop up -
 * s" frame): a full-width bottom sheet flush against the screen's edges,
 * not a corner-inset card like desktop — 24px/16px padding (vs desktop's
 * 32/24/24), top corners rounded only (no bottom radius, since the sheet
 * sits flush against the bottom edge), and no border (the design uses only
 * the drop-shadow already carried over via --lyricws-shadow). */
@media (max-width: 480px) {
	.lyricws-invite {
		left: 0;
		right: 0;
		bottom: 0;
		width: 100%;
		border: none;
		border-radius: var(--lyricws-radius) var(--lyricws-radius) 0 0;
		padding: 24px 16px;
	}

	/* Mobile-only text treatment per a direct design-context pull of the
	 * card's content frame (node-id=58-2049): heading and description are
	 * centered (desktop keeps the left-aligned, corner-card layout, which
	 * reserves right-margin room for the close icon instead — that part is
	 * unchanged). The heading-to-description gap is also a real correction
	 * from this same pull: 8px, not the 10px carried over from the desktop
	 * node's own spacing. */
	.lyricws-invite__heading {
		margin: 0 0 8px 0;
		text-align: center;
	}

	/* Per user request, the description now spans the card's full width
	 * (no width cap) instead of the narrower centered block from the
	 * previous round — the two-line wrap is guaranteed a different way
	 * now (see .lyricws-invite__description-break below), so a width cap is
	 * no longer needed to force it. */
	.lyricws-invite__description {
		text-align: center;
	}

	/* Reveals the deliberate line break after "help" (see
	 * buildInviteDescription() in lyricws-public.js) only on mobile — hidden
	 * by default just below, so desktop's text is never forced to break
	 * here. */
	.lyricws-invite__description-break {
		display: inline;
	}

	/* CTA button spans the full width of the card on mobile, per the same
	 * node — scoped to the invitation's own button so the modal's
	 * differently-sized footer buttons (`.lyricws-modal__footer .lyricws-btn`)
	 * are untouched. */
	.lyricws-invite .lyricws-btn {
		width: 100%;
	}
}

@keyframes lyricws-fade-slide-in {
	from {
		opacity: 0;
		transform: translateY(12px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* Figma's invite-card mockup (node 10-1758, and the close glyph's own node
 * 58-2055) shows a bare, unboxed × with no button chrome at all — no hit-box
 * sizing, no hover background/border, just the icon. A prior round gave this
 * a 44px flex hit-area with hover background/border (matching the touch-
 * target pattern used elsewhere in the widget), but per user feedback that
 * made the glyph look disproportionately small inside an oversized invisible
 * button box, and unbalanced once the mobile popup went full-width. It's now
 * sized to its own glyph with no padding/box, matching the plain-icon look
 * in Figma — unlike the modal's own close button (`.lyricws-modal__close`),
 * which intentionally keeps its bordered-square button treatment. */
.lyricws-invite__close {
	position: absolute;
	/* Keeps the close glyph sitting at the card's own padding edges
	 * (24px top / 16px right on mobile, matching node-id=58-2048; also
	 * used as-is on desktop for consistency). */
	top: 24px;
	right: 16px;
	background: transparent;
	border: none;
	padding: 0;
	cursor: pointer;
	/* Sized up from the 24px per node-id=32-857 (user request, a further
	 * bump beyond that node's own spec). */
	font-size: calc(28px * var(--lyricws-text-scale, 1));
	line-height: 1;
	color: var(--lyricws-color-text);
}

.lyricws-invite__close:hover {
	color: var(--lyricws-color-hover-border);
}

/* Bottom margin matches node-id=10-1760's own 24px gap between the text
 * block and the "Give Feedback" button below it. */
.lyricws-invite__description {
	margin: 0 0 24px 0;
	font-size: calc(13.5px * var(--lyricws-text-scale, 1));
	color: var(--lyricws-color-muted);
}

/* Sizing/weight per the "cta-button" typography token and the "button"
 * spacing/radius/border tokens from the official Figma token export
 * (Tokens Studio: Primitives + "Mapped - Responsive/desktop"): 12px/12px
 * padding (space.12 both axes), SemiBold weight, 1% letter-spacing. */
.lyricws-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	font-size: calc(14px * var(--lyricws-text-scale, 1));
	font-weight: 600;
	letter-spacing: 0.01em;
	padding: 12px 12px;
	min-height: 44px;
	min-width: 44px;
	border-radius: var(--lyricws-radius-sm);
	border: 1px solid var(--lyricws-color-accent);
	cursor: pointer;
	text-align: center;
	background: var(--lyricws-color-accent);
	color: var(--lyricws-color-accent-contrast);
}

.lyricws-btn:hover {
	background: var(--lyricws-color-primary-hover-bg);
	border-color: var(--lyricws-color-primary-hover-bg);
}

.lyricws-btn--secondary {
	background: var(--lyricws-color-bg);
	color: var(--lyricws-color-text);
}

.lyricws-btn--secondary:hover {
	background: var(--lyricws-color-selected-bg);
	border-color: var(--lyricws-color-accent);
	color: var(--lyricws-color-text);
}

.lyricws-btn:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

/* Visible, non-color-reliant focus state everywhere in the widget. */
.lyricws-root a:focus-visible,
.lyricws-root button:focus-visible,
.lyricws-root input:focus-visible,
.lyricws-root textarea:focus-visible,
.lyricws-root [tabindex]:focus-visible {
	outline: 3px solid var(--lyricws-color-focus);
	outline-offset: 2px;
}

/* ---------------------------------------------------------------------
 * Modal
 * ------------------------------------------------------------------- */

.lyricws-overlay {
	position: fixed !important;
	inset: 0 !important;
	z-index: var(--lyricws-z-overlay) !important;
	isolation: isolate;
	background: rgba(20, 22, 24, 0.55);
	display: flex !important;
	align-items: center;
	justify-content: center;
	padding: 16px;
}

/* 24px padding = the "gaps" spacing token at the desktop breakpoint. */
.lyricws-modal {
	position: relative !important;
	z-index: var(--lyricws-z-modal) !important;
	background: var(--lyricws-color-bg);
	border-radius: var(--lyricws-radius);
	box-shadow: var(--lyricws-shadow);
	width: min(560px, 100%);
	max-height: min(88vh, 720px);
	overflow-y: auto;
	padding: 24px;
}

/* All four mobile step/confirmation mocks (node-id=36-1057/1163/1299/1367)
 * share the same structure: a 24px top gutter above the card, and the card
 * itself stretching to fill 100% of whatever height remains below that —
 * so every step is the same total height regardless of how much content
 * it holds, rather than shrinking to fit like the desktop modal does.
 * `height: 100%` (not the desktop `max-height` cap) is what makes this
 * work; any step whose content is taller than the available space still
 * scrolls internally via the existing `overflow-y: auto`. */
@media (max-width: 480px) {
	.lyricws-overlay {
		padding: 24px 0 0 0;
		align-items: flex-end;
	}
	.lyricws-modal {
		width: 100%;
		height: 100%;
		max-height: none;
		border-radius: var(--lyricws-radius) var(--lyricws-radius) 0 0;
		/* 16px = the "gaps" spacing token at the mobile breakpoint. */
		padding: 16px;
	}
}

/* Matches the "SurveyFormHeader" component (node 31-646): title and close
 * button vertically centered with a 24px gap between them. The modal's own
 * 24px padding on all sides already covers this header's "pt-24/px-24";
 * margin-bottom here covers its "pb-12" before the progress indicator. */
.lyricws-modal__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	margin-bottom: 12px;
}

/* Mobile step mocks (node-id=36-1057/1163/1299/1367) show the header's own
 * 12px bottom padding plus the content area's own 12px top padding
 * immediately below it — a combined 24px gap before the progress bar,
 * vs. desktop's 12px alone. */
@media (max-width: 480px) {
	.lyricws-modal__header {
		margin-bottom: 24px;
	}
}

/* "form-header" typography token: Black weight, 18px. */
.lyricws-modal__title {
	margin: 0;
	font-size: calc(18px * var(--lyricws-text-scale, 1));
	font-weight: 900;
}

/* "icon close" Button variant, rest state: filled white background with a
 * thin border, not transparent — confirmed against node 31-646's own
 * design context (bg-[var(--background/default,white)]), not just the
 * screenshot. */
.lyricws-modal__close {
	width: 44px;
	height: 44px;
	min-width: 44px;
	min-height: 44px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--lyricws-color-bg);
	border: 1px solid var(--lyricws-color-border);
	border-radius: var(--lyricws-radius-sm);
	cursor: pointer;
	/* 24px close icon (was 18px), matching the enlarged size confirmed
	 * against the popup's own close icon (node-id=32-857, size-[24px]) —
	 * applied consistently to every "×" in the survey, not just the popup. */
	font-size: calc(24px * var(--lyricws-text-scale, 1));
	line-height: 1;
	color: var(--lyricws-color-text);
	flex-shrink: 0;
}

.lyricws-modal__close:hover {
	background: var(--lyricws-color-icon-btn-hover-bg);
	border-color: var(--lyricws-color-icon-btn-hover-border);
}

.lyricws-field {
	margin-bottom: 22px;
}

.lyricws-field:last-of-type {
	margin-bottom: 0;
}

.lyricws-field__legend,
.lyricws-field__label {
	display: block;
	margin-bottom: 4px;
	padding: 0;
}

/* Ordinary field labels (e.g. "Please specify") use the
 * "input-label" typography token (Medium weight, 14px). */
.lyricws-field__label {
	font-size: calc(14px * var(--lyricws-text-scale, 1));
	font-weight: 500;
}

/* Question-level headings (Q1/Q2/Q3) use the "section-title" typography
 * token — Bold (700), 16px, confirmed via a direct design-context pull of
 * node-id=9-1472 (was 800/ExtraBold; earlier passes had read this token
 * as ExtraBold from the static token export, but this component's own
 * live data shows Bold) — a step heavier and a size larger than ordinary
 * field sub-labels. Q3's heading is a <label> rather than a <legend> (it has
 * no radiogroup needing fieldset semantics), so lyricws-public.js adds this
 * class alongside .lyricws-field__label on that element to get the same
 * treatment; because this rule comes after .lyricws-field__label in the
 * cascade (equal specificity), it wins on elements carrying both classes. */
.lyricws-field__legend {
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 700;
}

/* Decorative required indicator; the actual "required" semantics are
 * conveyed to assistive tech via aria-required on the underlying
 * radiogroup/input, not by this glyph alone. */
.lyricws-required-mark {
	color: var(--lyricws-color-error);
	font-weight: 700;
}

.lyricws-field__description {
	margin: 0 0 10px 0;
	font-size: calc(13px * var(--lyricws-text-scale, 1));
	color: var(--lyricws-color-muted);
}

.lyricws-fieldset {
	border: 0;
	margin: 0;
	padding: 0;
}

.lyricws-radio-group {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin-top: 10px;
}

/* Mobile step 1 mock (node-id=36-1057): a tighter 6px gap between option
 * rows (vs. desktop's 8px), and a 12px gap after the question text —
 * combined with the label's own 4px margin-bottom, that's a 16px total
 * gap before the option list, vs. desktop's 14px. */
@media (max-width: 480px) {
	.lyricws-radio-group {
		gap: 6px;
		margin-top: 12px;
	}
}

.lyricws-radio-option {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 14px;
	border: 1px solid var(--lyricws-color-border);
	border-radius: var(--lyricws-radius-sm);
	cursor: pointer;
}

.lyricws-radio-option:hover {
	border-color: var(--lyricws-color-hover-border);
}

.lyricws-radio-option input[type="radio"] {
	margin: 0;
	width: 18px;
	height: 18px;
	min-width: 18px;
	flex-shrink: 0;
	accent-color: var(--lyricws-color-accent);
}

.lyricws-radio-option__text {
	font-size: calc(14.5px * var(--lyricws-text-scale, 1));
}

/* The checkmark sits to the right of the label text (pushed there by
 * margin-left: auto on the flex row) and is hidden until selected. A
 * hand-authored inline SVG (baked to the same navy as --lyricws-color-accent)
 * stands in for the Figma "check_small" asset, which this widget cannot
 * fetch — that asset is served from a localhost dev URL reachable only from
 * the machine running the Figma desktop app, not from this build. */
.lyricws-radio-option__check {
	display: none;
	margin-left: auto;
	flex-shrink: 0;
	width: 14px;
	height: 11px;
	background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNCAxMSI+PHBhdGggZD0iTTEgNS41IDUgOS41IDEzIDEuNSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwNjVjIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjwvc3ZnPg==") no-repeat center / contain;
}

/* Selection is shown by the native checked radio AND a border/background
 * change plus a checkmark glyph, so it never relies on color alone. */
.lyricws-radio-option.is-selected {
	border-color: var(--lyricws-color-accent);
	border-width: 1.5px;
	background: var(--lyricws-color-selected-bg);
	padding: 11.5px 13.5px;
}

.lyricws-radio-option.is-selected .lyricws-radio-option__check {
	display: inline-flex;
}

.lyricws-other-input {
	margin-top: 10px;
	margin-left: 28px;
}

/* Q2's "What made you give that rating?" follow-up is NOT nested under an
 * indented parent option (unlike Q1's "Other" field above), so it must not
 * share .lyricws-other-input's 28px left-indent — that was an unintended bug
 * from reusing the same class for two visually different contexts. Its own
 * class also widens the gap under the rating scale from the old 10px to a
 * more deliberate 24px, consistent with the 24px spacing unit already used
 * elsewhere in this stylesheet (e.g. the mobile modal padding). */
.lyricws-explain-input {
	display: block;
	margin-top: 24px;
	scroll-margin-bottom: 24px;
}

.lyricws-explain-input[hidden] {
	display: none;
}

.lyricws-input,
.lyricws-textarea {
	width: 100%;
	font-size: calc(14px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	padding: 10px 12px;
	border: 1px solid var(--lyricws-color-border);
	border-radius: var(--lyricws-radius-sm);
	background: var(--lyricws-color-bg);
}

.lyricws-input:focus,
.lyricws-textarea:focus {
	border-color: var(--lyricws-color-hover-border);
}

.lyricws-textarea {
	min-height: 96px;
	resize: vertical;
}

/* Q2's "explain your rating" box and Q3's feedback box are the two
 * long-text follow-up fields in the survey — per design review, both are
 * now a consistent 100px tall at every breakpoint (this ID selector's
 * specificity beats the shared .lyricws-textarea 96px default above). Figma's
 * own mocks actually show 100px on mobile (`node-id=36-1166`/`36-1302`) but
 * 110px on desktop (`node-id=9-1539`/`9-1607`) — both consistent with each
 * other at each breakpoint already, just not with each other across
 * breakpoints; one flat 100px everywhere was chosen instead, a
 * deliberate deviation from the desktop mock's 110px. Previously these two
 * fields didn't even match each other on mobile (90px vs 70px, an older,
 * un-reconciled pair of one-off Figma pulls). */
#lyricws-q2-explain-input,
#lyricws-q3-input {
	min-height: 100px;
}

/* Label-to-field gap for these same two fields: 16px per both mobile and
 * desktop Figma mocks (`node-id=36-1166`/`36-1302` mobile, `9-1539`/`9-1607`
 * desktop) — noticeably more than the 4px the shared .lyricws-field__legend
 * rule gives every other label in the survey. Scoped to just these two
 * labels via a `for`-attribute selector (higher specificity than the shared
 * class rule, so it wins regardless of source order) rather than changing
 * the shared rule itself, since Q1/Q2/Q3's own main headings are not part
 * of this request and must keep their existing 4px. */
label[for="lyricws-q2-explain-input"],
label[for="lyricws-q3-input"] {
	margin-bottom: 16px;
}

/* Rating scale: large, evenly sized touch targets that work in a row on
 * desktop and wrap gracefully on narrow screens. Wraps the number-box row
 * plus the "Very difficult"/"Very easy" caption row beneath it, matching
 * Figma's two-row "scale" group (node-id=9-1195) — the endpoint captions
 * run as their own full-width row below the whole group, not stacked
 * inside the endpoint boxes themselves. Gap between the two rows widened
 * to 16px (was 8px) per a direct design-context pull of node-id=9-1472,
 * which shows this exact 16px gap between them — a real correction, not
 * just a preference bump. */
.lyricws-scale-wrap {
	display: flex;
	flex-direction: column;
	gap: 16px;
	width: 100%;
	margin-top: 10px;
}

.lyricws-scale {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: 8px;
}

.lyricws-scale-option {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 10px;
	min-height: 64px;
	padding: 12px 6px 14px;
	border: 1px solid var(--lyricws-color-border);
	border-radius: var(--lyricws-radius-sm);
	cursor: pointer;
	text-align: center;
}

/* Mobile step 2 mock (node-id=36-1163): the 5 boxes keep the same 8px gap
 * as desktop (no override needed there — the previous 6px mobile override
 * didn't match this), but each box gets more horizontal padding (12px,
 * up from 6px) and slightly more bottom padding (16px, up from 14px). */
@media (max-width: 480px) {
	.lyricws-scale-option {
		padding: 12px 12px 16px;
	}
}

.lyricws-scale-option:hover {
	border-color: var(--lyricws-color-hover-border);
}

.lyricws-scale-option input[type="radio"] {
	width: 18px;
	height: 18px;
	accent-color: var(--lyricws-color-accent);
}

/* Black weight / 14px, confirmed against node-id=9-1195's number glyphs
 * (was previously a guessed 800/15px). */
.lyricws-scale-option__number {
	font-size: calc(14px * var(--lyricws-text-scale, 1));
	font-weight: 900;
}

.lyricws-scale-option.is-selected {
	border-color: var(--lyricws-color-accent);
	border-width: 1.5px;
	background: var(--lyricws-color-selected-bg);
}

/* The "Very difficult" / "Very easy" endpoint captions, as their own row
 * below the number boxes (not nested inside the endpoint boxes) — Medium
 * weight, 12px, muted color, spread across the full width with a 32px
 * gap so "Very difficult" sits under box 1 and "Very easy" sits under
 * box 5, confirmed against node-id=9-1195. Decorative only — the actual
 * accessible labeling for each option lives on its own aria-label. */
.lyricws-scale-captions {
	display: flex;
	gap: 32px;
	width: 100%;
	font-size: calc(12px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	line-height: 1;
	color: var(--lyricws-color-muted);
}

.lyricws-scale-captions__low {
	flex: 1 0 0;
	min-width: 0;
}

.lyricws-scale-captions__high {
	flex: 1 0 0;
	min-width: 0;
	text-align: right;
}

/* Reserved for submission-level failures only (network/server errors on
 * final submit) — there is no field to attach these to. Field-level
 * validation problems never use this; they show entirely via each field's
 * own inline .lyricws-field-error text, so there is no top-of-form banner. */
.lyricws-submit-error {
	display: block;
	color: var(--lyricws-color-error);
	font-size: calc(12px * var(--lyricws-text-scale, 1));
	line-height: 1.22;
	letter-spacing: -0.02em;
	font-weight: 700;
	margin: 0 0 12px 0;
	text-align: right;
}

.lyricws-submit-error[hidden] {
	display: none;
}

/* Bold, 122% line-height, -2% letter-spacing — confirmed against nodes
 * 7-996/9-1082. Font size corrected to 14px (was 12px, the "p.small"
 * token's own size) per a direct design-context pull of node-id=9-1472,
 * whose error text is explicitly sized at 14px rather than that token's
 * 12px. Top margin widened to 24px (was 6px) — that same node's own
 * top-level gap between the question block and its error row, applied
 * here to every field's error text for a consistent rhythm across all
 * three steps. */
.lyricws-field-error {
	display: block;
	color: var(--lyricws-color-error);
	font-size: calc(14px * var(--lyricws-text-scale, 1));
	line-height: 1.22;
	letter-spacing: -0.02em;
	margin-top: 24px;
	font-weight: 700;
}

/* BUG FIX: `display: block` above (needed so the shown error lays out on
 * its own line) has higher cascade priority than the browser's built-in
 * `[hidden] { display: none; }` UA rule, since author styles always beat
 * user-agent styles regardless of selector specificity. Without this
 * override, an error span with the `hidden` attribute set (i.e. every
 * field at rest, with no active error) still rendered — including this
 * element's own ::before warning-icon glyph below — even though it was
 * never supposed to be visible until a real validation error occurred. */
.lyricws-field-error[hidden] {
	display: none;
}

/* A hand-authored inline SVG (baked to the same red as --lyricws-color-error)
 * rather than a Unicode "⚠", which renders as an inconsistent color emoji
 * on some platforms/browsers regardless of text-presentation hints. */
.lyricws-field-error::before {
	content: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTEyIDIuNSAxLjUgMjEuNWgyMUwxMiAyLjV6IiBmaWxsPSIjOGIyNTIzIi8+PHJlY3QgeD0iMTEiIHk9IjkiIHdpZHRoPSIyIiBoZWlnaHQ9IjYuNSIgZmlsbD0iI2ZmZmZmZiIvPjxyZWN0IHg9IjExIiB5PSIxNyIgd2lkdGg9IjIiIGhlaWdodD0iMiIgZmlsbD0iI2ZmZmZmZiIvPjwvc3ZnPg==");
	display: inline-block;
	width: 13px;
	height: 13px;
	margin-right: 6px;
	vertical-align: -1px;
}

.lyricws-field.has-error .lyricws-input,
.lyricws-field.has-error .lyricws-textarea {
	border-color: var(--lyricws-color-error);
	border-width: 1.5px;
}

/* Consistent error-state treatment for Q1's radio group and Q2's rating
 * scale: a single bordered wrapper around the WHOLE option group (never a
 * per-option red border), confirmed identical on both Figma nodes 63-2312
 * (Q1) and 63-2329 (Q2) — 1px error-red border, 10px radius, 4px padding,
 * and the gap between option rows narrowed from the at-rest 8px to 6px.
 * Previously Q1 used an outline-with-offset treatment that had no Figma
 * basis, and Q2 had no error-state styling on its option group at all
 * (only the error message text below it changed) — this replaces both
 * with the one shared, Figma-matched wrapper style. */
.lyricws-field.has-error .lyricws-radio-group,
.lyricws-field.has-error .lyricws-scale {
	border: 1px solid var(--lyricws-color-error);
	border-radius: var(--lyricws-radius);
	padding: 4px;
	gap: 6px;
}

.lyricws-modal__footer {
	margin-top: 24px;
	display: flex;
	justify-content: space-between;
	gap: 24px;
}

/* Mobile mocks (steps 2/3 and the confirmation screen — node-id=36-1163,
 * 36-1299, 36-1367) show the footer sitting apart from the modal's own
 * 16px mobile inset (see .lyricws-modal's mobile rule) by an extra 8px on
 * each side and along the bottom, for a 24px total footer inset, and a
 * wider 40px gap above it (vs. desktop's 24px) — content's own bottom
 * padding plus the footer's own top padding, combined. Step 1's mock
 * measured slightly differently (a likely Figma authoring inconsistency,
 * since steps 2/3/confirmation all agree); the majority pattern is used
 * here for internal consistency across all four screens. */
@media (max-width: 480px) {
	.lyricws-modal__footer {
		margin-top: 40px;
		padding: 0 8px 8px;
	}
}

/* Footer/CTA buttons — Back/Close on the left, Next/Submit on the right,
 * and the confirmation screen's single centered Close — confirmed
 * against each screen's own Figma node (node-id=31-679 step 1,
 * 31-743 step 2, 31-836 step 3, 31-849 confirmation): fixed 100px/43px
 * sizing, 16px/12px padding. Scoped to just these buttons (not the
 * shared .lyricws-btn base) since the invitation's own "Give Feedback" CTA
 * wasn't part of this batch. min-width rather than a hard width so the
 * "Submitting…" label (longer than "Submit") can still grow instead of
 * clipping inside a fixed box. */
.lyricws-modal__footer .lyricws-btn,
.lyricws-thankyou__footer .lyricws-btn {
	min-width: 100px;
	height: 43px;
	padding: 12px 16px;
	line-height: 1;
}

/* Confirmation's Close button (node-id=31-849 desktop / 55-1896 mobile)
 * uses 24px horizontal padding, not the 16px shared by the Back/Next/
 * Submit footer buttons elsewhere; on mobile it also goes full-width
 * (the desktop version stays the same fixed/centered size as those other
 * buttons). */
.lyricws-thankyou__footer .lyricws-btn {
	padding: 12px 24px;
}

@media (max-width: 480px) {
	.lyricws-thankyou__footer .lyricws-btn {
		width: 100%;
	}
}

/* ---------------------------------------------------------------------
 * Step progress indicator (3-step wizard: reason → rating → feedback)
 *
 * Redesigned to match a segmented linear progress bar (node-id=47-1557
 * desktop, 47-1500 mobile — identical on both, unlike the previous
 * dot–line–dot cluster, which needed a separate mobile-only full-width
 * override): one thin 2px-tall, full-width track split into TOTAL_STEPS
 * equal segments (touching edge to edge, no gap between them), each
 * segment either filled (accent color, for the current step and every step
 * before it) or unfilled (a new light-neutral track color), with a
 * left-aligned "X / Y" label beneath it. Rounding is structural, not
 * per-state: the very first segment always rounds its left corners, the
 * very last segment always rounds its right corners, and the last FILLED
 * segment additionally rounds its right corners so the filled portion
 * always ends in a clean cap against the (square) unfilled track right
 * after it — confirmed against the reference nodes' own step-1 state,
 * where the sole filled segment is simultaneously first and last-filled
 * and shows rounding on every corner. Segments are purely decorative
 * (aria-hidden) either way; the actual accessible step announcement is
 * the "X / Y" text carried by lyricws-steps-label via aria-live, so this
 * redesign doesn't remove any assistive-tech information — non-color-
 * reliant state is still conveyed by how much of the track is filled. */

.lyricws-steps {
	margin-bottom: 20px;
	display: flex;
	flex-direction: column;
	gap: 10px;
}

/* Mobile mocks show a 24px gap between the progress bar and the question
 * content below it (vs. desktop's 20px) — confirmed across all three
 * step nodes (node-id=36-1058, 36-1166, 36-1302). */
@media (max-width: 480px) {
	.lyricws-steps {
		margin-bottom: 24px;
	}
}

.lyricws-steps-bar {
	display: flex;
	align-items: center;
	width: 100%;
}

.lyricws-steps-segment {
	flex: 1 0 0;
	height: 2px;
	min-width: 0;
	background: var(--lyricws-color-track);
}

.lyricws-steps-segment.is-filled {
	background: var(--lyricws-color-step-active);
}

.lyricws-steps-segment.is-round-left {
	border-top-left-radius: 999px;
	border-bottom-left-radius: 999px;
}

.lyricws-steps-segment.is-round-right {
	border-top-right-radius: 999px;
	border-bottom-right-radius: 999px;
}

/* Medium weight, 12px, no letter-spacing, left-aligned — a real change
 * from the previous Bold/right-aligned/-2%-tracking treatment, confirmed
 * against the same reference nodes. */
.lyricws-steps-label {
	margin: 0;
	font-size: calc(12px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	line-height: 1.22;
	color: var(--lyricws-color-muted);
	text-align: left;
}

/* Confirmation screen redesign (node-id=9-1712 desktop / 55-1887 mobile):
 * the whole card is now edge-to-edge (no shared modal header, no ambient
 * modal padding — see .lyricws-modal--confirmation below), split into two
 * full-bleed blocks that each carry their own padding: this icon+text
 * block, and the .lyricws-thankyou__footer block beneath it holding the
 * Close button. Icon-to-text-group gap and text-group's own internal gap
 * are both smaller on mobile than desktop, confirmed against both nodes. */
.lyricws-thankyou {
	text-align: center;
	padding: 32px 24px 24px;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 32px;
}

/* Corrected against a fresh design-context pull of node-id=55-1887's own
 * icon+text block (55-1890): pt-24/px-16/pb-14 with a 20px gap — not the
 * 38px-top/24px-gap figures an earlier pull had used. */
@media (max-width: 480px) {
	.lyricws-thankyou {
		padding: 24px 16px 14px;
		gap: 20px;
	}
}

/* Full-bleed footer for the confirmation screen's Close button — separate
 * from .lyricws-modal__footer since that one relies on the modal's own
 * ambient padding (still present for steps 1-3), while this screen has
 * none (see .lyricws-modal--confirmation) and needs its own explicit 24px
 * on every side instead. Confirmed against node-id=31-849 desktop /
 * 55-1896 mobile — same 24px padding at both breakpoints. */
.lyricws-thankyou__footer {
	display: flex;
	justify-content: center;
	padding: 24px;
}

/* Corrected against a fresh design-context pull of node-id=55-1887's own
 * footer block (55-1896): p-16, not the flat 24px carried over from
 * desktop (node-id=31-849) — the two breakpoints aren't actually the same
 * value here, unlike what an earlier round's pull had concluded. */
@media (max-width: 480px) {
	.lyricws-thankyou__footer {
		padding: 16px;
	}
}

/* The confirmation screen drops the shared modal header (see
 * onSubmitSuccess() in lyricws-public.js) and goes edge-to-edge instead —
 * .lyricws-thankyou and .lyricws-thankyou__footer below now supply their own
 * padding directly, matching node-id=9-1712/55-1887 exactly. Steps 1-3
 * are unaffected; this modifier class is only ever added once the
 * confirmation screen replaces the modal body. */
.lyricws-modal.lyricws-modal--confirmation {
	padding: 0;
}

/* Unlike the three step-screen mocks (node-id=36-1057/1163/1299/1367), the
 * confirmation card's own mobile mock (node-id=55-1887) does NOT stretch to
 * fill the viewport height — its Figma frame has no h-full on the card,
 * only on the steps. So on mobile this two-class selector (reliably beats
 * the single-class .lyricws-modal rule above on specificity, regardless of
 * source order or media-query nesting) reverts the confirmation card to
 * content-sized height. Corners are also full-radius on every side here
 * (matching this node's own `rounded-[10px]`, not the top-corners-only
 * bottom-sheet radius steps 1-3 use), since the confirmation card floats as
 * a centered dialog rather than sitting flush against the bottom edge —
 * see .lyricws-overlay--confirmation below for that centering. The max-height
 * cap is just a safety net for unusually short viewports; content still
 * scrolls via the modal's own overflow-y: auto if it's ever taller than
 * that. */
@media (max-width: 480px) {
	.lyricws-modal.lyricws-modal--confirmation {
		height: auto;
		max-height: calc(100vh - 48px);
		border-radius: var(--lyricws-radius);
	}
}

/* A fresh design-context pull of node-id=55-1887's own outer frame shows
 * `items-center justify-center` — the confirmation screen is vertically
 * CENTERED in the viewport on mobile, not bottom-anchored like steps 1-3
 * (which use the base .lyricws-overlay mobile rule's align-items: flex-end
 * and a top-only gutter). `.lyricws-overlay--confirmation` is added by
 * onSubmitSuccess() in lyricws-public.js alongside the modal's own
 * `.lyricws-modal--confirmation` class; this selector is declared after the
 * base mobile `.lyricws-overlay` rule above so it wins the cascade tie at
 * equal specificity regardless of media-query nesting (the same technique
 * `.lyricws-modal.lyricws-modal--confirmation` already relies on). */
@media (max-width: 480px) {
	.lyricws-overlay--confirmation {
		align-items: center;
		padding: 24px 16px;
	}
}

.lyricws-thankyou__icon {
	position: relative;
	z-index: 0;
	width: 28px;
	height: 28px;
	background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAJUElEQVR4nO3dW5LjxhEF0BqHFjLeibWI8SI9i5B34tmJ9CF3dAebbIJAPTIrz/m1QgEW8l4mwPGoNQAAAKCCb6svgP6+//Hjz1H/7l+//zQzG3EzExoZ8KsURC5uVnCRw36UUojLjQlkh7AfpRRicBMWqhT4ZxTCGg59MqF/ThnM46AnEPrzlMFYDncQoe9PGfTnQDsS+nmUQR8OsQPBX0cRXOPwLhD8OBTBOQ7tRUIfnzI4zkEdJPj5KILnHNATgp+fInjMwTwg+PtRBJ85kBuCvz9F8O4fqy8gEuGvwX1+pwmbgais+jZQ+sMLPm+qFkHZRwDh56Oq81Cu9areaI6rtA2U2gCEnyMqzUmJpqt0Q+lr921g+w1A+Lli9/nZugB2v3nMsfMcbbne7HzDWGu3R4LtNgDhZ6Td5murAtjt5hDTTnO2xTqz0w0hl+yPBOk3AOFnpezzl7oAsh8+e8g8h2kLIPOhs5+s85iyALIeNnvLOJfpCiDjIVNHtvlMVQDZDpeaMs1pmgLIdKiQZV5TFECWw4SPMsxt+ALIcIjwSPT5DV0A0Q8Pjog8x2ELIPKhwauiznPIAoh6WHBFxLkOVwARDwl6iTbfoQog2uHACJHmPEwBRDoUGC3KvIcogCiHATNFmPvlBRDhEGCV1fO/vACAdZYWwOr2gwhW5mBZAQg/vFuVhyUFIPzw2YpceAcAhU0vAN/+8NjsfEwtAOGH52bmZFoBCD8cNysv3gFAYVMKwLc/vG5GboYXgPDDeaPz4xEAChtaAL794bqRORpWAMIP/YzKk0cAKGxIAfj2h/5G5MoGAIV1LwDf/jBO73x1LQDhh/F65swjABTWrQB8+8M8vfJmA4DCuhSAb3+Yr0fufutxIRDZ//71n4f/2z//+++JVxLPt6v/At/+RPVV8G9lLoJfv/88nWPvANjSK+E/88/v4tIG4NufaHoEOeM2cHYLsAFAYQqAbfRa4ys9DpwuAOs/kfQObbYSOJtHGwDpZQtrJKcKwLc/UYwMf7ZiOZNLGwAU9nIB+PYnimzf0DO8mk8bACkJfx8KgHSEv5+XCsD6z2rC/9wrObUBkIbw96cASGFF+DP+fwJedbgArP+s4pv/dUfzagMgtFXhr/Dt35oCgE+qhL+1gwVg/WcFq/81R3Lr7wQkJC/95vAIQDjCP8/Tv0bI+s9Ms8NfIfhf/XVhNgDC8Mw/nwIgBGv/GgqA5YR/nS8LwPM/O6oW/q9ybANgKS/91lIALCP86ykAlhD+GBQA0wl/HA8LwAtARhD+NR7l2QbANP6gTzwKgCn81h+TAmA44Y9LAbAd4T/ubgF4AUgvXvrFcS/XNgCGEf74FABDCH8OCoDuhD8PBUBXwp+LAqAbf9AnHwVAF37rz0kBcJnw5/WpAPwZAKIT/vNu820D4BIv/XJTAJwm/PkpAE4R/j34bwPe8dVwG0Th34kC+ODIYL/9M1WH0m/9e/EI8H+vDnbFIPi5bz/lN4ArQ11pGxD+PdkAeEr491W6AHoNdsXHgZGEf56yBdA7tLuWgDf+eytbACPsVgLCv7+SBTBysHcpAeGvoWQBjJa9BIS/DgUwSNYSyHrdnKMABsoWJj/31aMABstSAsJfkwKYIHoJCH9dCoDphD+OkgWwYgCjbgHe+NdWsgBWiVYCwk/ZAlg1jFFKQPhprXABtFa3BISfN58K4NfvP7+tuJBqVpXA6vJhrdt8l94AWvv726nKJuDnPm6VL4A3u5eA8HOPAvhg9xKYSfhzUAA3diwBL/14RAHcsVMJCD9fUQAP7FACws8zCuALmUtA+DnibgH4swDvMpaA8HPPvVzbAA7IVAI7/qLAOArgoAwl4Ld+XqUAEnjlP1o6k/DnpwBesHLgo632wr+HhwXgReB9EUvASz+eeZRnG8AJkUpA+LlCAZwUIQjCz1UK4IKVvwwIPz0ogIsqBKPCZ6zqywLwIvAYASGyr3JsA+hk1xLY9XPxNwXQ0W5h2e3z8JkC6GyX0OzyOfja0wLwHuB12cOT/fp59yy/NoBBsoYo63VzjgIYKFuYsl0v1x0qAI8B52UJVZbr5LgjubUBTCBcRKUAJolcApGvjbEOF4DHgOsiBi3iNXHd0bzaACaLFLhI18IaCmCBCMGLcA2s91IBeAzYg/Dv7ZWc2gAWWRVC4ecjBbDQ7DAKP7deLgCPAX3NCqXw1/BqPm0AAQgnq5wqAFtAfyNLQMHUcCaXNoBABJXZTheALWCM3iWgVGo4m0cbQEC9Qiv8PKMAoLDLa/z3P3782eNCuO/MfwDEN38tVx7HbQDBvRpm4ecVXV7k2QLm+GobEPyarr6M/63XhTCekNNbl0cAPwnCfD1y5x0AFNatAGwBME+vvNkAoLCuBWALgPF65qz7BqAEYJze+fIIAIUNKQBbAPQ3Ilc2AChsWAHYAqCfUXkaugEoAbhuZI48AkBhwwvAFgDnjc7PlA1ACcDrZuTGIwAUNq0AbAFw3Ky8TN0AlAA8NzMn0x8BlAA8Njsf3gFAYUsKwBYAn63IxbINQAnAu1V5WPoIoARgbQ68A4DClheALYDKVs//8gJobf0hwAoR5j5EAbQW4zBglijzHqYAWotzKDBSpDkPVQCtxToc6C3afIcrgNbiHRL0EHGuQxZAazEPC86KOs9hC6C1uIcGr4g8x6ELoLXYhwfPRJ/f8AXQWvxDhHsyzG2KAmgtx2HCmyzzmqYAWstzqNSWaU5TFUBruQ6XerLNZ7oCaC3fIVNDxrlMWQCt5Txs9pV1HtMWQGt5D529ZJ7D1AXQWu7DJ7/s85f64m99/+PHn6uvgRqyB/9N+g3go11uCrHtNGdbFUBre90c4tltvrb6MLc8EtDLbsF/s90G8NGuN425dp6jrQugtb1vHuPtPj9bf7hbHgk4avfgv9l+A/ioyk3lmkpzUuaD3rINcKtS8N+U2gA+qnizeazqPJT80LdsA3VVDf6b0h/+liKoo3rw35R9BLjHUNTgPr9zEA/YBvYj+J85kCcUQX6C/5iDOUgR5CP4zzmgFymC+AT/OAd1gTKIQ+jPcWgdKIJ1BP8ah9eRIphH8PtwiIMog/6Evj8HOoEyOE/ox3K4kymD54R+Hge9kDJ4J/RrOPRAKhWCwMfgJgS3QykIe1xuTEKRS0HYc3GzNjSyIAQcAAAgrb8AcPTBKgZ1dygAAAAASUVORK5CYII=") no-repeat center center;
	background-size: contain;
}

/* Soft glow halo behind the checkmark, confirmed against the icon's own
 * node (node-id=37-1395, "check_circle") and the confirmation screen using
 * it (node-id=37-1393): the glow bleeds past the icon's nominal 28px box
 * by about 21% on every side (per that node's own negative-inset
 * layout), rather than being clipped to it — so this is a real 40px halo
 * layered behind the (unchanged) checkmark image, not a resize of the
 * checkmark itself. `z-index: -1` plus the icon's own `position: relative;
 * z-index: 0;` keeps the glow scoped behind just this icon, not any
 * unrelated sibling elsewhere on the page. */
.lyricws-thankyou__icon::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: -1;
	width: 40px;
	height: 40px;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: radial-gradient(circle, rgba(32, 191, 85, 0.22) 0%, rgba(32, 191, 85, 0.1) 55%, rgba(32, 191, 85, 0) 80%);
}

.lyricws-thankyou__text {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	width: 100%;
}

@media (max-width: 480px) {
	.lyricws-thankyou__text {
		gap: 10px;
	}
}

/* "form-header" typography token (Black, 18px) — the same weight/size
 * used for the modal title (see .lyricws-modal__title) — confirmed against
 * node-id=9-1717; was previously a lighter/smaller 700/17px guess. */
.lyricws-thankyou__message {
	font-size: calc(18px * var(--lyricws-text-scale, 1));
	font-weight: 900;
	line-height: 28px;
	margin: 0;
}

.lyricws-thankyou__detail {
	font-size: calc(14px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	line-height: 24px;
	color: var(--lyricws-color-muted);
	margin: 0;
	max-width: 404px;
	margin-left: auto;
	margin-right: auto;
}

/* Mobile mock (node-id=55-1887) constrains this line to a fairly narrow
 * 224px column — noticeably less than the space actually available — so
 * it wraps to two lines by design, not just when it has to. */
@media (max-width: 480px) {
	.lyricws-thankyou__detail {
		max-width: 224px;
	}
}

.lyricws-hp-field {
	position: absolute !important;
	left: -9999px !important;
	width: 1px;
	height: 1px;
	overflow: hidden;
}


/* Q3 option labels: the lead word (Excellent, Good, …) is bold. */
.lyricws-radio-option__lead {
	font-weight: 700;
}

/* Explicit text color (#130b2d via --lyricws-color-text) on every text
 * element that previously relied on inheritance. Without this, a host-page
 * rule like `p { color: … }` or `label { color: … }` beats the inherited
 * value — which is why the thank-you heading rendered light gray in the
 * preview. Declaring it directly makes the widget immune to site styles. */
.lyricws-thankyou__message,
.lyricws-modal__title,
.lyricws-field__legend,
.lyricws-field__label,
.lyricws-radio-option,
.lyricws-scale-option {
	color: var(--lyricws-color-text);
}

/* ======================================================================
 * LYRIC OPERA THEME
 * From the Lyric Figma design (desktop frames: Step 8 invitation,
 * step 1/3/5/6/7, and the step 1 / step 4 error states). Placed last so
 * it overrides the base styling above at equal specificity.
 * Mobile sizes (max-width: 480px) are scaled-down adaptations, since the
 * file has no Lyric mobile frames yet.
 * ====================================================================== */
.lyricws-root {
	--lyricws-color-text: #130b2d;
	--lyricws-color-ink: #000000;
	--lyricws-color-body: #262626;
	--lyricws-color-muted: #626262;
	--lyricws-color-border: rgba(0, 0, 0, 0.25);
	--lyricws-color-accent: #91004c;
	--lyricws-color-accent-hover: #6e003a;
	--lyricws-color-accent-contrast: #ffffff;
	--lyricws-color-hover-border: #91004c;
	--lyricws-color-track: rgba(0, 0, 0, 0.05);
	--lyricws-color-step-active: #91004c;
	--lyricws-color-focus: #91004c;
	--lyricws-color-error: #e9171f;
	--lyricws-radius: 0;
	--lyricws-radius-sm: 0;
	--lyricws-shadow: 1px 3px 6px rgba(0, 0, 0, 0.15);
	--lyricws-font: "Jost";
	font-family: var(--lyricws-font), "Helvetica Neue", Helvetica, Arial, sans-serif;
	line-height: 1.22;
}

/* Icons (inline SVG, no external files) */
.lyricws-icon {
	display: inline-block;
	flex-shrink: 0;
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
}
.lyricws-icon--close {
	width: 16px;
	height: 16px;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M1 1l14 14M15 1L1 15' stroke='%23000' stroke-width='1.5' fill='none'/%3E%3C/svg%3E");
}
.lyricws-icon--arrow {
	width: 26px;
	height: 16px;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 26 16'%3E%3Cpath d='M0 8h24M17 1l7 7-7 7' stroke='%23fff' stroke-width='2' fill='none'/%3E%3C/svg%3E");
}

/* Buttons: square, uppercase, bold */
.lyricws-btn {
	gap: 8px;
	font-size: calc(18px * var(--lyricws-text-scale, 1));
	font-weight: 700;
	line-height: 1;
	letter-spacing: 1.26px;
	text-transform: uppercase;
	padding: 18px 24px;
	min-height: 54px;
	border: 1.5px solid var(--lyricws-color-accent);
	border-radius: 0;
	background: var(--lyricws-color-accent);
	color: var(--lyricws-color-accent-contrast);
}
.lyricws-btn:hover {
	background: var(--lyricws-color-accent-hover);
	border-color: var(--lyricws-color-accent-hover);
}
.lyricws-btn--secondary {
	background: #ffffff;
	color: var(--lyricws-color-accent);
}
.lyricws-btn--secondary:hover {
	background: #ffffff;
	border-color: var(--lyricws-color-accent-hover);
	color: var(--lyricws-color-accent-hover);
}
.lyricws-modal__footer .lyricws-btn,
.lyricws-thankyou__footer .lyricws-btn {
	min-width: 108px;
	height: auto;
	padding: 18px 24px;
}

/* Invitation (bottom-right card) */
.lyricws-invite {
	right: 32px;
	bottom: 32px;
	width: min(583px, calc(100vw - 32px));
	border: none;
	border-radius: 0;
	padding: 32px;
}
.lyricws-invite__heading {
	margin: 0 70px 18px 0;
	font-size: calc(30px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	letter-spacing: -0.45px;
	color: var(--lyricws-color-ink);
}
.lyricws-invite__description {
	margin: 0 70px 48px 0;
	font-size: calc(20px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	color: var(--lyricws-color-body);
}
.lyricws-invite__close {
	top: 32px;
	right: 32px;
	width: 38px;
	height: 38px;
	display: flex;
	align-items: center;
	justify-content: center;
}
.lyricws-invite__close .lyricws-icon--close {
	width: 22px;
	height: 22px;
}
.lyricws-invite .lyricws-btn {
	/* Optically balanced: ~26px visible on both sides (right padding is
	 * smaller to offset the arrow graphic's built-in margin), and a ~12px
	 * visible gap between the text and the arrow (10.5px plus the trailing
	 * letter-spacing after the last letter). */
	gap: 10.5px;
	padding: 18px 23.5px 18px 24px;
}

/* Modal */
.lyricws-modal {
	width: min(678px, 100%);
	max-height: min(92vh, 900px);
	border-radius: 0;
	padding: 24px;
}
.lyricws-modal__header {
	gap: 24px;
	margin-bottom: 12px;
}
.lyricws-modal__title {
	font-size: calc(20px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	line-height: 1;
	color: var(--lyricws-color-text);
}
.lyricws-modal__close {
	width: 44px;
	height: 44px;
	margin: -10px -10px -10px 0;
	background: transparent;
	border: none;
	border-radius: 0;
}
.lyricws-modal__close:hover {
	background: var(--lyricws-color-track);
	border: none;
}

/* Progress */
.lyricws-steps {
	gap: 10px;
	margin-bottom: 32px;
}
.lyricws-steps-segment {
	height: 4px;
}
.lyricws-steps-segment.is-round-left,
.lyricws-steps-segment.is-round-right {
	border-radius: 0;
}
.lyricws-steps-label {
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	color: var(--lyricws-color-muted);
}

/* Question text */
.lyricws-field__legend,
.lyricws-field__label.lyricws-field__legend {
	margin-bottom: 32px;
	font-size: calc(24px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	letter-spacing: -0.24px;
	color: var(--lyricws-color-ink);
}
.lyricws-required-mark {
	color: var(--lyricws-color-error);
	font-weight: 500;
}

/* Answer options */
.lyricws-radio-group {
	gap: 8px;
	margin-top: 0;
}
.lyricws-radio-option {
	gap: 12px;
	padding: 14px 12px;
	border: 1px solid var(--lyricws-color-border);
	border-radius: 0;
	background: #ffffff;
	color: var(--lyricws-color-ink);
}
.lyricws-radio-option:hover {
	border-color: var(--lyricws-color-accent);
}
.lyricws-radio-option input[type="radio"],
.lyricws-scale-option input[type="radio"] {
	accent-color: var(--lyricws-color-accent);
}
.lyricws-radio-option__text {
	font-size: calc(20px * var(--lyricws-text-scale, 1));
	font-weight: 400;
}
.lyricws-radio-option__lead {
	font-weight: 600;
}
.lyricws-radio-option.is-selected {
	border: 2.5px solid var(--lyricws-color-accent);
	background: #ffffff;
	padding: 12.5px 10.5px;
}
.lyricws-radio-option.is-selected .lyricws-radio-option__check {
	display: none;
}

/* 1-5 scale */
.lyricws-scale-wrap {
	gap: 24px;
	margin-top: 0;
}
.lyricws-scale {
	gap: 8px;
}
.lyricws-scale-option {
	gap: 16px;
	padding: 24px 8px;
	border: 1px solid var(--lyricws-color-border);
	border-radius: 0;
	background: #ffffff;
	color: var(--lyricws-color-ink);
}
.lyricws-scale-option:hover {
	border-color: var(--lyricws-color-accent);
}
.lyricws-scale-option__number {
	font-size: calc(20px * var(--lyricws-text-scale, 1));
	font-weight: 600;
}
.lyricws-scale-option.is-selected {
	border: 2.5px solid var(--lyricws-color-accent);
	background: #ffffff;
	padding: 22.5px 6.5px;
}
.lyricws-scale-captions {
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	letter-spacing: 0.16px;
	line-height: 1.22;
	color: var(--lyricws-color-muted);
}

/* Text box */
.lyricws-input,
.lyricws-textarea {
	font-size: calc(20px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	padding: 16px;
	border: 1px solid var(--lyricws-color-border);
	border-radius: 0;
	color: var(--lyricws-color-ink);
}
.lyricws-textarea::placeholder,
.lyricws-input::placeholder {
	color: var(--lyricws-color-muted);
	opacity: 1;
}
.lyricws-input:focus,
.lyricws-textarea:focus {
	border-color: var(--lyricws-color-accent);
}
#lyricws-q4-input {
	min-height: 139px;
}
/* Optional follow-up inside step 3 (Average / Frustrating / Difficult) */
.lyricws-followup {
	display: block;
	margin: 32px 0 0 0;
	scroll-margin-bottom: 24px;
}
.lyricws-followup[hidden] {
	display: none;
}
.lyricws-followup__label {
	display: block;
	margin: 0 0 8px 0;
	font-size: calc(20px * var(--lyricws-text-scale, 1));
	font-weight: 600;
	line-height: 1.22;
	color: var(--lyricws-color-text);
}
.lyricws-followup__optional {
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	color: var(--lyricws-color-muted);
}
.lyricws-followup .lyricws-textarea {
	display: block;
	width: 100%;
}

/* Errors */
.lyricws-field-error {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-top: 24px;
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	letter-spacing: 0.16px;
	line-height: 1;
	color: var(--lyricws-color-error);
}
.lyricws-field-error[hidden] {
	display: none;
}
.lyricws-field-error::before {
	content: "";
	width: 14px;
	height: 12px;
	margin: 0;
	flex-shrink: 0;
	background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 12'%3E%3Cpath d='M7 0l7 12H0z' fill='%23c8102e'/%3E%3Cpath d='M6.3 4h1.4v4H6.3zM6.3 9h1.4v1.4H6.3z' fill='%23fff'/%3E%3C/svg%3E") no-repeat center / contain;
}
.lyricws-field.has-error .lyricws-radio-group,
.lyricws-field.has-error .lyricws-scale {
	border: 1.5px solid var(--lyricws-color-error);
	border-radius: 0;
	padding: 16px;
	gap: 8px;
}
.lyricws-submit-error {
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	letter-spacing: 0;
}

/* Footer */
.lyricws-modal__footer {
	margin-top: 56px;
	gap: 24px;
}

/* Thank-you screen (no icon in the Lyric design) */
.lyricws-thankyou {
	padding: 64px 24px 24px;
	gap: 0;
}
.lyricws-thankyou__icon {
	display: none;
}
.lyricws-thankyou__text {
	gap: 18px;
}
.lyricws-thankyou__message {
	font-size: calc(30px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	letter-spacing: -0.45px;
	line-height: 1.22;
	color: var(--lyricws-color-ink);
}
.lyricws-thankyou__detail {
	max-width: none;
	font-size: calc(20px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	line-height: 1.22;
	color: var(--lyricws-color-body);
}
.lyricws-thankyou__footer {
	padding: 48px 24px 24px;
}

/* Mobile adaptation */
@media (max-width: 480px) {
	.lyricws-invite {
		right: 0;
		bottom: 0;
		width: 100%;
		padding: 24px 16px;
	}
	.lyricws-invite__heading {
		margin: 0 44px 12px 0;
		font-size: calc(24px * var(--lyricws-text-scale, 1));
		text-align: left;
	}
	.lyricws-invite__description {
		margin: 0 0 24px 0;
		font-size: calc(18px * var(--lyricws-text-scale, 1));
		text-align: left;
	}
	.lyricws-invite__close {
		top: 20px;
		right: 12px;
	}
	.lyricws-modal {
		padding: 16px;
	}
	.lyricws-field__legend,
	.lyricws-field__label.lyricws-field__legend {
		margin-bottom: 20px;
		font-size: calc(20px * var(--lyricws-text-scale, 1));
	}
	.lyricws-followup__label {
		margin-bottom: 8px;
		font-size: calc(18px * var(--lyricws-text-scale, 1));
	}
	.lyricws-followup__optional {
		font-size: calc(14px * var(--lyricws-text-scale, 1));
	}
	.lyricws-radio-option__text,
	.lyricws-scale-option__number,
	.lyricws-input,
	.lyricws-textarea {
		font-size: calc(18px * var(--lyricws-text-scale, 1));
	}
	.lyricws-scale-option {
		padding: 16px 4px;
		gap: 10px;
	}
	.lyricws-scale-option.is-selected {
		padding: 14.5px 2.5px;
	}
	.lyricws-scale-captions {
		font-size: calc(14px * var(--lyricws-text-scale, 1));
	}
	.lyricws-modal__footer {
		margin-top: 32px;
		padding: 0;
	}
	.lyricws-thankyou {
		padding: 40px 16px 8px;
	}
	.lyricws-thankyou__message {
		font-size: calc(24px * var(--lyricws-text-scale, 1));
	}
	.lyricws-thankyou__detail {
		font-size: calc(18px * var(--lyricws-text-scale, 1));
	}
}

/* Invitation CTA: the arrow nudges 4px right on hover / keyboard focus,
 * at a slower 300ms to match the "READ MORE ->" links on lyricopera.org.
 * Arrow shortened to 23px to match the site's proportions. */
.lyricws-invite .lyricws-icon--arrow {
	width: 23px;
	height: 16px;
	transition: transform 300ms ease-out;
}
.lyricws-invite .lyricws-btn:hover .lyricws-icon--arrow,
.lyricws-invite .lyricws-btn:focus-visible .lyricws-icon--arrow {
	transform: translateX(4px);
}
@media (prefers-reduced-motion: reduce) {
	.lyricws-invite .lyricws-icon--arrow {
		transition: none;
	}
}

/* Radio styling (Figma node 1:80):
 * - Hover: option border turns black (1px). Selected keeps the 2.5px magenta border.
 * - Radio circle: 18px, 1px black stroke in every state; when selected,
 *   a 7px magenta dot fills the center. Sits in a 24px icon slot.
 * Applies to both the list options (Q1/Q3) and the 1-5 scale (Q2). */
.lyricws-radio-option:hover,
.lyricws-scale-option:hover {
	border-color: #000000;
}
.lyricws-radio-option.is-selected,
.lyricws-radio-option.is-selected:hover,
.lyricws-scale-option.is-selected,
.lyricws-scale-option.is-selected:hover {
	border-color: var(--lyricws-color-accent);
}
.lyricws-radio-option input[type="radio"],
.lyricws-scale-option input[type="radio"] {
	-webkit-appearance: none;
	appearance: none;
	flex-shrink: 0;
	width: 18px;
	height: 18px;
	min-width: 18px;
	margin: 3px;
	padding: 0;
	border: 1px solid #000000;
	border-radius: 50%;
	background: #ffffff;
	cursor: pointer;
	display: inline-block;
	vertical-align: middle;
}
.lyricws-radio-option input[type="radio"]:checked,
.lyricws-scale-option input[type="radio"]:checked {
	background: radial-gradient(circle, var(--lyricws-color-accent) 0 3.5px, #ffffff 4px);
}
.lyricws-radio-option input[type="radio"]:focus-visible,
.lyricws-scale-option input[type="radio"]:focus-visible {
	outline: 3px solid var(--lyricws-color-focus);
	outline-offset: 2px;
}
@media (forced-colors: active) {
	.lyricws-radio-option input[type="radio"],
	.lyricws-scale-option input[type="radio"] {
		-webkit-appearance: auto;
		appearance: auto;
	}
}

/* Button hover states (Figma node 10:449)
 * Primary (Next / Submit):    #91004C -> #58002E, white text.
 * Secondary (Close / Back):   keeps the 1.5px #91004C border and text; gains a
 *                             light tint (rgba(244,102,107,0.2) over white = #FDE0E1).
 * Same on keyboard focus. */
.lyricws-root {
	--lyricws-color-accent-hover: #58002e;
	--lyricws-color-secondary-hover-bg: #fde0e1;
}
.lyricws-btn,
.lyricws-btn--secondary {
	transition: background-color 150ms ease-out, color 150ms ease-out, border-color 150ms ease-out;
}
.lyricws-btn:hover,
.lyricws-btn:focus-visible {
	background: var(--lyricws-color-accent-hover);
	border-color: var(--lyricws-color-accent-hover);
	color: #ffffff;
}
.lyricws-btn--secondary:hover,
.lyricws-btn--secondary:focus-visible {
	background: var(--lyricws-color-secondary-hover-bg);
	border-color: var(--lyricws-color-accent);
	color: var(--lyricws-color-accent);
}
.lyricws-btn:disabled,
.lyricws-btn:disabled:hover {
	background: var(--lyricws-color-accent);
	border-color: var(--lyricws-color-accent);
}
@media (prefers-reduced-motion: reduce) {
	.lyricws-btn,
	.lyricws-btn--secondary {
		transition: none;
	}
}

/* ----------------------------------------------------------------------
 * Interaction polish
 * 1. Keyboard focus is dark plum (#58002E), distinct from the magenta
 *    "selected" border. On answer options the ring wraps the whole box.
 * 2. Text box: darker resting border (3:1+), black on hover, 2px magenta
 *    while typing.
 * 3. Close (X) buttons: pink tint hover, matching secondary buttons.
 * -------------------------------------------------------------------- */
.lyricws-root {
	--lyricws-color-focus: #58002e;
	--lyricws-color-input-border: #8c8c8c;
}

/* 1. Focus ring around the whole answer box (keyboard only). */
.lyricws-radio-option input[type="radio"]:focus-visible,
.lyricws-scale-option input[type="radio"]:focus-visible {
	outline: 3px solid var(--lyricws-color-focus);
	outline-offset: 2px;
}
@supports selector(:has(*)) {
	.lyricws-radio-option input[type="radio"]:focus-visible,
	.lyricws-scale-option input[type="radio"]:focus-visible {
		outline: none;
	}
	.lyricws-radio-option:has(input:focus-visible),
	.lyricws-scale-option:has(input:focus-visible) {
		outline: 3px solid var(--lyricws-color-focus);
		outline-offset: 3px;
	}
}

/* 2. Text box */
.lyricws-input,
.lyricws-textarea {
	border-color: var(--lyricws-color-input-border);
	transition: border-color 150ms ease-out, box-shadow 150ms ease-out;
}
.lyricws-input:hover,
.lyricws-textarea:hover {
	border-color: #000000;
}
.lyricws-input:focus,
.lyricws-textarea:focus,
.lyricws-input:focus-visible,
.lyricws-textarea:focus-visible {
	outline: none;
	border-color: var(--lyricws-color-accent);
	box-shadow: inset 0 0 0 1px var(--lyricws-color-accent);
}

/* 3. Close (X) buttons */
.lyricws-modal__close,
.lyricws-invite__close {
	transition: background-color 150ms ease-out;
}
.lyricws-modal__close:hover,
.lyricws-invite__close:hover,
.lyricws-modal__close:focus-visible,
.lyricws-invite__close:focus-visible {
	background: var(--lyricws-color-secondary-hover-bg);
	border: none;
}

@media (prefers-reduced-motion: reduce) {
	.lyricws-input,
	.lyricws-textarea,
	.lyricws-modal__close,
	.lyricws-invite__close {
		transition: none;
	}
}

/* 4. Pressed (active) states: one step beyond hover while clicking.
 * Primary:   #58002E hover -> #3F0021 pressed.
 * Secondary: #FDE0E1 hover -> #FBC9CB pressed (35% coral over white).
 * Close (X) buttons use the same pressed pink. */
.lyricws-root {
	--lyricws-color-accent-active: #3f0021;
	--lyricws-color-secondary-active-bg: #fbc9cb;
}
.lyricws-btn:active {
	background: var(--lyricws-color-accent-active);
	border-color: var(--lyricws-color-accent-active);
	color: #ffffff;
}
.lyricws-btn--secondary:active {
	background: var(--lyricws-color-secondary-active-bg);
	border-color: var(--lyricws-color-accent);
	color: var(--lyricws-color-accent);
}
.lyricws-modal__close:active,
.lyricws-invite__close:active {
	background: var(--lyricws-color-secondary-active-bg);
}
.lyricws-btn:disabled:active {
	background: var(--lyricws-color-accent);
	border-color: var(--lyricws-color-accent);
}

/* ----------------------------------------------------------------------
 * Invitation + thank-you refresh (Figma node 3:1672, "step 7")
 * Both cards 618px wide, headings Jost Regular 36px / -0.54px, body
 * 20px #262626, 48px before the button.
 * -------------------------------------------------------------------- */
.lyricws-invite {
	width: min(618px, calc(100vw - 32px));
	padding: 32px;
}
.lyricws-invite__heading {
	margin: 0 76px 24px 0; /* 44px close button + 32px gap */
	font-size: calc(36px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	line-height: 1.22;
	letter-spacing: -0.54px;
	color: var(--lyricws-color-ink);
}
.lyricws-invite__description {
	margin: 0 0 48px 0;
	font-size: calc(20px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	line-height: 1.22;
	color: var(--lyricws-color-body);
}
.lyricws-invite__close {
	top: 32px;
	right: 32px;
	width: 44px;
	height: 44px;
}

.lyricws-modal.lyricws-modal--confirmation {
	width: min(618px, 100%);
}
.lyricws-thankyou {
	padding: 48px 32px 0;
	gap: 0;
}
.lyricws-thankyou__text {
	gap: 24px;
}
.lyricws-thankyou__message {
	font-size: calc(36px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	line-height: 1.22;
	letter-spacing: -0.54px;
}
.lyricws-thankyou__detail {
	font-size: calc(20px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	line-height: 1.22;
	color: var(--lyricws-color-body);
}
.lyricws-thankyou__footer {
	padding: 48px 32px 32px;
}

/* Mobile adaptation (no Lyric mobile frames yet) */
@media (max-width: 480px) {
	.lyricws-invite {
		width: 100%;
		padding: 24px 16px;
	}
	.lyricws-invite__heading {
		margin: 0 52px 12px 0;
		font-size: calc(26px * var(--lyricws-text-scale, 1));
		letter-spacing: -0.39px;
	}
	.lyricws-invite__description {
		margin: 0 0 24px 0;
		font-size: calc(18px * var(--lyricws-text-scale, 1));
	}
	.lyricws-invite__close {
		top: 18px;
		right: 8px;
	}
	.lyricws-thankyou {
		padding: 40px 16px 0;
	}
	.lyricws-thankyou__text {
		gap: 16px;
	}
	.lyricws-thankyou__message {
		font-size: calc(26px * var(--lyricws-text-scale, 1));
		letter-spacing: -0.39px;
	}
	.lyricws-thankyou__detail {
		font-size: calc(18px * var(--lyricws-text-scale, 1));
	}
	.lyricws-thankyou__footer {
		padding: 32px 16px 24px;
	}
}

/* Modal title as a small uppercase label, echoing the site's nav and
 * "READ MORE" labels. Screen readers still read it as "Website feedback". */
.lyricws-modal__title {
	font-size: calc(14px * var(--lyricws-text-scale, 1));
	font-weight: 700;
	line-height: 1;
	letter-spacing: 1.12px;
	text-transform: uppercase;
	color: var(--lyricws-color-text);
}

/* Elements that only receive focus programmatically (tabindex="-1", e.g.
 * each step's question when the screen opens, so screen readers announce
 * it) must not show the keyboard focus ring. Tab-reachable controls keep
 * their plum ring. */
.lyricws-root [tabindex="-1"]:focus,
.lyricws-root [tabindex="-1"]:focus-visible {
	outline: none;
}

/* Header: "Website feedback  step 1 of 3" on one line, progress bar below. */
.lyricws-modal__header {
	margin-bottom: 24px;
}
.lyricws-modal__heading {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 10px;
	row-gap: 2px;
	min-width: 0;
}
.lyricws-modal__title {
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	line-height: 1.22;
	letter-spacing: 0;
	text-transform: none;
	color: var(--lyricws-color-text);
}
.lyricws-steps-label {
	margin: 0;
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	line-height: 1.22;
	letter-spacing: 0;
	color: var(--lyricws-color-muted);
}
.lyricws-steps {
	gap: 0;
	margin-bottom: 32px;
}
@media (max-width: 480px) {
	.lyricws-modal__header {
		margin-bottom: 16px;
	}
	.lyricws-steps {
		margin-bottom: 24px;
	}
}

/* Header text, exact values from Figma node 1:69:
 * 16px, line-height 1, letter-spacing 0.24px, 8px gap;
 * title Jost Medium black, step count Jost Regular #626262. */
.lyricws-modal__heading {
	align-items: center;
	column-gap: 8px;
}
.lyricws-modal__title {
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 500;
	line-height: 1;
	letter-spacing: 0.24px;
	white-space: nowrap;
	color: var(--lyricws-color-ink);
}
.lyricws-steps-label {
	font-size: calc(16px * var(--lyricws-text-scale, 1));
	font-weight: 400;
	line-height: 1;
	letter-spacing: 0.24px;
	color: var(--lyricws-color-muted);
}

/* Follow-up box: smooth reveal. The 32px space above it is padding (not
 * margin) so it opens and closes together with the box. */
.lyricws-followup {
	margin: 0;
	padding-top: 32px;
	overflow: hidden;
}
/* Opening: height eases out gently over 375ms, and the content fades in
 * slightly after the space starts opening, so it doesn't pop in.
 * Closing: the content fades out first, then the space closes. */
.lyricws-followup.is-animating {
	transition:
		height 375ms cubic-bezier(0.22, 1, 0.36, 1),
		opacity 300ms ease-out 75ms;
}
.lyricws-followup.is-animating.is-collapsing {
	transition:
		height 375ms cubic-bezier(0.22, 1, 0.36, 1) 50ms,
		opacity 175ms ease-in;
}
@media (prefers-reduced-motion: reduce) {
	.lyricws-followup.is-animating {
		transition: none;
	}
}

/* All titles and question headings are pure black (#000000). */
.lyricws-invite__heading,
.lyricws-modal__title,
.lyricws-field__legend,
.lyricws-field__label.lyricws-field__legend,
.lyricws-followup__label,
.lyricws-thankyou__message {
	color: #000000;
}

/* Anchor the survey near the top of the screen (desktop / tablet) instead
 * of centering it, so the header, progress bar and close button stay put
 * between steps and while the step-3 follow-up opens. Only the bottom edge
 * moves. The thank-you screen appears in the same place. Phones keep their
 * existing full-height layout. */
@media (min-width: 481px) {
	.lyricws-overlay,
	.lyricws-overlay--confirmation {
		align-items: flex-start;
		padding-top: max(24px, 8vh);
		padding-bottom: 24px;
	}
	.lyricws-modal,
	.lyricws-modal.lyricws-modal--confirmation {
		max-height: calc(100vh - max(24px, 8vh) - 24px);
	}
}

/* Progress bar: each segment fills left-to-right when you move forward and
 * empties right-to-left when you go Back (375ms, same easing as the
 * step-3 follow-up). Instant with "reduce motion". */
.lyricws-steps-segment,
.lyricws-steps-segment.is-filled {
	position: relative;
	overflow: hidden;
	background: var(--lyricws-color-track);
}
.lyricws-steps-segment::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--lyricws-color-step-active);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 375ms cubic-bezier(0.22, 1, 0.36, 1);
}
.lyricws-steps-segment.is-filled::after {
	transform: scaleX(1);
}
@media (prefers-reduced-motion: reduce) {
	.lyricws-steps-segment::after {
		transition: none;
	}
}
@media (forced-colors: active) {
	.lyricws-steps-segment::after {
		background: CanvasText;
	}
}

/* Pinned footer: Close/Back + Next/Submit stay at the bottom of the survey;
 * questions scroll above them when they don't fit. A thin divider appears
 * only when there's more content underneath. The modal's bottom padding
 * moves into the footer so it sits flush with the bottom edge. */
.lyricws-modal {
	padding-bottom: 0;
}
.lyricws-modal.lyricws-modal--confirmation {
	padding-bottom: 0;
}
.lyricws-modal__footer {
	position: sticky;
	bottom: 0;
	z-index: 1;
	margin: 56px -24px 0;
	padding: 24px;
	background: #ffffff;
	border-top: 1px solid transparent;
	transition: border-color 150ms ease-out, box-shadow 150ms ease-out;
}
.lyricws-modal__footer.is-stuck {
	border-top-color: rgba(0, 0, 0, 0.12);
	box-shadow: 0 -6px 12px -8px rgba(0, 0, 0, 0.18);
}
@media (max-width: 480px) {
	.lyricws-modal__footer {
		margin: 32px -16px 0;
		padding: 16px;
	}
}
@media (prefers-reduced-motion: reduce) {
	.lyricws-modal__footer {
		transition: none;
	}
}

/* ----------------------------------------------------------------------
 * Mobile refinements
 * 1. Keep controls clear of the iPhone home indicator (env() insets are
 *    0 on devices without one, and when the page doesn't extend under it).
 * 2. Size to the visible screen (dvh), so browser toolbars showing/hiding
 *    can't push the pinned buttons off screen. 100vh stays as a fallback.
 * 3. Back / Next split the width 50/50 for bigger thumb targets.
 * -------------------------------------------------------------------- */
@media (min-width: 481px) {
	.lyricws-modal,
	.lyricws-modal.lyricws-modal--confirmation {
		max-height: calc(100dvh - max(24px, 8vh) - 24px);
	}
}
@media (max-width: 480px) {
	.lyricws-overlay {
		height: 100vh;
		height: 100dvh;
	}
	.lyricws-modal {
		height: 100%;
		max-height: 100%;
	}
	.lyricws-modal__footer {
		gap: 12px;
		padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
	}
	.lyricws-modal__footer .lyricws-btn {
		flex: 1 1 0;
		min-width: 0;
	}
	.lyricws-invite {
		padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
	}
	.lyricws-thankyou__footer {
		padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
	}
	.lyricws-thankyou__footer .lyricws-btn,
	.lyricws-invite .lyricws-btn {
		width: 100%;
	}
}

/* Mobile buttons: 46px tall, 16px text (all buttons: footer, invitation,
 * thank-you). 13.5px padding + 16px text + 1.5px borders = 46px. */
@media (max-width: 480px) {
	.lyricws-btn,
	.lyricws-modal__footer .lyricws-btn,
	.lyricws-thankyou__footer .lyricws-btn,
	.lyricws-invite .lyricws-btn {
		min-height: 46px;
		height: 46px;
		padding-top: 13.5px;
		padding-bottom: 13.5px;
		font-size: calc(16px * var(--lyricws-text-scale, 1));
		letter-spacing: 1.12px;
	}
}

/* Mobile buttons: 15px text, still 46px tall (14px padding + 15px text +
 * 1.5px borders). Share Feedback's arrow scaled to match. */
@media (max-width: 480px) {
	.lyricws-btn,
	.lyricws-modal__footer .lyricws-btn,
	.lyricws-thankyou__footer .lyricws-btn,
	.lyricws-invite .lyricws-btn {
		padding-top: 14px;
		padding-bottom: 14px;
		font-size: calc(15px * var(--lyricws-text-scale, 1));
		letter-spacing: 1.05px;
	}
	.lyricws-invite .lyricws-icon--arrow {
		width: 20px;
		height: 14px;
	}
}

/* ----------------------------------------------------------------------
 * Invitation refinements
 * - Smaller desktop card (440px) so it reads as a corner invitation, not
 *   an interruption; heading 28px.
 * - Always stacks above the site's own floating elements (back-to-top,
 *   helper icons): z-index is set on .lyricws-invite with !important.
 * - Entrance uses the same 375ms easing as the rest of the survey.
 * - Compact on phones (heading 22px, tighter spacing).
 * -------------------------------------------------------------------- */
.lyricws-invite {
	width: min(440px, calc(100vw - 32px));
	padding: 28px;
	animation: lyricws-fade-slide-in 375ms cubic-bezier(0.22, 1, 0.36, 1);
}
.lyricws-invite__heading {
	margin: 0 60px 16px 0;
	font-size: calc(28px * var(--lyricws-text-scale, 1));
	letter-spacing: -0.42px;
}
.lyricws-invite__description {
	margin: 0 0 32px 0;
	font-size: calc(18px * var(--lyricws-text-scale, 1));
}
.lyricws-invite__close {
	top: 22px;
	right: 20px;
}
@media (prefers-reduced-motion: reduce) {
	.lyricws-invite {
		animation: none;
	}
}
@media (max-width: 480px) {
	.lyricws-invite {
		width: 100%;
		padding: 20px 16px calc(20px + env(safe-area-inset-bottom, 0px));
	}
	.lyricws-invite__heading {
		margin: 0 48px 8px 0;
		font-size: calc(22px * var(--lyricws-text-scale, 1));
		letter-spacing: -0.33px;
	}
	.lyricws-invite__description {
		margin: 0 0 20px 0;
		font-size: calc(16px * var(--lyricws-text-scale, 1));
	}
	.lyricws-invite__close {
		top: 10px;
		right: 6px;
	}
}


/* ----------------------------------------------------------------------
 * Readability for older visitors
 * 1. Nothing below 16px on phones (scale captions, "(optional)").
 * 2. Mobile button text back to 16px (buttons stay 46px tall).
 * 3. Answer box borders #8C8C8C (3.4:1), matching the text box.
 * 4. Error red deepened to #C8102E (5.9:1).
 * 5. All font sizes follow the visitor's default text-size setting via
 *    --lyricws-text-scale (set by the script; 1 = the standard 16px).
 * -------------------------------------------------------------------- */
.lyricws-root {
	--lyricws-color-error: #c8102e;
}
.lyricws-radio-option,
.lyricws-scale-option {
	border-color: var(--lyricws-color-input-border);
}
@media (max-width: 480px) {
	.lyricws-scale-captions,
	.lyricws-followup__optional {
		font-size: calc(16px * var(--lyricws-text-scale, 1));
	}
	.lyricws-btn,
	.lyricws-modal__footer .lyricws-btn,
	.lyricws-thankyou__footer .lyricws-btn,
	.lyricws-invite .lyricws-btn {
		height: auto;
		min-height: 46px;
		padding-top: 13.5px;
		padding-bottom: 13.5px;
		font-size: calc(16px * var(--lyricws-text-scale, 1));
		letter-spacing: 1.12px;
	}
	.lyricws-invite .lyricws-icon--arrow {
		width: 21px;
		height: 15px;
	}
}

/* Phones: the survey fills the screen, so pin Back / Next to the bottom
 * of the screen (thumb zone) even when a step is short. */
@media (max-width: 480px) {
	.lyricws-modal:not(.lyricws-modal--confirmation) {
		display: flex;
		flex-direction: column;
	}
	.lyricws-modal:not(.lyricws-modal--confirmation) > * {
		flex-shrink: 0;
	}
	.lyricws-modal:not(.lyricws-modal--confirmation) #lyricws-modal-body,
	.lyricws-modal:not(.lyricws-modal--confirmation) #lyricws-form {
		flex: 1 0 auto;
		display: flex;
		flex-direction: column;
	}
	#lyricws-form > .lyricws-step {
		padding-bottom: 32px;
	}
	#lyricws-form > .lyricws-modal__footer {
		margin-top: auto;
	}
}

/* Mobile invitation, from Figma node 17:588: a floating card inset 10px
 * from the screen edges (plus the iPhone home-bar area), 20px padding,
 * 26px heading, 16px gray body, full-width 50px button. */
@media (max-width: 480px) {
	.lyricws-invite {
		left: 10px;
		right: 10px;
		bottom: calc(10px + env(safe-area-inset-bottom, 0px));
		width: auto;
		padding: 20px;
		box-shadow: 1px 3px 12px rgba(0, 0, 0, 0.42); /* $survey-drop-shadow, in black */
	}
	.lyricws-invite__heading {
		margin: 0 40px 14px 0; /* 24px close icon + 16px gap */
		font-size: calc(26px * var(--lyricws-text-scale, 1));
		line-height: 1.16;
		letter-spacing: 0;
		text-align: left;
	}
	.lyricws-invite__description {
		margin: 0 0 18px 0;
		font-size: calc(16px * var(--lyricws-text-scale, 1));
		line-height: 1.19;
		color: var(--lyricws-color-muted);
		text-align: left;
	}
	/* 24px icon, centered in a 44px tap area */
	.lyricws-invite__close {
		top: 10px;
		right: 10px;
		width: 44px;
		height: 44px;
	}
	.lyricws-invite__close .lyricws-icon--close {
		width: 16px;
		height: 16px;
	}
	.lyricws-invite .lyricws-btn {
		width: 100%;
		height: auto;
		min-height: 50px;
		padding: 14px 22px;
		font-size: calc(16px * var(--lyricws-text-scale, 1));
		font-weight: 600;
		letter-spacing: 1.12px;
	}
	.lyricws-invite .lyricws-icon--arrow {
		width: 20px;
		height: 12px;
	}
}

/* Phones: 24px side padding in the survey, matching lyricopera.org's
 * mobile margins (~24-26px). The pinned footer stays full-bleed. */
@media (max-width: 480px) {
	.lyricws-modal {
		padding-left: 24px;
		padding-right: 24px;
		padding-top: 24px;
	}
	.lyricws-modal__footer,
	#lyricws-form > .lyricws-modal__footer {
		margin-left: -24px;
		margin-right: -24px;
		padding-left: 24px;
		padding-right: 24px;
	}
	.lyricws-thankyou {
		padding-left: 24px;
		padding-right: 24px;
	}
	.lyricws-thankyou__footer {
		padding-left: 24px;
		padding-right: 24px;
	}
}

/* Step 2 scale: desktop keeps the row of five boxes; phones get a vertical
 * list matching steps 1 and 3, with each option labeled
 * ("1 – Very difficult" ... "5 – Very easy"). The end captions are
 * redundant there, so they're hidden. */
.lyricws-scale-option__meaning {
	display: none;
}
@media (max-width: 480px) {
	.lyricws-scale {
		display: flex;
		flex-direction: column;
		gap: 8px;
	}
	.lyricws-scale-option {
		flex-direction: row;
		justify-content: flex-start;
		align-items: center;
		gap: 12px;
		min-height: 0;
		padding: 14px 12px;
		text-align: left;
	}
	.lyricws-scale-option.is-selected {
		padding: 12.5px 10.5px;
	}
	.lyricws-scale-option__number {
		font-size: calc(18px * var(--lyricws-text-scale, 1));
		font-weight: 600;
	}
	.lyricws-scale-option__meaning {
		display: inline;
		margin-left: -12px; /* cancel the row gap: the text's own spaces set the spacing, as in step 3 */
		font-size: calc(18px * var(--lyricws-text-scale, 1));
		font-weight: 400;
		color: var(--lyricws-color-ink);
	}
	.lyricws-scale-captions {
		display: none;
	}
	.lyricws-field.has-error .lyricws-scale {
		padding: 16px;
	}
}

/* Desktop invitation + thank-you, from Figma node 3:1672: both 600px wide,
 * so "Help us improve Lyric's website" fits on one line at 36px.
 * Replaces the earlier 440px experiment. Phones are unaffected. */
@media (min-width: 481px) {
	.lyricws-invite {
		right: 32px;
		bottom: 32px;
		width: min(600px, calc(100vw - 32px));
		padding: 32px;
	}
	.lyricws-invite__heading {
		margin: 0 76px 24px 0; /* 44px close button + 32px gap */
		font-size: calc(36px * var(--lyricws-text-scale, 1));
		line-height: 1.22;
		letter-spacing: -0.54px;
	}
	.lyricws-invite__description {
		margin: 0 0 44px 0;
		font-size: calc(20px * var(--lyricws-text-scale, 1));
		line-height: 1.22;
		color: var(--lyricws-color-body);
	}
	.lyricws-invite__close {
		top: 32px;
		right: 32px;
		width: 44px;
		height: 44px;
	}
	.lyricws-modal.lyricws-modal--confirmation {
		width: min(600px, 100%);
	}
	.lyricws-thankyou {
		padding: 48px 32px 0;
	}
	.lyricws-thankyou__footer {
		padding: 44px 32px 32px;
	}
}

/* Darker drop shadow everywhere (invitation, survey, thank-you), matching
 * the mobile card: Figma $survey-drop-shadow in black. */
.lyricws-root {
	--lyricws-shadow: 1px 3px 12px rgba(0, 0, 0, 0.42);
}
.lyricws-invite {
	box-shadow: var(--lyricws-shadow);
}

/* ----------------------------------------------------------------------
 * Site style guards
 * lyricopera.org's global stylesheet gives every <button> a trailing arrow
 * (button:after) and pushes down anything that follows a <label>
 * (label + * { margin-top: .5rem !important }). Inside the widget that put
 * an arrow on the X buttons, left arrows hanging off the footer buttons,
 * and made the "1" box on the rating scale taller than 2-5.
 * -------------------------------------------------------------------- */
.lyricws-root button::before,
.lyricws-root button::after {
	content: none !important;
	display: none !important;
}
.lyricws-root .lyricws-scale > .lyricws-scale-option {
	margin-top: 0 !important;
}

/* Footer buttons (Close / Back / Next / Submit): same arrow, text-to-arrow
 * gap, and right padding as the invitation's Share Feedback button. */
.lyricws-modal__footer .lyricws-btn,
.lyricws-thankyou__footer .lyricws-btn {
	gap: 10.5px;
	padding-right: 23.5px;
}
.lyricws-modal__footer .lyricws-icon--arrow,
.lyricws-thankyou__footer .lyricws-icon--arrow {
	width: 23px;
	height: 16px;
	transition: transform 300ms ease-out;
}
.lyricws-modal__footer .lyricws-btn:hover .lyricws-icon--arrow,
.lyricws-modal__footer .lyricws-btn:focus-visible .lyricws-icon--arrow,
.lyricws-thankyou__footer .lyricws-btn:hover .lyricws-icon--arrow,
.lyricws-thankyou__footer .lyricws-btn:focus-visible .lyricws-icon--arrow {
	transform: translateX(4px);
}
.lyricws-btn--secondary .lyricws-icon--arrow {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 26 16'%3E%3Cpath d='M0 8h24M17 1l7 7-7 7' stroke='%2391004c' stroke-width='2' fill='none'/%3E%3C/svg%3E");
}
@media (prefers-reduced-motion: reduce) {
	.lyricws-modal__footer .lyricws-icon--arrow,
	.lyricws-thankyou__footer .lyricws-icon--arrow {
		transition: none;
	}
}
@media (max-width: 480px) {
	.lyricws-modal__footer .lyricws-icon--arrow,
	.lyricws-thankyou__footer .lyricws-icon--arrow {
		width: 20px;
		height: 14px;
	}
}
