/* ==========================================================================
   Zynora design system
   Single stylesheet, no build step. Tokens first, then layout, then components.
   ========================================================================== */

:root {
    color-scheme: light dark;
    --brand:        #7c3aed;
    --brand-dark:   #6d28d9;
    --brand-light:  #a78bfa;
    --brand-wash:   #f5f3ff;
    --accent:       #ec4899;

    --ink:          #0f172a;
    --ink-soft:     #475569;
    --ink-muted:    #94a3b8;
    --line:         #e2e8f0;
    --surface:      #ffffff;
    --canvas:       #f8fafc;

    --ok:      #16a34a;
    --warn:    #ca8a04;
    --danger:  #dc2626;
    --info:    #0284c7;

    --radius:    14px;
    --radius-sm: 9px;
    --radius-lg: 22px;

    --shadow-sm: 0 1px 2px rgba(15, 23, 42, .06);
    --shadow:    0 4px 16px rgba(15, 23, 42, .08);
    --shadow-lg: 0 18px 48px rgba(15, 23, 42, .14);

    --space:  1rem;
    --sidebar-width: 232px;
    --navbar-height: 62px;
    --bottom-nav-height: 56px;

    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
            "Helvetica Neue", Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
    :root {
        --ink: #f1f5f9; --ink-soft: #cbd5e1; --ink-muted: #94a3b8;
        --line: #1e293b; --surface: #0f172a; --canvas: #020617;
        --brand-wash: #1e1b4b;
        --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
        --shadow: 0 4px 16px rgba(0,0,0,.5);
        --shadow-lg: 0 18px 48px rgba(0,0,0,.6);
    }
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    font-family: var(--font);
    font-size: 15px;
    line-height: 1.6;
    color: var(--ink);
    background: var(--canvas);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0 0 .5em; line-height: 1.25; font-weight: 650; }
h1 { font-size: 1.9rem; }
h2 { font-size: 1.4rem; }
h3 { font-size: 1.1rem; }
p  { margin: 0 0 1em; }
a  { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; display: block; }

/* ---------- layout ------------------------------------------------------- */
.page {
    max-width: 1120px;
    margin: 0 auto;
    padding: calc(var(--space) * 2) var(--space);
}

.app-layout {
    display: grid;
    grid-template-columns: var(--sidebar-width) 1fr;
    gap: calc(var(--space) * 2);
    max-width: 1240px;
    margin: 0 auto;
    padding: calc(var(--space) * 1.5) var(--space);
    align-items: start;
}

.app-content { min-width: 0; }

.page-header { margin-bottom: calc(var(--space) * 1.5); }
.page-title { margin-bottom: .2em; }
.page-subtitle { color: var(--ink-soft); margin: 0; }

.grid { display: grid; gap: var(--space); }
.grid-cards { grid-template-columns: repeat(auto-fill, minmax(152px, 1fr)); gap: .6rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

.stack > * + * { margin-top: var(--space); }
.row { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
.row-between { display: flex; gap: .6rem; align-items: center; justify-content: space-between; }
.muted { color: var(--ink-muted); }
.small { font-size: .86rem; }
.center { text-align: center; }

/* ---------- navbar ------------------------------------------------------- */
.navbar {
    position: sticky; top: 0; z-index: 40;
    height: var(--navbar-height);
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    backdrop-filter: saturate(160%) blur(8px);
}
.navbar-inner {
    max-width: 1240px; height: 100%;
    margin: 0 auto; padding: 0 var(--space);
    display: flex; align-items: center; gap: var(--space);
}
.navbar-brand {
    font-weight: 800; font-size: 1.22rem; letter-spacing: -.02em;
    color: var(--brand); text-decoration: none;
}
.navbar-links { display: flex; gap: 1.1rem; margin-left: auto; }
.navbar-links a {
    color: var(--ink-soft); font-weight: 500; font-size: .93rem;
    position: relative; text-decoration: none;
}
.navbar-links a:hover { color: var(--brand); }
.navbar-actions { display: flex; align-items: center; gap: .6rem; margin-left: 1rem; }
.navbar-avatar {
    width: 34px; height: 34px; border-radius: 50%; overflow: hidden;
    display: grid; place-items: center; background: var(--brand-wash);
}
.navbar-avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar-initial { font-weight: 700; color: var(--brand); text-transform: uppercase; }

/* Desktop already carries "Alerts" as a worded link in navbar-links, so the
   bell is mobile-only. The media query turns this around. */
.navbar-alerts { display: none; }

/* ---------- sidebar ------------------------------------------------------ */
.sidebar {
    position: sticky; top: calc(var(--navbar-height) + var(--space));
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: .8rem;
    box-shadow: var(--shadow-sm);
}
.sidebar-nav { display: flex; flex-direction: column; gap: .15rem; }
.sidebar-link {
    display: flex; align-items: center; gap: .6rem;
    padding: .5rem .65rem; border-radius: var(--radius-sm);
    color: var(--ink-soft); font-weight: 500; font-size: .92rem;
    text-decoration: none;
}
.sidebar-link:hover { background: var(--brand-wash); color: var(--brand); text-decoration: none; }
.sidebar-link.is-active { background: var(--brand); color: #fff; }
.sidebar-icon { width: 20px; text-align: center; }
.sidebar-avatar {
    display: inline-grid; place-items: center; overflow: hidden;
    width: 20px; height: 20px; border-radius: 50%;
    background: var(--brand-wash); vertical-align: middle;
}
.sidebar-avatar img { width: 100%; height: 100%; object-fit: cover; }

/* Sign out is a POST, so it is a button wearing a nav link's clothes.
   display:contents keeps the form out of the flex flow, so the button lines up
   with the anchors above it instead of sitting in a box of its own. */
.sidebar-form { display: contents; }
.sidebar-link:is(button) {
    width: 100%; font: inherit; font-weight: 500; font-size: .92rem;
    text-align: left; background: none; border: none; cursor: pointer;
}
.sidebar-danger { color: var(--danger); }
.sidebar-danger:hover { background: rgba(220, 38, 38, .1); color: var(--danger); }
.sidebar-danger .sidebar-icon { color: var(--danger); }
.sidebar-divider { height: 1px; background: var(--line); margin: .7rem 0; }

/* Drawer chrome and the mobile bottom bar exist in the markup at every size,
   but only earn their space below the breakpoint. Desktop is unchanged. */
.sidebar-head, .sidebar-close, .navbar-burger, .bottom-nav, .drawer-backdrop {
    display: none;
}
.sidebar-heading {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .06em;
    color: var(--ink-muted); margin: 0 0 .4rem .65rem;
}

/* ---------- buttons ------------------------------------------------------ */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
    padding: .58rem 1.05rem; border: 1px solid transparent;
    border-radius: var(--radius-sm); font: inherit; font-weight: 600; font-size: .92rem;
    cursor: pointer; text-decoration: none; transition: transform .06s, filter .15s;
}
.btn:hover { text-decoration: none; filter: brightness(1.06); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .55; cursor: not-allowed; }

.btn-primary { background: var(--brand); color: #fff; }
.btn-accent  { background: var(--accent); color: #fff; }
.btn-ghost   { background: transparent; color: var(--ink-soft); border-color: var(--line); }
.btn-danger  { background: var(--danger); color: #fff; }
.btn-block   { width: 100%; }
.btn-sm      { padding: .38rem .75rem; font-size: .85rem; }
.btn-lg      { padding: .8rem 1.6rem; font-size: 1rem; }

/* ---------- forms -------------------------------------------------------- */
.form-group { margin-bottom: 1rem; }
.form-label {
    display: block; margin-bottom: .32rem;
    font-weight: 600; font-size: .87rem; color: var(--ink-soft);
}
.form-input, .form-select, .form-textarea {
    width: 100%; padding: .6rem .8rem;
    border: 1px solid var(--line); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--ink);
    font: inherit; font-size: .95rem;
}
.form-input:focus, .form-select:focus, .form-textarea:focus {
    outline: none; border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(124, 58, 237, .16);
}
.form-textarea { resize: vertical; min-height: 96px; }
.form-file { font-size: .9rem; }
.form-check, .form-radio { margin-right: .4rem; accent-color: var(--brand); }
.form-help { margin: .3rem 0 0; font-size: .8rem; color: var(--ink-muted); }
.form-error { margin: .3rem 0 0; font-size: .84rem; color: var(--danger); }
.form-errors {
    background: rgba(220, 38, 38, .08); border: 1px solid rgba(220, 38, 38, .25);
    border-radius: var(--radius-sm); padding: .7rem .9rem; margin-bottom: 1rem;
}
.form-errors .form-error { margin: 0; }

/* Checkbox / radio groups rendered by Django as <ul> */
.form-group ul { list-style: none; margin: 0; padding: 0;
                 display: flex; flex-wrap: wrap; gap: .4rem; }
.form-group ul li label {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .38rem .7rem; border: 1px solid var(--line);
    border-radius: 999px; font-size: .87rem; cursor: pointer;
}
.form-group ul li label:hover { border-color: var(--brand); color: var(--brand); }

/* ---------- surfaces ----------------------------------------------------- */
.panel {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 1.15rem; box-shadow: var(--shadow-sm);
}
.panel-title { font-size: 1rem; font-weight: 650; margin-bottom: .8rem; }

.tile {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 1rem;
}
.tile-value { font-size: 1.7rem; font-weight: 750; line-height: 1.1; }
.tile-label { font-size: .82rem; color: var(--ink-muted); text-transform: uppercase;
              letter-spacing: .04em; }
.tile-sub { font-size: .82rem; color: var(--ink-soft); margin-top: .2rem; }

/* ---------- discovery cards ---------------------------------------------- */
.card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    display: flex;
    flex-direction: column;
    transition: transform .16s, box-shadow .16s, border-color .16s;
}
.card:hover {
    transform: translateY(-2px);
    border-color: var(--brand-light);
    box-shadow: var(--shadow);
}
.card.is-gone { opacity: 0; transform: scale(.94); pointer-events: none; }

/* Square rather than portrait: the single biggest saving in card height, and
   object-fit keeps faces framed either way. */
.card-media {
    position: relative;
    display: block;
    aspect-ratio: 1 / 1;
    background: var(--brand-wash);
    overflow: hidden;
}
.card-media img { width: 100%; height: 100%; object-fit: cover; }
.card-placeholder {
    position: absolute; inset: 0;
    display: grid; place-items: center;
    font-size: 2rem; font-weight: 700; color: var(--brand-light);
}

/* Verified is an icon, never a word — it reads instantly and costs no space. */
.card-verified { color: #3b82f6; flex-shrink: 0; }

.card-score {
    position: absolute; right: .35rem; bottom: .35rem;
    padding: .1rem .32rem; border-radius: 5px;
    background: rgba(15, 23, 42, .72);
    color: #fff; font-size: .66rem; font-weight: 700;
    letter-spacing: -.01em;
}

.card-body { padding: .45rem .5rem .35rem; flex: 1; }

/* Identity on one line: badge, name, age, status. */
.card-identity {
    display: flex; align-items: center; gap: .22rem;
    margin: 0 0 .16rem; font-size: .84rem; font-weight: 650;
    line-height: 1.2; min-width: 0;
}
.card-fullname {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card-age { font-weight: 400; color: var(--ink-soft); }

/* Online is a word, per the same logic in reverse: presence deserves language. */
.card-online {
    margin-left: auto; flex-shrink: 0; align-self: center;
    font-size: .58rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .03em; color: var(--ok);
}

.card-meta {
    display: flex; align-items: center; gap: .26rem;
    margin: 0 0 .1rem;
    font-size: .71rem; color: var(--ink-muted);
    overflow: hidden;
}
.card-meta span {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card-meta .icon { flex-shrink: 0; opacity: .75; }

.card-actions {
    display: flex; gap: .25rem; justify-content: space-between;
    padding: .3rem .4rem .4rem;
}
.act {
    flex: 1; height: 29px;
    display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--surface); color: var(--ink-muted);
    cursor: pointer; transition: all .14s;
    text-decoration: none;
}
.act:hover { text-decoration: none; }
.act:hover { transform: translateY(-1px); }
.act:disabled { opacity: .45; cursor: not-allowed; transform: none; }
.act-pass:hover  { border-color: var(--ink-muted); color: var(--ink); }
.act-like:hover  { border-color: var(--accent); color: var(--accent);
                   background: rgba(236, 72, 153, .07); }
.act-super:hover { border-color: #f59e0b; color: #f59e0b;
                   background: rgba(245, 158, 11, .09); }
.act-chat:hover  { border-color: var(--brand); color: var(--brand);
                   background: rgba(124, 58, 237, .07); }

/* How many likes this person has received. Muted by default so it reads as
   metadata, not as another action. */
.card-likes {
    display: flex; align-items: center; gap: .45rem;
    margin: .2rem 0 0; font-size: .71rem; color: var(--ink-muted);
}
.card-likes-part { display: inline-flex; align-items: center; gap: .18rem; }
.card-likes-part .icon { color: var(--accent); }
.card-likes-part.is-super .icon { color: #f59e0b; }

/* Liked state: the card stays, it just says so. */
.card-liked {
    position: absolute; left: .35rem; bottom: .35rem;
    display: inline-flex; align-items: center; gap: .2rem;
    padding: .12rem .35rem; border-radius: 5px;
    background: rgba(236, 72, 153, .92); color: #fff;
    font-size: .62rem; font-weight: 700; letter-spacing: -.01em;
}
.card-liked .icon { flex-shrink: 0; }

.act.is-active { cursor: default; opacity: 1; }
.act-like.is-active {
    border-color: var(--accent); color: #fff; background: var(--accent);
}
.act-super.is-active {
    border-color: #f59e0b; color: #fff; background: #f59e0b;
}
.act.is-active:hover { transform: none; }
.act:disabled.is-active { opacity: 1; }

.card-compose { padding: 0 .55rem .6rem; }
.card-compose .form-input { font-size: .84rem; padding: .4rem .55rem; }
.card-compose-actions {
    display: flex; gap: .35rem; justify-content: flex-end; margin-top: .35rem;
}

/* ---------- icons -------------------------------------------------------- */
.icon { display: inline-block; vertical-align: -.125em; flex-shrink: 0; }
.icon-lg { width: 20px; height: 20px; }

/* ---------- chips -------------------------------------------------------- */
.chip {
    display: inline-flex; align-items: center;
    padding: .18rem .55rem; border-radius: 999px;
    background: var(--brand-wash); color: var(--brand);
    font-size: .76rem; font-weight: 600;
}
.chip-verified { background: rgba(22, 163, 74, .14); color: var(--ok); }
.chip-online   { background: rgba(22, 163, 74, .14); color: var(--ok); }
.chip-boost    { background: rgba(236, 72, 153, .16); color: var(--accent); }
.chip-list { list-style: none; display: flex; flex-wrap: wrap; gap: .3rem;
             margin: .6rem 0 0; padding: 0; }

.badge {
    display: inline-grid; place-items: center; min-width: 18px; height: 18px;
    padding: 0 5px; margin-left: .3rem; border-radius: 999px;
    background: var(--accent); color: #fff; font-size: .68rem; font-weight: 700;
}

/* ---------- tabs --------------------------------------------------------- */
.tabs { display: flex; gap: .3rem; border-bottom: 1px solid var(--line);
        margin-bottom: var(--space); overflow-x: auto; }
.tab {
    padding: .55rem .9rem; border-bottom: 2px solid transparent;
    color: var(--ink-soft); font-weight: 600; font-size: .9rem;
    white-space: nowrap; text-decoration: none;
}
.tab:hover { color: var(--brand); text-decoration: none; }
.tab.is-active { color: var(--brand); border-bottom-color: var(--brand); }

/* ---------- lists -------------------------------------------------------- */
.list { display: flex; flex-direction: column; gap: .5rem; }
.list-item {
    display: flex; align-items: center; gap: .8rem;
    padding: .8rem; background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--radius);
    text-decoration: none; color: inherit;
}
.list-item:hover { border-color: var(--brand-light); text-decoration: none; }
.list-avatar {
    width: 48px; height: 48px; border-radius: 50%; overflow: hidden;
    flex-shrink: 0; background: var(--brand-wash);
    display: grid; place-items: center; font-weight: 700; color: var(--brand);
}
.list-avatar img { width: 100%; height: 100%; object-fit: cover; }
.list-body { flex: 1; min-width: 0; }
.list-title { font-weight: 650; margin: 0; }
.list-sub { margin: 0; font-size: .85rem; color: var(--ink-muted);
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-side { text-align: right; font-size: .78rem; color: var(--ink-muted); }
.list-item.is-unread { border-left: 3px solid var(--accent); }

/* ---------- swipe-to-delete ---------------------------------------------
   A row is a surface over a fixed-width action. Only the surface moves, so
   the action never reflows and the row keeps its height throughout. */
.swipe {
    position: relative; overflow: hidden;
    border-radius: var(--radius);
}
.swipe-action {
    position: absolute; top: 0; right: 0; bottom: 0;
    width: var(--swipe-action-width, 88px);
    display: flex; margin: 0;
}
.swipe-delete {
    flex: 1; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: .15rem;
    border: none; background: var(--danger); color: #fff;
    font: inherit; font-size: .72rem; font-weight: 700;
    cursor: pointer;
}
.swipe-delete:hover { filter: brightness(1.08); }

.swipe-surface {
    position: relative;
    /* Opaque, or the action shows through the row it is meant to hide. */
    background: var(--surface);
    transition: transform .2s ease;
    touch-action: pan-y;
}
/* While a finger is down the surface tracks it directly — no easing. */
.swipe.is-dragging .swipe-surface { transition: none; }
.swipe.is-open .swipe-surface { transform: translateX(calc(-1 * var(--swipe-action-width, 88px))); }

/* Leaving: collapse the row rather than letting the list jump. */
.swipe.is-removing {
    transition: opacity .18s ease, max-height .22s ease, margin .22s ease;
    max-height: 0; opacity: 0; margin-bottom: -.5rem;
}

/* Tabbing to the delete button reveals it at every size — keyboard access
   must not depend on having a mouse or being able to swipe. */
.swipe:focus-within .swipe-surface {
    transform: translateX(calc(-1 * var(--swipe-action-width, 88px)));
}

/* Pointer devices also get it on hover, without a gesture. */
@media (hover: hover) {
    .swipe:hover .swipe-surface {
        transform: translateX(calc(-1 * var(--swipe-action-width, 88px)));
    }
}

/* The hint is only true where there is a finger — pointer devices get the
   action on hover and never need telling to swipe. */
.swipe-hint { display: none; }
@media (hover: none) {
    .swipe-hint {
        display: flex; align-items: center; gap: .35rem;
        margin: 0 0 .6rem;
    }
}

/* ---------- empty state -------------------------------------------------- */
.empty {
    text-align: center; padding: 3rem 1rem;
    background: var(--surface); border: 1px dashed var(--line);
    border-radius: var(--radius);
}
.empty-icon { font-size: 2.6rem; margin-bottom: .5rem; }
.empty-text { color: var(--ink-soft); max-width: 420px; margin: 0 auto 1rem; }

/* ---------- progress ----------------------------------------------------- */
.progress { height: 8px; background: var(--line); border-radius: 999px; overflow: hidden; }
.progress-bar { height: 100%; background: var(--brand); border-radius: 999px;
                transition: width .3s; }
.meter { display: flex; align-items: center; gap: .6rem; }
.meter-value { font-size: .82rem; font-weight: 650; color: var(--ink-soft); min-width: 38px; }

/* ---------- flash messages ---------------------------------------------- */
.flash-stack {
    position: fixed; top: calc(var(--navbar-height) + 12px); right: 16px;
    z-index: 60; display: flex; flex-direction: column; gap: .5rem;
    max-width: 360px;
}
.flash {
    display: flex; align-items: flex-start; gap: .6rem;
    padding: .7rem .9rem; border-radius: var(--radius-sm);
    background: var(--surface); border: 1px solid var(--line);
    box-shadow: var(--shadow); font-size: .9rem;
    animation: slide-in .22s ease-out;
}
.flash-success { border-left: 3px solid var(--ok); }
.flash-error   { border-left: 3px solid var(--danger); }
.flash-warning { border-left: 3px solid var(--warn); }
.flash-info    { border-left: 3px solid var(--info); }
.flash-close {
    margin-left: auto; background: none; border: none; cursor: pointer;
    font-size: 1.15rem; line-height: 1; color: var(--ink-muted);
}
@keyframes slide-in { from { opacity: 0; transform: translateX(18px); } }

/* ---------- auth shell --------------------------------------------------- */
.auth-shell { background: linear-gradient(150deg, var(--brand-wash), var(--canvas)); }
.auth-main { min-height: 100vh; display: grid; place-items: center; padding: 2rem 1rem; }
.auth-wrap { width: 100%; max-width: 430px; text-align: center; }
.auth-brand {
    display: inline-block; margin-bottom: 1.4rem;
    font-size: 1.7rem; font-weight: 800; color: var(--brand); text-decoration: none;
}
.auth-card {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-lg); padding: 1.9rem;
    box-shadow: var(--shadow-lg); text-align: left;
}
.auth-title { font-size: 1.42rem; margin-bottom: .25rem; }
.auth-subtitle { color: var(--ink-soft); font-size: .92rem; margin-bottom: 1.4rem; }
.auth-footer { margin-top: 1.2rem; font-size: .9rem; color: var(--ink-soft); }

/* ---------- landing ------------------------------------------------------ */
.hero { padding: 4rem 1rem 3rem; text-align: center; }
.hero-title {
    font-size: clamp(2.1rem, 5vw, 3.4rem); font-weight: 800;
    letter-spacing: -.03em; margin-bottom: .4em;
}
.hero-gradient {
    background: linear-gradient(96deg, var(--brand), var(--accent));
    -webkit-background-clip: text; background-clip: text; color: transparent;
}
.hero-sub { font-size: 1.12rem; color: var(--ink-soft);
            max-width: 560px; margin: 0 auto 1.8rem; }
.hero-actions { display: flex; gap: .7rem; justify-content: center; flex-wrap: wrap; }

.feature { padding: 1.2rem; }
.feature-title { font-size: 1.02rem; margin-bottom: .3rem; }
.feature-text { color: var(--ink-soft); font-size: .92rem; margin: 0; }

/* ---------- pricing ------------------------------------------------------ */
.plan {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-lg); padding: 1.5rem;
    display: flex; flex-direction: column;
}
.plan.is-featured { border-color: var(--brand); box-shadow: var(--shadow-lg); }
.plan.is-current  { border-color: var(--ok); }
.plan-name { font-size: 1.15rem; font-weight: 700; }
.plan-tagline { color: var(--ink-muted); font-size: .88rem; margin-bottom: .9rem; }
.plan-price { font-size: 2rem; font-weight: 800; margin-bottom: .2rem; }
.plan-period { font-size: .85rem; color: var(--ink-muted); }
.plan-features { list-style: none; padding: 0; margin: 1.1rem 0; flex: 1;
                 display: flex; flex-direction: column; gap: .45rem; }
.plan-features li { font-size: .9rem; color: var(--ink-soft);
                    display: flex; gap: .45rem; align-items: flex-start; }
.plan-features li::before { content: "✓"; color: var(--ok); font-weight: 700; }

/* ---------- footer -------------------------------------------------------- */
.footer {
    border-top: 1px solid var(--line);
    margin-top: calc(var(--space) * 3);
    padding: calc(var(--space) * 1.6) var(--space);
}
.footer-inner {
    max-width: 1240px; margin: 0 auto;
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space); flex-wrap: wrap;
}
.footer-name { font-weight: 800; font-size: 1.05rem; color: var(--brand); margin: 0 0 .2rem; }
.footer-tagline { font-size: .85rem; color: var(--ink-muted); margin: 0; }
.footer-links { display: flex; gap: 1.4rem; flex-wrap: wrap; }
.footer-links a { color: var(--ink-soft); font-size: .88rem; text-decoration: none; }
.footer-links a:hover { color: var(--brand); }

/* ---------- chat --------------------------------------------------------- */
.chat-shell {
    display: grid; grid-template-rows: auto 1fr auto auto;
    height: calc(100vh - var(--navbar-height) - 3rem);
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius); overflow: hidden;
}

.chat-header {
    display: flex; align-items: center; gap: .5rem;
    padding: .55rem .7rem; border-bottom: 1px solid var(--line);
    background: var(--surface);
}
.chat-back {
    display: none; place-items: center; width: 32px; height: 32px;
    border-radius: 8px; color: var(--ink-soft);
}
.icon-flip { transform: rotate(180deg); }

.chat-peer {
    display: flex; align-items: center; gap: .55rem;
    flex: 1; min-width: 0; color: inherit; text-decoration: none;
}
.chat-peer:hover { text-decoration: none; }
.chat-peer .list-avatar { width: 38px; height: 38px; }
.chat-peer-text { display: flex; flex-direction: column; min-width: 0; }
.chat-peer-name {
    display: flex; align-items: center; gap: .25rem;
    font-weight: 650; font-size: .92rem; line-height: 1.2;
}
.chat-peer-status { font-size: .74rem; color: var(--ink-muted); }
.tone-verified { color: #3b82f6; }

.chat-thread {
    overflow-y: auto; padding: 1rem .9rem;
    display: flex; flex-direction: column; gap: .3rem;
    background:
        radial-gradient(circle at 20% 10%, rgba(124,58,237,.045), transparent 45%),
        radial-gradient(circle at 85% 80%, rgba(236,72,153,.045), transparent 45%);
}

.bubble {
    position: relative;
    max-width: min(72%, 440px);
    padding: .45rem .7rem .3rem;
    border-radius: 15px 15px 15px 4px;
    background: var(--canvas);
    border: 1px solid var(--line);
    align-self: flex-start;
    font-size: .9rem; line-height: 1.45;
    word-wrap: break-word; overflow-wrap: anywhere;
}
.bubble.is-mine {
    background: var(--brand); border-color: var(--brand);
    color: #fff; align-self: flex-end;
    border-radius: 15px 15px 4px 15px;
}
.bubble.is-deleted { font-style: italic; opacity: .6; }
.bubble-text { display: block; }
.bubble-image img { border-radius: 10px; margin-bottom: .3rem; max-height: 260px; }
.bubble audio { max-width: 220px; margin-bottom: .25rem; }
.bubble-video video {
    border-radius: 10px; margin-bottom: .3rem;
    max-height: 260px; max-width: 100%; display: block;
}
.bubble-document {
    display: flex; align-items: center; gap: .5rem;
    padding: .5rem .6rem; margin-bottom: .3rem;
    border-radius: 10px; background: rgba(15, 23, 42, .06);
    text-decoration: none; color: inherit;
}
.bubble.is-mine .bubble-document { background: rgba(255, 255, 255, .16); }
.bubble-document-name {
    font-size: .85rem; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; max-width: 180px;
}

.bubble-foot {
    display: flex; align-items: center; justify-content: flex-end; gap: .25rem;
    margin-top: .1rem; font-size: .66rem; opacity: .72;
}
.bubble .is-read { color: #93c5fd; }

/* Consecutive bubbles from the same side read as one turn. */
.bubble + .bubble { margin-top: 0; }

.chat-intro {
    margin: auto; text-align: center; color: var(--ink-muted); padding: 2rem 1rem;
}
.chat-intro-title { margin: .6rem 0 .2rem; font-weight: 650; color: var(--ink); }
.chat-intro-text { margin: 0; font-size: .88rem; }

.typing-indicator {
    padding: 0 1rem; margin: 0; min-height: 1.15rem;
    font-size: .76rem; color: var(--ink-muted); font-style: italic;
}

.chat-composer-wrap { position: relative; }
.chat-composer {
    display: flex; gap: .4rem; align-items: center;
    padding: .55rem .6rem; border-top: 1px solid var(--line);
    background: var(--surface);
}
.composer-icon-btn {
    display: grid; place-items: center; width: 36px; height: 36px;
    border-radius: 9px; color: var(--ink-muted); cursor: pointer;
    border: 1px solid var(--line); flex-shrink: 0; background: none;
}
.composer-icon-btn:hover { color: var(--brand); border-color: var(--brand); }
.composer-input { flex: 1; border-radius: 999px; padding: .5rem .9rem; }

.composer-popover {
    position: absolute; left: .6rem; bottom: calc(100% + .4rem);
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius); box-shadow: var(--shadow-lg);
    z-index: 20; padding: .5rem;
}
.composer-popover[hidden] { display: none; }

.composer-attach-menu { display: flex; flex-direction: column; gap: .15rem; min-width: 170px; }
.attach-menu-item {
    display: flex; align-items: center; gap: .55rem;
    padding: .5rem .6rem; border-radius: var(--radius-sm);
    background: none; border: none; color: var(--ink-soft);
    font: inherit; font-size: .88rem; cursor: pointer; text-align: left;
}
.attach-menu-item:hover { background: var(--canvas); color: var(--ink); }

[data-emoji-panel] {
    display: grid; grid-template-columns: repeat(10, 1fr); gap: .1rem;
    max-width: 300px;
}
.emoji-option {
    display: grid; place-items: center; width: 30px; height: 30px;
    border: none; background: none; border-radius: 6px;
    font-size: 1.15rem; line-height: 1; cursor: pointer;
}
.emoji-option:hover { background: var(--canvas); }
.composer-send {
    display: grid; place-items: center; width: 38px; height: 38px;
    border: none; border-radius: 50%; flex-shrink: 0;
    background: var(--brand); color: #fff; cursor: pointer;
    transition: filter .15s, transform .06s;
}
.composer-send:hover { filter: brightness(1.08); }
.composer-send:active { transform: scale(.94); }

.chat-closed {
    display: flex; align-items: center; justify-content: center; gap: .4rem;
    padding: .8rem; border-top: 1px solid var(--line);
    font-size: .85rem; color: var(--ink-muted);
}

/* ---------- tables ------------------------------------------------------- */
.table-wrap { overflow-x: auto; border: 1px solid var(--line);
              border-radius: var(--radius); background: var(--surface); }
.table { width: 100%; border-collapse: collapse; font-size: .88rem; }
.table th, .table td { padding: .6rem .8rem; text-align: left;
                       border-bottom: 1px solid var(--line); }
.table th { font-weight: 650; color: var(--ink-soft); background: var(--canvas);
            white-space: nowrap; }
.table tr:last-child td { border-bottom: none; }

.tone-danger  { color: var(--danger); font-weight: 650; }
.tone-warning { color: var(--warn); font-weight: 650; }
.tone-muted   { color: var(--ink-muted); }
.tone-ok      { color: var(--ok); font-weight: 650; }

/* ---------- charts ------------------------------------------------------- */
.chart { width: 100%; height: 200px; display: block; }
.chart-card { background: var(--surface); border: 1px solid var(--line);
              border-radius: var(--radius); padding: 1rem; }

/* ---------- wizard ------------------------------------------------------- */
.wizard { max-width: 620px; margin: 0 auto; }
.wizard-steps { display: flex; gap: .3rem; margin-bottom: 1.4rem; }
.wizard-step { flex: 1; height: 5px; border-radius: 999px; background: var(--line); }
.wizard-step.is-done { background: var(--brand); }
.wizard-step.is-current { background: var(--brand-light); }

/* ---------- responsive --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

/* ==========================================================================
   Utilities
   Small single-purpose classes so templates never need a style attribute.
   ========================================================================== */
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: .5rem; }
.mt-2 { margin-top: 1rem; }
.mt-3 { margin-top: 2rem; }
.mt-4 { margin-top: 3rem; }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: .5rem; }
.mb-2 { margin-bottom: 1rem; }
.mb-3 { margin-bottom: 2rem; }

.narrow      { max-width: 480px; }
.narrow-md   { max-width: 620px; }
.narrow-lg   { max-width: 760px; }
.centered    { margin-left: auto; margin-right: auto; }

.avatar-md { width: 72px; height: 72px; }
.avatar-lg { width: 84px; height: 84px; }
.avatar-stacked { margin: 0 auto .6rem; }

.tile-photo { border-radius: var(--radius); }
.code-block { display: block; word-break: break-all; }

/* ==========================================================================
   Chat section
   A conversation rail beside the open thread, both inside the app shell, so
   messaging is somewhere you navigate to rather than a window that pops out.
   ========================================================================== */
.chat-section {
    display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: var(--space);
    align-items: start;
}

.chat-rail {
    display: flex; flex-direction: column; min-height: 0;
    height: calc(100vh - var(--navbar-height) - 3rem);
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius); overflow: hidden;
}
.chat-rail-head {
    display: flex; align-items: center; gap: .4rem;
    padding: .8rem .9rem; border-bottom: 1px solid var(--line);
}
.chat-rail-title { margin: 0; font-size: .95rem; font-weight: 700; }
.chat-rail-list { overflow-y: auto; flex: 1; }
.chat-rail-empty {
    margin: auto; padding: 1rem; text-align: center;
    font-size: .84rem; color: var(--ink-muted);
}

.chat-rail-item {
    display: flex; align-items: center; gap: .55rem;
    padding: .55rem .7rem; color: inherit; text-decoration: none;
    border-left: 3px solid transparent;
}
.chat-rail-item:hover { background: var(--canvas); text-decoration: none; }
.chat-rail-item.is-current {
    background: var(--brand-wash); border-left-color: var(--brand);
}
.chat-rail-item .list-avatar { width: 38px; height: 38px; position: relative; }
.chat-rail-body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.chat-rail-name {
    display: flex; align-items: center; gap: .25rem;
    font-size: .87rem; font-weight: 650; line-height: 1.25;
}
.chat-rail-preview {
    font-size: .76rem; color: var(--ink-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-rail-item.is-unread .chat-rail-preview { color: var(--ink); font-weight: 600; }
.chat-rail-side {
    display: flex; align-items: center; gap: .2rem;
    color: var(--ink-muted); flex-shrink: 0;
}

.presence-dot {
    position: absolute; right: 0; bottom: 0;
    width: 10px; height: 10px; border-radius: 50%;
    background: var(--ok); border: 2px solid var(--surface);
}

.chat-shell-empty { display: grid; place-items: center; }

/* The inbox is one full-width column — no second pane to fill. */
.chat-section.is-list { grid-template-columns: minmax(0, 1fr); }
.chip-match { background: rgba(22, 163, 74, .14); color: var(--ok); }

/* Incoming intent on an admirer card — a like and a super like read
   differently, so they are coloured differently. */
.card-admirer {
    position: absolute; left: .35rem; top: .35rem;
    display: inline-flex; align-items: center; gap: .2rem;
    padding: .12rem .35rem; border-radius: 5px;
    background: rgba(236, 72, 153, .92); color: #fff;
    font-size: .62rem; font-weight: 700; letter-spacing: -.01em;
}
.card-admirer.is-super { background: rgba(245, 158, 11, .95); }
.card-admirer .icon { flex-shrink: 0; }

.badge-super { background: #f59e0b; gap: .15rem; grid-auto-flow: column; }

/* ==========================================================================
   Search
   ========================================================================== */
.navbar-search {
    display: grid; place-items: center;
    width: 34px; height: 34px; border-radius: 9px;
    color: var(--ink-soft); flex-shrink: 0;
}
.navbar-search:hover { background: var(--brand-wash); color: var(--brand); }

.search-page { max-width: 980px; margin: 0 auto; }
.search-head { margin-bottom: 1rem; }
.search-head .page-title { margin-bottom: .15rem; }
.search-head .page-subtitle { margin: 0; color: var(--ink-soft); }

.search-card {
    display: grid; gap: 1rem; padding: 1.1rem; margin-bottom: 1.4rem;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
}

/* The bar: one rounded field that owns the icon, the clear button and the go button. */
.search-bar {
    display: flex; align-items: center; gap: .4rem;
    padding: .3rem .3rem .3rem 1rem; min-height: 54px;
    background: var(--canvas); border: 1.5px solid var(--line); border-radius: 999px;
    transition: border-color .15s, box-shadow .15s, background .15s;
}
.search-bar:focus-within {
    border-color: var(--brand); background: var(--surface);
    box-shadow: 0 0 0 4px rgba(124, 58, 237, .14);
}
.search-bar-icon { display: grid; color: var(--ink-muted); flex-shrink: 0; }
.search-bar:focus-within .search-bar-icon { color: var(--brand); }
.search-input {
    flex: 1; min-width: 0; border: 0; outline: 0; background: transparent;
    color: var(--ink); font: inherit; font-size: 1rem; padding: .5rem .2rem;
    -webkit-appearance: none; appearance: none;
}
.search-input::placeholder { color: var(--ink-muted); }
.search-input::-webkit-search-cancel-button { display: none; }
.search-clear {
    display: grid; place-items: center; width: 30px; height: 30px; flex-shrink: 0;
    border: 0; border-radius: 50%; cursor: pointer; color: var(--ink-soft); background: var(--line);
}
.search-clear[hidden] { display: none; }
.search-clear:hover { color: var(--ink); }
.search-go {
    display: inline-flex; align-items: center; gap: .4rem; flex-shrink: 0;
    height: 44px; padding: 0 1.3rem; border: 0; border-radius: 999px; cursor: pointer;
    color: #fff; font: inherit; font-weight: 650;
    background: linear-gradient(135deg, var(--brand), var(--accent));
    box-shadow: 0 4px 14px rgba(124, 58, 237, .35);
}
.search-go:hover { filter: brightness(1.07); }
.search-go-icon { display: none; }

.search-scopes { display: flex; flex-wrap: wrap; gap: .5rem; }
.scope-chip {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .45rem .9rem; border-radius: 999px;
    border: 1px solid var(--line); background: var(--surface);
    font-size: .86rem; font-weight: 600; color: var(--ink-soft);
    cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
    transition: border-color .15s, color .15s, background .15s;
}
.scope-chip:hover { border-color: var(--brand-light); color: var(--brand); }
.scope-chip.is-active {
    background: var(--brand); border-color: var(--brand); color: #fff;
    box-shadow: 0 3px 10px rgba(124, 58, 237, .3);
}

/* Preference match as a proper switch with its explanation beside it. */
.switch-row { display: flex; align-items: center; gap: .8rem; cursor: pointer; padding-top: .9rem; border-top: 1px solid var(--line); }
.switch-input { position: absolute; opacity: 0; pointer-events: none; }
.switch-track {
    position: relative; flex-shrink: 0; width: 44px; height: 26px; border-radius: 999px;
    background: var(--line); transition: background .18s;
}
.switch-thumb {
    position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
    background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); transition: transform .18s;
}
.switch-input:checked + .switch-track { background: var(--brand); }
.switch-input:checked + .switch-track .switch-thumb { transform: translateX(18px); }
.switch-input:focus-visible + .switch-track { outline: 2px solid var(--brand); outline-offset: 2px; }
.switch-text { display: grid; line-height: 1.3; }
.switch-text strong { font-size: .92rem; }
.switch-text small { color: var(--ink-muted); font-size: .8rem; }

.search-summary {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    margin: 0 .2rem 1rem; color: var(--ink-soft);
}
.search-summary p { margin: 0; }
.search-summary strong { color: var(--ink); font-size: 1.15rem; }
.search-term { color: var(--ink); font-weight: 650; }
.search-in {
    margin-left: .35rem; padding: .12rem .55rem; border-radius: 999px; font-size: .76rem;
    font-weight: 650; color: var(--brand); background: var(--brand-wash);
}
.search-reset { font-size: .86rem; font-weight: 650; text-decoration: none; white-space: nowrap; }

.search-empty {
    display: grid; justify-items: center; gap: .5rem; text-align: center; padding: 2.8rem 1.2rem;
    background: var(--surface); border: 1px dashed var(--line); border-radius: var(--radius-lg);
}
.search-empty h2 { margin: .2rem 0 0; }
.search-empty p { margin: 0; color: var(--ink-soft); max-width: 420px; }
.search-empty-icon {
    display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%;
    color: var(--brand); background: var(--brand-wash);
}
.search-empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem; margin-top: .7rem; }

.search-browse { display: grid; gap: 1.6rem; }
.browse-title {
    display: flex; align-items: center; gap: .45rem; margin: 0 0 .7rem;
    font-size: .8rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted);
}
.browse-title .icon { color: var(--brand); }
.browse-chips { list-style: none; display: flex; flex-wrap: wrap; gap: .5rem; margin: 0; padding: 0; }
.browse-chips a {
    display: inline-block; padding: .5rem 1rem; border-radius: 999px; text-decoration: none;
    font-size: .9rem; font-weight: 600; color: var(--ink);
    background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-sm);
    transition: transform .12s, background .15s, color .15s, border-color .15s;
}
.browse-chips a:hover {
    background: var(--brand); color: #fff; border-color: var(--brand); transform: translateY(-1px);
}

@media (max-width: 560px) {
    .search-card { padding: .9rem; gap: .9rem; border-radius: var(--radius); }
    .search-bar { min-height: 50px; padding-left: .85rem; }
    .search-go { width: 42px; height: 42px; padding: 0; justify-content: center; }
    .search-go-text { display: none; }
    .search-go-icon { display: grid; }
    .scope-chip { padding: .4rem .75rem; font-size: .82rem; }
    .search-summary { flex-direction: column; align-items: flex-start; gap: .3rem; }
}

/* Distance shown for a result the search radius had to be widened to reach. */
.card-meta.is-far { color: var(--warn); }
.card-meta.is-far .icon { opacity: 1; }

/* ==========================================================================
   Mobile
   Below this width the sidebar becomes a drawer, a bottom bar carries the four
   destinations people return to, and the content column runs full width.
   Everything here is scoped to the media query — desktop is untouched.
   ========================================================================== */
@media (max-width: 900px) {
    .app-layout {
        grid-template-columns: 1fr;
        gap: var(--space);
        /* Clear the fixed bottom bar, including the home-indicator inset. */
        padding-bottom: calc(var(--bottom-nav-height) + var(--space)
                             + env(safe-area-inset-bottom));
    }

    .navbar-links { display: none; }

    /* With the links gone, the actions must claim the free space themselves
       or they sit stranded next to the wordmark. */
    .navbar-actions { margin-left: auto; gap: .35rem; }
    .navbar-avatar { display: none; }
    .navbar-alerts {
        display: grid; place-items: center; position: relative;
        width: 38px; height: 38px; border-radius: 10px;
        color: var(--ink-soft);
    }
    .navbar-alerts:active { background: var(--brand-wash); color: var(--brand); }
    .navbar-alerts-badge {
        position: absolute; top: 3px; right: 2px;
        min-width: 16px; height: 16px; padding: 0 4px;
        display: grid; place-items: center; border-radius: 999px;
        background: var(--accent); color: #fff;
        font-size: .6rem; font-weight: 700; line-height: 1;
    }

    .navbar-burger {
        display: grid; place-items: center;
        width: 38px; height: 38px; margin-right: -.2rem;
        border: none; border-radius: 10px;
        background: none; color: var(--ink-soft); cursor: pointer;
    }
    .navbar-burger:active { background: var(--brand-wash); color: var(--brand); }

    /* ---- drawer ---------------------------------------------------------- */
    .sidebar {
        position: fixed; top: 0; bottom: 0; left: 0; z-index: 60;
        width: min(82vw, 300px);
        margin: 0; padding: 0 .7rem calc(.8rem + env(safe-area-inset-bottom));
        border-width: 0 1px 0 0; border-radius: 0;
        box-shadow: none; overflow-y: auto; overscroll-behavior: contain;
        transform: translateX(-100%);
        transition: transform .24s ease;
    }
    .sidebar.is-open { transform: translateX(0); box-shadow: var(--shadow-lg); }

    .sidebar-head {
        position: sticky; top: 0; z-index: 1;
        display: flex; align-items: center; justify-content: space-between;
        gap: .5rem; padding: .85rem .15rem .7rem;
        background: var(--surface); border-bottom: 1px solid var(--line);
        margin-bottom: .6rem;
    }
    .sidebar-brand { font-size: 1.05rem; font-weight: 800; color: var(--brand); }
    .sidebar-close {
        display: grid; place-items: center;
        width: 34px; height: 34px; flex-shrink: 0;
        border: none; border-radius: 9px;
        background: none; color: var(--ink-soft); cursor: pointer;
    }

    /* Roomier rows: these are now touch targets, not pointer targets. */
    .sidebar-link { padding: .68rem .65rem; font-size: .95rem; }

    .drawer-backdrop {
        display: block; position: fixed; inset: 0; z-index: 55;
        background: rgba(2, 6, 23, .55);
        opacity: 0; pointer-events: none; transition: opacity .24s ease;
    }
    .drawer-backdrop.is-open { opacity: 1; pointer-events: auto; }

    /* The page must not scroll behind an open drawer. */
    body.drawer-open { overflow: hidden; }

    /* ---- bottom bar ------------------------------------------------------ */
    .bottom-nav {
        display: grid; grid-template-columns: repeat(5, 1fr);
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
        background: var(--surface); border-top: 1px solid var(--line);
        padding-bottom: env(safe-area-inset-bottom);
    }
    .bottom-nav-item {
        display: flex; flex-direction: column; align-items: center; gap: .12rem;
        min-height: var(--bottom-nav-height); justify-content: center;
        color: var(--ink-muted); text-decoration: none;
        font-size: .66rem; font-weight: 600;
    }
    .bottom-nav-item:hover { text-decoration: none; color: var(--ink-soft); }
    .bottom-nav-item.is-active { color: var(--brand); }
    .bottom-nav-icon { position: relative; display: grid; place-items: center; }

    /* The profile tab wears your photo. A ring rather than a colour change
       marks it active, since a photo cannot take currentColor. */
    .bottom-nav-avatar {
        display: grid; place-items: center; overflow: hidden;
        width: 22px; height: 22px; border-radius: 50%;
        background: var(--brand-wash);
        box-shadow: 0 0 0 1.5px var(--line);
    }
    .bottom-nav-avatar img { width: 100%; height: 100%; object-fit: cover; }
    .bottom-nav-initial {
        font-size: .68rem; font-weight: 700; line-height: 1;
        color: var(--brand); text-transform: uppercase;
    }
    .bottom-nav-item.is-active .bottom-nav-avatar {
        box-shadow: 0 0 0 2px var(--brand);
    }
    /* The centre button: raised, filled, always the brand colour. */
    .bottom-nav-center { overflow: visible; }
    .bottom-nav-fab {
        display: grid; place-items: center;
        width: 50px; height: 50px; margin-top: -20px; border-radius: 50%;
        color: #fff; background: linear-gradient(135deg, var(--brand), var(--accent));
        box-shadow: 0 6px 18px rgba(124, 58, 237, .45);
        border: 3px solid var(--surface);
    }
    .bottom-nav-center.is-active .bottom-nav-fab { box-shadow: 0 6px 22px rgba(236, 72, 153, .55); }
    .bottom-nav-fab svg { stroke: currentColor; stroke-width: .6; }  /* a slightly bolder plus */
    .bottom-nav-badge {
        position: absolute; top: -5px; right: -10px;
        min-width: 16px; height: 16px; padding: 0 4px;
        display: grid; place-items: center; border-radius: 999px;
        background: var(--accent); color: #fff;
        font-size: .6rem; font-weight: 700;
    }

    /* ---- content fit ----------------------------------------------------- */
    /* Underline tabs assume everything fits on one line. On a phone the wider
       strips (Discover has five) scrolled sideways, so the last options were
       invisible unless you thought to drag them into view. Wrapped pills show
       every option at once — nothing is hidden behind a gesture. */
    .tabs {
        flex-wrap: wrap; gap: .35rem;
        border-bottom: none; overflow-x: visible;
    }
    .tab {
        padding: .38rem .75rem; font-size: .82rem;
        border: 1px solid var(--line); border-radius: 999px;
    }
    .tab.is-active {
        background: var(--brand); border-color: var(--brand); color: #fff;
    }

    .page-title { font-size: 1.6rem; }
    .grid-2, .grid-3 { grid-template-columns: 1fr; }
    .table th, .table td { white-space: nowrap; }
    /* Bigger tap targets on the cards. */
    .act { height: 34px; }

    /* The chat card hugs the navbar and the bottom bar — only enough gap to
       read as separate from them, not the page's usual breathing room. Scoped
       to pages with a chat-section so every other mobile page keeps the
       normal padding. */
    .app-layout:has(.chat-section) {
        padding-top: .4rem;
        padding-bottom: calc(var(--bottom-nav-height) + .4rem + env(safe-area-inset-bottom));
    }

    /* One pane at a time: the rail is the inbox, the thread is its own screen. */
    .chat-section { grid-template-columns: 1fr; }
    .chat-section .chat-rail {
        height: auto;
        max-height: calc(100vh - var(--navbar-height) - var(--bottom-nav-height) - 1.3rem);
        max-height: calc(100dvh - var(--navbar-height) - var(--bottom-nav-height) - 1.3rem);
    }
    .chat-section.has-thread .chat-rail { display: none; }
    .chat-shell {
        /* 100vh is the *largest* possible viewport — with the mobile browser's
           address bar hidden. While it's showing (the common case), this
           overshoots the real visible height, so the shell no longer fits and
           the whole page scrolls as one block instead of just the thread —
           header and composer drift off with it. 100dvh tracks the actual
           visible viewport and is layered on top for browsers that support it;
           vh stays as the fallback for ones that don't. The .8rem matches the
           padding reserved above by .app-layout:has(.chat-section). */
        height: calc(100vh - var(--navbar-height) - var(--bottom-nav-height) - .8rem);
        height: calc(100dvh - var(--navbar-height) - var(--bottom-nav-height) - .8rem);
    }
    /* Belt and suspenders: keep header/composer pinned to the shell's own
       edges even if some device's height math is still off by a few pixels. */
    .chat-header { position: sticky; top: 0; z-index: 5; }
    .chat-composer-wrap { position: sticky; bottom: 0; z-index: 5; }
}

@media (max-width: 560px) {
    .page { padding: var(--space) .8rem; }
    .app-layout {
        padding: var(--space) .8rem
                 calc(var(--bottom-nav-height) + var(--space) + env(safe-area-inset-bottom));
    }
    .grid-cards { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
    .flash-stack { left: 12px; right: 12px; max-width: none; }
    .page-title { font-size: 1.4rem; }
    .chat-back { display: grid; }
    .bubble { max-width: 85%; }
    .footer-inner { flex-direction: column; text-align: center; }
    .footer-links { justify-content: center; }
}



/* ==========================================================================
   Posts
   A full-height vertical feed. On phones it is pinned between the top bar and
   the bottom bar, so nothing (author, caption, buttons) can hide behind them.
   ========================================================================== */
.posts-main { padding-bottom: 0; }
.posts-shell { position: relative; max-width: 440px; margin: 0 auto; }

.posts-bar {
    position: absolute; top: 0; left: 0; right: 0; z-index: 6;
    display: flex; align-items: center; justify-content: space-between;
    padding: .85rem 1rem 1.6rem; pointer-events: none;
    background: linear-gradient(to bottom, rgba(0,0,0,.62), rgba(0,0,0,0));
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.posts-bar > * { pointer-events: auto; }
.posts-title { margin: 0; color: #fff; font-size: 1.2rem; letter-spacing: .01em; text-shadow: 0 1px 6px rgba(0,0,0,.5); }
.posts-new {
    display: inline-flex; align-items: center; gap: .35rem; padding: .48rem .95rem;
    border-radius: 999px; color: #fff; font-weight: 650; font-size: .88rem; text-decoration: none;
    background: linear-gradient(135deg, var(--brand), var(--accent));
    box-shadow: 0 4px 14px rgba(124, 58, 237, .45);
}
.posts-new:hover { color: #fff; text-decoration: none; filter: brightness(1.08); }

.posts-feed {
    height: calc(100vh - var(--navbar-height) - 3rem);
    height: calc(100dvh - var(--navbar-height) - 3rem);
    overflow-y: auto; scroll-snap-type: y mandatory; scrollbar-width: none;
    overscroll-behavior: contain; background: #000;
    border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
}
.posts-feed::-webkit-scrollbar { display: none; }

.post-card {
    position: relative; height: 100%; overflow: hidden; color: #fff; background: #000;
    scroll-snap-align: start; scroll-snap-stop: always; user-select: none; -webkit-user-select: none;
}
.post-media { width: 100%; height: 100%; display: block; object-fit: contain; background: #000; }
.post-media.is-cover { object-fit: cover; }
.post-shade {
    position: absolute; inset: 0; pointer-events: none;
    background:
        linear-gradient(to top, rgba(0,0,0,.78) 0%, rgba(0,0,0,.28) 28%, rgba(0,0,0,0) 52%),
        linear-gradient(to bottom, rgba(0,0,0,.35), rgba(0,0,0,0) 14%);
}

.post-meta { position: absolute; left: 1rem; right: 5rem; bottom: 1.25rem; display: grid; gap: .55rem; }
.post-author { display: flex; align-items: center; gap: .6rem; color: #fff; text-decoration: none; min-width: 0; }
.post-author:hover { text-decoration: none; color: #fff; }
.post-author .list-avatar {
    width: 44px; height: 44px; flex-shrink: 0;
    box-shadow: 0 0 0 2px #fff, 0 2px 10px rgba(0,0,0,.4);
}
.post-author-text { display: grid; line-height: 1.25; min-width: 0; }
.post-author-name {
    display: inline-flex; align-items: center; gap: .3rem; font-weight: 700; font-size: .98rem;
    text-shadow: 0 1px 4px rgba(0,0,0,.6); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.post-author-name .icon { color: #60a5fa; flex-shrink: 0; }
.post-age { font-size: .76rem; opacity: .8; }
.post-caption {
    margin: 0; font-size: .93rem; line-height: 1.45; cursor: pointer; overflow-wrap: anywhere;
    text-shadow: 0 1px 4px rgba(0,0,0,.6);
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
}
.post-caption.is-open { -webkit-line-clamp: unset; line-clamp: unset; max-height: 38vh; overflow-y: auto; }

.post-actions {
    position: absolute; right: .7rem; bottom: 1.2rem;
    display: flex; flex-direction: column; align-items: center; gap: 1rem;
}
.post-action {
    display: grid; justify-items: center; gap: .22rem; padding: 0; border: 0; background: none;
    color: #fff; cursor: pointer; font-size: .76rem; font-weight: 650; text-decoration: none;
    text-shadow: 0 1px 3px rgba(0,0,0,.6); -webkit-tap-highlight-color: transparent;
}
.post-action:hover { color: #fff; text-decoration: none; }
.post-action-icon {
    display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%;
    background: rgba(20, 20, 30, .42); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
    transition: transform .15s ease, background .15s ease;
}
.post-action:active .post-action-icon { transform: scale(.88); }
.post-action.is-on .post-action-icon { color: #ff4d8d; background: rgba(255,255,255,.92); }
.post-action.is-pop .post-action-icon { animation: post-pop .38s ease; }
@keyframes post-pop { 0% { transform: scale(1); } 40% { transform: scale(1.28); } 100% { transform: scale(1); } }

.post-sound-icon { display: grid; place-items: center; }
.post-sound .post-sound-on, .post-sound.has-sound .post-sound-off { display: none; }
.post-sound.has-sound .post-sound-on { display: grid; }
.post-sound.has-sound .post-action-icon { background: rgba(124, 58, 237, .85); }   /* sound on reads at a glance */
.post-sound { margin-bottom: -.4rem; }          /* sits snug against Like, which is right below it */

.post-progress { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: rgba(255,255,255,.22); }
.post-progress i { display: block; height: 100%; width: 0; background: #fff; }

.post-paused {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(.8);
    width: 84px; height: 84px; display: grid; place-items: center; border-radius: 50%;
    background: rgba(0,0,0,.45); opacity: 0; pointer-events: none; transition: opacity .15s, transform .15s;
}
.post-card.is-paused .post-paused { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.post-burst {
    position: absolute; top: 50%; left: 50%; pointer-events: none; color: #ff4d8d; opacity: 0;
    transform: translate(-50%, -50%) scale(.4); filter: drop-shadow(0 4px 14px rgba(0,0,0,.5));
}
.post-burst.is-live { animation: post-burst .7s ease-out; }
@keyframes post-burst {
    0% { opacity: 0; transform: translate(-50%, -50%) scale(.4); }
    25% { opacity: 1; transform: translate(-50%, -50%) scale(1.15); }
    100% { opacity: 0; transform: translate(-50%, -62%) scale(1.3); }
}

.posts-empty {
    height: 100%; display: grid; place-content: center; justify-items: center; gap: .7rem;
    text-align: center; color: #fff; padding: 2rem;
    background: radial-gradient(circle at 50% 35%, #312e81, #020617 70%);
}
.posts-empty h2 { margin: 0; }
.posts-empty p { margin: 0; opacity: .8; }
.posts-empty-icon {
    display: grid; place-items: center; width: 76px; height: 76px; border-radius: 50%;
    background: rgba(255,255,255,.12);
}

/* ---- comments sheet ------------------------------------------------------ */
.comment-sheet {
    position: fixed; inset: 0; z-index: 70; display: flex; align-items: flex-end;
    justify-content: center; background: rgba(2, 6, 23, .55);
}
.comment-sheet[hidden] { display: none; }
.comment-panel {
    width: 100%; max-width: 520px; height: 72vh; height: min(72dvh, 620px); display: flex; flex-direction: column;
    background: var(--surface); color: var(--ink); padding: .5rem 1rem 0;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0; box-shadow: var(--shadow-lg);
    animation: sheet-up .22s ease-out;
}
@keyframes sheet-up { from { transform: translateY(40px); opacity: 0; } to { transform: none; opacity: 1; } }
.comment-grab { width: 42px; height: 4px; border-radius: 4px; background: var(--line); margin: .15rem auto .6rem; }
.comment-head {
    display: flex; justify-content: space-between; align-items: center;
    padding-bottom: .6rem; border-bottom: 1px solid var(--line);
}
.comment-close { background: none; border: 0; color: var(--ink-soft); cursor: pointer; padding: .3rem; }
.comment-list { list-style: none; margin: 0; padding: .4rem 0; overflow-y: auto; flex: 1; min-height: 0; }
.comment-item { display: flex; gap: .65rem; padding: .6rem 0; }
.comment-avatar {
    flex-shrink: 0; width: 34px; height: 34px; border-radius: 50%; overflow: hidden;
    display: grid; place-items: center; font-weight: 700; font-size: .85rem; color: #fff;
    background: linear-gradient(135deg, var(--brand), var(--accent));
}
.comment-avatar img { width: 100%; height: 100%; object-fit: cover; }
.comment-body { min-width: 0; }
.comment-who { font-size: .84rem; font-weight: 650; }
.comment-who small { color: var(--ink-muted); font-weight: 400; margin-left: .4rem; }
.comment-text { margin: .1rem 0 0; overflow-wrap: anywhere; font-size: .93rem; }
.comment-empty { color: var(--ink-muted); text-align: center; padding: 2.2rem 0; }
.comment-form {
    display: flex; gap: .5rem; padding: .7rem 0 calc(.7rem + env(safe-area-inset-bottom));
    border-top: 1px solid var(--line);
}
.comment-form .form-input { flex: 1; min-width: 0; border-radius: 999px; font-size: max(16px, 1rem); }  /* 16px: no iOS zoom */
.comment-form .btn { flex-shrink: 0; }

/* ---- composer ------------------------------------------------------------ */
.post-composer { max-width: 560px; position: relative; }
.post-close {
    position: absolute; top: .9rem; right: .9rem; z-index: 2; width: 38px; height: 38px;
    display: grid; place-items: center; border-radius: 50%;
    color: var(--ink-soft); background: var(--brand-wash); border: 1px solid var(--line);
    transition: background .15s, color .15s, transform .2s;
}
.post-close:hover { color: var(--ink); background: var(--line); text-decoration: none; transform: rotate(90deg); }
.post-composer-head { display: flex; align-items: center; gap: .85rem; padding-right: 2.9rem; }
.post-composer-badge {
    flex: none; display: grid; place-items: center; width: 46px; height: 46px; border-radius: 14px; color: #fff;
    background: linear-gradient(135deg, var(--brand), var(--accent)); box-shadow: 0 6px 16px rgba(124, 58, 237, .35);
}
.post-composer h1 { margin: 0 0 .1rem; font-size: 1.45rem; }
.post-composer-lead { color: var(--ink-soft); margin: 0; font-size: .92rem; }
.post-drop {
    position: relative; display: grid; place-items: center; min-height: 300px; cursor: pointer; overflow: hidden;
    border: 2px dashed var(--brand-light); border-radius: var(--radius-lg);
    background: linear-gradient(160deg, var(--brand-wash), var(--canvas));
    transition: border-color .15s, background .15s;
}
.post-drop:hover { border-color: var(--brand); }
.post-drop.has-file { border-style: solid; border-color: var(--line); background: #000; }
.post-drop-hint { display: grid; justify-items: center; gap: .35rem; color: var(--ink-soft); text-align: center; padding: 1.4rem; }
.post-drop-icon {
    display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%; color: #fff;
    background: linear-gradient(135deg, var(--brand), var(--accent)); margin-bottom: .3rem;
}
.post-drop-hint strong { color: var(--ink); font-size: 1.05rem; }
.post-preview { max-width: 100%; max-height: 460px; display: block; }
.post-preview[hidden], .post-drop-hint[hidden] { display: none; }
.post-change {
    position: absolute; right: .7rem; top: .7rem; padding: .3rem .75rem; border-radius: 999px;
    font-size: .8rem; font-weight: 650; color: #fff; background: rgba(20,20,30,.6);
}
.post-change[hidden] { display: none; }
.form-hint { color: var(--ink-muted); display: block; margin-top: .3rem; font-size: .82rem; }
.post-drop-types { display: flex; gap: .45rem; margin: .2rem 0 .3rem; }
.post-drop-types span {
    display: inline-flex; align-items: center; gap: .3rem; padding: .2rem .65rem; border-radius: 999px;
    font-size: .78rem; font-weight: 650; color: var(--brand); background: var(--surface); border: 1px solid var(--line);
}
.post-drop-icon { animation: post-drop-pulse 2.4s ease-out infinite; }
@keyframes post-drop-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(124, 58, 237, .45); }
    70%  { box-shadow: 0 0 0 16px rgba(124, 58, 237, 0); }
    100% { box-shadow: 0 0 0 0 rgba(124, 58, 237, 0); }
}
.composer-caption-top { display: flex; align-items: baseline; justify-content: space-between; }
.composer-caption-top .form-label { margin: 0; }
.post-count { font-size: .8rem; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.post-count.is-near { color: var(--warn); font-weight: 700; }
.post-error {
    margin: 0; padding: .65rem .85rem; font-size: .9rem; border-radius: var(--radius-sm);
    color: var(--danger); background: rgba(220, 38, 38, .1); border: 1px solid rgba(220, 38, 38, .3);
}
.post-error[hidden] { display: none; }
.post-share {
    justify-content: center; gap: .55rem; padding: .95rem 1.2rem; font-size: 1.02rem; margin-top: .2rem;
    background: linear-gradient(135deg, var(--brand), var(--accent));
    box-shadow: 0 8px 20px rgba(124, 58, 237, .35);
}
.post-share:disabled { box-shadow: none; filter: saturate(.5); opacity: .5; }

/* ---- upload progress ----------------------------------------------------- */
body.is-uploading { overflow: hidden; }
.post-uploading {
    position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; padding: 1.5rem;
    background: rgba(2, 6, 23, .72); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    animation: upload-fade .2s ease both;
}
.post-uploading[hidden] { display: none; }
.upload-card {
    width: min(320px, 100%); display: grid; justify-items: center; gap: 1rem; text-align: center;
    padding: 1.7rem 1.4rem 1.2rem; background: var(--surface); color: var(--ink);
    border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
    animation: upload-rise .35s cubic-bezier(.2, .8, .2, 1) both;
}
.upload-ring { position: relative; width: 120px; height: 120px; }
.upload-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); overflow: visible; }
.upload-ring circle { fill: none; stroke-width: 9; }
.upload-track { stroke: var(--line); }
.upload-bar {
    stroke-linecap: round; stroke-dasharray: 263.9; stroke-dashoffset: 263.9;
    transition: stroke-dashoffset .25s ease; filter: drop-shadow(0 0 6px rgba(236, 72, 153, .5));
}
.upload-ring.is-waiting svg { animation: upload-spin 1.1s linear infinite; }
.upload-ring.is-waiting .upload-bar { stroke-dashoffset: 190 !important; }
.upload-percent {
    position: absolute; inset: 0; display: grid; place-items: center;
    font-size: 1.55rem; font-weight: 800; font-variant-numeric: tabular-nums;
}
.upload-dots { display: flex; gap: .5rem; }
.upload-dots i {
    width: 11px; height: 11px; border-radius: 50%;
    background: linear-gradient(135deg, var(--brand), var(--accent));
    animation: upload-bounce 1s ease-in-out infinite;
}
.upload-dots i:nth-child(2) { animation-delay: .15s; }
.upload-dots i:nth-child(3) { animation-delay: .3s; }
.upload-message { margin: 0; min-height: 1.5em; font-weight: 650; }
.upload-message.is-in { animation: upload-text .4s ease both; }
.upload-cancel {
    border: 0; background: none; cursor: pointer; padding: .3rem .8rem;
    font: inherit; font-size: .85rem; color: var(--ink-muted);
}
.upload-cancel:hover { color: var(--ink); text-decoration: underline; }
@keyframes upload-fade   { from { opacity: 0; } }
@keyframes upload-rise   { from { opacity: 0; transform: translateY(16px) scale(.96); } }
@keyframes upload-spin   { to   { transform: rotate(270deg); } }
@keyframes upload-bounce { 0%, 80%, 100% { transform: translateY(0) scale(.8); opacity: .6; }
                           40% { transform: translateY(-9px) scale(1.1); opacity: 1; } }
@keyframes upload-text   { from { opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) {
    .post-drop-icon, .upload-dots i, .upload-ring.is-waiting svg,
    .upload-card, .post-uploading, .upload-message.is-in { animation: none; }
}
.row-actions { display: flex; justify-content: flex-end; gap: .6rem; }
.post-locked { display: grid; justify-items: center; gap: .6rem; text-align: center; padding: 1rem .5rem; }
.post-locked-icon {
    display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%;
    color: var(--brand); background: var(--brand-wash);
}
.post-perks { list-style: none; margin: .2rem 0; padding: 0; display: grid; gap: .35rem; color: var(--ink-soft); }

@media (max-width: 900px) {      /* same breakpoint as the bottom bar */
    .posts-shell {
        position: fixed; z-index: 10; max-width: none; margin: 0;
        top: var(--navbar-height); left: 0; right: 0;
        bottom: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom));
    }
    .posts-feed { height: 100%; border-radius: 0; box-shadow: none; }
    .posts-bar { border-radius: 0; }
    /* "New post" lives in the bottom bar on a phone. */
    .posts-bar .posts-new { display: none; }
    body:has(.posts-shell) { overflow: hidden; }
}

/* Any phone: keep the actions, caption and comment box on screen. */
@media (max-width: 900px) and (max-height: 700px) {
    .post-action-icon { width: 42px; height: 42px; }
    .post-actions { gap: .7rem; bottom: .9rem; }
    .post-meta { bottom: 1rem; }
    .post-author .list-avatar { width: 38px; height: 38px; }
}
@media (max-width: 900px) and (max-height: 480px) {          /* phone on its side */
    .post-action-icon { width: 36px; height: 36px; }
    .post-actions { gap: .4rem; bottom: .6rem; }
    .post-action { font-size: .68rem; }
    .post-meta { right: 4.2rem; bottom: .7rem; gap: .35rem; }
    .post-caption { -webkit-line-clamp: 1; line-clamp: 1; }
    .comment-panel { height: 94vh; height: 94dvh; max-width: none; }
}
@media (max-width: 360px) {                                  /* small phones */
    .post-meta { left: .8rem; right: 4.4rem; }
    .post-actions { right: .5rem; }
    .post-action-icon { width: 44px; height: 44px; }
    .post-caption { font-size: .88rem; }
    .comment-panel { padding-left: .8rem; padding-right: .8rem; }
}

/* ==========================================================================
   Calls
   ========================================================================== */
.chat-system {
    align-self: center; display: inline-flex; align-items: center; gap: .4rem;
    margin: .5rem auto; padding: .25rem .75rem; border-radius: 999px;
    background: var(--brand-wash); color: var(--ink-soft); font-size: .78rem;
}
.chat-system time { color: var(--ink-muted); }

.call-avatar {
    display: grid; place-items: center; overflow: hidden; border-radius: 50%;
    width: 84px; height: 84px; font-size: 2rem; font-weight: 700; color: #fff;
    background: linear-gradient(135deg, var(--brand), var(--accent));
}
.call-avatar img { width: 100%; height: 100%; object-fit: cover; }
.call-avatar-lg { width: 132px; height: 132px; font-size: 3rem; }

.call-btn {
    display: grid; place-items: center; width: 58px; height: 58px; border: 0;
    border-radius: 50%; cursor: pointer; color: #fff; background: rgba(255,255,255,.18);
    backdrop-filter: blur(6px);
}
.call-btn[hidden] { display: none; }
.call-btn-end { background: #dc2626; }
.call-btn-accept { background: #16a34a; }

.call-ring {
    position: fixed; inset: 0; z-index: 90; display: grid; place-items: center;
    background: rgba(2, 6, 23, .72);
}
.call-ring[hidden], .call-screen[hidden], .call-picker[hidden] { display: none; }
.call-ring-card {
    display: grid; justify-items: center; gap: .5rem; padding: 1.6rem 2rem;
    width: min(88vw, 340px); text-align: center; color: #fff;
    border-radius: var(--radius-lg); background: #0f172a; box-shadow: var(--shadow-lg);
}
.call-ring-name { margin: .3rem 0 0; font-size: 1.25rem; font-weight: 650; }
.call-ring-kind { margin: 0; opacity: .75; }
.call-ring-actions { display: flex; gap: 2.2rem; margin-top: 1rem; }

.call-screen {
    position: fixed; inset: 0; z-index: 95; display: grid; color: #fff;
    background: #020617; overflow: hidden;
}
.call-local {
    position: absolute; right: 1rem; top: 4.5rem; width: 110px; aspect-ratio: 3/4;
    object-fit: cover; border-radius: var(--radius); background: #111;
    border: 2px solid rgba(255,255,255,.5); transform: scaleX(-1);
}
.call-top {
    position: absolute; top: 0; left: 0; right: 0; z-index: 2;
    display: grid; gap: .1rem; padding: 1rem; text-align: center;
    padding-top: calc(1rem + env(safe-area-inset-top));
    background: linear-gradient(to bottom, rgba(0,0,0,.55), transparent);
}
.call-status { opacity: .8; font-size: .9rem; font-variant-numeric: tabular-nums; }
.call-controls {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
    display: flex; justify-content: center; gap: 1.2rem;
    padding: 1.4rem 1rem calc(1.6rem + env(safe-area-inset-bottom));
    background: linear-gradient(to top, rgba(0,0,0,.6), transparent);
}
body.in-call { overflow: hidden; }


/* ==========================================================================
   Chat, Telegram-style
   The thread scrolls on its own between a fixed header and a fixed message
   box, over a faint doodle background. On phones an open conversation takes
   the whole screen, so the box is always in view — nothing to scroll to.
   ========================================================================== */
:root { --chat-doodle: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='170'%20height='170'%20viewBox='0%200%20170%20170'%20fill='none'%20stroke='rgb%28124%2C58%2C237%29'%20stroke-opacity='.14'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M30%2052c-9-7-14-12-14-18a8%208%200%200%201%2014-5%208%208%200%200%201%2014%205c0%206-5%2011-14%2018z'/%3E%3Cpath%20d='M118%2026l5%2011%2012%201-9%208%203%2012-11-6-11%206%203-12-9-8%2012-1z'/%3E%3Cpath%20d='M96%2096h42a6%206%200%200%201%206%206v20a6%206%200%200%201-6%206h-24l-12%2010v-10h-6a6%206%200%200%201-6-6v-20a6%206%200%200%201%206-6z'/%3E%3Cpath%20d='M34%20118m-12%200a12%2012%200%201%200%2024%200a12%2012%200%201%200-24%200'/%3E%3Cpath%20d='M20%2092q10-12%2020%200t20%200'/%3E%3Cpath%20d='M150%2070v16M142%2078h16'/%3E%3Cpath%20d='M70%2070m-5%200a5%205%200%201%200%2010%200a5%205%200%201%200-10%200'/%3E%3C/svg%3E"); }
@media (prefers-color-scheme: dark) {
    :root { --chat-doodle: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='170'%20height='170'%20viewBox='0%200%20170%20170'%20fill='none'%20stroke='white'%20stroke-opacity='.08'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M30%2052c-9-7-14-12-14-18a8%208%200%200%201%2014-5%208%208%200%200%201%2014%205c0%206-5%2011-14%2018z'/%3E%3Cpath%20d='M118%2026l5%2011%2012%201-9%208%203%2012-11-6-11%206%203-12-9-8%2012-1z'/%3E%3Cpath%20d='M96%2096h42a6%206%200%200%201%206%206v20a6%206%200%200%201-6%206h-24l-12%2010v-10h-6a6%206%200%200%201-6-6v-20a6%206%200%200%201%206-6z'/%3E%3Cpath%20d='M34%20118m-12%200a12%2012%200%201%200%2024%200a12%2012%200%201%200-24%200'/%3E%3Cpath%20d='M20%2092q10-12%2020%200t20%200'/%3E%3Cpath%20d='M150%2070v16M142%2078h16'/%3E%3Cpath%20d='M70%2070m-5%200a5%205%200%201%200%2010%200a5%205%200%201%200-10%200'/%3E%3C/svg%3E"); }
}

.chat-thread {
    min-height: 0;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    background-color: var(--canvas);
    background-image:
        var(--chat-doodle),
        radial-gradient(circle at 20% 10%, rgba(124,58,237,.07), transparent 45%),
        radial-gradient(circle at 85% 80%, rgba(236,72,153,.06), transparent 45%);
    background-size: 170px 170px, auto, auto;
}
/* Few messages sit at the bottom, next to the box, as in every chat app. */
.chat-thread > :first-child { margin-top: auto; }
.chat-shell { min-height: 0; }

@media (max-width: 860px) {
    .chat-section.has-thread .chat-shell {
        position: fixed; inset: 0; z-index: 60;
        height: 100vh; height: 100dvh;
        border: 0; border-radius: 0;
        grid-template-rows: auto minmax(0, 1fr) auto auto;
        padding-top: env(safe-area-inset-top);
        background: var(--surface);
    }
    .chat-section.has-thread .chat-header { position: static; }
    .chat-section.has-thread .chat-composer-wrap {
        /* Stays the anchor for the attach and emoji popovers, which open
           upwards from the box. "static" here sent them off-screen. */
        position: relative;
        padding-bottom: env(safe-area-inset-bottom);
        background: var(--surface);
    }
    .chat-section.has-thread .chat-composer { border-top: 0; padding: .5rem .6rem; }
    /* Attach and emoji menus are pinned to the screen, just above the message
       box. They no longer depend on which ancestor is the positioning anchor,
       so no layout change can push them off-screen. */
    .chat-section.has-thread .composer-popover {
        position: fixed; left: .6rem; right: auto; z-index: 70;
        bottom: calc(4.3rem + env(safe-area-inset-bottom));
        max-width: calc(100vw - 1.2rem); max-height: 45dvh; overflow-y: auto;
    }
    .chat-section.has-thread .composer-input { background: var(--canvas); }
    .chat-section.has-thread .typing-indicator { background: var(--surface); }
    /* The page behind must not scroll under the full-screen conversation. */
    body:has(.chat-section.has-thread) { overflow: hidden; }
}

/* ==========================================================================
   Notification popups (WhatsApp-style)
   ========================================================================== */
.notify-stack {
    position: fixed; z-index: 85; top: 74px; right: 18px; width: min(380px, calc(100vw - 36px));
    display: flex; flex-direction: column; gap: .6rem; pointer-events: none;
}
.notify-card {
    position: relative; display: flex; align-items: center; gap: .8rem; pointer-events: auto;
    padding: .75rem 2.2rem .75rem .75rem; cursor: pointer; color: var(--ink);
    background: var(--surface); border: 1px solid var(--line); border-radius: 16px;
    box-shadow: var(--shadow-lg); animation: notify-in .28s cubic-bezier(.2, .9, .3, 1.2);
    border-left: 4px solid var(--brand);
}
.notify-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.notify-card.is-leaving { opacity: 0; transform: translateY(-10px) scale(.97); transition: opacity .2s, transform .2s; }
@keyframes notify-in { from { opacity: 0; transform: translateY(-14px) scale(.96); } to { opacity: 1; transform: none; } }

.notify-message { border-left-color: #22c55e; }
.notify-like, .notify-super_like { border-left-color: var(--accent); }
.notify-match { border-left-color: #f59e0b; }
.notify-missed_call { border-left-color: var(--danger); }
.notify-summary { border-left-color: var(--brand-light); }

.notify-avatar {
    position: relative; flex-shrink: 0; width: 46px; height: 46px; border-radius: 50%;
    display: grid; place-items: center; color: #fff;
    background: linear-gradient(135deg, var(--brand), var(--accent));
}
.notify-avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.notify-kind {
    position: absolute; right: -3px; bottom: -3px; width: 20px; height: 20px; border-radius: 50%;
    display: grid; place-items: center; color: #fff; background: var(--brand);
    border: 2px solid var(--surface);
}
.notify-message .notify-kind { background: #22c55e; }
.notify-like .notify-kind, .notify-super_like .notify-kind { background: var(--accent); }
.notify-match .notify-kind { background: #f59e0b; }
.notify-missed_call .notify-kind { background: var(--danger); }

.notify-text { min-width: 0; flex: 1; line-height: 1.3; }
.notify-top { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; }
.notify-top strong { font-size: .93rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.notify-top time { flex-shrink: 0; font-size: .72rem; color: var(--ink-muted); }
.notify-text p {
    margin: .12rem 0 0; font-size: .86rem; color: var(--ink-soft); overflow-wrap: anywhere;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
}
.notify-close {
    position: absolute; top: .45rem; right: .45rem; width: 24px; height: 24px; border: 0; border-radius: 50%;
    display: grid; place-items: center; cursor: pointer; color: var(--ink-muted); background: transparent;
}
.notify-close:hover { background: var(--line); color: var(--ink); }

@media (max-width: 860px) {
    .notify-stack {
        top: calc(env(safe-area-inset-top) + 8px); left: 10px; right: 10px; width: auto;
    }
}

/* The "turn on system notifications" card on the notifications page. */
.notify-prompt {
    display: flex; align-items: center; gap: .9rem; margin-bottom: 1rem; padding: .85rem 1rem;
    border-radius: var(--radius); border: 1px solid var(--line);
    background: linear-gradient(135deg, var(--brand-wash), var(--surface));
}
.notify-prompt[hidden] { display: none; }
.notify-prompt-icon {
    flex-shrink: 0; display: grid; place-items: center; width: 42px; height: 42px; border-radius: 50%;
    color: #fff; background: linear-gradient(135deg, var(--brand), var(--accent));
}
.notify-prompt-text { flex: 1; min-width: 0; line-height: 1.35; }
.notify-prompt-text strong { display: block; }
.notify-prompt-text small { color: var(--ink-soft); }
.notify-prompt-actions { display: flex; gap: .4rem; flex-shrink: 0; }
@media (max-width: 560px) {
    .notify-prompt { flex-wrap: wrap; }
    .notify-prompt-actions { width: 100%; justify-content: flex-end; }
}


/* ==========================================================================
   Desktop shell, Facebook-style
   The menu is attached to the top bar and the left edge: no card, no border,
   the same background as the page. It is fixed, so scrolling the page moves
   only the content; when the menu is longer than the screen it scrolls on its
   own, with a thin scrollbar that appears on hover. Phones keep the slide-out
   drawer, so none of this applies below 861px.
   ========================================================================== */
@media (min-width: 861px) {
    :root { --sidebar-width: 272px; }

    .sidebar {
        position: fixed; z-index: 30;
        top: var(--navbar-height); left: 0; bottom: 0; width: var(--sidebar-width);
        padding: .75rem .55rem 1.2rem;
        background: var(--canvas); border: 0; border-radius: 0; box-shadow: none;
        overflow-y: auto; overscroll-behavior: contain;
        scrollbar-width: thin; scrollbar-color: transparent transparent;
    }
    .sidebar:hover, .sidebar:focus-within { scrollbar-color: var(--ink-muted) transparent; }
    .sidebar::-webkit-scrollbar { width: 8px; }
    .sidebar::-webkit-scrollbar-track { background: transparent; }
    .sidebar::-webkit-scrollbar-thumb { background: transparent; border-radius: 8px; }
    .sidebar:hover::-webkit-scrollbar-thumb,
    .sidebar:focus-within::-webkit-scrollbar-thumb { background: var(--ink-muted); }

    /* The page makes room for the fixed menu and centres its content in what is left. */
    .app-layout {
        display: block; max-width: none; margin: 0;
        padding: calc(var(--space) * 1.5);
        padding-left: calc(var(--sidebar-width) + var(--space) * 1.5);
    }
    .app-content { max-width: 1040px; margin: 0 auto; }

    /* Items: a round coloured icon, a bold label, a soft highlight on hover. */
    .sidebar-nav { gap: .1rem; }
    .sidebar-link {
        gap: .8rem; padding: .45rem .6rem; border-radius: 10px;
        color: var(--ink); font-size: .95rem; font-weight: 600;
    }
    .sidebar-icon {
        display: grid; place-items: center; flex-shrink: 0;
        width: 36px; height: 36px; border-radius: 50%;
        background: var(--brand-wash); color: var(--brand);
    }
    .sidebar-avatar { width: 36px; height: 36px; }
    .sidebar-link:hover { background: rgba(124, 58, 237, .10); color: var(--ink); }
    .sidebar-link.is-active { background: rgba(124, 58, 237, .18); color: var(--ink); }
    .sidebar-link.is-active .sidebar-icon { background: var(--brand); color: #fff; }
    .sidebar-link .badge { margin-left: auto; }
    .sidebar-danger .sidebar-icon { background: rgba(220, 38, 38, .12); }
    .sidebar-danger:hover { background: rgba(220, 38, 38, .10); }
    .sidebar-divider { margin: .6rem .5rem; }
}

/* ==========================================================================
   Group calls: the participant grid and the contact picker
   ========================================================================== */
.call-local[hidden] { display: none; }
.call-grid {
    position: absolute; inset: 0; display: grid; gap: 2px; background: #000;
    grid-template-columns: 1fr; grid-auto-rows: 1fr;
}
.call-grid.grid-2 { grid-template-rows: 1fr 1fr; }
.call-grid.grid-3 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.call-grid.grid-3 .call-tile:nth-child(3) { grid-column: 1 / -1; }
@media (min-width: 861px) {
    .call-grid.grid-2 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr; }
}
.call-tile {
    position: relative; display: grid; place-items: center; overflow: hidden; min-height: 0;
    background: radial-gradient(circle at 50% 40%, #312e81, #020617 70%);
}
.call-tile video {
    position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
    background: #000; display: none;
}
.call-grid:not(.is-voice) .call-tile.has-stream video { display: block; }
.call-grid:not(.is-voice) .call-tile.has-stream .call-tile-avatar { display: none; }
.call-tile-avatar { width: 104px; height: 104px; font-size: 2.4rem; }
.call-grid.grid-3 .call-tile-avatar, .call-grid.grid-2 .call-tile-avatar { width: 84px; height: 84px; font-size: 2rem; }
.call-tile-name {
    position: absolute; left: .7rem; bottom: .7rem; max-width: calc(100% - 1.4rem);
    padding: .18rem .65rem; border-radius: 999px; font-size: .86rem; font-weight: 650;
    background: rgba(0, 0, 0, .5); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.call-tile-state {
    position: absolute; top: 4.2rem; left: 50%; transform: translateX(-50%);
    font-size: .8rem; opacity: .8; text-shadow: 0 1px 3px rgba(0,0,0,.6);
}
.call-tile-state:empty { display: none; }

.call-picker {
    position: fixed; inset: 0; z-index: 98; display: flex; align-items: flex-end; justify-content: center;
    background: rgba(2, 6, 23, .62);
}
.call-picker-card {
    width: min(460px, 100%); max-height: 78vh; max-height: 78dvh; display: flex; flex-direction: column;
    padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom)); color: var(--ink);
    background: var(--surface); border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--shadow-lg); animation: sheet-up .22s ease-out;
}
@media (min-width: 861px) {
    .call-picker { align-items: center; }
    .call-picker-card { border-radius: var(--radius-lg); }
}
.call-picker-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: .6rem; }
.call-picker-close { background: none; border: 0; cursor: pointer; color: var(--ink-soft); padding: .3rem; }
.call-picker-kind { display: flex; gap: .5rem; margin-bottom: .6rem; }
.call-picker-list { list-style: none; margin: 0; padding: 0; overflow-y: auto; min-height: 3rem; }
.call-picker-empty { color: var(--ink-muted); padding: 1.2rem .4rem; text-align: center; }
.call-picker-item {
    display: flex; align-items: center; gap: .75rem; width: 100%; padding: .55rem .6rem;
    border: 0; border-radius: 12px; background: none; color: inherit; font: inherit;
    text-align: left; cursor: pointer;
}
.call-picker-item:hover:not(:disabled) { background: var(--canvas); }
.call-picker-item:disabled { opacity: .5; cursor: not-allowed; }
.call-picker-item.is-chosen { background: var(--brand-wash); }
.call-picker-avatar { width: 42px; height: 42px; font-size: 1rem; flex-shrink: 0; }
.call-picker-name { flex: 1; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.call-picker-item small { color: var(--ink-muted); }
.call-picker-mark { width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--line); flex-shrink: 0; }
.call-picker-item.is-chosen .call-picker-mark {
    border-color: var(--brand); background: var(--brand) radial-gradient(circle, #fff 28%, transparent 30%);
}
.call-picker-foot { display: flex; align-items: center; justify-content: space-between; gap: .8rem; padding-top: .8rem; border-top: 1px solid var(--line); margin-top: .5rem; }
.call-picker-hint { color: var(--ink-soft); font-size: .86rem; }

.rail-action {
    margin-left: auto; display: inline-flex; align-items: center; gap: .35rem; padding: .3rem .7rem;
    border: 1px solid var(--line); border-radius: 999px; background: var(--surface); cursor: pointer;
    color: var(--ink-soft); font: inherit; font-size: .78rem; font-weight: 650; text-decoration: none;
}
.rail-action:hover { color: var(--brand); border-color: var(--brand); text-decoration: none; }


/* ==========================================================================
   In-call controls: muted state, minimize, the small window, the banner
   ========================================================================== */
.call-btn .ic-off, .call-mini-btn .ic-off { display: none; }
.call-btn[aria-pressed="true"] .ic-on, .call-mini-btn[aria-pressed="true"] .ic-on { display: none; }
.call-btn[aria-pressed="true"] .ic-off, .call-mini-btn[aria-pressed="true"] .ic-off { display: block; }
/* Muted or camera off: a red button with the crossed-out icon, as in Meet and WhatsApp. */
.call-btn[aria-pressed="true"] { background: #dc2626; color: #fff; }
.call-mini-btn[aria-pressed="true"] { background: #dc2626; color: #fff; }

.call-top { grid-template-columns: 1fr; }
.call-minimize {
    position: absolute; left: .7rem; top: calc(.7rem + env(safe-area-inset-top));
    width: 40px; height: 40px; display: grid; place-items: center; border: 0; border-radius: 50%;
    cursor: pointer; color: #fff; background: rgba(255, 255, 255, .16);
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.call-minimize:hover { background: rgba(255, 255, 255, .28); }

/* Minimized: a slim bar across the very top, like a phone call in progress. The
   page moves down to make room rather than being covered, and a tap on the bar
   returns to the call. The remote video stays in the page (hidden) so the
   audio carries on. */
:root { --call-bar-height: 46px; --call-offset: 0px; }
body.in-call-mini {
    --call-offset: calc(var(--call-bar-height) + env(safe-area-inset-top));
    padding-top: var(--call-offset);
}
.call-mini { display: none; }
.call-screen.is-mini {
    inset: 0 0 auto 0; width: 100%; height: var(--call-offset, 46px);
    z-index: 96; cursor: pointer; border: 0; border-radius: 0;
    background: linear-gradient(90deg, #6d28d9, #be185d);
    box-shadow: 0 4px 18px rgba(0, 0, 0, .35);
    animation: mini-in .2s ease-out;
}
@keyframes mini-in { from { transform: translateY(-100%); } to { transform: none; } }
.call-screen.is-mini .call-grid,
.call-screen.is-mini .call-top,
.call-screen.is-mini .call-controls,
.call-screen.is-mini .call-local { display: none; }
.call-screen.is-mini .call-mini {
    position: absolute; inset: auto 0 0 0; height: var(--call-bar-height);
    display: flex; align-items: center; gap: .5rem; padding: 0 .8rem;
}
.call-mini-text { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: .6rem; font-size: .88rem; }
.call-mini-text strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .92rem; }
.call-mini-text span { opacity: .9; font-variant-numeric: tabular-nums; white-space: nowrap; }
.call-mini-text span::after { content: " · tap to return"; opacity: .75; font-size: .78rem; }
.call-mini-btn {
    width: 32px; height: 32px; display: grid; place-items: center; flex-shrink: 0;
    border: 0; border-radius: 50%; cursor: pointer; color: #fff; background: rgba(255, 255, 255, .22);
}
.call-mini-btn.is-end { background: #dc2626; }
@media (max-width: 380px) { .call-mini-text span::after { content: ""; } }

/* Everything that is pinned to the top moves down by the height of the bar. */
body.in-call-mini .navbar { top: var(--call-offset); }
@media (min-width: 861px) {
    body.in-call-mini .sidebar { top: calc(var(--navbar-height) + var(--call-offset)); }
}
@media (max-width: 860px) {
    body.in-call-mini .posts-shell { top: calc(var(--navbar-height) + var(--call-offset)); }
    body.in-call-mini .chat-section.has-thread .chat-shell { inset: var(--call-offset) 0 0 0; }
    body.in-call-mini .notify-stack { top: calc(env(safe-area-inset-top) + var(--call-offset) + 8px); }
}
body.in-call-mini .call-banner { top: calc(var(--call-offset) + 10px); }

.call-banner {
    position: fixed; top: calc(10px + env(safe-area-inset-top)); left: 50%; transform: translateX(-50%);
    z-index: 96; display: flex; align-items: center; gap: .6rem; max-width: calc(100vw - 20px);
    padding: .6rem .8rem .6rem 1rem; color: #fff; background: #0f172a;
    border: 1px solid rgba(255, 255, 255, .16); border-radius: 16px; box-shadow: var(--shadow-lg);
}
.call-banner[hidden] { display: none; }
.call-banner-text { font-weight: 600; font-size: .92rem; }
.call-banner .btn-ghost { color: #fff; border-color: rgba(255, 255, 255, .3); }

.call-picker-search { margin-bottom: .6rem; border-radius: 999px; }
.call-banner-text, .call-banner .btn { white-space: nowrap; }
@media (max-width: 420px) { .call-banner { gap: .4rem; padding-left: .8rem; } .call-banner-text { font-size: .85rem; } }


/* ==========================================================================
   Plans
   ========================================================================== */
.plans-grid {
    display: grid; gap: 1.2rem; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
    max-width: 780px; margin: 0 auto;
}
.plans-grid .plan { position: relative; display: flex; flex-direction: column; }
.plan-ribbon {
    position: absolute; top: -.7rem; right: 1rem; padding: .18rem .75rem; border-radius: 999px;
    font-size: .74rem; font-weight: 700; letter-spacing: .03em; color: #fff;
    background: linear-gradient(135deg, var(--brand), var(--accent)); box-shadow: var(--shadow);
}
.plan-interval { margin-left: .3rem; font-size: .95rem; font-weight: 600; color: var(--ink-muted); }
.plan-usd { margin: 0; font-size: .8rem; color: var(--ink-muted); }
.plan-permonth { margin: .25rem 0 0; font-size: .86rem; font-weight: 650; color: var(--ok); }
.launch-note {
    display: flex; align-items: center; gap: .8rem; max-width: 780px; margin: 0 auto 1.2rem;
    padding: .8rem 1rem; border-radius: var(--radius); border: 1px solid var(--line);
    background: linear-gradient(135deg, var(--brand-wash), var(--surface));
}
.launch-note > div { display: grid; line-height: 1.35; }
.launch-note small { color: var(--ink-soft); }
.launch-note-icon {
    flex-shrink: 0; display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%;
    color: #fff; background: linear-gradient(135deg, var(--brand), var(--accent));
}

/* The three feature cards on the front page suit wide screens; on a phone they
   only push the sign-up buttons' neighbours down the page, so they are hidden. */
@media (max-width: 640px) {
    .landing-features { display: none; }
}


/* ==========================================================================
   Page frame and footer
   The page is a full-height column, so on a short page the footer sits at the
   bottom of the screen instead of floating mid-way with empty space beneath it.
   ========================================================================== */
body { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
body > main { flex: 1 0 auto; width: 100%; }
body > .footer { flex-shrink: 0; }

.footer { margin-top: 0; padding-bottom: calc(var(--space) * 1.6 + env(safe-area-inset-bottom)); }
.footer-copy {
    flex-basis: 100%; margin: .2rem 0 0; padding-top: var(--space);
    border-top: 1px solid var(--line); text-align: center;
    font-size: .78rem; color: var(--ink-muted);
}

@media (max-width: 640px) {
    .footer { padding: 1.4rem 1rem calc(1.1rem + env(safe-area-inset-bottom)); }
    .footer-inner { flex-direction: column; align-items: center; text-align: center; gap: 1rem; }
    .footer-brand { text-align: center; }
    /* Five links as an even, wrapping row of comfortable tap targets. */
    .footer-links {
        justify-content: center; gap: .25rem .35rem; max-width: none; width: 100%;
    }
    .footer-links a {
        padding: .45rem .7rem; border-radius: 999px; font-size: .9rem;
    }
    .footer-links a:active { background: var(--brand-wash); color: var(--brand); }
}
@media (max-width: 360px) {
    .footer-links a { padding: .4rem .55rem; font-size: .84rem; }
    .footer-tagline { font-size: .8rem; }
}


/* ==========================================================================
   Front page: everything on one screen, nothing to scroll
   Sizes follow the screen's height as well as its width, so the header, the
   headline, the buttons and the footer fit together on a phone or a laptop.
   Below 340px of height there is not room to fit it, so the page scrolls rather
   than hiding anything.
   ========================================================================== */
@media (min-height: 340px) {
    body.landing-page { height: 100vh; height: 100dvh; overflow: hidden; }
    body.landing-page > main {
        flex: 1 1 0; min-height: 0; padding-top: 0; padding-bottom: 0;
        display: flex; flex-direction: column; justify-content: center;
    }
    .landing-page .hero { padding: clamp(.3rem, 2vh, 1.6rem) 1rem; }
    .landing-page .hero-title {
        font-size: clamp(1.75rem, 3.2vw + 2.8vh, 3.6rem); margin-bottom: .3em;
    }
    .landing-page .hero-sub {
        font-size: clamp(.92rem, .9vw + 1.2vh, 1.15rem);
        margin-bottom: clamp(.8rem, 2.8vh, 1.8rem);
    }
    .landing-page .landing-features { margin-top: clamp(.4rem, 2vh, 1.6rem); gap: clamp(.5rem, 1.5vh, 1rem); }
    .landing-page .feature { padding: clamp(.6rem, 1.8vh, 1.2rem) 1.1rem; }
    .landing-page .feature-text { font-size: clamp(.82rem, .5vw + .8vh, .92rem); line-height: 1.45; }

    .landing-page .footer { padding-top: clamp(.5rem, 1.6vh, 1.4rem); padding-bottom: calc(clamp(.5rem, 1.6vh, 1.4rem) + env(safe-area-inset-bottom)); }
    .landing-page .footer-copy { margin: 0; padding-top: .45rem; }
}
/* Short screens: drop the tagline and tighten, so the rest stays readable. */
@media (min-height: 340px) and (max-height: 720px) {
    .landing-page .footer-tagline { display: none; }
    .landing-page .footer-inner { gap: .4rem; }
}
@media (min-height: 340px) and (max-height: 600px) {
    .landing-page .footer-copy { display: none; }
}

/* A phone on its side: a very short screen, so the footer shrinks to its links. */
@media (min-height: 340px) and (max-height: 460px) {
    .landing-page .landing-features { display: none; }
    .landing-page .navbar { --navbar-height: 52px; height: 52px; }
    .landing-page .hero { padding-top: .1rem; padding-bottom: .1rem; }
    .landing-page .hero-title { font-size: clamp(1.4rem, 5vh, 1.9rem); margin-bottom: .2em; }
    .landing-page .hero-sub { font-size: .85rem; margin-bottom: .6rem; line-height: 1.4; }
    .landing-page .hero-actions .btn { padding: .5rem 1.2rem; }
    .landing-page .footer-brand { display: none; }
    .landing-page .footer-links a { padding: .2rem .55rem; }
}
.landing-page .hero-sub { max-width: 40rem; text-wrap: balance; }

/* Phones: the headline stays near the top, the paragraph drops one gap below it,
   and the buttons drop two gaps below where they started, so the three read as
   evenly spaced. The gap follows the screen's height so it still fits. The
   gap sits on the headline's own margin (not the paragraph's) so it cannot be
   swallowed by margin collapsing. */
@media (max-width: 640px) and (min-height: 340px) {
    body.landing-page { --landing-gap: clamp(.8rem, 4vh, 2.6rem); }
    body.landing-page > main { justify-content: flex-start; }
    .landing-page .hero { padding-top: clamp(1.2rem, 9.8vh, 5rem); }
    .landing-page .hero-title { margin-bottom: calc(.3em + var(--landing-gap)); }
    .landing-page .hero-sub {
        margin-top: 0;
        margin-bottom: calc(clamp(.8rem, 2.8vh, 1.8rem) + var(--landing-gap));
    }
}

/* ==========================================================================
   Front page: animated background and the story of the app
   ========================================================================== */
html:has(body.landing-page), body.landing-page { overflow-x: hidden; }
body.landing-page > * { max-width: 100vw; }
@media (min-height: 340px) { html:has(body.landing-page) { overflow: hidden; } }

/* The header must never be wider than the screen, however large the member's
   text or display size is set. */
.landing-page .navbar-inner { min-width: 0; gap: .5rem; }
.landing-page .navbar-actions { min-width: 0; }   /* spacing otherwise as on every other page */
@media (max-width: 400px) {
    .landing-page .navbar-inner { padding-left: .8rem; padding-right: .8rem; }
    .landing-page .navbar-brand { font-size: 1.1rem; }
    .landing-page .navbar .btn-sm { padding: .4rem .65rem; font-size: .8rem; }
}
@media (max-width: 320px) {
    .landing-page .navbar .btn-sm { padding: .36rem .5rem; font-size: .76rem; }
}

/* ---- the drifting, floating background -------------------------------------- */
.landing-bg { position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
body.landing-page > main, body.landing-page > .footer { position: relative; z-index: 1; }
.landing-page .footer { background: color-mix(in srgb, var(--canvas) 72%, transparent); }

.bg-glow {
    position: absolute; width: 70vmax; height: 70vmax; border-radius: 50%; opacity: .32;
    animation: glow-drift 24s ease-in-out infinite alternate; will-change: transform;
}
.bg-glow.g1 { top: -25vmax; left: -20vmax; background: radial-gradient(circle, var(--brand), transparent 62%); }
.bg-glow.g2 { bottom: -28vmax; right: -22vmax; background: radial-gradient(circle, var(--accent), transparent 62%); animation-duration: 29s; animation-delay: -9s; }
.bg-glow.g3 { top: 25%; left: 38%; width: 46vmax; height: 46vmax; opacity: .16; background: radial-gradient(circle, #0ea5e9, transparent 62%); animation-duration: 33s; animation-delay: -15s; }
@keyframes glow-drift {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to   { transform: translate3d(6vmax, 4vmax, 0) scale(1.18); }
}

.bg-card {
    position: absolute; left: var(--x); bottom: -26%; width: 124px; padding: 10px; border-radius: 16px;
    background: color-mix(in srgb, var(--surface) 72%, transparent); border: 1px solid var(--line);
    box-shadow: var(--shadow); opacity: 0;
    animation: card-rise var(--d) linear infinite; animation-delay: var(--delay); will-change: transform;
}
.bg-card .av { display: block; width: 34px; height: 34px; border-radius: 50%; background: linear-gradient(135deg, var(--brand), var(--accent)); }
.bg-card b { display: block; height: 7px; border-radius: 4px; margin-top: 8px; background: var(--line); }
.bg-card b.short { width: 58%; }
@keyframes card-rise {
    0%   { opacity: 0;   transform: translateY(0) rotate(-4deg) scale(var(--s)); }
    10%  { opacity: .34; }
    90%  { opacity: .34; }
    100% { opacity: 0;   transform: translateY(-150vh) rotate(5deg) scale(var(--s)); }
}
/* ---- the story: match, chat, call (12 seconds, looping) ----------------------- */
.landing-stage {
    /* An even margin on each side that grows with the screen, so the scene is
       centred with a gap on both sides on every phone. */
    flex: 1 1 0; min-height: 0; max-height: 240px; padding: 0 clamp(1.5rem, 9vw, 3.2rem); overflow: hidden;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .55rem;
}
@media (max-height: 640px) { .landing-stage { display: none; } }

.story {
    /* Size follows both the height and the width, so on a narrow phone the two
       people never grow past the space they have. */
    --h: clamp(64px, min(13vh, 30vw), 116px);
    width: min(440px, 100%); height: var(--h);
    display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: .5rem;
}
.who { position: relative; display: grid; justify-items: center; }
.story-avatar {
    display: grid; place-items: center; color: #fff;
    width: calc(var(--h) * .58); height: calc(var(--h) * .58); border-radius: 50%;
    background: linear-gradient(135deg, var(--brand), var(--accent));
    box-shadow: 0 0 0 4px rgba(124, 58, 237, .2); animation: avatar-pulse 3s ease-in-out infinite;
}
.who-b .story-avatar { background: linear-gradient(135deg, #0ea5e9, var(--brand)); animation-delay: -1.5s; }
@keyframes avatar-pulse { 0%, 100% { transform: scale(.96); } 50% { transform: scale(1.04); } }

.story .chip {
    position: absolute; opacity: 0; white-space: nowrap; padding: .12rem .5rem; border-radius: 999px;
    font-size: .68rem; font-weight: 700; color: var(--brand); background: var(--brand-wash);
    border: 1px solid var(--line); animation: chip-life 12s infinite;
}
/* One chip above each avatar and one below, centred, so none is clipped by the
   edge of the screen or covers a face. */
.story .chip { left: 0; right: 0; margin-inline: auto; width: max-content; }
.story .chip-1, .story .chip-3 { top: -13px; }
.story .chip-2, .story .chip-4 { bottom: -13px; }
.story .chip-2 { animation-delay: .35s; }
.story .chip-3 { animation-delay: .15s; }
.story .chip-4 { animation-delay: .5s; }
@keyframes chip-life {
    0% { opacity: 0; transform: translateY(6px); }
    5% { opacity: 1; transform: none; }
    30% { opacity: 1; }
    36%, 100% { opacity: 0; }
}

.story-mid { position: relative; height: 100%; display: grid; place-items: center; }
.story-mid > * { position: absolute; }
.story-link { left: 0; right: 0; top: 50%; height: 4px; transform: translateY(-50%); overflow: visible; }
.story-link path {
    fill: none; stroke: var(--brand-light); stroke-width: 2; stroke-linecap: round;
    stroke-dasharray: 100; stroke-dashoffset: 100; animation: link-draw 12s infinite;
}
@keyframes link-draw {
    0%, 18% { stroke-dashoffset: 100; opacity: 1; }
    32% { stroke-dashoffset: 0; opacity: 1; }
    46% { stroke-dashoffset: 0; opacity: 1; }
    50%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
.story-match {
    display: grid; justify-items: center; gap: .1rem; opacity: 0; color: var(--accent);
    font-size: .82rem; font-weight: 800; animation: match-pop 12s infinite;
}
@keyframes match-pop {
    0%, 30% { opacity: 0; transform: scale(.4); }
    35% { opacity: 1; transform: scale(1.18); }
    39% { transform: scale(1); }
    48% { opacity: 1; }
    52%, 100% { opacity: 0; transform: scale(.9); }
}
.story-bubble {
    opacity: 0; white-space: nowrap; padding: .32rem .7rem; font-size: clamp(.66rem, 2.7vw, .78rem); font-weight: 600;
    color: var(--ink); background: var(--surface); border: 1px solid var(--line);
}
.bubble-1 { top: 0; left: 0; border-radius: 14px 14px 14px 4px; animation: bubble-in 12s infinite; }
.bubble-2 {
    bottom: 0; right: 0; border-radius: 14px 14px 4px 14px; color: #fff;
    background: var(--brand); border-color: var(--brand); animation: bubble-in-2 12s infinite;
}
@keyframes bubble-in {
    0%, 52% { opacity: 0; transform: translateY(8px); }
    57% { opacity: 1; transform: none; }
    80% { opacity: 1; }
    86%, 100% { opacity: 0; }
}
@keyframes bubble-in-2 {
    0%, 61% { opacity: 0; transform: translateY(8px); }
    66% { opacity: 1; transform: none; }
    80% { opacity: 1; }
    86%, 100% { opacity: 0; }
}
.story-call {
    display: flex; align-items: center; gap: clamp(.4rem, 2vw, .7rem); padding: .5rem clamp(.65rem, 3vw, .9rem); border-radius: 999px; color: #fff;
    background: linear-gradient(90deg, #16a34a, #22c55e); opacity: 0;
    animation: call-in 12s infinite, call-ring 1.4s ease-out infinite;
}
@keyframes call-in {
    0%, 73% { opacity: 0; transform: scale(.7); }
    78% { opacity: 1; transform: scale(1); }
    93% { opacity: 1; }
    98%, 100% { opacity: 0; }
}
@keyframes call-ring {
    0% { box-shadow: 0 0 0 0 rgba(34, 197, 94, .55); }
    100% { box-shadow: 0 0 0 16px rgba(34, 197, 94, 0); }
}

.story-caption { position: relative; width: 100%; height: 1.5em; margin: 0; text-align: center; font-size: .92rem; font-weight: 650; color: var(--ink-soft); }
.cap { position: absolute; inset: 0; opacity: 0; }
.cap-a { animation: cap-a 12s infinite; }
.cap-b { animation: cap-b 12s infinite; }
.cap-c { animation: cap-c 12s infinite; }
@keyframes cap-a { 0% { opacity: 0; } 3%, 46% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes cap-b { 0%, 50% { opacity: 0; } 54%, 70% { opacity: 1; } 74%, 100% { opacity: 0; } }
@keyframes cap-c { 0%, 74% { opacity: 0; } 78%, 93% { opacity: 1; } 97%, 100% { opacity: 0; } }

@media (max-width: 640px) {
    .bg-card { width: 92px; padding: 8px; }
    .bg-card .av { width: 26px; height: 26px; }
    .story-caption { font-size: .86rem; }
}
/* Anyone who has asked their device for less motion gets the finished scene, still. */
@media (prefers-reduced-motion: reduce) {
    .bg-glow, .bg-card, .story-avatar, .story-call, .story .chip, .story-link path { animation: none; }
    .bg-card { display: none; }
    .story-link path { stroke-dashoffset: 0; }
    .story-match, .story-bubble, .story .chip { opacity: 1; animation: none; }
    .story-call { display: none; }
    .cap { animation: none; }
    .cap-a { opacity: 1; }
}

/* Hidden (but still measurable) when the screen has no room for the whole story. */
.landing-stage.is-cramped > * { visibility: hidden; }

@media (max-width: 340px) {
    .footer-links { gap: 0; }
    .footer-links a { padding: .35rem .34rem; font-size: .8rem; }
}

/* Five footer links stay on one row down to the narrowest phones, by tightening
   in steps as the screen narrows. */
@media (max-width: 420px) {
    .footer-links { gap: .1rem; }
    .footer-links a { padding: .45rem .5rem; font-size: .88rem; }
}
@media (max-width: 360px) {
    .footer-links a { padding: .4rem .38rem; font-size: .84rem; }
}

/* ==========================================================================
   Onboarding: photo step
   Photos are a compact grid, so a handful of them never pushes Continue out of
   sight, and Continue stays pinned to the bottom of the screen.
   ========================================================================== */
.photo-thumbs { display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem; }
.photo-thumbs img {
    width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--radius-sm);
    background: var(--canvas);
}
.photo-add, .photo-drop {
    display: grid; place-items: center; align-content: center; gap: .3rem; cursor: pointer;
    color: var(--brand); border: 2px dashed var(--brand-light); border-radius: var(--radius);
    background: linear-gradient(160deg, var(--brand-wash), var(--canvas));
    transition: border-color .15s, opacity .15s;
}
.photo-add { aspect-ratio: 1; font-size: .78rem; font-weight: 700; border-radius: var(--radius-sm); }
.photo-add:hover, .photo-drop:hover { border-color: var(--brand); }
.photo-drop { padding: 2rem 1rem; text-align: center; }
.photo-drop strong { color: var(--ink); font-size: 1.05rem; }
.photo-drop small { color: var(--ink-soft); }
.photo-drop-icon {
    display: grid; place-items: center; width: 62px; height: 62px; border-radius: 50%; color: #fff;
    background: linear-gradient(135deg, var(--brand), var(--accent)); margin-bottom: .3rem;
}
.photo-add.is-busy, .photo-drop.is-busy { opacity: .5; pointer-events: none; }
.photo-status { margin: 0; text-align: center; font-weight: 650; color: var(--brand); }
.photo-status[hidden] { display: none; }

.photo-step .wizard-continue {
    position: sticky; bottom: calc(.8rem + env(safe-area-inset-bottom)); z-index: 5;
    margin-top: .4rem; padding-top: .6rem;
    background: linear-gradient(to top, var(--surface) 65%, transparent);
}
.photo-step .wizard-continue .btn { box-shadow: 0 8px 24px rgba(124, 58, 237, .35); }
.photo-step .wizard-continue .btn:disabled { box-shadow: none; }


/* ==========================================================================
   Turning on alerts, and the call "tap to hear" prompt
   ========================================================================== */
.push-ask {
    position: fixed; z-index: 80; left: 50%; transform: translateX(-50%);
    bottom: calc(var(--bottom-nav-height, 0px) + 14px + env(safe-area-inset-bottom));
    display: flex; align-items: center; gap: .75rem; width: min(440px, calc(100vw - 24px));
    padding: .7rem .8rem; border-radius: 16px; color: var(--ink);
    background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow-lg);
    animation: push-ask-in .3s ease-out;
}
@keyframes push-ask-in { from { opacity: 0; transform: translate(-50%, 14px); } to { opacity: 1; transform: translate(-50%, 0); } }
.push-ask-icon {
    flex-shrink: 0; display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%;
    color: #fff; background: linear-gradient(135deg, var(--brand), var(--accent));
}
.push-ask-text { flex: 1; min-width: 0; display: grid; line-height: 1.3; }
.push-ask-text small { color: var(--ink-soft); }
.push-ask-no { border: 0; background: none; color: var(--ink-muted); cursor: pointer; padding: .3rem; }
@media (min-width: 861px) { .push-ask { bottom: 18px; } }
body.in-call .push-ask, body.in-call-mini .push-ask { display: none; }

.call-tap {
    position: absolute; z-index: 5; left: 50%; top: 5.5rem; transform: translateX(-50%);
    padding: .65rem 1.2rem; border: 0; border-radius: 999px; cursor: pointer; white-space: nowrap;
    font: inherit; font-weight: 700; color: #0f172a; background: #fff; box-shadow: 0 8px 24px rgba(0, 0, 0, .4);
}

/* Icon-only action row on a public profile. */
.profile-actions { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1rem; }
.pa {
    position: relative; width: 46px; height: 46px; display: grid; place-items: center; padding: 0;
    border: 1px solid var(--line); border-radius: 50%; background: var(--surface);
    color: var(--ink-muted); cursor: pointer; text-decoration: none; transition: all .14s;
}
.pa:hover { text-decoration: none; transform: translateY(-1px); color: var(--brand); border-color: var(--brand); }
.pa-primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.pa-primary:hover { color: #fff; filter: brightness(1.08); }
.pa-like:hover, .pa-like.is-on { color: var(--accent); border-color: var(--accent); }
.pa.is-on { cursor: default; color: var(--accent); border-color: var(--accent); background: rgba(236, 72, 153, .08); }
.pa.is-on:hover { transform: none; }
.pa-danger:hover { color: #dc2626; border-color: #dc2626; }
.pa:disabled { opacity: .45; cursor: not-allowed; transform: none; }
.pa-lock { position: absolute; right: 5px; bottom: 5px; display: grid; color: var(--ink-muted); }

/* Replying and reacting in a chat. */
.bubble { position: relative; }
.bubble.has-reactions { margin-bottom: 1rem; }
.bubble.is-flash { animation: bubble-flash 1.4s ease-out; }
@keyframes bubble-flash { 0%, 60% { box-shadow: 0 0 0 3px var(--brand-light); } 100% { box-shadow: 0 0 0 0 transparent; } }
.bubble-quote {
    display: block; margin-bottom: .3rem; padding: .25rem .5rem; border-radius: 8px;
    border-left: 3px solid var(--brand); background: rgba(124, 58, 237, .1);
    color: inherit; text-decoration: none; font-size: .8rem; line-height: 1.25;
}
.bubble-quote.is-mine { border-left-color: var(--accent); }
.bubble.is-mine .bubble-quote { background: rgba(255, 255, 255, .18); border-left-color: #fff; }
.bubble-quote b { display: block; font-size: .72rem; opacity: .9; }
.bubble-quote span { display: block; opacity: .85; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.bubble-more {
    position: absolute; top: 2px; right: 4px; width: 22px; height: 22px; padding: 0;
    display: none; place-items: center; border: 0; border-radius: 50%; cursor: pointer;
    color: inherit; background: rgba(0, 0, 0, .18);
}
@media (hover: hover) { .bubble:hover > .bubble-more { display: grid; } }
.bubble-reactions { position: absolute; bottom: -.85rem; right: .5rem; display: flex; gap: .2rem; }
.bubble:not(.is-mine) .bubble-reactions { right: auto; left: .5rem; }
.reaction-chip {
    padding: 0 .35rem; height: 22px; font-size: .78rem; line-height: 1; cursor: pointer; color: var(--ink);
    border: 1px solid var(--line); border-radius: 999px; background: var(--surface);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}
.reaction-chip.is-mine { border-color: var(--brand); background: var(--brand-wash); }

.msg-menu {
    position: absolute; z-index: 30; top: 100%; left: 0; margin-top: 4px; min-width: 200px;
    padding: .35rem; color: var(--ink); background: var(--surface); border: 1px solid var(--line);
    border-radius: 14px; box-shadow: var(--shadow-lg);
}
.msg-menu.is-mine { left: auto; right: 0; }
.msg-menu-reacts { display: flex; gap: .1rem; justify-content: space-between; }
.msg-menu-reacts button {
    width: 34px; height: 34px; font-size: 1.2rem; cursor: pointer; border: 0; border-radius: 50%; background: none;
}
.msg-menu-reacts button:hover { background: var(--brand-wash); }
.msg-menu-reply {
    display: flex; align-items: center; gap: .4rem; width: 100%; margin-top: .25rem; padding: .45rem .55rem;
    border: 0; border-radius: 8px; cursor: pointer; color: inherit; background: none; font: inherit; font-size: .85rem;
}
.msg-menu-reply:hover { background: var(--brand-wash); }

.reply-bar {
    display: flex; align-items: center; gap: .6rem; margin: 0 .5rem; padding: .4rem .6rem;
    border-left: 3px solid var(--brand); border-radius: 8px 8px 0 0; background: var(--brand-wash);
}
.reply-bar[hidden] { display: none; }
.reply-bar-text { flex: 1; min-width: 0; font-size: .8rem; }
.reply-bar-text b { display: block; color: var(--brand); font-size: .74rem; }
.reply-bar-text span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-muted); }
.reply-bar-close { border: 0; background: none; color: var(--ink-muted); cursor: pointer; padding: .2rem; }

.bubble { touch-action: pan-y; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.bubble.is-swipe-ready::before {
    content: ""; position: absolute; left: -34px; top: 50%; width: 22px; height: 22px; margin-top: -11px;
    border-radius: 50%; background: var(--brand) center / 12px no-repeat;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='white'%3E%3Cpath d='M5.921 11.9 1.353 8.62a.72.72 0 0 1 0-1.238L5.921 4.1A.716.716 0 0 1 7 4.719V6c1.5 0 6 0 7 8-2.5-4.5-7-4-7-4v1.281c0 .56-.606.898-1.079.62z'/%3E%3C/svg%3E");
}


/* ==========================================================================
   Install-the-app sheet (static/js/install.js)
   ========================================================================== */
.install-sheet {
    position: fixed; left: .75rem; right: .75rem; z-index: 70;
    bottom: calc(.75rem + env(safe-area-inset-bottom));
    max-width: 440px; margin: 0 auto;
    padding: 1.1rem 1.1rem 1rem;
    background: var(--surface); color: var(--ink);
    border: 1px solid var(--line); border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    animation: install-in .32s cubic-bezier(.2, .8, .2, 1) both;
}
.install-sheet--above-nav {
    bottom: calc(var(--bottom-nav-height) + .75rem + env(safe-area-inset-bottom));
}
.install-sheet.is-leaving { animation: install-out .2s ease-in both; }
.install-head { display: flex; align-items: center; gap: .85rem; padding-right: 1.6rem; }
.install-icon { flex: none; width: 56px; height: 56px; border-radius: 14px; box-shadow: var(--shadow-sm); }
.install-head h2 { margin: 0 0 .15rem; font-size: 1.1rem; }
.install-head p { margin: 0; font-size: .9rem; color: var(--ink-soft); }
.install-perks, .install-steps {
    margin: .9rem 0 0; padding: 0; display: grid; gap: .45rem;
    font-size: .9rem; color: var(--ink-soft);
}
.install-perks { list-style: none; }
.install-perks li { padding-left: 1.4rem; position: relative; }
.install-perks li::before {
    content: "\2713"; position: absolute; left: 0; font-weight: 700; color: var(--brand);
}
.install-steps { padding-left: 1.25rem; }
.install-steps b { color: var(--ink); }
.install-share {
    display: inline-grid; place-items: center; width: 1.7rem; height: 1.7rem; vertical-align: middle;
    border-radius: 8px; background: var(--brand-wash); color: var(--brand);
}
.install-actions { display: flex; gap: .6rem; margin-top: 1rem; }
.install-actions .btn { flex: 1; justify-content: center; }
.install-close {
    position: absolute; top: .45rem; right: .55rem; width: 2rem; height: 2rem;
    border: 0; background: transparent; color: var(--ink-muted); font-size: 1.5rem; line-height: 1; cursor: pointer;
}
@keyframes install-in  { from { opacity: 0; transform: translateY(28px); } }
@keyframes install-out { to   { opacity: 0; transform: translateY(28px); } }
@media (prefers-reduced-motion: reduce) {
    .install-sheet, .install-sheet.is-leaving { animation: none; }
}
@media (min-width: 821px), (display-mode: standalone) { .install-sheet { display: none; } }
