/**
 * UCF Contact Form — structural stylesheet
 *
 * Ships with the plugin and is enqueued by ContactFormShortcode::enqueueAssets
 * whenever the [ucf_contact_form] shortcode is present. Carries the complete
 * skin: layout, form states, responsive rules, spinner, character counter and
 * sidebar variant, driven entirely by the custom properties declared below.
 *
 * The token block uses brand-neutral defaults (grayscale primary). Themes
 * re-brand by shipping <active-theme>/assets/css/ucf-contact-form.css with a
 * token override scoped to .ucf-contact-wrapper; it is auto-enqueued after
 * this file (registered as a dependent style), so its values win the cascade.
 *
 * Tokens are scoped to .ucf-contact-wrapper (custom properties inherit to all
 * descendants) so nothing here leaks into the surrounding theme.
 *
 * Browser floor: browserslist "baseline 2022 with downstream"
 * (Chrome/Edge 108+, Firefox 108+, Safari/iOS 16.0+, Samsung 21+).
 * Range media-query syntax needs Safari 16.4 — use classic min/max-width.
 */
.ucf-contact-wrapper {
  /* CONTRAST CONTRACT for theme overrides — these are not free-form brand slots.
     A theme that overrides them must keep, at minimum:
       --color-primary       >= 4.5:1 vs --color-text-inverse  (button label sits on it)
       --color-primary-text  >= 4.5:1 vs --color-background-subtle (sidebar/link text)
       --color-focus-ring    >= 3:1   vs --color-background     (SC 1.4.11)
       --color-border-default>= 3:1   vs --color-background     (identifies the control)
       --color-border-hover  >= 3:1   vs --color-background     (a hover state is still the control)
     --color-border-subtle is deliberately NOT on this list: it draws the card, which is a
     decorative container rather than a UI component, so 1.4.11 does not reach it and a theme
     may set it to anything. Keep that distinction when editing — the two tokens were one until
     the card's control-grade border made the form read as a cage.
     The neutral defaults below all pass. This block previously documented what each token
     DOES but never what it must satisfy, so a theme author had no way to know an override
     broke conformance — and one did: a brand orange at 2.98:1 on the submit button and
     ~2.9:1 on sidebar links, while this plugin claimed AA. */
  /* Brand — neutral defaults; themes override these in their token file */
  --color-primary: #4b5563;
  --color-primary-hover: #374151;
  --color-primary-text: #374151;
  --color-primary-underline: rgba(75, 85, 99, 0.4);
  /* Field focus ring — defaults to the brand primary; a theme may soften it
     independently (e.g. a calmer hue) without changing the button/link color. */
  --color-focus-ring: var(--color-primary);
  --shadow-button-hover:
    0 4px 14px rgba(75, 85, 99, 0.15),
    0 2px 6px rgba(75, 85, 99, 0.12),
    0 0 0 1px rgba(75, 85, 99, 0.05);
  --shadow-button-active:
    0 2px 8px rgba(75, 85, 99, 0.18),
    0 1px 3px rgba(75, 85, 99, 0.15),
    inset 0 1px 2px rgba(0, 0, 0, 0.1);

  /* Neutral scale */
  --color-background: #ffffff;
  --color-background-subtle: #f9fafb;
  /* 3:1 vs --color-background is required by SC 1.4.11: on a white card the border is
     the only thing identifying the control. The old #e5e7eb was 1.24:1 — the fields read
     as ghosts. prefers-contrast:more still darkens further below, but that only rescues
     users who set an OS preference; the shipped default must pass on its own.
     #868e9c is 3.30:1 — the criterion with ~10% headroom, rather than the 4.83:1 of
     --color-neutral-500, which cleared it by 61% and made every field look stamped on.
     Do not reach for a lighter grey: nothing readable as "light" passes here. The scale's
     own #d1d5db is 1.47:1 and #9ca3af is 2.54:1; 3:1 on white bottoms out around #949494. */
  --color-border-default: #868e9c;
  /* Decorative only — the card outline. No contrast contract (see the block above). */
  --color-border-subtle: #e5e7eb;
  /* Hover must be DARKER than resting, not lighter. See the hover rule for why that is
     stated here rather than left to whoever picks the next value. */
  --color-border-hover: var(--color-neutral-500);
  --color-neutral-100: #f3f4f6;
  --color-neutral-300: #d1d5db;
  --color-neutral-500: #6b7280;
  --color-neutral-600: #4b5563;
  --color-neutral-700: #374151;
  --color-neutral-900: #111827;
  --color-text-primary: var(--color-neutral-900);
  --color-text-secondary: var(--color-neutral-600);
  --color-text-muted: var(--color-neutral-500);
  --color-text-inverse: #ffffff;

  --color-error: #ef4444;
  --color-error-background: #fee2e2;
  --color-error-border: #fca5a5;
  --color-error-text: #b91c1c;
  --color-success-background: #d1fae5;
  --color-success-border: #6ee7b7;
  --color-success-text: #047857;
  --color-warning-background: #fef3c7;
  --color-warning-text: #b45309;

  --spacing-sm: 0.25rem;
  --spacing-md: 0.5rem;
  --spacing-0_75: 0.75rem;
  --spacing-lg: 1rem;
  --spacing-xl: 1.5rem;
  --spacing-2xl: 2rem;
  --spacing-3xl: 3rem;
  --spacing-4xl: 4rem;

  --font-size-caption: 0.75rem;
  --font-size-body-sm: 0.875rem;
  --font-size-label: 0.875rem;
  --font-size-body: 1rem;
  --font-size-h5: 1.125rem;
  --font-size-h2: 1.875rem;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --line-height-normal: 1.5;

  --border-radius-sm: 0.25rem;
  --border-radius-md: 0.375rem;
  --border-radius-lg: 0.5rem;
  --border-radius-full: 50%;

  --input-border-width: 1px;
  --input-border-radius: var(--border-radius-md);
  --input-padding-x: 1rem;
  --input-padding-y: 0.75rem;

  --button-border-radius: var(--border-radius-md);
  --button-height-lg: 3rem;
  --button-transform-hover: translateY(-1.5px) scale(1.02);
  --button-transform-active: translateY(-0.5px) scale(0.99);
  /* Enumerated, not `all`: `all` includes outline-width/outline-offset/box-shadow, so the
     focus indicator grew in over 180ms instead of appearing at once. Focus indication
     must never be animated. */
  --button-transition: background-color 180ms var(--ease-premium),
                       transform 180ms var(--ease-premium),
                       box-shadow 180ms var(--ease-premium);

  --duration-short: 200ms;
  --ease-in-out: cubic-bezier(0.4, 0, 0.6, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-premium: cubic-bezier(0.23, 1, 0.32, 1);
  --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}

/* Container */
.ucf-contact-wrapper {
  max-width: 600px;
  margin: 0 auto;
  padding: clamp(var(--spacing-xl), 1rem + 2vw, var(--spacing-2xl))
           clamp(var(--spacing-lg), 4vw - 0.5rem, var(--spacing-2xl));
}

/* Screen-reader-only text (required-fields note, submit status, char-count
   prefix). The markup depends on this class; the plugin sheet must carry it —
   themes ship token overrides only and may define no global .sr-only. */
.ucf-contact-wrapper .sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.ucf-contact-wrapper.ucf-with-sidebar {
  max-width: 1200px;
}

/* Two-column layout */
.ucf-layout-container {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--spacing-3xl);
}

@media (min-width: 768px) {
  .ucf-layout-container {
    grid-template-columns: 1fr 320px;
    gap: var(--spacing-4xl);
  }
}

/* Header */
.ucf-contact-header {
  margin-bottom: var(--spacing-2xl);
  text-align: center;
}

.ucf-contact-title {
  font-size: clamp(1.5rem, 4vw + 0.5rem, var(--font-size-h2));
  font-weight: var(--font-weight-bold);
  line-height: 1.2;
  letter-spacing: -0.025em;
  margin-bottom: var(--spacing-md);
  color: var(--color-text-primary);
}

.ucf-contact-subtitle {
  font-size: clamp(var(--font-size-body-sm), 0.8rem + 0.4vw, var(--font-size-body));
  line-height: 1.5;
  color: var(--color-text-secondary);
  margin: 0;
}

/* Form */
.ucf-contact-form {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
  background-color: var(--color-background);
  /* Subtle, not the control border: this is the card around the fields, and SC 1.4.11 covers
     user interface components — a container panel is not one. Sharing the control token drew
     a 3:1 rectangle around five more 3:1 rectangles and read as a cage. */
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--border-radius-lg);
  /* The wrapper's padding already clamps down on mobile, but this was a flat 32px at
     every width, so the two stacked: 96px of plugin-owned inset at 375px, leaving the
     fields 226px. Unchanged at desktop. */
  padding: clamp(1.25rem, 5vw, var(--spacing-2xl));
}

.ucf-form-row {
  display: flex;
  gap: var(--spacing-lg);
}

.ucf-form-group {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
}

.ucf-form-group.ucf-full-width {
  flex: 1;
}

/* Labels */
.ucf-label {
  font-size: var(--font-size-label);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-primary);
}

/* --color-error-text, not --color-error: the latter is ~3.7:1 on white and fails AA as
   text. Same reasoning as .ucf-error-message below; these consumers were missed when that
   one was corrected. Borders keep --color-error, where 3.7:1 clears the 3:1 non-text bar. */
.ucf-required {
  color: var(--color-error-text);
}

/* Inputs */
.ucf-input,
.ucf-select,
.ucf-textarea {
  width: 100%;
  padding: var(--input-padding-y) var(--input-padding-x);
  font-size: 1rem; /* 16px at all widths; anything smaller triggers iOS auto-zoom on focus */
  font-family: inherit;
  line-height: var(--line-height-normal);
  color: var(--color-text-primary);
  background-color: var(--color-background);
  background-clip: padding-box;
  border: var(--input-border-width) solid var(--color-border-default);
  border-radius: var(--input-border-radius);
  transition: border-color var(--duration-short) var(--ease-premium),
              box-shadow var(--duration-short) var(--ease-premium),
              transform var(--duration-short) var(--ease-premium);
}

/* Darker on hover. This read --color-neutral-300 (#d1d5db, 1.47:1) back when resting was
   #e5e7eb (1.24:1) — both failing, but at least hover darkened. Raising resting to clear
   1.4.11 inverted the pair without touching this rule, so pointing at a field made its
   border FAINTER and dropped a hovered control back under 3:1. A hover state is still the
   control; it does not get to fail the criterion the resting state was fixed to meet. */
/* The exclusion is for the other half of 1.4.11 — states. Hover was (0,4,0) and the two invalid
   rules below are (0,2,0), so without it, hovering a field the user just failed validation on
   replaced the red border with the hover grey.
   BOTH error routes have to be named. The error border comes from `[aria-invalid="true"]` (set by
   the JS, and sticky until the next submit) AND from `:user-invalid` (set by the browser the
   moment an invalid value is committed) — excluding only the first leaves the live route erased
   on every in-floor Firefox, which has had :user-invalid since 88, plus Chrome 119+/Safari 16.5+.
   :is() rather than listing them in :not() directly, because :is() takes a FORGIVING list: on
   Chrome 108-118 / Safari 16.0-16.4 the unknown :user-invalid is dropped from the list and the
   rule survives, where a bare :not(:user-invalid) would invalidate the whole rule. Specificity is
   unchanged — :is() and :not() both take their most specific argument, and both arguments are
   (0,1,0). */
.ucf-input:hover:not(:focus):not(:disabled):not(:is([aria-invalid="true"], :user-invalid)),
.ucf-contact-form .ucf-select:hover:not(:focus):not(:disabled):not(:is([aria-invalid="true"], :user-invalid)),
.ucf-textarea:hover:not(:focus):not(:disabled):not(:is([aria-invalid="true"], :user-invalid)) {
  border-color: var(--color-border-hover);
  box-shadow: var(--shadow-sm);
}

.ucf-textarea {
  resize: vertical;
  min-height: 120px;
}

.ucf-contact-form .ucf-select {
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6,9 12,15 18,9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--spacing-0_75) center;
  background-size: 16px 16px; /* the SVG's intrinsic box is 16x16; 16x12 squashed it 25% */
  padding-right: var(--spacing-2xl);
}

.ucf-input:focus-visible,
.ucf-contact-form .ucf-select:focus-visible,
.ucf-textarea:focus-visible {
  border-color: var(--color-focus-ring);
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
  box-shadow: var(--shadow-sm);
}

/* Error state — JS sets aria-invalid on validation (all browsers).
   Kept as its own rule: grouping it with :user-invalid below would drop the
   whole list on browsers that don't know that pseudo-class (Chrome 108-118,
   Safari 16.0-16.4 — inside our floor). */
.ucf-input[aria-invalid="true"],
.ucf-contact-form .ucf-select[aria-invalid="true"],
.ucf-textarea[aria-invalid="true"] {
  border-color: var(--color-error);
}

/* :user-invalid adds real-time feedback where supported (Chrome 119+, Safari 16.5+) */
.ucf-input:user-invalid,
.ucf-contact-form .ucf-select:user-invalid,
.ucf-textarea:user-invalid {
  border-color: var(--color-error);
}

/* Character count */
.ucf-char-count {
  font-size: var(--font-size-caption);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
  text-align: right;
  opacity: 0;
  transition: opacity var(--duration-short) var(--ease-in-out),
              color var(--duration-short) var(--ease-in-out);
}

.ucf-textarea:focus ~ .ucf-char-count,
.ucf-char-count.ucf-visible {
  opacity: 1;
}

.ucf-char-count.ucf-warning {
  opacity: 1;
  color: var(--color-warning-text);
  font-weight: var(--font-weight-medium);
}

.ucf-char-count.ucf-danger {
  opacity: 1;
  color: var(--color-error-text);
  font-weight: var(--font-weight-semibold);
}

/* Error messages */
.ucf-error-message {
  font-size: var(--font-size-body-sm);
  /* Darker error token (not --color-error, which is ~3.7:1 on white and fails WCAG AA at this
     14px size); matches .ucf-error-message-global. The JS no longer sets an inline color. */
  color: var(--color-error-text);
  min-height: 1.25rem;
}

.ucf-error-message:empty {
  display: none;
}

/* Submit button */
.ucf-submit-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-md);
  width: 100%;
  padding: var(--spacing-md) clamp(var(--spacing-lg), 2.5vw, var(--spacing-2xl));
  min-height: var(--button-height-lg);
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-semibold);
  font-family: inherit;
  color: var(--color-text-inverse);
  background-color: var(--color-primary);
  border: none;
  border-radius: var(--button-border-radius);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: var(--button-transition);
}

.ucf-submit-btn:hover:not(:disabled) {
  /* Pin the inverse text color: a theme's global `button:hover { color }`
     (e.g. kickstart-pro-v2 sets it to the brand color) would otherwise win
     here and render the label the same hue as the button — invisible. */
  color: var(--color-text-inverse);
  background-color: var(--color-primary-hover);
  transform: var(--button-transform-hover);
  box-shadow: var(--shadow-button-hover);
}

.ucf-submit-btn:active:not(:disabled) {
  transform: var(--button-transform-active);
  box-shadow: var(--shadow-button-active);
  transition-duration: 75ms;
}

/* Two faults compounded here, and fixing either alone leaves the indicator failing.
   Geometry: outlines paint ABOVE box-shadow, so a 3px outline at 2px offset covered
   2px-5px of a 5px shadow — the only surviving band was 0px-2px, in --color-primary,
   directly against a button whose background is that same token. It read as the button
   growing 2px. Contrast: what remained was white against the brand orange at 2.98:1,
   under the 3:1 of SC 1.4.11. Now the ring is --color-focus-ring (the token that exists
   so a theme can supply a contrast-safe ring, which the AS theme does at 4.54:1) and the
   shadow is a plain separator beneath it, so the ring has white on BOTH sides. */
.ucf-submit-btn:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--color-text-inverse);
}

/* aria-disabled is matched alongside :disabled — the JS stopped using the `disabled`
   property so the button keeps its place in the accessibility tree and the focus ring. */
.ucf-submit-btn:disabled,
.ucf-submit-btn[aria-disabled="true"] {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* Loading state.
   The submitting veil below is absolutely positioned at z-index 1 over a static button,
   so it covered the button, its spinner and its "Sending..." label — the one state that
   can persist up to the 15s solve ceiling. Compositing the 40% white veil and the blur
   over the old opacity:0.85 left the label at ~1.74:1. Lift the button above the veil and
   drop the dimming: a veil plus a spinner already reads as busy without fading the thing
   the user is watching.

   opacity:1 is explicit and load-bearing. The JS sets aria-disabled AND aria-busy together,
   and the [aria-disabled] rule above declares opacity:0.6 at the same specificity (0,2,0) —
   so omitting it here does not "drop the dimming", it deepens it to 0.6 and takes the label
   to 2.87:1, below AA, in the state that persists up to the 15s solve ceiling.

   The compound selector is why that holds regardless of source order. Both single-attribute
   rules are (0,2,0), so opacity:1 would otherwise win only by sitting later in this file — and
   theme overrides are enqueued as DEPENDENTS of this sheet, so they load after it. One that
   set [aria-disabled] opacity would silently re-break AA with nothing to catch it. */
.ucf-submit-btn[aria-busy="true"],
.ucf-submit-btn[aria-busy="true"][aria-disabled="true"] {
  position: relative;
  z-index: 2;
  opacity: 1;
  cursor: wait;
  transform: none;
  box-shadow: var(--shadow-sm);
}

.ucf-contact-form.ucf-submitting {
  position: relative;
}

.ucf-contact-form.ucf-submitting::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgb(255 255 255 / 40%);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  border-radius: var(--border-radius-lg);
  z-index: 1;
  animation: ucf-fade-in var(--duration-short) var(--ease-out);
}

@keyframes ucf-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Spinner */
.ucf-spinner {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  border: 2px solid rgb(255 255 255 / 30%);
  border-top-color: var(--color-text-inverse);
  border-radius: var(--border-radius-full);
  animation: ucf-spin 0.8s linear infinite;
}

@keyframes ucf-spin {
  to { transform: rotate(360deg); }
}

/* Form messages.
   No margin-top: the container holds two permanently-present hidden divs, so it is never
   :empty and its margin always collected — stacking with the form's flex gap and the card
   padding into ~65px of dead space under the button. The flex gap alone spaces it. */
.ucf-form-messages {
  margin-top: 0;
}

.ucf-success-message {
  padding: var(--spacing-lg);
  background-color: var(--color-success-background);
  color: var(--color-success-text);
  border: 1px solid var(--color-success-border);
  border-radius: var(--border-radius-md);
  font-weight: var(--font-weight-medium);
  box-shadow: 0 2px 4px rgba(16, 185, 129, 0.1);
  animation: ucf-slide-in-down 400ms var(--ease-out);
}

.ucf-error-message-global {
  padding: var(--spacing-lg);
  background-color: var(--color-error-background);
  color: var(--color-error-text);
  border: 1px solid var(--color-error-border);
  border-radius: var(--border-radius-md);
  box-shadow: 0 2px 4px rgba(239, 68, 68, 0.1);
  animation: ucf-shake 300ms var(--ease-in-out);
}

@keyframes ucf-slide-in-down {
  from {
    opacity: 0;
    transform: translateY(-12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes ucf-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}

@media (prefers-reduced-motion: reduce) {
  /* Token override must live here too: the wrapper-scoped declarations above
     shadow any :root-level reduced-motion override a theme ships. */
  .ucf-contact-wrapper {
    --duration-short: 0ms;
  }

  .ucf-contact-form.ucf-submitting::before,
  .ucf-success-message,
  .ucf-error-message-global {
    animation: none;
  }

  /* --button-transition carries a literal 180ms, so zeroing --duration-short
     alone would leave the button hover lift/scale animating. */
  .ucf-contact-wrapper {
    --button-transition: none;
  }

  .ucf-spinner {
    animation-duration: 1.5s;
  }
}

@media (prefers-contrast: more) {
  .ucf-contact-wrapper {
    /* All three, not just the control border. --color-border-subtle darkened here for free
       while the card shared the control token; splitting them would otherwise have left the
       card pale for the one group that explicitly asked for more contrast.
       --color-border-hover is listed for a sharper reason: it resolves to #6b7280, which is
       LIGHTER than the #111827 resting value on this branch — leaving it out would rebuild
       the lighter-on-hover inversion inside a media query almost nobody tests. Hover indication
       is dropped in this mode: --shadow-sm is a 5%-alpha 1px shadow, at or below the perceptual
       floor for this cohort, so treat it as absent rather than as preserved feedback. */
    --color-border-default: var(--color-neutral-900);
    --color-border-subtle: var(--color-neutral-900);
    --color-border-hover: var(--color-neutral-900);
  }
}

/* Sidebar */
.ucf-sidebar-column {
  padding: var(--spacing-2xl);
  background-color: var(--color-background-subtle);
  border: 1px solid var(--color-neutral-100);
  border-radius: var(--border-radius-lg);
  box-shadow: var(--shadow-sm);
}

.ucf-info-grid {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-2xl);
}

/* Both levels, because the template picks between them: the heading is h3 only when the
   shortcode rendered its own title, and h2 otherwise. Matching h3 alone left the sidebar
   headings unstyled on every `title=""` page — they fell through to the theme's generic h2
   (25.5px/300/#666 against this rule's 18px/600/#111827). */
.ucf-info-item :is(h2, h3) {
  font-size: var(--font-size-h5);
  font-weight: var(--font-weight-semibold);
  line-height: 1.5;
  margin-bottom: var(--spacing-md);
  color: var(--color-text-primary);
}

.ucf-info-item p {
  font-size: var(--font-size-body-sm);
  line-height: 1.5;
  color: var(--color-neutral-600);
  margin: 0;
}

.ucf-info-item a {
  color: var(--color-primary-text);
  font-weight: var(--font-weight-semibold);
  text-decoration: underline;
  text-decoration-color: var(--color-primary-underline);
  text-underline-offset: 2px;
}

.ucf-info-item a:hover {
  text-decoration-color: var(--color-primary);
}

.ucf-info-item a:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
  border-radius: var(--border-radius-sm);
}

/* ------------------------------------------------
   Responsive refinements — discrete switches only;
   value scaling is handled by clamp() above
   ------------------------------------------------ */

/* Mobile */
@media (max-width: 767.98px) {
  .ucf-contact-title {
    line-height: 1.3;
  }

  .ucf-contact-subtitle {
    line-height: 1.6;
  }

  .ucf-form-row {
    flex-direction: column;
  }
}

/* Tablet */
@media (min-width: 768px) and (max-width: 1023.98px) {
  .ucf-input,
  .ucf-contact-form .ucf-select {
    /* min-height, not height: the natural height is 50px, so a fixed 2.75rem SHRANK these
       to 44px on exactly the tablet widths where touch accuracy matters most — the
       opposite of what the comment intended. This is now a floor. */
    min-height: 2.75rem;
  }
}
