@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=Playfair+Display:wght@700&display=swap');

* { box-sizing: border-box; margin: 0; padding: 0; }

/* Anti-FOUC: hide the page until the i18n JS swaps the English markup for the
   chosen language, then reveal. This CSS lives in <head>, so the body is
   hidden BEFORE the first paint — no flash of English. JS adds .i18n-ready the
   moment labels are applied (instant on repeat visits via the label cache).
   The CSS-only animation is a safety net: it force-reveals after 0.6s so any
   page lacking the i18n bootstrap (e.g. internal admin pages) can never stay
   blank. */
body { visibility: hidden; animation: i18nReveal 0s linear .6s forwards; }
html.i18n-ready body { visibility: visible; animation: none; }
@keyframes i18nReveal { to { visibility: visible; } }
/* While the body is hidden by the gate, the page background lives on <body>,
   so paint the same base tone on <html> — the brief blank shows the app's
   light background instead of stark white. */
html { background: var(--bg, #f7f5fa); }
/* Kill stray horizontal scroll from absolutely-positioned badges / wide
   media. `clip` (not `hidden`) does NOT create a scroll container, so the
   sticky topbar keeps working. */
html, body { overflow-x: clip; max-width: 100%; }
:root {
    --pink: #fb6f92;
    --pink-dark: #f25179;
    --purple: #c490e4;
    --green: #2ecc71;
    --red: #e74c3c;
    --bg: #f7f5fa;
    --card: #ffffff;
    --text: #2a2a2a;
    --muted: #888;
    --border: #e8e4ef;
    --shadow: 0 4px 16px rgba(0,0,0,.08);
    --radius: 14px;
}
/* Dark mode — opt-in via <html data-theme="dark"> (set by api.js from the
   user's saved choice). Only the surface colours flip; the pink/purple brand
   accents stay so the app still feels like itself. */
html[data-theme="dark"] {
    --bg: #15131a;
    --card: #211d2b;
    --text: #ece9f1;
    --muted: #9a93a8;
    --border: #332d40;
    --shadow: 0 4px 16px rgba(0,0,0,.45);
    --pink: #ff8fab;
}
body {
    font-family: 'DM Sans', -apple-system, sans-serif;
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
}

/* ---------- AUDIO ELEMENTS ----------
   Native <audio> has an intrinsic min-width (~300px) that overflows narrow
   Android viewports and triggers horizontal scroll. Force it to fit its
   container. The duration label injected by audio-fix.js must not push the
   row wider either. */
audio {
    max-width: 100%;
    box-sizing: border-box;
}
.audio-duration-label {
    flex: 0 0 auto;
}

/* ---------- BOTTOM NAV (Android only) ----------
   Injected by brand.js when document.body.classList contains `is-android`.
   Hidden on iOS / web — the existing topbar nav stays the source of truth
   there. On Android we ALSO hide the topbar's nav links via the override
   block further down so we don't show two nav surfaces at once. */
:root {
    --bottom-nav-height: 60px;
    --bottom-nav-reserve: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom, 0px));
}
.bottom-nav {
    display: none;
    position: fixed; left: 0; right: 0; bottom: 0;
    z-index: 80;
    background: var(--card);
    box-shadow: 0 -2px 10px rgba(0,0,0,.08);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    /* Force a compositor layer so Android Chrome keeps the bar pinned during
       the address-bar collapse/expand on scroll (otherwise it repaints out). */
    transform: translateZ(0);
    will-change: transform;
}
.bottom-nav-inner {
    display: flex; align-items: stretch; justify-content: space-around;
    height: var(--bottom-nav-height);
    max-width: 560px; margin: 0 auto;
}
.bottom-nav a {
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px;
    color: var(--muted); text-decoration: none;
    font-size: .68rem; font-weight: 600; line-height: 1.1;
    position: relative;
}
.bottom-nav a .bn-icon { font-size: 1.35rem; line-height: 1; }
.bottom-nav a.active { color: var(--pink); }
.bottom-nav a.active .bn-icon { transform: translateY(-1px); }
.bottom-nav .bn-badge {
    position: absolute;
    top: 6px;
    /* Position is logical-direction aware so it sits on the icon's right edge
       in LTR layouts and on the left edge in RTL Hebrew. */
    inset-inline-start: calc(50% + 8px);
    background: var(--pink); color: #fff;
    border-radius: 999px; padding: 0 5px;
    font-size: .62rem; font-weight: 700; line-height: 14px; min-width: 14px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--card);
}
.bottom-nav .bn-badge.hidden { display: none; }

/* ---------- ANDROID OVERRIDES ----------
   Bottom nav carries the 4 PRIMARY tabs. The topbar nav is NOT fully hidden:
   only the four relocated links are hidden, so secondary actions — About,
   Logout, and the language picker — stay reachable in the topbar. Without
   this, those three vanished entirely on Android. */
.is-android .bottom-nav { display: block; }
/* Hide every relocated topbar link — keep only About + Logout. Targeting by
   :not(#nav-about):not(#nav-logout) instead of listing each primary id,
   because the games/home link uses inconsistent ids across pages
   (#nav-games on main.html, #nav-discover on keeps.html, etc.).
   Uses the `.is-android` class which an inline <head> script sets on <html>
   BEFORE first paint — so the links are hidden immediately and never flash
   visible while brand.js (deferred) catches up. */
/* Android: the main tabs live in the bottom-nav, so hide them in the topbar.
   The language picker + the profile-menu trigger remain. */
.is-android .topbar .nav a { display: none; }
.is-android .topbar .nav { flex: 0 0 auto; justify-content: flex-end; gap: .2rem; }
/* Reserve space for the bottom nav only where it is shown. play.html carries
   the no-bottom-nav class (excluded in brand.js) so it gets neither the bar
   nor the reserve — its reaction-bar + cancel dock owns the bottom area. */
body.is-android:not(.no-bottom-nav) { padding-bottom: var(--bottom-nav-reserve); }
body.is-android.no-bottom-nav .bottom-nav { display: none; }

/* ---------- TOPBAR ---------- */

.topbar {
    display: flex; justify-content: space-between; align-items: center;
    padding: .8rem 1.5rem;
    background: var(--card);
    box-shadow: 0 1px 6px rgba(0,0,0,.06);
    position: sticky; top: 0; z-index: 50;
}
.brand {
    display: flex; flex-direction: column; align-items: center; gap: .05rem;
    flex-shrink: 0; text-decoration: none;
}
.brand-avatar {
    width: 32px; height: 32px; border-radius: 50%;
    object-fit: cover; border: 2px solid var(--pink);
    display: block;
}
.brand-tagline {
    font-family: 'DM Sans', sans-serif;
    font-size: .6rem; color: var(--muted); font-weight: 600;
    white-space: nowrap; letter-spacing: .03em; text-align: center;
}
/* brand-logo/brand-name shown until JS replaces them */

/* Push the nav (and the profile-trigger that follows it) to the trailing edge
   so the header reads: brand · … · tabs+lang · profile-trigger. */
.nav { display: flex; gap: .5rem; align-items: center; flex-wrap: nowrap; margin-inline-start: auto; }
.nav a {
    color: var(--muted);
    text-decoration: none;
    font-size: .88rem;
    font-weight: 700;
    padding: .3rem .5rem;
    border-radius: 8px;
    transition: color .15s, background .15s;
    white-space: nowrap; flex-shrink: 0;
}
.nav a:hover { color: var(--pink); background: rgba(251,111,146,.06); }
.nav a.active { color: var(--pink); background: rgba(251,111,146,.12); }
.nav .user-badge { font-size: .82rem; color: var(--text); font-weight: 500; }

/* Mobile: bottom-nav style — each item is an equal-width column with the
   icon stacked over a small label. No horizontal scroll, no cramped
   single line, bigger tap targets. */
@media (max-width: 560px) {
    /* Single row: small avatar inline on one side, nav items (icon over a
       small label) squeezed to fit on the SAME line — so the avatar sits
       level with the buttons, not on a row below them. */
    .topbar { flex-wrap: nowrap; padding: .4rem .5rem; gap: .3rem; align-items: center; }
    .brand { flex-shrink: 0; flex-direction: row; gap: 0; }
    .brand-tagline, .brand-name, .brand-logo { display: none; }
    .brand-avatar { width: 30px; height: 30px; }
    .nav { flex: 1 1 auto; min-width: 0; gap: 0; flex-wrap: nowrap; justify-content: space-around; }
    .nav::-webkit-scrollbar { display: none; }
    .nav a {
        flex: 1 1 0; min-width: 0;
        display: flex; flex-direction: column; align-items: center; justify-content: center;
        gap: 1px; padding: .3rem .1rem;
        font-size: 1.05rem; line-height: 1.1; text-align: center; white-space: normal;
    }
    .nav a .nav-icon { font-size: 1.15rem; line-height: 1; }
    /* Wrap (don't nowrap) so a long label stays inside its column instead
       of spilling over and overlapping the neighbouring item. */
    .nav-text { font-size: .6rem; line-height: 1.05; font-weight: 600; word-break: break-word; }
    .lang-picker { flex: 0 0 auto; }
}
.badge {
    background: var(--pink); color: white; border-radius: 50%;
    padding: 0 6px; font-size: .72rem; margin-left: 2px;
    vertical-align: middle;
}

/* ---------- PROFILE / SETTINGS MENU ----------
   The trigger sits in the topbar; the menu + backdrop are body-level (so the
   topbar's z-index can't trap the menu under the backdrop). JS only toggles
   `.open` on the menu (and backdrop). CSS turns that single state into:
     • desktop (default) → a fixed dropdown pinned to the top-right
     • ≤768px            → a bottom-sheet that slides up + a dimming backdrop
   JS never reads the viewport — state (JS) and presentation (CSS) stay split. */
.profile-menu-wrap { flex: 0 0 auto; }
.profile-trigger {
    width: 38px; height: 38px; border-radius: 50%;
    border: none; background: rgba(251,111,146,.12); color: var(--pink);
    font-size: 1.1rem; line-height: 1; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
}
.profile-trigger:hover { background: rgba(251,111,146,.22); }
/* "You are here": solid highlight when on a page the menu owns (Profile/About). */
.profile-trigger.active { background: var(--pink); color: #fff; }

/* Fill in the Blank — inline editable blank inside the sentence. */
.fillblank-sentence { font-size: 1.05rem; line-height: 2.2; }
.blank-inline-input {
    display: inline-block; min-width: 130px; width: auto; vertical-align: baseline;
    border: none; border-bottom: 2px solid var(--pink);
    background: rgba(251,111,146,.08); color: var(--pink);
    font: inherit; font-weight: 600; text-align: center;
    padding: .1rem .45rem; margin: 0 .2rem; border-radius: 7px 7px 0 0;
}
.blank-inline-input:focus { outline: none; background: rgba(251,111,146,.18); }

/* Desktop dropdown — pinned under the top-right trigger; shown on .open. */
.profile-menu {
    position: fixed; top: 58px; inset-inline-end: 14px;
    min-width: 210px; background: var(--card);
    border-radius: 14px; box-shadow: 0 12px 32px rgba(0,0,0,.18);
    padding: .4rem; display: none; flex-direction: column; gap: .12rem; z-index: 1001;
}
.profile-menu.open { display: flex; }
.profile-menu-item {
    display: flex; align-items: center; gap: .6rem;
    padding: .65rem .8rem; border-radius: 10px;
    font-size: .92rem; font-family: inherit; font-weight: 600;
    color: var(--text); text-decoration: none; text-align: start;
    background: none; border: none; cursor: pointer; width: 100%;
}
.profile-menu-item:hover { background: rgba(251,111,146,.08); }
.profile-menu-logout { color: var(--red); }
.profile-menu-backdrop { display: none; }

/* Mobile / APK: the SAME .open class drives a bottom-sheet + dimming backdrop. */
@media (max-width: 768px) {
    .profile-menu {
        top: auto; inset: auto 0 0 0; width: 100%; min-width: 0;
        border-radius: 18px 18px 0 0;
        padding: .6rem .6rem calc(.6rem + env(safe-area-inset-bottom, 0px));
        box-shadow: 0 -8px 32px rgba(0,0,0,.22);
        display: flex;                       /* laid out; visibility via transform */
        transform: translateY(110%); transition: transform .22s ease;
    }
    .profile-menu.open { transform: translateY(0); }
    .profile-menu-item { padding: .9rem 1rem; font-size: 1rem; }
    /* Profile lives in the bottom-nav on mobile — drop it from the sheet so it
       appears in exactly one place. */
    .profile-menu-item-profile { display: none; }
    .profile-menu-backdrop {
        position: fixed; inset: 0; background: rgba(0,0,0,.45);
        opacity: 0; pointer-events: none; transition: opacity .22s ease; z-index: 1000;
        display: block;
    }
    .profile-menu-backdrop.open { opacity: 1; pointer-events: auto; }
}

/* ---------- LOGIN ---------- */
.login-bg {
    background: linear-gradient(135deg, var(--pink), var(--purple));
    display: flex; align-items: center; justify-content: center;
    min-height: 100vh;
}
.login-card {
    background: var(--card);
    padding: 2.5rem 2rem;
    border-radius: 20px;
    box-shadow: 0 16px 40px rgba(0,0,0,.2);
    width: 380px;
    text-align: center;
}
.login-card h1 {
    font-family: 'Playfair Display', serif;
    font-size: 2.2rem;
    color: var(--pink);
    margin-bottom: .3rem;
}
.subtitle { color: var(--muted); margin-bottom: 1.5rem; font-size: .95rem; }
.login-card input {
    width: 100%; padding: .8rem 1rem; margin-bottom: 1rem;
    border: 1px solid var(--border); border-radius: 10px;
    font-size: .95rem; font-family: inherit;
}
.login-card input:focus { outline: none; border-color: var(--pink); }
button {
    cursor: pointer; border: none;
    padding: .7rem 1.2rem; border-radius: 10px;
    font-size: .95rem; font-weight: 500;
    font-family: inherit;
    background: #eee; transition: transform .1s, background .15s;
}
button:hover { transform: translateY(-1px); }
button:active { transform: translateY(0); }
button.primary { background: var(--pink); color: white; width: 100%; }
button.primary:hover { background: var(--pink-dark); }
button.google-btn {
    width: 100%; background: white; color: #444;
    border: 1px solid #dadce0;
    display: flex; align-items: center; justify-content: center;
    gap: .6rem; font-weight: 500;
}
button.google-btn:hover { background: #f8f9fa; }
button.google-btn.disabled { opacity: .4; cursor: not-allowed; }
.divider {
    display: flex; align-items: center; gap: .8rem;
    color: #bbb; margin: 1.2rem 0; font-size: .82rem;
}
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.demo-row { display: flex; gap: .6rem; }
.demo-row button { flex: 1; font-size: .9rem; }
.err { color: var(--red); margin-top: 1rem; min-height: 1rem; font-size: .88rem; }
.hint { color: var(--muted); font-size: .85rem; }

/* ---------- SWIPE STAGE ---------- */
.swipe-stage {
    display: flex; flex-direction: column; align-items: center;
    padding: 1.5rem 1rem;
}
.card-area {
    position: relative; width: 360px; height: 540px;
    margin-bottom: 1.2rem;
}
.card {
    position: absolute; inset: 0;
    background: var(--card);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1rem;
    display: grid;
    grid-template-rows: auto 1fr auto;
    grid-template-columns: 24px 1fr 24px;
    transition: transform .35s ease, opacity .35s ease;
    user-select: none;
}
.card.behind-1 { transform: rotate(-4deg) translateY(6px); }
.card.behind-2 { transform: rotate(5deg) translateY(12px); }
.card .top {
    grid-column: 1 / span 3; text-align: center;
    font-size: .88rem; padding: .5rem; line-height: 1.4;
}
.card .top strong { font-size: 1rem; }
.card .photo-wrap {
    grid-column: 2; grid-row: 2;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden; border-radius: 10px;
}
.card .photo-wrap img { width: 100%; height: 100%; object-fit: cover; }
.card .left-vert, .card .right-vert {
    writing-mode: vertical-rl; text-align: center;
    font-size: .75rem; color: var(--muted); padding: 4px 0;
    align-self: stretch; grid-row: 2;
}
.card .left-vert { grid-column: 1; transform: rotate(180deg); }
.card .right-vert { grid-column: 3; }
.card .bottom {
    grid-column: 1 / span 3; text-align: center;
    font-size: .82rem; padding: .5rem; color: #555; line-height: 1.4;
}
.card .stamp {
    position: absolute; top: 30px; font-size: 3.5rem; font-weight: 900;
    border: 6px solid; border-radius: 12px; padding: 4px 16px;
    opacity: 0; pointer-events: none; transition: opacity .15s;
}
.card .stamp.keep { left: 16px; color: var(--green); border-color: var(--green); transform: rotate(-15deg); }
.card .stamp.reject { right: 16px; color: var(--red); border-color: var(--red); transform: rotate(15deg); }
.card.dragging-right .stamp.keep { opacity: 1; }
.card.dragging-left .stamp.reject { opacity: 1; }
.card.swipe-out-right { transform: translateX(120%) rotate(20deg); opacity: 0; }
.card.swipe-out-left { transform: translateX(-120%) rotate(-20deg); opacity: 0; }

.actions {
    display: flex; gap: 2rem; margin-bottom: .8rem;
    width: 360px; justify-content: center;
}
.actions button {
    width: 60px; height: 60px; border-radius: 50%;
    font-size: 1.5rem; box-shadow: 0 4px 14px rgba(0,0,0,.12);
    background: var(--card);
}
.reject-btn { color: var(--red); }
.keep-btn { color: var(--green); }

.empty {
    background: var(--card); padding: 2rem 1.5rem; border-radius: var(--radius);
    text-align: center; color: var(--muted); max-width: 400px;
}
.empty h3 { color: var(--text); margin-bottom: .5rem; }
.empty a { color: var(--pink); }
/* Empty-state with personality: a big emoji on top of friendly copy. */
.empty .empty-emoji { font-size: 2.6rem; line-height: 1; display: block; margin-bottom: .6rem; }
.empty .empty-text { font-size: .95rem; line-height: 1.45; }
.hidden { display: none !important; }

/* ---------- SKELETON SHIMMER (loading placeholders) ---------- */
@keyframes skeleton-shimmer {
    0%   { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}
.skeleton {
    background: linear-gradient(90deg,
        var(--border) 25%, rgba(0,0,0,.06) 37%, var(--border) 63%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.4s ease-in-out infinite;
    border-radius: 8px;
}
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }
.skeleton-card {
    display: flex; gap: .7rem; align-items: center;
    background: var(--card); padding: .9rem; border-radius: var(--radius);
}
.skeleton-card .sk-photo { width: 64px; height: 64px; border-radius: 12px; flex: 0 0 auto; }
.skeleton-card .sk-lines { flex: 1; display: flex; flex-direction: column; gap: .5rem; }
.skeleton-card .sk-line { height: 12px; }
.skeleton-card .sk-line.short { width: 45%; }
.skeleton-card .sk-line.med   { width: 70%; }

/* ---------- AT LIMIT SCREEN ---------- */
.at-limit {
    background: var(--card); padding: 3rem 2rem;
    border-radius: 18px; box-shadow: var(--shadow);
    max-width: 480px; text-align: center; margin: 2rem auto;
}
.at-limit-icon { font-size: 4rem; margin-bottom: 1rem; }
.at-limit h2 { color: var(--pink); margin-bottom: 1rem; }
.at-limit p { color: #555; line-height: 1.6; margin-bottom: 1rem; }
.at-limit-actions {
    margin-top: 1.5rem; display: flex; flex-direction: column;
    gap: .8rem; align-items: center;
}
.at-limit-actions a { color: var(--muted); text-decoration: none; font-size: .9rem; }
.at-limit-actions a:hover { color: var(--pink); }

/* ---------- PROFILE FORM ---------- */
.profile-page, .matches-page, .keeps-page {
    max-width: 640px; margin: 1.5rem auto; padding: 1rem 1.5rem;
}
.profile-page h2, .matches-page h2, .keeps-page h2 { margin-bottom: 1rem; }
fieldset {
    border: 1px solid var(--border); border-radius: var(--radius);
    padding: 1rem 1.2rem; margin-bottom: 1.2rem; background: var(--card);
}
fieldset legend { padding: 0 .5rem; color: var(--muted); font-weight: 500; }
fieldset label { display: block; margin: .5rem 0; font-size: .9rem; }
fieldset label.check { display: flex; gap: .5rem; align-items: center; justify-content: space-between; }
/* Checkboxes must stay their natural size — the generic `fieldset input`
   rule below forces width:100%, which stretched them and broke alignment. */
fieldset label.check input[type="checkbox"] { width: auto; margin: 0; flex: 0 0 auto; }
fieldset .check-header { font-weight: 600; margin: .3rem 0 .1rem; }
fieldset .check-divider { border-top: 1px solid var(--border); margin: .7rem 0 .3rem; }
.prem-label { text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }
.prem-tooltip {
    display: none; background: #2b2b3a; color: #fff; font-size: .78rem;
    border-radius: 8px; padding: .55rem .75rem; margin: .1rem 0 .4rem;
    line-height: 1.55; white-space: pre-line; box-shadow: 0 4px 14px rgba(0,0,0,.2);
}
.prem-tooltip.show { display: block; }
fieldset input, fieldset select {
    width: 100%; padding: .5rem .7rem; border: 1px solid var(--border);
    border-radius: 8px; font-size: .93rem; margin-top: 4px; font-family: inherit;
}
fieldset input:focus, fieldset select:focus { outline: none; border-color: var(--pink); }
.photo-list { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .8rem; }
.photo-list img { width: 80px; height: 80px; object-fit: cover; border-radius: 8px; }
.photo-upload-area {
    display: block;
    border: 2px dashed var(--border); border-radius: var(--radius);
    padding: 2rem; text-align: center; cursor: pointer;
    transition: border-color .2s; margin-top: .5rem;
}
/* A real <input type=file> stretched transparently over the upload zone, so a
   tap lands DIRECTLY on the input. Android WebView reliably opens the picker for
   a direct tap on the input (but not for synthetic clicks or label proxies). */
.file-input-overlay {
    position: absolute; inset: 0; width: 100%; height: 100%;
    opacity: 0; cursor: pointer; z-index: 2;
}
.photo-upload-area:hover { border-color: var(--pink); }
.photo-upload-area.drag-over { border-color: var(--pink); background: rgba(251,111,146,.04); }

/* ---------- DISTANCE SLIDER & MAP ---------- */
.distance-label { display: block; margin: .5rem 0; font-size: .9rem; }
.distance-value-row {
    display: flex; align-items: center; gap: .8rem; margin-top: 6px;
}
.distance-slider {
    flex: 1; -webkit-appearance: none; appearance: none;
    height: 6px; border-radius: 3px; border: none; padding: 0; margin: 0;
    background: linear-gradient(to right, var(--pink) 0%, var(--pink) 20%, var(--border) 20%, var(--border) 100%);
    cursor: pointer;
    width: 100%;
}
.distance-slider::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 20px; height: 20px; border-radius: 50%;
    background: var(--pink); border: 3px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,.25); cursor: pointer;
}
.distance-slider::-moz-range-thumb {
    width: 20px; height: 20px; border-radius: 50%;
    background: var(--pink); border: 3px solid #fff;
    box-shadow: 0 1px 4px rgba(0,0,0,.25); cursor: pointer;
}
.distance-output {
    min-width: 62px; text-align: right;
    font-weight: 700; color: var(--pink); font-size: .95rem;
    flex-shrink: 0;
}
/* Date-of-birth picker: Year → Month → Day on one row (year-first). */
.dob-row { display: flex; gap: .5rem; }
.dob-col { display: flex; flex-direction: column; gap: .15rem; flex: 1; min-width: 0; }
.dob-col.dob-year { flex: 1.25; }
.dob-col select { width: 100%; }
/* Permanent caption above each box so it's always clear which is which. */
.dob-cap { font-size: .7rem; color: var(--muted); }
/* Manual lat/long fallback row. */
.manual-loc { margin-top: .7rem; }
.manual-loc-row { display: flex; gap: .5rem; margin-top: .3rem; }
.manual-loc-row input { flex: 1; min-width: 0; }
.manual-loc-row button { flex-shrink: 0; }
/* Show the in-box "Year/Month/Day" placeholder muted until a value is chosen. */
.dob-row select:invalid { color: var(--muted); }
.dob-row select option { color: var(--text, #333); }
.distance-map {
    width: 100%; height: 320px;
    border-radius: var(--radius); overflow: hidden;
    border: 1px solid var(--border);
    background: #f0f0f0;
}
/* Empty-state CTA layered over the grey map until a location is chosen. */
.map-wrap { position: relative; }
.map-locate-overlay {
    position: absolute; inset: 0; width: 100%; height: 100%;
    border: 2px dashed var(--pink); border-radius: var(--radius);
    background: #f0f0f0; color: var(--pink);
    font-family: inherit; font-weight: 700; font-size: 1.05rem;
    display: flex; align-items: center; justify-content: center;
    gap: .4rem; text-align: center; padding: 1rem; cursor: pointer;
}
.map-locate-overlay:hover { background: #fce4ec; }
html[data-theme="dark"] .map-locate-overlay { background: #2a2333; }
/* Inline spinner for the "update location" button while a fix is acquired. */
.btn-spinner {
    display: inline-block; width: .9em; height: .9em; margin-inline-end: .45em;
    border: 2px solid currentColor; border-top-color: transparent;
    border-radius: 50%; vertical-align: -.1em; animation: btn-spin .7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
#btn-detectLocation:disabled { opacity: .7; cursor: default; }
@media (prefers-reduced-motion: reduce) { .btn-spinner { animation: none; } }
/* Leaflet popup tweak */
.leaflet-popup-content-wrapper { border-radius: 10px !important; font-family: inherit; }
.distance-map-hint { font-size: .8rem; color: var(--muted); margin-top: .4rem; text-align: center; }

/* ---------- MATCHES / NOTIFICATIONS ---------- */
.notif-list { display: flex; flex-direction: column; gap: .5rem; }
.notif-row {
    background: var(--card); padding: 1rem; border-radius: var(--radius);
    display: flex; justify-content: space-between; align-items: center;
    box-shadow: 0 1px 3px rgba(0,0,0,.04);
}
.notif-row.unread { border-left: 4px solid var(--pink); }
.notif-row .info { display: flex; gap: .8rem; align-items: center; }
.notif-row img { width: 48px; height: 48px; border-radius: 50%; object-fit: cover; }

/* ---------- MODAL ---------- */
.modal {
    position: fixed; inset: 0;
    background: rgba(0,0,0,.5);
    display: flex; align-items: center; justify-content: center;
    z-index: 100;
}
.modal-card {
    background: var(--card); padding: 1.5rem; border-radius: var(--radius);
    width: 480px; max-width: 90%;
}
.modal-card h3 { margin-bottom: .5rem; }
.modal-card p { color: var(--muted); font-size: .9rem; margin-bottom: 1rem; }
.modal-card textarea {
    width: 100%; padding: .6rem; margin: .5rem 0;
    border: 1px solid var(--border); border-radius: 8px;
    font-family: inherit; resize: vertical;
}
.modal-actions { display: flex; gap: .5rem; justify-content: flex-end; }

/* ---------- MY KEEPS ---------- */
.keeps-list { display: flex; flex-direction: column; gap: .7rem; }
/* Compact horizontal card: small photo on the left, body (name, status,
   buttons) on the right — photo shares the row with the action buttons. */
.keep-card {
    background: var(--card); border-radius: var(--radius);
    box-shadow: var(--shadow); overflow: hidden;
    display: flex; gap: .7rem; padding: .7rem;
}
.keep-photos { display: flex; gap: .3rem; flex-shrink: 0; }
.keep-photo { width: 72px; height: 90px; object-fit: cover; border-radius: 10px; cursor: pointer; }
.keep-photo.primary { width: 72px; height: 90px; }
.keep-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .35rem; }
.keep-name { margin: 0; font-size: 1rem; }
.keep-details { display: flex; flex-direction: column; gap: .12rem; font-size: .76rem; color: #555; }
.keep-status { padding: .4rem .6rem; border-radius: 8px; margin: 0; font-size: .8rem; }
.status-waiting { background: #fff3cd; color: #664d03; }
.status-accepted { background: #d1e7dd; color: #0f5132; }
.status-rejected { background: #f8d7da; color: #842029; }
.keep-dates { font-size: .72rem; margin-top: .2rem; opacity: .7; }
.keep-chances { font-size: .76rem; color: var(--muted); margin: 0; }
.keep-actions { display: flex; gap: .4rem; flex-wrap: wrap; margin-top: .1rem; }
.keep-actions button { margin-top: 0 !important; }
.undo-btn { background: #f8d7da; color: #842029; font-size: .85rem; padding: .5rem 1rem; }
.undo-btn:hover { background: #f1aeb5; }

/* ---------- SWITCH ---------- */
.user-list { display: flex; flex-direction: column; gap: .5rem; }
.user-row {
    background: var(--card); padding: 1rem; border-radius: var(--radius);
    display: flex; justify-content: space-between; align-items: center;
}

/* ---------- VOICE CLIPS ON CARD ---------- */
.profile-link { color: inherit; text-decoration: none; }
.profile-link:hover { color: var(--pink); text-decoration: underline; }
.voice-play-card-btn {
    display: inline-block; margin-top: .4rem;
    background: linear-gradient(135deg, var(--pink), var(--purple));
    color: white; border: none; border-radius: 16px;
    padding: .3rem .8rem; font-size: .78rem; font-weight: 600;
    cursor: pointer;
}
.voice-play-card-btn:hover { opacity: .9; transform: translateY(-1px); }

/* ---------- VOICE MODAL ---------- */
.voice-modal-overlay {
    position: fixed; inset: 0; z-index: 200;
    background: rgba(0,0,0,.7);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
}
.voice-modal-card {
    background: var(--card); border-radius: 18px; padding: 1.5rem;
    width: 420px; max-width: 90vw; max-height: 80vh; overflow-y: auto;
    cursor: default;
}
.voice-modal-card h3 { margin-bottom: 1rem; color: var(--pink); }
.voice-modal-clip {
    background: var(--bg); border-radius: 10px; padding: .8rem;
    margin-bottom: .8rem;
}
.voice-modal-q {
    display: flex; gap: .6rem; align-items: flex-start;
    font-size: .88rem; color: #555; margin-bottom: .3rem;
}
.voice-modal-num {
    background: var(--pink); color: white;
    width: 22px; height: 22px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: .75rem; font-weight: 700; flex-shrink: 0;
}
.voice-modal-close {
    width: 100%; margin-top: .5rem; background: var(--border);
    color: var(--text); padding: .6rem; border-radius: 10px;
}
