/* ==========================================================================
   Destined for Marriage — shared design system (2026-08-19 harmonization,
   see DECISIONS.md). Canonical source is the live public homepage
   (matching/templates/matching/home.html) — every value below was copied
   from what's actually implemented there, not from a mockup or an earlier
   description of the palette. This is the ONE stylesheet for the whole
   app: home.html, base.html (all authenticated + standalone auth pages),
   and the admin panel all link here instead of each carrying its own
   copy of the tokens. Page-specific sections (the homepage's hero/bento/
   editorial content, etc.) stay local to the one template that uses them
   — only what's actually shared lives here.
   ========================================================================== */

:root{
  /* ---- canonical tokens, home.html's own names, exact values ---- */
  --cream:#FBF3EA;
  --cream-2:#F5EADB;
  --ink:#241A12;
  --ink-soft:#4A3B2E;
  --rust:#C1502A;
  --rust-dark:#9B3E1F;
  --forest:#2B4636;
  --forest-dark:#1D3226;
  --gold:#CB9A3C;
  --gold-soft:#EFD9A8;
  --line:rgba(36,26,18,0.12);
  --white:#FFFDF9;
  --danger:#B23A3A;

  /* ---- app-layer aliases — templates/base.html's existing naming
     scheme (paper/coral/teal/gold-light/wine), same values, kept so the
     app's existing component CSS below didn't need a full rename pass.
     --coral-light/--teal-light/--ink-2 have no homepage source (the
     homepage never needed a tag-tint or a dark-nested-surface color) —
     new values, in the same families, flagged in DECISIONS.md. ---- */
  --paper:var(--cream);
  --paper-2:var(--cream-2);
  --ink-2:#3A2A1C;
  --ink-soft-on-dark:rgba(255,255,255,.68);
  --coral:var(--rust);
  --coral-deep:var(--rust-dark);
  --coral-light:#F3DCCF;
  --teal:var(--forest);
  --teal-deep:var(--forest-dark);
  --teal-light:#E3E9E1;
  --gold-light:var(--gold-soft);
  --wine:var(--danger);

  --display:'Fraunces', serif;
  --body:'Inter', sans-serif;
}

*{box-sizing:border-box;margin:0;padding:0;}
html{scroll-behavior:smooth;}
body{
  font-family:var(--body);
  background:var(--cream);
  color:var(--ink);
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3{font-family:var(--display);}
.serif{font-family:"Fraunces",serif;}
a{color:inherit;text-decoration:none;}
img{display:block;max-width:100%;}
ul{list-style:none;}
.wrap{max-width:1240px;margin:0 auto;padding:0 40px;}

/* ==========================================================================
   Canonical buttons — from home.html exactly. This is the ONE button
   system for simple actions site-wide (nav CTAs, standalone-page form
   submits, single-action links). The bm-* layer below is a deliberate,
   pre-existing, DIFFERENT set of larger "thumb-friendly" in-app action
   buttons (dashboard cards, connection accept/decline, chat) — kept
   because the homepage has no authenticated-app equivalent to model that
   interaction pattern on; not a duplicate of this one, a different job.
   ========================================================================== */
.pill{display:inline-flex;align-items:center;gap:8px;padding:8px 16px;border-radius:999px;font-size:13px;font-weight:600;letter-spacing:.01em;}
.btn{display:inline-flex;align-items:center;gap:8px;padding:14px 26px;border-radius:999px;font-weight:600;font-size:15px;cursor:pointer;border:1px solid transparent;transition:transform .18s ease, background .18s ease, box-shadow .18s ease;}
.btn:hover{transform:translateY(-2px);}
.btn-primary{background:var(--rust);color:var(--white);}
.btn-primary:hover{background:var(--rust-dark);box-shadow:0 10px 24px rgba(193,80,42,0.28);}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--line);}
.btn-ghost:hover{background:var(--white);border-color:var(--ink);}
.btn-light{background:var(--white);color:var(--ink);}
.btn-light:hover{background:var(--gold-soft);}
.btn[disabled]{opacity:.5;cursor:not-allowed;transform:none!important;}
@media (prefers-reduced-motion: reduce){
  .btn:hover{transform:none;}
}

/* ==========================================================================
   Shared header — markup lives in templates/_header.html, included by
   every page (home.html, base.html, and therefore everything that
   extends base.html). Exact structure/values from home.html; extended
   centrally with an authenticated-nav branch (home.html never needed
   one, since logged-in users never see it — matching.views.home redirects
   them straight to /dashboard/).
   ========================================================================== */
header{position:sticky;top:0;z-index:50;background:rgba(251,243,234,0.86);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border-bottom:1px solid var(--line);}
.nav-row{display:flex;align-items:center;justify-content:space-between;padding:18px 40px;}
.brand{display:flex;align-items:center;gap:10px;font-weight:600;font-size:18px;}
.brand img{width:30px;height:auto;}
.nav-links{display:flex;gap:30px;font-size:14.5px;font-weight:500;color:var(--ink-soft);flex-wrap:wrap;}
.nav-links a:hover{color:var(--rust);}
.nav-links a.active{color:var(--rust-dark);font-weight:700;}
.nav-actions{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:14px;row-gap:8px;}
.nav-actions .login{font-size:14.5px;font-weight:600;padding:10px 6px;}
.nav-actions .btn{padding:11px 24px;}

/* ---------- bottom tab bar (mobile, authenticated app only) ----------
   No homepage equivalent to model — the marketing site's own mobile
   treatment is just "hide .nav-links, keep the brand + login/signup"
   (see the @media rules below), which would leave a logged-in member
   with literally no way to reach Dashboard/Profile/Chat/etc. on a phone.
   Kept as a necessary, documented extension, not a duplicate nav. ---------- */
.bm-tabbar{display:none;}
@media (max-width:768px){
  body.has-tabbar{padding-bottom:78px;}
  .bm-tabbar{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:200;
    background:rgba(251,243,234,.96);backdrop-filter:blur(14px);
    -webkit-backdrop-filter:blur(14px);
    border-top:1px solid var(--line);
    padding:8px 6px calc(8px + env(safe-area-inset-bottom));
  }
  .bm-tabbar a{
    flex:1;display:flex;flex-direction:column;align-items:center;gap:3px;
    font-size:10.5px;font-weight:700;letter-spacing:.02em;color:var(--ink-soft);
    padding:6px 2px;border-radius:14px;
  }
  .bm-tabbar a svg{width:22px;height:22px;}
  .bm-tabbar a.active{color:var(--rust-dark);background:rgba(193,80,42,.12);}
}

/* ==========================================================================
   Shared footer — markup in templates/_footer.html. From home.html
   exactly, including its "#" placeholder links (About/Careers/Press/
   Contact/Safety/X/FB) — those are pre-existing content on the live
   homepage itself, not something this pass invented or should silently
   "finish"; see DECISIONS.md.
   ========================================================================== */
footer{background:var(--ink);color:rgba(245,237,225,0.75);padding:70px 0 30px;}
.footer-grid{display:grid;grid-template-columns:1.4fr repeat(3,1fr);gap:40px;padding-bottom:50px;border-bottom:1px solid rgba(245,237,225,0.14);}
.footer-brand .brand{color:var(--cream-2);margin-bottom:14px;}
.footer-brand p{font-size:13.5px;line-height:1.6;max-width:260px;color:rgba(245,237,225,0.55);margin-bottom:20px;}
.social-row{display:flex;gap:10px;}
.social-row a{width:34px;height:34px;border-radius:50%;border:1px solid rgba(245,237,225,0.25);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;}
.social-row a:hover{background:var(--rust);border-color:var(--rust);}
.foot-col h5{font-size:13px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:rgba(245,237,225,0.9);margin-bottom:18px;}
.foot-col li{margin-bottom:12px;font-size:14px;}
.foot-col a:hover{color:var(--gold);}
.foot-bottom{display:flex;justify-content:space-between;align-items:center;padding-top:24px;font-size:12.5px;color:rgba(245,237,225,0.45);flex-wrap:wrap;gap:8px;}

@media (max-width:980px){
  .wrap{padding:0 28px;}
  .nav-row{padding:16px 28px;}
  .nav-links{display:none;}
  .footer-grid{grid-template-columns:1fr 1fr;gap:32px;}
}
@media (max-width:640px){
  .wrap{padding:0 20px;}
  .nav-row{padding:14px 20px;}
  .brand{font-size:16px;}
  /* 2026-09-10 (see DECISIONS.md, "Log in missing on mobile") — this
     used to be `.nav-actions .login{display:none;}`, silently dropping
     "Log in" (and, on every authenticated page sharing this same
     header, "Log out" too) below 640px with no other way to reach it —
     no hamburger/mobile-menu markup exists anywhere to have "caught"
     it instead. Fixed by letting `.nav-actions` wrap (see its base rule
     above) as a fallback for widths where even the tightened sizing
     below still isn't enough room. */
  .footer-grid{grid-template-columns:1fr;gap:28px;}
  .foot-bottom{flex-direction:column;align-items:flex-start;}
}
/* 2026-09-10 (see DECISIONS.md, "mobile header alignment") — the
   previous fix let "Log in"/"Log out" wrap below "Join us" instead of
   disappearing, which solved reachability but read as two unrelated
   floating elements rather than one grouped header block. Below 480px
   specifically, there still isn't room for both at their full desktop
   sizing next to each other (measured: "Log in" + "Join us" together
   need ~170px, but nav-actions only has ~145px to work with at 375px
   once the brand takes its share) — so this trims padding just enough
   to keep them side by side on one line instead of stacking (the
   task's own first-choice option over stacking). Only horizontal
   padding shrinks — tap-target height is untouched, so both stay
   comfortably tappable; `.nav-actions`'s wrap (above) still exists as
   a fallback for anything narrower than this was tuned for. */
@media (max-width:480px){
  .brand{font-size:14px;gap:4px;}
  .brand img{width:24px;}
  .nav-actions{gap:4px;row-gap:6px;}
  .nav-actions .login{padding:10px 2px;}
  .nav-actions .btn{padding:10px 14px;}
}

/* ==========================================================================
   App shell layout + "page hero" inner-page banner (billing, verify-
   identity, chat call, both verification-capture screens — a real,
   already-established component distinct from the homepage's own
   marketing .hero, kept as-is since it's still actively used).
   ========================================================================== */
main.content{max-width:1180px;margin:0 auto;padding:36px 28px 90px;}

.page-hero{position:relative;padding:0;overflow:hidden;background:var(--paper);}
.page-hero .blob{
  position:absolute;top:-160px;right:-120px;width:420px;height:420px;border-radius:50%;
  background:radial-gradient(circle at 40% 40%, var(--gold-light), var(--gold) 65%);
  opacity:.25;filter:blur(2px);
}
.page-hero .wrap{position:relative;z-index:2;max-width:900px;padding:44px 40px;}
.page-hero h1{font-size:clamp(28px,4vw,40px);line-height:1.1;font-weight:700;letter-spacing:-.01em;color:var(--ink);margin:14px 0 12px;}
.page-hero p.lede{font-size:16px;max-width:560px;color:var(--ink-soft);}
.eyebrow{
  display:inline-flex;align-items:center;gap:10px;
  font-size:13px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--rust);margin-bottom:14px;
}
.eyebrow .dia{width:9px;height:9px;background:var(--gold);transform:rotate(45deg);flex:none;}
.script-accent{font-family:var(--display);font-style:italic;font-size:1.5rem;color:var(--gold);display:block;}

.card{background:#fff;border-radius:20px;padding:32px;margin-bottom:28px;border:1.5px solid var(--line);box-shadow:0 20px 44px rgba(36,26,18,.06);}

.check-list{list-style:none;display:flex;flex-direction:column;gap:0;}
.check-list li{display:flex;gap:12px;align-items:flex-start;font-size:15.5px;padding:12px 0;border-top:1px solid var(--line);}
.check-list li:last-child{border-bottom:1px solid var(--line);}
.check-list .icon{color:var(--forest);margin-top:2px;width:20px;height:20px;flex-shrink:0;}
.fine-print{font-size:12.5px;color:var(--ink-soft);opacity:.8;line-height:1.5;}

/* ---------- chips / tags / score ---------- */
.chip{display:inline-flex;align-items:center;gap:8px;padding:9px 16px;border-radius:999px;font-size:13px;font-weight:500;background:#fff;border:1.5px solid rgba(36,26,18,.12);color:var(--ink);}
.chip .dot{width:8px;height:8px;border-radius:50%;flex:none;}
.tag{display:inline-block;background:var(--paper-2);color:var(--ink);padding:3px 12px;border-radius:999px;font-size:12px;font-weight:700;}
.tag.t1{background:var(--teal-light);color:var(--teal-deep);}
.tag.t2{background:var(--coral-light);color:var(--coral-deep);}
.tag.t3{background:var(--paper-2);color:var(--ink-soft);}
.score{font-family:var(--display);font-weight:700;color:var(--coral-deep);font-size:1.5rem;}

/* ---------- compatibility ring (templates/_ring.html) ---------- */
.ring{
  --pct:0;width:168px;height:168px;border-radius:50%;flex:none;
  background:conic-gradient(from -90deg, var(--rust), var(--forest) calc(var(--pct)*3.6deg), var(--paper-2) 0);
  display:inline-flex;align-items:center;justify-content:center;padding:9px;
}
.ring-inner{
  width:100%;height:100%;border-radius:50%;
  background:linear-gradient(145deg,var(--gold-light),var(--paper-2));
  display:flex;align-items:center;justify-content:center;overflow:hidden;
  border:4px solid var(--white);color:var(--coral-deep);
}
.ring-inner img{width:100%;height:100%;object-fit:cover;}
.ring-inner svg{width:42%;height:42%;opacity:.55;}
.ring.ring-sm{width:44px;height:44px;padding:4px;}
.ring.ring-sm .ring-inner{border-width:2px;background:var(--white);}
.ring-sm .ring-pct{font-family:var(--display);font-weight:800;font-size:12px;color:var(--ink);}
.score-badge{
  display:inline-flex;align-items:center;gap:4px;background:var(--ink);color:var(--white);
  font-family:var(--display);font-weight:800;font-size:14px;padding:6px 16px;border-radius:999px;
  box-shadow:0 6px 14px rgba(36,26,18,.25);white-space:nowrap;
}
.score-badge b{color:var(--gold);font-weight:800;}

/* ---------- pricing comparison cards (billing.html) ---------- */
/* 2026-08-21: was repeat(4,1fr) — a leftover from an earlier 4-tier
   ladder design (see DECISIONS.md) — but only 2 price-cards have ever
   been placed in this grid since the 2-tier collapse, leaving the right
   half of the row empty. Genuinely 2 columns now, since that's the only
   layout this grid has held for a while. */
.pricing-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px;align-items:stretch;margin-top:8px;}
.price-card{display:flex;flex-direction:column;background:#fff;border-radius:20px;padding:28px 24px;border:1.5px solid rgba(36,26,18,.1);box-shadow:0 16px 36px rgba(36,26,18,.06);position:relative;}
.price-card .tier-name{font-family:var(--display);font-weight:700;font-size:20px;color:var(--ink);margin-bottom:6px;}
.price-card .tier-price{font-family:var(--display);font-weight:700;font-size:34px;color:var(--rust-dark);line-height:1;}
.price-card .tier-price .per{font-family:var(--body);font-weight:500;font-size:14px;color:var(--ink-soft);}
.price-card .tier-matches{margin:16px 0;padding:10px 14px;background:var(--paper);border-radius:12px;font-size:14px;font-weight:600;color:var(--ink);text-align:center;}
.price-card .tier-photos{font-size:13px;color:var(--ink-soft);margin-bottom:16px;line-height:1.5;}
.price-list{list-style:none;display:flex;flex-direction:column;gap:9px;margin:0 0 22px;flex:1;}
.price-list .lead{font-size:12.5px;font-weight:700;color:var(--rust-dark);text-transform:uppercase;letter-spacing:.04em;margin-top:4px;}
.price-list li:not(.lead){display:flex;gap:8px;align-items:flex-start;font-size:14px;color:var(--ink);}
.check-sm{flex:none;width:16px;height:16px;border-radius:5px;margin-top:2px;background:var(--gold);display:flex;align-items:center;justify-content:center;}
.check-sm svg{width:9px;height:9px;}
.price-card form{margin:0;}
.price-card .btn{width:100%;text-align:center;justify-content:center;padding:13px 20px;}
.price-card .btn[disabled]{background:var(--paper-2);color:var(--ink-soft);box-shadow:none;}
@media (max-width:640px){.pricing-grid{grid-template-columns:1fr;}}

/* Dark "current plan" treatment (2026-08-21, see DECISIONS.md) — reuses
   .bm-card.on-navy's exact dark-surface token pattern (--ink background,
   --paper text) rather than the mockup's own literal hex values, so it
   stays in sync with the rest of the app's dark-surface color if that
   token ever changes. Applied to whichever of the two price-cards is
   the subscriber's actual current tier; the other stays the plain light
   .price-card above — both remain visible side by side. */
.price-card.current-plan{
  background:linear-gradient(135deg,var(--ink),var(--ink-2));
  border-color:transparent;box-shadow:0 22px 50px rgba(36,26,18,.3);
}
.price-card.current-plan .cp-badge{
  display:inline-block;background:var(--gold);color:var(--ink);font-size:11px;font-weight:800;
  letter-spacing:.06em;text-transform:uppercase;padding:5px 12px;border-radius:999px;margin-bottom:10px;
}
.price-card.current-plan .tier-name,.price-card.current-plan .tier-price{color:var(--paper);}
.price-card.current-plan .tier-price .per{color:var(--ink-soft-on-dark);}
.price-card.current-plan .tier-matches{background:rgba(251,243,234,.1);color:var(--paper);}
.price-card.current-plan .tier-photos{color:var(--ink-soft-on-dark);}
.price-card.current-plan .price-list li:not(.lead){color:var(--paper);}
.price-card.current-plan .price-list .lead{color:var(--gold-soft);}
.price-card.current-plan .check-sm{background:var(--gold);}
.price-card.current-plan .check-sm svg{stroke:var(--ink)!important;}
.price-card.current-plan .btn-ghost{border-color:rgba(251,243,234,.3);color:var(--paper);}
.price-card.current-plan .btn-ghost:hover{background:rgba(251,243,234,.12);border-color:rgba(251,243,234,.5);}
.price-card.current-plan .btn-ghost[disabled]{background:transparent;color:var(--ink-soft-on-dark);}

/* ---------- term selection cards (billing.html — replaces the old plain
   radio list) ---------- */
.section-title{font-family:var(--display);font-weight:700;font-size:18px;color:var(--ink);margin:32px 0 14px;}
.term-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;}
.term-card{position:relative;display:block;background:#fff;border-radius:18px;padding:22px 18px;text-align:center;
  border:2px solid rgba(36,26,18,.1);box-shadow:0 8px 20px rgba(36,26,18,.05);cursor:pointer;}
.term-card input[type=radio]{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none;}
.term-card:has(input:checked){border-color:var(--rust);box-shadow:0 14px 30px rgba(193,80,42,.18);}
.term-card .current-badge{
  position:absolute;top:-11px;left:50%;transform:translateX(-50%);background:var(--rust);color:var(--paper);
  font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;padding:4px 10px;
  border-radius:999px;white-space:nowrap;display:none;
}
.term-card:has(input:checked) .current-badge{display:block;}
.term-name{font-size:12.5px;font-weight:700;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.04em;}
.term-price{font-family:var(--display);font-weight:700;font-size:25px;color:var(--ink);margin:8px 0 2px;}
.term-price .cur{font-size:13px;font-weight:500;color:var(--ink-soft);}
.term-eff{font-size:11.5px;color:var(--ink-soft);margin-bottom:14px;}
.term-select{display:inline-block;width:100%;border:1.5px solid var(--ink);border-radius:999px;padding:9px 0;
  font-weight:700;font-size:12.5px;color:var(--ink);}
.term-card:has(input:checked) .term-select{background:var(--rust);color:var(--paper);border-color:var(--rust);}
@media (max-width:800px){.term-grid{grid-template-columns:1fr 1fr;}}
@media (max-width:480px){.term-grid{grid-template-columns:1fr;}}

/* ---------- match-priorities: cap-tracking banner + segmented rows
   (2026-08-21, see DECISIONS.md) ---------- */
.cap-banner{display:flex;align-items:center;justify-content:space-between;background:#fff;
  border-radius:18px;padding:16px 22px;margin-bottom:22px;box-shadow:0 8px 20px rgba(36,26,18,.06);}
.cap-banner .cap-label{font-size:13.5px;font-weight:700;color:var(--ink);}
.cap-count{display:flex;align-items:center;gap:8px;}
.cap-dots{display:flex;gap:5px;}
.cap-dot{width:10px;height:10px;border-radius:50%;background:var(--paper-2);}
.cap-dot.filled{background:var(--rust);}
.cap-count span{font-size:12.5px;font-weight:700;color:var(--ink-soft);}

.priority-list{background:#fff;border-radius:22px;box-shadow:0 10px 26px rgba(36,26,18,.06);overflow:hidden;}
.priority-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:16px 22px;border-bottom:1px solid var(--paper-2);}
.priority-row:last-child{border-bottom:none;}
.pr-name{font-size:14.5px;font-weight:700;color:var(--ink);}
.pr-name .helptext{display:block;font-size:12px;font-weight:500;color:var(--ink-soft);margin-top:2px;}

.segmented{display:flex;background:var(--paper-2);border-radius:999px;padding:3px;flex:none;}
.segmented label{padding:7px 15px;border-radius:999px;font-size:12.5px;font-weight:700;color:var(--ink-soft);cursor:pointer;}
.segmented input[type=radio]{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none;}
.segmented label:has(input[value="LOW"]:checked){background:#fff;color:var(--ink);box-shadow:0 2px 6px rgba(36,26,18,.1);}
.segmented label:has(input[value="MEDIUM"]:checked){background:var(--gold);color:var(--ink);}
.segmented label:has(input[value="HIGH"]:checked){background:var(--rust);color:var(--paper);}
@media (max-width:560px){
  .priority-row{flex-direction:column;align-items:flex-start;gap:10px;}
  .segmented{align-self:stretch;}
  .segmented label{flex:1;text-align:center;}
}

/* ---------- forms (plain form p > label pattern — profile wizard pages) ---------- */
form p{margin:16px 0;}
form p > label, form > label{display:block;font-size:12px;letter-spacing:.12em;text-transform:uppercase;font-weight:700;color:var(--coral-deep);margin-bottom:8px;}
form ul{list-style:none;padding:0;margin:4px 0;}
form ul label{font-weight:400;text-transform:none;letter-spacing:normal;font-size:15px;color:var(--ink);display:flex;align-items:center;gap:8px;margin-bottom:6px;}
input[type=text],input[type=password],input[type=number],input[type=email],input[type=date],select,textarea{
  width:100%;padding:14px 16px;border-radius:12px;background:var(--paper);border:1.5px solid rgba(36,26,18,.14);
  color:var(--ink);font-family:var(--body);font-size:15px;transition:border-color .25s, box-shadow .25s;
}
textarea{min-height:120px;resize:vertical;}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--rust);box-shadow:0 0 0 4px rgba(193,80,42,.14);}
input[type=file]{width:100%;font-family:var(--body);font-size:12.5px;color:var(--ink-soft);padding:8px 0;}
input[type=file]::file-selector-button{
  font-family:var(--body);font-size:12.5px;font-weight:700;color:var(--ink);
  background:var(--paper-2);border:1.5px solid rgba(36,26,18,.14);border-radius:999px;
  padding:7px 14px;margin-right:10px;cursor:pointer;transition:background .2s;
}
input[type=file]::file-selector-button:hover{background:var(--paper);}
fieldset{border:1px solid rgba(36,26,18,.12);border-radius:14px;margin-bottom:16px;padding:14px 18px;}
legend{font-family:var(--display);font-weight:700;font-size:19px;color:var(--ink);padding:0 6px;}
.helptext{display:block;font-size:12.5px;color:var(--ink-soft);margin-top:4px;}

/* ---------- questionnaire wizard progress (also reused by the signup
   wizard, replacing its own separate progress-bar implementation) ---------- */
.wizard-progress{margin:22px 0 30px;}
.wizard-steps{display:flex;justify-content:space-between;gap:8px;margin-bottom:10px;}
.wizard-step{flex:1;text-align:center;font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;font-weight:700;color:var(--ink-soft);text-decoration:none;cursor:pointer;}
.wizard-step:hover{color:var(--rust);}
.wizard-step.done,.wizard-step.current{color:var(--rust-dark);}
.wizard-track{height:8px;border-radius:999px;background:var(--paper-2);overflow:hidden;}
.wizard-fill{height:100%;border-radius:999px;background:var(--rust);transition:width .3s ease;}
.wizard-encouragement{background:var(--paper-2);border-radius:14px;padding:14px 18px;font-size:14.5px;color:var(--ink);margin-bottom:26px;}
.wizard-question{padding:18px 0;border-bottom:1px solid var(--paper-2);}
.wizard-question:last-child{border-bottom:none;}
.wizard-weight ul{display:flex;flex-wrap:wrap;gap:14px;margin-top:8px;}
.wizard-weight ul label{margin-bottom:0;font-size:13px;}
.wizard-weight{margin-top:10px;padding-top:10px;border-top:1px dashed rgba(36,26,18,.14);}
.wizard-weight > span{font-size:11px;letter-spacing:.1em;text-transform:uppercase;font-weight:700;color:var(--ink-soft);}
.wizard-nav{display:flex;justify-content:space-between;align-items:center;margin-top:24px;}

table{width:100%;border-collapse:collapse;}
table th,table td{text-align:left;padding:10px;border-bottom:1px solid rgba(36,26,18,.08);font-size:14.5px;}
.match-row{display:flex;justify-content:space-between;align-items:center;padding:18px 0;border-bottom:1px solid var(--paper-2);}
.match-row:last-child{border-bottom:none;}
.muted{color:var(--ink-soft);font-size:14px;}

/* ---------- messages / toasts ---------- */
ul.messages{list-style:none;padding:0;}
ul.messages li{padding:14px 20px;border-radius:16px;margin-bottom:16px;font-size:14.5px;border-left:4px solid transparent;}
ul.messages li.success{background:var(--teal-light);color:var(--ink);border-left-color:var(--teal-deep);}
ul.messages li.error{background:var(--coral-light);color:var(--wine);border-left-color:var(--wine);}
ul.messages li.info,ul.messages li.warning{background:var(--gold-light);color:var(--ink);border-left-color:var(--gold);}

/* ==========================================================================
   "bm-" prefix = the app-screen interaction layer (sign-up funnel,
   dashboard, connection requests, profile editing, chat) — larger,
   thumb-friendly, non-pill buttons and cards, deliberately distinct from
   the canonical marketing .btn above (see the note at the top of the
   button section). Unchanged in values from the previous migration.
   ========================================================================== */
.bm-shell{max-width:640px;margin:0 auto;}
.bm-eyebrow{display:inline-flex;align-items:center;gap:8px;font-size:12px;letter-spacing:.24em;text-transform:uppercase;font-weight:700;color:var(--rust-dark);margin-bottom:10px;}
.bm-h1{font-family:var(--display);font-weight:700;font-size:clamp(28px,5vw,40px);line-height:1.08;letter-spacing:-.01em;color:var(--ink);margin-bottom:10px;}
.bm-lede{color:var(--ink-soft);font-size:16px;max-width:52ch;margin-bottom:28px;}

.dash-status-strip{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-bottom:24px;}
.dash-status-card{padding:22px 20px;margin-bottom:0;}
.dash-status-value{font-family:var(--display);font-weight:700;font-size:1.3rem;color:var(--ink);margin-top:6px;}
.dash-quicklinks{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin-top:14px;}
.dash-quicklinks a{
  display:flex;align-items:center;justify-content:center;text-align:center;
  padding:16px 14px;border-radius:16px;background:var(--paper);
  border:1.5px solid rgba(36,26,18,.1);font-weight:700;font-size:14px;color:var(--ink);
  transition:background .2s,border-color .2s;
}
.dash-quicklinks a:hover{background:var(--paper-2);border-color:var(--rust);}
@media (max-width:640px){
  .dash-status-strip{grid-template-columns:1fr;}
  .dash-quicklinks{grid-template-columns:1fr;}
}

.bm-card{background:#fff;border-radius:28px;padding:34px 30px;border:1.5px solid rgba(36,26,18,.07);box-shadow:0 24px 56px rgba(36,26,18,.09);margin-bottom:24px;}
.bm-card.on-sand{background:var(--white);}
.bm-card.on-navy{background:var(--ink);color:var(--paper);border-color:rgba(251,243,234,.12);}
.bm-card.on-navy .bm-h1,.bm-card.on-navy h2,.bm-card.on-navy h3{color:var(--paper);}
.bm-card.on-navy p{color:var(--ink-soft-on-dark);}
.bm-card input[type=text],.bm-card input[type=password],.bm-card input[type=email],
.bm-card input[type=number],.bm-card select,.bm-card textarea{padding:16px 18px;border-radius:16px;font-size:16px;}
.bm-card input:focus,.bm-card select:focus,.bm-card textarea:focus{border-color:var(--rust-dark);box-shadow:0 0 0 4px rgba(193,80,42,.16);}

.bm-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  min-height:56px;padding:16px 36px;border-radius:16px;border:none;
  font-family:var(--body);font-size:15.5px;font-weight:700;letter-spacing:.02em;
  cursor:pointer;transition:all .25s cubic-bezier(.2,.6,.2,1);
  background:var(--ink);color:var(--paper);box-shadow:0 14px 30px rgba(36,26,18,.28);
  width:100%;
}
.bm-btn:hover{transform:translateY(-2px);box-shadow:0 18px 38px rgba(36,26,18,.34);}
.bm-btn.rose{background:var(--rust);color:var(--paper);box-shadow:0 14px 30px rgba(193,80,42,.38);}
.bm-btn.rose:hover{background:var(--rust-dark);color:var(--paper);}
.bm-btn.gold{background:var(--gold);color:var(--ink);box-shadow:0 14px 30px rgba(203,154,60,.36);}
.bm-btn.ghost{background:transparent;color:var(--ink);box-shadow:none;border:2px solid rgba(36,26,18,.16);}
.bm-btn.ghost:hover{background:rgba(36,26,18,.06);transform:none;}
.bm-btn[disabled]{opacity:.5;cursor:not-allowed;transform:none!important;}

.bm-btn-circle{
  display:inline-flex;align-items:center;justify-content:center;
  width:64px;height:64px;border-radius:50%;border:none;flex:none;
  cursor:pointer;transition:all .25s cubic-bezier(.2,.6,.2,1);
  box-shadow:0 14px 28px rgba(36,26,18,.16);
}
.bm-btn-circle:hover{transform:translateY(-2px) scale(1.04);}
.bm-btn-circle.yes{background:var(--rust-dark);color:#fff;}
.bm-btn-circle.no{background:#fff;color:var(--ink-soft);border:2px solid rgba(36,26,18,.12);}
.bm-circle-row{display:flex;align-items:center;justify-content:center;gap:22px;margin:26px 0 6px;}

.bm-match-card{background:#fff;border-radius:32px;overflow:hidden;box-shadow:0 28px 64px rgba(36,26,18,.12);border:1.5px solid rgba(36,26,18,.06);}
.bm-match-photo{aspect-ratio:4/5;background:var(--paper-2);background-size:cover;background-position:center;}
.bm-match-body{padding:28px 26px 30px;}
.bm-match-name{font-family:var(--display);font-weight:700;font-size:26px;color:var(--ink);}
.bm-match-meta{color:var(--ink-soft);font-size:14.5px;margin-top:4px;}

.bm-bubble{border-radius:20px;padding:12px 18px;max-width:72%;font-size:15px;line-height:1.5;}
.bm-bubble.mine{background:var(--rust);color:var(--white);margin-left:auto;border-bottom-right-radius:6px;}
.bm-bubble.theirs{background:#fff;color:var(--ink);border:1.5px solid rgba(36,26,18,.08);border-bottom-left-radius:6px;}

/* ==========================================================================
   Standalone-page components — fee display, verification steps, sign-up
   wizard fields. Previously duplicated verbatim across login/signup/
   check-email/pay-signup-fee's own inline <style> blocks; now defined
   once here, since those four pages now extend base.html/link this file
   instead of being fully standalone documents.
   ========================================================================== */
.field-group{margin-bottom:20px;}
.field-label{font-size:13.5px;font-weight:700;margin-bottom:6px;display:block;}
.field-hint{font-size:12px;color:var(--ink-soft);margin-top:5px;line-height:1.5;}
.field-error{font-size:12px;color:var(--danger);margin-top:5px;font-weight:600;}
.row-2{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
@media (max-width:480px){.row-2{grid-template-columns:1fr;}}

.radio-row{display:flex;flex-wrap:wrap;gap:10px;}
.radio-row label{display:flex;align-items:center;gap:8px;flex:1;min-width:160px;padding:12px 14px;border-radius:12px;border:1.5px solid var(--line);background:var(--white);font-size:14px;font-weight:500;cursor:pointer;}
.radio-row input[type=radio]{width:auto;accent-color:var(--rust);}
.radio-row label:has(input:checked){border-color:var(--rust);background:var(--gold-soft);}
.radio-row label:has(input[value=""]){display:none;}

.honeypot{position:absolute !important;left:-9999px !important;top:-9999px !important;opacity:0;pointer-events:none;}

.remember{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink-soft);cursor:pointer;}
.remember input{width:15px;height:15px;accent-color:var(--rust);}

.fee-callout,.fee-hero{background:var(--forest);color:var(--cream-2);border-radius:18px;padding:18px 20px;margin-bottom:24px;}
.fee-callout{display:flex;gap:14px;align-items:flex-start;}
.fee-callout svg{width:20px;height:20px;flex-shrink:0;margin-top:2px;color:var(--gold-soft);}
.fee-callout b{display:block;font-family:"Fraunces",serif;font-size:15px;margin-bottom:4px;}
.fee-callout p{font-size:12.5px;line-height:1.55;color:rgba(245,237,225,0.82);}
.fee-hero{text-align:center;padding:26px 24px;}
.fee-hero .lbl{font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--gold-soft);}
.fee-hero .amount{font-family:"Fraunces",serif;font-weight:600;font-size:42px;margin:8px 0 4px;}
.fee-hero .sub{font-size:12.5px;color:rgba(245,237,225,0.75);}

.guarantee-row{display:flex;gap:10px;align-items:flex-start;background:var(--gold-soft);border-radius:14px;padding:14px 16px;margin-bottom:24px;}
.guarantee-row svg{width:18px;height:18px;color:#6b4e15;flex-shrink:0;margin-top:1px;}
.guarantee-row p{font-size:12.5px;color:#6b4e15;font-weight:600;line-height:1.5;}

.whats-included{margin-bottom:26px;}
.whats-included .wi-title{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-soft);margin-bottom:12px;}
.wi-item{display:flex;gap:10px;align-items:flex-start;padding:8px 0;border-top:1px solid var(--line);}
.wi-item:first-of-type{border-top:none;}
.wi-item svg{width:16px;height:16px;color:var(--forest);flex-shrink:0;margin-top:2px;}
.wi-item span{font-size:13px;color:var(--ink);font-weight:500;}
.wi-note{font-size:12px;color:var(--ink-soft);margin-top:10px;line-height:1.5;}
.wi-note a{color:var(--rust);font-weight:700;text-decoration:none;}

.icon-badge{width:74px;height:74px;border-radius:50%;background:var(--gold-soft);display:flex;align-items:center;justify-content:center;margin:0 auto 24px;position:relative;}
.icon-badge svg{width:32px;height:32px;color:var(--rust-dark);}
.icon-pulse{position:absolute;inset:-6px;border-radius:50%;border:2px solid var(--gold);opacity:.5;}
.email-pill{display:inline-block;background:var(--white);border:1.5px solid var(--line);border-radius:999px;padding:7px 16px;font-weight:700;font-size:13.5px;margin:14px 0 26px;word-break:break-all;}
.steps-mini{text-align:left;background:var(--white);border-radius:16px;padding:18px 20px;margin-bottom:26px;border:1px solid var(--line);}
.steps-mini li{display:flex;gap:10px;font-size:13px;color:var(--ink-soft);padding:6px 0;list-style:none;align-items:flex-start;}
.steps-mini li b{color:var(--ink);font-weight:700;}
.steps-mini .num{width:18px;height:18px;border-radius:50%;background:var(--forest);color:var(--white);font-size:10.5px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;}
.expiry-note{display:flex;align-items:center;justify-content:center;gap:6px;font-size:11.5px;color:var(--ink-soft);margin-top:18px;}
.expiry-note svg{width:13px;height:13px;flex-shrink:0;}

.info-banner{background:var(--gold-soft);color:#6b4e15;border-radius:14px;padding:12px 16px;font-size:12.5px;font-weight:600;margin-bottom:22px;display:flex;gap:10px;align-items:center;}
.info-banner svg{width:16px;height:16px;flex-shrink:0;}

.pw-rules{list-style:none;margin-top:8px;display:flex;flex-direction:column;gap:6px;}
.pw-rules li{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--ink-soft);}
.pw-rules li svg{width:14px;height:14px;color:var(--line);flex-shrink:0;}
.pw-rules li.met{color:var(--forest);font-weight:600;}
.pw-rules li.met svg{color:var(--forest);}

/* Face-guide overlay (2026-09-03, see DECISIONS.md) — the oval sits over
   the live camera <video>; its parent must be position:relative. Starts
   a neutral white outline, turns green once a face is detected roughly
   filling it — a UX aid only, never a capture gate (see static/js/
   face-guide.js). */
.face-guide-oval{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;height:72%;border-radius:50%;border:3px solid rgba(255,255,255,.6);pointer-events:none;transition:border-color .15s ease;box-shadow:0 0 0 1px rgba(0,0,0,.25);}
.face-guide-oval.good{border-color:var(--forest);}

/* Photo crop modal (2026-09-03, see DECISIONS.md) — Cropper.js itself
   (static/vendor/cropperjs/cropper.min.css) styles the actual crop box/
   handles; this just styles the modal chrome around it. */
.photo-crop-modal{display:none;position:fixed;inset:0;background:rgba(20,14,8,.72);z-index:1000;align-items:center;justify-content:center;padding:20px;}
.photo-crop-dialog{background:var(--white,#fff);border-radius:20px;padding:24px;max-width:480px;width:100%;}
.photo-crop-title{font-family:var(--display);font-weight:700;font-size:1.15rem;color:var(--ink);margin-bottom:4px;}
.photo-crop-hint{color:var(--ink-soft);font-size:13.5px;margin-bottom:16px;}
.photo-crop-canvas-wrap{max-height:60vh;overflow:hidden;background:#000;border-radius:12px;}
.photo-crop-img{display:block;max-width:100%;}
.photo-crop-error{color:var(--danger);font-size:13px;margin-top:12px;}
.photo-crop-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:18px;}

#payment-element{margin-bottom:18px;}
.pay-loading{font-size:13px;color:var(--ink-soft);text-align:center;padding:16px 0;}
/* Visible by default — used both for server-rendered field errors
   (login/signup, shown unconditionally via {% if form.x.errors %}) and
   for JS-toggled alert banners (#pay-error etc.), which start hidden via
   their own inline style="display:none" on the element instead of a
   class-level default, so the two uses don't fight each other. */
.form-error{background:#F8E0DC;color:var(--danger);border-radius:12px;padding:12px 16px;font-size:13px;font-weight:600;margin-bottom:16px;}
.helper-note{text-align:center;font-size:13px;color:var(--ink-soft);}
.helper-note a{color:var(--rust);font-weight:700;text-decoration:none;}
.divider{display:flex;align-items:center;gap:12px;margin:26px 0;color:var(--ink-soft);font-size:12px;font-weight:600;}
.divider::before,.divider::after{content:"";flex:1;height:1px;background:var(--line);}
.row-between{display:flex;justify-content:space-between;align-items:center;margin:2px 0 22px;flex-wrap:wrap;gap:10px;}
.row-between a{font-size:12.5px;font-weight:700;color:var(--rust);text-decoration:none;}
.btn .spin,.bm-btn .spin{width:15px;height:15px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:spin .7s linear infinite;display:none;}
.btn[disabled] .spin,.bm-btn[disabled] .spin{display:inline-block;}
@keyframes spin{to{transform:rotate(360deg);}}
/* Standalone processing indicator (verify_identity.html's "checking
   with Smile ID" state, 2026-08-21) — same spin keyframe as the button
   spinner above, just sized/colored for display outside a button. */
.processing-spinner{flex:none;width:22px;height:22px;border:3px solid var(--line);border-top-color:var(--rust);border-radius:50%;animation:spin .8s linear infinite;}
.lock-note{display:flex;align-items:center;justify-content:center;gap:6px;font-size:11.5px;color:var(--ink-soft);margin-top:18px;}
.lock-note svg{width:13px;height:13px;flex-shrink:0;}

.btn-resend{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:14px 0;border-radius:14px;font-weight:700;font-size:14.5px;border:none;cursor:pointer;text-decoration:none;font-family:"Inter",sans-serif;background:transparent;border:1.5px solid var(--rust);color:var(--rust);margin-top:12px;}
.btn-resend:hover{background:var(--white);}
.btn-resend[disabled]{border-color:var(--line);color:var(--ink-soft);cursor:default;background:transparent;}
.btn-resend svg{width:15px;height:15px;}
.btn-resend .spin{animation:spin 1.6s linear infinite;}
.btn-resend[disabled] .spin{animation:none;}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}

/* ---------- photo-slot custom file input (2026-08-20, self-profile
   step 1 — items 2/3/10) — the native <input type=file> stays in the
   DOM (real, focusable, accessible) but visually hidden; a styled
   <label for=...> triggers it natively (no JS needed to open the file
   picker), and JS shows a real client-side thumbnail + filename + an
   upload progress bar on top. ---------- */
.photo-slot input[type=file]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
/* 2026-08-26 (see DECISIONS.md, self-profile Photos step) — was an
   inline grid-template-columns with a 150px minimum; photos are now the
   sole content of their own dedicated wizard step, so they get much more
   room to actually judge quality/framing by, not a small incidental
   preview sharing space with four other questions.
   2026-08-27 — was a free-flowing auto-fit grid (items just wrapped in
   DOM order); now an explicit 2-column layout instead, by request: the
   3 square (600×600) slots — headshot + the two "other" slots — form a
   left column, the 2 taller full-length slots form a right column, each
   placed by its exact field name below rather than by DOM order, so this
   holds regardless of how the 5 fields happen to be looped over in the
   template. Three squares stacked (3×W + 2×gap tall) and two 2:3
   portraits stacked (3×W + 1×gap tall) land at close to the same total
   height, which is why this specific 3-vs-2 split reads as a balanced
   two-column layout rather than two mismatched columns. Collapses to a
   single column in DOM order on narrow screens (see the media query
   below) — two 240px-minimum columns side by side stop fitting well
   under roughly 560px. */
.photo-slots-grid{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:18px;}
.photo-slot[data-slot="headshot"]{grid-column:1;grid-row:1;}
.photo-slot[data-slot="other_photo_1"]{grid-column:1;grid-row:2;}
.photo-slot[data-slot="other_photo_2"]{grid-column:1;grid-row:3;}
.photo-slot[data-slot="full_length_photo_1"]{grid-column:2;grid-row:1;}
.photo-slot[data-slot="full_length_photo_2"]{grid-column:2;grid-row:2;}
@media (max-width:560px){
  .photo-slots-grid{grid-template-columns:1fr;}
  .photo-slots-grid .photo-slot{grid-column:1!important;grid-row:auto!important;}
}
.photo-preview-wrap{position:relative;width:100%;aspect-ratio:1;border-radius:16px;margin-bottom:8px;overflow:hidden;cursor:pointer;transition:transform .18s ease,box-shadow .18s ease;}
/* 2026-08-27 (see DECISIONS.md) — full-length photos are a whole person,
   head to feet: a square preview box cropped them awkwardly (the same
   1:1 box a close-up headshot actually suits). Portrait 2:3 (matches a
   600×900px reference frame) instead, for the two full-length slots
   specifically — headshot and the two "other" slots keep the square box,
   which fits a face-centered shot better. This only changes the PREVIEW
   BOX's shape; the underlying upload requirements (JPG/PNG, min
   600×600px, max 5MB) are unchanged for every slot, full-length included
   — a 600×900px photo already clears that minimum on both dimensions. */
.photo-slot[data-category="full_length"] .photo-preview-wrap{aspect-ratio:600/900;}
.photo-preview-img{width:100%;height:100%;object-fit:cover;display:block;border:1.5px solid rgba(36,26,18,.1);border-radius:16px;}
.photo-preview-empty{width:100%;height:100%;border-radius:16px;border:1.5px dashed rgba(36,26,18,.22);background:var(--paper);display:flex;align-items:center;justify-content:center;color:var(--ink-soft);font-size:12px;text-align:center;padding:8px;}
.photo-upload-bar-wrap{position:absolute;left:8px;right:8px;bottom:8px;height:6px;border-radius:999px;background:rgba(255,253,249,.6);overflow:hidden;display:none;}
.photo-upload-bar{height:100%;width:0%;border-radius:999px;background:var(--rust);transition:width .15s linear;}
.photo-choose-btn{display:inline-block;cursor:pointer;padding:9px 14px;border-radius:10px;border:1.5px solid var(--line);background:var(--white);color:var(--ink);font-size:12.5px;font-weight:700;text-align:center;}
.photo-choose-btn:hover{border-color:var(--rust);color:var(--rust-dark);}
.photo-filename{display:block;margin-top:6px;font-size:11.5px;color:var(--ink-soft);word-break:break-all;}
/* Fix 5 (see DECISIONS.md) — the size/format guidance repeated at each
   individual upload field, not just once in the intro paragraph above
   all five. */
.photo-requirement-caption{display:block;margin-top:4px;font-size:10.5px;color:var(--ink-soft);letter-spacing:.01em;}
.photo-hard-error{color:var(--wine);font-size:12px;margin-top:6px;}
/* Soft face-detection warnings (new feature, see DECISIONS.md) —
   deliberately styled as a gentle notice, not an error: amber/paper
   tones, not the wine/red used for the hard-validation errors above,
   since this is a dismissible double-check prompt, never a rejection. */
.photo-soft-warning{align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px;padding:8px 10px;border-radius:10px;background:#FFF4E5;border:1px solid rgba(193,80,42,.25);font-size:12px;color:var(--ink);}
.photo-soft-warning-dismiss{flex-shrink:0;padding:4px 10px;border-radius:8px;border:1px solid var(--line);background:var(--white);font-size:11.5px;font-weight:700;cursor:pointer;}
.photo-soft-warning-dismiss:hover{border-color:var(--rust);}

/* Shared lightbox (2026-09-07, see DECISIONS.md, "photo lightbox on
   dashboard + self-profile") — click/tap opens this on every device,
   desktop included; the injected DOM (static/js/lightbox.js) reuses
   these exact class names, which previously only existed inline in
   self_profile_step.html. Superseded the earlier (2026-08-26) decision
   below to intentionally skip a touch/non-touch split for hover — this
   pass explicitly requires hover-preview to be desktop/mouse-only, so
   .lightbox-trigger's hover-scale is now gated by @media(hover:hover),
   with click/tap unconditionally opening the lightbox on every device
   via static/js/lightbox.js regardless of hover support. */
.photo-lightbox{position:fixed;inset:0;background:rgba(20,14,10,.88);z-index:1000;align-items:center;justify-content:center;padding:24px;}
.photo-lightbox-img{max-width:min(92vw,680px);max-height:86vh;border-radius:14px;box-shadow:0 30px 80px rgba(0,0,0,.5);display:block;}
.photo-lightbox-close{position:absolute;top:20px;right:24px;background:rgba(255,255,255,.15);color:#fff;border:none;border-radius:999px;width:44px;height:44px;font-size:26px;line-height:1;cursor:pointer;}
.photo-lightbox-close:hover{background:rgba(255,255,255,.28);}

.lightbox-trigger{cursor:pointer;}
@media (hover:hover) and (pointer:fine){
  .photo-preview-wrap.lightbox-trigger:hover{transform:scale(1.06);box-shadow:0 16px 36px rgba(36,26,18,.28);z-index:2;cursor:zoom-in;}
  .ring-has-photo:hover{transform:scale(1.06);}
  .match-thumb.lightbox-trigger:hover{transform:scale(1.12);box-shadow:0 10px 22px rgba(36,26,18,.28);z-index:2;cursor:zoom-in;}
  /* 2026-09-10 (see DECISIONS.md, "photo enlarge platform-wide audit") —
     the "Your active connection" and "Matches you saved for later"
     photo strips (matching/templates/matching/dashboard.html) were
     never wired to the lightbox at all in the original pass, unlike
     every other photo location on this same page — same component,
     just never applied here. */
  .partner-photo.lightbox-trigger:hover{transform:scale(1.12);box-shadow:0 10px 22px rgba(36,26,18,.28);z-index:2;cursor:zoom-in;}
}
.ring-has-photo{transition:transform .18s ease;}
.match-thumb{transition:transform .18s ease,box-shadow .18s ease;}
.partner-photo{transition:transform .18s ease,box-shadow .18s ease;}

/* Real-time notifications (2026-09-09, see DECISIONS.md) — nav badges
   for the bottom tab bar (static/js/notifications.js sets these) and
   the toast used for both chat messages and connection requests. */
.dfm-nav-badge{
  position:absolute;top:2px;right:calc(50% - 26px);min-width:16px;height:16px;padding:0 4px;
  border-radius:999px;background:var(--wine);color:#fff;font-size:10px;font-weight:800;
  align-items:center;justify-content:center;line-height:1;
}
/* Desktop header's "Chat" link is plain inline text (templates/_header.html),
   not the icon+label stack .dfm-nav-badge is positioned for — this variant
   sits inline next to the label instead of absolutely over an icon. */
.dfm-nav-badge-inline{
  min-width:16px;height:16px;padding:0 4px;margin-left:6px;
  border-radius:999px;background:var(--wine);color:#fff;font-size:10px;font-weight:800;
  align-items:center;justify-content:center;line-height:1;vertical-align:middle;
}
.dfm-toast-host{position:fixed;top:16px;left:50%;transform:translateX(-50%);z-index:2000;display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none;}
.dfm-toast{
  display:block;max-width:min(92vw,420px);padding:12px 20px;border-radius:999px;
  background:var(--ink);color:#fff;font-family:var(--body);font-size:13.5px;font-weight:600;
  text-decoration:none;box-shadow:0 14px 32px rgba(0,0,0,.24);
  opacity:0;transform:translateY(-12px);transition:opacity .25s ease,transform .25s ease;
  pointer-events:auto;
}
.dfm-toast-in{opacity:1;transform:translateY(0);}

/* 2026-09-16 (see DECISIONS.md, "incoming call notifications
   investigation") — site-wide incoming-call overlay, shown by
   static/js/notifications.js on Stream Video's "call.ring" event. */
.dfm-incoming-call{
  position:fixed;top:16px;right:16px;z-index:2100;width:min(90vw,300px);
  background:var(--white);border-radius:20px;padding:20px 18px;
  box-shadow:0 20px 44px rgba(36,26,18,.32);text-align:center;
  animation:dfmIncomingCallIn .25s ease;
}
@keyframes dfmIncomingCallIn{from{opacity:0;transform:translateY(-10px);}to{opacity:1;transform:translateY(0);}}
.dfm-incoming-call-photo{
  width:64px;height:64px;border-radius:50%;object-fit:cover;margin:0 auto 10px;display:block;
}
.dfm-incoming-call-photo-fallback{
  display:flex;align-items:center;justify-content:center;background:var(--paper-2);
  color:var(--ink);font-family:var(--display);font-size:26px;font-weight:700;
}
.dfm-incoming-call-name{font-family:var(--display);font-weight:700;font-size:18px;color:var(--ink);}
.dfm-incoming-call-sub{color:var(--ink-soft);font-size:13px;margin-top:2px;}
.dfm-incoming-call-actions{display:flex;gap:10px;margin-top:14px;}
.dfm-incoming-call-actions button{
  flex:1;border:none;border-radius:999px;padding:11px 0;font-family:var(--body);
  font-size:14px;font-weight:700;cursor:pointer;transition:transform .15s ease;
}
.dfm-incoming-call-actions button:hover{transform:translateY(-1px);}
.dfm-incoming-call-decline{background:var(--paper-2);color:var(--ink);}
.dfm-incoming-call-accept{background:var(--forest);color:#fff;}
