/* v108 — Switzer is self-hosted. The Fontshare API returned
   "Access to the Fontshare API has been temporarily restricted." on 1 Sep 2026,
   which silently dropped the body typeface to the device default (Roboto on
   Android) and changed every line break on the page. The four weights now ship
   with the site, so the body font no longer depends on a third party. */
@font-face{font-family:'Switzer';src:url('../assets/fonts/switzer-300.woff2') format('woff2');font-weight:300;font-style:normal;font-display:swap}
@font-face{font-family:'Switzer';src:url('../assets/fonts/switzer-400.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Switzer';src:url('../assets/fonts/switzer-500.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'Switzer';src:url('../assets/fonts/switzer-600.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
/* ============ Rio Now — member app design system =============
   Tokens are copied from the approved marketing site (rio-now/style.css)
   so the member side reads as the same product. Do not diverge these.
   ============================================================ */
:root {
  --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
  --text-sm: clamp(0.875rem, 0.8rem + 0.35vw, 1rem);
  --text-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  --text-lg: clamp(1.125rem, 1rem + 0.75vw, 1.5rem);
  --text-xl: clamp(1.5rem, 1.2rem + 1.25vw, 2.25rem);
  --text-2xl: clamp(2.1rem, 1.2rem + 2.5vw, 3.5rem);

  --space-1: .25rem; --space-2: .5rem; --space-3: .75rem; --space-4: 1rem;
  --space-5: 1.25rem; --space-6: 1.5rem; --space-7: 1.75rem; --space-8: 2rem; --space-10: 2.5rem;
  --space-12: 3rem; --space-16: 4rem; --space-20: 5rem;

  --radius-sm: .375rem; --radius-md: .625rem; --radius-lg: 1rem; --radius-full: 9999px;
  --transition-interactive: 200ms cubic-bezier(.16,1,.3,1);
  --card: 26rem;

  --font-display: 'Instrument Serif', Georgia, serif;
  --font-body: 'Switzer', 'Inter', system-ui, sans-serif;

  --color-bg: #080a14;
  --color-surface: #0d1020;
  --color-surface-2: #141829;
  --color-border: #272c42;
  --color-border-soft: #1a1e2e;
  --color-text: #f7efe3;
  --color-text-muted: #a7a397;
  --color-text-faint: #74716a;
  --color-accent: #c8452f;
  --color-accent-soft: #f0a173;
  --color-coral: #d9663f;
  --color-on-accent: #fff3ea;
  --glow: rgba(200,69,47,.26);
  --grain-opacity: .055;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
body {
  min-height: 100dvh; line-height: 1.6;
  font-family: var(--font-body); font-weight: 400;
  background: var(--color-bg); color: var(--color-text);
  font-size: var(--text-base);
}
img, svg { display: block; max-width: 100%; }
input, button { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }

.grain {
  position: fixed; inset: -50%; z-index: 60; pointer-events: none;
  opacity: var(--grain-opacity); mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ============ app chrome ============ */
.app-topbar {
  position: relative; z-index: 3;
  padding: var(--space-5) var(--space-5) 0;
}
.topbar-inner {
  width: 100%; max-width: var(--card); margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3);
}
.app-back {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border-soft);
  color: var(--color-text-muted);
  transition: color var(--transition-interactive), border-color var(--transition-interactive);
}
.app-back:hover { color: var(--color-text); border-color: var(--color-border); }
.app-back svg { width: 16px; height: 16px; }

.brand-lockup { display: flex; align-items: center; gap: .5rem; color: var(--color-text); }
.brand-mark { width: 22px; height: 22px; color: var(--color-accent); flex: none; }
.brand-word { font-family: var(--font-display); font-size: 1.28rem; letter-spacing: .005em; line-height: 1; }
.brand-word-thin { font-style: italic; color: var(--color-accent-soft); margin-left: .18em; }

.lang-switch {
  display: flex; align-items: center; gap: .1rem;
  border: 1px solid rgba(247,239,227,.22); border-radius: var(--radius-full);
  background: rgba(8,10,20,.42);
  padding: 2px;
}
.lang-switch button {
  font-size: .72rem; font-weight: 500; letter-spacing: .1em;
  padding: .3rem .52rem; border-radius: var(--radius-full);
  color: rgba(255,255,255,.9);
  transition: color var(--transition-interactive), background var(--transition-interactive);
}
.lang-switch button.active { color: var(--color-on-accent); background: rgba(200,69,47,.9); }
.lang-switch button:hover:not(.active) { color: #fff8ee; }

/* ============ auth screens ============ */
.auth-screen {
  position: relative; min-height: 100dvh;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.auth-sky { position: absolute; inset: 0 0 auto; height: 46dvh; z-index: 0; }
.auth-sky img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 42%;
  /* Identical treatment to .hero-media img on the marketing site, so the same
     photograph reads the same everywhere. Do not tune these per screen. */
  filter: brightness(1.02) saturate(1.06) contrast(1.02); }
.auth-sky::after {
  content: ''; position: absolute; inset: 0;
  background:
    linear-gradient(to bottom, rgba(8,10,20,.30) 0%, rgba(8,10,20,.34) 46%, rgba(8,10,20,.9) 84%, var(--color-bg) 100%);
}

.auth-body {
  position: relative; z-index: 2;
  flex: 1; display: flex; flex-direction: column;
  padding: var(--space-8) var(--space-5) var(--space-6);
}
.auth-card { width: 100%; max-width: var(--card); margin: 0 auto; }

.eyebrow {
  font-size: .68rem; font-weight: 500; letter-spacing: .17em; text-transform: uppercase;
  color: var(--color-accent-soft);
}
.auth-card h1 {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(2rem, 1.4rem + 3.2vw, 2.9rem); line-height: 1.02;
  letter-spacing: -.01em; margin-top: var(--space-3);
}
.auth-card h1 em { font-style: italic; color: var(--color-accent-soft); }
.auth-sub {
  margin-top: var(--space-3); max-width: 24ch;
  font-size: var(--text-sm); color: #ffffff;
}

.field-label {
  margin-top: var(--space-8);
  font-size: .7rem; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: #ffffff;
}

.phone-field {
  margin-top: var(--space-3);
  display: flex; align-items: center; gap: var(--space-3);
  background: rgba(20,24,41,.72); border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0 var(--space-4);
  transition: border-color var(--transition-interactive), box-shadow var(--transition-interactive);
}
.phone-field:focus-within { border-color: rgba(200,69,47,.75); box-shadow: 0 0 0 3px rgba(200,69,47,.13); }
.phone-field .flag { font-size: 1.05rem; line-height: 1; }
.phone-field .divider { width: 1px; height: 22px; background: var(--color-border); }
/* The flag is a real control now, not decoration. It needs to look pressable
   without competing with the coral primary button below it. */
.phone-field .country-btn {
  display: flex; align-items: center; gap: .4rem;
  margin-left: calc(var(--space-4) * -1); padding: .95rem var(--space-3) .95rem var(--space-4);
  background: none; border: 0; cursor: pointer; color: var(--color-text);
  font-size: 1.02rem; line-height: 1; border-radius: var(--radius-md) 0 0 var(--radius-md);
  transition: background var(--transition-interactive);
}
.phone-field .country-btn:hover { background: rgba(255,255,255,.05); }
.phone-field .country-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.phone-field .country-btn .dial { letter-spacing: .02em; font-variant-numeric: tabular-nums; }
.phone-field .country-btn .caret { font-size: .62rem; color: rgba(247,239,227,.75); transform: translateY(1px); }

/* ---- country picker ---- */
.country-sheet .sheet-body { max-height: 82vh; display: flex; flex-direction: column; }
.country-search { margin-bottom: var(--space-4); flex: 0 0 auto; }
.country-list { overflow-y: auto; -webkit-overflow-scrolling: touch; margin: 0 calc(var(--space-5) * -1); padding: 0 var(--space-5); }
.country-row {
  width: 100%; display: flex; align-items: center; gap: var(--space-4);
  padding: .8rem 0; background: none; border: 0; cursor: pointer; text-align: left;
  border-bottom: 1px solid var(--color-border-soft); color: var(--color-text);
}
.country-row:last-child { border-bottom: 0; }
.country-row:hover { background: rgba(255,255,255,.04); }
.country-row:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.country-row[hidden] { display: none; }
.country-row .flag { font-size: 1.25rem; line-height: 1; flex: 0 0 auto; }
.country-row .cname { flex: 1; font-size: .95rem; }
.country-row .cdial { font-size: .9rem; color: rgba(247,239,227,.75); font-variant-numeric: tabular-nums; }
/* The current choice is marked with the accent, not with a tick that could be
   mistaken for a checkbox the member has to tap twice. */
.country-row.is-current .cname { color: var(--color-accent-soft); }
.country-row.is-current .cdial { color: var(--color-accent-soft); }
.country-empty { font-size: .88rem; color: rgba(247,239,227,.8); padding: var(--space-5) 0 0; }
.phone-field input {
  flex: 1; background: none; border: 0; outline: none;
  padding: .95rem 0; font-size: 1.02rem; letter-spacing: .02em;
}
.phone-field input::placeholder { color: rgba(247,239,227,.6); letter-spacing: .04em; }

.delivery-stack { margin-top: var(--space-3); display: grid; gap: var(--space-3); }
.delivery-card {
  display: flex; align-items: center; gap: var(--space-4);
  text-align: left; width: 100%;
  padding: var(--space-4);
  background: rgba(13,16,32,.66);
  border: 1px solid var(--color-border-soft); border-radius: var(--radius-md);
  transition: border-color var(--transition-interactive), background var(--transition-interactive);
}
.delivery-card:hover { border-color: var(--color-border); }
.delivery-card[aria-pressed='true'] {
  border-color: rgba(200,69,47,.7); background: rgba(200,69,47,.09);
}
.delivery-icon { width: 34px; height: 34px; flex: none; display: grid; place-items: center; border-radius: var(--radius-full); }
.delivery-icon svg { width: 18px; height: 18px; }
.delivery-icon.wa { background: rgba(37,211,102,.14); color: #5fd58e; }
.delivery-icon.sms { background: rgba(240,161,115,.13); color: var(--color-accent-soft); }
.delivery-text { flex: 1; min-width: 0; }
.delivery-text strong { display: block; font-weight: 500; font-size: var(--text-sm); }
.delivery-text small { display: block; font-size: .74rem; color: rgba(255,255,255,.92); }
.delivery-check { flex: none; width: 18px; height: 18px; color: var(--color-accent-soft); opacity: 0; transition: opacity var(--transition-interactive); }
.delivery-card[aria-pressed='true'] .delivery-check { opacity: 1; }

.auth-foot { margin-top: auto; padding-top: var(--space-8); }
.coral-btn {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: .5rem;
  padding: 1rem var(--space-6); border-radius: var(--radius-full);
  background: var(--color-accent); color: var(--color-on-accent);
  font-size: var(--text-sm); font-weight: 500; letter-spacing: .01em;
  box-shadow: 0 10px 30px -12px var(--glow);
  transition: transform var(--transition-interactive), background var(--transition-interactive);
}
.coral-btn:hover { background: #d24d35; transform: translateY(-1px); }
.coral-btn:disabled { opacity: .6; transform: none; cursor: default; }
.tiny-copy {
  margin-top: var(--space-4); text-align: center;
  font-size: .76rem; color: rgba(255,255,255,.9);
}
.tiny-copy a { color: var(--color-text-muted); }

@media (min-width: 48rem) {
  .auth-sky { height: 100dvh; }
  .auth-sky img { object-position: 50% 46%; }
  .auth-sky::after {
    background:
      linear-gradient(to right, rgba(6,7,14,.94) 0%, rgba(6,7,14,.84) 34%, rgba(6,7,14,.26) 62%, rgba(6,7,14,0) 100%),
      linear-gradient(to bottom, rgba(8,10,20,.2) 0%, rgba(8,10,20,0) 40%, rgba(8,10,20,.44) 100%);
  }
  .app-topbar { padding: var(--space-5) var(--space-5) 0 var(--space-16); }
  .topbar-inner { max-width: none; }
  .auth-body { justify-content: center; padding: var(--space-12) var(--space-16); }
  .auth-card { margin: 0; max-width: 25rem; }
  .auth-foot { margin-top: var(--space-10); padding-top: 0; }
}

/* ---- Screen 2 — OTP boxes ---- */
.otp-wrap { position: relative; }
.otp-hidden {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; border: 0; background: none; font-size: 16px;
  letter-spacing: 2em; color: transparent; caret-color: transparent;
  z-index: 2; cursor: pointer;
}
.otp-boxes { display: grid; grid-template-columns: repeat(6, 1fr); gap: .5rem; }
.otp-boxes span {
  height: 3.5rem; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 1.6rem; line-height: 1;
  color: var(--color-text);
  background: rgba(13,16,32,.72);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  transition: border-color .18s ease, background .18s ease, transform .18s ease;
}
.otp-boxes span.filled { border-color: rgba(240,161,115,.5); background: rgba(20,24,41,.86); }
.otp-boxes span.active {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(200,69,47,.16);
}
.otp-boxes span.active::after {
  content: ''; width: 1px; height: 1.5rem;
  background: var(--color-accent-soft);
  animation: caret 1.05s steps(1) infinite;
}
@keyframes caret { 0%,49% { opacity: 1 } 50%,100% { opacity: 0 } }

.sent-to { color: var(--color-accent-soft); white-space: nowrap; }

.resend-copy {
  margin: 1.1rem 0 0; font-size: .82rem; color: rgba(255,255,255,.9);
}
.resend-copy button {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--color-accent-soft);
  text-decoration: underline; text-underline-offset: 3px;
}
.resend-copy button:hover { color: var(--color-text); }

@media (min-width: 900px) {
  .otp-boxes { gap: .6rem; }
  .otp-boxes span { height: 3.9rem; font-size: 1.8rem; }
}

/* ---- Screen 3 — onboarding basics ---- */
.form-screen .auth-body { padding-bottom: var(--space-10); }
.auth-sky.sky-short { height: 28dvh; }
.auth-sky.sky-short::after {
  background:
    linear-gradient(to bottom, rgba(8,10,20,.30) 0%, rgba(8,10,20,.34) 46%, rgba(8,10,20,.9) 84%, var(--color-bg) 100%);
}

.step-dots { display: flex; align-items: center; gap: .38rem; margin: 0 0 1.1rem; }
.step-dots i {
  width: 1.35rem; height: 3px; border-radius: 2px;
  background: rgba(247,239,227,.22);
}
.step-dots i.on { background: var(--color-accent); }
.step-dots span {
  margin-left: .55rem; font-size: .68rem; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(255,255,255,.9);
}

.form-row { display: grid; gap: .75rem; margin-top: 1.4rem; }
.form-row.two { grid-template-columns: 1fr 5.5rem; align-items: end; }
.form-row .field-label { display: block; }

.choice-block { margin-top: 1.35rem; }
.choice-row { display: flex; flex-wrap: wrap; gap: .5rem; }
.choice {
  flex: 1 1 auto; min-height: 2.85rem; padding: 0 .95rem;
  font: 500 .88rem/1 var(--font-body); color: #ffffff;
  background: rgba(13,16,32,.72);
  border: 1px solid var(--color-border);
  border-radius: 999px; cursor: pointer; white-space: nowrap;
  transition: border-color .18s ease, background .18s ease, color .18s ease;
}
.choice:hover { border-color: rgba(240,161,115,.45); color: var(--color-text); }
.choice.active {
  background: rgba(200,69,47,.16);
  border-color: var(--color-accent);
  color: var(--color-text);
}
.choice.wide { flex: 1 1 45%; }

input.input {
  width: 100%; height: 3.25rem; padding: 0 .95rem;
  font: 400 1rem/1 var(--font-body); color: var(--color-text);
  background: rgba(13,16,32,.72);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  transition: border-color .18s ease, box-shadow .18s ease;
  -moz-appearance: textfield;
}
input.input::placeholder { color: rgba(247,239,227,.5); }
input.input:focus { outline: none; border-color: rgba(200,69,47,.75); box-shadow: 0 0 0 3px rgba(200,69,47,.13); }
input.input::-webkit-outer-spin-button,
input.input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---- Screen 3 — one step smaller across the board (scoped to .form-screen) ---- */
.form-screen .auth-card h1 { font-size: clamp(1.68rem, 1.2rem + 2.4vw, 2.35rem); }
.form-screen .auth-sub { font-size: .88rem; }
.form-screen .field-label { font-size: .64rem; }
.form-screen input.input { height: 2.75rem; font-size: .92rem; border-radius: 12px; }
.form-screen .choice { min-height: 2.4rem; padding: 0 .8rem; font-size: .8rem; }
.form-screen .choice-block { margin-top: 1.05rem; }
.form-screen .form-row { margin-top: 1.15rem; }
.form-screen .form-row.two { grid-template-columns: 1fr 4.75rem; }
.form-screen .coral-btn { padding: .78rem var(--space-5); font-size: .86rem; }
.form-screen .tiny-copy { font-size: .7rem; }
.form-screen .step-dots i { width: 1.15rem; height: 2px; }
.form-screen .step-dots span { font-size: .62rem; }

/* buttons one notch smaller again (screen 3) */
.form-screen .choice { min-height: 2.2rem; padding: 0 .72rem; font-size: .76rem; }
.form-screen .coral-btn { padding: .66rem var(--space-5); font-size: .82rem; }

/* ---- Screen 4 — choice cards (visitor timing, availability, and later steps) ---- */
.auth-sub.wide { max-width: 40ch; }
.choice-stack { display: grid; gap: .55rem; margin-top: 1.3rem; }
.choice-card {
  display: flex; align-items: center; justify-content: space-between; gap: .8rem;
  width: 100%; min-height: 3.4rem; padding: .7rem .95rem; text-align: left;
  background: rgba(13,16,32,.72);
  border: 1px solid var(--color-border);
  border-radius: 14px; cursor: pointer;
  transition: border-color .18s ease, background .18s ease;
}
.choice-card:hover { border-color: rgba(240,161,115,.45); }
.choice-card span { display: flex; flex-direction: column; gap: .18rem; }
.choice-card strong {
  font: 500 .92rem/1.1 var(--font-body); color: var(--color-text);
}
.choice-card small {
  font-size: .72rem; color: rgba(255,255,255,.9);
}
.choice-card b { opacity: 0; color: var(--color-accent-soft); font-size: .95rem; }
.choice-card.active {
  background: rgba(200,69,47,.14);
  border-color: var(--color-accent);
}
.choice-card.active b { opacity: 1; }

/* --- screen 5: availability — divider + standalone card --- */
.form-screen .stack-divider{
  display:flex; align-items:center; gap:.7rem;
  margin:.85rem 0;
  color:rgba(255,255,255,.72);
  font-size:.66rem; letter-spacing:.14em; text-transform:uppercase;
}
.form-screen .stack-divider::before,
.form-screen .stack-divider::after{
  content:""; flex:1; height:1px; background:var(--color-border);
}
.form-screen .choice-card.standalone{ border-style:dashed; }
.form-screen .choice-card.standalone.active{ border-style:solid; }

/* --- screen 6: details — units, language pills, optional tag --- */
.form-screen .field-label .optional{
  color:rgba(255,255,255,.8); letter-spacing:.04em; text-transform:none; font-size:.62rem;
}
.form-screen .form-row.two{
  display:grid; grid-template-columns:1fr 4.75rem; gap:.8rem; align-items:end;
}
.form-screen .input-with-units input.input{ width:100%; }
.form-screen .unit-pair{ display:flex; gap:.3rem; margin-top:.35rem; }
.form-screen .unit{
  flex:1; min-height:1.9rem; padding:0 .4rem;
  font-family:var(--font-body); font-size:.68rem; letter-spacing:.02em;
  color:rgba(255,255,255,.9);
  background:var(--color-surface); border:1px solid var(--color-border);
  border-radius:9px; cursor:pointer; transition:.16s ease;
}
.form-screen .unit:hover{ color:var(--color-text); border-color:rgba(240,161,115,.4); }
.form-screen .unit.active{
  color:var(--color-text); border-color:rgba(200,69,47,.85);
  background:linear-gradient(180deg, rgba(200,69,47,.22), rgba(200,69,47,.1));
}
.form-screen .field-block{ margin-top:.95rem; }
.form-screen .language-pills{
  display:flex; flex-wrap:wrap; gap:.4rem; margin-top:.4rem;
}
.form-screen .language-pills button{
  min-height:2.1rem; padding:0 .7rem;
  font-family:var(--font-body); font-size:.74rem;
  color:#ffffff;
  background:var(--color-surface); border:1px solid var(--color-border);
  border-radius:999px; cursor:pointer; transition:.16s ease;
}
.form-screen .language-pills button:hover{ color:var(--color-text); border-color:rgba(240,161,115,.45); }
.form-screen .language-pills button.active{
  color:var(--color-text); border-color:rgba(200,69,47,.9);
  background:linear-gradient(180deg, rgba(200,69,47,.26), rgba(200,69,47,.12));
}
.form-screen .language-pills button.active::after{ content:" ✓"; color:var(--color-accent-soft); }

/* --- screen 6 revision: full-width stacked fields (approved 29 Aug 2026) --- */
.form-screen .form-row.stacked{
  display:grid; grid-template-columns:1fr; gap:1.05rem;
}
.form-screen .form-row.stacked .unit-pair{ margin-top:.4rem; }
.form-screen .form-row.stacked .unit{ min-height:2.1rem; font-size:.72rem; }
.form-screen .field-block{ margin-top:1.15rem; }
.form-screen .form-row.stacked{ gap:.9rem; }
@media (max-width: 420px){ .form-screen .auth-body{ padding-bottom: .5rem; } }
@media (max-width: 420px){ .form-screen .choice-block{ margin-top: 1.15rem; } }
@media (max-width: 420px){
  .form-screen .auth-foot{ padding-top: var(--space-5); }
  .form-screen .choice-block{ margin-top: 1rem; }
}

/* --- screen 7: photos --- */
.photo-grid{
  display:grid; grid-template-columns:1fr 1fr; gap:.7rem; margin-top:1.15rem;
}
.photo-slot{
  position:relative; display:flex; align-items:center; justify-content:center;
  aspect-ratio: 1 / 1; overflow:hidden; cursor:pointer;
  border:1px dashed rgba(240,161,115,.4); border-radius:16px;
  background:rgba(13,16,32,.72);
  transition:border-color .18s ease, background .18s ease;
}
.photo-slot:hover{ border-color:var(--color-accent); background:rgba(200,69,47,.12); }
.photo-slot input[type="file"]{
  position:absolute; inset:0; width:100%; height:100%; opacity:0; cursor:pointer;
}
.photo-slot .slot-empty{
  display:flex; flex-direction:column; align-items:center; gap:.35rem;
  font:500 .78rem/1 var(--font-body); color:#fff; pointer-events:none;
}
.photo-slot .slot-empty b{
  font-size:1.15rem; font-weight:400; line-height:1;
  color:var(--color-accent-soft);
}
.photo-slot.filled{ border-style:solid; border-color:var(--color-border); }
.photo-slot img{ width:100%; height:100%; object-fit:cover; }
.photo-slot .remove{
  position:absolute; top:.4rem; right:.4rem; z-index:3;
  width:1.65rem; height:1.65rem; display:flex; align-items:center; justify-content:center;
  border:none; border-radius:999px; cursor:pointer;
  background:rgba(8,10,20,.78); color:#fff; font-size:1rem; line-height:1;
}
.photo-slot .remove:hover{ background:var(--color-accent); }
.photo-hint{
  margin:.85rem 0 0; font:400 .74rem/1.45 var(--font-body);
  color:rgba(255,255,255,.9);
}
.toast{
  position:fixed; left:50%; bottom:1.25rem; transform:translate(-50%, 1rem);
  max-width:20rem; padding:.65rem 1rem; border-radius:12px;
  background:rgba(20,24,41,.96); border:1px solid var(--color-border);
  color:#fff; font:500 .8rem/1.35 var(--font-body); text-align:center;
  opacity:0; pointer-events:none; transition:opacity .2s ease, transform .2s ease;
  z-index:50;
}
.toast.show{ opacity:1; transform:translate(-50%, 0); }

/* --- screen 8: about me --- */
.about-block{ position:relative; }
textarea.about-input{
  width:100%; min-height:8.5rem; resize:vertical;
  padding:.85rem .95rem; border-radius:14px;
  font:400 .92rem/1.5 var(--font-body); color:var(--color-text);
  background:rgba(13,16,32,.72); border:1px solid var(--color-border);
}
textarea.about-input:focus{ outline:none; border-color:var(--color-accent); }
.char-count{
  margin-top:.4rem; text-align:right;
  font:500 .7rem/1 var(--font-body); color:rgba(255,255,255,.9);
}
.text-btn{
  display:block; width:100%; margin-top:.7rem; padding:.5rem 0;
  background:none; border:none; cursor:pointer;
  font:500 .82rem/1 var(--font-body); color:#fff;
  text-decoration:underline; text-underline-offset:3px;
}
.text-btn:hover{ color:var(--color-accent-soft); }
.about-screen .auth-card{ display:flex; flex-direction:column; flex:1; }
.about-screen .about-block{ display:flex; flex-direction:column; flex:1; min-height:0; }
.about-screen textarea.about-input{ flex:1; resize:none; }
.about-screen textarea.about-input{ max-height:17rem; }
/* screen 8 revisions: visible box edge, buttons lifted off the bottom */
.about-screen textarea.about-input{
  border-color: rgba(255,255,255,.42);
  background: rgba(13,16,32,.82);
}
.about-screen textarea.about-input:focus{ border-color: var(--color-accent); }
.about-screen .about-block{ flex:0 0 auto; }
.about-screen .auth-foot{ margin-top: var(--space-6); }
.about-screen textarea.about-input{ height:17rem; min-height:17rem; }

/* ============================================================
   GLOBAL LEGIBILITY RULES (approved 29 Aug 2026)
   Standing instruction: nothing on any member screen should be
   hard to read. Applies to every screen via this stylesheet.
   ============================================================ */

/* 1. Dark wash behind the logo so the wordmark always sits on
      near-black, whatever the sky photo is doing underneath. */
.app-topbar::before{
  content:''; position:absolute; z-index:-1; pointer-events:none;
  top:-2rem; left:0; right:0; height:12rem;
  background:radial-gradient(115% 125% at 0% 0%,
    rgba(2,3,8,.95) 0%,
    rgba(2,3,8,.86) 26%,
    rgba(2,3,8,.45) 50%,
    rgba(2,3,8,.12) 68%,
    rgba(2,3,8,0) 80%);
}

/* 2. Placeholders readable, not ghosts. */
input.input::placeholder,
.phone-field input::placeholder,
textarea.about-input::placeholder{
  color:rgba(255,255,255,.72); letter-spacing:.02em;
}

/* 3. Every input and text box has a visible edge. */
input.input,
textarea.about-input,
.about-screen textarea.about-input{
  border:1px solid rgba(255,255,255,.6);
}
input.input:focus,
textarea.about-input:focus,
.about-screen textarea.about-input:focus{ border-color:var(--color-accent); }

/* 4. Empty photo slots: visible dashed edge and readable label. */
.photo-slot{ border-color:rgba(255,255,255,.55); }
.photo-slot .slot-empty{ color:#fff; }

/* ============================================================
   SCREEN 9 — browse grid (route /browse)
   ============================================================ */
.inside-shell{ min-height:100dvh; display:flex; flex-direction:column; background:var(--color-bg); }
.inside-shell.with-nav{ padding-bottom:5.4rem; }
.inside-shell.with-selection-bar{ padding-bottom:9.6rem; }
.inside-page{ width:100%; max-width:var(--card); margin:0 auto; padding:0 var(--space-5); }
@media (min-width:900px){ .inside-page{ max-width:none; padding-left:var(--space-16); padding-right:var(--space-16); } }

.browse-top{
  display:flex; align-items:center; justify-content:space-between; gap:var(--space-3);
  padding:var(--space-5) 0 var(--space-4);
}
.filter-button{
  display:inline-flex; align-items:center; gap:.4rem;
  padding:.5rem .9rem .5rem .75rem; border-radius:var(--radius-full);
  border:1px solid rgba(255,255,255,.55); color:#fff;
  font-size:.82rem; font-weight:500; letter-spacing:.02em;
  background:rgba(255,255,255,.05);
  transition:border-color var(--transition-interactive), background var(--transition-interactive);
}
.filter-button:hover{ border-color:#fff; background:rgba(255,255,255,.1); }
.filter-button svg{ width:17px; height:17px; }
.filter-button i{
  font-style:normal; min-width:1.15rem; height:1.15rem; border-radius:var(--radius-full);
  background:var(--color-accent); color:var(--color-on-accent);
  font-size:.7rem; font-weight:600; display:grid; place-items:center;
}

.browse-filter-row{ display:flex; gap:.5rem; padding-bottom:var(--space-4); }
.browse-filter-row button{
  flex:1; padding:.62rem .5rem; border-radius:var(--radius-full);
  border:1px solid rgba(255,255,255,.42); color:#fff;
  font-size:.84rem; font-weight:500; white-space:nowrap;
  transition:border-color var(--transition-interactive), background var(--transition-interactive);
}
.browse-filter-row button:hover{ border-color:#fff; }
.browse-filter-row button.active{
  background:var(--color-accent); border-color:var(--color-accent); color:var(--color-on-accent); font-weight:600;
}

.browse-grid{ display:grid; grid-template-columns:1fr 1fr; gap:.7rem; padding-bottom:var(--space-5); }
.profile-card{
  position:relative; aspect-ratio:3/4; overflow:hidden;
  border-radius:var(--radius-lg); border:1px solid rgba(255,255,255,.22);
  background:var(--color-surface-2); cursor:pointer;
  transition:border-color var(--transition-interactive), transform var(--transition-interactive);
}
.profile-card:hover{ transform:translateY(-2px); }
.profile-card.selected{ border-color:var(--color-accent); box-shadow:0 0 0 1px var(--color-accent) inset; }
.profile-card .real-photo{ width:100%; height:100%; object-fit:cover; display:block; }
.profile-card .demo-photo{
  width:100%; height:100%; display:grid; place-items:center;
  font-family:var(--font-display); font-size:3rem; color:var(--color-accent-soft);
}
.profile-card::after{
  content:''; position:absolute; inset:auto 0 0 0; height:38%;
  background:linear-gradient(180deg, rgba(4,5,10,0) 0%, rgba(4,5,10,.62) 46%, rgba(4,5,10,.95) 100%);
  pointer-events:none;
}
.profile-overlay{ position:absolute; inset:auto 0 0 0; z-index:2; padding:.5rem .6rem .55rem; }
.profile-overlay h3{
  font-family:var(--font-body); font-size:.98rem; font-weight:600; color:#fff;
  line-height:1.15; margin:0;
}
.profile-overlay p{ margin:.12rem 0 .28rem; font-size:.76rem; color:#fff; opacity:.88; }
.profile-overlay .avail{ display:inline-flex; align-items:center; gap:.34rem; font-size:.74rem; color:#fff; font-weight:500; }
.availability-dot{
  width:.42rem; height:.42rem; border-radius:var(--radius-full);
  background:var(--color-accent-soft); box-shadow:0 0 0 2px rgba(240,161,115,.22);
}
.profile-select{
  position:absolute; top:.5rem; right:.5rem; z-index:3;
  width:2.1rem; height:2.1rem; border-radius:var(--radius-full);
  display:grid; place-items:center;
  background:rgba(4,5,10,.55); border:1px solid rgba(255,255,255,.5); color:#fff;
  backdrop-filter:blur(4px);
  transition:background var(--transition-interactive), border-color var(--transition-interactive);
}
.profile-select svg{ width:17px; height:17px; }
.profile-select:hover{ border-color:#fff; }
.profile-select.on{ background:var(--color-accent); border-color:var(--color-accent); color:var(--color-on-accent); }
.profile-select.on svg path{ fill:currentColor; }

.multi-interest-bar{
  position:fixed; left:0; right:0; bottom:4.4rem; z-index:6;
  display:flex; align-items:center; justify-content:space-between; gap:var(--space-4);
  width:100%; max-width:var(--card); margin:0 auto;
  padding:.7rem var(--space-5);
  background:var(--color-surface-2); border-top:1px solid rgba(255,255,255,.16);
}
.multi-interest-bar .sel-count{ display:flex; flex-direction:column; gap:.1rem; }
.multi-interest-bar strong{ font-size:.86rem; color:#fff; font-weight:600; }
.multi-interest-bar .sel-count button{
  font-size:.76rem; color:#fff; text-decoration:underline; text-underline-offset:3px; text-align:left;
}
.multi-interest-bar .coral-btn{ width:auto; padding:.68rem 1.05rem; font-size:.82rem; }

.nav-bottom{
  position:fixed; left:0; right:0; bottom:0; z-index:7;
  display:grid; grid-template-columns:repeat(4,1fr);
  width:100%; max-width:var(--card); margin:0 auto;
  padding:.5rem var(--space-4) .62rem;
  background:rgba(8,10,20,.96); border-top:1px solid rgba(255,255,255,.14);
  backdrop-filter:blur(8px);
}
.nav-bottom button{
  display:flex; flex-direction:column; align-items:center; gap:.2rem;
  color:#fff; opacity:.62; font-size:.68rem; font-weight:500; letter-spacing:.02em;
  transition:opacity var(--transition-interactive), color var(--transition-interactive);
}
.nav-bottom button svg{ width:21px; height:21px; }
.nav-bottom button:hover{ opacity:1; }
.nav-bottom button.active{ opacity:1; color:var(--color-accent-soft); }

.empty-state{
  grid-column:1 / -1; text-align:center; padding:var(--space-10) var(--space-4); color:#fff;
}
.empty-state strong{ display:block; font-size:1rem; margin-bottom:.35rem; }
.empty-state p{ font-size:.86rem; opacity:.85; }
.multi-interest-bar[hidden]{ display:none; }
@media (min-width:900px){
  .browse-grid{ grid-template-columns:repeat(auto-fill,minmax(13rem,1fr)); gap:1rem; }
  .browse-filter-row button{ flex:0 0 auto; padding:.62rem 1.4rem; }
  .browse-filter-row{ gap:.7rem; }
  .nav-bottom, .multi-interest-bar{ max-width:none; padding-left:var(--space-16); padding-right:var(--space-16); }
  .nav-bottom{ grid-template-columns:repeat(4,7rem); justify-content:start; }
}

/* browse revisions: brighter bottom nav, availability-framed chip row */
.nav-bottom button{ opacity:1; color:rgba(255,255,255,.9); }
.nav-bottom button:hover{ color:#fff; }
.nav-bottom button.active{ color:var(--color-accent-soft); }
.filter-row-label{
  font-size:.72rem; font-weight:600; letter-spacing:.12em; text-transform:uppercase;
  color:#fff; opacity:.9; margin:0 0 .5rem;
}
.browse-filter-row{ flex-wrap:wrap; }
.browse-filter-row button{ flex:1 1 auto; min-width:calc(50% - .25rem); }
@media (min-width:900px){ .browse-filter-row button{ min-width:0; } }

/* ============================================================
   SCREEN 10 — filter sheet (in-DOM modal over browse)
   ============================================================ */
.filter-sheet{ position:fixed; inset:0; z-index:20; display:flex; align-items:flex-end; justify-content:center; }
.filter-sheet[hidden]{ display:none; }
.filter-backdrop{ position:absolute; inset:0; background:rgba(2,3,8,.72); backdrop-filter:blur(2px); }
.sheet-body{
  position:relative; z-index:1; width:100%; max-width:var(--card);
  background:var(--color-surface); border:1px solid rgba(255,255,255,.2);
  border-bottom:0; border-radius:var(--radius-xl) var(--radius-xl) 0 0;
  padding:.6rem var(--space-5) var(--space-6);
}
.sheet-handle{ width:2.6rem; height:.22rem; border-radius:var(--radius-full); background:rgba(255,255,255,.4); margin:0 auto var(--space-4); }
.sheet-head{ display:flex; align-items:baseline; justify-content:space-between; margin-bottom:var(--space-5); }
.sheet-head h2{ font-family:var(--font-display); font-size:1.6rem; color:var(--color-text); margin:0; }
.sheet-head button{ font-size:.84rem; color:#fff; text-decoration:underline; text-underline-offset:3px; }
.sheet-label{
  display:block; font-size:.72rem; font-weight:600; letter-spacing:.12em; text-transform:uppercase;
  color:#fff; margin:0 0 .6rem;
}
.sheet-choices{ display:flex; flex-wrap:wrap; gap:.5rem; margin-bottom:var(--space-5); }
.sheet-choices button{
  flex:1 1 auto; min-width:calc(50% - .25rem);
  padding:.66rem .6rem; border-radius:var(--radius-full);
  border:1px solid rgba(255,255,255,.42); color:#fff; font-size:.86rem; font-weight:500;
}
.sheet-choices button:hover{ border-color:#fff; }
.sheet-choices button.active{ background:var(--color-accent); border-color:var(--color-accent); color:var(--color-on-accent); font-weight:600; }
.age-filter-row{ display:flex; align-items:flex-end; gap:.7rem; margin-bottom:var(--space-6); }
.age-box{
  flex:1; display:flex; flex-direction:column; gap:.34rem;
  font-size:.78rem; color:#fff;
}
.age-box input{
  width:100%; padding:.72rem .8rem; border-radius:var(--radius-md);
  background:rgba(13,16,32,.82); border:1px solid rgba(255,255,255,.6);
  color:var(--color-text); font-family:var(--font-body); font-size:1rem;
}
.age-box input:focus{ border-color:var(--color-accent); outline:none; }
.age-dash{ color:#fff; padding-bottom:.9rem; }
@media (min-width:900px){
  .filter-sheet{ align-items:center; }
  .sheet-body{ border-radius:var(--radius-xl); border-bottom:1px solid rgba(255,255,255,.2); max-width:28rem; }
}

/* filter sheet — additional sections + browse empty state */
.sheet-body{ max-height:88dvh; overflow-y:auto; }
.sheet-hint{ font-size:.8rem; color:#fff; opacity:.8; margin:-.35rem 0 .6rem; }
.sheet-choices.sheet-langs button{ min-width:calc(33.333% - .34rem); padding:.6rem .4rem; font-size:.82rem; }
.browse-empty{
  text-align:center; padding:var(--space-10) var(--space-4) var(--space-8);
}
.browse-empty h3{ font-family:var(--font-display); font-size:1.7rem; color:var(--color-text); margin:0 0 .6rem; }
.browse-empty p{ color:#fff; opacity:.86; margin:0 auto var(--space-6); max-width:20rem; line-height:1.55; }
.browse-empty .coral-btn{ max-width:16rem; margin:0 auto; }
.profile-card[hidden]{ display:none; }
.browse-grid[hidden]{ display:none; }
.sheet-choices.sheet-status button{ min-width:calc(33.333% - .34rem); padding:.6rem .4rem; font-size:.82rem; }
.sheet-body .sheet-head{ position:sticky; top:0; background:var(--color-surface); padding-bottom:.5rem; z-index:1; }
/* three availability options after "Often free" was removed */
.browse-filter-row button{ min-width:calc(33.333% - .34rem); }
.sheet-choices:not(.sheet-langs):not(.sheet-status) button{ min-width:calc(33.333% - .34rem); padding:.6rem .4rem; font-size:.82rem; }
@media (min-width:900px){ .browse-filter-row button{ min-width:0; } }

/* filter sheet — "Who's available" dropdown (replaces the browse chip row) */
.select-wrap{ position:relative; margin-bottom:var(--space-5); }
.select-wrap select{
  -webkit-appearance:none; appearance:none; width:100%;
  padding:.86rem 2.6rem .86rem .9rem; border-radius:var(--radius-md);
  background:rgba(13,16,32,.82); border:1px solid rgba(255,255,255,.6);
  color:var(--color-text); font-family:var(--font-body); font-size:1rem; line-height:1.3;
}
.select-wrap select:focus{ border-color:var(--color-accent); outline:none; }
.select-wrap option{ background:var(--color-surface-2); color:var(--color-text); }
.select-caret{
  position:absolute; right:.9rem; top:50%; transform:translateY(-50%);
  width:1.15rem; height:1.15rem; color:#fff; pointer-events:none;
}

/* filter sheet — "show other people if I run out" switch */
.sheet-switch{
  display:flex; align-items:center; gap:.7rem; cursor:pointer;
  margin:0 0 var(--space-5);
}
.sheet-switch input{ position:absolute; opacity:0; width:1px; height:1px; }
.switch-track{
  flex:0 0 auto; width:2.7rem; height:1.5rem; border-radius:var(--radius-full);
  background:rgba(255,255,255,.16); border:1px solid rgba(255,255,255,.5);
  position:relative; transition:background .18s ease, border-color .18s ease;
}
.switch-dot{
  position:absolute; top:.2rem; left:.22rem; width:1rem; height:1rem;
  border-radius:var(--radius-full); background:#fff; transition:transform .18s ease;
}
.sheet-switch input:checked + .switch-track{ background:var(--color-accent); border-color:var(--color-accent); }
.sheet-switch input:checked + .switch-track .switch-dot{ transform:translateX(1.16rem); }
.sheet-switch input:focus-visible + .switch-track{ outline:2px solid var(--color-accent-soft); outline-offset:2px; }
.switch-text{ font-size:.88rem; color:#fff; line-height:1.35; }

/* divider between matches and the spill-over */
.grid-divider{
  grid-column:1 / -1; order:1; margin:var(--space-3) 0 0;
  font-size:.76rem; font-weight:600; letter-spacing:.1em; text-transform:uppercase;
  color:#fff; opacity:.9;
}
.grid-divider[hidden]{ display:none; }

/* ============ SCREEN 11 — profile detail ============ */
.detail-screen{ padding:0 0 6.5rem; }
.detail-hero{ position:relative; width:100%; aspect-ratio:3/4; overflow:hidden; background:var(--color-surface-2); cursor:pointer; }
.detail-photo{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; opacity:0; transition:opacity .25s ease; }
.detail-photo.active{ opacity:1; }
.detail-scrim{ position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(to bottom, rgba(8,10,20,.55) 0%, rgba(8,10,20,0) 26%, rgba(8,10,20,0) 62%, rgba(8,10,20,.9) 100%); }
.detail-back, .detail-more{
  position:absolute; top:.9rem; width:2.4rem; height:2.4rem; border-radius:var(--radius-full);
  display:grid; place-items:center; border:1px solid rgba(255,255,255,.35);
  background:rgba(8,10,20,.55); backdrop-filter:blur(6px); color:#fff; cursor:pointer;
}
.detail-back{ left:.9rem; } .detail-more{ right:.9rem; }
.detail-back svg, .detail-more svg{ width:1.25rem; height:1.25rem; }
.detail-dots{ position:absolute; bottom:.85rem; left:0; right:0; display:flex; gap:.35rem; justify-content:center; }
.detail-dots span{ width:1.6rem; height:.2rem; border-radius:var(--radius-full); background:rgba(255,255,255,.4); }
.detail-dots span.active{ background:#fff; }
.detail-copy{ padding:var(--space-5) var(--space-5) 0; }
.detail-title-row{ display:flex; align-items:baseline; justify-content:space-between; gap:var(--space-3); }
.detail-title-row h1{ font-family:var(--font-display); font-size:1.85rem; line-height:1.1; margin:0; }
.tonight-badge{ display:inline-flex; align-items:center; gap:.35rem; flex:0 0 auto;
  font-size:.78rem; font-weight:600; color:#fff; padding:.3rem .6rem;
  border:1px solid rgba(255,255,255,.34); border-radius:var(--radius-full); background:rgba(255,255,255,.06); }
.detail-status{ margin:.35rem 0 0; font-size:.95rem; color:#fff; opacity:.85; }
.profile-stats{ margin:var(--space-5) 0 0; border-top:1px solid var(--color-border); }
.stat-row{ display:flex; justify-content:space-between; gap:var(--space-3);
  padding:.7rem 0; border-bottom:1px solid var(--color-border); font-size:.92rem; }
.stat-row span{ color:#fff; opacity:.75; }
.stat-row strong{ font-weight:600; color:#fff; }
.detail-about{ margin-top:var(--space-5); }
.detail-about label{ display:block; font-size:.74rem; letter-spacing:.1em; text-transform:uppercase; color:#fff; opacity:.75; margin-bottom:.4rem; }
.detail-about p{ margin:0; font-size:.98rem; line-height:1.55; color:#fff; }
.detail-actions{ margin-top:var(--space-6); display:grid; gap:.4rem; }

/* ============ mutual match / payment success ============ */
.center-screen{ min-height:100dvh; display:flex; flex-direction:column; justify-content:center; padding:var(--space-6) var(--space-5) var(--space-7); text-align:center; }
.match-heart{ width:4.4rem; height:4.4rem; margin:0 auto var(--space-5); border-radius:var(--radius-full);
  display:grid; place-items:center; background:var(--color-accent); color:var(--color-on-accent); }
.match-heart svg{ width:2.2rem; height:2.2rem; }
.match-heart.small{ width:3.4rem; height:3.4rem; }
.match-heart.small svg{ width:1.7rem; height:1.7rem; }
.center-screen h1{ font-family:var(--font-display); font-size:2.1rem; line-height:1.1; margin:0 0 var(--space-3); }
.center-screen > p{ margin:0 auto var(--space-6); max-width:22rem; font-size:1rem; line-height:1.55; color:#fff; }
.match-person{ display:flex; align-items:center; gap:var(--space-3); text-align:left;
  margin:0 auto var(--space-6); padding:.7rem .9rem; max-width:20rem;
  border:1px solid var(--color-border); border-radius:var(--radius-lg); background:var(--color-surface); }
.match-person img{ width:3.2rem; height:3.2rem; border-radius:var(--radius-full); object-fit:cover; }
.match-person strong{ display:block; font-size:1rem; }
.match-person span{ display:flex; align-items:center; gap:.35rem; font-size:.82rem; color:#fff; opacity:.85; }
.center-actions{ display:grid; gap:.4rem; max-width:22rem; margin:0 auto; width:100%; }
.loading-line{ font-size:.9rem; color:#fff; opacity:.8; }

/* ============ activation ============ */
.activation-option{ display:flex; align-items:flex-start; gap:var(--space-3); text-align:left; cursor:pointer;
  padding:var(--space-4); border:1px solid rgba(255,255,255,.4); border-radius:var(--radius-lg);
  background:var(--color-surface); margin-bottom:.6rem; transition:border-color .16s ease, background .16s ease; }
.activation-option.selected{ border-color:var(--color-accent); background:rgba(200,69,47,.14); }
.activation-option input{ position:absolute; opacity:0; width:1px; height:1px; }
.activation-icon{ flex:0 0 auto; width:2.3rem; height:2.3rem; border-radius:var(--radius-full);
  display:grid; place-items:center; background:rgba(255,255,255,.1); color:#fff; }
.activation-option.selected .activation-icon{ background:var(--color-accent); color:var(--color-on-accent); }
.activation-icon svg{ width:1.15rem; height:1.15rem; }
.activation-option small{ display:block; font-size:.8rem; color:#fff; opacity:.85; }
.activation-option strong{ display:block; font-family:var(--font-display); font-size:1.5rem; line-height:1.2; margin:.1rem 0 .25rem; }
.activation-option em{ display:block; font-style:normal; font-size:.85rem; line-height:1.45; color:#fff; opacity:.85; }
.included-pass-card{ text-align:left; padding:var(--space-4); border:1px solid var(--color-accent);
  border-radius:var(--radius-lg); background:rgba(200,69,47,.14); margin-bottom:var(--space-4); }
.included-pass-card > span{ display:flex; align-items:center; gap:.4rem; font-size:.82rem; color:#fff; }
.included-pass-card strong{ display:block; font-family:var(--font-display); font-size:1.4rem; margin:.25rem 0 .2rem; }
.included-pass-card small{ display:block; font-size:.82rem; color:#fff; opacity:.85; }

/* ============ lists: matches, chats ============ */
.list-header{ padding:var(--space-6) var(--space-5) var(--space-4); }
.list-header h1{ font-family:var(--font-display); font-size:2rem; margin:0; }
.list-rows{ padding:0 var(--space-5); }
.match-list-row{ width:100%; display:flex; align-items:center; gap:var(--space-3); text-align:left;
  padding:.75rem 0; border:0; border-bottom:1px solid var(--color-border); background:none; color:inherit; cursor:pointer; }
.match-list-row img, .match-avatar{ flex:0 0 auto; width:3.1rem; height:3.1rem; border-radius:var(--radius-full); object-fit:cover; }
.match-avatar{ display:grid; place-items:center; background:var(--color-surface-2); font-weight:600; }
.match-main{ flex:1 1 auto; min-width:0; }
.match-main strong{ display:block; font-size:1rem; }
.match-main small{ display:flex; align-items:center; gap:.35rem; font-size:.83rem; color:#fff; opacity:.85; }
.match-action{ flex:0 0 auto; font-size:.86rem; font-weight:600; color:var(--color-accent-soft); }
.match-list-row.pending .match-action{ color:var(--color-accent-soft); }

/* ============ chat ============ */
.chat-screen{ display:flex; flex-direction:column; min-height:100dvh; padding:0; }
.chat-header{ display:flex; align-items:center; gap:var(--space-3); padding:.8rem var(--space-4);
  border-bottom:1px solid var(--color-border); background:var(--color-surface); position:sticky; top:0; z-index:5; }
.chat-header button.chat-back{ width:2rem; height:2rem; border:0; background:none; color:#fff; cursor:pointer; display:grid; place-items:center; }
.chat-header button.chat-back svg{ width:1.3rem; height:1.3rem; }
.chat-who{ display:flex; align-items:center; gap:.6rem; flex:1 1 auto; min-width:0; }
.chat-who img{ width:2.2rem; height:2.2rem; border-radius:var(--radius-full); object-fit:cover; }
.chat-who strong{ font-size:1rem; }
.chat-more{ color:#fff; opacity:.7; letter-spacing:.12em; }
.message-list{ flex:1 1 auto; display:flex; flex-direction:column; gap:.5rem;
  padding:var(--space-5) var(--space-4); overflow-y:auto; }
.bubble{ max-width:78%; padding:.6rem .8rem .45rem; border-radius:1rem; font-size:.95rem; line-height:1.45; }
.bubble small{ display:block; margin-top:.2rem; font-size:.68rem; opacity:.8; }
.bubble.mine{ align-self:flex-end; background:var(--color-accent); color:var(--color-on-accent); border-bottom-right-radius:.3rem; }
.bubble.theirs{ align-self:flex-start; background:var(--color-surface-2); color:#fff;
  border:1px solid var(--color-border); border-bottom-left-radius:.3rem; }
.chat-compose{ display:flex; gap:.5rem; padding:.7rem var(--space-4) 1rem;
  border-top:1px solid var(--color-border); background:var(--color-surface); position:sticky; bottom:0; }
.chat-compose input{ flex:1 1 auto; min-width:0; }
.chat-send{ flex:0 0 auto; width:2.8rem; height:2.8rem; border-radius:var(--radius-full); border:0;
  background:var(--color-accent); color:var(--color-on-accent); display:grid; place-items:center; cursor:pointer; }
.chat-send svg{ width:1.2rem; height:1.2rem; }
.locked-chat{ flex:1 1 auto; display:flex; flex-direction:column; justify-content:center;
  text-align:center; padding:var(--space-6) var(--space-5) var(--space-7); }
.lock-ring{ width:4rem; height:4rem; margin:0 auto var(--space-5); border-radius:var(--radius-full);
  display:grid; place-items:center; border:1px solid rgba(255,255,255,.4); background:var(--color-surface-2); color:#fff; }
.lock-ring svg{ width:1.6rem; height:1.6rem; }
.locked-chat h1{ font-family:var(--font-display); font-size:1.9rem; line-height:1.15; margin:0 0 var(--space-3); }
.locked-chat p{ margin:0 auto var(--space-6); max-width:20rem; color:#fff; line-height:1.55; }

/* ============ account ============ */
.account-card{ display:flex; align-items:center; gap:var(--space-3); margin:0 var(--space-5) var(--space-5);
  padding:var(--space-4); border:1px solid var(--color-border); border-radius:var(--radius-lg); background:var(--color-surface); }
.account-card img{ width:3.6rem; height:3.6rem; border-radius:var(--radius-full); object-fit:cover; }
.account-card h2{ font-family:var(--font-display); font-size:1.35rem; margin:0; }
.account-card p{ margin:.15rem 0 0; font-size:.86rem; color:#fff; opacity:.85; }
.account-details{ margin:0 var(--space-5) var(--space-5); border-top:1px solid var(--color-border); }
.pass-card{ margin:0 var(--space-5) var(--space-4); padding:.8rem var(--space-4);
  border:1px solid var(--color-accent); border-radius:var(--radius-lg); background:rgba(200,69,47,.14); }
.pass-card span{ font-size:.8rem; color:#fff; }
.pass-card strong{ display:block; font-size:1rem; margin-top:.15rem; }
.account-note{ margin:0 var(--space-5) var(--space-5); font-size:.85rem; color:#fff; opacity:.85; }
.settings-list{ padding:0 var(--space-5); }
.settings-row{ width:100%; display:flex; align-items:center; justify-content:space-between; gap:var(--space-3);
  padding:.95rem 0; border:0; border-bottom:1px solid var(--color-border); background:none;
  color:#fff; font-size:.98rem; text-align:left; cursor:pointer; }
.settings-row > span{ color:#fff; opacity:.7; font-size:.9rem; }
.settings-row.danger{ color:var(--color-accent-soft); }

/* ticks and glyph sizing on the reused choice cards */
.choice-card b svg{ width:1rem; height:1rem; }
.included-pass-card > span svg{ width:.95rem; height:.95rem; flex:0 0 auto; }

/* pages with no step dots: darker sky so the heading is never over bright sunset */
/* sky-dim removed 30 Aug: screens 14, 15, 22 now use the same wash as every other screen */
.page-center .auth-body{ justify-content:center; padding-bottom:var(--space-8); }
.page-center .tiny-copy{ color:#fff; margin:var(--space-4) 0 var(--space-3); font-size:.82rem; }
.page-center .choice-stack{ margin-top:var(--space-5); }
.included-pass-card{ margin-top:var(--space-4); }
.message-list{ justify-content:flex-end; }
.chat-compose .input{ height:2.9rem; }

/* full-screen empty states inside the tabbed shell */
.empty-state.page-empty, .with-nav .empty-state{
  min-height:58dvh; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:.15rem; padding:var(--space-6) var(--space-6);
}
.with-nav .empty-state .coral-btn{ width:100%; max-width:15rem; margin-top:var(--space-5); }
.with-nav .empty-state p{ max-width:19rem; line-height:1.5; }
.center-actions[hidden]{ display:none; }

/* desktop: inner member screens sit in a centred column, not stretched */
@media (min-width:900px){
  .page-column{
    max-width:34rem; margin-inline:auto; min-height:100dvh;
    border-left:1px solid var(--color-border); border-right:1px solid var(--color-border);
  }
  .page-column .nav-bottom{
    max-width:34rem; grid-template-columns:repeat(4,1fr); justify-content:stretch;
    padding-left:var(--space-4); padding-right:var(--space-4);
  }
  .page-column .detail-hero{ aspect-ratio:4/3; }
}

/* screen 11: one fact line instead of three rows, taller photo */
.detail-facts{
  margin:var(--space-4) 0 0; padding:.55rem 0 0;
  border-top:1px solid var(--color-border);
  font-size:.92rem; line-height:1.45; color:#fff;
}
.detail-hero{ aspect-ratio:2/3; }
@media (min-width:900px){ .page-column .detail-hero{ aspect-ratio:4/3; } }

/* onboarding switch on a card, and the massage role block */
.card-switch{ margin:var(--space-5) 0 0; padding:.9rem 1rem; border:1px solid rgba(255,255,255,.6); border-radius:var(--radius-md); background:var(--color-surface-2); }
.field-label{ margin:var(--space-5) 0 .5rem; font-size:.8rem; letter-spacing:.08em; text-transform:uppercase; color:#fff; }
#massageRole[hidden]{ display:none; }

/* massage & wellness */
.massage-tag{
  display:inline-block; margin-top:.34rem; padding:.14rem .46rem;
  border:1px solid rgba(255,255,255,.55); border-radius:999px;
  font-size:.68rem; letter-spacing:.02em; color:#fff; background:rgba(8,10,20,.5);
}
.detail-massage{
  margin:.55rem 0 0; padding:.5rem 0 0; border-top:1px solid var(--color-border);
  font-size:.92rem; color:#fff;
}
.detail-massage span{ color:#fff; opacity:.78; margin-right:.4rem; }
.with-nav .empty-state[hidden], .empty-state[hidden]{ display:none !important; }
.pass-card.plain{ border-color:var(--color-border); background:var(--color-surface-2); margin-top:var(--space-3); }

/* browse cards — two lines only, photo stays visible */
.profile-overlay .card-line{
  display:flex; align-items:center; gap:.34rem;
  margin:.14rem 0 0; font-size:.76rem; font-weight:500; color:#fff; opacity:1;
  white-space:nowrap;
}
.massage-badge{
  position:absolute; top:.5rem; left:.5rem; z-index:3;
  padding:.2rem .44rem; border-radius:999px;
  font-size:.66rem; font-weight:600; letter-spacing:.02em;
  color:#fff; background:rgba(4,5,10,.62); border:1px solid rgba(255,255,255,.5);
  backdrop-filter:blur(4px);
}

.demo-toggle{ display:flex; gap:var(--space-4); justify-content:center; margin-top:var(--space-4); }
.demo-toggle .text-btn{ font-size:.76rem; }

/* ---- Renewal — account screen ----
   New for 2026-08-30. The website promises "one tap keeps you going", so the
   account screen now carries a real control instead of a passive sentence.
   Three states: comfortable, urgent (3 days or fewer), and already over. */
.renew-card{
  margin: var(--space-5) var(--space-5) var(--space-4);
  padding: 1rem 1.05rem 1.05rem;
  border: 1px solid var(--color-border);
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(200,69,47,.10), rgba(200,69,47,.03));
  display: flex; flex-direction: column; gap: .3rem;
}
.renew-card span{ font-size: .8rem; color: rgba(247,239,227,.82); }
.renew-card strong{ font-size: 1.12rem; color: var(--color-text); font-weight: 600; }
.renew-card .coral-btn.slim{ margin-top: .7rem; }
/* Urgent and ended both warm up the border so the card reads at a glance,
   without ever dimming the text — everything here stays fully legible. */
.renew-card.is-urgent{ border-color: rgba(200,69,47,.55); background: linear-gradient(180deg, rgba(200,69,47,.18), rgba(200,69,47,.06)); }
.renew-card.is-over{ border-color: rgba(200,69,47,.7); background: linear-gradient(180deg, rgba(200,69,47,.22), rgba(200,69,47,.08)); }
.coral-btn.slim{ padding: .72rem 1rem; font-size: .95rem; width: 100%; }

.renew-choices{ display: flex; flex-direction: column; gap: .55rem; margin: .2rem 0 .3rem; }
.renew-choices button{
  width: 100%; text-align: left;
  padding: .95rem 1.05rem;
  border: 1px solid var(--color-border); border-radius: 12px;
  background: var(--color-surface-2); color: var(--color-text);
  font-size: 1rem; font-weight: 500; cursor: pointer;
  transition: border-color var(--transition-interactive), background var(--transition-interactive);
}
.renew-choices button:hover,
.renew-choices button:focus-visible{ border-color: var(--color-accent); background: rgba(200,69,47,.14); }

/* A profile with no end date has no countdown and no renew button, so the one
   line it does have carries the whole card — full brightness, body size, not
   the small dim label size the dated version uses. */
.renew-card.is-manual{ background:linear-gradient(180deg, rgba(200,69,47,.07), rgba(200,69,47,.02)); }
.renew-card.is-manual span{ font-size:1.02rem; color:var(--color-text); font-weight:500; }

/* Helper line under a field label. Fully legible, not a whisper. */
.field-hint{
  margin:.2rem 0 .1rem; font-size:.86rem; line-height:1.45;
  color:rgba(247,239,227,.9);
}

/* ============================================================================
   Onboarding — the classes app.js actually renders
   ----------------------------------------------------------------------------
   Everything above was written against the mockup markup (.auth-card, .form-row,
   .field-label, .unit-pair). The live app renders .profile-form, .field, <label>
   and .unit-row, which had no rules at all: headings fell back to the browser
   default and the cm / ft-in and kg / lb buttons ran together as bare text.
   These rules reuse the approved values rather than inventing new ones.
   ========================================================================== */
.inside-shell.form-screen{ position:relative; overflow:hidden; }
.inside-shell.form-screen > .inside-page{ position:relative; z-index:2; }

.profile-create-page{ padding-top:var(--space-3); }
.profile-form{
  width:100%; max-width:var(--card); margin:0 auto;
  padding:var(--space-6) var(--space-5) var(--space-8);
}
.profile-form h1{
  font-family:var(--font-display); font-weight:400;
  font-size:clamp(1.68rem, 1.2rem + 2.4vw, 2.35rem); line-height:1.06;
  letter-spacing:-.01em; margin:0;
}
.profile-form h1 em{ font-style:italic; color:var(--color-accent-soft); }
.profile-form > p{
  margin:var(--space-3) 0 0; max-width:30ch;
  font-size:.9rem; line-height:1.5; color:#fff;
}
.profile-form .required-note{ color:var(--color-accent-soft); font-weight:600; }
.profile-form > .coral-btn{ margin-top:var(--space-6); width:100%; }
.profile-form .text-btn{ display:block; margin:var(--space-4) auto 0; }

/* one field = label, then its control */
.field{ margin-top:var(--space-6); }
.field > label{
  display:block; margin-bottom:.5rem;
  font-size:.7rem; font-weight:500; letter-spacing:.14em; text-transform:uppercase;
  color:#fff;
}
.field > label .optional{
  margin-left:.4rem; letter-spacing:.06em; text-transform:none;
  font-size:.72rem; font-weight:400; color:rgba(247,239,227,.72);
}
.field > label.card-switch{ text-transform:none; letter-spacing:0; font-size:.88rem; }
.field .choice-stack{ margin-top:0; }
.field .field-hint{ margin:0 0 .55rem; }

/* value + its unit toggle on one line: [ 180 ][ cm ][ ft / in ] */
.unit-row{ display:flex; align-items:stretch; gap:.35rem; }
.unit-row input.input{ flex:1 1 auto; min-width:0; }
.unit-row .unit{ flex:0 0 auto; white-space:nowrap; }

/* profile detail page had no rules either */
.detail-page{ padding-bottom:var(--space-8); }

/* pill rows for gender / interested-in / status, and the top bar's brand slot */
.choices{ display:flex; flex-wrap:wrap; gap:.4rem; }
.app-brand{ display:flex; align-items:center; justify-content:center; flex:1 1 auto; }

/* ---- top bar: the live app's own class names ----------------------------
   app.js renders .language-control, .brand-words and .brand-arc; member.css
   only had .lang-switch, .brand-word and .brand-mark from the mockups, so the
   language buttons ran together ("ENPTES") and the logo's SVG paths drew as a
   filled blob. Same values as the mockup rules above. */
.language-control{
  display:flex; align-items:center; gap:.1rem; flex:0 0 auto;
  border:1px solid rgba(247,239,227,.22); border-radius:var(--radius-full);
  background:rgba(8,10,20,.42); padding:2px;
}
.language-control button{
  font-size:.72rem; font-weight:500; letter-spacing:.1em;
  padding:.3rem .52rem; border-radius:var(--radius-full);
  color:rgba(255,255,255,.9);
  transition:color var(--transition-interactive), background var(--transition-interactive);
}
.language-control button.active{ color:var(--color-on-accent); background:rgba(200,69,47,.9); }
.language-control button:hover:not(.active){ color:#fff8ee; }

.brand-mark path{ fill:none; stroke:currentColor; stroke-width:7; stroke-linecap:round; stroke-linejoin:round; }
.brand-mark .brand-arc{ stroke:var(--color-accent-soft); stroke-width:5; opacity:.85; }
.brand-words{ display:flex; align-items:baseline; font-family:var(--font-display); font-size:1.28rem; line-height:1; }
.brand-words span:first-child{ color:var(--color-text); }
.brand-words span:last-child{ font-style:italic; color:var(--color-accent-soft); margin-left:.18em; }

/* the step bar sits in the page, not the card, so it needs the same gutter */
.profile-create-page > .step-dots{
  width:100%; max-width:var(--card); margin:var(--space-5) auto 0;
  padding:0 var(--space-5);
}
/* the massage switch is a label too, but it must stay a flex row */
.field > label.card-switch{ display:flex; }

/* the sub-line under a choice card was .72rem at 90% -- about 11.5px on a 360px
   phone. Standing legibility rule: nothing should be hard to read. */
.choice-card small{ font-size:.78rem; line-height:1.35; color:#fff; }

/* Logo left, language right -- the arrangement the approved screens use.
   Nothing sits to the left of the logo now that the back arrow is gone. */
.app-brand{ justify-content:flex-start; }

/* ===========================================================================
 * v45 — the verification screen was impossible to complete.
 *
 * `.otp-hidden` is `position:absolute; inset:0` and was written to sit inside
 * `.otp-wrap { position: relative; }` (line 252). That wrapper was never in the
 * markup, so the input had no positioned ancestor and resolved against the
 * initial containing block: a transparent 390x844 field covering the ENTIRE
 * viewport at z-index 2. Measured on a 390x844 phone, the invisible input's box
 * was 0,0 390x844 and `document.elementFromPoint()` at the dead centre of the
 * Verify button returned `#otp`, not the button. Every tap anywhere on that
 * screen — Verify, "Send via SMS", the language switcher — hit the invisible
 * input instead. Nobody could get past /verify on a phone.
 *
 * app.js now emits the `.otp-wrap` div the CSS always expected. The rules below
 * are a belt-and-braces guard so the button can never be swallowed again even
 * if that wrapper goes missing in a future edit.
 * ========================================================================= */
.otp-card { position: relative; }
.otp-wrap { position: relative; display: block; }
/* Containment, not decoration: the overlay may only ever cover its own wrapper. */
.otp-wrap > .otp-hidden { position: absolute; inset: 0; width: 100%; height: 100%; }
/* If the wrapper is ever absent the input falls back to sitting on the boxes
   only, and can never reach the Verify button below it. */
.otp-card > .otp-hidden { position: absolute; left: 0; right: 0; width: 100%; height: 3.5rem; inset-block: auto; }
/* Nothing may paint or capture taps above the primary action. */
.otp-card .coral-btn { position: relative; z-index: 3; }
.otp-card .resend-copy { position: relative; z-index: 3; }

/* v45 — "WhatsAppRecommended" ran together as one word.
   `.delivery-text strong/small { display: block }` targets a class the markup
   never carries: app.js emits a bare <span> wrapping <strong> + <small>, so both
   stayed inline. Target the element that is actually there. */
.delivery-card > span:not(.delivery-icon) { flex: 1; min-width: 0; }
.delivery-card > span:not(.delivery-icon) > strong { display: block; font-weight: 500; font-size: var(--text-sm); }
.delivery-card > span:not(.delivery-icon) > small { display: block; margin-top: .12rem; font-size: .74rem; color: rgba(255,255,255,.72); }

/* v45 — the selected-channel styling keyed off `[aria-pressed='true']`, but the
   markup marks the choice with `.active`. The chosen row was never highlighted. */
.delivery-card.active { border-color: rgba(200,69,47,.7); background: rgba(200,69,47,.09); }
.delivery-card > b { flex: none; width: 18px; text-align: center; color: var(--color-accent-soft); }

/* ============================================================================
 * v46 — verify screen: breathing room, a readable error, and the sunset back
 * ==========================================================================
 * Three complaints from a real phone, in the order they were reported:
 *
 * 1. "the verify button is much too close to the 'didn't get it' line" — the
 *    resend sentence sat directly above the primary action with 1.1rem between
 *    them, so the underlined "Send via SMS" link was inside the thumb path of
 *    the Verify button. The resend line now renders BELOW the button (app.js),
 *    which is also the conventional order, and both get real separation.
 * 2. "I entered 123456 and nothing happens" — failures were reported only via
 *    toast(), which removes itself after 2400ms. `.otp-error` is a permanent
 *    element instead.
 * 3. The agreed sunset/mountain backdrop was only ever wired into the profile
 *    steps. app.js now emits `.auth-sky.sky-short` on all six auth screens; the
 *    existing `.auth-sky` rules do the rest, so the photograph is treated
 *    identically here to everywhere else.
 * ========================================================================= */
.otp-card .otp-boxes { margin-bottom: 1.5rem; }
/* Generous, deliberate gap above the primary action. */
.otp-card .coral-btn { margin-top: .35rem; }
/* Below the button now, and pushed clear of it. */
.otp-card .resend-copy { margin: 1.35rem 0 0; text-align: center; }

.otp-error {
  margin: 0 0 1rem; padding: .62rem .8rem;
  border: 1px solid rgba(200,69,47,.55);
  border-radius: .6rem;
  background: rgba(200,69,47,.12);
  font-size: .84rem; line-height: 1.35;
  color: #ffd9d1;
}
.otp-error[hidden] { display: none; }

/* The auth screens are now `.inside-shell.form-screen`, which is
   `overflow:hidden`. The country sheet is `position:fixed` with no transformed
   ancestor, so it is not clipped — but state this explicitly so a later edit
   does not "tidy" the sheet into the flow and lose the picker. */
.inside-shell.form-screen > .filter-sheet,
.inside-shell.form-screen .filter-sheet { position: fixed; }

/* The auth screens put a headline and body copy directly over the top band of
   the photograph, which is its brightest region (the sun). The onboarding
   scrim was tuned for screens whose first element is a row of step bars, so
   white text on /join and /verify came out barely legible. Darken the scrim on
   these screens only — the photograph, its crop and its filter are untouched,
   so it still reads as the same image used everywhere else. */
.auth-page ~ .auth-sky::after,
.inside-shell.form-screen:has(.auth-page) .auth-sky::after {
  background:
    linear-gradient(to bottom,
      rgba(8,10,20,.46) 0%,
      rgba(8,10,20,.44) 42%,
      rgba(8,10,20,.72) 72%,
      rgba(8,10,20,.93) 90%,
      var(--color-bg) 100%);
}
/* Belt and braces for the headline itself, which sits highest. */
.auth-page .onboarding-card h1,
.auth-page .onboarding-card > p { text-shadow: 0 1px 12px rgba(4,6,14,.75); }

/* Auth screens are short on content and long on empty space below the fold, so
   the photograph gets the taller treatment (the same 46dvh used on the entry
   screen) rather than the 28dvh strip the multi-field onboarding steps need. */
.auth-page ~ .auth-sky.sky-short,
.inside-shell.form-screen:has(.auth-page) .auth-sky.sky-short { height: 44dvh; }

/* With the taller photograph behind them the code boxes now sit over the
   mountain ridge, where a semi-transparent fill would leave the typed digits
   competing with the skyline. Make the boxes read as solid surfaces. */
.otp-card .otp-boxes span {
  background: rgba(9,11,22,.9);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  border-color: rgba(255,255,255,.16);
}
.otp-card .otp-boxes span.filled {
  background: rgba(14,17,32,.95);
  border-color: rgba(240,161,115,.6);
}

/* `.icon-ring` on the invitation screen had no rule anywhere in the stylesheet,
   so its glyph rendered as a stray 12px character floating under the logo. It
   is meant to be a badge, like `.match-heart` on the confirmation screen. */
.icon-ring {
  width: 3.4rem; height: 3.4rem; margin: 0 auto var(--space-4);
  border-radius: var(--radius-full);
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(240,161,115,.45);
  background: rgba(200,69,47,.14);
  color: var(--color-accent-soft);
  font-size: 1.5rem; line-height: 1;
}
/* Same tight-spacing complaint as the verify screen: the primary action sat
   almost against the field above it. */
.invitation-card .coral-btn { margin-top: 1.1rem; }
.invitation-card .small-copy { margin-top: .9rem; }

/* ============================================================
   v47 — profile detail, browse hints, filter sheet
   Reported from a real session on a phone: the profile screen ran labels into
   their values, "Pass" sat almost on top of the copy, the filter sheet was
   cramped with white number boxes, and sending interest looked like nothing.
   ============================================================ */

/* "About me" was an unstyled <label>, i.e. inline text the same size as the
   sentence under it, with no gap — it read as part of the paragraph. */
.detail-about{ margin-top:var(--space-6); }
.detail-about > label{
  display:block; margin:0 0 .5rem;
  font:600 .72rem/1 var(--font-body); letter-spacing:.12em; text-transform:uppercase;
  color:rgba(255,255,255,.72);
}
.detail-about > p{ margin:0; font-size:.98rem; line-height:1.6; color:#fff; }
.detail-copy > p{ margin:.35rem 0 0; font-size:.95rem; color:#fff; opacity:.85; }
.profile-stats{ margin-top:var(--space-6); }

/* Room between the copy, the two actions, and the bottom nav. */
.detail-actions{ margin-top:var(--space-7); padding-bottom:calc(4.6rem + var(--space-6)); }
.detail-actions .text-btn{ margin-top:var(--space-4); }

/* Browse: say out loud that several people can be chosen at once. */
.browse-hint{
  margin:.15rem var(--space-5) .3rem; font-size:.8rem; line-height:1.45;
  color:rgba(255,255,255,.78);
}
/* v68 — this used to carry an ✕ and wait to be dismissed. Being told a block
   worked is not a task, and it should not leave litter on the screen to be
   tidied up. It fades out on its own after about five seconds. The transition
   is on opacity and transform only, both compositor properties, so the fade
   costs no layout while the grid behind it is still settling. */
.flash-note{
  margin:.55rem var(--space-5) .2rem; padding:.7rem .8rem;
  border:1px solid rgba(255,255,255,.28); border-left:3px solid var(--color-accent);
  border-radius:var(--radius-md); background:rgba(255,255,255,.08);
  font-size:.85rem; line-height:1.45; color:#fff;
  opacity:1; transform:translateY(0);
  transition:opacity .55s ease, transform .55s ease;
}
.flash-note.is-going{ opacity:0; transform:translateY(-.35rem); }
@media (prefers-reduced-motion:reduce){
  .flash-note{ transition:opacity .55s ease; }
  .flash-note.is-going{ transform:none; }
}

/* Heart / tick are drawn now, and a chosen card actually turns coral. */
.profile-select svg{ width:17px; height:17px; fill:currentColor; display:block; }
.profile-select.selected{ background:var(--color-accent); border-color:var(--color-accent); color:var(--color-on-accent); }
.sent-badge{
  position:absolute; left:.5rem; top:.5rem; z-index:3;
  padding:.22rem .5rem; border-radius:var(--radius-full);
  background:rgba(4,5,10,.66); border:1px solid rgba(255,255,255,.4);
  font-size:.66rem; font-weight:600; letter-spacing:.03em; color:#fff;
  backdrop-filter:blur(4px);
}
.profile-card.already-sent .real-photo, .profile-card.already-sent .demo-photo{ opacity:.82; }

/* Filter sheet: breathing room between the three groups. */
.sheet-body{ padding:.6rem var(--space-5) calc(var(--space-6) + .4rem); }
.sheet-head{ margin-bottom:var(--space-6); }
.sheet-label{ margin-bottom:.75rem; }
.sheet-choices{ gap:.6rem; margin-bottom:var(--space-7); }
.sheet-choices button{ padding:.74rem .6rem; }
.age-filter-row{ gap:.85rem; margin-bottom:var(--space-7); }
.age-box > span{ font-size:.78rem; color:rgba(255,255,255,.82); }
.filter-sheet .age-box input{
  /* iOS renders an unstyled number input as a white pill — this rule was written
     for `.age-box input`, but the markup had no `.age-box`, so it never landed. */
  background:rgba(13,16,32,.82); color:var(--color-text);
  border:1px solid rgba(255,255,255,.6); -webkit-appearance:none; appearance:none;
}
.filter-sheet .coral-btn{ margin-top:.2rem; }

/* Match + activation screens now sit on the sunset like the rest of the flow. */
.activation-page.auth-page, .centered-flow.auth-page{ position:relative; z-index:1; }

/* ============================================================
   v48 — typography and vertical rhythm on mobile
   Reported on a phone: the auth headings were in the body sans at 32px and
   "Check your WhatsApp" read as huge and ugly; every auth screen was pressed
   against the logo with 150px+ of unused screen below; Browse showed a plain
   text "Rio Now" instead of the lockup; the chips were tall and the filter
   sheet had no air between its groups.
   ============================================================ */

/* The step-down + display serif rules were written for `.auth-card`. These
   screens are `.onboarding-card`, so nothing applied: Switzer at 32.35px. */
.auth-page .onboarding-card h1{
  font-family:var(--font-display); font-weight:400;
  font-size:clamp(1.72rem, 1.3rem + 1.9vw, 2.1rem); line-height:1.12;
  letter-spacing:.004em; margin:0 0 .55rem;
}
.auth-page .onboarding-card > h1 + p{ margin:0 0 1.15rem; font-size:.92rem; line-height:1.55; }

/* Centre the card in the space available instead of stacking it under the logo.
   Guarded by min-height so short screens keep the old top alignment and can
   never clip inside the shell's overflow:hidden. */
@media (min-height:600px){
  .inside-shell.form-screen > .inside-page.auth-page{ flex:1 1 auto; display:flex; flex-direction:column; }
  .inside-page.auth-page > .onboarding-card{ margin-top:auto; margin-bottom:auto; }
  .inside-page.auth-page > .app-topbar{ flex:0 0 auto; }
}

/* Browse: shorter day chips, tighter header, and the sunset behind it all. */
.browse-top{ padding:var(--space-4) 0 var(--space-3); }
.browse-top .brand-lockup{ pointer-events:none; }
.browse-filter-row{ padding-bottom:var(--space-3); }
.browse-filter-row button{ padding:.44rem .5rem; font-size:.8rem; }
.inside-shell.browse-shell{ position:relative; overflow-x:hidden; }
.inside-shell.browse-shell > .inside-page{ position:relative; z-index:2; }
.auth-sky.sky-browse{ height:23dvh; }
.auth-sky.sky-browse::after{
  background:
    linear-gradient(to bottom, rgba(8,10,20,.42) 0%, rgba(8,10,20,.52) 40%, rgba(8,10,20,.88) 78%, var(--color-bg) 100%);
}

/* Filter sheet: real separation between the three groups, smaller chips. */
.filter-sheet .sheet-label{ margin:var(--space-6) 0 .6rem; }
.filter-sheet .sheet-label:first-of-type{ margin-top:0; }
.filter-sheet .sheet-choices{ margin-bottom:0; }
.filter-sheet .sheet-choices:not(.sheet-langs):not(.sheet-status) button{
  padding:.5rem .5rem; font-size:.8rem;
}
.filter-sheet .age-filter-row{ margin-bottom:0; }
.filter-sheet .coral-btn{ margin-top:var(--space-6); }

/* Profile detail, second pass. The stats table is now a stacked list: three
   languages wrapped badly against the row dividers and the hairlines read as
   stray white dashes between the words. */
.profile-stats{ border-top:0; display:grid; gap:var(--space-5); margin-top:var(--space-6); }
.stat-item > span{
  display:block; margin-bottom:.3rem;
  font:600 .7rem/1 var(--font-body); letter-spacing:.12em; text-transform:uppercase;
  color:rgba(255,255,255,.66);
}
.stat-item > strong{ font-weight:500; font-size:1rem; color:#fff; }
.lang-pills{ display:flex; flex-wrap:wrap; gap:.4rem; }
.lang-pills em{
  font-style:normal; font-size:.84rem; color:#fff;
  padding:.26rem .62rem; border-radius:var(--radius-full);
  border:1px solid rgba(255,255,255,.32); background:rgba(255,255,255,.06);
}
/* Real distance between the end of the About text and the two actions. */
.detail-actions{ margin-top:var(--space-16); }
.detail-about{ margin-top:var(--space-7); }

/* Bottom-nav icons are inline SVG now (they were dingbat characters). */
.nav-bottom .nav-icon{ display:block; }
.nav-bottom .nav-icon svg{ width:1.28rem; height:1.28rem; display:block; margin:0 auto; }

/* One photo produced one carousel dot, and the active dot is a wide bar — that
   was the stray white dash sitting above the profile details. */
.detail-dots:empty{ display:none; }

/* The sheet sat flush to the bottom of the screen, so the "Show people" button
   ended up underneath the tab bar. Lift the content clear of it and let the
   sheet scroll on short screens instead of running off the bottom. */
.filter-sheet{ z-index:30; }
.filter-sheet .sheet-body{
  padding-bottom:calc(4.6rem + var(--space-5));
  max-height:92dvh; overflow-y:auto; -webkit-overflow-scrolling:touch;
}

/* ---- brand lockup: identical to the public site (index.html) ---- */
.brand-lockup{ display:inline-flex; align-items:center; gap:var(--space-2); color:var(--color-text);
  text-shadow:0 1px 3px rgba(6,4,10,.92), 0 2px 16px rgba(6,4,10,.75); }
.brand-lockup .brand-mark{ width:26px; height:26px; color:var(--color-accent); flex:none; }
/* the shared .brand-mark path rule below forced a stroke-only look on the moon */
.brand-lockup .brand-mark circle{ fill:currentColor; stroke:none; }
.brand-lockup .brand-mark path{ fill:none; stroke:currentColor; stroke-width:2.2; }
.brand-word{ font-family:var(--font-display); font-size:1.4rem; letter-spacing:-.01em; line-height:1; }
.brand-word-thin{ font-style:italic; color:var(--color-accent); margin-left:.18em; }

/* ---- phone field: the generic input.input rule (border + dark fill + its own
   radius) was overriding ".phone-field input", so the number sat in a second
   box inside the field. Same specificity, defined later, so it won. ---- */
.phone-field input.input{
  height:auto; padding:.95rem 0; border:0; border-radius:0;
  background:transparent; box-shadow:none;
}
.phone-field input.input:focus{ border:0; box-shadow:none; outline:none; }

/* ---- join screen: the primary action was hard against the SMS card, and the
   small print was hard against the button. ---- */
.login-card #sendOtp{ margin-top:var(--space-6); }
.login-card .tiny-copy{ margin-top:var(--space-5); }

/* Day filters: shorter, and sized to their own text instead of stretching to
   fill the row. */
.browse-filter-row button{
  flex:0 0 auto; min-width:0;
  padding:.34rem .95rem; font-size:.8rem; line-height:1.15;
}
@media (max-width:420px){
  .browse-filter-row button{ padding:.34rem .8rem; }
}

/* Denser browse grid: three across on phones so a screenful shows nine or more
   people instead of four. Overlay text and the heart shrink to match. */
@media (max-width:700px){
  .browse-grid{ grid-template-columns:repeat(3,1fr); gap:.42rem; }
  .profile-card{ aspect-ratio:1/1; border-radius:var(--radius-md); }
  .profile-overlay{ padding:.3rem .38rem .34rem; }
  .profile-overlay h3{ font-size:.8rem; }
  .profile-overlay p{ display:none; }
  .profile-overlay .avail, .profile-overlay span{ font-size:.62rem; }
  .profile-select{ width:1.55rem; height:1.55rem; top:.3rem; right:.3rem; }
  .profile-select svg{ width:13px; height:13px; }
  .sent-badge{ font-size:.58rem; padding:.12rem .3rem; }
}

/* =====================================================================
   v52
   Five things, all from testing on a phone:
   1. Unread badges on the bottom bar, so a new match or message is
      visible the moment the app loads.
   2. Browse cards: the caption moved off the photograph and under it,
      separated by a hairline. Nothing covers a face any more — not the
      name, not the availability line, and not "Interest sent".
   3. Chat: proper bubbles with tails, a heart you can put on a message,
      and a compose field that is dark with white text (it used to be a
      white box with white text — you could not see what you typed).
   4. The ••• in the chat header is gone; it was never a real menu.
   5. Activate screen: display face for the heading, vertically centred,
      and it now shows who you are activating.
   ===================================================================== */

/* --- 1. badges ------------------------------------------------------ */
.nav-bottom .nav-icon{ position:relative; }
.nav-badge{
  position:absolute; top:-.32rem; left:calc(50% + .28rem);
  min-width:1.05rem; height:1.05rem; padding:0 .22rem;
  display:grid; place-items:center;
  border-radius:var(--radius-full);
  background:var(--color-accent); color:var(--color-on-accent);
  border:1.5px solid rgba(8,10,20,.96);
  font-family:var(--font-body); font-size:.62rem; font-weight:700;
  font-style:normal; line-height:1; letter-spacing:0;
}
.match-list-row .new-tag{
  margin-left:.45rem; padding:.1rem .38rem;
  border-radius:var(--radius-full);
  background:var(--color-accent); color:var(--color-on-accent);
  font-family:var(--font-body); font-size:.6rem; font-weight:700;
  font-style:normal; letter-spacing:.04em; text-transform:uppercase;
  vertical-align:.08rem;
}
.match-list-row.is-unread .match-main small{ color:var(--color-accent-soft); font-weight:600; }
.match-list-row .unread-dot{
  display:inline-block; width:.45rem; height:.45rem; margin-right:.4rem;
  border-radius:var(--radius-full); background:var(--color-accent);
  vertical-align:.05rem;
}

/* --- 2. browse cards ----------------------------------------------- */
.app-profile-card{
  aspect-ratio:auto;                 /* the photo owns the ratio now */
  display:flex; flex-direction:column;
  background:var(--color-surface-2);
}
.app-profile-card::after{ content:none; }   /* the old bottom scrim */
.app-profile-card .card-photo{
  position:relative; aspect-ratio:1/1; overflow:hidden;
}
.app-profile-card .card-photo .real-photo,
.app-profile-card .card-photo .demo-photo{ width:100%; height:100%; }
.app-profile-card .card-foot{
  border-top:1px solid rgba(255,255,255,.5);   /* the separating line */
  padding:.38rem .45rem .42rem;
  background:rgba(8,10,20,.92);
}
.app-profile-card .card-foot h3{
  margin:0; font-family:var(--font-body); font-size:.82rem; font-weight:600;
  color:#fff; line-height:1.2; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.app-profile-card .card-foot .card-line{
  display:flex; align-items:center; gap:.3rem;
  margin:.16rem 0 0; font-size:.66rem; font-weight:500;
  color:rgba(255,255,255,.82); white-space:nowrap;
}
.app-profile-card .card-foot .card-line.is-sent{ color:var(--color-accent-soft); }
.app-profile-card .card-foot .card-line.is-sent svg{
  width:.72rem; height:.72rem; fill:currentColor; flex:0 0 auto;
}
.app-profile-card.av-tonight .availability-dot{ background:var(--color-accent-soft); }
.app-profile-card.av-this_week .availability-dot{ background:#8fb8d8; box-shadow:0 0 0 2px rgba(143,184,216,.2); }
.app-profile-card.av-flexible .availability-dot{ background:#9fd8b0; box-shadow:0 0 0 2px rgba(159,216,176,.2); }
/* Interest already sent: the heart turns into a quiet filled tick. It stays a
   small round control in the corner — it never covers the photograph. */
.app-profile-card .profile-select.is-sent{
  background:rgba(200,69,47,.9); border-color:rgba(255,243,234,.65);
  color:var(--color-on-accent);
}
.app-profile-card.already-sent .real-photo,
.app-profile-card.already-sent .demo-photo{ opacity:1; }
@media (max-width:700px){
  .app-profile-card{ aspect-ratio:auto; }
  .app-profile-card .card-foot{ padding:.3rem .36rem .34rem; }
  .app-profile-card .card-foot h3{ font-size:.74rem; }
  .app-profile-card .card-foot .card-line{ font-size:.6rem; }
}

/* --- 3 + 4. chat --------------------------------------------------- */
.chat-header .chat-who{ display:flex; align-items:center; gap:.55rem; min-width:0; }
.chat-header .chat-who img,
.chat-header .chat-who .match-avatar{
  width:2.1rem; height:2.1rem; flex:0 0 auto;
  border-radius:var(--radius-full); object-fit:cover;
  display:grid; place-items:center; background:var(--color-surface-2);
  font-family:var(--font-display); font-size:1rem; color:var(--color-accent-soft);
}
.chat-header .chat-who strong{
  font-size:1rem; font-weight:600; color:#fff;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}

.message-list{ gap:.34rem; padding-bottom:var(--space-4); }
.msg-row{ display:flex; align-items:flex-end; gap:.32rem; max-width:100%; }
.msg-row.mine{ flex-direction:row-reverse; align-self:flex-end; }
.msg-row.theirs{ align-self:flex-start; }
.msg-row .bubble{
  max-width:min(78vw,20rem); position:relative;
  padding:.5rem .75rem .42rem; border-radius:1.15rem;
  font-size:.95rem; line-height:1.4; cursor:default;
  -webkit-user-select:none; user-select:none;
}
.msg-row .bubble .bubble-text{ display:inline; }
.msg-row .bubble small{
  display:block; margin-top:.14rem; font-size:.64rem; opacity:.72; text-align:right;
}
/* Mine: coral, tail bottom right. Theirs: a dark grey that reads as a bubble
   against the page rather than a white card, tail bottom left. */
.msg-row.mine .bubble{
  background:var(--color-accent); color:var(--color-on-accent);
  border:0; border-bottom-right-radius:.35rem;
}
.msg-row.theirs .bubble{
  background:#232838; color:#fff;
  border:1px solid rgba(255,255,255,.09); border-bottom-left-radius:.35rem;
}
.msg-row.mine .bubble:after,
.msg-row.theirs .bubble:after{
  content:''; position:absolute; bottom:0; width:.62rem; height:.62rem;
}
.msg-row.mine .bubble:after{
  right:-.16rem; background:var(--color-accent);
  clip-path:polygon(0 0,100% 100%,0 100%);
}
.msg-row.theirs .bubble:after{
  left:-.16rem; background:#232838;
  clip-path:polygon(100% 0,100% 100%,0 100%);
}
/* The heart. Faint until you use it, so the thread stays calm. */
.like-btn{
  flex:0 0 auto; width:1.5rem; height:1.5rem; padding:0;
  display:grid; place-items:center; border:0; background:none; cursor:pointer;
  color:rgba(255,255,255,.3); opacity:.55;
  transition:opacity var(--transition-interactive), color var(--transition-interactive), transform var(--transition-interactive);
}
.like-btn svg{ width:.95rem; height:.95rem; fill:currentColor; display:block; }
.like-btn:hover{ opacity:1; color:var(--color-accent-soft); transform:scale(1.12); }
.like-btn.on{ opacity:1; color:var(--color-accent); }
.msg-row.is-liked .bubble{ margin-bottom:.42rem; }
.bubble-heart{
  position:absolute; bottom:-.5rem; z-index:2;
  width:1.15rem; height:1.15rem; display:grid; place-items:center;
  border-radius:var(--radius-full);
  background:#232838; border:1px solid rgba(255,255,255,.14);
  color:var(--color-accent-soft);
}
.msg-row.mine .bubble-heart{ left:-.35rem; }
.msg-row.theirs .bubble-heart{ right:-.35rem; }
.bubble-heart svg{ width:.6rem; height:.6rem; fill:currentColor; display:block; }
.bubble-heart.mine{ color:var(--color-accent); }

/* Compose: dark field, white text, visible caret. The shared .input styling
   made this white-on-white on a phone. */
.chat-compose{ align-items:center; gap:.5rem; background:rgba(8,10,20,.96); }
.chat-compose input.chat-input{
  flex:1 1 auto; min-width:0; height:2.75rem;
  padding:0 1rem; border-radius:var(--radius-full);
  background:#1a1f30 !important;
  border:1px solid rgba(255,255,255,.14) !important;
  color:#fff !important;
  -webkit-text-fill-color:#fff;
  caret-color:var(--color-accent-soft);
  font-family:var(--font-body); font-size:.95rem;
  box-shadow:none;
}
.chat-compose input.chat-input::placeholder{ color:rgba(255,255,255,.45); -webkit-text-fill-color:rgba(255,255,255,.45); }
.chat-compose input.chat-input:focus{
  outline:none; border-color:rgba(240,161,115,.55) !important;
  box-shadow:0 0 0 2px rgba(240,161,115,.14);
}
.chat-compose .send-btn{
  flex:0 0 auto; width:2.5rem; height:2.5rem; border:0; padding:0;
  border-radius:var(--radius-full); display:grid; place-items:center;
  background:var(--color-accent); color:var(--color-on-accent); cursor:pointer;
}
.chat-compose .send-btn svg{ width:1.05rem; height:1.05rem; display:block; }
.chat-compose .send-btn:hover{ filter:brightness(1.08); }

/* --- 5. activate screen -------------------------------------------- */
.activation-page .activation-card{
  flex:1 1 auto; display:flex; flex-direction:column; justify-content:center;
  padding:var(--space-5) var(--space-5) var(--space-8);
}
.activation-page .activation-card h1{
  font-family:var(--font-display); font-size:2rem; line-height:1.14;
  margin:0 0 var(--space-4); text-align:center;
}
.activate-who{
  display:flex; align-items:center; gap:.7rem; justify-content:center;
  margin:0 auto var(--space-5); padding:.5rem .85rem .5rem .55rem;
  border:1px solid var(--color-border); border-radius:var(--radius-full);
  background:rgba(20,24,41,.72);
}
.activate-who img, .activate-who .match-avatar{
  width:2.6rem; height:2.6rem; flex:0 0 auto; border-radius:var(--radius-full);
  object-fit:cover; display:grid; place-items:center;
  background:var(--color-surface-2); font-family:var(--font-display);
  font-size:1.1rem; color:var(--color-accent-soft);
}
.activate-who span{ display:flex; flex-direction:column; gap:.1rem; text-align:left; }
.activate-who strong{ font-size:.95rem; font-weight:600; color:#fff; }
.activate-who small{ font-size:.72rem; color:var(--color-text-muted); }
.coral-btn.is-busy{ opacity:.72; cursor:progress; }

/* onboarding: the "pick one" line under the availability question */
.form-hint{ margin:.15rem 0 var(--space-4); font-size:.82rem; color:var(--color-text-muted); }

/* The activate screen sat hard under the logo with a tall empty space beneath
   it. Let the page fill the shell so the card can centre itself. */
.inside-shell .activation-page{ flex:1 1 auto; display:flex; flex-direction:column; }
.activation-page .activation-card{ margin-top:0; }

/* The thread never filled the screen: the compose row stopped wherever the last
   message ended and left a slab of black between it and the bottom bar. The
   page is now a full-height column — header, scrolling messages, compose
   sitting just above the nav. */
.inside-shell .chat-page{
  flex:1 1 auto; display:flex; flex-direction:column; min-height:0;
}
.chat-page .message-list{ flex:1 1 auto; min-height:0; overflow-y:auto; }
.chat-page .chat-compose{ margin-top:auto; }
.inside-shell.with-nav:has(.chat-page){ padding-bottom:0; }
.inside-shell.with-nav .chat-page{ padding-bottom:5.4rem; }
/* reaction badge sits on the tail side, clear of the heart button */
.msg-row.mine .bubble-heart{ left:auto; right:.7rem; bottom:-.55rem; }
.msg-row.theirs .bubble-heart{ right:auto; left:.7rem; bottom:-.55rem; }

/* The day filters sat almost on top of the first row of photographs. A hairline
   and a little more air now separate the controls from the people. */
.browse-filter-row{
  padding-bottom:.75rem; margin-bottom:.9rem;
  border-bottom:1px solid rgba(255,255,255,.3);
}

/* ---- v53 ----------------------------------------------------------------
   The three day filters were sized to their own text, so "All" was a stub
   next to "This week". On phones they now sit on the same three-column grid
   as the photographs below, sharing its .42rem gutter, so the pill edges line
   up with the photo edges. Desktop keeps text-width pills. */
@media (max-width:700px){
  .browse-filter-row{
    display:grid; grid-template-columns:repeat(3,1fr); gap:.42rem;
    flex-wrap:nowrap;
  }
  .browse-filter-row button{
    width:100%; min-width:0; flex:none;
    padding:.44rem .3rem; text-align:center; white-space:nowrap;
  }
}

/* Square browse thumbnails centre-cropped tall portraits, which cut the top of
   the head off (Patricia, Fernanda, Larissa). Bias the crop upward so the
   face keeps the frame; on wider-than-tall photos this has no effect. */
.app-profile-card .card-photo .real-photo,
.app-profile-card .card-photo .demo-photo,
.profile-card .real-photo,
.profile-card .demo-photo{ object-position:50% 22%; }

/* ==== v54 — desktop only (>=900px) =======================================
   The member screens were built phone-first and then had their width cap
   removed at 900px (.inside-page{max-width:none}), so on a laptop every card
   stretched edge to edge: "Welcome to Rio Now" and "Check your WhatsApp" ran
   the full width of the monitor, and a profile photo rendered 1312px wide by
   1968px tall — taller than two screens, so you could not see the person.
   Nothing below changes the phone layout. */
@media (min-width:900px){

  /* --- Sign in / verify / profile building: a real centred card. --- */
  .inside-page.auth-page,
  .inside-page.profile-create-page,
  .inside-page.activation-page{
    max-width:35rem; margin-inline:auto;
    padding-left:var(--space-5); padding-right:var(--space-5);
  }
  .auth-page .onboarding-card,
  .profile-create-page .onboarding-card{ max-width:29rem; margin-inline:auto; }
  .auth-page .onboarding-card h1{ font-size:2.05rem; line-height:1.12; }
  .auth-page .onboarding-card > h1 + p{ font-size:1rem; }

  /* --- Profile detail: photo beside the copy instead of a giant slab. --- */
  .inside-page.detail-page{
    max-width:62rem; margin-inline:auto; padding-top:var(--space-8);
    display:grid; grid-template-columns:22rem minmax(0,1fr);
    gap:var(--space-10); align-items:start;
  }
  .detail-page .detail-hero{
    aspect-ratio:3/4; border-radius:var(--radius-lg); position:sticky; top:var(--space-8);
  }
  .detail-page .detail-copy{ padding-top:var(--space-2); }
  .detail-page .detail-actions{ margin-top:var(--space-10); max-width:22rem; }

  /* --- Browse: let more of the sky show before the faces start. --- */
  .auth-sky.sky-browse{ height:34dvh; }
  .inside-page.browse-page{ padding-top:var(--space-8); }
  .browse-page .browse-filter-row{ margin-bottom:var(--space-6); }

  /* Matches and chats lists were also full-bleed. */
  .inside-page.list-page{ max-width:46rem; margin-inline:auto; }
}

@media (min-width:900px){
  /* The auth scrim was a left-to-right wash, built when the copy sat on the
     left edge. With the card centred it left a bright block to its right, so
     the gradient becomes a straight top-to-bottom fade. */
  .auth-page ~ .auth-sky::after,
  .inside-shell.form-screen:has(.auth-page) .auth-sky::after{
    background:
      linear-gradient(to bottom, rgba(8,10,20,.34) 0%, rgba(8,10,20,.52) 42%, rgba(8,10,20,.93) 82%, var(--color-bg) 100%);
  }
  .auth-page ~ .auth-sky.sky-short,
  .inside-shell.form-screen:has(.auth-page) .auth-sky.sky-short{ height:60dvh; }

  /* Centre the card in the window rather than parking it under the topbar. */
  .inside-shell.form-screen > .inside-page.auth-page{
    min-height:100dvh; display:flex; flex-direction:column;
  }
  .inside-page.auth-page > .app-topbar{ flex:0 0 auto; }
  .inside-page.auth-page > .onboarding-card{ margin-top:auto; margin-bottom:auto; }

  /* Name and availability belong together, not at opposite ends of a wide column. */
  .detail-page .detail-title-row{ justify-content:flex-start; gap:var(--space-4); flex-wrap:wrap; }
}

/* ── v55 ─────────────────────────────────────────────────────────────────
   Photo navigation. The only hint that a profile had three photographs was
   the 3px dot strip, which is invisible on a laptop. Arrows, a counter and
   larger dots now sit on translucent dark discs so they stay legible over
   a bright sky or a dark shirt alike. Everything is inside .detail-hero,
   which is position:relative, so it tracks the photo at every width. */
.photo-nav{
  position:absolute; top:50%; transform:translateY(-50%);
  width:2.6rem; height:2.6rem; display:grid; place-items:center;
  border:1px solid rgba(255,255,255,.34); border-radius:50%;
  background:rgba(6,8,16,.52); color:#fff; cursor:pointer; padding:0;
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  box-shadow:0 2px 10px rgba(0,0,0,.4);
  transition:background .16s ease, transform .16s ease, border-color .16s ease;
  z-index:3;
}
.photo-nav svg{ width:1.25rem; height:1.25rem; }
.photo-nav.prev{ left:.65rem; }
.photo-nav.next{ right:.65rem; }
.photo-nav:hover{ background:rgba(6,8,16,.78); border-color:rgba(255,255,255,.6); }
.photo-nav:active{ transform:translateY(-50%) scale(.94); }
.photo-count{
  position:absolute; top:.8rem; right:.8rem; z-index:3;
  font-size:.78rem; letter-spacing:.02em; color:rgba(255,255,255,.82);
  background:rgba(6,8,16,.56); border:1px solid rgba(255,255,255,.2);
  border-radius:999px; padding:.2rem .6rem; line-height:1.4;
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
}
.photo-count b{ color:#fff; font-weight:600; }
/* Larger, higher-contrast dots with a dark halo so they survive a pale photo. */
.detail-dots{ z-index:3; gap:.4rem; }
.detail-dots span{
  height:5px; border-radius:999px; background:rgba(255,255,255,.42);
  box-shadow:0 1px 3px rgba(0,0,0,.65); transition:background .16s ease, width .16s ease;
}
.detail-dots span.active{ background:#fff; }
@media (hover:none){ .photo-nav{ width:2.9rem; height:2.9rem; } }

/* In-app route back to the marketing pages, at the foot of Profile. */
.legal-links{
  display:flex; flex-wrap:wrap; align-items:center; gap:.35rem .9rem;
  margin-top:var(--space-8); padding-top:var(--space-5);
  border-top:1px solid rgba(255,255,255,.09);
}
.legal-links span{
  width:100%; font-size:.7rem; letter-spacing:.14em; text-transform:uppercase;
  color:rgba(255,255,255,.4); margin-bottom:.1rem;
}
.legal-links a{
  font-size:.85rem; color:rgba(255,255,255,.66);
  text-decoration:none; border-bottom:1px solid rgba(255,255,255,.22); padding-bottom:1px;
}
.legal-links a:hover{ color:#fff; border-bottom-color:rgba(255,255,255,.6); }

/* ── v55 · the grey left side ────────────────────────────────────────────
   .app-topbar::before is a 115%×125% radial vignette anchored to the top
   bar. On a phone the top bar is the full width, so the vignette darkens
   the whole top of the sky. In v54 I capped .inside-page at 32rem, which
   dragged the top bar — and its vignette — into a 560px column in the
   middle of a 1440px window. The result was a hard-edged dark rectangle
   from x=440 to x=1000 with undimmed, greyish photograph either side.
   Measured at 1440: pixel at x=470,y=60 was rgb(28,15,18) inside the
   vignette against rgb(80,39,38) just outside it.
   The card stays capped; the vignette goes back to full-bleed. */
@media (min-width:900px){
  .form-screen .inside-page.auth-page .app-topbar::before,
  .form-screen .inside-page.profile-create-page .app-topbar::before,
  .form-screen .inside-page.activation-page .app-topbar::before,
  .inside-page.auth-page .app-topbar::before,
  .inside-page.profile-create-page .app-topbar::before,
  .inside-page.activation-page .app-topbar::before{
    left:50%; right:auto; width:100vw; transform:translateX(-50%);
  }
}

/* The links sit at the very foot of Profile, so they need clearance above the
   fixed bottom nav — otherwise they render underneath it and look missing. */
.legal-links{ margin-bottom:var(--space-10); }
@media (min-width:900px){
  /* Profile was still full-bleed on a laptop; match the Matches/Chats column. */
  .inside-page.account-page{ max-width:46rem; margin-inline:auto; }
}

/* ── v57 · alerts ────────────────────────────────────────────────────────
   One question, asked once on Browse, dismissed by answering it either way.
   Deliberately quieter than the v56 card it replaces: it is a preference,
   not a gate, so it should not look like a wall in front of the grid. */
.alerts-card{
  margin:0 0 var(--space-6); padding:var(--space-6);
  border:1px solid rgba(255,255,255,.14); border-radius:var(--radius-lg);
  background:linear-gradient(180deg, rgba(22,24,38,.92), rgba(12,14,24,.92));
  box-shadow:0 10px 34px rgba(0,0,0,.42);
}
.alerts-card h2{ margin:0 0 .35rem; font-size:1.12rem; line-height:1.25; }
.alerts-card > p{ margin:0 0 var(--space-6); font-size:.86rem; line-height:1.5; color:rgba(255,255,255,.62); }
.alert-actions{ display:flex; align-items:center; gap:var(--space-5); flex-wrap:wrap; }
.alert-actions .coral-btn{ flex:1 1 12rem; margin:0; }
.alert-skip{
  background:none; border:0; cursor:pointer; padding:.4rem .2rem;
  font-size:.85rem; color:rgba(255,255,255,.55); text-decoration:underline;
  text-underline-offset:3px;
}
.alert-skip:hover{ color:rgba(255,255,255,.85); }
@media (min-width:900px){
  /* Full width above a five-column grid reads as a barrier. Keep it to about
     two columns so it sits there as a note. */
  .alerts-card{ max-width:34rem; }
}
/* The choice cards on /alerts carry a line of explanation under the label. */
.choice-card em{
  display:block; font-style:normal; margin-top:.2rem;
  font-size:.8rem; line-height:1.45; color:rgba(255,255,255,.55);
}
.choice-card.active em{ color:rgba(255,255,255,.68); }

/* The Show-more control under the Browse grid. */
.browse-more{ margin:var(--space-6) 0 var(--space-8); text-align:center; }
.browse-more .ghost-btn{
  display:inline-block; padding:.7rem 1.6rem; border-radius:var(--radius-full);
  border:1px solid rgba(255,255,255,.22); background:rgba(255,255,255,.04);
  color:#fff; font-size:.9rem; cursor:pointer;
}
.browse-more .ghost-btn:hover{ background:rgba(255,255,255,.09); border-color:rgba(255,255,255,.34); }
.browse-more p{ margin:.6rem 0 0; font-size:.78rem; color:rgba(255,255,255,.45); }
/* The footnote under the alert choices tracked some narrower inherited width
   and wrapped after four words while the cards beside it were 353px. Match it
   to the choice stack. */
.settings-page .form-note{
  max-width:29rem; margin:var(--space-5) 0 0;
  font-size:.8rem; line-height:1.5; color:rgba(255,255,255,.5);
}
.settings-page .choice-stack{ max-width:29rem; }

/* ═══════════════════════════════════════════════════════════════════════════
   v59 — one product, not five screens
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1 ── The sky now sits behind Matches, Chats, Profile and the profile detail
   as well as Browse. Those pages carry .browse-shell so the existing
   `.inside-shell.browse-shell > .inside-page{z-index:2}` rule already lifts
   their content clear; all that is missing is room for the logo row and a
   heading that starts below the brightest part of the photograph. */
.list-page > .browse-top,
.account-page > .browse-top,
.detail-page > .browse-top{ padding:var(--space-4) 0 var(--space-2); }
.list-page > .list-header,
.account-page > .list-header{ padding-left:0; padding-right:0; padding-top:var(--space-2); }

/* 2 ── The heart, once.
   .bubble-heart is no longer emitted. The button beside the bubble is the whole
   indicator: hollow when nobody liked it, coral when the like is mine, warm
   grey when it is theirs — so you can still tell the two apart at a glance. */
.like-btn.theirs{ opacity:1; color:rgba(255,255,255,.62); }
.msg-row.is-liked .bubble{ margin-bottom:0; }

/* 3 ── Age as a menu rather than a text field. Native <select>, so a phone
   opens its own wheel and a laptop still accepts typed digits. The chevron is
   drawn in the background because appearance:none removes the browser's. */
.age-select{
  width:100%; padding:.72rem 2.1rem .72rem .8rem; border-radius:var(--radius-md);
  background:rgba(13,16,32,.82); border:1px solid rgba(255,255,255,.6);
  color:var(--color-text); font-family:var(--font-body); font-size:1rem;
  -webkit-appearance:none; appearance:none; cursor:pointer;
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right .7rem center; background-size:1rem;
}
.age-select:focus{ border-color:var(--color-accent); outline:none; }
/* The dropdown list itself is drawn by the OS; only these two properties
   carry into it, and without them a dark-theme select shows black on black. */
.age-select option{ background:#151a2b; color:#fff; }

/* 4 ── The filter sheet keeps the sunset instead of a flat black wash. */
.filter-backdrop{ overflow:hidden; background:rgba(2,3,8,.55); }
.filter-backdrop img{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; object-position:50% 38%;
  opacity:.5; filter:blur(3px); transform:scale(1.06);
}
.filter-backdrop::after{
  content:''; position:absolute; inset:0;
  background:linear-gradient(to bottom, rgba(8,10,20,.45) 0%, rgba(8,10,20,.78) 100%);
}

/* 6 ── Profile detail on a laptop.
   It was a narrow column pinned to the left of an empty page. The card is now
   centred with a real width, the photo is a sane shape rather than a tower,
   and the sky and logo match every other screen. Phones are untouched — the
   card is simply full width there. */
.detail-card{ width:100%; }
@media (min-width:900px){
  /* The two-column split (photo | copy) used to live on .inside-page itself.
     The page now also carries the logo row and the footer, and those are not
     columns — so the grid moves down onto .detail-card and the page becomes a
     plain centred stack again. Without this the logo and footer were being
     treated as grid cells and shoved the whole card off to the right. */
  .inside-page.detail-page{
    display:block; max-width:64rem; margin-inline:auto;
    padding-top:var(--space-5);
  }
  .detail-page > .detail-card{
    display:grid; grid-template-columns:22rem minmax(0,1fr);
    gap:var(--space-10); align-items:start;
    margin-top:var(--space-6);
  }
  .detail-page > .detail-card > .detail-hero{
    aspect-ratio:3/4; border-radius:var(--radius-lg);
    position:sticky; top:var(--space-6);
  }
  .detail-page > .detail-card > .detail-copy{ padding:0; }
}

/* 7 ── Chat list previews. "You:" is dimmed so the message itself leads, and
   the line is clipped rather than wrapped so every row stays the same height. */
.match-main small{
  display:block; max-width:100%;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.preview-you{ font-style:normal; color:rgba(255,255,255,.42); }
/* An unread preview must not be quieter than a read one: this sits after the
   rule at 1572 and was overriding it back to plain white. */
.match-list-row.is-unread .match-main small{ color:var(--color-accent-soft); font-weight:600; }
.match-list-row.is-unread .match-main strong{ color:#fff; }

/* 8 ── On the list, account and detail screens the sky has no grid of cards
   sitting on top of it, so the same 34dvh crop that reads well on Browse left
   headings floating on bright orange. Shorter and dimmer on those four. */
.auth-sky.sky-browse.sky-soft{ height:19dvh; }
.auth-sky.sky-browse.sky-soft::after{
  background:linear-gradient(to bottom, rgba(8,10,20,.55) 0%, rgba(8,10,20,.66) 38%, rgba(8,10,20,.93) 76%, var(--color-bg) 100%);
}
@media (min-width:900px){
  .auth-sky.sky-browse.sky-soft{ height:26dvh; }
}

/* 9 ── The thread on a laptop.
   Bubbles were anchored to the far left and far right of a 1400px page, so a
   two-word reply sat half a screen away from the message it answered. The
   conversation now runs in a readable column, the way it does on a phone. */
@media (min-width:900px){
  /* The column goes on the containers, not on each row: capping the rows
     individually made every bubble centre itself, which destroyed the
     left-is-them / right-is-you reading of the thread. */
  .chat-page .message-list,
  .chat-page .chat-compose{ max-width:46rem; margin-inline:auto; width:100%; }
  /* v68 — the header was the one part of the thread still running the full
     width of the window, which pushed the safety control into the far top-right
     corner, a long way from the conversation it belongs to and easy to miss
     entirely. Putting the header in the same 46rem column brings it back to the
     edge of the messages, where the eye already is. */
  .chat-page .chat-header{ max-width:46rem; margin-inline:auto; width:100%; }
  /* And make it look like a control rather than three faint dots. */
  .chat-page .chat-safety{
    width:2.4rem; height:2.4rem;
    border:1px solid rgba(255,255,255,.34);
    background:rgba(255,255,255,.07);
    color:#fff;
  }
  .chat-page .chat-safety:hover{ background:rgba(255,255,255,.16); border-color:rgba(255,255,255,.55); }
  /* Two hairlines and a barely-there wash, so the column reads as a defined
     space instead of text floating in the middle of a very wide dark window.
     Deliberately faint — the point is to bound the conversation, not to draw
     a box that competes with the messages inside it. */
  .inside-shell .chat-page{
    max-width:46rem; margin-inline:auto; width:100%;
    border-left:1px solid rgba(255,255,255,.07);
    border-right:1px solid rgba(255,255,255,.07);
    background:rgba(255,255,255,.012);
  }
}

/* ── v61: an unread thread you cannot miss in a list of seven ──────────────
   Four independent signals, so it survives a bright phone screen outdoors and
   does not depend on colour alone: position (unread sorts to the top), a
   tinted row with a coral edge, a counted pill, and heavier type. */
.match-list-row.is-unread{
  position:relative;
  background:linear-gradient(90deg, rgba(224,90,58,.14) 0%, rgba(224,90,58,.045) 42%, transparent 100%);
  border-radius:var(--radius-md);
  padding-left:.85rem;
}
.match-list-row.is-unread::before{
  content:''; position:absolute; left:0; top:.55rem; bottom:.55rem;
  width:3px; border-radius:var(--radius-full); background:var(--color-accent);
}
.match-list-row.is-unread .match-main strong{ color:#fff; font-weight:700; }
.unread-pill{
  display:inline-grid; place-items:center; min-width:1.4rem; height:1.4rem;
  padding:0 .38rem; border-radius:var(--radius-full);
  background:var(--color-accent); color:#fff;
  font-style:normal; font-size:.75rem; font-weight:700; line-height:1;
  box-shadow:0 2px 8px rgba(224,90,58,.45);
}

/* ── v62: age moved out of the sheet and onto Browse ───────────────────────
   It sits directly under the day chips and reads as one sentence: Age 18 – 99.
   The selects shrink to their content instead of inheriting the full-width
   form styling they had inside the sheet. */
.browse-age-row{
  display:flex; align-items:center; flex-wrap:wrap; gap:.4rem;
  margin:0 0 var(--space-5);
}
.browse-age-row .age-lead{
  font-size:.72rem; letter-spacing:.14em; text-transform:uppercase;
  color:rgba(255,255,255,.5); margin-right:.35rem;
}
/* v63 — shorter. These were 33px tall and read as buttons competing with the
   day chips above them; they are a quiet secondary control and should sit
   lower in the hierarchy. Now ~26px. */
.browse-age-row .age-select{
  width:auto; min-width:3.6rem; padding:.2rem 1.5rem .2rem .55rem;
  font-size:.86rem; line-height:1.25; border-radius:var(--radius-full);
  border-color:rgba(255,255,255,.22); background-color:rgba(13,16,32,.6);
  background-size:.75rem; background-position:right .45rem center;
}
.browse-age-row .age-dash{ color:rgba(255,255,255,.45); padding:0 .1rem; }
.age-reset{
  margin-left:auto; background:none; border:0; cursor:pointer;
  color:var(--color-accent); font-family:var(--font-body);
  font-size:.82rem; padding:.3rem .1rem;
}
.age-reset:hover{ text-decoration:underline; }
@media (min-width:900px){
  .browse-age-row{ gap:.55rem; }
  .browse-age-row .age-select{ font-size:.88rem; }
}

/* ══ v64 ═════════════════════════════════════════════════════════════════
   The age range, drawn as a range; and the safety toolkit.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── the dual-thumb slider ─────────────────────────────────────────────── */
.age-slider{ margin:0 0 var(--space-5); }
.age-slider-head{ display:flex; align-items:center; gap:.55rem; margin-bottom:.55rem; }
.age-slider .age-lead{
  font-size:.66rem; letter-spacing:.16em; text-transform:uppercase;
  color:rgba(255,255,255,.55); font-weight:600;
}
.age-slider .age-value{
  font-size:.86rem; font-weight:600; color:#fff; font-variant-numeric:tabular-nums;
}
.age-slider .age-reset{
  margin-left:auto; font-size:.72rem; color:rgba(255,255,255,.7);
  text-decoration:underline; text-underline-offset:3px;
}
.age-slider .age-reset:hover{ color:#fff; }

.age-track-wrap{ position:relative; height:1.5rem; display:flex; align-items:center; }
.age-track{
  position:absolute; left:0; right:0; height:.25rem;
  border-radius:var(--radius-full); background:rgba(255,255,255,.16);
}
.age-fill{
  position:absolute; top:0; bottom:0; border-radius:var(--radius-full);
  background:var(--color-accent);
}

/* Both inputs sit on top of each other. They ignore the pointer so a press on
   the bare track does nothing; only the thumbs take it. Without this the input
   stacked on top would swallow every press across the whole width and the
   lower thumb would be unreachable. */
.age-range{
  position:absolute; left:0; width:100%; margin:0; height:1.5rem;
  -webkit-appearance:none; appearance:none; background:transparent;
  pointer-events:none;
}
.age-range:focus{ outline:none; }
.age-range::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none; pointer-events:auto;
  width:1.15rem; height:1.15rem; border-radius:50%;
  background:#fff; border:2px solid var(--color-accent);
  box-shadow:0 1px 4px rgba(0,0,0,.5); cursor:grab;
}
.age-range::-webkit-slider-thumb:active{ cursor:grabbing; transform:scale(1.08); }
.age-range::-moz-range-thumb{
  pointer-events:auto; width:1.15rem; height:1.15rem; border-radius:50%;
  background:#fff; border:2px solid var(--color-accent);
  box-shadow:0 1px 4px rgba(0,0,0,.5); cursor:grab;
}
.age-range::-moz-range-track{ background:transparent; }
.age-range:focus-visible::-webkit-slider-thumb{ box-shadow:0 0 0 3px rgba(255,255,255,.45); }
.age-range:focus-visible::-moz-range-thumb{ box-shadow:0 0 0 3px rgba(255,255,255,.45); }

/* ── the three dots, and the plus-one badge ────────────────────────────── */
.chat-header{ position:relative; }
.chat-safety{
  margin-left:auto; width:2.2rem; height:2.2rem; flex:0 0 auto;
  display:grid; place-items:center; border-radius:50%;
  color:rgba(255,255,255,.72);
}
.chat-safety svg{ width:1.15rem; height:1.15rem; }
.chat-safety:hover{ background:rgba(255,255,255,.1); color:#fff; }
.date-shared-badge{
  display:inline-flex; align-items:center; gap:.24rem; margin-left:.5rem;
  padding:.16rem .46rem; border-radius:var(--radius-full);
  background:rgba(255,255,255,.13); border:1px solid rgba(255,255,255,.2);
  font-size:.66rem; font-weight:600; letter-spacing:.02em; color:#fff; white-space:nowrap;
}
.date-shared-badge svg{ width:.78rem; height:.78rem; }

/* ── the sheet ─────────────────────────────────────────────────────────── */
.safety-sheet .sheet-scrim{
  position:fixed; inset:0; background:rgba(4,6,14,.6); border:0; padding:0;
  -webkit-backdrop-filter:blur(2px); backdrop-filter:blur(2px);
}
.safety-sheet .sheet-body{ position:relative; z-index:1; }
.safety-sheet .sheet-hint{ margin-bottom:var(--space-4); line-height:1.5; opacity:.82; }
.safety-sheet .coral-btn{ width:100%; margin-top:var(--space-4); }
.safety-sheet .text-btn{ width:100%; margin-top:.5rem; }
.safety-sheet .input{ width:100%; }
.safety-sheet .sheet-label{ margin-top:var(--space-4); }

.safety-actions{ display:flex; flex-direction:column; gap:.45rem; }
.safety-actions button{
  display:flex; align-items:flex-start; gap:.7rem; width:100%; text-align:left;
  padding:.75rem .8rem; border-radius:var(--radius-lg);
  border:1px solid rgba(255,255,255,.16); background:rgba(255,255,255,.05);
  color:#fff;
}
.safety-actions button:hover{ background:rgba(255,255,255,.1); border-color:rgba(255,255,255,.3); }
.safety-actions .sa-ico{
  flex:0 0 1.5rem; height:1.5rem; display:grid; place-items:center;
  font-size:.95rem; color:var(--color-accent);
}
.safety-actions .sa-ico svg{ width:1.05rem; height:1.05rem; }
.safety-actions strong{ display:block; font-size:.92rem; font-weight:600; line-height:1.3; }
.safety-actions small{ display:block; margin-top:.12rem; font-size:.76rem; opacity:.66; line-height:1.35; }
.safety-actions button.is-grave .sa-ico{ color:#ff7a6b; }

.report-reasons{ display:flex; flex-direction:column; gap:.4rem; }
.report-reasons button{
  width:100%; text-align:left; padding:.62rem .75rem; border-radius:var(--radius-lg);
  border:1px solid rgba(255,255,255,.16); background:rgba(255,255,255,.04); color:#fff;
}
.report-reasons button:hover{ border-color:rgba(255,255,255,.36); }
.report-reasons button.active{
  border-color:var(--color-accent); background:rgba(255,122,107,.14);
}
.report-reasons strong{ display:block; font-size:.87rem; font-weight:600; line-height:1.3; }
.report-reasons small{ display:block; margin-top:.1rem; font-size:.74rem; opacity:.62; line-height:1.35; }

.grave-list{ margin:0 0 var(--space-4); padding-left:1.05rem; }
.grave-list li{ font-size:.83rem; line-height:1.5; opacity:.85; margin-bottom:.3rem; }
.safety-sheet .coral-btn.is-grave{ background:#c8402f; }
.safety-sheet .coral-btn.is-grave:hover{ background:#b3392a; }
.safety-sheet .coral-btn[disabled]{ opacity:.45; cursor:not-allowed; }

@media (min-width:900px){
  .age-slider .age-value{ font-size:.9rem; }
  .safety-actions strong{ font-size:.95rem; }
}

/* v64 — the report box. .input was only ever styled for <input>, so the
   textarea fell through to the browser default: white, monospace, and jarring
   against everything around it. */
.safety-sheet textarea.input{
  width:100%; resize:vertical; min-height:4.2rem;
  font-family:var(--font-body); font-size:.88rem; line-height:1.45;
  color:#fff; background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.18); border-radius:var(--radius-lg);
  padding:.6rem .7rem;
}
.safety-sheet textarea.input::placeholder{ color:rgba(255,255,255,.42); }
.safety-sheet textarea.input:focus{ outline:none; border-color:var(--color-accent); background:rgba(255,255,255,.09); }
.safety-sheet input.input{
  width:100%; font-family:var(--font-body); font-size:.9rem; color:#fff;
  background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.18);
  border-radius:var(--radius-lg); padding:.58rem .7rem;
}
.safety-sheet input.input::placeholder{ color:rgba(255,255,255,.42); }
.safety-sheet input.input:focus{ outline:none; border-color:var(--color-accent); background:rgba(255,255,255,.09); }
.safety-sheet .sheet-label{ display:block; margin:var(--space-4) 0 .35rem; }

/* v64 — .sheet-switch is the toggle used on the alerts card; reused here it
   hid its own input and rendered as a bare heading, so the choice was
   invisible and unclickable. This is a plain, visible checkbox. */
.safety-check{ display:flex; align-items:flex-start; gap:.55rem; cursor:pointer; margin-top:var(--space-3); }
.safety-check input{ position:absolute; opacity:0; width:1px; height:1px; }
.safety-check .sc-box{
  flex:0 0 1.05rem; width:1.05rem; height:1.05rem; margin-top:.08rem;
  border:1px solid rgba(255,255,255,.4); border-radius:.28rem;
  background:rgba(255,255,255,.05); position:relative;
}
.safety-check .sc-text{ font-size:.83rem; line-height:1.4; opacity:.85; }
.safety-check input:checked + .sc-box{ background:var(--color-accent); border-color:var(--color-accent); }
.safety-check input:checked + .sc-box::after{
  content:''; position:absolute; left:.32rem; top:.12rem;
  width:.26rem; height:.52rem; border:solid #fff; border-width:0 2px 2px 0;
  transform:rotate(42deg);
}
.safety-check input:focus-visible + .sc-box{ box-shadow:0 0 0 3px rgba(255,255,255,.35); }
.safety-sheet .input + .sheet-hint{ margin-top:var(--space-3); }

/* v64 — a 1300px-wide slider for 81 years of age means one pixel is a fifth of
   a year, which is precision nobody wants and a lot of mouse travel to get it.
   Capped so the whole range stays inside one comfortable sweep. */
@media (min-width:900px){
  .age-slider{ max-width:22rem; }
}

/* ═══ v65 ═══════════════════════════════════════════════════════════════ */

/* Community guidelines. Long-form reading on a phone, so the measure is
   capped and the rules are set apart from the prose around them — a wall of
   identical paragraphs is how house rules go unread. */
.guidelines{ max-width:34rem; }
.guidelines h1{ margin-bottom:.9rem; }
.guidelines .g-intro{ color:var(--color-text-muted); line-height:1.6; }
.guidelines .g-lead{ margin:1.4rem 0 .8rem; font-weight:600; color:var(--color-text); }
.guidelines .g-rule,
.guidelines .g-block{
  border-left:2px solid rgba(255,255,255,.10);
  padding:.1rem 0 .1rem .95rem;
  margin:0 0 1.15rem;
}
.guidelines .g-rule strong,
.guidelines .g-block strong{
  display:block; margin-bottom:.3rem;
  font-size:1rem; letter-spacing:.01em; color:var(--color-text);
}
.guidelines .g-rule p,
.guidelines .g-block p{
  margin:0; line-height:1.6; color:var(--color-text-muted); font-size:.94rem;
}
/* The one rule with no second side to hear. Marked, not shouted. */
.guidelines .g-grave{ border-left-color:var(--color-accent); }
.guidelines .g-grave strong{ color:var(--color-accent); }
.guidelines .g-wa{ color:var(--color-accent); text-decoration:underline; text-underline-offset:2px; white-space:nowrap; }

/* The link out of the safety sheet to those rules. */
.safety-sheet .sheet-foot{ margin:1rem 0 .25rem; text-align:center; }
.safety-sheet .sheet-foot a{
  color:var(--color-text-muted); font-size:.86rem;
  text-decoration:underline; text-underline-offset:3px;
}
.safety-sheet .sheet-foot a:hover{ color:var(--color-text); }

/* The CDC art. 49 notice moved out of the payment screen and into Terms in
   v65 — the right exists whether or not it is advertised on the button, and
   Terms is where a purchase right conventionally lives. Its styling went with
   it, into the marketing stylesheet. */

/* ── v68: the moderation inbox ─────────────────────────────────────────────
   Same visual language as the rest of the app — one card per report, the
   person reported set in the strongest weight because that is what the eye is
   looking for when it scans a queue. A reviewed report stays on the screen at
   reduced contrast rather than vanishing: the record of what was decided is
   the point of having the screen. */
.report-list{ display:grid; gap:.7rem; margin:.5rem var(--space-5) 1rem; }
.report-heading{
  margin:1.4rem var(--space-5) .1rem; font-size:.78rem; font-weight:600;
  letter-spacing:.08em; text-transform:uppercase; color:var(--color-text-muted);
}
.report-card{
  padding:.85rem .9rem; border:1px solid rgba(255,255,255,.16);
  border-left:3px solid var(--color-accent);
  border-radius:var(--radius-md); background:rgba(255,255,255,.05);
}
.report-card.is-closed{ border-left-color:rgba(255,255,255,.22); opacity:.62; }
.report-top{ display:flex; align-items:baseline; justify-content:space-between; gap:.6rem; }
.report-top strong{ font-size:1rem; color:#fff; }
.report-when{ flex:0 0 auto; font-size:.72rem; color:var(--color-text-muted); }
.report-meta{ margin:.28rem 0 0; font-size:.8rem; color:rgba(255,255,255,.82); }
.report-detail{ margin:.4rem 0 0; font-size:.86rem; line-height:1.5; color:#fff; }
.report-detail em{ color:var(--color-text-muted); font-style:normal; }
.report-flag{
  margin:.5rem 0 0; font-size:.74rem; font-weight:600; letter-spacing:.04em;
  text-transform:uppercase; color:var(--color-accent);
}
.report-outcome{ margin:.5rem 0 0; font-size:.78rem; color:var(--color-text-muted); }
.report-actions{ display:flex; flex-wrap:wrap; gap:.5rem; margin-top:.75rem; }
.report-actions button{ flex:1 1 auto; min-width:9rem; font-size:.85rem; padding:.55rem .8rem; }
@media (min-width:900px){
  /* Everything on this screen shares one column, including the title and the
     intro line. Centring only the cards left the heading stranded against the
     left page margin, reading as two unrelated things on one screen. */
  .mod-page .report-list,
  .mod-page .report-heading,
  .mod-page .list-header,
  .mod-page .browse-hint,
  .mod-page .flash-note,
  .mod-page .empty-state{ max-width:44rem; margin-inline:auto; }
  .mod-page .list-header,
  .mod-page .browse-hint{ padding-inline:0; }
  /* A decision button does not need to be 640px wide to be pressed. */
  .report-actions button{ flex:0 0 auto; min-width:11rem; }
}

/* v69 — the Reports screen can now be reached by a moderator who has no member
   profile at all, so it has no bottom navigation to leave by. This is the one
   way out. */
.mod-page .legal-links{margin-top:2rem;text-align:center}
.mod-page .linklike{background:none;border:0;padding:.4rem .6rem;font:inherit;
  color:var(--color-text-muted);text-decoration:underline;text-underline-offset:.24em;cursor:pointer}
.mod-page .linklike:hover{color:var(--color-text)}

/* v92 — "Interested in", on Browse.
   Same lead-label type as the age slider above it so the two filters read as
   one block, and pills that borrow the day-chip treatment rather than
   inventing a third button style. Left-aligned and auto-width: three short
   words stretched full-width looked like a second row of day filters. */
.show-me{ margin:0 0 var(--space-4); }
.show-me .show-me-lead{
  display:block; margin-bottom:.5rem;
  font-size:.66rem; letter-spacing:.16em; text-transform:uppercase;
  color:rgba(255,255,255,.55); font-weight:600;
}
.show-me-pills{ display:flex; gap:.5rem; flex-wrap:wrap; }
.show-me-pills button{
  padding:.5rem .95rem; border-radius:var(--radius-full);
  border:1px solid rgba(255,255,255,.42); color:#fff;
  font-size:.82rem; font-weight:500; white-space:nowrap; cursor:pointer;
  transition:border-color var(--transition-interactive), background var(--transition-interactive);
}
.show-me-pills button:hover{ border-color:#fff; }
.show-me-pills button.active{
  background:var(--color-accent); border-color:var(--color-accent);
  color:var(--color-on-accent); font-weight:600;
}

/* v92 — photo slots that have not downloaded yet.
   The carousel now draws every slot immediately so the arrows and the counter
   are there from the first frame; the ones still downloading show the Browse
   thumbnail blurred, which reads as a photo developing rather than as a
   duplicate. Each is replaced by the real image when it lands. */
.detail-photo.pending{ filter:blur(14px) brightness(.82); transform:scale(1.06); }

/* ── v94 — desktop breathing room, and the filters laid across the width ────
   On a 1330px screen the day chips, "Interested in" and the age slider were
   three stacked rows crammed under the logo, with two thirds of the width
   empty to their right, and the first of them starting 6px below the mark.
   On desktop they now sit side by side on one line, bottom-aligned, and the
   logo gets real air under it. Phones are untouched: below 900px this whole
   block does nothing and the rows stay stacked. */
@media (min-width:900px){
  .browse-top{ padding:1.5rem 0 3rem; }
  .list-page > .browse-top,
  .account-page > .browse-top,
  .detail-page > .browse-top{ padding:1.5rem 0 3rem; }
  /* v96 — side by side across the width read as three unrelated things on a
     laptop. They stack again, hard against the left margin, with pills big
     enough to be worth aiming at and the age slider kept to the width of the
     chip rows above it rather than running across the whole page. */
  .browse-controls{ display:block; margin-bottom:var(--space-6); }
  .browse-controls > *{ margin:0 0 .85rem; }
  .browse-controls > *:last-child{ margin-bottom:0; }
  .browse-controls .browse-filter-row{
    flex-wrap:nowrap; justify-content:flex-start; gap:.6rem;
    padding-bottom:0; border-bottom:0;
  }
  .browse-controls .browse-filter-row button{
    flex:0 0 auto; padding:.8rem 1.9rem; font-size:1rem;
  }
  .browse-controls .age-slider{ max-width:24rem; }
}

/* v96 — visiting / lives here, a second chip row under the availability one.
   On phones it shares the photo grid's gutter like the row above it, but two
   across instead of three. The rule that draws a hairline under the filters
   moves to whichever row is last, so there is one divider, not two. */
.browse-page .browse-filter-row:not(.browse-where-row){
  border-bottom:0; padding-bottom:0; margin-bottom:.5rem;
}
@media (max-width:700px){
  .browse-where-row{ grid-template-columns:repeat(2,1fr); }
}

/* v97 — the filter block had no name and ran straight into the photo grid.
   A small-caps FILTERS eyebrow with a hairline running off to the right of
   it, matching the AGE RANGE label already used inside the slider, and the
   existing hairline below the last chip row closes the area off. */
.filters-head{
  display:flex; align-items:center; gap:.75rem;
  margin:0 0 .85rem;
}
.filters-head span{
  font-size:.66rem; letter-spacing:.16em; text-transform:uppercase;
  color:rgba(255,255,255,.55); font-weight:600; flex:0 0 auto;
}
.filters-head i{
  flex:1 1 auto; height:1px; display:block;
  background:linear-gradient(to right,rgba(255,255,255,.16),rgba(255,255,255,0));
}
@media (min-width:900px){
  .browse-controls .filters-head{ max-width:24rem; }
}

/* v98 — FILTERS read smaller on a laptop than on a phone, because .66rem is
   a bigger share of a 360px screen than of a 1330px one. On desktop only it
   goes up to .82rem with a touch more tracking, and the hairline drops to sit
   on the label's baseline rather than its middle. */
@media (min-width:900px){
  .browse-controls .filters-head{ gap:.9rem; margin-bottom:1rem; }
  .browse-controls .filters-head span{ font-size:.82rem; letter-spacing:.19em; }
}

/* v99 — .82rem was still a 2.5px change and read as no change at all. On
   desktop the label is now 1.2rem, brighter, and tracked more tightly, since
   at that size wide tracking starts to look like a caption again. */
@media (min-width:900px){
  .browse-controls .filters-head{ gap:1rem; margin-bottom:1.15rem; }
  .browse-controls .filters-head span{
    font-size:1.2rem; letter-spacing:.11em; font-weight:600;
    color:rgba(255,255,255,.82);
  }
}

/* v100 — each chip row now says what it does, as one sentence broken across
   the block: "Show me people available / Tonight This week Flexible / Who are
   / Visiting Live here". Sentence case, not small caps, so it reads as prose
   under the FILTERS heading instead of competing with it. */
.filter-sublabel{
  font-size:.82rem; color:rgba(255,255,255,.6);
  margin:0 0 .5rem; line-height:1.3;
}
.browse-controls > .filter-sublabel + .browse-filter-row{ margin-bottom:.9rem; }
@media (min-width:900px){
  .browse-controls .filter-sublabel{ font-size:.95rem; margin-bottom:.6rem; }
  .browse-controls > .filter-sublabel:not(:first-of-type){ margin-top:.35rem; }
}

/* v101 — the hairline under the last chip row was a phone-only leftover from
   when the chips were the whole filter block. Desktop never drew it, and the
   FILTERS rule at the top already opens the area, so it goes. */
.browse-page .browse-filter-row,
.browse-page .browse-filter-row.browse-where-row{
  border-bottom:0; padding-bottom:0; margin-bottom:.5rem;
}

/* v103 — a standing complaint, fixed properly this time: the small labels on
   the member screens were authored at phone sizes and never scaled up, so on
   a 1330px laptop AGE RANGE was the same 10.6px it is on a 360px phone and
   read as fine print. Every recurring micro-label on desktop now steps up by
   roughly the same 1.5–1.8x the FILTERS heading already uses. Mobile is
   untouched — these are all inside @media (min-width:900px). */
@media (min-width:900px){
  .age-slider .age-lead{ font-size:1rem; letter-spacing:.13em; }
  .age-slider .age-value{ font-size:1.2rem; }
  .age-slider .age-reset{ font-size:.92rem; }
  .age-slider-head{ gap:.7rem; margin-bottom:.7rem; }
  .browse-controls .filter-sublabel{ font-size:1.05rem; }
  .browse-age-row .age-lead{ font-size:1rem; letter-spacing:.13em; }
  .filter-row-label,
  .sheet-label,
  .grid-divider{ font-size:.95rem; letter-spacing:.1em; }
  .detail-about label,
  .about-block label{ font-size:.95rem; letter-spacing:.09em; }
  .stat-row{ font-size:1.02rem; }
}

/* v105 — on a phone the page title sat 8px under the wordmark on Matches,
   Chats and Profile, so "Chats" read as part of the lockup rather than as the
   heading of the screen. The gap is now 28px on those screens. Desktop is
   untouched: it already got its own air in v94. */
@media (max-width:899px){
  .list-page > .browse-top,
  .account-page > .browse-top,
  .detail-page > .browse-top{ padding-bottom:var(--space-4); }
  .list-page > .list-header,
  .account-page > .list-header{ padding-top:var(--space-3); }
}

/* ============================================================
   v117 — the logo inside the app, one size up on the phone, to
   match the marketing pages. Same lockup, same spacing.
   ============================================================ */
.brand-mark{ width:26px; height:26px; }
.brand-words{ font-size:1.5rem; }
.brand-word{ font-size:1.6rem; }
.brand-lockup .brand-mark{ width:30px; height:30px; }

/* v125 — on a phone the FILTERS block started immediately under the Rio Now
   wordmark on Browse, so the two read as one lockup. 34px of air between
   them. Desktop already has its own spacing and is untouched. */
@media (max-width:899px){
  .browse-page .browse-controls{ margin-top:34px !important; }
}

/* ══ v128 ═══════════════════════════════════════════════════════════════════
   Four desktop complaints, all measured on a 1330×860 laptop:
   the six code boxes were invisible, the alerts card was invisible, every
   screen sat on a different horizontal axis, and My Profile was a ragged
   column. Nothing below touches the phone layout except where noted. */

/* --- 1. The six code boxes ------------------------------------------------
   They were a 1px rgba(255,255,255,.16) hairline over a photograph of a
   mountain at dusk: on a laptop you could not tell there were six of them.
   Solid ink, a real border, and the accent on the box you are typing into. */
.otp-card .otp-boxes span,
.otp-boxes span{
  background:rgba(4,6,14,.94);
  border:2px solid rgba(247,239,227,.58);
  box-shadow:0 2px 14px rgba(0,0,0,.5);
  color:var(--color-text);
}
.otp-card .otp-boxes span.filled,
.otp-boxes span.filled{
  background:rgba(10,13,26,.97);
  border-color:var(--color-accent-soft);
}
.otp-card .otp-boxes span.active,
.otp-boxes span.active{
  border-color:var(--color-accent-soft);
  box-shadow:0 0 0 4px rgba(240,161,115,.24), 0 2px 14px rgba(0,0,0,.5);
}
@media (min-width:900px){
  .otp-boxes{ gap:.7rem; }
  .otp-boxes span{ height:4.4rem; font-size:2rem; }
}

/* --- 2. The alerts choice -------------------------------------------------
   Same problem: a .14 border and .62 body text over a dark gradient. This is
   the one question the app asks, so it should be readable first time. */
.alerts-card{
  border:1px solid rgba(247,239,227,.34);
  background:linear-gradient(180deg, rgba(28,31,48,.96), rgba(14,17,29,.96));
  box-shadow:0 14px 40px rgba(0,0,0,.5);
}
.alerts-card h2{ font-size:1.22rem; color:var(--color-text); }
.alerts-card > p{ color:rgba(247,239,227,.86); font-size:.92rem; }
.alert-skip{ color:rgba(247,239,227,.8); }
.alert-skip:hover{ color:var(--color-text); }
@media (min-width:900px){
  .alerts-card{ max-width:none; padding:var(--space-7); }
  .alerts-card > p{ max-width:64ch; }
}

/* --- 3. One centre line on desktop ---------------------------------------
   Sign-in, profile detail and the two lists were centred (v54); Browse, My
   Profile, settings, chat and the moderation inbox still inherited
   .inside-page{max-width:none} and so started at the left window edge. Every
   member screen now shares an axis. */
@media (min-width:900px){
  .inside-page.browse-page{ max-width:62rem; margin-inline:auto; }
  .inside-page.account-page,
  .inside-page.settings-page,
  .inside-page.chat-page,
  .inside-page.mod-page{ max-width:46rem; margin-inline:auto; }
  /* The bottom bar is the one thing that should stay full width, but its
     buttons belong over the centred column. */
  .nav-bottom{ max-width:none; }
  .nav-bottom > *{ }
}

/* --- 4. My Profile ------------------------------------------------------
   The heading sat at the page edge while the card, the detail rows and the
   duration card each carried their own var(--space-5) side margin, so four
   different left edges ran down the screen. One edge now. */
.account-page .account-card,
.account-page .account-details,
.account-page .pass-card,
.account-page .account-note,
.account-page .renew-card{ margin-left:0; margin-right:0; }
.account-page .settings-list{ padding-left:0; padding-right:0; }

/* Height / weight / languages read as a run-on sentence because the label and
   the value had identical weight and no separation. Two columns, quiet label,
   bright value. */
.account-details{ padding-top:var(--space-4); }
.account-details > div{
  display:flex; align-items:baseline; gap:.5rem; padding:.3rem 0;
  color:rgba(247,239,227,.66); font-size:.92rem;
}
.account-details > div strong{
  color:var(--color-text); font-weight:600; font-size:1rem;
}
@media (min-width:900px){
  .account-page .list-header h1{ font-size:2.4rem; }
  .account-page .account-card{ padding:var(--space-5); }
  .account-page .account-card img{ width:4.6rem; height:4.6rem; }
  .account-page .account-card h2{ font-size:1.6rem; }
  .account-details > div{ font-size:.98rem; padding:.42rem 0; }
  .account-details > div strong{ font-size:1.06rem; }
  .account-page .settings-row{ padding:1.15rem 0; font-size:1.05rem; }
}

/* The onboarding cards were sized to their content, not to their max-width, so
   on a laptop the "Check your WhatsApp" card was 250px wide inside a 464px cap
   and the six code boxes came out 32px wide by 70px tall — a row of slots. */
@media (min-width:900px){
  .auth-page .onboarding-card,
  .profile-create-page .onboarding-card,
  .activation-page .onboarding-card{ width:100%; }
  .otp-boxes span{ height:4rem; font-size:1.9rem; }
}

/* ── v131 · the swipe deck ──────────────────────────────────────────────────
   One card at a time, the next photograph directly underneath so it appears
   the instant the top card moves. The deck is a fixed aspect box rather than
   a viewport-height panel, so the filters above it and the nav below it keep
   their place on both the phone and the laptop. */
.deck-wrap{ position:relative; margin:.55rem 0 0; }
.deck{
  position:relative; width:100%; aspect-ratio:3/4;
  max-height:min(58vh,34rem);
  touch-action:pan-y; margin-bottom:.2rem;
}
.deck-card{
  position:absolute; inset:0; border-radius:var(--radius-md,14px); overflow:hidden;
  background:var(--color-surface); border:1px solid rgba(247,239,227,.12);
  box-shadow:0 18px 42px rgba(0,0,0,.5);
  will-change:transform; user-select:none; -webkit-user-select:none;
  -webkit-tap-highlight-color:transparent;
}
.deck-card:not(.is-top){ pointer-events:none; }
.deck-card.is-top{ cursor:grab; }
.deck-card .card-photo{ position:absolute; inset:0; }
.deck-card .real-photo{ width:100%; height:100%; object-fit:cover; display:block; }
.deck-card .demo-photo{
  width:100%; height:100%; display:grid; place-items:center;
  font-family:var(--font-display); font-size:4.2rem; color:var(--color-accent-soft);
  background:linear-gradient(160deg,#141830,#0b0e1c);
}
.deck-card::after{
  content:''; position:absolute; left:0; right:0; bottom:0; height:52%;
  background:linear-gradient(to top,rgba(4,6,14,.94),rgba(4,6,14,.5) 45%,transparent);
  pointer-events:none; z-index:2;
}
.deck-info{ position:absolute; left:1rem; right:1rem; bottom:.95rem; z-index:3; }
.deck-info h3{ font-family:var(--font-display); font-size:1.75rem; line-height:1.05; color:#fff; margin:0 0 .28rem; font-weight:400; }
.deck-info .card-line{ display:flex; align-items:center; gap:.4rem; margin:0; font-size:.85rem; color:rgba(247,239,227,.84); }
.deck-stamp{
  position:absolute; top:1.05rem; z-index:4; opacity:0;
  font-size:.95rem; font-weight:700; letter-spacing:.16em;
  padding:.34rem .66rem; border-radius:.45rem; border:2px solid; background:rgba(4,6,14,.28);
}
.deck-stamp.yes{ left:1rem; color:#63d68f; border-color:#63d68f; transform:rotate(-12deg); }
.deck-stamp.no{ right:1rem; color:#ff6f61; border-color:#ff6f61; transform:rotate(12deg); }
.deck-actions{ display:flex; justify-content:center; gap:1.5rem; margin:.85rem 0 .45rem; }
.deck-btn{
  width:3.5rem; height:3.5rem; border-radius:50%; display:grid; place-items:center;
  border:1px solid rgba(247,239,227,.24); background:rgba(13,16,32,.92); color:#fff; cursor:pointer;
  transition:transform .12s ease, background .18s ease;
}
.deck-btn:active{ transform:scale(.94); }
.deck-btn svg{ width:22px; height:22px; fill:currentColor; display:block; }
.deck-btn.pass{ color:#ff8f84; }
.deck-btn.like{ background:var(--color-accent); border-color:var(--color-accent); color:var(--color-on-accent,#fff); }
.deck-count{
  text-align:center; margin:0 0 var(--space-5); font-size:.72rem;
  letter-spacing:.14em; text-transform:uppercase; color:rgba(247,239,227,.5);
}
.deck-empty{ display:grid; gap:.55rem; justify-items:center; text-align:center; }
.deck-empty .ghost-btn{ margin-top:.5rem; width:auto; padding:.7rem 1.2rem; }

/* The teaching overlay, first visit only. It leaves the moment a thumb lands
   on the card, and the card itself rocks twice so the photograph underneath
   is seen rather than described. */
.deck-coach{
  position:absolute; inset:0; z-index:6; border-radius:inherit;
  display:flex; align-items:center; justify-content:space-between; padding:0 .55rem;
  background:rgba(4,6,14,.58); pointer-events:none;
}
.coach-side{ display:grid; justify-items:center; gap:.4rem; width:7.4rem; color:#fff; }
.coach-side span{
  width:2.7rem; height:2.7rem; border-radius:50%; display:grid; place-items:center;
  border:1px solid rgba(255,255,255,.55); font-size:1.05rem;
}
.coach-side b{ font-size:.78rem; font-weight:500; line-height:1.28; text-align:center; }
.coach-left{ animation:coachNudgeL 2.6s ease-in-out infinite; }
.coach-right{ animation:coachNudgeR 2.6s ease-in-out infinite; }
.coach-got{
  position:absolute; left:50%; bottom:1.05rem; transform:translateX(-50%);
  pointer-events:auto; cursor:pointer;
  background:rgba(247,239,227,.14); border:1px solid rgba(247,239,227,.4); color:#fff;
  border-radius:2rem; padding:.5rem 1.1rem; font-size:.8rem; letter-spacing:.04em;
}
@keyframes coachNudgeL{ 0%,100%{transform:translateX(0)} 50%{transform:translateX(-.45rem)} }
@keyframes coachNudgeR{ 0%,100%{transform:translateX(0)} 50%{transform:translateX(.45rem)} }
@keyframes deckNudge{
  0%,100%{ transform:none }
  16%{ transform:translateX(-46px) rotate(-4deg) }
  42%{ transform:translateX(42px) rotate(4deg) }
  68%{ transform:none }
}
.deck-card.is-coaching{ animation:deckNudge 3.4s ease-in-out .5s 2; }
@media (prefers-reduced-motion:reduce){
  .deck-card.is-coaching, .coach-left, .coach-right{ animation:none; }
}
@media (min-width:700px){
  .deck-wrap{ max-width:24rem; margin-left:auto; margin-right:auto; }
  .deck{ max-height:none; }
  .deck-info h3{ font-size:1.85rem; }
  .deck-btn{ width:3.9rem; height:3.9rem; }
  .deck-btn svg{ width:24px; height:24px; }
}
.required-mark{ font-size:.72rem; letter-spacing:.06em; color:var(--color-accent-soft); opacity:.9; }
/* v131 — FILTERS is now the control that opens the panel. */
.filters-head{ width:100%; background:none; border:0; padding:0; cursor:pointer; text-align:left; -webkit-tap-highlight-color:transparent; }
.filters-head .filters-chev{
  flex:0 0 auto; width:.62rem; height:.62rem; display:block; margin-left:-.25rem;
  border-right:1.5px solid rgba(255,255,255,.5); border-bottom:1.5px solid rgba(255,255,255,.5);
  transform:rotate(45deg) translateY(-2px); transition:transform .18s ease;
}
.browse-controls.is-open .filters-head .filters-chev{ transform:rotate(225deg) translateY(-2px); }
.browse-controls:not(.is-open) .filters-head{ margin-bottom:.55rem; }
.filter-body[hidden]{ display:none; }
/* v131 — on a laptop the panel sits on the same centre line as the deck. */
@media (min-width:900px){
  .browse-page .browse-controls{ max-width:24rem; margin-left:auto; margin-right:auto; }
  .browse-page .browse-controls .filters-head,
  .browse-page .browse-controls .browse-filter-row,
  .browse-page .browse-controls .age-slider{ max-width:none; }
}
@media (min-width:900px){
  .browse-page .deck{ max-height:min(54vh,30rem); }
  .browse-page .deck-count{ margin-bottom:.4rem; }
}
