:root {
  --bg-1: #ff9fb5;
  --bg-2: #ff5a87;
  --bg-3: #a45cd6;
  --bg-4: #6b4ba8;

  --ink:        #2a1340;
  --ink-soft:   #4a2e5c;
  --ink-mute:   #8a6f9c;
  --line:       #ecd9f0;

  --card:       #ffffff;
  --card-soft:  #fbf4ff;

  --accent:     #e91e63;
  --accent-2:   #7b1fa2;
  --accent-soft: #ffb4c9;   /* light end of the progress-bar gradient */
  --tint:       #fff0f6;    /* hover / selected background on white */
  --field-bg:   #fbf8ff;    /* textarea background */
  --icon-1:     #fce7f3;    /* feature icon chip gradient */
  --icon-2:     #f3e8ff;
  --bg-top:     #ffe6f0;    /* page background base gradient */
  --bg-bottom:  #f4e4ff;
  --good:       #2e7d32;
  --bad:        #c62828;

  /* Shadow and overlay colors; alpha is applied with color-mix(). */
  --shadow-ink: #2e083c;
  --scrim-ink:  #140528;
  --backdrop:   rgba(26, 17, 34, 0.55);

  --radius:     18px;
  --radius-sm:  12px;
  --shadow-sm:  0 2px 6px color-mix(in srgb, var(--shadow-ink) 8%, transparent);
  --shadow-md:  0 10px 30px color-mix(in srgb, var(--shadow-ink) 15%, transparent);
  --shadow-lg:  0 24px 60px color-mix(in srgb, var(--shadow-ink) 22%, transparent);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
               Arial, "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
  color: var(--ink);
  background:
    radial-gradient(1100px 700px at 10% -10%, var(--bg-1), transparent 60%),
    radial-gradient(900px 700px at 110% 10%, var(--bg-2), transparent 55%),
    radial-gradient(1200px 900px at 50% 110%, var(--bg-3), transparent 60%),
    linear-gradient(180deg, var(--bg-top) 0%, var(--bg-bottom) 100%);
  background-attachment: fixed;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

.container {
  max-width: 780px;
  margin: 0 auto;
  padding: 32px 20px 64px;
}

.container-wide {
  max-width: 960px;
  margin: 0 auto;
  padding: 32px 20px 64px;
}

header.site {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Respect iOS safe-area insets (notch / Dynamic Island / home indicator)
     while keeping 18/24 as minimums on devices that don't need insets. */
  padding:
    max(18px, env(safe-area-inset-top))
    max(24px, env(safe-area-inset-right))
    18px
    max(24px, env(safe-area-inset-left));
  max-width: 1120px;
  margin: 0 auto;
}

header.site .brand {
  font-weight: 700;
  font-size: 23px;
  letter-spacing: -0.015em;
  color: var(--ink);
}
header.site .brand .dot { color: var(--accent); }

header.site .age-chip {
  font-size: 12px;
  color: var(--ink-soft);
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(0,0,0,0.06);
  padding: 6px 10px;
  border-radius: 999px;
  backdrop-filter: blur(6px);
}

/* Same shape / weight as .age-chip, but interactive. Used for the
   "Send feedback" entry point that replaces the chip on every public
   page except the active quiz. */
header.site .chip-btn {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink-soft);
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(0,0,0,0.06);
  padding: 8px 14px;
  border-radius: 999px;
  backdrop-filter: blur(6px);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background 120ms ease, color 120ms ease, transform 120ms ease,
              border-color 120ms ease, box-shadow 160ms ease;
}
header.site .chip-btn:hover,
header.site .chip-btn:focus-visible {
  color: white;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
  border-color: transparent;
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 28%, transparent);
  outline: none;
}
header.site .chip-btn:active { transform: translateY(1px); }

/* Compact icon-only variant — used alongside nameChip on /quiz so both
   fit in the header without crowding. */
header.site .chip-btn.icon-only {
  padding: 8px 11px;
  font-size: 15px;
  line-height: 1;
}

/* Right-side cluster for pages that need multiple header affordances
   (quiz: feedback button + nameChip). */
header.site .header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ----- Feedback modal ----- */
.fb-backdrop {
  position: fixed; inset: 0;
  background: var(--backdrop);
  backdrop-filter: blur(3px);
  opacity: 0;
  /* Without this, the backdrop stays in place after .open is removed
     and silently eats every click on the page even though it's invisible. */
  pointer-events: none;
  transition: opacity 180ms ease;
  z-index: 40;
}
.fb-backdrop.open {
  opacity: 1;
  pointer-events: auto;
}

.fb-modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  padding-top: max(20px, env(safe-area-inset-top));
  padding-bottom: max(20px, env(safe-area-inset-bottom));
  z-index: 41;
  pointer-events: none;
}
.fb-card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: 0 24px 80px color-mix(in srgb, var(--scrim-ink) 35%, transparent);
  padding: 24px 26px 20px;
  width: 100%;
  max-width: 460px;
  position: relative;
  transform: translateY(10px) scale(0.98);
  opacity: 0;
  transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
              opacity 180ms ease;
  /* Card also needs to opt out of hit-testing while closed — it's still
     rendered (faded out) and would otherwise catch clicks in its stale
     position near the center of the viewport. */
  pointer-events: none;
}
.fb-modal.open .fb-card {
  transform: translateY(0) scale(1);
  opacity: 1;
  pointer-events: auto;
}

.fb-close {
  position: absolute;
  top: 12px; right: 12px;
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: white;
  color: var(--ink-soft);
  font-size: 18px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 140ms ease, color 140ms ease;
}
.fb-close:hover { background: var(--tint); color: var(--accent); }

.fb-title {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 4px;
}
.fb-sub {
  font-size: 13px;
  color: var(--ink-mute);
  margin: 0 0 14px;
}
.fb-textarea {
  width: 100%;
  min-height: 120px;
  max-height: 320px;
  resize: vertical;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--field-bg);
  font: inherit;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
  outline: none;
  transition: border-color 140ms ease, box-shadow 140ms ease;
  box-sizing: border-box;
}
.fb-textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent);
}
.fb-textarea::placeholder { color: var(--ink-mute); }

.fb-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 12px;
}
.fb-count {
  font-size: 11px;
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
}
.fb-count.warn { color: var(--accent); }

.fb-send {
  /* Use .btn inline-style; kept here for completeness in case .btn
     rules move later. */
  min-width: 96px;
}
.fb-send[disabled] { opacity: 0.55; cursor: not-allowed; }

.fb-status {
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 13px;
}
.fb-status.ok   { background: #e3f6e8; color: #2e7d32; }
.fb-status.err  { background: #ffebee; color: #8e0000; }

@media (max-width: 480px) {
  .fb-card { padding: 20px 18px 16px; }
  .fb-title { font-size: 17px; }
}

@media (prefers-reduced-motion: reduce) {
  .fb-backdrop, .fb-modal .fb-card { transition: none; }
}

/* ----- Cards ----- */
.card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 28px;
}
.card + .card { margin-top: 20px; }
.card.soft { background: var(--card-soft); box-shadow: var(--shadow-sm); }

.card h1 {
  font-size: 32px;
  margin: 0 0 8px;
  letter-spacing: -0.02em;
}
.card h2 {
  font-size: 22px;
  margin: 0 0 6px;
  letter-spacing: -0.01em;
}
/* Use margin-block (top+bottom only) so child paragraphs that set
   `margin: 0 auto ...` for centering don't have their inline (left/right)
   margins clobbered by the shorthand. Previously `margin: 0 0 12px` set
   all four sides, silently defeating `auto` side-margins on descendants. */
.card p { color: var(--ink-soft); line-height: 1.5; margin-block: 0 12px; }
.muted { color: var(--ink-mute); font-size: 14px; }

/* ----- Buttons ----- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 20px;
  border-radius: 999px;
  border: none;
  /* Three-stop "palindromic" gradient (pink → purple → pink) drawn at
     200% size so only half is visible in the button at any given time.
     At rest, we frame the top-left half (pink → purple); on hover we
     slide the frame to the bottom-right half (purple → pink). Because
     we're animating `background-position` — an interpolable CSS value —
     the transition is buttery smooth, unlike swapping the whole gradient
     image which browsers can't tween. */
  background-image: linear-gradient(
    135deg,
    var(--accent)   0%,
    var(--accent-2) 50%,
    var(--accent)   100%
  );
  background-size: 200% 200%;
  background-position: 0% 0%;
  color: white;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: transform 150ms ease,
              box-shadow 180ms ease,
              background-position 550ms cubic-bezier(0.22, 1, 0.36, 1),
              opacity 120ms ease;
  box-shadow: 0 8px 20px color-mix(in srgb, var(--accent) 35%, transparent);
  /* .btn may be applied to an <a>; suppress the global a:hover underline. */
  text-decoration: none;
}
.btn:hover,
.btn:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 12px 28px color-mix(in srgb, var(--accent) 48%, transparent);
  /* Slide to the far corner — the visible "window" now shows the purple
     → pink half, so the gradient appears to flow across the button. */
  background-position: 100% 100%;
  text-decoration: none;
  outline: none;
}
.btn:active { transform: translateY(0); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .btn { transition: opacity 120ms ease; }
}

.btn.secondary {
  background: white;
  color: var(--ink);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
}
.btn.secondary:hover { box-shadow: var(--shadow-md); }

.btn.big {
  padding: 16px 28px;
  font-size: 18px;
}

.btn.ghost {
  background: transparent;
  color: var(--ink);
  box-shadow: none;
  border: 1px dashed var(--line);
}

/* ----- Hero (landing) ----- */
.hero {
  text-align: center;
  padding: 48px 20px 24px;
}
.hero .emojis {
  font-size: 40px;
  margin-bottom: 18px;
  display: inline-flex;
  gap: 14px;
}
/* Each emoji floats + tilts independently on a 3.6s loop, staggered by
   0.5s so they feel alive without being in lockstep. Alternating rotation
   directions (via :nth-child) add a touch of playful asymmetry. */
.hero .emojis span {
  display: inline-block;
  animation: emoji-float 3.6s ease-in-out infinite;
  will-change: transform;
  transform-origin: center bottom;
}
.hero .emojis span:nth-child(1) { animation-delay: 0s;    animation-name: emoji-float-left; }
.hero .emojis span:nth-child(2) { animation-delay: 0.45s; animation-name: emoji-float-right; }
.hero .emojis span:nth-child(3) { animation-delay: 0.9s;  animation-name: emoji-float-left; }
.hero .emojis span:nth-child(4) { animation-delay: 1.35s; animation-name: emoji-float-right; }

@keyframes emoji-float-left {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-10px) rotate(-6deg); }
}
@keyframes emoji-float-right {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-10px) rotate(6deg); }
}

@media (prefers-reduced-motion: reduce) {
  .hero .emojis span { animation: none; }
}
.hero h1 {
  font-size: 44px;
  letter-spacing: -0.02em;
  margin: 0 0 12px;
  line-height: 1.05;
}
/* Optional hero parts a brand stylesheet can switch on (index.html). */
.hero-eyebrow, .hero-alt, .hero-art { display: none; }
.hero h1 em { font-style: inherit; }
.hero p.lead {
  font-size: 18px;
  color: var(--ink-soft);
  max-width: 560px;
  margin: 0 auto 28px;
  line-height: 1.5;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-top: 28px;
}
.feature {
  background: rgba(255, 255, 255, 0.88);
  border-radius: var(--radius);
  padding: 26px 20px 22px;
  box-shadow: var(--shadow-sm);
  text-align: center;
  border: 1px solid rgba(255, 255, 255, 0.6);
  transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1),
              box-shadow 220ms ease,
              background 200ms ease;
}
.feature:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 36px color-mix(in srgb, var(--shadow-ink) 16%, transparent);
  background: rgba(255, 255, 255, 0.96);
}

/* Icon chip — a soft pink→purple gradient circle instead of a bare emoji.
   Adds visual weight to each card and makes them feel like "real" products. */
.feature .icon {
  width: 52px;
  height: 52px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--icon-1) 0%, var(--icon-2) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  line-height: 1;
  box-shadow: inset 0 -1px 2px color-mix(in srgb, var(--accent) 8%, transparent),
              0 2px 6px color-mix(in srgb, var(--shadow-ink) 6%, transparent);
}

/* h2 is the semantic level (flat hierarchy under the hero h1); visual
   size is set here rather than relying on the default browser h2. */
.feature h2 { margin: 0 0 6px; font-size: 16px; letter-spacing: -0.005em; }
.feature p  { margin: 0; font-size: 14px; color: var(--ink-soft); line-height: 1.5; }

@media (prefers-reduced-motion: reduce) {
  .feature { transition: none; }
  .feature:hover { transform: none; }
}

/* ----- Press strip ("As featured in") ----- */
/* Quiet social-proof section. Logos sit grayscale + dimmed at rest so
   they don't compete with the feature cards above or the "How it works"
   steps below; hover (where available) pops them to full color. Flex
   with wrap so 2 or 4 logos render cleanly at any viewport. */
.press {
  margin: 36px 0 8px;
  text-align: center;
}
.press .press-kicker {
  margin: 0 0 18px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.press-logos {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 24px 44px;
}
.press-logos li {
  display: flex;
  align-items: center;
  justify-content: center;
}
.press-logos img {
  /* Let the grid cell control width; images cap at 110px wide on desktop,
     scale down to 80px on narrow mobile. Explicit height cap keeps the
     varying aspect ratios visually consistent. */
  height: auto;
  max-height: 28px;
  width: auto;
  max-width: 110px;
  object-fit: contain;
  /* Base: desaturate and mute so the strip sits quietly in the page.
     Most wordmarks (GQ, Cosmo, AskMen) are already near-black so they
     don't need extra darkening — a single brightness() value can't suit
     all logos at once. Per-logo overrides below darken the outliers. */
  filter: grayscale(1) opacity(0.75);
  transition: filter 220ms ease, transform 220ms ease;
}
/* Bumble's gold is too light against the lavender page — pull it down
   so it reads at the same weight as the darker wordmarks. */
.press-logos img[src$="bumble.png"] {
  filter: grayscale(1) brightness(0.45) opacity(0.9);
}
@media (hover: hover) {
  .press-logos img:hover,
  .press-logos img[src$="bumble.png"]:hover {
    filter: grayscale(0) brightness(1) opacity(1);
    transform: translateY(-1px);
  }
}
@media (max-width: 560px) {
  .press { margin-top: 26px; }
  .press-logos { gap: 18px 28px; }
  .press-logos img { max-width: 80px; max-height: 22px; }
}

/* Numbered steps — gradient circles replace the default <ol> markers for
   a more "onboarding card" feel on the "How it works" section. */
ol.steps {
  list-style: none;
  padding: 0;
  margin: 18px 0 0;
  display: grid;
  gap: 16px;
}
ol.steps li {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}
ol.steps .n {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
  color: white;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.02em;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 26%, transparent);
}
ol.steps p {
  margin: 5px 0 0;
  color: var(--ink-soft);
  line-height: 1.55;
  flex: 1;
}

@media (max-width: 720px) {
  .feature-grid { grid-template-columns: 1fr; }
  .hero h1 { font-size: 34px; }
}

/* ----- Forms ----- */
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
}
.field label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.field input[type="text"],
.field select {
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  font-size: 16px;
  font-family: inherit;
  background: white;
  color: var(--ink);
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.field input[type="text"]:focus,
.field select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

.row-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
@media (max-width: 560px) { .row-2 { grid-template-columns: 1fr; } }

.partner-block {
  background: var(--card-soft);
  border-radius: var(--radius);
  padding: 20px;
}
.partner-block h3 {
  margin: 0 0 16px;
  font-size: 18px;
}

.anatomy-toggle {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.anatomy-toggle label {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  border: 2px solid var(--line);
  border-radius: var(--radius-sm);
  background: white;
  cursor: pointer;
  user-select: none;
  transition: all 120ms ease;
}
.anatomy-toggle label .emj { font-size: 34px; line-height: 1; }
.anatomy-toggle input { display: none; }
.anatomy-toggle input:checked + label {
  border-color: var(--accent);
  background: var(--tint);
  color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent);
}

/* Form action row: right-aligned on desktop (original behavior),
   centered on mobile so the button doesn't hug the edge. Add `.centered`
   to force centered alignment on desktop too — useful for primary CTAs
   that shouldn't hug the corner. */
.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 14px;
}
.form-actions.centered {
  justify-content: center;
}
@media (max-width: 560px) {
  .form-actions {
    justify-content: center;
  }
}

/* ----- Share page (partner A's link-delivery card) ----- */

.share-card .share-title {
  text-align: center;
  margin: 0 0 8px;
  letter-spacing: -0.01em;
}
.share-card .share-intro {
  text-align: center;
  max-width: 48ch;
  margin: 0 auto 26px;
  line-height: 1.55;
}

/* Two methods side-by-side on desktop, stacked on mobile. Flex-wrap
   handles the breakpoint naturally — no media-query split needed. */
.share-methods {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  align-items: stretch;
  justify-content: center;
  margin: 0 0 8px;
}

/* QR method (fixed width, takes only what it needs) */
.share-qr {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
.qr-frame {
  background: white;
  padding: 14px;
  border-radius: 16px;
  border: 1px solid var(--line);
  box-shadow: 0 6px 24px color-mix(in srgb, var(--shadow-ink) 10%, transparent),
              0 1px 2px  color-mix(in srgb, var(--shadow-ink) 5%, transparent);
}
.qr-slot svg {
  display: block;
  width: 180px;
  height: 180px;
}
/* The library emits the QR modules as an <path> with no fill attribute
   (defaults to black). Override via CSS to match the brand ink — it's
   still very dark (#2a1340) so scanner contrast stays high. */
.qr-slot svg path { fill: var(--ink); }

/* "OR" divider between the two methods. Vertical stripe on desktop,
   horizontal on mobile — a single flex-direction swap at the breakpoint
   does both. */
.share-divider {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: var(--ink-mute);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  padding: 8px 0;
}
.share-divider::before,
.share-divider::after {
  content: '';
  width: 1px;
  flex: 1 1 40px;
  background: var(--line);
}

/* Link method (fills available space on desktop, full-width on mobile) */
.share-link {
  flex: 1 1 280px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
}
.share-link .linkblock { margin: 0; }
.share-link .share-privacy {
  margin: 4px 0 0;
  font-size: 12px;
  line-height: 1.5;
}

.method-label {
  margin: 0;
  font-size: 13px;
  color: var(--ink-mute);
  text-align: center;
}
.share-link .method-label { text-align: left; }
.method-label strong {
  color: var(--ink-soft);
  font-weight: 700;
}

.share-card .form-actions.centered { margin-top: 28px; }
.share-card .share-bookmark-tip {
  text-align: center;
  font-size: 12px;
  margin: 12px 0 0;
}

/* Mobile: stack vertically, flip the divider horizontal */
@media (max-width: 560px) {
  .share-divider {
    flex-direction: row;
    padding: 4px 0;
    width: 100%;
  }
  .share-divider::before,
  .share-divider::after {
    height: 1px;
    width: auto;
    flex: 1 1 auto;
  }
  .qr-slot svg { width: 200px; height: 200px; }
  .share-link .method-label { text-align: center; }
}

/* ----- Link share block: input-group pattern (URL field + attached Copy
   button flush on the right). Tighter than a loose flex row with gap. --- */
.linkblock {
  display: flex;
  align-items: stretch;
  padding: 0;
  border: 1px solid var(--line);
  background: white;
  border-radius: var(--radius-sm);
  overflow: hidden;          /* clip children to rounded corners */
}
.linkblock code {
  flex: 1 1 auto;
  min-width: 0;              /* lets flex actually shrink so ellipsis kicks in */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
  color: var(--ink-soft);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  padding: 12px 14px;
  display: flex;
  align-items: center;
}
.linkblock button {
  flex-shrink: 0;
  margin: 0;
  padding: 0 20px;
  border: 0;
  border-left: 1px solid var(--line);
  border-radius: 0;
  background: var(--card-soft);
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}
.linkblock button:hover  { background: var(--tint); color: var(--accent); }
.linkblock button:active { background: var(--line); }
.linkblock button.copied { background: #e9f9ed; color: #2e7d32; }
/* Legacy external confirmation — kept for any page still using it, but
   new copy flow flashes the button text instead. */
.copy-status {
  font-size: 12px;
  color: var(--good);
  margin-left: 6px;
  opacity: 0;
  transition: opacity 120ms ease;
}
.copy-status.on { opacity: 1; }

/* ----- Progress ----- */
.progress {
  height: 10px;
  background: var(--line);
  border-radius: 999px;
  overflow: hidden;
  margin: 20px 0 6px;
}
.progress > div {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  border-radius: 999px;
  transition: width 240ms ease;
}
.section-meta {
  display: flex;
  justify-content: flex-end;
  font-size: 12px;
  color: var(--ink-mute);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 600;
  margin: 0 4px 14px;
}

/* ----- Question / intro enter animation ----------------------------------

   A small fade + upward slide on the prompt and choices whenever a new
   question is rendered. Pairs with the existing progress-bar animation
   so the UI feels coordinated rather than having the prompt "snap" in
   place while the bar alone glides.

   The card gets `.anim-in` added every time we (re-)render. The replay
   trick (remove → reflow → re-add) makes the animation fire each time
   even though the class name doesn't change.

   Respects `prefers-reduced-motion`.
*/
@keyframes q-fade-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.card.anim-in .prompt,
.card.anim-in .choices,
.card.anim-in .intro-emoji,
.card.anim-in .intro-name,
.card.anim-in .intro-subtitle,
.card.anim-in .intro-description,
.card.anim-in .intro-meta {
  animation: q-fade-in 240ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.card.anim-in .choices           { animation-delay: 40ms; }
.card.anim-in .intro-name        { animation-delay: 20ms; }
.card.anim-in .intro-subtitle    { animation-delay: 40ms; }
.card.anim-in .intro-description { animation-delay: 60ms; }
.card.anim-in .intro-meta        { animation-delay: 80ms; }

@media (prefers-reduced-motion: reduce) {
  .card.anim-in .prompt,
  .card.anim-in .choices,
  .card.anim-in .intro-emoji,
  .card.anim-in .intro-name,
  .card.anim-in .intro-subtitle,
  .card.anim-in .intro-description,
  .card.anim-in .intro-meta {
    animation: none;
  }
}

/* ----- Category intro card ----- */
.intro-card {
  padding: 40px 28px;
}
.intro-emoji {
  font-size: 72px;
  line-height: 1;
  margin-bottom: 10px;
}
.intro-name {
  font-size: 36px;
  margin: 0 0 6px;
  letter-spacing: -0.02em;
}
.intro-subtitle {
  font-size: 18px;
  color: var(--ink-soft);
  font-weight: 500;
  margin: 0 0 18px;
}
/* Needs `.intro-card` prefix (specificity 0,2,0) to beat the generic
   `.card p { margin: 0 0 12px }` rule that would otherwise reset our
   `auto` side-margins to 0 and leave the block left-aligned. */
.intro-card .intro-description {
  max-width: 640px;
  margin: 0 auto 10px;
  line-height: 1.55;
  text-align: center;
}
.intro-meta {
  font-size: 13px;
  color: var(--ink-mute);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 600;
  margin: 18px 0 0;
}

/* ----- Quiz ----- */
.quiz-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
}
.category-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: white;
  padding: 8px 12px;
  border-radius: 999px;
  box-shadow: var(--shadow-sm);
  font-weight: 600;
  font-size: 14px;
}
.category-chip .emoji { font-size: 18px; }
.qcount { font-size: 14px; color: var(--ink-mute); }

.prompt {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin: 24px 0 8px;
  text-align: center;
  /* Reserve space for ~3 lines of the prompt so short and long questions
     don't shift the position of the choice grid and nav buttons beneath.
     Rapid-clicking users would otherwise have to re-aim their thumb for
     every question with a different line count. */
  min-height: calc(1.3em * 3);
  /* Center the text vertically inside the reserved area so a one-line
     prompt doesn't sit at the top with dead space below it. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.prompt .hint { display: block; font-size: 14px; color: var(--ink-mute); font-weight: 400; margin-top: 8px; }

@media (max-width: 560px) {
  .prompt {
    font-size: 22px;
    /* Narrower line-width on mobile means prompts wrap to more lines.
       Reserve 4 lines here so the choice grid stays put even for the
       longest questions in the bank. */
    min-height: calc(1.3em * 4);
  }
}

.choices {
  display: grid;
  /* minmax(0, 1fr) — prevents wide content (the 40px emoji) from forcing
     the column wider than its allocated share. Without the explicit 0
     minimum, narrow screens (≤ ~360px) would overflow horizontally and
     the whole card would scroll-shift to the right. */
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 10px;
  margin: 28px 0 10px;
}
.choice {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 18px 6px 12px;
  background: white;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
  min-width: 0;                      /* allow shrink below content size */
  transition: transform 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
}
.choice .emj {
  font-size: 40px;
  line-height: 1;
  margin-bottom: 6px;
  transition: transform 160ms ease;
}
.choice .lbl { font-size: 12px; color: var(--ink-mute); font-weight: 600; text-transform: uppercase; letter-spacing: 0.02em; }

/* Narrow screens: shrink the emoji so 5 cells can fit comfortably within
   the card padding without any one cell demanding more than its 1fr share. */
@media (max-width: 560px) {
  .choices { gap: 6px; }
  .choice { padding: 14px 4px 10px; }
  .choice .emj { font-size: 32px; }
  .choice .lbl { font-size: 11px; letter-spacing: 0.01em; }
}
@media (max-width: 380px) {
  .choice .emj { font-size: 28px; }
  .choice .lbl { font-size: 10px; }
}
/* Hover lift + emoji scale are gated behind `hover: hover` so they only
   apply to devices with a real pointer (mouse / trackpad). On touch
   screens — especially iOS Safari — `:hover` state sticks to the last
   tapped element until another element gets focus, which made the
   next question render with the previous tap's lift + scale still
   visually "stuck" on the same screen position. Gating kills the bug
   and doesn't cost anything on touch since users already get tactile
   feedback from the auto-advance. */
@media (hover: hover) {
  .choice:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
  .choice:hover .emj { transform: scale(1.08); }
}
.choice.selected {
  border-color: var(--accent);
  background: var(--tint);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}
.choice.selected .lbl { color: var(--accent); }

.quiz-nav {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin-top: 16px;
}

/* On mobile the quiz is a thumb-driven interaction and the choice row
   sits right above the Prev/Skip buttons. Give both edges a bit more
   air so the status text beneath doesn't crowd the controls and
   accidental taps are less likely. */
@media (max-width: 560px) {
  .quiz-nav { margin-top: 28px; }
}

/* Needs `.card` prefix (specificity 0,2,0) to beat the generic
   `.card p { margin-block: 0 12px }` rule on line 304, which would
   otherwise zero out the margin-top via the margin-block shorthand. */
.card .quiz-status {
  text-align: center;
  color: var(--ink-mute);
  font-size: 14px;
  margin-top: 22px;
  margin-bottom: 0;
}
@media (max-width: 560px) {
  .card .quiz-status {
    margin-top: 28px;
    margin-bottom: 8px;
  }
}

/* ----- Waiting card (shown when one partner has finished and the other
   hasn't; used on /results and /s). Two avatars with a heartbeat between
   them, plus a visible poll-interval progress bar so the user can see
   the page is actively checking for updates. --- */
.waiting-card {
  text-align: center;
  padding: 40px 28px;
}
.waiting-title {
  font-size: 30px;
  margin: 0 0 4px;
  letter-spacing: -0.02em;
}
.waiting-duo {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 20px;
  margin: 24px 0 12px;
}
.waiting-partner {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 120px;
}
.waiting-partner .avatar {
  position: relative;
  width: 88px;
  height: 88px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 44px;
  line-height: 1;
  border-radius: 50%;
  background: var(--card-soft);
  border: 3px solid var(--line);
  margin-bottom: 10px;
  transition: background 240ms ease, border-color 240ms ease;
}
.waiting-partner .name {
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.waiting-partner .status {
  font-size: 11px;
  color: var(--ink-mute);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-weight: 600;
  margin-top: 3px;
}

/* Done: green ring + corner checkmark badge. */
.waiting-partner.done .avatar {
  border-color: #81c784;
  background: #eafaee;
}
.waiting-partner.done .avatar::after {
  content: '✓';
  position: absolute;
  bottom: -4px;
  right: -4px;
  width: 28px;
  height: 28px;
  background: #2e7d32;
  color: #fff;
  border-radius: 50%;
  font-size: 14px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 3px solid #fff;
}
.waiting-partner.done .status { color: #2e7d32; }

/* Pending: pink ring + subtle expanding halo. */
.waiting-partner.pending .avatar {
  border-color: var(--accent);
  animation: waiting-ring 1.8s ease-out infinite;
}
@keyframes waiting-ring {
  0%   { box-shadow: 0 0 0 0   color-mix(in srgb, var(--accent) 45%, transparent); }
  100% { box-shadow: 0 0 0 22px color-mix(in srgb, var(--accent) 0%, transparent);   }
}
.waiting-partner.pending .status { color: var(--accent); }

/* Heartbeat between the two avatars. Aligned to the avatar centers via
   margin-top so it sits at eye level with them (not the names below). */
.waiting-heart {
  font-size: 30px;
  line-height: 1;
  margin-top: 30px;
  animation: heartbeat 1.4s ease-in-out infinite;
}
@keyframes heartbeat {
  0%, 100% { transform: scale(1); }
  14%      { transform: scale(1.22); }
  28%      { transform: scale(1); }
  42%      { transform: scale(1.22); }
  70%      { transform: scale(1); }
}

/* Per-partner mini progress bar under each avatar. */
.waiting-partner .mini-progress {
  margin-top: 10px;
  width: 120px;
}
.waiting-partner .mini-progress .bar {
  height: 5px;
  background: var(--line);
  border-radius: 999px;
  overflow: hidden;
}
.waiting-partner .mini-progress .bar > div {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  border-radius: 999px;
  transition: width 400ms ease;
}
.waiting-partner.done .mini-progress .bar > div {
  background: #81c784;
}
.waiting-partner .mini-progress .count {
  margin-top: 4px;
  font-size: 11px;
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
}

.waiting-msg {
  margin: 4px auto 22px;
  max-width: 460px;
  font-size: 15px;
}

/* Poll-tick indicator. Pulse dot + label + slim 5s filling bar. */
.waiting-check {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
}
.waiting-check-label {
  font-size: 11px;
  color: var(--ink-mute);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
}
.waiting-progress {
  width: 220px;
  height: 3px;
  margin: 0;
  background: var(--line);
}
.waiting-progress > div {
  width: 0%;
  animation: waiting-tick 5s linear infinite;
}
@keyframes waiting-tick {
  0%   { width: 0%;   opacity: 1; }
  92%  { width: 96%;  opacity: 1; }
  100% { width: 100%; opacity: 0.5; }
}

@media (prefers-reduced-motion: reduce) {
  .waiting-partner.pending .avatar,
  .waiting-heart,
  .waiting-progress > div {
    animation: none !important;
  }
}

@media (max-width: 560px) {
  .waiting-duo { gap: 10px; }
  .waiting-partner { min-width: 90px; }
  .waiting-partner .avatar { width: 72px; height: 72px; font-size: 36px; }
  .waiting-heart { font-size: 26px; margin-top: 22px; }
  .waiting-partner .mini-progress { width: 90px; }
}

/* Partner-link recovery affordance on the results waiting screen.
   Subtle by default (collapsed <summary>), reveals the same QR + link
   block as /share/{token} when opened. */
.partner-share-recovery {
  margin: 28px auto 0;
  max-width: 560px;
  text-align: left;
  border-top: 1px solid var(--line);
}
.partner-share-recovery > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 18px 4px;
  font-size: 15px;
  color: var(--ink-soft);
  text-align: center;
}
.partner-share-recovery > summary::-webkit-details-marker,
.partner-share-recovery > summary::marker { display: none; }
.partner-share-recovery > summary .recover-cta {
  color: var(--accent);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.partner-share-recovery > summary:hover .recover-cta,
.partner-share-recovery > summary:focus-visible .recover-cta {
  text-decoration: none;
}
.partner-share-recovery[open] > summary { color: var(--ink-soft); }
.partner-share-body {
  padding: 8px 0 4px;
}
.partner-share-body .share-methods { margin: 0; }

/* ----- Results ----- */
.score-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-top: 6px;
}
@media (max-width: 720px) { .score-cards { grid-template-columns: 1fr; } }
.score-card {
  padding: 22px;
  background: white;
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.score-card h3 {
  margin: 0 0 8px;
  font-size: 16px;
  color: var(--ink-soft);
}
.score-card .big-number {
  font-size: 44px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
}
.score-card .sub {
  color: var(--ink-mute);
  font-size: 14px;
  margin-top: 6px;
}

/* Celebratory readout for the matched-desires count on the compatibility
   card. Deliberately NOT rendered as a stat-row + bar (which would imply
   "X out of Y" — the quiz is intentionally vast and not matching on every
   item is the norm). The pill-ish background with an accent-colored
   number gives the count visual weight without a progress framing. */
.shared-desires-callout {
  display: flex;
  align-items: baseline;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 16px;
  padding: 12px 16px;
  background: var(--card-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  text-align: center;
  font-size: 15px;
  color: var(--ink-soft);
  line-height: 1.3;
}
.shared-desires-callout .emj { font-size: 18px; }
.shared-desires-callout .count {
  font-size: 24px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: -0.01em;
}

.adv-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 10px;
}
.adv-name { font-weight: 600; }
.adv-value { font-weight: 700; font-size: 20px; letter-spacing: -0.01em; }

.bar {
  height: 8px;
  background: var(--line);
  border-radius: 999px;
  overflow: hidden;
  margin-top: 6px;
}
.bar > div {
  height: 100%;
  background: linear-gradient(90deg, var(--accent-soft), var(--accent));
  border-radius: 999px;
}

/* Each category is a native <details>. We treat the whole section like
   a mini-card: the <summary> is a rounded, tappable header that hints
   at its affordance via background, hover, and a rotating chevron, and
   the body indents under it with a connecting left rail so the
   collapsed/expanded relationship stays visually clear. */
.category-section {
  margin-top: 16px;
  border-radius: var(--radius-sm);
  background: var(--card-soft);
  border: 1px solid var(--line);
  overflow: hidden;
  transition: box-shadow 180ms ease, border-color 180ms ease;
}
.category-section[open] {
  border-color: color-mix(in srgb, var(--accent-2) 22%, transparent);
  box-shadow: 0 6px 20px -14px color-mix(in srgb, var(--accent-2) 35%, transparent);
}

.category-section > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
  outline: none;
  /* no border-radius on the summary itself — the parent <details>
     already clips; this means hover fills the whole header edge-to-edge */
}
.category-section > summary::-webkit-details-marker,
.category-section > summary::marker { display: none; }
.category-section > summary:hover {
  background: color-mix(in srgb, var(--accent) 5%, transparent);
}
.category-section > summary:focus-visible {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent-2) 40%, transparent);
}

.category-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  margin: 0;
  transition: background 160ms ease;
}
.category-header .emj {
  font-size: 26px;
  line-height: 1;
  flex-shrink: 0;
}
.category-header h2 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.category-header .count {
  color: var(--ink-soft);
  font-size: 12px;
  font-weight: 600;
  padding: 3px 10px;
  background: white;
  border: 1px solid var(--line);
  border-radius: 999px;
  white-space: nowrap;
}
.category-header .chev {
  margin-left: auto;
  color: var(--ink-mute);
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: white;
  border: 1px solid var(--line);
  transition: transform 220ms cubic-bezier(.2, .8, .2, 1),
              color 160ms ease,
              border-color 160ms ease,
              background 160ms ease;
  transform: rotate(-90deg);
  flex-shrink: 0;
}
.category-header .chev svg {
  display: block;
}
.category-section[open] .category-header .chev {
  transform: rotate(0deg);
  color: var(--accent-2);
  border-color: color-mix(in srgb, var(--accent-2) 35%, transparent);
  background: color-mix(in srgb, var(--accent-2) 6%, transparent);
}
.category-section > summary:hover .chev {
  color: var(--accent-2);
  border-color: color-mix(in srgb, var(--accent-2) 35%, transparent);
}
.category-body {
  padding: 4px 16px 14px 16px;
}

@media (max-width: 560px) {
  .category-header { padding: 12px 12px; gap: 10px; }
  .category-header h2 { font-size: 16px; }
  .category-header .emj { font-size: 22px; }
  .category-body { padding: 4px 10px 12px 10px; }
}

.match {
  padding: 14px 16px;
  background: white;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  margin-bottom: 10px;
}
.category-body .match:last-child { margin-bottom: 0; }
.match .q {
  font-size: 15px;
  color: var(--ink);
  line-height: 1.4;
}
.match .q .sep { color: var(--ink-mute); margin: 0 8px; }
.match .answers {
  display: flex;
  gap: 18px;
  margin-top: 8px;
  font-size: 14px;
  color: var(--ink-soft);
}
.match .answers span .emj { font-size: 18px; margin-left: 4px; vertical-align: middle; }

.empty-cat { color: var(--ink-mute); font-style: italic; padding: 6px 0; }

/* ----- Results "Rate us" card ----- */
/* Inline rating card on the results page. Same .card shell as everything
   else, with a stars + textarea + send affordance inside. Distinct from
   the header feedback chip — this one POSTs source=results_rating so
   admins can split the two intake channels. */
.rate-card {
  text-align: center;
}
.rate-card h2 { margin-bottom: 4px; }
.rate-card .muted { margin-bottom: 18px; }

.stars {
  display: inline-flex;
  gap: 4px;
  margin: 6px 0 16px;
  direction: ltr;
}
.stars .star {
  appearance: none;
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 36px;
  line-height: 1;
  padding: 4px 6px;
  color: var(--line);
  transition: color 140ms ease, transform 140ms ease;
  /* iOS Safari taps highlight the whole button in blue otherwise. */
  -webkit-tap-highlight-color: transparent;
}
.stars .star:hover,
.stars .star:focus-visible {
  transform: scale(1.12);
  outline: none;
}
/* Hover-fill: every star up to and including the hovered one lights up,
   so the click target gives clear feedback without committing. Uses
   :has() — supported in every evergreen browser. */
.stars:hover .star { color: var(--line); }
.stars .star:hover,
.stars .star:hover ~ .star { /* fallback — see :has() block below */ }
.stars:has(.star:hover) .star { color: var(--line); }
.stars:has(.star[data-value="1"]:hover) .star[data-value="1"],
.stars:has(.star[data-value="2"]:hover) .star[data-value="1"],
.stars:has(.star[data-value="2"]:hover) .star[data-value="2"],
.stars:has(.star[data-value="3"]:hover) .star[data-value="1"],
.stars:has(.star[data-value="3"]:hover) .star[data-value="2"],
.stars:has(.star[data-value="3"]:hover) .star[data-value="3"],
.stars:has(.star[data-value="4"]:hover) .star[data-value="1"],
.stars:has(.star[data-value="4"]:hover) .star[data-value="2"],
.stars:has(.star[data-value="4"]:hover) .star[data-value="3"],
.stars:has(.star[data-value="4"]:hover) .star[data-value="4"],
.stars:has(.star[data-value="5"]:hover) .star[data-value="1"],
.stars:has(.star[data-value="5"]:hover) .star[data-value="2"],
.stars:has(.star[data-value="5"]:hover) .star[data-value="3"],
.stars:has(.star[data-value="5"]:hover) .star[data-value="4"],
.stars:has(.star[data-value="5"]:hover) .star[data-value="5"] {
  color: #f5a623;
}
/* Selected state — sticky after a click, set via .selected by JS. */
.stars .star.selected { color: #f5a623; }

.rate-textarea {
  width: 100%;
  min-height: 90px;
  max-height: 240px;
  resize: vertical;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--field-bg);
  font: inherit;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
  outline: none;
  transition: border-color 140ms ease, box-shadow 140ms ease;
  box-sizing: border-box;
  text-align: left;
}
.rate-textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent);
}
.rate-textarea::placeholder { color: var(--ink-mute); }

.rate-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 12px;
}
.rate-count {
  font-size: 11px;
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
}
.rate-count.warn { color: var(--accent); }
.rate-send { min-width: 96px; }

.rate-status {
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 13px;
  text-align: left;
}
.rate-status.err { background: #ffebee; color: #8e0000; }

.rate-thanks {
  padding: 12px 0 4px;
}
.rate-thanks-emj {
  font-size: 44px;
  line-height: 1;
  margin-bottom: 10px;
}
.rate-thanks h2 { margin-bottom: 6px; }
.rate-thanks .muted { margin-bottom: 0; }

/* ----- FAQ (homepage) ----- */
.faq details {
  border-top: 1px solid var(--line);
  padding: 4px 0;
}
.faq details:last-of-type {
  border-bottom: 1px solid var(--line);
}
.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 14px 28px 14px 0;
  font-weight: 600;
  color: var(--ink);
  font-size: 16px;
  position: relative;
  user-select: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+';
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink-mute);
  transition: transform 180ms ease;
}
.faq details[open] > summary::after {
  content: '−';
  color: var(--accent);
}
.faq summary:hover { color: var(--accent); }
.faq details p, .faq details ul {
  color: var(--ink-soft);
  margin: 0 0 12px;
  line-height: 1.55;
  font-size: 15px;
}
.faq details ul { padding-left: 22px; }
.faq details > *:last-child { margin-bottom: 14px; }

/* ----- All-questions page ----- */
.questions-page .qnav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  padding: 14px 16px;
  background: var(--card-soft);
  border-radius: var(--radius-sm);
  margin: 18px 0 26px;
}
.questions-page .qnav a {
  font-size: 13px;
  color: var(--ink-soft);
  font-weight: 600;
  text-decoration: none;
  padding: 4px 10px;
  border-radius: 999px;
  background: white;
  border: 1px solid var(--line);
  transition: border-color 140ms ease, color 140ms ease;
}
.questions-page .qnav a:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.questions-page .qnav a span {
  color: var(--ink-mute);
  font-weight: 500;
}
/* The questions page piggy-backs on the shared .category-section
   styles (see the <details> block near the top of the file) for the
   card/summary/chevron look. These rules only cover the content
   unique to this page: the subtitle, description, question list,
   and the restriction pill. */
.qcat {
  /* Offset anchor-link targets from the top of the viewport so the
     opened summary isn't jammed against the browser chrome. */
  scroll-margin-top: 20px;
}
/* The /questions page wraps everything in .card.legal (same shell as
   /terms) so it inherits .card.legal h2 { margin-top: 28px; } — which
   pushes our category-header <h2> below the emoji/chip in the flex
   row. Bump specificity past .card.legal h2 (0,2,1) by chaining so
   this wins regardless of source order. */
.card.legal .qcat .category-header h2 {
  margin: 0;
  scroll-margin-top: 0;
}
.qcat .cat-subtitle {
  margin: 2px 0 4px;
  color: var(--ink-soft);
  font-size: 15px;
}
.qcat .cat-description {
  margin: 4px 0 14px;
}
.qcat .qlist {
  list-style: none;
  padding: 0;
  margin: 0;
  border-top: 1px solid var(--line);
}
.qcat .qlist li {
  padding: 10px 4px;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
  color: var(--ink);
  line-height: 1.5;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
}
.qcat .qlist li:last-child { border-bottom: none; }
.qcat .restriction {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  background: white;
  border: 1px solid var(--line);
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
}

/* Expand-all / collapse-all controls above the category stack. Kept
   visually light — they're a convenience for a power-user / Ctrl-F
   flow, not primary navigation. */
.qcat-controls {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin: 0 0 10px;
}
.qcat-toggle {
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-soft);
  background: white;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 12px;
  cursor: pointer;
  transition: border-color 140ms ease, color 140ms ease, background 140ms ease;
}
.qcat-toggle:hover {
  border-color: var(--accent-2);
  color: var(--accent-2);
  background: color-mix(in srgb, var(--accent-2) 4%, transparent);
}

/* ----- Legal / terms page ----- */
.card.legal h1 { font-size: 28px; margin: 0 0 16px; }
.card.legal h2 { font-size: 20px; margin-top: 28px; scroll-margin-top: 20px; }
.card.legal h3 { font-size: 15px; margin: 18px 0 6px; color: var(--ink-soft); }
.card.legal p, .card.legal li {
  line-height: 1.6;
  font-size: 15px;
  color: var(--ink-soft);
}
.card.legal ul { padding-left: 22px; margin: 0 0 12px; }
.card.legal li { margin-bottom: 4px; }
.card.legal hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 28px 0 14px;
}
.legal-toc {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  font-size: 13px;
  padding: 10px 0;
  border-top: 1px dashed var(--line);
  border-bottom: 1px dashed var(--line);
  margin: 14px 0 10px;
}

/* ----- "Session gone" card (404-ish state for expired / deleted
   session tokens). Shown in place of the normal page content when
   GET /api/sessions/by-token/:t or /api/questions?token=:t 404s —
   keeps the user from seeing a half-loaded skeleton with just an
   error chip underneath. ----- */
.not-found-card {
  text-align: center;
  padding: 44px 28px 32px;
  max-width: 560px;
  margin: 40px auto 0;
}
.not-found-card .not-found-icon {
  font-size: 56px;
  line-height: 1;
  margin-bottom: 14px;
  opacity: 0.9;
}
.not-found-card h1 {
  margin: 0 0 10px;
  font-size: 24px;
  letter-spacing: -0.01em;
}
.not-found-card > p {
  color: var(--ink-soft);
  margin: 0 0 22px;
  line-height: 1.5;
  max-width: 44ch;
  margin-left: auto;
  margin-right: auto;
  margin-bottom: 22px;
}
.not-found-card .not-found-home {
  font-size: 13px;
  color: var(--ink-mute);
  margin-top: 18px;
  margin-bottom: 0;
}

/* ----- Misc ----- */
footer.site {
  text-align: center;
  color: var(--ink-soft);
  font-size: 13px;
  padding: 28px 20px 40px;
}

/* Rounded translucent card that wraps the footer copy + the "crafted"
   tagline. Inline-block so it naturally sizes to its content and stays
   centered on narrow screens; subtle white-ish fill + backdrop blur sits
   nicely over the lavender page background and keeps the text readable. */
footer.site .footer-card {
  display: inline-block;
  max-width: 100%;
  padding: 16px 22px;
  background: rgba(255, 255, 255, 0.65);
  border: 1px solid rgba(0, 0, 0, 0.05);
  border-radius: 16px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 2px 14px color-mix(in srgb, var(--scrim-ink) 5%, transparent);
  line-height: 1.55;
}

/* Secondary link row under the main footer sentence (home/start pages).
   Tighter gap above than the crafted line so the visual rhythm reads as
   "main text → its own links → tagline". */
footer.site .footer-links {
  margin-top: 8px;
  font-size: 13px;
}

/* Copyright line. Sits BELOW the rounded footer card as a tiny, muted
   signature — the card is the "page footer", this is the legal stamp. */
footer.site .footer-copyright {
  margin-top: 14px;
  font-size: 11px;
  color: var(--ink-mute);
  opacity: 0.75;
  letter-spacing: 0.02em;
}

/* "Crafted with ❤ in NYC" — tasteful, tiny, gradient on the city,
   heart beats. Shown as a separate block line under each page's contextual
   footer text. */
footer.site .crafted {
  margin-top: 24px;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 6px;
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-mute);
  opacity: 0.95;
}
footer.site .crafted .heart {
  display: inline-block;
  font-size: 12px;
  line-height: 1;
  transform-origin: center;
  animation: heartbeat 1.6s ease-in-out infinite;
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--accent) 45%, transparent));
}
footer.site .crafted .city {
  background: linear-gradient(90deg, var(--accent-2) 0%, var(--accent) 100%);
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  font-weight: 700;
  letter-spacing: 0.14em;
}
@keyframes heartbeat {
  0%, 60%, 100% { transform: scale(1);    }
  15%           { transform: scale(1.25); }
  30%           { transform: scale(1);    }
  45%           { transform: scale(1.18); }
}
@media (prefers-reduced-motion: reduce) {
  footer.site .crafted .heart { animation: none; }
}
.pulse {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  margin-right: 6px;
  vertical-align: middle;
  animation: pulse 1.2s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { transform: scale(1);   opacity: 1; }
  50%      { transform: scale(1.6); opacity: 0.4; }
}

.notice {
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: #fff8e1;
  border: 1px solid #fde8a7;
  color: #6a4f00;
  font-size: 14px;
  margin-bottom: 12px;
}
.notice.error { background: #ffebee; border-color: #ffcdd2; color: #8e0000; }

.topline {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 16px;
}
.topline .back { color: var(--ink-soft); font-size: 14px; }
.topline .back:hover { color: var(--accent); }

.checklist {
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: var(--ink-soft);
  font-size: 14px;
  margin: 10px 0;
}
.checklist .chk { margin-right: 8px; }

/* Utility: elements that only render on paper. Kept outside @media
   print so the off-screen hiding is always in effect. */
.print-only { display: none; }

/* ============================================================
   Print styles — the results page is the primary target here.
   Goal: a calm, document-style printout with everything visible,
   no interactive affordances, and match rows that don't break
   across pages. All of this is scoped to @media print so the
   live site stays rich.
   ============================================================ */
@media print {
  /* Reset the gradient background so we don't burn a wall of pink ink. */
  html, body {
    background: #fff !important;
    color: #111 !important;
  }

  /* Hide chrome / navigation / interactive widgets that don't belong
     on paper. results.js's beforeprint handler also forces every
     <details> open so the category bodies render. */
  header.site,
  footer.site,
  .chip-btn,
  .feedbackBtn,
  .fb-backdrop,
  .fb-card,
  .waiting-check,
  #waiting,
  .btn,
  .not-found-card .not-found-actions {
    display: none !important;
  }

  /* Drop the bottom "Print or save as PDF" CTA card entirely — it's
     redundant inside the printout itself. Also drop the rate-us card
     (interactive only, no print value). */
  #report > .card:last-child,
  #report > .rate-card { display: none !important; }

  main.container-wide {
    max-width: 100%;
    padding: 0;
    margin: 0;
  }

  /* Cards become plain sections — no background, no shadow, no border,
     just vertical spacing. */
  .card {
    background: transparent !important;
    box-shadow: none !important;
    border: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    margin: 0 0 18px 0 !important;
  }

  h1, h2, h3 { color: #111 !important; }
  .muted, .sub { color: #444 !important; }

  /* Top score cards: keep them as tidy outlined boxes (printer-safe
     whether or not the browser renders page backgrounds) with real
     breathing room inside. Stacked vertically so each gets full width
     on paper — scanning numbers is easier in one column. */
  .score-cards {
    display: block !important;
  }
  .score-card {
    background: transparent !important;
    box-shadow: none !important;
    border: 1px solid #ccc !important;
    border-radius: 6px !important;
    padding: 14px 18px !important;
    margin: 0 0 12px 0 !important;
    break-inside: avoid;
  }
  .score-card h3 {
    margin: 0 0 6px 0 !important;
    font-size: 13px !important;
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .big-number { font-size: 32px !important; }
  /* Adventurousness bars become simple rules so the printout doesn't
     need color to be legible. */
  .score-card .bar {
    background: #eee !important;
    height: 6px !important;
  }
  .score-card .bar > div {
    background: #888 !important;
  }

  /* Drop the pink card-soft background and border on print so the
     callout reads as a centered text line, not a nested box. The
     accent-colored count stays as text emphasis. */
  .shared-desires-callout {
    background: transparent !important;
    border: 0 !important;
    padding: 6px 0 !important;
  }
  .shared-desires-callout .count {
    color: #111 !important;
  }

  /* Category sections: strip the "expandable card" visual language
     entirely — on paper it's just a heading followed by matches. */
  .category-section,
  .category-section[open] {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    margin: 18px 0 0 0 !important;
    break-inside: auto;
  }
  .category-section > summary { padding: 0 !important; }
  .category-header {
    padding: 0 0 6px 0 !important;
    margin: 0 !important;
    border-bottom: 1px solid #ccc !important;
    gap: 8px !important;
  }
  .category-header h2 {
    font-size: 15px !important;
    font-weight: 700 !important;
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .category-header .emj { font-size: 18px !important; }
  /* The match-count chip is redundant when every match is printed
     right below — hide the chip to keep the heading quiet. */
  .category-header .count,
  .category-header .chev {
    display: none !important;
  }

  .category-body {
    padding: 6px 0 0 0 !important;
  }

  /* Match rows: simple bordered-less lines, bias toward NOT breaking
     a single match across a page break. */
  .match {
    background: transparent !important;
    box-shadow: none !important;
    border: none !important;
    border-radius: 0 !important;
    padding: 6px 0 !important;
    margin: 0 !important;
    border-bottom: 1px dotted #ddd !important;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .category-body .match:last-child {
    border-bottom: none !important;
  }
  .match .q { font-size: 12.5px !important; }
  .match .q .sep { color: #666 !important; }
  .match .answers {
    font-size: 11.5px !important;
    color: #333 !important;
    gap: 14px !important;
  }
  .match .answers .emj { font-size: 13px !important; }

  .empty-cat { color: #666 !important; }

  /* Flip on the print-only helpers. */
  .print-only { display: block !important; }

  /* Branded header at the top of the printout. Sits above the report
     cards so the first thing the reader/printer sees is where this
     paper came from. The accent bar under the brand mirrors the site's
     gradient in a subtle, ink-friendly tint. */
  .print-header {
    margin: 0 0 18px 0;
    padding: 0 0 10px 0;
    border-bottom: 2px solid #111;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
  }
  .print-brand {
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: #111;
  }
  .print-brand .dot {
    color: #c2185b;
  }
  .print-meta {
    font-size: 11px;
    color: #555;
    letter-spacing: 0.02em;
  }
  .print-meta .sep { margin: 0 6px; color: #999; }

  .print-footer {
    margin-top: 22px;
    padding-top: 10px;
    border-top: 1px solid #ccc;
    text-align: center;
    font-size: 11px;
    color: #555;
  }
  .print-footer strong {
    color: #111;
    font-weight: 700;
  }

  /* Set comfortable margins; browsers will honor these for @page. */
  @page { margin: 0.6in; }
}
