/* ===== Gravity Forms — core field styling (Theme chunk 3) =====
   Maps the Claude Design field treatments (layout/app/fields.jsx +
   Salary Survey Site.html) onto GF 2.10's actual markup.

   Form theme is the legacy "gravity-theme" (gform-theme--no-framework), so we
   override the visual layer scoped to `.gform_wrapper.gravity-theme` to match
   GF's own specificity and win cleanly (no !important spraying).

   Tokens are namespaced --gf-*: they resolve from the .site wrapper when a form
   is rendered in-page (honouring the switchable density/shape variants), and
   fall back to sensible defaults inside the body-level GP Nested Forms modal.

   Scope: core inputs only — text, number, textarea, select, radio, checkbox,
   labels/descriptions/required/validation, and page/submit buttons.
   Likert (survey), Advanced Select, address, and the section stepper = chunk 4. */

/* Also declared on .gpnf-modal: the modal's own chrome — tingle's close button,
   the section tag, the footer — sits outside .gform_wrapper, so tokens scoped
   only to the form wrapper do not resolve there and silently fall back to
   nothing (a transparent close button, an ink-coloured section tag). */
.gform_wrapper.gravity-theme,
.gpnf-modal {
  --gf-accent:      var(--wp--preset--color--accent, #1E5C8C);
  --gf-accent-d:    color-mix(in srgb, var(--gf-accent) 82%, #000);
  --gf-accent-tint: color-mix(in srgb, var(--gf-accent) 12%, #fff);
  --gf-accent-soft: color-mix(in srgb, var(--gf-accent) 30%, #fff);
  --gf-ink:         var(--wp--preset--color--ink, #1B2733);
  --gf-ink-2:       var(--wp--preset--color--ink-2, #51606D);
  /* Darkened from the design's #8A97A3, which was 2.98:1 on white and 2.78:1 on
     the page grey — against 4.5:1 for body text at this size. axe had flagged it
     since the first audit; the ratio went unmeasured because a naive probe reads
     the element's own `rgba(0,0,0,0)` and has to walk up for the first opaque
     ancestor. The binding case is not the field descriptions on white but the
     submit note on the grey page, so a value chosen for white alone still
     failed. This clears both: 5.10 and 4.75. */
  --gf-ink-3:       var(--wp--preset--color--ink-3, #666F7A);
  --gf-card:        var(--wp--preset--color--card, #FFFFFF);
  --gf-rule:        var(--wp--preset--color--rule, #E3E7EC);
  --gf-rule-soft:   var(--wp--preset--color--rule-soft, #EEF1F4);
  --gf-opt-bg:      var(--wp--preset--color--option, #EDF0F4);
  --gf-error:       #C0392B;
  /* Filled disc with the exclamation knocked out (evenodd), used as a mask so
     it takes the colour of whatever text it sits beside. */
  --gf-alert-mask:  url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0Zm0 3.2a1.1 1.1 0 0 0-1.1 1.16l.25 4.2a.85.85 0 0 0 1.7 0l.25-4.2A1.1 1.1 0 0 0 8 3.2Zm0 8a1.2 1.2 0 1 0 0 2.4 1.2 1.2 0 0 0 0-2.4Z'/%3E%3C/svg%3E");
  --gf-radius:      var(--field-radius, 12px);
  --gf-opt-py:      var(--opt-py, 11px);
  --gf-opt-px:      var(--opt-px, 11px);
  /* Radio/checkbox mark. Small on purpose: the whole card is the hit area, so
     the mark only has to read as a state, not as the target. Everything else
     about the mark derives from this — see .gchoice > label. */
  --gf-mark:        16px;
  --gf-mark-dot:    7px;
  --gf-field-gap:   var(--field-gap, 26px);
  --gf-gap:         var(--gap, 11px);
  color: var(--gf-ink);
}

/* The tweak variables (density / fill / shape) are declared on the .site
   wrapper in templates/index.html, which the modal is not inside — GP Nested
   Forms mounts it at body level. Mirrored here so modal fields match the page
   instead of quietly falling back to the token defaults. Scoped to .gpnf-modal
   alone: declaring it alongside .gform_wrapper would override the inherited
   value for page forms too and make the .site attributes inert.
   Keep in step with .site[data-fieldshape] in style.css. */
.gpnf-modal { --field-radius: 12px; }

/* ---------------------------------------------------------------- Fields */
/* Keep GF's 12-col grid intact: only set the vertical (row) rhythm; leave the
   column gap to GF so width classes + grid-column placement lay out correctly. */
.gform_wrapper.gravity-theme .gform_fields { row-gap: var(--gf-field-gap); column-gap: 2rem; }
.gform_wrapper.gravity-theme .gfield { margin: 0; }

/* Labels — question text. Radio/checkbox use <legend> with the same class.
   Mapped onto the design's `.f-q`: sans, 700, 19px. Domine is the editorial
   voice in this design — the left-hand section headings and card titles — and
   questions are deliberately not in it, so no font-family here; the body face
   is what the design asks for. The 18px below is the design's `.f-head`
   margin, dropping to 7px when a description follows (design `.f-help`).

   Both element names are spelled out on purpose. GF sets `.gfield_label` to
   16px/8px at exactly three classes, the same as a bare `.gfield_label`
   override, and it loads after us — so a bare selector wins for `<legend>`
   (choice fields, where our own `legend.gfield_label` outranks it) and loses
   for `<label>` (everything else). That is why single-line text questions like
   "What is your job title?" sat at 16px while the questions either side of them
   were 19px. */
.gform_wrapper.gravity-theme label.gfield_label,
.gform_wrapper.gravity-theme legend.gfield_label {
  display: block;
  margin: 0 0 18px;
  padding: 0;
  font-weight: 700;
  font-size: 19px;
  line-height: 1.3;
  color: var(--gf-ink);
}
.gform_wrapper.gravity-theme .gfield--has-description label.gfield_label,
.gform_wrapper.gravity-theme .gfield--has-description legend.gfield_label { margin-bottom: 7px; }

/* Descriptions / help text */
.gform_wrapper.gravity-theme .gfield_description {
  margin: 0 0 18px;
  padding: 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--gf-ink-2);
}

/* Strip the padding GF wraps around descriptions, and the paragraph margins
   inside them. Between `.description, .gfield_description { padding-top: 13px }`,
   `.field_description_above .description { padding-bottom: 16px }` and the 15px
   margins on the <p>, a single line of help text occupied 83px for 24px of
   words. Five classes because that padding-bottom rule is itself four, so the
   obvious override lost. */
.gform_wrapper.gravity-theme .gform_fields .gfield .gfield_description { padding: 0; }
.gform_wrapper.gravity-theme .gform_fields .gfield .gfield_description > :first-child { margin-top: 0; }
.gform_wrapper.gravity-theme .gform_fields .gfield .gfield_description > :last-child { margin-bottom: 0; }

/* Required asterisk */
.gform_wrapper.gravity-theme .gfield_required_asterisk,
.gform_wrapper.gravity-theme .gfield_required {
  color: var(--gf-accent-d);
  font-weight: 700;
  margin-left: 3px;
}

/* HTML info blocks inherit the page's normal typography — no blanket restyle
   (that flattened intro copy). Only the "alert" callout variant gets a box. */
.gform_wrapper.gravity-theme .gfield--type-html.alert {
  background: var(--gf-accent-tint);
  border: 1px solid color-mix(in srgb, var(--gf-accent) 30%, #fff);
  border-radius: 10px;
  padding: 12px 16px;
  color: var(--gf-ink);
}
/* Zero the outer paragraph margins so the text is centred in the box's own
   padding — the first <p>'s 16px top margin was stacking on the 12px padding
   and pushing the text low, while the bottom was already flush. */
.gform_wrapper.gravity-theme .gfield--type-html.alert > :first-child { margin-top: 0; }
.gform_wrapper.gravity-theme .gfield--type-html.alert > :last-child { margin-bottom: 0; }

/* A role already claimed as the primary one, greyed out in the additional-roles
   list (exclusive-role.js). Kept in place rather than removed so the list does
   not reshuffle under the reader — but it has to look decisively unavailable,
   or it reads as an option they simply failed to click. */
.gform_wrapper.gravity-theme .gfield.wtd-role-additional .gchoice.wtd-role-taken {
  opacity: .55;
}
.gform_wrapper.gravity-theme .gfield.wtd-role-additional .gchoice.wtd-role-taken > label {
  cursor: default;
}
.gform_wrapper.gravity-theme .gchoice.wtd-role-taken .wtd-role-taken-note {
  font-style: italic;
  color: var(--gf-ink-3);
  white-space: nowrap;
}

/* Scope note — tells one cohort how to read the question below it (currently
   the employee-contractors' "answer for your employee role" on both role
   questions). Deliberately not .alert: that box is the abbreviation nudge, and
   it means "something you entered needs fixing". This is standing instruction,
   not correction, so it gets a quieter treatment — a rule down the side rather
   than a filled panel — and it must not compete with the question heading it
   introduces. */
.gform_wrapper.gravity-theme .gfield--type-html.wtd-scope-note {
  border-inline-start: 3px solid var(--gf-accent-soft);
  padding: 2px 0 2px 14px;
  color: var(--gf-ink-2);
  font-size: 15px;
  line-height: 1.5;
}
.gform_wrapper.gravity-theme .gfield--type-html.wtd-scope-note > :first-child { margin-top: 0; }
.gform_wrapper.gravity-theme .gfield--type-html.wtd-scope-note > :last-child { margin-bottom: 0; }
/* The note belongs to the question underneath it, so it sits closer to that
   question than the field gap would put it. question-spacing.js marks the
   question as following a visible field; without this the pair reads as two
   unrelated blocks. */
.gform_wrapper.gravity-theme .gfield--type-html.wtd-scope-note + .gfield.wtd-q-follows {
  margin-top: 14px;
}
.gform_wrapper.gravity-theme .gfield--type-html.wtd-scope-note strong { color: var(--gf-ink); }

/* Job-title abbreviation nudge — hidden by default, revealed by job-title-nudge.js
   toggling .is-visible as the respondent types. GF conditional logic does not
   re-fire on keystrokes inside a GP Nested Forms modal, so the note is owned in JS. */
.gform_wrapper.gravity-theme .gfield.wtd-title-nudge { display: none; }
.gform_wrapper.gravity-theme .gfield.wtd-title-nudge.is-visible { display: block; }

/* Salary intro (form 4). An HTML field carrying the screen's question, the
   description, and the formatting hint — the hint sits full width just above the
   three columns, so the salary input aligns with Currency and "This amount is:"
   rather than being pushed down by a per-field description. */
.gform_wrapper.gravity-theme .wtd-salary-intro .wtd-field-q,
.gform_wrapper.gravity-theme .wtd-title-intro .wtd-field-q {
  margin: 0 0 12px;
  font-family: inherit;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--gf-ink);
}
.gform_wrapper.gravity-theme .wtd-salary-intro .wtd-field-hint,
.gform_wrapper.gravity-theme .wtd-title-intro .wtd-field-hint {
  margin: 4px 0 0;
  color: var(--gf-ink-2);
  font-size: 14px;
  line-height: 1.5;
}
/* The 12px under the heading is sized for a question sitting straight above its
   input. Where a hint follows, that gap belongs below the pair instead, or the
   hint floats between the two and reads as neither. (:has is already load-bearing
   in this stylesheet — see the buttonized checked state.) */
.gform_wrapper.gravity-theme .wtd-title-intro .wtd-field-q:has(+ .wtd-field-hint) {
  margin-bottom: 6px;
}

/* Plain (un-carded) checkboxes: the salary "Show my salary" reveal toggle and
   the "Yes! This is my salary." confirmation. Both render as a checkbox beside
   its label rather than a full-width option card — their 2025 `nobg` class has
   no styling behind it, so without this they inherit the option-card look. */
.gform_wrapper.gravity-theme .gfield.toggle_salary .gfield_checkbox,
.gform_wrapper.gravity-theme .gfield.confirm_check .gfield_checkbox { display: block; }
.gform_wrapper.gravity-theme .gfield.toggle_salary .gchoice,
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice {
  display: inline-flex;
  width: auto;
  background: none;
  border: 0;
  padding: 2px 0;
}
.gform_wrapper.gravity-theme .gfield.toggle_salary .gchoice:hover,
.gform_wrapper.gravity-theme .gfield.toggle_salary .gchoice:has(input:checked),
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice:hover,
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice:has(input:checked) {
  background: none;
  border-color: transparent;
  box-shadow: none;
}
.gform_wrapper.gravity-theme .gfield.toggle_salary .gchoice > label,
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice > label {
  flex: 0 0 auto;             /* don't collapse to zero and wrap */
  /* Full shorthand: these sit on a bare row, not a card, so they must clear the
     card padding the base label now carries. */
  padding: 0 0 0 26px;        /* room for the mark, which we pull to the edge */
  line-height: 1.3;
  white-space: nowrap;
}
.gform_wrapper.gravity-theme .gfield.toggle_salary .gchoice > label::before,
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice > label::before {
  left: 0;                   /* card has no left padding, so the box sits at the edge */
}
.gform_wrapper.gravity-theme .gfield.toggle_salary .gchoice:has(input:checked) > label::after,
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice:has(input:checked) > label::after {
  left: calc((var(--gf-mark) - 8px) / 2 + 2px);   /* tick centred inside the box at left:0 */
}

/* A neutral plain checkbox — checkbox beside a normal-weight label that may wrap,
   no option-card, no confirmation card, no injected helper text. `confirm_check`
   can't be reused here: a later block re-cards it, bolds the label, and appends
   "Check this box to confirm and continue." via ::after. Reuses the base mark. */
.gform_wrapper.gravity-theme .gfield.wtd-plain-check .gfield_checkbox { display: block; }
.gform_wrapper.gravity-theme .gfield.wtd-plain-check .gchoice {
  display: inline-flex;
  width: auto;
  background: none;
  border: 0;
  box-shadow: none;
  padding: 2px 0;
}
.gform_wrapper.gravity-theme .gfield.wtd-plain-check .gchoice:hover,
.gform_wrapper.gravity-theme .gfield.wtd-plain-check .gchoice:has(input:checked) {
  background: none;
  border-color: transparent;
  box-shadow: none;
}
.gform_wrapper.gravity-theme .gfield.wtd-plain-check .gchoice > label {
  flex: 0 1 auto;
  padding: 0 0 0 26px;
  margin: 0;
  font-weight: 400;
  line-height: 1.4;
  white-space: normal;
}
.gform_wrapper.gravity-theme .gfield.wtd-plain-check .gchoice > label::before { left: 0; }
.gform_wrapper.gravity-theme .gfield.wtd-plain-check .gchoice:has(input:checked) > label::after {
  left: calc((var(--gf-mark) - 8px) / 2 + 2px);
}

/* The reveal toggle reads as a low-key utility; the confirmation keeps the
   normal label weight and colour. */
.gform_wrapper.gravity-theme .gfield.toggle_salary .gchoice > label {
  font-size: 14px;
  color: var(--gf-ink-2);
}

/* ------------------------------------------------- Text / number / area */
.gform_wrapper.gravity-theme .ginput_container input[type="text"],
.gform_wrapper.gravity-theme .ginput_container input[type="number"],
.gform_wrapper.gravity-theme .ginput_container input[type="email"],
.gform_wrapper.gravity-theme .ginput_container input[type="url"],
.gform_wrapper.gravity-theme .ginput_container_textarea textarea,
.gform_wrapper.gravity-theme .ginput_container_select select,
.gform_wrapper.gravity-theme .ginput_container_address select {
  width: 100%;
  padding: 12px 14px;
  font-family: inherit;
  font-size: 16px;
  line-height: 1.4;
  color: var(--gf-ink);
  background: var(--gf-card);
  border: 1px solid var(--gf-rule);
  border-radius: var(--gf-radius);
  box-shadow: none;
  transition: border-color .15s, box-shadow .15s;
}
/* GF size classes shouldn't force tiny/huge widths in our layout */
.gform_wrapper.gravity-theme .ginput_container input.small,
.gform_wrapper.gravity-theme .ginput_container input.medium,
.gform_wrapper.gravity-theme .ginput_container input.large { width: 100%; }
.gform_wrapper.gravity-theme .ginput_container input[type="number"].small { max-width: 180px; }

.gform_wrapper.gravity-theme .ginput_container_textarea textarea { min-height: 132px; resize: vertical; }

/* Hide the native number spinner arrows — they invite click-nudging a salary and
   add visual noise to a field that only ever takes a typed figure. */
.gform_wrapper.gravity-theme input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.gform_wrapper.gravity-theme input[type="number"]::-webkit-outer-spin-button,
.gform_wrapper.gravity-theme input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Hide the character counter under textareas ("N of 2000 max characters"). The
   comments fields are optional free text; a live countdown reads as pressure and
   the limit is generous. Applies to every counter in the survey. */
.gform_wrapper.gravity-theme .ginput_counter { display: none; }

/* Salary privacy: the salary/earnings figures (fields carrying `masked`) show
   their characters as dots until the respondent checks "Show my salary", which
   adds `unmasked` (salary-privacy.js). -webkit-text-security is honoured by
   Chrome, Safari, Edge and Firefox 121+, on desktop and mobile. */
.gform_wrapper.gravity-theme .gfield.masked input { -webkit-text-security: disc; }
.gform_wrapper.gravity-theme .gfield.unmasked input { -webkit-text-security: none; }

/* A fixed run of dots on the confirmation figures, rather than one per digit.
   Per-character masking still says how big the number is — three dots and ten
   dots are very different salaries — which is most of what the reader wanted
   hidden. A constant four gives nothing away, and the box stops resizing with
   the value too.

   Only where the figure is a read-only copy. The fields people type into keep
   per-character dots: there the count is feedback on what you have entered so
   far, and you already know your own salary. */
.gform_wrapper.gravity-theme .gfield.confirm.masked:not(.unmasked) .ginput_container {
  display: inline-flex;
  align-items: baseline;
}
.gform_wrapper.gravity-theme .gfield.confirm.masked:not(.unmasked) input { display: none; }
.gform_wrapper.gravity-theme .gfield.confirm.masked:not(.unmasked) .ginput_container::after {
  content: "••••";
  letter-spacing: .12em;
}

/* Figures written out (salary-words.js): "eighty-five thousand US dollars".
   A misplaced zero is invisible in digits and obvious in words, which is the one
   error on these pages that nothing else catches.

   A full-width line inside the card, directly under the figure it describes —
   the salary when that is yearly, the "= … yearly" line when it was given
   monthly, and one per rate row on the contractor card. The script indents each
   to its own figure's left edge, so the words start where the digits do rather
   than at the card's edge; only the layout knows how wide the currency pill
   ended up. Quiet type: this is a check on the figure, not a second headline. */
.gform_wrapper.gravity-theme .wtd-words-line {
  flex-basis: 100%;
  min-width: 0;
  overflow-wrap: anywhere;
  margin: -4px 0 0;
  font-size: 14.5px;
  line-height: 1.4;
  color: var(--gf-ink-2);
  font-style: italic;
}
.gform_wrapper.gravity-theme .wtd-words-line:empty { display: none; }
/* Masked with the figure — salary-privacy.js toggles `unmasked` on these too.
   Hiding a number while spelling it out underneath would defeat the switch.

   The same fixed run of dots as the figures. Dotting each character would have
   been worse here than anywhere: the length of the words tracks the size of the
   number closely ("five hundred UAE dirhams" against eighty-odd characters for
   the millions), and with the spaces dotted too the line became one unbreakable
   word that forced the card wider than the modal. Collapsing the text to zero
   size and drawing the dots as a pseudo-element sidesteps both. */
.gform_wrapper.gravity-theme .wtd-words-line:not(.unmasked) { font-size: 0; }
.gform_wrapper.gravity-theme .wtd-words-line:not(.unmasked)::after {
  content: "••••";
  font-size: 14.5px;
  letter-spacing: .12em;
}

/* ---------------------------------------------- Salary summary card
   Confirmation page (form 4, page 2). salary-confirm.js wraps the currency /
   figure / salary-type fields and the monthly->annual line into one
   .wtd-sum-card and tags each .wtd-cur / .wtd-amt / .wtd-per / .wtd-annual-*.
   The fields are read-only calc/copy inputs; their `size` attr (set in JS)
   drives width so they sit inline. Design source: .sum-card / .sum-cur /
   .sum-amt / .sum-per / .sum-annual. */
.gform_wrapper.gravity-theme .wtd-sum-card {
  grid-column: 1 / -1;                 /* span the field grid */
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  /* The card is two columns: the figures and the privacy panel. Both numbers
     are named because the rate-row dividers have to span back across them. */
  --wtd-sum-gap: 24px;
  --wtd-priv-w: 300px;
  gap: var(--wtd-sum-gap);             /* design .sum-card */
  padding: 24px 28px;
  background: var(--gf-card);
  border: 1px solid var(--gf-rule);
  border-radius: 14px;
  /* Queried below so the figure row can restack itself. The card's width is what
     decides whether the period word fits beside the figure, and that depends on
     whether the privacy panel is still alongside — which a viewport query cannot
     see. */
  container-type: inline-size;
}
/* The figure (or the rate rows) — one column of the card, the privacy panel the
   other. salary-confirm.js wraps whatever the card already held. */
.gform_wrapper.gravity-theme .wtd-sum-body {
  flex: 1 1 260px;                     /* design .sum-fig */
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  align-content: center;
  gap: 14px;
}
.gform_wrapper.gravity-theme .wtd-sum-card .gfield { margin: 0; }
.gform_wrapper.gravity-theme .wtd-sum-card .gfield > .ginput_container { margin: 0; }
/* strip GF's input chrome inside the card — these are a read-only summary */
.gform_wrapper.gravity-theme .wtd-sum-card .confirm input {
  width: auto;
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  color: var(--gf-ink);
  font-family: inherit;
  pointer-events: none;
}
.gform_wrapper.gravity-theme .wtd-sum-card .confirm input:focus { outline: none; box-shadow: none; border: 0; }

/* Currency code -> pill (.sum-cur) */
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-cur { align-self: center; }
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-cur input {
  /* Monospaced so every three-letter code is the same width — in a proportional
     face "AMD" is visibly wider than "ILS", and on the rates card, where three
     pills stack, the ragged edge shows. Fixing the width instead would mean
     guessing a value that fits the broadest code; equal-width glyphs let the
     existing measuring pass in salary-confirm.js arrive at the same answer every
     time. It also suits the content: this is a code, not a word. */
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  padding: 4px 10px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--gf-accent);
  background: var(--gf-accent-tint);
  border: 1px solid var(--gf-accent-soft);
  border-radius: 8px;
  text-align: center;
}
/* Gross figure (.sum-amt) */
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-amt input,
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-amt .wtd-cur-sym,
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-amt .ginput_container::after {
  font-family: "Domine", Georgia, serif;
  font-size: 38px;
  font-weight: 700;
  line-height: 1;
  color: var(--gf-ink);
}
/* The currency symbol (currency-symbol.js) sits inside the figure's container,
   just before the input. It takes its type from the figure's own rules above —
   it is listed alongside `input` there — so it matches at every size without a
   second set of font declarations. Not masked: the pill already names the
   currency, so hiding the symbol would conceal nothing. */
.gform_wrapper.gravity-theme .wtd-cur-sym {
  margin-right: .12em;   /* em, so the gap scales with the figure */
  color: inherit;
}

/* Salary type — monthly / yearly (.sum-per) */
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-per input {
  font-size: 15.5px;
  color: var(--gf-ink-2);
}

/* Monthly->annual line (.sum-annual): one dashed sub-row reading
   "= <figure> <cur> yearly". salary-confirm.js groups the fields into
   .wtd-annual and shows it only for a monthly figure; the "=" and "yearly" are
   CSS labels, the figure/currency are ordered between them. */
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual {
  flex-basis: 100%;
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin-top: 4px;
  padding-top: 12px;
  border-top: 1px dashed var(--gf-rule);
  font-size: 14.5px;
  color: var(--gf-ink-2);
}
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual::before { content: "="; order: 0; }
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual::after { content: "yearly"; order: 3; }
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual-amt { order: 1; }
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual-cur { order: 2; }
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual-amt input,
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual-amt .wtd-cur-sym,
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual-amt .ginput_container::after,
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual-cur input {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--gf-ink-2);
}
/* The verbose note and the spare block are replaced by the "=…yearly" labels.
   !important beats GF's inline display when it reveals the note for monthly. */
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual-note,
.gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual-x { display: none !important; }

/* ---------------------------------------------- Privacy switch (design v3)
   The masking control as the design's breakout panel: a warm-yellow aside
   inside the summary card, holding a switch rather than a checkbox. ON means
   masked, which is the default — the switch reads as "privacy is on", not as
   "reveal my salary".

   The panel is the toggle's own `.gfield`, moved into the card by
   salary-confirm.js (.wtd-sum-priv) or left in place on the entry pages
   (.wtd-priv-aside). Everything below is shared; only the placement differs. */
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside {
  /* One knob: the switch is absolutely positioned, so its offset and the
     label's own indent both derive from these and stay in step. */
  --wtd-priv-pad: 14px;
  --wtd-priv-pad-y: 10px;
  --wtd-priv-track: 52px;
  --wtd-priv-switch-h: 30px;
  position: relative;                  /* the switch positions against the panel */
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  margin: 0;
  /* Even padding. The switch column used to be reserved by indenting the whole
     panel, which pushed the note in as well; only the label needs to clear it,
     so the note can run the full width underneath. */
  padding: var(--wtd-priv-pad-y) var(--wtd-priv-pad);
  background: var(--gf-warn-bg, #FDF6E7);
  border: 1px solid var(--gf-warn-rule, #E4C87E);
  border-radius: 12px;
}
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv {
  flex: 0 1 var(--wtd-priv-w);         /* design .sum-priv */
  /* Top-aligned rather than centred: the card is taller now that the figure is
     written out beneath itself, and on the rates card it holds three rows — a
     centred panel in a tall card reads as adrift rather than paired with the
     figures it controls. */
  align-self: flex-start;
}
/* Entry pages: floated into the intro copy, which wraps around it. */
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside {
  float: right;
  width: 300px;
  margin: 4px 0 12px 24px;
}
@media (max-width: 640px) {
  /* Too narrow to wrap copy beside it — take the row instead. */
  .gform_wrapper.gravity-theme .gfield.wtd-priv-aside {
    float: none;
    width: auto;
    margin: 0 0 16px;
  }
}
/* The panel is prepended to the intro block, so the copy that wraps around it
   begins with a paragraph's own top margin and starts a line lower than the
   panel — the two should begin level. The salary intro escapes this because its
   heading (.wtd-field-q) already zeroes its top margin; the rates intro opens
   with a plain paragraph. */
.gform_wrapper.gravity-theme .gfield--type-html > .wtd-priv-aside + p { margin-top: 0; }
/* GF puts the description before the input; the design reads title then note. */
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .ginput_container,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .ginput_container { order: 0; margin: 0; }
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .gfield_description,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .gfield_description {
  order: 1;
  /* Zero the margin, not just the padding: GF gives descriptions an 18px
     bottom margin, which made the panel 18px taller than its text and pushed
     that text above centre — while the switch, positioned against the box,
     stayed centred. That mismatch is what read as "off". */
  margin: 0;
  padding: 0;
  font-size: 13px;
  line-height: 1.35;
  color: var(--gf-ink-2);
}
/* The choice row carries no chrome of its own here, and must not be the
   positioning context — the switch centres against the whole panel. */
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .gchoice,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .gchoice {
  position: static;
  display: block;
  padding: 0;
  background: none;
  border: 0;
}
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .gchoice > label,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .gchoice > label {
  /* Sits beside the switch and clears it on its own, so the note below is free
     to run full width. Centred against the track rather than sitting on its
     baseline, so a label that wraps to two lines stays paired with it. */
  display: flex;
  align-items: center;
  min-height: var(--wtd-priv-switch-h);
  padding: 0 0 0 calc(var(--wtd-priv-track) + 10px);
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  /* Brown rather than the design's grey — Kay's call, and it ties the heading to
     the panel's border and background. */
  color: var(--gf-warn-ink, #8A6A1F);
  white-space: normal;
}
/* Track — replaces the checkbox mark. */
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .gchoice > label::before,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .gchoice > label::before {
  content: "";
  position: absolute;
  left: var(--wtd-priv-pad);
  /* Centred on the label row rather than on the panel: the note below is now
     full width, so a panel-centred switch would drift down away from the
     label it belongs to as the note grows. */
  top: calc(var(--wtd-priv-pad-y) + var(--wtd-priv-switch-h) / 2);
  transform: translateY(-50%);
  width: var(--wtd-priv-track);
  height: var(--wtd-priv-switch-h);
  border-radius: 15px;
  background: #EFE3C4;
  border: 1px solid #D9BE72;
  transition: background .15s, border-color .15s;
}
/* Knob — always drawn, slides on state, unlike the base tick. */
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .gchoice > label::after,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .gchoice > label::after {
  content: "";
  position: absolute;
  left: calc(var(--wtd-priv-pad) + 3px);
  top: calc(var(--wtd-priv-pad-y) + var(--wtd-priv-switch-h) / 2);
  width: 23px;
  height: 23px;
  margin: 0;
  transform: translateY(-50%);
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
  transition: left .15s;
}
/* Checked = masked = switch on. */
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .gchoice:has(input:checked) > label::before,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .gchoice:has(input:checked) > label::before {
  background: #B98A1E;
  border-color: #A97D18;
}
/* Restate the knob's geometry, not just its position: the checked state
   otherwise inherits the base rules' tick — a 6x12px chevron — which out-specify
   the unchecked knob above and collapsed it to a sliver. */
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .gchoice:has(input:checked) > label::after,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .gchoice:has(input:checked) > label::after {
  left: calc(var(--wtd-priv-pad) + 25px);   /* 3px inset + 22px travel */
  top: calc(var(--wtd-priv-pad-y) + var(--wtd-priv-switch-h) / 2);
  width: 23px;
  height: 23px;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
  transform: translateY(-50%);
}
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .gchoice > label:focus-visible::before,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .gchoice > label:focus-visible::before,
.gform_wrapper.gravity-theme .gfield.wtd-sum-priv .gchoice:focus-within > label::before,
.gform_wrapper.gravity-theme .gfield.wtd-priv-aside .gchoice:focus-within > label::before {
  box-shadow: 0 0 0 3px rgba(185, 138, 30, .28);
}

/* ---------------------------------------------- Contractor rates card
   Confirmation page (form 5, page 4). Same visual grammar as the salary card —
   currency pill, serif figure, period word — but up to three lines, one per
   rate type entered. salary-confirm.js groups each label/currency/rate triple
   into a .wtd-rate-row and tags them .wtd-per / .wtd-cur / .wtd-amt. */
/* The rate lines stack, but the card itself still runs figure | privacy panel,
   so the column belongs to the body rather than the card. */
.gform_wrapper.gravity-theme .wtd-sum-card--rates .wtd-sum-body {
  flex-direction: column;
  align-items: stretch;
  align-content: stretch;
  gap: 0;
}
.gform_wrapper.gravity-theme .wtd-rate-row {
  display: flex;
  /* Wraps so the written-out figure (salary-words.js) drops to its own line
     beneath the rate. Without it a full-width item cannot break, and squeezes
     the row sideways instead. */
  flex-wrap: wrap;
  align-items: baseline;
  gap: 14px;
  padding: 14px 0;
}
/* Hairline between lines only — the card already has its own border. */
.gform_wrapper.gravity-theme .wtd-rate-row ~ .wtd-rate-row {
  border-top: 1px solid var(--gf-rule);
}
/* ...and it reads as a rule across the card, not a line under one column. The
   rows live in the figures column, which stops short of the privacy panel, so
   the divider is drawn by a pseudo-element that reaches back across the gap and
   the panel to the card's padding edge. The border stays, transparent, so the
   spacing it contributes does not move. Only while the panel is beside the
   figures — once it stacks underneath, the row is already full width. */
@media (min-width: 641px) {
  .gform_wrapper.gravity-theme .wtd-sum-card--rates .wtd-rate-row ~ .wtd-rate-row {
    position: relative;
    border-top-color: transparent;
  }
  .gform_wrapper.gravity-theme .wtd-sum-card--rates .wtd-rate-row ~ .wtd-rate-row::before {
    content: "";
    position: absolute;
    top: -1px;
    left: 0;
    width: calc(100% + var(--wtd-sum-gap) + var(--wtd-priv-w));
    border-top: 1px solid var(--gf-rule);
    pointer-events: none;
  }
}
/* First/last *visible* row — tagged in JS, since a skipped rate type would
   otherwise leave the trim on a hidden row.

   These have to out-rank the two sibling rules above, not merely match them. A
   skipped rate type is still in the DOM, so `.wtd-rate-row ~ .wtd-rate-row`
   goes on matching the first *visible* row and rules it off from nothing — the
   stray line above a lone day rate when hourly was left blank. A bare
   `.wtd-rate-row--first` is one class short of that sibling selector and loses
   outright, so the class is repeated to carry the weight. */
.gform_wrapper.gravity-theme .wtd-rate-row ~ .wtd-rate-row.wtd-rate-row--first,
.gform_wrapper.gravity-theme .wtd-rate-row--first { padding-top: 0; border-top: 0; }
/* The wide layout draws the same divider as a pseudo-element that reaches back
   across the privacy panel, and clearing `border-top` does not touch it. */
.gform_wrapper.gravity-theme .wtd-sum-card--rates .wtd-rate-row ~ .wtd-rate-row.wtd-rate-row--first::before {
  content: none;
}
.gform_wrapper.gravity-theme .wtd-rate-row--last { padding-bottom: 0; }
/* Read as "<CUR> <figure> <period>": the period word is authored first (it is
   the row's anchor field), so order it to the end. */
.gform_wrapper.gravity-theme .wtd-rate-row .wtd-cur { order: 0; }
.gform_wrapper.gravity-theme .wtd-rate-row .wtd-amt { order: 1; }
.gform_wrapper.gravity-theme .wtd-rate-row .wtd-per { order: 2; }
/* Last, so the written-out figure wraps to its own line beneath the rate. The
   row orders its children explicitly, and an unordered item defaults to 0 —
   which put this alongside the currency pill and broke the row into three. */
.gform_wrapper.gravity-theme .wtd-rate-row .wtd-words-line { order: 3; }
/* Three 38px figures would dominate the modal; step the rate figures down. */
.gform_wrapper.gravity-theme .wtd-sum-card--rates .wtd-amt input,
.gform_wrapper.gravity-theme .wtd-sum-card--rates .wtd-amt .wtd-cur-sym,
.gform_wrapper.gravity-theme .wtd-sum-card--rates .wtd-amt .ginput_container::after { font-size: 30px; }
/* The period word is an HTML block here, not a copied input, so it needs the
   .wtd-per input styling applied to its paragraph instead. */
.gform_wrapper.gravity-theme .wtd-rate-row .wtd-per p {
  margin: 0;
  font-size: 15.5px;
  color: var(--gf-ink-2);
}
/* These blocks carry .right (the editorial label column); inside the card they
   are inline parts of the line, not a right-aligned column. Not .wrap-scoped —
   nested forms render in the GPNF modal, outside .wrap. */
.gform_wrapper.gravity-theme .wtd-rate-row .gfield.right {
  grid-column: auto;
  text-align: left;
  padding: 0;
}

/* ------------------------------------------ Narrow card: the period restacks
   On a phone the run of pill + figure + period does not fit — measured at 360,
   393 and 412 against 85,000 / 250,000 / 1,250,000 / 8,500 monthly, it wrapped
   every time. Left to `flex-wrap` the period drops to the *container's* left
   edge, which is under the currency pill, so it read as a stray word floating
   below the card rather than as a label on the figure.

   Placed rather than wrapped, so it is the same layout for every respondent
   instead of depending on how many digits they earn. The period takes the
   figure's column, which puts it under the currency symbol; the written-out
   figure and the annual row still span the full width, and salary-words.js goes
   on indenting the words to the figure's left edge from there exactly as it does
   in the wide layout — it measures from the body, which has not moved. */
@container (max-width: 560px) {
  .gform_wrapper.gravity-theme .wtd-sum-card:not(.wtd-sum-card--rates) .wtd-sum-body,
  .gform_wrapper.gravity-theme .wtd-rate-row {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: baseline;
    column-gap: 14px;
    row-gap: 2px;                      /* the 14px figure gap is far too much under a 38px number */
  }
  /* `.gfield` is in these selectors for weight, not for reach. Gravity Forms
     places every field on its own grid with `.gform_fields .gfield`, which is
     four classes — exactly what `.wtd-rate-row > .wtd-cur` comes to, so the tie
     went to whichever stylesheet loaded last and the column was ignored while
     the row was honoured. Pill and figure then landed in the same cell, one
     drawn over the other. The salary card only escaped it by carrying an extra
     `:not()` in its chain. */
  .gform_wrapper.gravity-theme .wtd-sum-card:not(.wtd-sum-card--rates) .wtd-sum-body > .gfield.wtd-cur,
  .gform_wrapper.gravity-theme .wtd-rate-row > .gfield.wtd-cur { grid-column: 1; grid-row: 1; }
  .gform_wrapper.gravity-theme .wtd-sum-card:not(.wtd-sum-card--rates) .wtd-sum-body > .gfield.wtd-amt,
  .gform_wrapper.gravity-theme .wtd-rate-row > .gfield.wtd-amt { grid-column: 2; grid-row: 1; }
  .gform_wrapper.gravity-theme .wtd-sum-card:not(.wtd-sum-card--rates) .wtd-sum-body > .gfield.wtd-per,
  .gform_wrapper.gravity-theme .wtd-rate-row > .gfield.wtd-per { grid-column: 2; grid-row: 2; }

  /* Each item hugs the start of its column. The period word carries `.right`
     (it is authored as the editorial label column) and GPNF right-aligns that
     class from inside the modal at the same weight as the theme's override, so
     text-align is a fight worth not having: the figure's column is a wide `1fr`
     and the word was drifting to the far edge of it. `justify-self` is a grid
     property, settles the position outright, and shrinks the item to its text
     so the alignment inside it stops mattering. */
  .gform_wrapper.gravity-theme .wtd-sum-card .wtd-sum-body > .gfield,
  .gform_wrapper.gravity-theme .wtd-rate-row > .gfield { justify-self: start; }
  /* Full width, so the JS indent still lands them under the figure. */
  .gform_wrapper.gravity-theme .wtd-sum-card .wtd-annual,
  .gform_wrapper.gravity-theme .wtd-sum-card .wtd-words-line { grid-column: 1 / -1; }

  /* Quieter, now it is a caption under the number rather than a word beside it. */
  .gform_wrapper.gravity-theme .wtd-sum-card .wtd-per input,
  .gform_wrapper.gravity-theme .wtd-rate-row .wtd-per p {
    font-size: 14.5px;
    line-height: 1.2;
  }
}

/* ---------------------------------------------- Confirmation checkbox
   The "Yes! This is my salary." checkbox as the design's button-box
   (.confirm-box): a bordered accent panel with a 26px rounded-square mark and a
   small subtitle. These rules are more specific than both the plain-checkbox
   block above and the base mark/tick rules below, so they win regardless of
   order; the plain treatment still covers the show/hide toggle. */
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;             /* title + subtitle hug the left, beside the mark */
  gap: 3px;
  width: 100%;
  margin-top: 6px;
  padding: 18px 20px 18px 60px;        /* left room for the 26px mark */
  text-align: left;
  background: var(--gf-card);
  border: 2px solid var(--gf-accent);
  border-radius: 14px;
  cursor: pointer;
  transition: background .15s, box-shadow .15s;
}
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice:hover {
  background: var(--gf-card);
  border-color: var(--gf-accent);
  box-shadow: 0 0 0 3px var(--gf-accent-tint);
}
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice:has(input:checked) {
  background: var(--gf-accent-tint);
  border-color: var(--gf-accent);
  box-shadow: none;
}
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice > label {
  flex: 0 0 auto;
  padding: 0;
  margin: 0;
  font-size: 16.5px;
  font-weight: 700;
  color: var(--gf-ink);
  line-height: 1.3;
  white-space: normal;
}
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice::after {
  content: "Check this box to confirm and continue.";
  font-size: 13.5px;
  font-weight: 400;
  color: var(--gf-ink-3);
  line-height: 1.3;
}
/* 26px rounded-square mark, centred against the whole box */
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice > label::before {
  left: 20px;
  top: 50%;
  transform: translateY(-50%);
  width: 26px;
  height: 26px;
  border: 2px solid var(--gf-accent);
  border-radius: 8px;
  background: var(--gf-card);
}
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice:has(input:checked) > label::before {
  background: var(--gf-accent);
}
/* tick */
.gform_wrapper.gravity-theme .gfield.confirm_check .gchoice:has(input:checked) > label::after {
  /* The box spans 20px..46px, so its centre is 33px; a 6px tick centres at 30px.
     It was a pixel to the left of its own box. */
  left: 30px;
  top: 50%;
  width: 6px;
  height: 12px;
  border: solid #fff;
  border-width: 0 3px 3px 0;
  transform: translateY(-62%) rotate(45deg);
}

.gform_wrapper.gravity-theme .ginput_container input:focus,
.gform_wrapper.gravity-theme .ginput_container_textarea textarea:focus,
.gform_wrapper.gravity-theme .ginput_container_select select:focus,
.gform_wrapper.gravity-theme .ginput_container_address select:focus {
  outline: none;
  border-color: var(--gf-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gf-accent) 22%, transparent);
}
.gform_wrapper.gravity-theme ::placeholder { color: var(--wp--preset--color--ink-3, #666F7A); opacity: 1; }

/* Native select chevron */
.gform_wrapper.gravity-theme .ginput_container_select select,
.gform_wrapper.gravity-theme .ginput_container_address select {
  appearance: none; -webkit-appearance: none;
  padding-right: 40px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path fill='%2351606D' d='M0 0h12L6 8z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
}

/* --------------------------------------------- Radio / checkbox choices */
/* Container → the option grid; honour GF's column classes. */
.gform_wrapper.gravity-theme .gfield_radio,
.gform_wrapper.gravity-theme .gfield_checkbox {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--gf-gap);
}
.gform_wrapper.gravity-theme .gf_list_2col_vertical .gfield_radio,
.gform_wrapper.gravity-theme .gf_list_2col_vertical .gfield_checkbox,
.gform_wrapper.gravity-theme .gf_list_2col .gfield_radio,
.gform_wrapper.gravity-theme .gf_list_2col .gfield_checkbox { grid-template-columns: repeat(2, 1fr); }
.gform_wrapper.gravity-theme .gf_list_3col .gfield_radio,
.gform_wrapper.gravity-theme .gf_list_3col .gfield_checkbox { grid-template-columns: repeat(3, 1fr); }
/* Multi-column choice lists ("Display in columns", 2/3/5 across this survey)
   are NOT laid out by the grid above. GF uses CSS multi-column —
   `.gf_list_2col_vertical .gfield_radio { column-count: 2; display: block }` —
   at four classes, which beats the three-class `display: grid`. Multicol has
   no row gap at all: the vertical spacing it assumes is each item's own
   margin-bottom, which we zero to build the option cards, so the options ended
   up touching with only GF's 2rem between columns.

   Fallback (no JS): stay on multicol and put the row spacing back as margin,
   pulling the container up by the same amount so the trailing margin under the
   last card in each column adds nothing below. Column gap to match — the
   design's `.opt-grid` uses one uniform `gap`. */
.gform_wrapper.gravity-theme [class*="gf_list_"] .gchoice {
  margin-bottom: var(--gf-gap);
  break-inside: avoid;   /* never split an option card across a column break */
}
.gform_wrapper.gravity-theme .gfield[class*="gf_list_"] .gfield_radio,
.gform_wrapper.gravity-theme .gfield[class*="gf_list_"] .gfield_checkbox {
  margin-bottom: calc(var(--gf-gap) * -1);
  column-gap: var(--gf-gap);
}

/* `.tight_cols` — for short multi-column option sets whose labels only just
   miss fitting on one line. Lifts GF's `max-width: calc(100% - 32px)` on the
   choice label: that clearance is sized for a mark sitting outside the label,
   but the option card's own left padding already reserves that room, so the cap
   only forces an avoidable wrap. (Same cap that wrapped the satisfaction scale
   labels — there the mark had moved above the text, here it is inside the pad.)
   The column gutter is deliberately left at the uniform --gf-gap: the cards are
   a 1fr grid, so a narrower gutter only widens already-roomy cards. */
.gform_wrapper.gravity-theme .gfield.tight_cols .gchoice > label { max-width: none; }
/* The rate-type marks sit a pixel left of where the eye wants them against the
   copy above. Nudge the mark alone — the box and the tick both hang off the same
   offset, so they move together and the label keeps its spacing. */
.gform_wrapper.gravity-theme .gfield.tight_cols .gchoice > label::before {
  left: calc(var(--gf-opt-px) + 1px);
}
.gform_wrapper.gravity-theme .gfield.tight_cols .gchoice:has(input:checked) > label::after {
  left: calc(var(--gf-opt-px) + 1px + (var(--gf-mark) - 8px) / 2);
}

/* Preferred: a grid flowing down each column in turn — same order as multicol,
   but the rows line up when an option wraps to two lines, which multicol
   cannot do. Needs the row count, which CSS can't derive from the child count,
   so choice-columns.js supplies --wtd-rows/--wtd-cols and adds `wtd-cols`;
   until it does, the multicol above stands. Five classes to beat GF's
   four-class `display: block`. */
.gform_wrapper.gravity-theme .gfield .gfield_radio.wtd-cols,
.gform_wrapper.gravity-theme .gfield .gfield_checkbox.wtd-cols {
  display: grid;
  grid-auto-flow: column;
  grid-template-columns: repeat(var(--wtd-cols, 1), 1fr);
  grid-template-rows: repeat(var(--wtd-rows, 1), auto);
  gap: var(--gf-gap);
  margin-bottom: 0;
}
.gform_wrapper.gravity-theme .gfield .gfield_radio.wtd-cols .gchoice,
.gform_wrapper.gravity-theme .gfield .gfield_checkbox.wtd-cols .gchoice { margin-bottom: 0; }

/* A card stretches to the tallest in its grid row, but its label does not
   follow on its own — so a one-line option opposite a two-line one had its text
   sitting near the top of an over-tall card, which is what "None of the above"
   and "I'd rather not say" were doing beside the two degree options. Stretch the
   label to the card, then centre the text inside it. Same fix the buttonized
   segments already needed; only the columns make it visible.

   Not the scale: `.wtd-scale` is also a column list (gf_list_5col), but it lays
   its labels out itself — column flow, mark on top, text centred with
   text-align. Forcing `display: flex` here left-aligned all five, because a flex
   item is placed by justify-content and ignores text-align. */
.gform_wrapper.gravity-theme .gfield:not(.wtd-scale) .gfield_radio.wtd-cols .gchoice > label,
.gform_wrapper.gravity-theme .gfield:not(.wtd-scale) .gfield_checkbox.wtd-cols .gchoice > label {
  align-self: stretch;
  display: flex;
  align-items: center;
}

/* Family-grouped lists (choice-groups.js) flow rather than sit on a grid: each
   option is as wide as its own label. A fixed column forces every card to the
   width of the longest label in the list, which is why one long option used to
   set the height of a whole row and why short ones like "Editor" and "Support"
   sat in oceans of space. Flowing them is also what the design already does
   with the likert chips, so it is not a new idea in this system.

   min-width keeps the shortest labels from reading as stray tags; the family
   headings take a full row of their own, which is what starts each family.

   Six classes, because GF styles the two column variants at different weights
   and the heavier one is five: `.gf_list_Ncol_vertical .gfield_radio` is four
   (multicol), but `.gfield.gf_list_Ncol .gfield_radio` is five (a real grid).
   A five-class override tied with the latter and lost on source order, so the
   role list flowed while the additional-roles list stayed on GF's grid — with
   the headings sitting in single cells instead of starting a row. */
.gform_wrapper.gravity-theme .gfield.gfield--type-choice .gfield_radio.wtd-grouped,
.gform_wrapper.gravity-theme .gfield.gfield--type-choice .gfield_checkbox.wtd-grouped {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gf-gap);
  margin-bottom: 0;
}
.gform_wrapper.gravity-theme .gfield.gfield--type-choice .wtd-grouped .gchoice {
  /* No shrink. With flex-shrink left at 1 the cards give up width to fit the
     line and the labels wrap instead — "Technical writer" over two lines while
     the row still has space — which is the fixed-column problem in a new
     costume. Content width, floored for the very short labels, and max-width
     so a genuinely long option can still wrap rather than overflow. */
  flex: 0 0 auto;
  min-width: 130px;
  max-width: 100%;
  margin-bottom: 0;
}
/* And the label has to contribute its own width, which takes beating two GF
   rules. `.gchoice > label` carries `flex: 1` — i.e. `flex-basis: 0`, so the
   label counts as zero when the card works out how wide it wants to be. And
   `.gfield-choice-input + label` caps it at `calc(100% - 32px)`: a percentage
   max-width against a container whose width is what we are trying to derive,
   which poisons the intrinsic size and leaves every card at the min-width with
   its text wrapped inside — the fixed columns we just removed, in a new
   costume. Lifting the cap alone took this list from 753px to 612px. */
.gform_wrapper.gravity-theme .gfield.gfield--type-choice .wtd-grouped .gchoice > label {
  flex: 0 1 auto;
  max-width: none;
}
.gform_wrapper.gravity-theme .gfield.gfield--type-choice .wtd-grouped .wtd-optgroup-title {
  flex: 0 0 100%;           /* full width, so it always starts a new row */
  margin: 14px 0 1px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--gf-ink-3);
}
.gform_wrapper.gravity-theme .gfield.gfield--type-choice .wtd-grouped .wtd-optgroup-title:first-child { margin-top: 0; }
/* Where the other groups must be answered, the optional ones say so. Lower
   contrast and no letter-spacing so it reads as an aside on the heading rather
   than part of it. */
.gform_wrapper.gravity-theme .wtd-optgroup-title .wtd-optgroup-optional {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  font-size: 12px;
  color: var(--gf-ink-3);
}
@media (max-width: 560px) {
  .gform_wrapper.gravity-theme .gfield_radio,
  .gform_wrapper.gravity-theme .gfield_checkbox {
    grid-template-columns: 1fr !important;
    column-count: 1 !important;      /* multicol ignores grid-template-columns */
    /* and the column-flow grid ignores both, so unwind it too — otherwise the
       explicit rows push the overflow into implicit columns off to the side. */
    grid-auto-flow: row !important;
    grid-template-rows: none !important;
  }
}

/* Each choice becomes a full-click option card (design .opt).

   Only the <label> is clickable — the card is a plain div, so a click that
   lands on it rather than on the label does nothing. The card's padding
   therefore lives on the label, which stretches to fill the card, making the
   whole card one hit target. With the padding on the card instead, the label
   was inset by --gf-opt-py/--gf-opt-px on every side (a 196x20 label in a
   252x44 card) and that border was dead to clicks. Same approach the scale and
   segmented variants already take. */
.gform_wrapper.gravity-theme .gchoice {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 12px;
  margin: 0;
  padding: 0;
  background: var(--gf-opt-bg);
  border: 1px solid transparent;
  border-radius: var(--gf-radius);
  cursor: pointer;
  transition: background .12s, border-color .12s, box-shadow .12s;
}
.gform_wrapper.gravity-theme .gchoice:hover { background: color-mix(in srgb, var(--gf-opt-bg) 88%, var(--gf-accent)); }

/* Outlined fill variant */
.site[data-fieldfill="outlined"] .gform_wrapper.gravity-theme .gchoice,
[data-fieldfill="outlined"] .gform_wrapper.gravity-theme .gchoice {
  background: var(--gf-card);
  border-color: var(--gf-rule);
}

/* Hide native input, draw our own mark */
.gform_wrapper.gravity-theme .gchoice input.gfield-choice-input {
  position: absolute;
  opacity: 0;
  width: 1px; height: 1px;
  margin: 0;
}
.gform_wrapper.gravity-theme .gchoice > label {
  flex: 1;
  margin: 0;
  /* The card's padding, plus room for the mark — absolutely positioned against
     the card at --gf-opt-px, so the text clears it by the mark's width and a
     7px gap. Flex-centred rather than relying on the card's align-items, so a
     one-line label still sits centred in a card stretched by a two-line
     neighbour. */
  display: flex;
  align-items: center;
  padding: var(--gf-opt-py) var(--gf-opt-px) var(--gf-opt-py) calc(var(--gf-opt-px) + var(--gf-mark) + 7px);
  font-size: 16px;
  line-height: 1.35;
  color: var(--gf-ink);
  cursor: pointer;
}
/* GF caps the choice label at `calc(100% - 32px)` to reserve room for a mark
   drawn inline before it. Ours is absolutely positioned and the label's own
   padding already clears it, so the cap only ever costs us — it left 32px of
   dead, unclickable card down the right-hand edge, wrapped labels that had the
   room not to, and poisoned intrinsic width on the content-width lists.
   Four classes: GF's rule is body-prefixed, so a three-class selector ties on
   specificity and loses. Lifted once here rather than per variant (.wtd-scale,
   .tight_cols and .wtd-grouped each had to do it locally). */
.gform_wrapper.gravity-theme .gfield .gchoice > label { max-width: none; }

/* the mark (circle for radio, square for checkbox) */
.gform_wrapper.gravity-theme .gchoice > label::before {
  content: "";
  position: absolute;
  left: var(--gf-opt-px);
  top: 50%;
  transform: translateY(-50%);
  width: var(--gf-mark); height: var(--gf-mark);
  background: var(--gf-card);
  border: 1.5px solid var(--wp--preset--color--ink-3, #666F7A);
  transition: border-color .12s, background .12s;
}
.gform_wrapper.gravity-theme .gfield--type-radio .gchoice > label::before { border-radius: 50%; }
.gform_wrapper.gravity-theme .gfield--type-checkbox .gchoice > label::before { border-radius: 5px; }

/* Selected card (uses :has — supported in all current evergreen browsers) */
.gform_wrapper.gravity-theme .gchoice:has(input:checked) {
  background: var(--gf-accent-tint);
  border-color: var(--gf-accent);
  box-shadow: inset 0 0 0 1px var(--gf-accent);
}
.gform_wrapper.gravity-theme .gchoice:has(input:checked) > label::before { border-color: var(--gf-accent); }
/* radio inner dot */
.gform_wrapper.gravity-theme .gfield--type-radio .gchoice:has(input:checked) > label::after {
  content: "";
  position: absolute;
  left: calc(var(--gf-opt-px) + (var(--gf-mark) - var(--gf-mark-dot)) / 2);
  top: 50%; transform: translateY(-50%);
  width: var(--gf-mark-dot); height: var(--gf-mark-dot); border-radius: 50%;
  background: var(--gf-accent);
}
/* checkbox tick */
.gform_wrapper.gravity-theme .gfield--type-checkbox .gchoice:has(input:checked) > label::before {
  background: var(--gf-accent);
  border-color: var(--gf-accent);
}
.gform_wrapper.gravity-theme .gfield--type-checkbox .gchoice:has(input:checked) > label::after {
  content: "";
  position: absolute;
  /* The rotated tick reads as centred slightly left of true centre, so the
     offset is derived against a nominal 8px box rather than the tick's own
     width — that reproduces the hand-tuned position at any mark size. */
  left: calc(var(--gf-opt-px) + (var(--gf-mark) - 8px) / 2);
  top: 50%;
  width: 4.5px; height: 8px;
  border: solid #fff; border-width: 0 2px 2px 0;
  transform: translateY(-60%) rotate(45deg);
}
/* keyboard focus on the (hidden) input → ring the card */
.gform_wrapper.gravity-theme .gchoice:has(input:focus-visible) {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gf-accent) 25%, transparent);
}

/* Radio "Other" free-text option */
.gform_wrapper.gravity-theme .gchoice input.gform-field-label--type-inline + input[type="text"],
.gform_wrapper.gravity-theme .gchoice .gchoice_other_control,
.gform_wrapper.gravity-theme .gchoice input[type="text"] {
  margin-left: 8px;
  padding: 8px 12px;
  border: 1px solid var(--gf-rule);
  border-radius: 8px;
  font-size: 15px;
}

/* --------------------------------------------------------- Validation
   Deliberately quiet, following both the 2025 site and the design, whose only
   error treatment is `.modal-gap-note` — red text at 14.5px/600, no box and no
   banner. The message carries the error; nothing else turns red. */

/* Summary banner — hidden, as it was in 2025. Gravity Forms prints it above the
   form, which inside the modal lands between the section tag and the stepper
   and breaks the nav band open. It also only restates what the field message
   says, on a page showing a single question. */
.gform_wrapper.gravity-theme .gform_validation_errors { display: none; }

/* Keep the error colour from inheriting. GF sets it on the whole field wrapper,
   which tinted every choice label in the question red and read as though all
   the options were wrong. */
.gform_wrapper.gravity-theme .gfield_error,
.gform_wrapper.gravity-theme .gfield_error .gfield_label,
.gform_wrapper.gravity-theme .gfield_error legend.gfield_label { color: var(--gf-ink); }

/* Choice labels are the answers, not the error. GF reddens every label inside
   an errored field via `.gfield_error label` — three classes and an element,
   exactly the weight of our own `.gchoice > label` rule, so source order
   settled it and the options came out red. */
.gform_wrapper.gravity-theme .gfield.gfield_error .gchoice > label { color: var(--gf-ink); }

/* Text inputs still take a red border: conventional, and unlike a colour on the
   field it cannot spread to the choices. */
.gform_wrapper.gravity-theme .gfield_error .ginput_container input,
.gform_wrapper.gravity-theme .gfield_error .ginput_container textarea,
.gform_wrapper.gravity-theme .gfield_error .ginput_container select { border-color: var(--gf-error); }

/* The message. Carries a mark as well as the colour, so the error does not rest
   on colour alone — which matters more now the label stays in ink. Drawn as a
   mask rather than a background image so it inherits the text colour; 2025 used
   a Font Awesome glyph, and this theme does not load Font Awesome.

   Selectors carry five classes. Gravity Forms styles this element with a rule
   whose selector is character-for-character identical to the obvious override,
   then piles on `.validation_above .gfield_validation_message` and
   `.field_description_above .description` at four classes apiece — so three and
   four class overrides both lose. Qualifying with `.gfield.gfield_error` clears
   all of them. */
.gform_wrapper.gravity-theme .gfield.gfield_error .gfield_validation_message,
.gform_wrapper.gravity-theme .gfield.gfield_error .validation_message {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 0 14px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--gf-error);
}
.gform_wrapper.gravity-theme .gfield.gfield_error .gfield_validation_message::before,
.gform_wrapper.gravity-theme .gfield.gfield_error .validation_message::before {
  content: "";
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 1px;
  background-color: currentColor;
  -webkit-mask: var(--gf-alert-mask) no-repeat center / contain;
  mask: var(--gf-alert-mask) no-repeat center / contain;
}

/* ------------------------------------------- Arrived without a basis
   The hub is reachable directly, and renders without the basis the start form
   passes through. The block Gravity Forms shows on that was unstyled — a plain
   paragraph among the section cards, which is the one thing it must not read as.

   Given a border and a tint rather than the bare message used on fields: this is
   not one answer needing correction, it is the whole page being unusable, and it
   has to survive being skimmed. Same error colour and mark as the field
   messages, so it stays one language. */
.gform_wrapper.gravity-theme .gfield.wtd-missing-basis {
  position: relative;                  /* the mark is positioned against this */
  grid-column: 1 / -1;
  margin: 8px 0 4px;
  /* Left padding clears the mark. Not a flex row: the message is one sentence
     of mixed inline content — bold opening, plain text, link — and making the
     paragraph a flex container turns each of those into a column. */
  padding: 18px 20px 18px 52px;
  background: color-mix(in srgb, var(--gf-error) 7%, var(--gf-card));
  border: 1px solid color-mix(in srgb, var(--gf-error) 35%, transparent);
  border-left: 4px solid var(--gf-error);
  border-radius: var(--gf-radius);
}
.gform_wrapper.gravity-theme .gfield.wtd-missing-basis::before {
  content: "";
  position: absolute;
  left: 20px;
  top: 20px;
  width: 19px;
  height: 19px;
  background-color: var(--gf-error);
  -webkit-mask: var(--gf-alert-mask) no-repeat center / contain;
  mask: var(--gf-alert-mask) no-repeat center / contain;
}
.gform_wrapper.gravity-theme .gfield.wtd-missing-basis p {
  margin: 0;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--gf-ink);
}
/* The paragraph keeps a 14px bottom margin from the theme's own prose rules,
   which sat the panel 14px deeper than its top padding and read as lopsided.
   `:last-child` for the weight to clear it, and scoped so a future second
   paragraph in here would still be spaced from the first. */
.gform_wrapper.gravity-theme .gfield.wtd-missing-basis > p:last-child { margin-bottom: 0; }
.gform_wrapper.gravity-theme .gfield.wtd-missing-basis strong { color: var(--gf-error); }
.gform_wrapper.gravity-theme .gfield.wtd-missing-basis a {
  color: var(--gf-ink);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.gform_wrapper.gravity-theme .gfield.wtd-missing-basis a:hover { color: var(--gf-error); }

/* Everything else goes. Without a basis the sections cannot be submitted, so
   offering them is an invitation to waste an evening — and the two that carry no
   basis condition of their own would otherwise stay on screen. Hiding the footer
   with them also removes the submit button, which matters: button-gate.js counts
   *visible* incomplete sections, so hiding the cards alone would have left it
   with nothing to object to and enabled the button. (It is gated on the basis
   directly as well — this is not the only thing standing there.) */
.gform_wrapper.gravity-theme.wtd-no-basis .gfield:not(.wtd-missing-basis),
.gform_wrapper.gravity-theme.wtd-no-basis .gform_footer,
.gform_wrapper.gravity-theme.wtd-no-basis .gform_page_footer { display: none !important; }

/* ------------------------------------------------------------- Buttons */
.gform_wrapper.gravity-theme .gform_next_button,
.gform_wrapper.gravity-theme .gform_previous_button,
.gform_wrapper.gravity-theme .gform_button,
.gform_wrapper.gravity-theme .gform-theme-button {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 13px 26px;
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  line-height: 1;
  border: 1px solid transparent;
  border-radius: var(--gf-radius);
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s, box-shadow .12s;
}
/* Primary: Next + Submit */
.gform_wrapper.gravity-theme .gform_next_button,
.gform_wrapper.gravity-theme .gform_button {
  background: var(--gf-accent);
  color: #fff;
}
.gform_wrapper.gravity-theme .gform_next_button:hover,
.gform_wrapper.gravity-theme .gform_button:hover { background: var(--gf-accent-d); }
/* Secondary: Previous */
.gform_wrapper.gravity-theme .gform_previous_button,
.gform_wrapper.gravity-theme .gform-theme-button--secondary {
  background: var(--gf-card);
  color: var(--gf-ink);
  border-color: var(--gf-rule);
}
.gform_wrapper.gravity-theme .gform_previous_button:hover,
.gform_wrapper.gravity-theme .gform-theme-button--secondary:hover {
  background: var(--gf-opt-bg);
}
.gform_wrapper.gravity-theme .gform_next_button:focus-visible,
.gform_wrapper.gravity-theme .gform_previous_button:focus-visible,
.gform_wrapper.gravity-theme .gform_button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gf-accent) 30%, transparent);
}
/* Footer layout: Prev left, Next/Submit right */
.gform_wrapper.gravity-theme .gform_page_footer,
.gform_wrapper.gravity-theme .gform_footer {
  display: flex;
  gap: 16px;
  align-items: center;
  margin-top: 28px;
}
.gform_wrapper.gravity-theme .gform_page_footer .gform_next_button,
.gform_wrapper.gravity-theme .gform_page_footer .gform_button { margin-left: auto; }

/* ===== Chunk 3 — browser-review fixes (2026-07-01) ===== */

/* 1. Required messaging removed by design. The survey flow never lets you
   proceed past a required field without answering, so the top legend and the
   per-field asterisks are redundant noise. Fields remain required server-side. */
/* !important: GF's own body-prefixed rules out-specify a plain class selector. */
.gform_wrapper.gravity-theme .gform_required_legend,
.gform_wrapper.gravity-theme .gfield_required,
.gform_wrapper.gravity-theme .gfield_required_asterisk { display: none !important; }

/* 2. Start form (id 11) — basis selectors are "buttonized" per the design's
   segmented control (.seg), not radio-dot option cards. Short 2–3 option sets.
   Reusable via the .wtd-seg CSS Class Name too (for Yes/No etc. in chunk 4). */
.gform_wrapper.gravity-theme .gfield.buttonized .gfield_radio,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gfield_radio {
  /* !important: GF's body-prefixed gf_list_Ncol grid rules out-specify us */
  display: flex !important;
  grid-template-columns: none !important;
  flex-wrap: nowrap;
  width: 100%;
  gap: 0 !important;
  background: var(--gf-card);
  border: 1px solid var(--gf-rule);
  border-radius: 10px;
  overflow: hidden;
}
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice {
  flex: 1 1 0;
  min-width: 0;
  margin: 0;
  padding: 0 !important;   /* beat GF's body-prefixed .gchoice padding */
  background: transparent;
  border: 0;
  border-left: 1px solid var(--gf-rule);
  border-radius: 0;
  box-shadow: none;
}
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice:first-child,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice:first-child { border-left: 0; }

/* Stretched to the full content column, a two-option control gives 353px of
   button to the words "I'm employed", which reads as a slab rather than a
   choice. Capped at 80% instead of shrunk to fit (.wtd-seg, below): the start
   form stacks three of these, and shrink-to-fit would end each at a different
   place down the page. A shared cap keeps their right edges aligned. */
.gform_wrapper.gravity-theme .gfield.buttonized .gfield_radio { max-width: 80%; }
@media (max-width: 640px) {
  .gform_wrapper.gravity-theme .gfield.buttonized .gfield_radio { max-width: 100%; }
}

/* .wtd-seg is the compact variant: the control shrinks to fit its labels and
   sits left-aligned, rather than stretching the full row like the start form's
   basis selectors (.buttonized). Used for short Yes/No sets. Same selector
   weight as the shared rules above, placed after them to win on source order. */
.gform_wrapper.gravity-theme .gfield.wtd-seg .gfield_radio { width: max-content; max-width: 100%; }
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice { flex: 0 0 auto; }

/* .wtd-scale — scales are chips, not cards.
   ------------------------------------------------------------------------
   A scale is a short run of mutually exclusive options with uniform labels,
   and every scale in the survey now wears the same clothes as the likert's
   chips. Previously this was the design's .scale-opt: a card per option with a
   22px mark above a centred label. That reads well at desk width and badly on a
   phone — five cards wrap 2 / 2 / 1, the last one stranded at full width, and a
   single question runs 489px tall. Worse, the satisfaction pages put that
   treatment one page away from a likert asking the same question on the same
   five-point scale as chips, so the same thing looked like two different
   questions.

   The mark goes because it carries nothing here: one answer out of five, laid
   out in a row, is already unmistakably pick-one, and the repetition down a
   likert page makes six marks per statement pure noise. Lists keep their marks
   — there the mark is the only thing separating single-select from multi, which
   the roles questions depend on.

   !important on the layout to beat GF's gf_list_Ncol column grid, as the
   buttonized rules do. */
.gform_wrapper.gravity-theme .gfield.wtd-scale .gfield_radio {
  display: flex !important;
  grid-template-columns: none !important;
  flex-wrap: wrap;
  gap: 8px !important;                            /* matches the likert chip gap */
}
/* Stacked questions need more air than the 26px field gap gives them: it leaves
   each question's answers sitting almost as close to the *next* question's
   heading as to their own. question-spacing.js marks every question that
   follows another visible one — an adjacent-sibling rule cannot, because the
   conditional "please specify" follow-up sits between two questions in the DOM
   even while hidden, and selectors cannot skip hidden siblings. Follow-ups stay
   tied to their own question and are deliberately left unmarked. */
.gform_wrapper.gravity-theme .gfield.wtd-q-follows {
  margin-top: 22px;
}
/* The three rate rows are one question wearing three hats — hourly, day and
   monthly, all revealed by the same "I will enter these rates" checkbox — so the
   full question gap oversells the break between them. The grid's own row gap is
   enough to keep them apart as a group. (question-spacing.js cannot tell: rows
   two and three are triggered by a checkbox two rows up, not by the row above,
   which is what it tests for.)

   Pulled tighter still than that row gap: three rows plus the intro just
   overflowed the modal, and closing this gap is both the least intrusive place
   to find the height and the direction these rows wanted anyway. */
.gform_wrapper.gravity-theme .gfield.wtd-rate-entry.wtd-q-follows {
  margin-top: -10px;
}

/* `.wtd-scale-pad` was here: a 60px band above and below a lone scale, to lift a
   short page toward the height of the likert pages after it and halve the lurch
   as the modal resized between them.

   Removed with the class it keyed off, because it had stopped buying that. The
   modal box carries a 600px floor, so a scale page measures 600px with the band
   and 600px without it — the whitespace moved the content down and left the box
   where it was. On a phone the modal fills the screen and the question is moot.
   What remains of the lurch is the gap between that floor and a likert page,
   which this never reached. Once the scale became chips the empty band was also
   the most conspicuous thing on the page. */
/* The chip sizes to its label rather than sharing the row equally: a five-point
   scale reads as one run of options, and equal columns turn it into a table. */
.gform_wrapper.gravity-theme .gfield.wtd-scale .gchoice {
  flex: 0 0 auto;
  padding: 0;                                    /* padding lives on the label, so the whole chip is one click target */
}
.gform_wrapper.gravity-theme .gfield.wtd-scale .gchoice > label {
  /* Chip metrics, shared with .gsurvey-likert-choice. */
  padding: 8px 15px;
  max-width: none;                               /* lift GF's calc(100% - 32px) cap: that clearance is for a mark we no longer draw */
  font-size: 14px;
  font-weight: 600;
  line-height: 1.55;
  color: var(--gf-ink-2);
}
/* No mark, and no dot inside it. */
.gform_wrapper.gravity-theme .gfield.wtd-scale .gchoice > label::before,
.gform_wrapper.gravity-theme .gfield.wtd-scale .gchoice:has(input:checked) > label::after {
  content: none;
}
/* Chosen. Matches the likert chip: the fill inverts and the label goes white, so
   the change is in lightness as well as hue and does not rest on colour alone.
   The base .gchoice hover paints a tint at equal weight, so the chosen state is
   qualified with :has() at one class more to stay chosen while hovered. */
.gform_wrapper.gravity-theme .gfield.wtd-scale .gchoice:has(input:checked),
.gform_wrapper.gravity-theme .gfield.wtd-scale .gchoice:has(input:checked):hover {
  background: var(--gf-accent);
  border-color: var(--gf-accent);
}
.gform_wrapper.gravity-theme .gfield.wtd-scale .gchoice:has(input:checked) > label { color: #fff; }
/* Keyboard focus keeps the ring the rest of the form uses. */
.gform_wrapper.gravity-theme .gfield.wtd-scale .gchoice:has(input:focus-visible) {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gf-accent) 22%, transparent);
}
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice > label,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice > label {
  flex: 1;
  align-self: stretch;          /* fill the full segment height */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px 20px;
  text-align: center;
  white-space: nowrap;   /* case follows the form's stored labels (no transform) */
  font-weight: 600;
  font-size: 15px;
  color: var(--gf-ink-2);
}
/* no radio mark in buttonized mode */
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice > label::before,
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice > label::after,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice > label::before,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice > label::after { content: none; display: none; }
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice:hover,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice:hover { background: var(--gf-opt-bg); }
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice:has(input:checked),
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice:has(input:checked) {
  background: var(--gf-accent);
  box-shadow: none;
}
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice:has(input:checked) > label,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice:has(input:checked) > label {
  background: var(--gf-accent);   /* label fills the segment, so fill it too */
  color: #fff;
}

/* 3. Grid-column placement utilities (GF lays .gform_fields as a 12-col grid).
   Add one of these as a field's "CSS Class Name" in the GF editor to place /
   size HTML blocks & fields explicitly — the 2025 grid-column-start/end
   technique, as reusable classes instead of brittle per-field-ID rules.
   Mobile (<640px) collapses everything to full width. */
.gform_wrapper.gravity-theme .gfield.gf-col-full   { grid-column: 1 / -1; }
.gform_wrapper.gravity-theme .gfield.gf-col-half    { grid-column: span 6; }
.gform_wrapper.gravity-theme .gfield.gf-col-third   { grid-column: span 4; }
.gform_wrapper.gravity-theme .gfield.gf-col-quarter { grid-column: span 3; }
.gform_wrapper.gravity-theme .gfield.gf-col-two-thirds { grid-column: span 8; }
/* explicit placement: start/end on the 12-col track (end line is exclusive) */
.gform_wrapper.gravity-theme .gfield.gf-col-1-5   { grid-column: 1 / 5; }
.gform_wrapper.gravity-theme .gfield.gf-col-5-13  { grid-column: 5 / 13; }
.gform_wrapper.gravity-theme .gfield.gf-col-1-7   { grid-column: 1 / 7; }
.gform_wrapper.gravity-theme .gfield.gf-col-7-13  { grid-column: 7 / 13; }
.gform_wrapper.gravity-theme .gfield.gf-col-center { grid-column: 3 / 11; }
@media (max-width: 640px) {
  .gform_wrapper.gravity-theme .gfield[class*="gf-col-"] { grid-column: 1 / -1 !important; }
}

/* ===== Page-form layout (start + main survey) — 2026-07-01 =====
   Scoped to .wrap: only the on-page forms (start, main hub). Nested child
   forms render in the GPNF modal (outside .wrap) and use their own rules. */

/* Forms fill the full content shell (~996px), not the 820px reading measure. */
.wrap .wp-block-post-content { max-width: none; }
.wrap .gform_wrapper.gravity-theme { max-width: none; }

/* Two-column editorial layout on GF's 12-col grid (ports 2025 .right/.intro).
   .right  = label column, grid cols 1–3, right-aligned.
   .intro  = content column, grid cols 4–12, indented so the gutter between the
            two columns reads as ~2× the grid column-gap (32px grid + 32px pad).
   --wtd-col-gap tunes that indent. */
.wrap .gform_wrapper.gravity-theme { --wtd-col-gap: 32px; --wtd-row-pad: 42px; }
.wrap .gform_wrapper.gravity-theme .gfield.right {
  grid-column: 1 / 4;
  text-align: right;
}
/* Nested forms render in the GPNF modal, outside .wrap, so the rule above never
   reached them and their label column read as left-aligned body copy. The modal
   places .right fields by field width (a third of the row) rather than by
   explicit grid columns, so only the alignment is carried over. */
.gpnf-modal .gform_wrapper.gravity-theme .gfield.right { text-align: right; }
/* `.span_three_cols` is the hub's equivalent of `.intro` — a 2025 legacy grid
   class still on the three "Basis of employment" intro blocks. Left to GF it
   resolves to the field's stored width (Half = span 6), which stopped the copy
   about two thirds of the way across the content column. Treated as a content
   column marker so hub and start form agree. */
.wrap .gform_wrapper.gravity-theme .gfield.intro,
.wrap .gform_wrapper.gravity-theme .gfield.span_three_cols {
  grid-column: 4 / 13;
  padding-inline-start: var(--wtd-col-gap);
}
@media (max-width: 640px) {
  .wrap .gform_wrapper.gravity-theme .gfield.right,
  .wrap .gform_wrapper.gravity-theme .gfield.intro,
  .wrap .gform_wrapper.gravity-theme .gfield.span_three_cols {
    grid-column: 1 / -1;
    text-align: left;
    padding-inline-start: 0;
  }
}

/* ---- Hub grid: 16 columns instead of GF's 12 ----------------------------
   The hub lays section cards out beside the label column. On a 12-col grid the
   label takes 3, leaving 9 for content — which divides evenly into three cards
   but not two, so two-card rows could only be 5+4 (visibly lopsided) and were
   padded out with an empty third cell instead.

   16 columns fixes the arithmetic: the label takes 4 and content 12, which
   divides evenly by both 2 (span 6) and 3 (span 4). Because GF's column-gap is
   a percentage, the label and content columns come out the same width as
   before (234px / 742px at the 996px form width) — only the card split changes.

   Scoped to the hub (form 1) so the start form keeps GF's 12-col grid and its
   gf-col-* helpers. Fields default to full width here, with the editorial
   columns and cards as the explicit exceptions. */
.wrap #gform_wrapper_1 {
  --wtd-label-w: 236px;   /* visible width of the right-aligned label column */
  --wtd-gutter: 46px;     /* label -> content gap (design .ed-row) */
  --wtd-card-gap: 16px;   /* gap between cards (design .sec-grid) */
}
/* The label/content gutter is part of the grid rather than padding on the
   intro, so the copy and the cards share one left edge. When the gutter lived
   in padding, only the text was indented and the cards sat 32px to its left.
   The label track carries the difference between the two gaps and pads it back
   out, which keeps the label text itself at its established width. */
.wrap #gform_wrapper_1 .gform_fields {
  grid-template-columns:
    calc(var(--wtd-label-w) + var(--wtd-gutter) - var(--wtd-card-gap))
    repeat(12, 1fr);
  column-gap: var(--wtd-card-gap);
}
.wrap #gform_wrapper_1 .gform_fields > .gfield { grid-column: 1 / -1; }
.wrap #gform_wrapper_1 .gform_fields > .gfield.right {
  grid-column: 1;
  padding-inline-end: calc(var(--wtd-gutter) - var(--wtd-card-gap));
}
.wrap #gform_wrapper_1 .gform_fields > .gfield.intro,
.wrap #gform_wrapper_1 .gform_fields > .gfield.span_three_cols {
  grid-column: 2 / -1;
  padding-inline-start: 0;
}
.wrap #gform_wrapper_1 .gform_fields > .gfield.wtd-card-2 { grid-column: span 6; }
.wrap #gform_wrapper_1 .gform_fields > .gfield.wtd-card-3 { grid-column: span 4; }
/* Legacy empty <p></p> fillers that padded two-card rows to three. Redundant
   now the cards fill the row; hidden rather than deleted so the change is
   reversible from the form export. */
.wrap #gform_wrapper_1 .gform_fields > .gfield.wtd-row-spacer { display: none; }
@media (max-width: 640px) {
  .wrap #gform_wrapper_1 .gform_fields > .gfield.wtd-card-2,
  .wrap #gform_wrapper_1 .gform_fields > .gfield.wtd-card-3 { grid-column: 1 / -1; }
}

/* ---- Hub progress meter -------------------------------------------------
   Design: .hub-progress in Salary Survey Site.html. Injected after the intro
   copy by assets/js/hub-progress.js, since the intro is form content and the
   denominator depends on which sections the chosen basis reveals. */
.wrap .wtd-hub-progress {
  margin-top: 24px;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
/* Sits in the grid as a sibling of the intro fields, so it has to take the
   content column and its indent itself. */
.wrap #gform_wrapper_1 .gform_fields > .wtd-hub-progress {
  grid-column: 2 / -1;
}
@media (max-width: 640px) {
  .wrap #gform_wrapper_1 .gform_fields > .wtd-hub-progress { grid-column: 1 / -1; }
}

/* ---- Submit area --------------------------------------------------------
   Design .submit-wrap: rule above, generous padding, and a note naming the
   sections still outstanding. The design centres this; we keep the button on
   the content column's left edge to match the rest of the page. */
.wrap #gform_wrapper_1 .gform_footer {
  grid-template-columns:
    calc(var(--wtd-label-w) + var(--wtd-gutter) - var(--wtd-card-gap))
    repeat(12, 1fr);
  column-gap: var(--wtd-card-gap);
  margin: 0;
  padding: 48px 0 8px;
  border-top: 1px solid var(--gf-rule-soft);
}
.wrap #gform_wrapper_1 .gform_footer > input:not([type="hidden"]),
.wrap #gform_wrapper_1 .gform_footer > button {
  grid-column: 2 / -1;
  justify-self: start;
  margin-inline-start: 0;
  /* design .btn.xl */
  padding: 16px 64px;
  font-size: 17px;
  border-radius: 12px;
}
/* Sits under the button, so it needs its own row on the content column. */
.wrap #gform_wrapper_1 .gform_footer .wtd-submit-note {
  grid-column: 2 / -1;
  margin: 14px 0 0;
  font-size: 14px;
  color: var(--gf-ink-3);
}
@media (max-width: 640px) {
  .wrap #gform_wrapper_1 .gform_footer { padding-top: 32px; }
  .wrap #gform_wrapper_1 .gform_footer > input:not([type="hidden"]),
  .wrap #gform_wrapper_1 .gform_footer > button { padding: 14px 30px; font-size: 16px; }
  .wrap #gform_wrapper_1 .gform_footer .wtd-submit-note { grid-column: 1 / -1; }
}

/* ---- Hub grid: collapse to one column on small screens ------------------
   The generic collapse further up is `.wrap .gform_wrapper.gravity-theme
   .gfield.right` (0,4,0), while every hub placement is
   `.wrap #gform_wrapper_1 ...` (1,3,0). An id outranks any number of classes,
   so the hub never received it and its columns stayed put at every width. The
   start form has no id-scoped placements, which is why it collapsed correctly
   and only the hub did not.

   It does not present as overflow, which is what made it easy to miss. The
   first track is a fixed 266px (236 + 46 - 16) and there are twelve 16px gaps,
   so the grid cannot be narrower than 458px; below that the browser widens the
   layout viewport to fit it — measured at 477px on a 390px device — and scales
   the page down instead of overflowing. A scrollWidth check therefore looks
   clean while the whole hub renders about 18% small.

   Both grids are collapsed here, and every explicit placement is returned to
   the single track. Stated after the hub's own rules so source order cannot
   undo it where specificity ties. */
@media (max-width: 640px) {
  .wrap #gform_wrapper_1 .gform_fields,
  .wrap #gform_wrapper_1 .gform_footer {
    grid-template-columns: 1fr;
  }
  .wrap #gform_wrapper_1 .gform_fields > .gfield,
  .wrap #gform_wrapper_1 .gform_fields > .gfield.right,
  .wrap #gform_wrapper_1 .gform_fields > .gfield.intro,
  .wrap #gform_wrapper_1 .gform_fields > .gfield.span_three_cols,
  .wrap #gform_wrapper_1 .gform_fields > .gfield.wtd-card-2,
  .wrap #gform_wrapper_1 .gform_fields > .gfield.wtd-card-3,
  .wrap #gform_wrapper_1 .gform_fields > .wtd-hub-progress,
  .wrap #gform_wrapper_1 .gform_footer > input:not([type="hidden"]),
  .wrap #gform_wrapper_1 .gform_footer > button,
  .wrap #gform_wrapper_1 .gform_footer .wtd-submit-note {
    grid-column: 1 / -1;
  }
  /* The label column's right-alignment and gutter only make sense beside the
     content it labels; stacked, it is a heading above it. */
  .wrap #gform_wrapper_1 .gform_fields > .gfield.right {
    padding-inline-end: 0;
    text-align: left;
    /* Beside its content the column gap did the separating. Stacked, the
       standfirst under "Employee" / "Your job" runs straight into the copy
       below it, so the block has to carry its own space. */
    margin-bottom: 18px;
  }
  /* Section cards butt together once they are full width — row-gap is 0 on page
     forms, and side by side the column gap was the only thing between them. */
  .wrap #gform_wrapper_1 .gform_fields > .gfield--type-form {
    margin-bottom: var(--wtd-card-gap);
  }
  /* The footer sets grid-template-columns but never `display: grid`, so the
     generic `.gform_footer { display: flex; align-items: center }` is what
     actually lays it out and the tracks are inert. Stacked, that put the
     "complete all N sections" note beside the button rather than under it.
     State the axis rather than rely on tracks that were never in effect. */
  .wrap #gform_wrapper_1 .gform_footer {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
  }
  /* The desktop footer pushes the button to the content column's edge with an
     auto inline margin. In a stacked column that auto margin reads as "shove
     it right", so it has to be unset here rather than left to align-items. */
  .wrap #gform_wrapper_1 .gform_footer > input:not([type="hidden"]),
  .wrap #gform_wrapper_1 .gform_footer > button {
    align-self: flex-start;
    margin-inline-start: 0;
    margin-left: 0;
  }
}
.wrap .wtd-hub-progress-track {
  flex: 1;
  min-width: 200px;
  height: 8px;
  border-radius: 999px;
  background: var(--gf-rule);
  overflow: hidden;
}
.wrap .wtd-hub-progress-fill {
  height: 100%;
  width: 0;
  background: var(--gf-accent);
  border-radius: 999px;
  transition: width .3s;
}
.wrap .wtd-hub-progress-label {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--gf-ink-2);
}
@media (prefers-reduced-motion: reduce) {
  .wrap .wtd-hub-progress-fill { transition: none; }
}

/* Section dividers — the hub separates editorial rows with bare <hr> HTML
   fields. The design draws them in the soft rule tint with the row padding
   either side (.ed-row: padding var(--row-pad) 0; border-top). Page forms run
   at row-gap 0, so these margins set the whole rhythm between sections. */
.wrap .gform_wrapper.gravity-theme .gfield--type-html hr {
  height: 0;
  border: 0;
  border-top: 1px solid var(--gf-rule-soft);
  margin: var(--wtd-row-pad) 0;
}
@media (max-width: 640px) {
  .wrap .gform_wrapper.gravity-theme .gfield--type-html hr {
    margin: calc(var(--wtd-row-pad) * 0.6) 0;
  }
}

/* ----- Section label typography (.right column) — ports design .ed-label ----- */
.wrap .gform_wrapper.gravity-theme .gfield.right h2 {
  margin: 0;
  font-family: "Domine", Georgia, serif;
  font-weight: 600;
  font-size: 25px;   /* form section labels stay compact — dense form copy */
  line-height: 1.15;
  color: var(--gf-ink);
}
.wrap .gform_wrapper.gravity-theme .gfield.right p {
  margin: 12px 0 0;
  font-size: 14.5px;
  font-style: italic;
  line-height: 1.5;
  color: var(--gf-ink-2);
}
@media (max-width: 640px) {
  .wrap .gform_wrapper.gravity-theme .gfield.right h2 { font-size: 23px; }
}

/* ----- Vertical rhythm: no automatic row-gap on page forms -----
   Label + intro + question rows sit tight; extra vertical space is added
   explicitly via .add_buffer (or padding) exactly where a new section needs it,
   rather than a uniform gap between every grid row. */
.wrap .gform_wrapper.gravity-theme .gform_fields { row-gap: 0; }
.wrap .gform_wrapper.gravity-theme .gfield.add_buffer { margin-top: 40px; }

/* The basis question follows the intro block with nothing between them.
   question-spacing.js only marks a question that follows another *question*, so
   this pair never earns the 22px question gap and was left sitting on the
   intro's closing paragraph margin (14px, the paragraph rhythm). That was
   enough when the intro was two short lines; now it carries the whole "which
   should I choose" explanation and ends on a list, the question wants the
   grid's own field rhythm. Set as one gap rather than added to the paragraph
   margin, so the two cannot drift apart later. */
.wrap #gform_wrapper_11 #field_11_6 > :last-child { margin-bottom: 0; }
.wrap #gform_wrapper_11 #field_11_2 { margin-top: var(--gf-field-gap); }

/* ----- Paragraph rhythm (design convention: p{margin:0 0 14px}) -----
   Bottom-only margins: the first paragraph in the content column has no top
   margin, so it aligns flush with the margin:0 heading in the label column —
   without needing top padding (which would re-open a gap above tight-packed
   questions). Inter-paragraph + text→question spacing comes from bottom margin. */
.wrap .gform_wrapper.gravity-theme .gfield--type-html p,
.wrap .gform_wrapper.gravity-theme .gfield--type-html ul { margin: 0 0 14px; }

/* ----- Buttonized fill hardening (2026-07-01) -----
   Force the label to fill the whole segment: kill the base .gchoice flex gap and
   keep the native input fully out of flow, so nothing eats horizontal space. */
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice {
  display: block !important;   /* block, not flex — label fills width reliably */
  gap: 0 !important;
}
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice input.gfield-choice-input,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice input.gfield-choice-input {
  position: absolute !important; width: 1px !important; height: 1px !important;
  opacity: 0 !important; margin: 0 !important; padding: 0 !important;
}
.gform_wrapper.gravity-theme .gfield.buttonized .gchoice > label,
.gform_wrapper.gravity-theme .gfield.wtd-seg .gchoice > label {
  display: block !important;
  width: 100% !important;
  margin: 0 !important;
  text-align: center;
}

/* ===== Main hub — nested-form section cards (2026-07-01) =====
   Each GP Nested Forms field (.gfield--type-form) becomes a design .sec-card:
   white card, Domine title, "N questions" meta, full-width accent button.
   Scoped to .wrap (page hub); the child forms inside the modal are chunk 4. */
.wrap .gform_wrapper.gravity-theme .gfield--type-form {
  display: flex;
  flex-direction: column;
  background: var(--gf-card);
  border: 1px solid var(--gf-rule);
  border-radius: 14px;
  padding: 20px;
  transition: box-shadow .15s, border-color .15s, background .15s;
}
.wrap .gform_wrapper.gravity-theme .gfield--type-form:hover {
  box-shadow: 0 6px 20px rgba(20, 40, 60, .07);
}
/* title */
.wrap .gform_wrapper.gravity-theme .gfield--type-form > .gfield_label {
  margin: 0;
  font-family: "Domine", Georgia, serif;
  font-weight: 600;
  font-size: 19px;
  line-height: 1.2;
  color: var(--gf-ink);
}
/* meta ("N questions") */
.wrap .gform_wrapper.gravity-theme .gfield--type-form > .gfield_description {
  margin: 6px 0 0;
  padding: 0;
  font-size: 13.5px;
  color: var(--wp--preset--color--ink-3, #666F7A);
}
.wrap .gform_wrapper.gravity-theme .gfield--type-form > .gfield_description p { margin: 0; }
/* GP Nested Forms' table chrome no longer needs hiding: wtd-survey-core replaces
   the nested-entries template outright (see gp_template_output_nested-entries),
   so the card body is just the two button states below. */
.wrap .gform_wrapper.gravity-theme .gfield--type-form .gpnf-nested-entries-container {
  margin: auto 0 0;  /* pin the button to the card bottom, whatever the title height */
  padding-top: 16px;
  border: 0;
  background: none;
}
/* Both states = design .btn.full — outline for "Answer Questions", filled accent
   for "Review Responses" once the section is complete. */
.wrap .gform_wrapper.gravity-theme .gfield--type-form .gpnf-add-entry,
.wrap .gform_wrapper.gravity-theme .gfield--type-form .wtd-review-entry {
  display: block;
  width: 100%;
  padding: 12px 16px;
  text-align: center;
  font-family: inherit;
  font-weight: 600;
  font-size: 15px;
  border-radius: var(--gf-radius);
  background: var(--gf-card);
  color: var(--gf-accent-d);
  border: 1px solid var(--gf-accent-soft);
  cursor: pointer;
  text-decoration: none;
  transition: background .12s, border-color .12s;
}
.wrap .gform_wrapper.gravity-theme .gfield--type-form .gpnf-add-entry:hover {
  background: var(--gf-accent-tint);
  border-color: var(--gf-accent);
}

/* Completed section — the whole card tints, per the design's .sec-card.is-done.
   Detected from the button our nested-entries template swaps in, since GPNF
   puts no completion class on the field itself. */
.wrap .gform_wrapper.gravity-theme .gfield--type-form:has(.wtd-review-entry) {
  background: var(--gf-accent-tint);
  border-color: var(--gf-accent-soft);
}

/* Completed section — filled accent button (design pages_survey-main-completed-section). */
.wrap .gform_wrapper.gravity-theme .gfield--type-form .wtd-review-entry {
  background: var(--gf-accent);
  color: #fff;
  border: 1px solid var(--gf-accent);
}
.wrap .gform_wrapper.gravity-theme .gfield--type-form .wtd-review-entry:hover {
  background: var(--gf-accent-d);
  border-color: var(--gf-accent-d);
}

/* ----- Page-form footer button: align with the content column (2026-07-01) -----
   The submit/next button lives in .gform_footer (outside the 12-col field grid),
   so it defaults to the far-left page edge. Re-grid the footer to the same 12
   columns and place the button in the content column (4/13), left-aligned, so it
   sits under the questions like the design's .cta-wrap in .ed-body. */
.wrap .gform_wrapper.gravity-theme .gform_footer,
.wrap .gform_wrapper.gravity-theme .gform_page_footer {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: 2rem;
  /* Submitting the page is a bigger break than moving between sections, so it
     needs more air than the 40px .add_buffer puts between them — the inherited
     28px left the button sitting closer to the last question than the questions
     sat to each other. 48px matches the hub's submit area. (The hub sets its own
     margin/padding through an #id selector, so it is unaffected by this.) */
  margin-top: 48px;
}
.wrap .gform_wrapper.gravity-theme .gform_footer > input:not([type="hidden"]),
.wrap .gform_wrapper.gravity-theme .gform_footer > button,
.wrap .gform_wrapper.gravity-theme .gform_page_footer > input:not([type="hidden"]),
.wrap .gform_wrapper.gravity-theme .gform_page_footer > button {
  grid-column: 4 / 13;
  justify-self: start;
  /* match the content column's text indent so the button lines up with the copy */
  margin-inline-start: var(--wtd-col-gap, 32px);
}
@media (max-width: 640px) {
  .wrap .gform_wrapper.gravity-theme .gform_footer,
  .wrap .gform_wrapper.gravity-theme .gform_page_footer { display: flex; }
  .wrap .gform_wrapper.gravity-theme .gform_footer > input:not([type="hidden"]),
  .wrap .gform_wrapper.gravity-theme .gform_page_footer > input:not([type="hidden"]) { grid-column: auto; }
}

/* Highlight callout block (e.g. start form "Additional instructions") — space
   above it. Both the .right label and .intro body carry .highlight, so the whole
   row shifts down together (row-gap is 0 on page forms). */
.wrap .gform_wrapper.gravity-theme .gfield.highlight { margin-top: 40px; }

/* ======================================= Advanced Select (chunk 4)
   Design source: the multi-select field — `.ms` / `.ms-control` / `.ms-chip` /
   `.ms-x` / `.ms-input` / `.ms-menu` / `.ms-opt` / `.ms-empty`.

   GP Advanced Select is enabled (gpadvsEnable) on five fields: the four
   167-choice currency selects and the 34-choice industry multiselect. It is
   built on Tom Select and ships tom-select.bootstrap5.css, so the starting
   point is raw Bootstrap — square corners, a #343A40 border, 16px text.
   Mapping:

     .ts-wrapper          -> .ms          (positioning context)
     .ts-control          -> .ms-control
     .ts-control .item    -> .ms-chip     (selected values, multi only)
     .item .remove        -> .ms-x
     .ts-control input    -> .ms-input
     .ts-dropdown         -> .ms-menu
     .option              -> .ms-opt
     .option.active       -> .ms-opt:hover  (Tom Select's keyboard highlight)
     .no-results          -> .ms-empty

   Note the control keeps a literal 12px radius rather than --gf-radius: the
   design specifies 12px here even in pill mode, and a 999px radius on a
   multi-line control that grows with each selection reads as a lozenge. The
   selected chips are the pill-shaped part. */

.gform_wrapper.gravity-theme .ts-wrapper { position: relative; }

.gform_wrapper.gravity-theme .ts-wrapper .ts-control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  min-height: 48px;
  padding: 8px 10px;
  background: var(--gf-card);
  border: 1px solid var(--gf-rule);
  border-radius: 12px;
  box-shadow: none;
  cursor: text;
  font-size: 15.5px;
  color: var(--gf-ink);
}
.gform_wrapper.gravity-theme .ts-wrapper.focus .ts-control {
  border-color: var(--gf-accent);
  box-shadow: 0 0 0 3px var(--gf-accent-tint);
}
.gform_wrapper.gravity-theme .ts-wrapper .ts-control > input {
  flex: 1;
  min-width: 140px;
  margin: 0;
  padding: 5px 4px;
  border: 0;
  outline: 0;
  background: transparent;
  font-family: inherit;
  font-size: 15.5px;
  color: var(--gf-ink);
}

/* Selected values (multi-select only) */
.gform_wrapper.gravity-theme .ts-wrapper .ts-control > .item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  /* Right padding is deliberately 0: Tom Select's remove_button plugin sets
     `padding-right: 0 !important` on the item, so any value here is dead. The
     gap to the right of the button comes from its own margin instead — see
     `.remove` below. */
  padding: 5px 0 5px 11px;
  background: var(--gf-accent-tint);
  border: 1px solid var(--gf-accent-soft);
  border-radius: 999px;
  color: var(--gf-accent-d);
  font-size: 14px;
  font-weight: 600;
}
.gform_wrapper.gravity-theme .ts-wrapper .ts-control > .item .remove {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  /* Holds the button off the pill's right edge, since the item cannot carry
     padding there. The plugin also sets margin-left: 5px, which would stack on
     the item's 7px gap — state the whole margin so the two sides stay even. */
  margin: 0 6px 0 0;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--gf-accent) 22%, #fff);
  color: var(--gf-accent-d);
  font-size: 13px;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}
.gform_wrapper.gravity-theme .ts-wrapper .ts-control > .item .remove:hover {
  background: var(--gf-accent);
  color: #fff;
}

/* Menu */
.gform_wrapper.gravity-theme .ts-wrapper .ts-dropdown {
  margin: 5px 0 0;
  padding: 6px;
  background: var(--gf-card);
  border: 1px solid var(--gf-rule);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(20, 40, 60, .16);
}
/* The menu opens inside .gform_body, which scrolls — so it is clipped to the
   modal rather than overflowing it, and anything taller than the space below
   the control is simply cut off. Keep it short enough to fit; the field is
   type-to-search, so a long list was never the way through it anyway. Tom
   Select's own overflow-y on this element does the scrolling. */
.gform_wrapper.gravity-theme .ts-wrapper .ts-dropdown .ts-dropdown-content {
  max-height: 190px;
  padding: 0;
}
.gform_wrapper.gravity-theme .ts-wrapper .ts-dropdown .option {
  padding: 10px 12px;
  border-radius: 8px;
  background: transparent;
  color: var(--gf-ink);
  font-size: 15px;
  line-height: 1.35;
}
/* Headline + keywords (headline-options.js). The industry labels carry the
   category name and every term that belongs in it, which searches well and reads
   badly. The headline gets the label's weight; the keywords sit under it, muted
   and clipped to one line, so every option is a predictable two lines instead of
   wrapping to four. Selected chips render the headline alone. */
.gform_wrapper.gravity-theme .ts-wrapper .ts-dropdown .option .wtd-opt__head {
  display: block;
  color: var(--gf-ink);
}
.gform_wrapper.gravity-theme .ts-wrapper .ts-dropdown .option .wtd-opt__rest {
  display: block;
  margin-top: 1px;
  font-size: 13px;
  line-height: 1.3;
  color: var(--gf-ink-3);
  /* One line only: the point is to show that the keywords are there and
     searchable, not to reproduce all twelve of them. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Tom Select marks the keyboard-highlighted row `.active`; the design draws
   that the same as hover. */
.gform_wrapper.gravity-theme .ts-wrapper .ts-dropdown .option:hover,
.gform_wrapper.gravity-theme .ts-wrapper .ts-dropdown .option.active {
  background: var(--gf-accent-tint);
  color: var(--gf-ink);
}
.gform_wrapper.gravity-theme .ts-wrapper .ts-dropdown .option.selected {
  color: var(--gf-accent-d);
  font-weight: 600;
}
.gform_wrapper.gravity-theme .ts-wrapper .ts-dropdown .no-results {
  padding: 12px;
  color: var(--gf-ink-3);
  font-size: 14.5px;
}

/* ============================================ Likert scales (chunk 4)
   Design source: the "Cards (per statement)" likert variant —
   `.lk-cards` / `.lk-card` / `.lk-card-stmt` / `.lk-chips` / `.chip`.

   The Survey Add-On renders a 6-column matrix table:

     .gsurvey-likert > thead > tr > td.gsurvey-likert-row-label + th.gsurvey-likert-choice-label × 6
                     > tbody > tr > td.gsurvey-likert-row-label + td.gsurvey-likert-choice × 6
                                    (each choice cell holds a bare radio and
                                     carries data-label="Strongly agree")

   Two things make the card layout possible without touching the markup:

   1. Every choice cell carries its column label in `data-label`, so each chip
      can render its own text from CSS. No JS, and no reliance on the header row
      still being visible.
   2. The radios are named by `aria-labelledby` pointing at the row and column
      label ids, so each one is self-describing. That means the header row can
      be hidden and the table's own semantics dropped without the controls
      losing their accessible names — `aria-labelledby` resolves against hidden
      elements. It is also why the header row is hidden rather than removed.

   Dropping table semantics is intentional: a 6 × 8 matrix is miserable to
   navigate by cell, and the design deliberately breaks it into per-statement
   cards. */

/* GF draws the matrix with a left and bottom rule; the cards need neither. */
.gform_wrapper.gravity-theme .gsurvey-likert { display: block; width: 100%; border: 0; }
.gform_wrapper.gravity-theme .gsurvey-likert thead { display: none; }
.gform_wrapper.gravity-theme .gsurvey-likert tbody { display: flex; flex-direction: column; }

/* One statement per card. The row is the flex container for its own chips. */
.gform_wrapper.gravity-theme .gsurvey-likert tbody tr {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 16px 0;
  border-bottom: 1px solid var(--gf-rule-soft);
}
.gform_wrapper.gravity-theme .gsurvey-likert tbody tr:last-child { border-bottom: 0; }

/* An unanswered statement, after a failed Next (likert-validation.js).
   The rule down the side is what makes it findable while scrolling past; the
   mark beside the statement is what stops it resting on colour alone. Padding
   rather than a margin so the rule sits clear of the text without moving the
   chips, and a matching negative margin so a marked row does not shift the ones
   around it as marks come and go. */
.gform_wrapper.gravity-theme .gsurvey-likert tbody tr.wtd-likert-row-error {
  margin-inline-start: -14px;
  padding-inline-start: 11px;
  border-inline-start: 3px solid var(--gf-error);
  border-radius: 2px;
}
.gform_wrapper.gravity-theme .ginput_container_likert .gsurvey-likert tbody tr.wtd-likert-row-error .gsurvey-likert-row-label {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  color: var(--gf-error);
}
.gform_wrapper.gravity-theme .gsurvey-likert tbody tr.wtd-likert-row-error .gsurvey-likert-row-label::before {
  content: "";
  flex: none;
  width: 15px;
  height: 15px;
  margin-top: 3px;
  background-color: currentColor;
  -webkit-mask: var(--gf-alert-mask) no-repeat center / contain;
  mask: var(--gf-alert-mask) no-repeat center / contain;
}

/* The jump inside the field's error message. Reads as a link rather than a
   button: it sits inside a sentence, and a filled control there would compete
   with the page's own Next. */
/* The jump follows the message rather than sitting inside it — the message is a
   flex row of [mark][text], and a third item there either squeezes in beside the
   sentence or, once that row wraps, pushes the mark onto a line of its own. So
   the message closes up and the jump takes the line below, indented past the
   mark to start under the text. */
.gform_wrapper.gravity-theme .gfield.gfield_error .gfield_validation_message:has(+ .wtd-likert-jump),
.gform_wrapper.gravity-theme .gfield.gfield_error .validation_message:has(+ .wtd-likert-jump) {
  margin-bottom: 5px;
}
.gform_wrapper.gravity-theme .wtd-likert-jump {
  display: block;
  margin: 0 0 14px 24px;          /* 24px = the 16px mark + the message row's 8px gap */
  padding: 0;
  border: 0;
  background: none;
  /* Named rather than inherited: the field wrapper deliberately holds the error
     colour back from its children, and this control is now a sibling of the
     message rather than a child, so `inherit` would hand it plain ink. */
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.45;
  color: var(--gf-error);
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.gform_wrapper.gravity-theme .wtd-likert-jump:hover { text-decoration-thickness: 2px; }
.gform_wrapper.gravity-theme .wtd-likert-jump:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gf-error) 26%, transparent);
  border-radius: 3px;
}

/* The statement — full width so the chips wrap onto their own line.
   `.ginput_container_likert` is in the chain purely for weight: GF shades these
   cells with `table.gsurvey-likert tr:nth-child(2n+1) .gsurvey-likert-row-label`,
   where the nth-child counts as a class, so the obvious four-class override
   loses on element count and every other statement kept a grey band. */
.gform_wrapper.gravity-theme .ginput_container_likert .gsurvey-likert tbody tr .gsurvey-likert-row-label {
  flex: 0 0 100%;
  margin: 0 0 3px;   /* + the 8px row gap = the design's 11px */
  padding: 0;
  border: 0;
  background: none;
  /* Stated explicitly, not inherited. GF centres these cells in one rule and
     resets them to left in a second, and which of the two wins varies by
     environment — headless Chrome resolved to left while a real browser showed
     them centred. Declaring it here makes the result the same everywhere. */
  text-align: left;
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--gf-ink);
}

/* Chips. The cell is the chip; its label comes from data-label and the radio is
   stretched invisibly across it so the whole chip is the hit area. */
.gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice {
  position: relative;
  /* Flex-centred rather than relying on the line box: the label is a
     pseudo-element and picks up a 28px line-height against the chip's 16.8px,
     which sat the text low in the pill. */
  display: flex;
  align-items: center;
  justify-content: flex-start;
  min-height: 0;
  height: auto;         /* GF gives the choice <td> an explicit height:26px (border-box), which clipped the padding + line box into a cramped pill; let it size to content */
  margin: 0;
  padding: 8px 15px;
  border: 1px solid transparent;
  border-radius: var(--gf-radius);
  background: var(--gf-opt-bg);
  color: var(--gf-ink-2);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.55;
  white-space: nowrap;
  cursor: pointer;
  transition: background .13s, border-color .13s, color .13s;
}
.gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice::after {
  content: attr(data-label);
  display: block;
  /* Gravity Forms puts `margin-left: 32px` on every `td::after` in a likert, to
     clear the radio mark it draws at the left of the cell. This chip has no such
     mark — the radio is stretched invisibly across the whole cell — so that
     margin was 32px of dead space inside each pill, which is why the labels sat
     off-centre and the chips were a third wider than their text. */
  margin-left: 0;
  /* Design line-height (body is 1.55). Flex align-items:center handles the
     vertical centring now, so the tall line box no longer sits the text low —
     it just gives the chip the design's height (8+15 padding was already matched,
     the compressed 1.2 line-height was what made the chips look cramped). */
  line-height: 1.55;
}
.gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice input[type="radio"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}
.gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice:hover {
  border-color: var(--gf-accent-soft);
  color: var(--gf-ink);
}
/* GF tracks focus and selection with its own JS-applied classes and paints both
   #dfefff — `.gsurvey-likert-selected` plus a tick as a background image, and
   `.gsurvey-likert-focus` with !important. The selected rule is outranked
   normally, but nothing outranks an !important except another one, so the
   checked state matches that weight. It still beats the focus reset below on
   specificity, so a chip that is both focused and chosen reads as chosen. */
.gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice.gsurvey-likert-focus {
  background: var(--gf-opt-bg) !important;
}
.gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice:has(input:checked) {
  background: var(--gf-accent) !important;
  border-color: var(--gf-accent);
  color: #fff;
}
/* Keyboard focus keeps our own ring rather than GF's fill, so it shows on the
   chip that actually has focus instead of every clicked one. */
.site[data-fieldfill="outlined"] .gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice.gsurvey-likert-focus,
[data-fieldfill="outlined"] .gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice.gsurvey-likert-focus {
  background: var(--gf-card) !important;
}
.gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice:has(input:focus-visible) {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gf-accent) 22%, transparent);
}

/* Outlined fill variant, matching the treatment on the option cards. */
.site[data-fieldfill="outlined"] .gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice,
[data-fieldfill="outlined"] .gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice {
  background: var(--gf-card);
  border-color: var(--gf-rule);
}

@media (max-width: 560px) {
  /* Let long scale labels wrap rather than overflow the card. */
  .gform_wrapper.gravity-theme .gsurvey-likert .gsurvey-likert-choice { white-space: normal; }
}

/* ================================================ Section modal (chunk 4)
   Design source: .modal-overlay / .modal / .modal-x / .modal-nav /
   .modal-section-tag / .modal-body / .modal-foot in Salary Survey Site.html.

   GP Nested Forms renders the modal with tingle.js, so the design's structure
   has to be mapped onto tingle's boxes plus GF's own form markup:

     .gpnf-modal (.tingle-modal)      -> .modal-overlay
       button.tingle-modal__close     -> .modal-x   (a sibling of the box, not
                                         a child — see the close button below)
       .tingle-modal-box              -> .modal
         .tingle-modal-box__content
           .gpnf-modal-header         -> .modal-section-tag
           .gform_wrapper > form
             .gf_page_steps           -> the stepper half of .modal-nav
             .gform_body              -> .modal-body
         .tingle-modal-box__footer    -> .modal-foot

   The design's .modal-nav is a single bordered band holding the section tag and
   the stepper. Here those are in different branches of the tree, so the band is
   reconstructed by padding the header and closing it with a border under the
   stepper. Scoped to .gpnf-modal so other tingle modals are unaffected. */

.gpnf-modal.tingle-modal {
  display: flex;
  /* tingle lays the overlay out as a column, which silently transposes the two
     alignment axes: justify-content then centres vertically and align-items
     pins the modal to the left edge. */
  flex-direction: row;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 20px;
  overflow-y: auto;
  background: rgba(14, 24, 34, .55);
  backdrop-filter: blur(2px);
}
/* GP Nested Forms sets `.gpnf-modal .tingle-modal-box { width: clamp(800px,
   60%, 1000px) }` — the same specificity as a two-class override, so source
   order alone decided the width. Qualifying with .tingle-modal outranks it.

   Width is stated rather than left to flex-basis: a flex item sized 100% has a
   base size of the whole container, so justify-content has no free space to
   centre with and max-width only trims the right edge, pinning the modal left.
   min() keeps it at 880 with room to spare and lets it fill a narrow viewport.
   align-self keeps it at the top independently of the overlay's align-items. */
.gpnf-modal.tingle-modal .tingle-modal-box {
  width: min(880px, 100%);
  max-width: 880px;
  align-self: flex-start;
  margin: 0;
  border-radius: 18px;
  box-shadow: 0 30px 80px rgba(8, 18, 28, .4);
  /* max-height alone let a short page shrink the modal to fit, which left the
     industry picker's dropdown nowhere to open: Tom Select positions it
     absolutely inside .gform_body, and that scrolls, so it is clipped to the
     box rather than overflowing it. A floor tall enough to hold the open menu
     (264px of options plus the control and the question above it) keeps the
     space there. It also stops the modal resizing step to step, which read as
     jumpy on the short sections.

     min() rather than a flat value so a short viewport falls back to the same
     cap as max-height instead of forcing the modal off-screen. */
  min-height: min(600px, calc(100vh - 80px));
  max-height: calc(100vh - 80px);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* Padding moves onto the individual bands so the nav border can span edge to
   edge, as it does in the design.

   Long pages (Other Roles has 21 options; the likerts run to eight statements)
   are taller than a laptop viewport, so something has to scroll. tingle already
   caps the box and scrolls this content area, which keeps the footer in place —
   but the section tag and the stepper live in here too, so they scrolled away
   with the questions and you lost your place in the section.

   Give the scroll to the questions alone. That needs a flex column threaded all
   the way down to .gform_body, because every level between here and there is a
   plain block that would otherwise size to its content: content > wrapper >
   form > body. `min-height: 0` on each stretched item is what actually lets it
   shrink — a flex item's default `min-height: auto` refuses to go below its
   content, which is the usual reason a nested scroller silently does nothing. */
.gpnf-modal .tingle-modal-box__content {
  padding: 0;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;   /* the scroll now belongs to .gform_body */
}
.gpnf-modal .tingle-modal-box__content > .gform_wrapper,
.gpnf-modal .tingle-modal-box__content > .gform_wrapper > form {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
.gpnf-modal .gform_wrapper.gravity-theme .gform_body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;   /* don't chain the scroll to the page behind */
}

/* Section tag — small uppercase eyebrow, not a heading. */
.gpnf-modal .gpnf-modal-header {
  margin: 0;
  padding: 22px 30px 16px;
  font-family: "Open Sans", system-ui, sans-serif;
  font-size: 11.5px;
  /* GP Nested Forms styles this as a title bar and leaves a 72px line-height
     on it, so the 11.5px text floated in the middle of a line box far taller
     than itself and no amount of padding moved it to the top. */
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--gf-accent-d);
}
/* GF's heading block holds an empty description and the required-field legend.
   The design has neither, and it was the source of the gap between the section
   tag and the stepper. */
.gpnf-modal .gform_heading { display: none; }

/* Stepper closes the nav band. Both it and the section tag are pinned: flex:none
   so the scrolling body below cannot squeeze them. */
.gpnf-modal .gpnf-modal-header { flex: none; }
.gpnf-modal .gform_wrapper.gravity-theme .gf_page_steps {
  flex: none;
  margin: 0;
  padding: 0 30px 18px;
  border-bottom: 1px solid var(--gf-rule);
}

.gpnf-modal .gform_wrapper.gravity-theme .gform_body { padding: 28px 30px; }

/* Note on GF's own page footer, which looks like 84px of dead weight in here:
   GP Nested Forms mirrors Previous/Next into the tingle footer and hides the
   originals with `visibility: hidden`, so the box is still 84px tall. It is
   already out of the page's flow, though — `.gform_page` measures exactly its
   fields, and collapsing the footer changes `.gform_body`'s scrollHeight by
   zero. Measured, not assumed. Leave it alone. */

/* Footer — design .modal-foot. GP Nested Forms renders Cancel, Previous and
   Next in that source order; the design puts navigation at the outer edges, so
   Next is pushed right with an auto margin rather than relying on
   space-between, which would strand Previous in the middle of the row. */
.gpnf-modal .tingle-modal-box__footer {
  position: relative;   /* anchors the step count */
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 30px;
  border-top: 1px solid var(--gf-rule);
  background: #FBFCFD;
}

/* Buttons — design .btn. Selectors carry three classes: tingle styles these as
   `.tingle-modal-box__footer .tingle-btn`, which would otherwise tie with a
   two-class override and be settled by stylesheet order. */
.gpnf-modal .tingle-modal-box__footer .tingle-btn {
  margin: 0;
  padding: 11px 22px;
  font-family: "Open Sans", system-ui, -apple-system, sans-serif;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.1;
  white-space: nowrap;
  border: 1px solid transparent;
  border-radius: 10px;
  background: transparent;
  color: var(--gf-ink);
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, box-shadow .15s;
}

/* Primary — advances the section. On the last page GP Nested Forms swaps
   gpnf-btn-next for gpnf-btn-submit ("Complete this section"), so both carry
   the treatment or the button loses its styling and its place on the right. */
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-next,
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-submit {
  margin-inline-start: auto;
  background: var(--gf-accent);
  color: #fff;
  box-shadow:
    0 1px 0 color-mix(in srgb, var(--gf-accent) 55%, #000),
    0 4px 14px color-mix(in srgb, var(--gf-accent) 30%, transparent);
}
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-next:hover,
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-submit:hover { background: var(--gf-accent-d); }

/* Step count — design .modal-foot-mid, added by stepper.js.
   Centred by absolute positioning rather than as a flex item, so it is truly
   centred in the footer whatever buttons are present: Previous is absent on the
   first page, and the primary changes on the last. Positioning it in the flow
   would shift it as those come and go. */
.gpnf-modal .tingle-modal-box__footer .wtd-step-count {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--gf-ink-3);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

/* Saving — the ~250ms between save-and-close and the modal closing.
   GP Nested Forms rebuilds the footer mid-submit and proxies in its own copy of
   the save button, so the row briefly shows two identical buttons while the step
   count blinks out and back. Nothing has gone wrong, but it reads as though
   something has. Hold the row still and say what is happening instead.
   Hiding rather than emptying keeps the footer's height, so the modal does not
   jump on the way out. */
.gpnf-modal .tingle-modal-box.wtd-saving .tingle-modal-box__footer > * {
  visibility: hidden;
}
.gpnf-modal .tingle-modal-box.wtd-saving .tingle-modal-box__footer::after {
  content: "Saving…";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-size: 15px;
  font-weight: 600;
  color: var(--gf-ink-3);
}

/* ---------------------------------------------- Leave-section confirmation
   Shown by modal-close-confirm.js when the X (or Escape, or the overlay) would
   discard answers. It covers the modal box rather than the viewport: the thing
   at risk is this section, and dimming the whole page would read as a second
   modal on top of the first. */
.gpnf-modal .wtd-leave-confirm {
  position: absolute;
  inset: 0;
  z-index: 4;                          /* over the box; the close button is 3 */
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(27, 39, 51, .55);
}
.gpnf-modal .wtd-leave-confirm.is-open { display: flex; }
.gpnf-modal .wtd-leave-confirm__box {
  width: 100%;
  max-width: 420px;
  padding: 24px;
  background: var(--gf-card, #fff);
  border-radius: 14px;
  box-shadow: 0 18px 48px rgba(27, 39, 51, .28);
}
.gpnf-modal .wtd-leave-confirm__heading {
  margin: 0 0 10px;
  font-family: "Domine", Georgia, serif;
  font-size: 21px;
  line-height: 1.2;
  color: var(--gf-ink);
}
.gpnf-modal .wtd-leave-confirm__body {
  margin: 0 0 20px;
  font-size: 15px;
  line-height: 1.5;
  color: var(--gf-ink-2);
}
.gpnf-modal .wtd-leave-confirm__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.gpnf-modal .wtd-leave-confirm__actions button {
  appearance: none;
  flex: 1 1 auto;
  padding: 12px 18px;
  border-radius: var(--gf-radius, 10px);
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
}
/* Staying is the safe outcome, so it carries the weight. */
.gpnf-modal .wtd-leave-confirm__stay {
  background: var(--gf-accent);
  color: #fff;
}
.gpnf-modal .wtd-leave-confirm__stay:hover { background: var(--gf-accent-d); }
/* Leaving is destructive but not the point of the dialog — outlined in the
   error colour rather than filled with it, so it reads as available without
   competing for the click. */
.gpnf-modal .wtd-leave-confirm__leave {
  background: transparent;
  border-color: var(--gf-rule);
  color: var(--gf-error);
}
.gpnf-modal .wtd-leave-confirm__leave:hover {
  border-color: var(--gf-error);
  background: color-mix(in srgb, var(--gf-error) 7%, #fff);
}
.gpnf-modal .wtd-leave-confirm__actions button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gf-accent) 30%, transparent);
}
@media (max-width: 640px) {
  /* Stack them: side by side at this width the two labels wrap mid-phrase. */
  .gpnf-modal .wtd-leave-confirm__actions { flex-direction: column-reverse; }
}

/* Editing an answered section: the work can be kept, so there is a third way
   out and the hierarchy changes with it. Three labels do not fit across 420px
   without wrapping mid-phrase, so the row becomes a column at every width —
   three classes, which outranks the two-class row and media rules above without
   depending on source order. Order is best outcome first, top to bottom. */
.gpnf-modal .wtd-leave-confirm__actions button[hidden] { display: none; }
.gpnf-modal .wtd-leave-confirm--savable .wtd-leave-confirm__actions {
  flex-direction: column;
}
/* Saving keeps the answers and still gets them out, so it takes the weight. */
.gpnf-modal .wtd-leave-confirm__save {
  background: var(--gf-accent);
  color: #fff;
}
.gpnf-modal .wtd-leave-confirm__save:hover { background: var(--gf-accent-d); }
/* ...and staying steps down, rather than two filled buttons competing. */
.gpnf-modal .wtd-leave-confirm--savable .wtd-leave-confirm__stay {
  background: transparent;
  border-color: var(--gf-rule);
  color: var(--gf-ink);
}
.gpnf-modal .wtd-leave-confirm--savable .wtd-leave-confirm__stay:hover {
  border-color: var(--gf-ink-3);
  background: color-mix(in srgb, var(--gf-ink) 4%, #fff);
}

/* Ghost — cancel and back out. */
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-cancel,
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-cancel-mobile,
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-previous {
  background: transparent;
  color: var(--gf-ink-2);
  box-shadow: none;
}
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-cancel:hover,
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-cancel-mobile:hover,
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-previous:hover {
  background: var(--gf-rule-soft);
  color: var(--gf-ink);
}
.gpnf-modal .tingle-modal-box__footer .tingle-btn:disabled {
  opacity: .4;
  cursor: default;
}

/* Buttons we deliberately do not offer (all hidden in 2025 too).

   Cancel duplicates the close button, which is the clearer affordance of the
   two, and it sat next to Previous where it reads as navigation.

   Delete would let someone wipe a completed section from inside the review
   modal, leaving the card back at "Answer Questions" with no warning.

   "Back to Last Page" is injected by GP Multi-Page Navigation: with
   activation_type "progression" it appears whenever the current page is behind
   the furthest page reached, so it turns up every time a respondent steps back
   to check an answer. It is redundant next to the stepper, which already jumps
   to any visited step, and confusing next to Next/Previous. Its siblings for
   error recovery (gform_next_page_errors_button, gform_resubmit_button) are
   left alone: those only appear after a failed final submission, where they do
   something useful.

   Note the last-page button needs hiding twice. GP Nested Forms mirrors the
   form's page-footer buttons into the modal footer as its own tingle buttons
   and hides the originals, so the injected input and its footer proxy are two
   separate elements — and only the proxy is the one on screen. (That mirroring
   is also why GF's own Next/Previous inputs are in the DOM but never seen.) */
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-cancel,
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-cancel-mobile,
.gpnf-modal .tingle-modal-box__footer .gpnf-btn-delete,
.gpnf-modal .tingle-modal-box__footer .gform_last_page_button,
.gform_wrapper.gravity-theme .gform_last_page_button { display: none; }

/* Close button. tingle renders it as a sibling of the box, pinned to the
   overlay, so it cannot simply be positioned against the modal. The box is
   centred at a known max width, which makes its right edge computable: half the
   viewport less half the box, clamped so it stays inside once the box starts
   filling the screen. */
.gpnf-modal .tingle-modal__close {
  z-index: 3;                                  /* above the box, which tingle stacks over it */
  top: 54px;                                   /* overlay padding + design inset */
  right: max(34px, calc(50% - 426px));         /* 440px half-box - 14px inset */
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 9px;
  background: var(--gf-rule-soft);
  color: var(--gf-ink-2);
  font-size: 15px;
  transition: background .13s, color .13s;
}
.gpnf-modal .tingle-modal__close:hover {
  background: var(--gf-rule);
  color: var(--gf-ink);
}
/* tingle gives the icon span a 12.8px right margin to separate it from the
   "Close" label beside it. We hide that label, but the margin stayed and kept
   shoving the cross left of centre — 6px from one edge, 19px from the other.
   Clear the margin and let the button's own centring do its job. */
.gpnf-modal .tingle-modal__closeIcon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: auto;
  height: auto;
  margin: 0;
}
.gpnf-modal .tingle-modal__close svg { width: 15px; height: 15px; display: block; }
.gpnf-modal .tingle-modal__close svg path { fill: currentColor; }
.gpnf-modal .tingle-modal__closeLabel { display: none; }

/* Phone — full-screen sheet, per the design's 640px breakpoint. */
@media (max-width: 640px) {
  .gpnf-modal.tingle-modal { padding: 0; align-items: stretch; }
  .gpnf-modal.tingle-modal .tingle-modal-box {
    width: 100%;
    max-width: none;
    border-radius: 0;
    /* Height, not just max-height: the sheet should fill the viewport rather
       than stopping at its content and letting the page show underneath. */
    height: 100vh;
    height: 100dvh;
    max-height: 100dvh;
  }
  .gpnf-modal .gpnf-modal-header { padding: 16px 18px 13px; }
  .gpnf-modal .gform_wrapper.gravity-theme .gf_page_steps { padding: 0 18px 14px; }
  .gpnf-modal .gform_wrapper.gravity-theme .gform_body { padding: 22px 18px; }
  .gpnf-modal .tingle-modal-box__footer {
    padding: 12px 18px;
    padding-bottom: max(12px, env(safe-area-inset-bottom));
  }
  /* tingle hides the close button on small screens because GP Nested Forms
     substitutes its own Cancel in the footer. We hide that Cancel, so the
     close button has to come back — without it there is no way out of the
     modal on a phone at all. */
  .gpnf-modal .tingle-modal__close {
    display: flex;
    align-items: center;
    justify-content: center;
    top: 12px;
    /* tingle's small-screen rules pin it left; both edges have to be stated. */
    left: auto;
    right: 12px;
    width: 36px;
    height: 36px;
    border-radius: 10px;
  }

  /* Step rail — name only the step you are on.
     Eight sections at 40px plus their connectors overran the 390px sheet by
     58px, and a long label on the active step pushed the tail of the rail off
     screen. Rather than shrink everything until none of it is legible, the
     current step grows and the rest become markers: you can still read your
     position at a glance, and the numerals come back at desktop width.
     Non-active markers carry a top margin that puts their centres on the same
     line as the larger active circle, so the connectors still run straight. */
  .gpnf-modal .gform_wrapper.gravity-theme .gf_page_steps .gf_step {
    min-width: 0;
    padding: 0 4px;
  }
  .gpnf-modal .gform_wrapper.gravity-theme .gf_page_steps .gf_step .gf_step_number {
    width: 16px;
    height: 16px;
    margin-top: 9px;    /* centre lands at 17px, matching the active circle */
    font-size: 0;       /* the numeral cannot be read at this size */
  }
  .gpnf-modal .gform_wrapper.gravity-theme .gf_page_steps .gf_step.gf_step_active .gf_step_number {
    width: 34px;
    height: 34px;
    margin-top: 0;
    font-size: 15px;
    box-shadow: 0 0 0 3px var(--gf-accent-tint);
  }
  .gpnf-modal .gform_wrapper.gravity-theme .gf_page_steps .gf_step.gf_step_active .gf_step_label {
    display: block;
    font-size: 12px;
  }
  .gpnf-modal .gform_wrapper.gravity-theme .gf_page_steps .wtd-step-line {
    min-width: 8px;
    margin-top: 16px;   /* centred on 17px, as the circles now are */
  }

  /* No room for it: the footer is narrow enough that the primary button runs
     under the centre line, and the rail above already shows the position. */
  .gpnf-modal .tingle-modal-box__footer .wtd-step-count { display: none; }
}

/* =================================================== Section stepper (chunk 4)
   Design source: `.sn-step` / `.sn-node` / `.sn-num` / `.sn-lbl` / `.sn-line`
   (layout/app/chrome.jsx StepNav, progress variant "stepper").

   GF renders `pagination.type = steps` as a flat list of sibling divs:
     .gf_page_steps > .gf_step[.gf_step_active|_completed|_pending|_first|_last]
                        > .gf_step_number + .gf_step_label
   Two things differ from the design markup:
   1. There are NO connector elements between nodes. They are inserted by
      assets/js/stepper.js as real siblings, matching the design's structure,
      rather than drawn as a pseudo-element on each step. The design's nodes are
      `flex: none` and the lines `flex: 1`, so the lines absorb all the slack:
      that is what spreads the numbers out and leaves a gap between each line
      and the circles, neither of which a percentage-positioned pseudo-element
      on an equal-width step can reproduce.
   2. GP Multi-Page Navigation rewrites clickable steps, wrapping their contents
      in `<a class="gpmpn-page-link">`. The column layout therefore has to apply
      to the anchor as well as the bare step, or linked steps collapse to inline
      flow. Everything visual is stated for both. */

.gform_wrapper.gravity-theme .gf_page_steps {
  display: flex;
  align-items: flex-start;
  gap: 0;
  margin: 0 0 26px;
  padding: 0 0 2px;
  border: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.gform_wrapper.gravity-theme .gf_page_steps::-webkit-scrollbar { display: none; }

/* Node — sized to its own content (design .sn-node). The lines take the slack. */
.gform_wrapper.gravity-theme .gf_page_steps .gf_step {
  flex: none;
  min-width: var(--gf-step-w, 56px);
  margin: 0;
  padding: 0 8px;
  background: none;
  border: 0;
  font-family: inherit;
}
/* Gap is expressed as a label margin rather than flex `gap`, so it applies
   exactly once whether or not GPMPN has wrapped the contents in an anchor. */
.gform_wrapper.gravity-theme .gf_page_steps .gf_step,
.gform_wrapper.gravity-theme .gf_page_steps .gf_step > a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
}
.gform_wrapper.gravity-theme .gf_page_steps .gf_step > a {
  width: 100%;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
.gform_wrapper.gravity-theme .gf_page_steps .gf_step > a:hover .gf_step_label { color: var(--gf-ink); }

/* Connector line — the design's `.sn-line`, inserted between steps by
   stepper.js. flex:1 makes it absorb the rail's spare width, which both spreads
   the numbers and keeps the line clear of the circles by the node's padding. */
.gform_wrapper.gravity-theme .gf_page_steps .wtd-step-line {
  flex: 1;
  min-width: 14px;
  height: 2px;
  margin-top: 13px;   /* centres on the 28px circle */
  background: var(--gf-rule);
}
.gform_wrapper.gravity-theme .gf_page_steps .wtd-step-line.is-done { background: var(--gf-accent); }

/* Number bubble */
.gform_wrapper.gravity-theme .gf_page_steps .gf_step .gf_step_number {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  margin: 0;
  border: 2px solid var(--gf-rule);
  border-radius: 50%;
  background: var(--gf-card);
  color: var(--gf-ink-3);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
}
/* Legacy gravity-theme paints completed steps as a 40px slate (#607382) disc
   plus a white icon-font tick, stacked over the number via ::before/::after at
   `.gform_wrapper.gravity-theme .gf_page_steps .gf_step_completed .gf_step_number` — the same
   specificity as our reset, so source order alone decided it and GF won. Adding
   `.gf_step` alongside `.gf_step_completed` outranks it without !important.
   The design keeps the numeral and re-colours it (see is-done in chrome.jsx), so
   the overlay is dropped rather than restyled. */
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gf_step_completed .gf_step_number::before,
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gf_step_completed .gf_step_number::after {
  content: none;
  display: none;
}

/* Label */
/* GPMPN underlines the label (not the anchor) on clickable steps — the design
   keeps step labels undecorated, so clear it on the span itself. */
.gform_wrapper.gravity-theme .gf_page_steps .gf_step .gf_step_label {
  display: block;
  margin: 7px 0 0;
  /* GF indents the label 16px to clear the number in its own inline layout,
     which left the text sitting 8px right of the circle it sits under. */
  padding: 0;
  text-decoration: none;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--gf-ink-3);
  text-align: center;
  white-space: nowrap;
  transition: color .15s;
}

/* States */
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gf_step_active .gf_step_number {
  background: var(--gf-accent);
  border-color: var(--gf-accent);
  color: #fff;
  box-shadow: 0 0 0 4px var(--gf-accent-tint);
}
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gf_step_active .gf_step_label { color: var(--gf-ink); }

.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gf_step_completed .gf_step_number {
  background: var(--gf-accent-tint);
  border-color: var(--gf-accent);
  color: var(--gf-accent-d);
}
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gf_step_completed .gf_step_label { color: var(--gf-ink-2); }

/* Clickable steps. GPMPN marks a navigable step `.gpmpn-step-linked` and wraps
   its contents in an anchor, but gives it no affordance of its own — so a step
   you can jump to looked exactly like one you cannot. That is worst in edit
   mode, where the whole rail is navigable (stepper.js) yet every step but the
   current one is still drawn in the pending grey. */
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gpmpn-step-linked,
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gpmpn-step-linked a { cursor: pointer; }
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gpmpn-step-linked:hover .gf_step_number {
  border-color: var(--gf-accent);
  color: var(--gf-accent-d);
}
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gpmpn-step-linked:hover .gf_step_label { color: var(--gf-ink); }
/* Keyboard parity — the anchor is the focusable element, so the ring goes on it
   rather than the step. */
.gform_wrapper.gravity-theme .gf_page_steps .gf_step.gpmpn-step-linked a:focus-visible {
  outline: 2px solid var(--gf-accent);
  outline-offset: 3px;
  border-radius: 8px;
}

/* Phone — scroll the row and show only the current label, per the design's
   640px breakpoint. */
@media (max-width: 640px) {
  .gform_wrapper.gravity-theme .gf_page_steps .gf_step {
    min-width: auto;
    padding: 0 6px;
  }
  .gform_wrapper.gravity-theme .gf_page_steps .wtd-step-line { min-width: 18px; }
  .gform_wrapper.gravity-theme .gf_page_steps .gf_step .gf_step_label { display: none; }
  .gform_wrapper.gravity-theme .gf_page_steps .gf_step.gf_step_active .gf_step_label { display: block; }
}
