/* RHSC membership application form — layout.

   Controls (inputs, selects, the 32px pill shape) come from assets/css/forms.css
   via the starter-forms dependency declared in functions.php. Nothing here
   restyles a control; this file positions them.

   Markup contract: patterns/membership-form.php.
   Behaviour: assets/js/membership-form.js.

   Steps are shown/hidden with the `hidden` attribute rather than a class so the
   accessibility tree matches the visual state; `[hidden]` needs the explicit
   display:none below because .rhsc-step sets display:flex. */

/* 20px of breathing room on mobile, dropped once there is room for the
   centred 720px column. padding rather than margin so the max-width still
   measures the content box and the form stays 720px on desktop.

   Applied to the subscribe form too: it shares this stylesheet by declaring it
   as a dependency, and had the same flush-to-edge problem. */
.rhsc-membership-form,
.rhsc-subscribe-form {
	max-width: 720px;
	margin-inline: auto;
	padding-inline: 20px;
}

@media (min-width: 782px) {
	.rhsc-membership-form,
	.rhsc-subscribe-form {
		padding-inline: 0;
	}
}

/* Each step is a vertical stack. Declared before the [hidden] rule below,
   which must override it — hence the !important there. */
.rhsc-step {
	display: flex;
	flex-direction: column;
}

.rhsc-membership-form [hidden] {
	display: none !important;
}

/* Each step's <h2> exists only to give the section an accessible name and a
   focus target on advance. It must be visually hidden but still reachable by
   assistive tech — so NOT display:none and NOT visibility:hidden.

   Scoped locally rather than relying on the ambient .screen-reader-text: the
   rule that reaches this page sets position:absolute without clipping, which
   left the heading rendering at its full 214x51px. Because the JS focuses
   these headings on every step change, that put a visible box on screen at
   each transition. */
.rhsc-membership-form .screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Focusing a clipped heading must not scroll or paint an outline — it is a
   programmatic focus target, never a user-visible control. */
.rhsc-membership-form .screen-reader-text:focus {
	outline: none;
}

/* The submission sink. Must stay in the layout (not display:none) or some
   browsers refuse to use it as a form target. */
.rhsc-capsule-sink {
	position: absolute;
	width: 0;
	height: 0;
	border: 0;
	visibility: hidden;
}

/* ───────────────────────────────────────────────────────────────── stepper */
.rhsc-stepper {
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	gap: 8px;
	margin: 0 0 32px;
	padding: 0;
	list-style: none;
	position: relative;
}

/* Connecting rule, behind the numbers. Three items at flex:1 put the first and
   last circle centres at 1/6 and 5/6 of the track, so the rule must start and
   stop there — any wider and it pokes out to the left of "1" / right of "3". */
.rhsc-stepper::before {
	content: "";
	position: absolute;
	top: 14px;
	left: calc(100% / 6);
	right: calc(100% / 6);
	height: 3px;
	background: var(--wp--preset--color--neutral-20, #dddddd);
	z-index: 0;
}

.rhsc-stepper__item {
	position: relative;
	z-index: 1;
	flex: 1;
	text-align: center;
	font-size: 14px;
	line-height: 1.4;
}

.rhsc-stepper__num {
	display: grid;
	place-items: center;
	width: 28px;
	height: 28px;
	margin: 0 auto 8px;
	border-radius: 50%;
	background: var(--wp--preset--color--neutral-20, #dddddd);
	color: var(--wp--preset--color--neutral-inky-deep, #181423);
	font-weight: 600;
}

/* Three states, three appearances. is-current and is-done used to share this
   rule, so a finished step was indistinguishable from the one being filled in —
   the stepper showed progress only by which circle happened to be orange, and
   after step 1 there were two of them. */
.rhsc-stepper__item.is-current .rhsc-stepper__num {
	background: var(--wp--preset--color--orange-100, #FF6B35);
	color: var(--wp--preset--color--neutral-inky-deep, #181423);
}

/* Done: a dark circle carrying a tick instead of its number, per the design. */
.rhsc-stepper__item.is-done .rhsc-stepper__num {
	background: var(--wp--preset--color--neutral-inky-deep, #181423);
	color: var(--wp--preset--color--custom-white, #ffffff);
}

/* The tick is centred by position, not by the grid.

   The circle is a grid and the digit is a grid ITEM alongside the ::before
   tick, so the two stacked into separate rows: with `font-size: 0` the digit
   still claimed one (measured: grid-template-rows "20px 8px"), which pushed
   the tick above the circle's centre. Taking the tick out of flow and centring
   it on the box makes its position independent of whatever else the grid holds.

   `font-size: 0` still hides the digit, and is kept rather than `display: none`
   or `visibility: hidden` because those would drop it from the accessibility
   tree as well — the list should still linearise as "1, 2, 3" for a screen
   reader. */
.rhsc-stepper__item.is-done .rhsc-stepper__num {
	position: relative;
	font-size: 0;
}

.rhsc-stepper__item.is-done .rhsc-stepper__num::before {
	content: '\e91c';
	font-family: 'Icon-Font';
	font-size: 12px;
	font-weight: 400;
	line-height: 1;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
}

/* The rule behind the circles is grey for the whole track; the completed part
   is drawn over it by the done items themselves. Each item spans a third of the
   row, so a segment starting at its own centre reaches the next circle. Not on
   the last item — there is nothing after it to join to. */
.rhsc-stepper__item.is-done:not(:last-child)::after {
	content: "";
	position: absolute;
	top: 14px;
	left: 50%;
	width: 100%;
	height: 3px;
	background: var(--wp--preset--color--neutral-inky-deep, #181423);
	z-index: -1;
}

/* The label under each circle. Had no rule of its own, so it inherited the
   item's 14px/400 and read lighter than the design, which sets these as the
   heading for their step rather than as caption text. display: block so the
   two-word labels wrap to their own lines under the circle instead of running
   as inline text against the neighbouring item. */
.rhsc-stepper__label {
	display: block;
	font-size: 15px;
	font-weight: 600;
	color: var(--wp--preset--color--neutral-inky-deep, #181423);
}

/* The upcoming steps are muted, so the current one reads as where you are. */
.rhsc-stepper__item:not(.is-current):not(.is-done) .rhsc-stepper__label {
	font-weight: 500;
	color: var(--wp--preset--color--neutral-60, #6B6B6B);
}

/* ──────────────────────────────────────────────────────────────── fields */

/* Italic, per the design — it is an aside about the form, not part of it. */
.rhsc-form__required-note {
	font-size: 14px;
	font-style: italic;
	margin: 0 0 16px;
}

.rhsc-field {
	margin: 0 0 20px;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.rhsc-field__label {
	font-size: 14px;
	font-weight: 500;
}

.rhsc-req {
	color: var(--wp--preset--color--orange-100, #FF6B35);
	margin-left: 2px;
}

/* ─────────────────────────────────────────── floating labels (opt-in)

   The label starts inside the pill reading as placeholder text, then shrinks
   and rises to the top of the pill on focus or once the field holds a value.

   Mechanism: the label is taken out of flow and positioned over the control,
   and the control gains top padding to reserve the floated label's line.
   There is NO new wrapper — .rhsc-field is a <p>, which cannot legally contain
   a <div>, and the existing <label> is already inline-level.

   The floated state is driven by :focus-within (focus) OR an `is-filled` class
   that membership-form.js maintains (value). A pure-CSS
   :not(:placeholder-shown) was rejected: it never matches a <select>, and
   three inputs carry a real placeholder="https://" that must not fight the
   label for the same line.

   Opt-IN, not opt-out: a field added later without this class renders as a
   plain stacked label, which is safe. The long-question labels deliberately
   keep .rhsc-field--static-label — at 50-80 characters none can read as
   placeholder text at any size, and the copy is client-approved. */
.rhsc-field--float {
	position: relative;
	/* The label is out of flow, so the column gap would leave a 6px hole. */
	gap: 0;
}

.rhsc-field--float .rhsc-field__label {
	position: absolute;
	/* 1px border + 12px padding, so the resting label sits exactly on the
	   value's own baseline box. */
	top: 18px;
	left: 21px;
	right: 21px;
	z-index: 1;
	/* Never eat a click meant for the control beneath: label activation would
	   focus a <select> without opening it. The pill is a far larger target and
	   for/id association is unaffected, so this costs nothing. */
	pointer-events: none;
	transform-origin: left top;
	transition: transform 120ms ease-out, color 120ms ease-out;
	font-size: 16px;
	font-weight: 400;
	line-height: 24px;
	/* neutral-70, not the mock's neutral-50 (#B5B3B8): while resting this text
	   IS the field's only visible label, so it must meet WCAG 1.4.3. neutral-50
	   on white is 2.3:1 and fails; neutral-70 is 4.97:1 and passes. */
	color: var(--wp--preset--color--neutral-70, #726e79);
	/* A long label must not wrap while resting — two lines in a single-line
	   pill breaks the placeholder illusion. Truncation is visual only: the full
	   string stays the accessible name and returns the moment it floats. */
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Floated: 0.75 scale (16px → 12px) up to the pill's top inset. transform
   rather than font-size so the transition is composited and the text does not
   reflow mid-animation. */
.rhsc-field--float:focus-within .rhsc-field__label,
.rhsc-field--float.is-filled .rhsc-field__label {
	transform: translateY(-12px) scale(0.75);
}

/* Reserve the floated label's line. Applied unconditionally, not only when
   floated, so the control's height never changes and the pill does not jump
   on focus.

   Scoped through .rhsc-form and typed on the input to outrank the pill rule
   above (`.rhsc-form input[type="text"]`, specificity 0,2,1). Without the
   attribute selectors this loses the cascade and the value renders UNDER the
   floated label — the padding silently stays 12px. */
.rhsc-form .rhsc-field--float input[type="text"],
.rhsc-form .rhsc-field--float input[type="email"],
.rhsc-form .rhsc-field--float input[type="url"],
.rhsc-form .rhsc-field--float input[type="tel"],
.rhsc-form .rhsc-field--float select.rhsc-field__input {
	padding-top: 22px;
	padding-bottom: 6px;
}

/* Textareas need the value to start below the label, not beside it. */
.rhsc-form .rhsc-field--float textarea {
	padding-top: 24px;
	padding-bottom: 12px;
}

/* A <select> always renders its selected option, so an EMPTY one still shows
   "Please select" — and the resting label sits on that same line, giving two
   overlapping strings ("Country:" over "Please select"). A text input has no
   such problem: empty means nothing is drawn.

   So the placeholder option is made transparent while the label is resting, and
   returns the moment the label floats clear of the value line. The text stays
   in the DOM and keeps its colour in the open dropdown — only the closed
   control's rendering of it is hidden, because that is the only place the
   collision happens.

   Keyed off the same two states that float the label, so the two can never
   disagree: whenever the label is up, the placeholder is visible beneath it. */
.rhsc-field--float:not(.is-filled):not(:focus-within) select.rhsc-field__input {
	color: transparent;
}

/* The options themselves are never transparent — only the closed control was. */
.rhsc-field--float select.rhsc-field__input option {
	color: var(--wp--preset--color--neutral-inky-deep, #181423);
}

/* forms.css reserves 44px on the right of a select for the chevron; the
   floated label must stop short of it or a long option runs under the caret. */
.rhsc-field--float:has(select) .rhsc-field__label {
	right: 45px;
}

/* The `https://` hints stay hidden until the label has floated clear, so the
   two never occupy the same line. */
.rhsc-field--float .rhsc-field__input::placeholder {
	color: transparent;
}

.rhsc-field--float:focus-within .rhsc-field__input::placeholder {
	color: var(--wp--preset--color--neutral-50, #B5B3B8);
	opacity: 1;
}

/* An invalid field's floated label turns red with its border, so the error
   reads as one signal rather than a red box with a neutral caption. */
/* Both label styles, not just the floating one. A static label sets
   `color: inherit` (see .rhsc-field--static-label below), so without this it
   stays black while the border, message and summary around it all go red —
   the long-question fields looked untouched next to their own error. */
.rhsc-field--float:has([aria-invalid="true"]) .rhsc-field__label,
.rhsc-field--static-label:has([aria-invalid="true"]) .rhsc-field__label,
.rhsc-field:has([aria-invalid="true"]) > .rhsc-field__label {
	color: var(--wp--preset--color--error-400, #FF2632);
}

/* gap:0 above closed the hole the out-of-flow label left, which also removed
   the counter's breathing room. Put it back on the counter only. */
.rhsc-field--float .rhsc-counter {
	margin-top: 6px;
}

@media (prefers-reduced-motion: reduce) {
	.rhsc-field--float .rhsc-field__label {
		transition: none;
	}
}

/* The long-question fields opt out: at 50-80 characters none of them can read
   as placeholder text at any size, and the copy is client-approved and not to
   be shortened. Explicit rather than implicit — the class documents that this
   was deliberate, and the rebuild tool asserts the count. Visually identical
   to the pre-restyle default. */
.rhsc-field--static-label .rhsc-field__label {
	position: static;
	font-size: 14px;
	font-weight: 500;
	color: inherit;
}

/* The pill itself — box, border, radius, padding, type — now comes from
   assets/css/forms.css, which applies it to every native control site-wide.
   The block that used to sit here duplicated it at 1px/42px and then had to be
   corrected by a second `border-width: 3px` rule further down; both are gone.
   Only genuinely form-specific rules remain below. */

.rhsc-form :is(input, textarea, select):focus-visible {
	outline: 2px solid var(--wp--preset--color--orange-100, #FF6B35);
	outline-offset: 1px;
}

/* Error/400 (#FF2632), matching the invalid border below and the Figma Error
   state — the message and the field it belongs to now read as one thing.
   Bumped from 13px: this is the only text that explains a blocked step, and
   500 gives it enough weight to be seen without shouting. */
.rhsc-error {
	color: var(--wp--preset--color--error-400, #FF2632);
	font-size: 14px;
	font-weight: 500;
	line-height: 1.4;
}

.rhsc-field > .rhsc-error {
	margin-top: 8px;
}

.rhsc-field:not(.rhsc-field--float) > .rhsc-error {
	margin-top: 2px;
}

.rhsc-counter {
	font-size: 12px;
	color: #6b6875;
	align-self: flex-end;
}

/* These are <h2> as of the heading-level change, so they now inherit the
   theme's h2 sizing from theme.json/global styles — which is a page-title size,
   far larger than the 22px this row is meant to be. font-size is therefore
   restated, and line-height with it, so the value does not depend on whatever
   the global h2 happens to carry. */
/* Form headings declare their own typography rather than inheriting it.

   theme.json styles headings per TAG: h1/h2/h4 are Young Serif, h3 is
   Instrument Sans at weight 500. That is a deliberate global choice, but it
   means a form heading's appearance depended on which tag its pattern happened
   to use — and the three forms did not agree. membership-form.php and
   join-group-form.php write .rhsc-section-title as <h2> (serif 400); the
   subscribe form writes it as <h3>, so the SAME class rendered sans 500 there.
   Heading level is a document-structure decision, not a styling one, so the
   class pins the font instead of the tag deciding it.

   Young Serif to match the section titles the client signed off on, and to
   stay consistent with .rhsc-group-title below. */
.rhsc-section-title {
	margin: 32px 0 8px;
	font-family: var(--wp--preset--font-family--young-serif, "Young Serif", serif);
	font-size: 22px;
	font-weight: 400;
	line-height: 1.3;
}

.rhsc-step > .rhsc-section-title:first-child {
	margin-top: 0;
}

.rhsc-section-intro {
	margin: 0 0 16px;
	font-size: 15px;
}

/* The design sets every link in this form's explanatory copy — the Reference
   intro and the consent note — bold and underlined in the body colour.

   This is now the SAME treatment css-framework.css gives every inline body
   link; it used to be an exception to that file's brand-orange rule, and the
   site-wide default was changed to match this one rather than the other way
   round. The rule still has to exist here: these are plain <p> elements inside
   a wp:html block, and the framework selector only reaches
   `main p.wp-block-paragraph` and list items, so it never matches them. Keep
   the two in step — if the framework treatment changes again, this changes
   with it.

   .rhsc-check__label is in the list because the consent checkboxes' labels are
   prose too — "I agree to the Terms & Conditions and Cookies & Privacy" — and
   their links were rendering at weight 400 with no underline, one of the
   inconsistent variants this pass removed. It covers the subscribe form as
   well, which uses the same class and takes this file as a dependency.

   These paragraphs carry no .has-link-color opt-out (unlike the thank-you
   cards further down this file) and do not need one, for the same reason.
   Only the global-styles default has to be beaten here, and that is emitted at
   (0,0,1), so no !important is required. */
.rhsc-section-intro a,
.rhsc-form__consent-note a,
.rhsc-check__label a {
	font-weight: 700;
	text-decoration: underline;
	color: inherit;
}

/* ─────────────────────────────────────────────────────────── checkboxes */
.rhsc-check {
	display: flex;
	align-items: flex-start;
	/* wrap so an error message can drop to its own line — see below */
	flex-wrap: wrap;
	gap: 10px;
	margin: 0 0 12px;
}

/* A checkbox's error belongs UNDER the box and its label, not beside them.
   ---------------------------------------------------------------------------
   showError() looks for a .rhsc-field ancestor and falls back to the field's
   parentNode. A checkbox has no .rhsc-field wrapper (a <p class="rhsc-check">
   is the whole unit), so the message is appended into that flex ROW and became
   a third flex item sitting to the right of the label — far from the box it
   describes, and on a long Terms label it landed in the whitespace beside the
   text with nothing visually tying the two together.

   width:100% alone is not enough: .rhsc-check defaults to flex-wrap:nowrap, so
   a 100%-wide third item is compressed onto the same line rather than moved to
   the next one. The wrap above and the basis here are a pair; changing one
   without the other reintroduces the bug.

   margin-left aligns the message with the LABEL rather than the checkbox, so
   it reads as a continuation of the sentence above it: 24px box + 10px gap. */
.rhsc-check > .rhsc-error {
	flex: 0 0 100%;
	margin-left: 34px;
}

.rhsc-form__form
	:is(.rhsc-section-intro, .rhsc-section-title, .rhsc-group-title):has(
		+ .rhsc-check
	) {
	margin-bottom: 0;
}

.rhsc-form__form
	:is(.rhsc-section-intro, .rhsc-section-title, .rhsc-group-title)
	+ .rhsc-check {
	margin-top: 16px;
}

/* 24x24, 4px radius, 2px Inky Deep border, per the membership frame.

   appearance:none is unavoidable: accent-color can recolour a native checkbox
   but cannot give it a radius or a border width, which is the whole spec here.
   That means the tick has to be drawn too — hence the ::after chevron below.

   margin:0 (not the old 2px top nudge) because .rhsc-check aligns the row with
   align-items:flex-start and the box is now the same 24px as the label's line
   box, so the two line up on their own. */
.rhsc-check__input {
	flex: none;
	appearance: none;
	-webkit-appearance: none;
	position: relative;
	width: 24px;
	height: 24px;
	margin: 0;
	border: 2px solid var(--wp--preset--color--neutral-inky-deep, #181423);
	border-radius: 4px;
	background-color: var(--wp--preset--color--custom-white, #fff);
	cursor: pointer;
}

.rhsc-check__input:checked {
	background-color: var(--wp--preset--color--neutral-inky-deep, #181423);
}

/* The tick: a rotated rectangle with two borders, which needs no icon font and
   no SVG data-URI, and scales with the box if the size ever changes.
   Positioned slightly above centre because a chevron's optical centre sits
   below its bounding box. */
.rhsc-check__input:checked::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 45%;
	width: 5px;
	height: 10px;
	border: solid var(--wp--preset--color--custom-white, #fff);
	border-width: 0 2px 2px 0;
	transform: translate(-50%, -50%) rotate(45deg);
}

/* Matches the field treatment: the border colour carries the state. */
.rhsc-check__input:hover {
	border-color: var(--wp--preset--color--orange-100, #FF6B35);
}

/* Keyboard focus needs a real indicator here — unlike the text fields, a
   checkbox has no 3px border to recolour without also changing its resting
   look, so the ring stays. */
.rhsc-check__input:focus-visible {
	outline: 2px solid var(--wp--preset--color--orange-100, #FF6B35);
	outline-offset: 2px;
}

/* flex/min-width let a long label share the row with its box.
   ---------------------------------------------------------------------------
   .rhsc-check wraps (an error message has to be able to drop to its own line —
   see .rhsc-check > .rhsc-error). A flex item is sized from its max-content
   width first, so a label whose unwrapped text is wider than the row measures
   the full container width, leaves no room beside the 24px box, and the wrap
   drops it entirely onto the next line. That is what happened to the Terms
   label: 720px of text in a 720px row, box stranded on the line above.

   flex:1 lets it shrink to the space left over; min-width:0 is what allows a
   flex item to go below max-content at all, so the two are a pair. Short
   labels are unaffected — they were never wider than the row. */
.rhsc-check__label {
	font-size: 15px;
	line-height: 1.5;
	flex: 1;
	min-width: 0;
}

/* Sub-headings inside the member-groups reveal: Working Groups, Advisory
   Groups, Additional Listservs. Lighter than .rhsc-section-title because they
   sit one level down, inside a section that already has a title. */
/* Sub-heading inside a section ("Working Groups", "Advisory Groups"). Same
   family as .rhsc-section-title above, one step down in size, so a form reads
   as one typographic system rather than switching family mid-question.

   line-height is set explicitly: theme.json gives h3 a flat 40px, which is a
   heading-3-sized value and leaves a visible gap above a 17px sub-head. */
.rhsc-group-title {
	margin: 20px 0 10px;
	font-family: var(--wp--preset--font-family--young-serif, "Young Serif", serif);
	font-size: 17px;
	font-weight: 400;
	line-height: 1.3;
}

.rhsc-group-title:first-child {
	margin-top: 0;
}

/* ────────────────────────────────────────────────── focus checkbox group */
/* A fieldset rather than a .rhsc-field, so it needs its own reset: browsers
   give fieldsets a default border, padding and margin that would otherwise
   box this group differently from every other question on the step. */
.rhsc-fieldset {
	margin: 0;
	padding: 0;
	border: 0;
	min-width: 0;
}

/* Browsers give <legend> 2px of inline padding, which pushes this question's
   text out of line with every other field label on the step. */
.rhsc-fieldset legend {
	display: block;
	padding-inline: 0;
}

.rhsc-focus-group .rhsc-section-intro {
	display: block;
	margin: 4px 0 12px;
}

/* The group's error is appended to the fieldset itself (see showError), so it
   lands after the last checkbox rather than beside the first one. */
.rhsc-focus-group .rhsc-error {
	display: block;
	margin-top: 4px;
}

.rhsc-reveal {
	margin: 0 0 16px;
	padding-left: 30px;
}

.rhsc-reveal--nested {
	padding-left: 0;
	margin-top: 12px;
}

/* Language preferences sit on one row on wider screens — three short labels
   stacked vertically read as a much heavier choice than they are. Wraps to
   stacked on narrow screens without a media query. */
.rhsc-reveal--inline .rhsc-check--inline {
	display: inline-flex;
	margin-right: 24px;
}

/* A group-level message ("Please select at least one.") is appended to the
   REVEAL container rather than to any one .rhsc-check, because the rule is
   about the set. The checkboxes above it are inline-flex items, so without
   this the message tucks in beside the last one. */
.rhsc-reveal--inline > .rhsc-error {
	display: block;
	width: 100%;
	margin-top: 4px;
}

/* The shared message for an any-of checkbox group ("tick at least one").

   Emitted by anyOfGroup() in join-group-form.js as the last child of the
   group's container, so it needs to break onto its own line regardless of what
   that container is: the language reveal is a flex row (hence the rule above),
   but #jag-groups is a plain block wrapping three <h3> sub-sections.

   display:block alone is not enough inside the flex reveal — flex children do
   not honour it — which is why the width/basis pair is set here too. A
   checkbox-row error needs BOTH flex-basis and wrap to clear the line; width
   alone cannot break it. */
.rhsc-error--group {
	display: block;
	flex: 0 0 100%;
	width: 100%;
	margin-top: 8px;
}

/* :empty so an un-triggered slot takes no vertical space. The element is
   created lazily on first validation and then reused, never removed. */
.rhsc-error--group:empty {
	display: none;
}

/* ──────────────────────────────────────────────────────── honeypot + nav */
/* Off-screen rather than display:none — bots skip undisplayed fields. */
.rhsc-hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.rhsc-nav {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	/* So .rhsc-nav__hint can take a full-width line of its own below the
	   buttons instead of being squeezed between them in the row-reverse
	   desktop layout. */
	flex-wrap: wrap;
	gap: 12px;
	margin-top: 32px;
}

/* Only ever shown when the timing guard blocks a real person (see
   showNavMessage in membership-form.js). Bots are never told anything. */
.rhsc-nav__message {
	margin: 0;
	font-size: 14px;
	font-weight: 500;
	color: var(--wp--preset--color--error-400, #FF2632);
}

/* The canonical site button is the core/button block style
   `is-style-primary-btn` (assets/css/block-styles/primary-button.css). Its
   selectors are scoped to `.wp-block-button__link`, which cannot reach the
   bare <button> elements this form uses, so the tokens are PORTED here rather
   than shared. If primary-button.css changes shape, change this to match —
   nothing will tell you they have drifted.

   Deliberately NOT scoped to .rhsc-membership-form: subscribe-form.php shares
   .rhsc-btn and declares this file as a dependency precisely to inherit it,
   so the Subscribe button gets the same site shape. Only the arrows and the
   gated disabled state below are membership-only. */
/* Mobile: every nav button spans the column. .rhsc-nav is a column flex at
   this width with align-items:flex-start, which shrink-wraps each button to
   its label — so "Go Back" and "Continue" came out different widths and left
   a ragged edge against the full-width fields above them. width:100% on the
   button plus stretch on the container is what squares them off.

   Both are needed: stretch alone cannot beat the inline-flex shrink-wrap, and
   width:100% alone is measured against a flex-start container that has already
   collapsed. Undone at 782px, where .rhsc-nav becomes row-reverse and the
   buttons return to their natural inline width. */
@media (max-width: 781px) {
	.rhsc-nav {
		align-items: stretch;
	}

	.rhsc-nav .rhsc-btn {
		width: 100%;
	}
}

.rhsc-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 10px 24px;
	border-radius: 16px 3px;
	border: 3px solid transparent;
	font-family: inherit;
	font-size: 16px;
	line-height: 24px;
	font-weight: 600;
	cursor: pointer;
}

.rhsc-btn--primary {
	background: var(--wp--preset--color--neutral-inky-deep, #181423);
	border-color: var(--wp--preset--color--neutral-inky-deep, #181423);
	color: var(--wp--preset--color--neutral-05, #F6F6F6);
}

/* Hover empties the fill rather than painting it white, matching
   primary-button.css: whatever the button sits on shows through, and the
   border and label stay Inky Deep so the shape is unchanged. */
.rhsc-btn--primary:hover:not(:disabled):not([aria-disabled='true']) {
	background: transparent;
	color: var(--wp--preset--color--neutral-inky-deep, #181423);
}

/* Go Back: the outline twin of Continue. Same border, radius and weight — only
   the fill differs, so the pair reads as one control with a direction. */
.rhsc-btn--ghost {
	background: transparent;
	border-color: var(--wp--preset--color--neutral-inky-deep, #181423);
	color: var(--wp--preset--color--neutral-inky-deep, #181423);
}

.rhsc-btn--ghost:hover {
	background: var(--wp--preset--color--neutral-inky-deep, #181423);
	color: var(--wp--preset--color--neutral-05, #F6F6F6);
}

/* Keyboard focus only. Matches the control ring above so a button and a field
   look the same under Tab. Needed explicitly because the hover rules also fire
   on :focus-visible — a colour swap alone is not a focus indicator. */
.rhsc-btn:focus-visible {
	outline: 2px solid var(--wp--preset--color--orange-100, #FF6B35);
	outline-offset: 2px;
}

/* Live gating: Continue and Subscribe carry the grey until their required
   fields are silently valid (updateNavState in membership-form.js,
   updateSubmitState in subscribe-form.js). neutral-50 is the theme token; the
   Figma mock's #B5B3B8 has no token and would drift the moment the ramp is
   touched.

   The subscribe form was exempt until QA asked for the same gate there
   ("the submit button should be greyed out if the required fields are not
   completed"), so both roots are listed. Disabled controls are exempt from
   WCAG 1.4.3, so the low-contrast label here is deliberate. */
.rhsc-membership-form .rhsc-btn:disabled,
.rhsc-membership-form .rhsc-btn[aria-disabled='true'],
.rhsc-subscribe-form .rhsc-btn:disabled,
.rhsc-subscribe-form .rhsc-btn[aria-disabled='true'] {
	background: var(--wp--preset--color--neutral-50, #B5B3B8);
	border-color: var(--wp--preset--color--neutral-50, #B5B3B8);
	color: var(--wp--preset--color--neutral-05, #F6F6F6);
	cursor: not-allowed;
}

/* `aria-disabled`, not `disabled`, is what Continue and Submit carry while the
   step is incomplete — see updateNavState() in membership-form.js. The button
   stays focusable and clickable on purpose: pressing it names the fields at
   fault, which a dead button cannot do. This rule is only the colour. */

/* ── nav arrows ─────────────────────────────────────────────────────────
   Icon-font glyphs matching `ic-btn-arrow` (\e91e) and `ic-btn-arrow-left`
   (\e91f) in assets/css/icon-fonts.css, which is enqueued globally.

   The glyphs are HARD-CODED rather than applied by adding an `ic-btn-*` class
   to the button, because icon-fonts.css also sets `content` on
   [class^='ic-btn-']:before — the class would paint a duplicate standalone
   glyph beside this one. Precedent: header.css:705 and header.css:1024.

   font-family is set ONLY on the pseudo-element. It inherits, so putting it on
   the button leaks the icon font into the label, which has no glyphs for
   letters and falls all the way back to a serif — see icon-fonts.css:12-19,
   which documents that exact regression.

   Scoped to the role classes, NOT .rhsc-btn or .rhsc-nav__submit:
   .rhsc-nav__submit is also the Subscribe button, and a terminal action must
   not grow a "next step" arrow. */
.rhsc-membership-form .rhsc-nav__continue::after,
.rhsc-membership-form .rhsc-nav__back::before {
	font-family: "Icon-Font";
	font-style: normal;
	font-weight: normal;
	font-variant: normal;
	text-transform: none;
	font-size: 1rem;
	line-height: 1;
	flex-shrink: 0;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

.rhsc-membership-form .rhsc-nav__continue::after {
	content: "\e91e";
}

/* LEADING, not trailing: a left arrow after the label would point back into
   the word "Back" rather than in the direction of travel. */
.rhsc-membership-form .rhsc-nav__back::before {
	content: "\e91f";
}

/* The error summary, written only after Continue/Submit is pressed (see
   syncStepSummary in membership-form.js). It replaces the old .rhsc-nav__hint,
   which was grey advisory text shown while the button sat disabled; this is a
   real error, so it takes the error colour.

   .rhsc-nav is row-reverse at 782px+, so flex-basis:100% plus wrap is what
   keeps this below the button pair rather than between them. */
.rhsc-nav__summary {
	flex: 1 0 100%;
	margin: 0;
	font-size: 14px;
	line-height: 1.4;
	font-weight: 500;
	color: var(--wp--preset--color--error-400, #FF2632);
}

.rhsc-nav__summary:empty {
	display: none;
}

/* ────────────────────────────────────────────────────────────── thank you */
.rhsc-thankyou__cards {
	display: grid;
	gap: 16px;
	margin-top: 32px;
}

.rhsc-card {
	padding: 24px;
	border-radius: 12px;
	background: var(--wp--preset--color--neutral-10, #EDECEE);
}

.rhsc-card__list {
	margin: 8px 0 0;
	padding-left: 18px;
}

/* ───────────────────────────────────────────── standalone thank-you page */
/* The page an applicant lands on after submitting, per Figma 4455:15569.
   Deliberately NOT nested under .rhsc-membership-form: that wrapper caps width
   at 720px, which is exactly what this page needs to escape.

   Markup contract: patterns/membership-thankyou.php. */
.rhsc-thankyou-page {
	padding-block: var(--wp--preset--spacing--large, 64px);
}

.rhsc-thankyou-page__lede {
	color: var(--wp--preset--color--neutral-90, #36323F);
	margin-top: 8px;
}

/* Cards stack on mobile — which is all the Figma frame (375px) showed — and go
   to three columns from 782px, matching the other card grids in this theme. */
.rhsc-resource-cards {
	display: grid;
	gap: 24px;
	margin-top: 40px;
}

/* The group block ships with is-layout-flow, whose `> * + *` rule adds a
   24px top margin to every child after the first. Inside a grid that offsets
   cards 2 and 3 downward by a row-gap they should not have — the cards are
   already equal height, they just start at different y. Zero it here rather
   than switching the block to a grid layout, which would let the Site Editor
   fight this back on the next save. */
.rhsc-resource-cards > * {
	margin-block: 0;
}

@media (min-width: 782px) {
	.rhsc-resource-cards {
		grid-template-columns: repeat(3, 1fr);
	}
}

/* align-items:stretch on the grid gives every card the row's full height, so
   the cards line up regardless of how much body copy each one carries. */
.rhsc-resource-card {
	display: flex;
	flex-direction: column;
	gap: 8px;
	height: 100%;
	padding: 16px 24px 24px;
	border-radius: 12px;
	background: var(--wp--preset--color--neutral-05, #F6F6F6);
}

/* 48px tinted tile holding a 33–37px icon. Background-image rather than a mask:
   the Groups icon is two-tone (a white detail on red), which a mask would
   flatten into a single silhouette. */
.rhsc-resource-card__icon {
	display: block;
	flex: none;
	width: 48px;
	height: 48px;
	border-radius: 8px;
	background-repeat: no-repeat;
	background-position: center;
	background-size: 33px 33px;
	margin-bottom: 8px;
}

.rhsc-resource-card__icon--orange {
	background-color: var(--wp--preset--color--orange-10, #FFF4DA);
	background-image: url('../../images/icons/membership-service-center.svg');
	background-size: 37px 37px;
}

/* No red-10 token exists in theme.json; #FFECF2 comes straight from the design.
   Swap this for the token if a reds ramp is ever added. */
.rhsc-resource-card__icon--red {
	background-color: #FFECF2;
	background-image: url('../../images/icons/membership-groups.svg');
}

.rhsc-resource-card__icon--green {
	background-color: var(--wp--preset--color--green-10, #E6FFED);
	background-image: url('../../images/icons/membership-directory.svg');
}

/* Instrument Sans SemiBold 20/22 per the design. Pinned explicitly because
   theme.json gives h2 the Young Serif display face, which is far too heavy at
   card size — the heading level here is about document structure, not looks. */
.rhsc-resource-card__title {
	font-family: var(--wp--preset--font-family--instrument-sans, inherit);
	font-size: 20px;
	font-weight: 600;
	line-height: 22px;
	margin: 0;
}

.rhsc-resource-card__body {
	font-size: 14px;
	line-height: 20px;
	margin: 0;
	/* Pushes the link to the bottom so links align across cards of unequal
	   text length — the design shows them on one line. */
	flex: 1 0 auto;
}

.rhsc-resource-card__link {
	margin: 8px 0 0;
}

/* css-framework.css paints body-copy links orange via
   `main :is(p.wp-block-paragraph:not(.has-link-color), …) a:not(…)`, which
   scores (0,4,2) and loads after this file — so out-specifying it here would
   mean an arms race. It offers an opt-out instead: `.has-link-color` on the
   paragraph disables the rule at source. The pattern carries that class, so
   this selector only has to beat the (0,1,0) global-styles default.

   The design calls for dark links here; the framework's orange is for inline
   body links, and these read as buttons. */
.rhsc-resource-card__link a,
.rhsc-resource-card__link a:hover,
.rhsc-resource-card__link a:focus {
	font-weight: 700;
	text-decoration: underline;
	color: var(--wp--preset--color--neutral-inky-deep, #181423);
}

/* The design's trailing arrow. A pseudo-element rather than a character in the
   content so editors cannot lose it while editing the link text. */
.rhsc-resource-card__link a::after {
	content: '→';
	text-decoration: none;
	display: inline-block;
	margin-left: 6px;
}

/* Cards on this page sit in their own grid context; the shared rule above only
   sets the columns at 782px+, which is what we want here too. */
.rhsc-thankyou-page .rhsc-thankyou__cards {
	margin-top: 40px;
}

@media (min-width: 782px) {
	.rhsc-nav {
		flex-direction: row-reverse;
		justify-content: flex-end;
	}
	.rhsc-thankyou__cards {
		grid-template-columns: repeat(3, 1fr);
	}
}

/* ═══════════════════════════════ the field shape, per the Design System page
   Second tab, row 126: "The form fields are styled incorrectly compared to
   designs, please refer to static/active/filled states in the figma file."

   Figma > Design System > Inputs. Text Field and Single Select Dropdown are one
   shape — 60px tall, 32px radius, a 3px border — and the state lives entirely
   in that border's colour:

     Default / Filled   #181423  (Neutral/Inky Deep)
     Rollover / Typing  #FF6B35  (Oranges/Persimmon)
     Uneditable         #ABB0BF on a #FAFBFF fill (Neutral/300 on Neutral/50)
     Error              #FF2632  (Error/400)

   These values now live at :root in forms.css and ARE the site-wide default,
   so the .rhsc-form token override that used to sit here is gone. It existed
   only to keep the Publication Library's facets on the old 1px/42px filter
   pill; that pill has been retired and every control shares this one shape.

   Text Area followed its own Design System spec (1px Neutral/300, 8px radius)
   until the membership frame (4455:15371) was inspected directly: there it
   carries the SAME 3px Inky Deep border as the text fields, at 32px radius with
   16px/24px padding. The frame wins — it is the screen being built, and a
   textarea sitting in a column of 3px pills is visibly wrong when it alone is a
   thin grey rectangle. See the textarea block below. */
/* Rollover and Typing are the same border in the frame, so hover and focus are
   written together. The colour change IS the focus indicator here — 3px of
   Persimmon against Inky Deep — which is why the old 2px outline ring goes:
   with both, focus drew a double ring the design does not have. */
.rhsc-form input[type="text"]:hover,
.rhsc-form input[type="email"]:hover,
.rhsc-form input[type="url"]:hover,
.rhsc-form input[type="tel"]:hover,
.rhsc-form textarea:hover,
.rhsc-form select:hover,
.rhsc-form :is(input, textarea, select):focus,
.rhsc-form :is(input, textarea, select):focus-visible {
	border-color: var(--wp--preset--color--orange-100, #ff6b35);
	outline: none;
}

.rhsc-form :is(input, textarea, select):disabled,
.rhsc-form :is(input, textarea, select)[readonly] {
	background-color: #fafbff;
	border-color: #abb0bf;
}

/* Error/400 (#FF2632), per the Figma Error state. The field border, its
   floated label, the message beneath it and the nav summary all use this one
   colour, so a blocked step reads as a single signal rather than three reds.

   The token resolves to theme.json's Error 400 (#F72828); the literal here is
   the Figma value and the fallback if the token is ever absent.

   TYPED SELECTORS ARE REQUIRED. The pill rule near the top of this file uses
   the `border` SHORTHAND at `.rhsc-form input[type="text"]` — specificity
   0,2,1, and a shorthand resets border-color outright. A bare
   `.rhsc-form [aria-invalid="true"]` is only 0,2,0, so it loses and the
   invalid field renders with the ordinary dark border: aria-invalid is set,
   the message shows, and the box gives no sign at all. Observed on
   #org-name before this was typed out. Same trap, same fix as the floated
   label padding at the top of the file. */
.rhsc-form [aria-invalid="true"],
.rhsc-form [aria-invalid="true"]:hover,
.rhsc-form input[type="text"][aria-invalid="true"],
.rhsc-form input[type="email"][aria-invalid="true"],
.rhsc-form input[type="url"][aria-invalid="true"],
.rhsc-form input[type="tel"][aria-invalid="true"],
.rhsc-form textarea[aria-invalid="true"],
.rhsc-form select[aria-invalid="true"],
.rhsc-form input[type="text"][aria-invalid="true"]:hover,
.rhsc-form input[type="email"][aria-invalid="true"]:hover,
.rhsc-form input[type="url"][aria-invalid="true"]:hover,
.rhsc-form input[type="tel"][aria-invalid="true"]:hover,
.rhsc-form textarea[aria-invalid="true"]:hover,
.rhsc-form select[aria-invalid="true"]:hover {
	border-color: var(--wp--preset--color--error-400, #FF2632);
}

/* Text Area, per the membership frame: the same 3px Inky Deep border and 32px
   radius as the text fields, with 16px/24px padding.

   Only padding is genuinely different — 16px top/bottom against the pill's 15
   — so that is all this rule needs to state. border, radius and colour all come
   from the global control skin in forms.css, and leaving them unset is what
   lets the hover/focus/error rules recolour the textarea exactly as they do the
   inputs. forms.css also sets min-height: 120px, which this deliberately does
   not fight: the frame's boxes are all taller than that. */
.rhsc-form textarea {
	padding: 16px 24px;
}

/* The floated label needs the taller box: 24 above the value, 6 below, which
   with the 3px borders is the same 60 as the static state (the control must not
   change height when the label floats). */
.rhsc-form .rhsc-field--float input[type="text"],
.rhsc-form .rhsc-field--float input[type="email"],
.rhsc-form .rhsc-field--float input[type="url"],
.rhsc-form .rhsc-field--float input[type="tel"],
.rhsc-form .rhsc-field--float select.rhsc-field__input {
	padding-top: 24px;
	padding-bottom: 6px;
}
