/* ============================================================
   show&watch
   1. tokens   2. reset   3. layout   4. chrome
   5. components  6. pages   7. responsive
   ============================================================ */

/* ---- 1. tokens ---- */
:root{
  --ink:#FFFFFF;
  --ink-2:#F6F3F8;
  --wine:#EFE6FF;
  --flare:#8B5CF6;
  --flare-rgb:139,92,246;
  --ink-rgb:255,255,255;
  --cream-rgb:43,34,51;
  --sand-rgb:110,100,120;
  --cream:#2B2233;
  --sand:#6E6478;
  --sand-dim:rgba(110,100,120,.85);
  --line:rgba(43,34,51,.10);
  --gold:#E8935F;

  --fs-xs:12px;
  --fs-sm:14px;
  --fs:17px;
  --fs-lg:20px;
  --fs-xl:26px;
  --fs-line:clamp(24px,5vw,26px);
  --fs-title:clamp(28px,5vw,40px);
  --fs-hero:clamp(38px,6vw,62px);
  --font:system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;

  --shell:1080px;
  --shell-narrow:560px;
  --pad:clamp(16px,4vw,32px);
  --r:3px;
  --r-pill:999px;
}

/* ---- 2. reset ---- */
*,*::before,*::after{box-sizing:border-box}
*{margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  background:var(--ink);
  color:var(--cream);
  font:400 var(--fs)/1.6 var(--font);
  -webkit-font-smoothing:antialiased;
  overflow-wrap:break-word;
}
img,svg,video{display:block;max-width:100%}

/* The hidden attribute must beat any author display rule.
   Without this, .hidden = true silently does nothing on any
   element whose class sets display. */
a{color:var(--sand);text-decoration-thickness:1px;text-underline-offset:2px}
a:hover:not(.mark){color:var(--flare)}
button{font:inherit;cursor:pointer}
:focus-visible{outline:2px solid var(--flare);outline-offset:2px}

.skip{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;background:var(--flare);color:var(--ink);padding:10px 14px;z-index:99}

/* ---- 3. layout ---- */
.shell{width:min(var(--shell-narrow),100% - var(--pad)*2);margin-inline:auto;padding-block:48px 72px}
.shell-wide,.shell:has(.lp-hero){width:min(var(--shell),100% - var(--pad)*2)}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:40px}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}

/* ---- 4. chrome ---- */
.site-head{position:sticky;top:0;height:71px;background:var(--ink);z-index:30}
.head-in{
  width:min(1180px,100% - var(--pad)*2);margin-inline:auto;
  display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding-block:14px;
}
.mark{display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:var(--cream);font:700 var(--fs-lg)/1 var(--font);letter-spacing:-.02em}
.mark-line{display:inline-flex;align-items:center;gap:7px}
.mark-stack{flex-direction:column;align-items:flex-start;gap:2px;line-height:1.05;font-size:var(--fs-xl)}
/* The script sits between the two plain words, so it holds the
   mark together rather than trailing off the end. Larger than
   its neighbours because script x-heights run small. */
.inline{display:inline}
.linkish{background:none;border:0;color:var(--sand);padding:0}
.linkish:hover{color:var(--flare)}

.site-foot{border-top:1px solid var(--line);margin-top:auto}
.foot-in{
  width:min(var(--shell),100% - var(--pad)*2);margin-inline:auto;
  display:flex;flex-wrap:wrap;gap:14px 28px;align-items:center;justify-content:space-between;
  padding-block:28px 40px;font-size:var(--fs-sm);color:var(--sand-dim);
}
.foot-nav{display:flex;flex-wrap:wrap;gap:18px}
.foot-nav a{text-decoration:none}

body.bare .shell{padding-block:24px}

/* Flash: a toast over the top of the page. It goes by itself, or on a tap. */
.flash{
  position:fixed;left:50%;top:calc(12px + env(safe-area-inset-top));z-index:200;
  width:max-content;max-width:min(92vw,420px);transform:translateX(-50%);
  padding:10px 16px;border-radius:var(--r);background:var(--cream);color:var(--ink);
  font-size:var(--fs-sm);text-align:center;box-shadow:0 6px 24px rgba(0,0,0,.18);cursor:pointer;
  animation:flash-out .3s ease 4.5s forwards;
}
@keyframes flash-out{to{opacity:0;visibility:hidden;transform:translate(-50%,-8px)}}

/* ---- 5. components ---- */
/*
* One button. Size and weight are modifiers, never new classes:
* .btn            primary, filled
* .btn-ghost      secondary, outlined
* .btn-lg/-sm/-xs size
*
* Anything that looked like a button and had its own rule - the follow
* control, the composer chips - uses these instead, so the padding and
* radius live in one place.
*/
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  background:var(--flare);color:var(--ink);
  border:1px solid transparent;border-radius:var(--r-pill);padding:13px 26px;
  font-weight:700;font-size:var(--fs);line-height:1;text-decoration:none;cursor:pointer;
}
.btn:hover{background:var(--gold);color:var(--ink)}
.btn-lg{padding:16px 32px;font-size:var(--fs)}
.btn-sm{padding:9px 16px;font-size:var(--fs-sm)}
.btn-xs{padding:5px 12px;font-size:var(--fs-xs);font-weight:600}
.btn-ghost{background:none;color:var(--sand);border-color:var(--line)}
.btn-ghost:hover{background:none;border-color:var(--flare);color:var(--flare)}
.btn-ghost.on{border-color:var(--line);color:var(--sand-dim)}

.card{padding-block:20px}
.card.face{border-bottom:1px solid var(--line)}
.post-by a{text-decoration:none;font-weight:500;color:var(--cream)}
.post-by span{color:var(--sand-dim);font-size:var(--fs)}
.post-body{margin-top:8px}
.post-foot{margin-top:12px}
.act{display:inline-flex;align-items:center;gap:7px;background:none;border:0;color:var(--sand-dim);padding:4px 0}
.act:hover,.act[aria-pressed="true"]{color:var(--flare)}
.act .count{font-size:var(--fs-sm)}

.face{border:0;padding:0}
.face-img{
  aspect-ratio:1;background:var(--wine);border-radius:var(--r);
  display:grid;place-items:center;color:rgba(var(--cream-rgb),.45);
}
.face-name{margin-top:10px;font-size:var(--fs)}
.face-loc{font-size:var(--fs-sm);color:var(--sand-dim)}

.feature svg{color:var(--flare);margin-bottom:12px}
.feature h3{font-size:var(--fs-lg);font-weight:600;margin-bottom:6px}
.feature p{color:var(--sand);font-size:var(--fs);max-width:32ch}

/* Scoped deliberately: a bare .empty is too generic a name and was
   colliding with modifier classes elsewhere. */
div.empty{border:1px dashed var(--line);border-radius:var(--r);padding:40px 24px;text-align:center}
div.empty .empty-title{font-weight:600}
div.empty .empty-body{color:var(--sand-dim);font-size:var(--fs);margin-top:4px}

.form{display:grid;gap:2px;max-width:400px;margin-top:24px}
.field{display:grid;gap:5px;margin-bottom:16px}
.field label{font-size:var(--fs-sm);color:var(--sand)}
.field input{
  background:transparent;border:1px solid rgba(var(--sand-rgb),.4);
  border-radius:var(--r);padding:12px 14px;color:var(--cream);font:inherit;
}
.field input:focus-visible{border-color:transparent}
.form .btn{margin-top:10px;justify-self:start}

.hint{font-size:var(--fs-sm);color:var(--sand-dim)}
.err{color:var(--flare);font-size:var(--fs-sm)}
.note{font-size:var(--fs-sm);color:var(--sand-dim)}
.muted{font-size:var(--fs);color:var(--sand)}
.lead{color:var(--sand);font-size:var(--fs-lg);max-width:46ch}
.alt{margin-top:26px;font-size:var(--fs);color:var(--sand)}
.kicker{font-size:var(--fs-sm);letter-spacing:.14em;text-transform:uppercase;color:var(--flare);margin-bottom:14px}
.more{display:inline-block;margin-top:24px}

/* ---- 6. pages ---- */
.page-h{font-size:var(--fs-title);font-weight:700;letter-spacing:-.02em;line-height:1.1;margin-bottom:14px}

.lp-hero{padding-block:72px 56px}
.lp-hero h1{font-size:var(--fs-hero);font-weight:700;line-height:1.06;letter-spacing:-.03em}
.lp-hero h1 em{font-style:normal;color:var(--flare)}
.lp-hero .lead{margin-top:20px}
.lp-cta{margin-top:32px;display:flex;flex-wrap:wrap;align-items:center;gap:22px}

.lp-stats{display:flex;flex-wrap:wrap;gap:56px;border-block:1px solid var(--line);padding-block:28px}
.lp-stats strong{font-size:32px;font-weight:700;color:var(--flare);letter-spacing:-.02em}
.lp-stats span{display:block;font-size:var(--fs-sm);color:var(--sand)}

.lp-block{padding-block:72px}
.lp-block h2{font-size:var(--fs-title);font-weight:700;letter-spacing:-.02em;margin-bottom:36px}

.lp-prompt{border:1px solid var(--line);border-radius:var(--r);padding:48px var(--pad);margin-block:16px}
.lp-prompt blockquote{font-size:var(--fs-line);font-weight:600;line-height:1.25;letter-spacing:-.015em;max-width:26ch}
.lp-prompt .note{margin-top:14px}
.lp-prompt p:last-child{margin-top:26px}

.lp-end{padding-block:88px 100px;text-align:center}
.lp-end h2{font-size:var(--fs-title);font-weight:700;letter-spacing:-.02em;margin-bottom:14px}
.lp-end .lead{margin-inline:auto}
.lp-end .btn-lg{margin-top:28px}

.stream{margin-bottom:28px}

/* ---- 7. responsive ---- */
@media (max-width:860px){
  .grid-3{grid-template-columns:1fr;gap:32px}
  .grid-4{grid-template-columns:repeat(2,1fr)}
  .lp-stats{gap:28px}
  .lp-hero{padding-block:48px 40px}
  .lp-block{padding-block:56px}
}

@media (prefers-reduced-motion:reduce){
  *{animation:none !important;transition:none !important}
  html{scroll-behavior:auto}
}

.toast{
  position:fixed;left:50%;bottom:24px;translate:-50% 0;
  background:var(--cream);color:var(--ink);
  padding:12px 20px;border-radius:var(--r);font-size:var(--fs);
  opacity:0;pointer-events:none;transition:opacity .18s;z-index:60;
}
.toast.show{opacity:1}

/* ---- composer ---- */
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
.composer{border:1px solid var(--line);border-radius:var(--r);padding:14px;margin-bottom:28px}
.composer textarea{
  width:100%;background:transparent;border:0;color:var(--cream);
  font:inherit;resize:vertical;min-height:52px;
}
.composer textarea::placeholder{color:var(--sand-dim)}
.composer textarea:focus-visible{outline:0}
.composer-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:10px}
.pick{display:inline-flex;align-items:center;gap:8px;color:var(--sand);font-size:var(--fs-sm);cursor:pointer}
.pick:hover{color:var(--flare)}
.pick input{position:absolute;width:1px;height:1px;opacity:0}
.pick:focus-within{color:var(--flare);outline:2px solid var(--flare);outline-offset:4px;border-radius:2px}
.composer-note{font-size:var(--fs-sm);color:var(--sand-dim);margin-top:8px}

/* ---- post media ---- */
.post-media{position:relative;margin-block:12px;aspect-ratio:4/5;overflow:hidden;border-radius:var(--r);background:var(--ink-2)}
.post-media img,.post-media video{display:block;width:100%;height:100%;object-fit:cover}
.post-media.multi{display:grid;grid-template-columns:1fr 1fr;grid-auto-rows:1fr;gap:6px;background:none}

/* ---- moderation ---- */
.mod-sec{margin-bottom:48px}
.mod-sec h2{font-size:var(--fs-lg);font-weight:600;margin-bottom:18px;display:flex;align-items:center;gap:10px}
.pill{background:var(--wine);color:var(--cream);font-size:var(--fs-sm);font-weight:400;padding:2px 9px;border-radius:20px}
.mod-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:18px}
.mod-item img{width:100%;aspect-ratio:1;object-fit:cover;border-radius:var(--r);background:var(--ink-2)}
.mod-by{font-size:var(--fs-sm);color:var(--sand-dim);margin-top:8px}
.mod-acts{display:flex;gap:8px;margin-top:8px}

.shot{position:relative;margin:0}
.shot img{width:100%;height:auto;border-radius:var(--r);background:var(--ink-2);display:block}
.shot.in-review img{opacity:.55}
.shot figcaption{
  position:absolute;left:10px;bottom:10px;
  background:rgba(var(--ink-rgb),.9);color:var(--sand);
  font-size:var(--fs-sm);padding:5px 10px;border-radius:2px;
}

/* ============ composer ============ */
.composer-head{margin-bottom:16px}
.composer-head h2{font-size:var(--fs);font-weight:700;letter-spacing:-.01em}
.composer-head p{font-size:var(--fs-sm);color:var(--sand-dim)}

.picks{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:8px;margin-bottom:12px}
.pick-tile{
  aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;
  border:1px dashed var(--line);border-radius:var(--r);color:var(--sand-dim);
  font-size:var(--fs-xs);cursor:pointer;text-align:center;padding:6px;
}
.pick-tile:hover{border-color:var(--flare);color:var(--flare)}
.pick-tile input{position:absolute;width:1px;height:1px;opacity:0}
.pick-tile:focus-within{border-color:var(--flare);color:var(--flare)}

.thumb{position:relative;aspect-ratio:1;border-radius:var(--r);overflow:hidden;background:var(--ink-2);cursor:grab}
.thumb img{width:100%;height:100%;object-fit:cover}
.thumb.dragging{opacity:.4}
.thumb .lead{
  position:absolute;left:4px;top:4px;background:var(--flare);color:var(--ink);
  font-size:var(--fs-xs);font-weight:700;padding:2px 6px;border-radius:2px;letter-spacing:.04em;
}
.thumb .drop{
  position:absolute;right:4px;top:4px;width:22px;height:22px;border:0;border-radius:50%;
  background:rgba(var(--ink-rgb),.85);color:var(--cream);display:grid;place-items:center;line-height:1;
}
.picks-note{font-size:var(--fs-sm);color:var(--sand-dim);margin-bottom:12px}

.chip{
  display:inline-flex;align-items:center;gap:7px;background:none;
  border:1px solid var(--line);border-radius:var(--r-pill);padding:7px 14px;
  color:var(--sand);font-size:var(--fs-sm);cursor:pointer;
}
.chip:hover{border-color:var(--flare);color:var(--flare)}

.sheet{border:0;padding:0;background:transparent;max-width:min(520px,94vw)}
.sheet::backdrop{background:rgba(var(--ink-rgb),.72)}
.sheet-in{background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r);padding:22px}
.sheet-in h3{font-size:var(--fs-lg);font-weight:600;margin-bottom:14px}
.starter-list{list-style:none;display:grid;gap:6px;margin-bottom:16px}
.starter{
  width:100%;display:flex;gap:12px;align-items:flex-start;text-align:left;
  background:none;border:1px solid transparent;border-radius:var(--r);padding:11px 12px;color:var(--cream);
}
.starter:hover{border-color:var(--flare);background:rgba(var(--flare-rgb),.07)}
.starter svg{color:var(--flare);flex:0 0 auto;margin-top:2px}
.starter strong{display:block;font-size:var(--fs);font-weight:600}
.starter em{display:block;font-style:normal;font-size:var(--fs-sm);color:var(--sand-dim);margin-top:2px}

/* ---- avatars ----
   One shape for every avatar: a clipped circle that centres whatever is
   inside it, image or fallback icon. Each use below adds only its size,
   and its colours where it sits on a surface that needs different ones.
   Change the shape here and it changes everywhere. */
.post-avatar,.reply-av,.notif-av,.person-av,.cs-open-av,.rail-me-av,
.story-av,.tray-av,.thread-av,.th-av,.msg-av,.buddy-av,.acct-av,.pf-avatar,.mnav-av{
  display:grid;place-items:center;flex:none;
  overflow:hidden;border-radius:50%;
  background:var(--wine);color:var(--sand);
}
.post-avatar img,.reply-av img,.notif-av img,.person-av img,.cs-open-av img,
.rail-me-av img,.story-av img,.tray-av img,.thread-av img,.th-av img,.msg-av img,
.buddy-av img,.acct-av img,.pf-avatar img,.mnav-av img{
  width:100%;height:100%;object-fit:cover;
}

/* ============ post card ============ */
.post-avatar{width:40px;height:40px;color:rgba(var(--cream-rgb),.55)}
.post-who{flex:1;min-width:0}
.post-name{font-size:var(--fs);font-weight:600;display:flex;align-items:center;gap:5px}
.post-name a{color:var(--cream);text-decoration:none}
.post-name a:hover{color:var(--flare)}
.verified{color:var(--flare);display:inline-flex}
.post-meta{font-size:var(--fs-sm);color:var(--sand-dim)}

.menu{position:relative;flex:0 0 auto}
.menu summary{list-style:none;cursor:pointer;color:var(--sand-dim);padding:4px}
.menu summary::-webkit-details-marker{display:none}
.menu summary:hover{color:var(--cream)}
.menu-pop{
  position:absolute;right:0;top:100%;z-index:30;min-width:190px;
  background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r);
  padding:5px;display:grid;gap:1px;
}
.menu-pop button{
  display:flex;align-items:center;gap:9px;width:100%;text-align:left;
  background:none;border:0;color:var(--cream);font-size:var(--fs-sm);padding:9px 10px;border-radius:2px;
}
.menu-pop button:hover{background:rgba(var(--flare-rgb),.12);color:var(--flare)}

.starter-tag{color:var(--flare);font-size:var(--fs-sm);margin-bottom:6px}
.starter-tag a{color:inherit;text-decoration:none}
.starter-tag a:hover{text-decoration:underline}
.post-body{margin-bottom:12px}
.post-body.prompt{font-size:var(--fs-lg);font-weight:600;letter-spacing:-.01em}

/* ---- gallery ---- */
.gal{display:grid;gap:4px;height:100%;grid-auto-rows:1fr;border-radius:var(--r);overflow:hidden}
.gal-2{grid-template-columns:1fr 1fr}
.gal-3{grid-template-columns:2fr 1fr;grid-template-rows:1fr 1fr}
.gal-3 .tile:first-child{grid-row:span 2}
.gal-4{grid-template-columns:1fr 1fr}
.tile{position:relative;padding:0;border:0;background:var(--ink-2);cursor:zoom-in;overflow:hidden;display:block}
.tile img{width:100%;height:100%;object-fit:cover;object-position:50% 30%;display:block}

/* A single photo gets its own aspect, clamped inline by the template
   to somewhere between 4:5 and 1.91:1. Nothing is cut from the file. */

/* Two photos read best as a pair of portraits. Three and four use
   squares, because four 4:5 tiles make a card taller than a screen. */
.more-count{
  position:absolute;inset:0;display:grid;place-items:center;
  background:rgba(var(--ink-rgb),.66);color:var(--cream);font-size:var(--fs-xl);font-weight:700;
}
.tile.in-review img{opacity:.5}
.review-tag{
  position:absolute;left:8px;bottom:8px;background:rgba(var(--ink-rgb),.9);
  color:var(--sand);font-size:var(--fs-xs);padding:4px 8px;border-radius:2px;
}

.post-counts{display:flex;flex-wrap:wrap;gap:14px;font-size:var(--fs-sm);color:var(--sand-dim);margin-bottom:10px}

.post-acts{display:flex;flex-wrap:wrap;gap:6px;padding-top:10px}
/* Same shape as the reels rail, but on a card rather than video: the
   colour comes from the palette, not white-on-dark. */
.post-acts .act{
  flex:1;display:grid;justify-items:center;gap:3px;
  border:0;border-radius:var(--r);padding:8px 6px;
}
.post-acts .act .act-n{font-size:var(--fs-xs);font-weight:600;min-height:14px}
.post-acts .act-face{width:26px;height:26px;object-fit:contain}
.post-acts .act:hover:not(:disabled){color:var(--flare)}
.post-acts .act.on{color:var(--flare)}
.post-acts .act:disabled{opacity:.5;cursor:default}

/* ---- replies ---- */
.replies{border-top:1px solid var(--line);margin-top:12px;padding-top:14px}
.reply{display:flex;gap:10px;padding:8px 0}
.reply.child{margin-left:34px}
.reply-av{width:28px;height:28px;color:rgba(var(--cream-rgb),.55)}
.reply-in{flex:1;min-width:0}
.reply-who{font-size:var(--fs-sm);font-weight:600}
.reply-who a{color:var(--cream);text-decoration:none}
.reply-body{font-size:var(--fs);margin-top:1px}
.reply-acts{display:flex;gap:14px;margin-top:5px;font-size:var(--fs-sm);color:var(--sand-dim)}
.reply-acts button{background:none;border:0;color:inherit;padding:0;display:inline-flex;align-items:center;gap:5px}
.reply-acts button:hover{color:var(--flare)}
.reply-acts button.on{color:var(--flare)}
.reply-signalled{color:var(--flare);font-size:var(--fs-xs);display:inline-flex;align-items:center;gap:4px;margin-top:4px}

.reply-form{display:flex;gap:8px;margin-top:12px;align-items:flex-end}
.reply-form textarea{
  flex:1;background:transparent;border:1px solid var(--line);border-radius:var(--r);
  padding:10px 12px;color:var(--cream);font:inherit;resize:none;min-height:42px;
}
.reply-form textarea::placeholder{color:var(--sand-dim)}
.reply-form button{
  background:var(--flare);color:var(--ink);border:0;border-radius:var(--r);
  width:42px;height:42px;display:grid;place-items:center;flex:0 0 auto;
}
.reply-more{background:none;border:0;color:var(--sand);font-size:var(--fs-sm);padding:6px 0}
.reply-more:hover{color:var(--flare)}

/* ---- lightbox ---- */
/* Anything that covers the page. Saying it once means no component
   can forget that hidden means hidden. */
.overlay{position:fixed;inset:0}

/* The attribute wins. Components set display for their own layout;
   without this each one has to remember what hidden means, and
   the one that forgets renders over the page. */

.lb{position:fixed;inset:0;background:rgba(var(--ink-rgb),.96);z-index:80;display:none;place-items:center}
.lb.open{display:grid}
.lb-track > img{max-width:94vw;max-height:86vh;object-fit:contain}
.lb-close,.lb-prev,.lb-next,.lb-up,.lb-down{
  position:absolute;background:var(--ink);border:0;color:var(--cream);box-shadow:0 2px 8px rgba(0,0,0,.2);z-index:1;
  width:46px;height:46px;border-radius:50%;display:grid;place-items:center;
}
.lb-close{top:18px;right:18px}
.lb-prev{left:14px;top:50%;translate:0 -50%}
.lb-next{right:14px;top:50%;translate:0 -50%}

/* ---- notifications ---- */
.nav-notif{position:relative}
.dot{
  background:var(--flare);color:var(--ink);font-size:var(--fs-xs);font-weight:700;
  border-radius:10px;padding:1px 6px;margin-left:5px;
}
.notif-list{list-style:none;display:grid}
.notif{display:flex;gap:12px;align-items:center;padding:14px 0;border-bottom:1px solid var(--line)}
.notif-av{width:40px;height:40px}
.notif-text{flex:1;font-size:var(--fs)}
.notif-text a{margin-left:8px}
.notif-when{font-size:var(--fs-sm);color:var(--sand-dim);flex:0 0 auto}
.notif.mutual{background:rgba(var(--flare-rgb),.06);padding-inline:12px}

@media (max-width:600px){
  .post-acts .act{padding:8px 4px}
}

/* ============ reels ============ */
.reels{
  height:100dvh;overflow-y:scroll;scroll-snap-type:y mandatory;
  background:#000;margin:0;scrollbar-width:none;
}
.reels::-webkit-scrollbar{display:none}
body:has(.reels){overflow:hidden}

.reel{
  position:relative;height:100dvh;scroll-snap-align:start;scroll-snap-stop:always;
  display:grid;place-items:center;overflow:hidden;
}
.reel-video{width:100%;height:100%;object-fit:contain;background:#000}
.reel-shade{
  position:absolute;inset:auto 0 0 0;height:42%;pointer-events:none;
  background:linear-gradient(to top,rgba(0,0,0,.78),transparent);
}

.reel-info{position:absolute;left:16px;right:84px;bottom:calc(24px + env(safe-area-inset-bottom))}
.reel-who{font-size:var(--fs);font-weight:600}
.reel-who a{color:#fff;text-decoration:none}
.reel-loc{font-size:var(--fs-sm);color:rgba(var(--cream-rgb),.7)}
.reel-cap{font-size:var(--fs);color:rgba(var(--cream-rgb),.92);margin-top:8px;max-width:34ch}

.reel-rail{
  position:absolute;right:12px;bottom:calc(28px + env(safe-area-inset-bottom));
  display:grid;gap:18px;justify-items:center;
}
.rail-btn{
  background:none;border:0;color:#fff;display:grid;justify-items:center;gap:3px;
  filter:drop-shadow(0 1px 3px rgba(0,0,0,.6));padding:2px;
}
.rail-btn span{font-size:var(--fs-xs);font-weight:600;min-height:14px}
.rail-btn.on{color:var(--flare)}
.rail-btn:disabled{opacity:.5}

.reel-back,.reel-add{
  position:fixed;z-index:40;width:42px;height:42px;border-radius:50%;border:0;
  background:rgba(0,0,0,.45);color:#fff;display:grid;place-items:center;
  backdrop-filter:blur(6px);text-decoration:none;
}
.reel-back{left:12px;top:calc(12px + env(safe-area-inset-top))}
.reel-add{right:12px;top:calc(12px + env(safe-area-inset-top));background:var(--flare);color:var(--ink)}

.reel-replies{
  position:absolute;left:0;right:0;bottom:0;max-height:62dvh;overflow-y:auto;
  background:var(--ink);border-top:1px solid var(--line);
  padding:14px 16px calc(16px + env(safe-area-inset-bottom));margin:0;z-index:30;
}

.reel-empty{
  height:100dvh;display:grid;place-content:center;justify-items:center;gap:14px;
  text-align:center;padding:24px;
}

#reel-form{position:absolute;width:1px;height:1px;overflow:hidden;opacity:0}
.sheet-in textarea{
  width:100%;background:transparent;border:1px solid var(--line);border-radius:var(--r);
  padding:10px 12px;color:var(--cream);font:inherit;resize:none;margin-block:10px;
}
.sheet-acts{display:flex;gap:10px;justify-content:flex-end;margin-top:14px}

.nav-reels{display:inline-flex;align-items:center;gap:6px}

/* ============ recorder ============ */
.rec{z-index:70;background:#000;display:grid;place-items:center}

/* Everything is posted square. The frame shows exactly what will be
   kept, so the shot is set up for the square rather than cropped
   after upload. */
.rec-frame{
  position:relative;aspect-ratio:1;
  width:min(100vw,100dvh);
  background:#000;overflow:hidden;
}
.rec-preview{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;background:#000}
/* mirroring is set in JS: front camera only */

.rec-top{
  position:absolute;top:calc(12px + env(safe-area-inset-top));left:12px;right:12px;
  display:flex;align-items:center;justify-content:space-between;gap:12px;
}
.rec-icon{
  width:42px;height:42px;border:0;border-radius:50%;
  background:rgba(0,0,0,.45);color:#fff;display:grid;place-items:center;
  backdrop-filter:blur(6px);
}
.rec-timer{
  background:var(--flare);color:var(--ink);font-size:var(--fs-sm);font-weight:700;
  padding:5px 12px;border-radius:20px;font-variant-numeric:tabular-nums;
}

.rec-bar{position:absolute;left:0;right:0;top:0;height:3px;background:rgba(var(--cream-rgb),.2)}
.rec-bar span{display:block;height:100%;width:0;background:var(--flare);transition:width .2s linear}

.rec-bottom{
  position:absolute;left:0;right:0;bottom:calc(30px + env(safe-area-inset-bottom));
  display:flex;align-items:center;justify-content:center;gap:16px;padding-inline:24px;
}
#rec-controls{justify-content:space-between}
.rec-spacer{width:42px}

.rec-shutter{
  width:74px;height:74px;border-radius:50%;border:4px solid #fff;
  background:transparent;display:grid;place-items:center;padding:0;
}
.rec-shutter span{
  width:56px;height:56px;border-radius:50%;background:var(--flare);
  transition:border-radius .2s,width .2s,height .2s;
}
.rec-shutter.on span{width:28px;height:28px;border-radius:6px}

.rec-hint{
  position:absolute;left:0;right:0;bottom:calc(112px + env(safe-area-inset-bottom));
  text-align:center;font-size:var(--fs-sm);color:rgba(var(--cream-rgb),.75);
}

/* ---- reel card inside the feed ---- */
.composer-tools{display:flex;gap:8px;flex-wrap:wrap}
.feed-reel{position:relative;height:100%;border-radius:var(--r);background:#000 center/cover no-repeat}
.feed-video{width:100%;height:100%;object-fit:cover;object-position:50% 30%;background:transparent;display:block;border-radius:inherit}
.feed-video{opacity:1}
/* Catches the tap before Safari's own play control can swallow it. */
.feed-tap{position:absolute;inset:0}
.feed-reel-tag{
  position:absolute;left:10px;top:10px;display:inline-flex;align-items:center;gap:5px;
  background:rgba(0,0,0,.55);color:#fff;font-size:var(--fs-xs);font-weight:600;
  padding:4px 9px;border-radius:20px;backdrop-filter:blur(4px);
}
.feed-sound{
  position:absolute;right:10px;bottom:10px;width:34px;height:34px;border:0;border-radius:50%;
  background:rgba(0,0,0,.55);color:#fff;display:grid;place-items:center;backdrop-filter:blur(4px);
}
.feed-sound.on{background:var(--flare);color:var(--ink)}

/* ============ profile ============ */

.pf-avatar{position:relative;overflow:visible;width:104px;height:104px;color:rgba(var(--cream-rgb),.5)}
.pf-avatar img{aspect-ratio:1;border-radius:50%}
.pf-avatar-edit{
  /* Centre on the circle's edge at 45 degrees: 14.6% in from each side, whatever the size. */
  position:absolute;right:calc(14.6% - 12px);bottom:calc(14.6% - 12px);width:24px;height:24px;
  border:2px solid var(--ink);border-radius:50%;background:var(--flare);color:var(--ink);
  display:grid;place-items:center;cursor:pointer;font:700 18px/1 var(--font);
}
.pf-avatar:has(#avatar-edit){cursor:pointer}

.pf-id{min-width:0}
.pf-meta{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:var(--fs-sm);color:var(--sand-dim);margin-top:3px}
.pf-bio{font-size:var(--fs);margin-top:12px;max-width:58ch}

.pf-acts .btn.on,.pf-acts .btn:disabled{background:none;border:1px solid var(--line);color:var(--flare)}
.pf-menu summary{width:34px;height:34px;border:1px solid var(--line);border-radius:var(--r-pill);display:grid;place-items:center;list-style:none;cursor:pointer}

.pf-menu{position:relative}
.pf-menu summary::-webkit-details-marker{display:none}
.pf-menu-list{position:absolute;right:0;top:calc(100% + 6px);z-index:10;display:grid;min-width:140px;padding:6px;background:var(--ink-2);border:1px solid var(--line);border-radius:12px}
.pf-menu-list button{padding:10px 12px;border:0;border-radius:8px;background:none;font:inherit;text-align:left;cursor:pointer}
.pf-menu-list button:hover{background:rgba(0,0,0,.05)}

.pf-tabs{display:flex;gap:4px;border-bottom:1px solid var(--line);margin:0 0 22px}
.pf-tabs a{
  padding:13px 16px;font-size:var(--fs);text-decoration:none;color:var(--sand);
  border-bottom:2px solid transparent;margin-bottom:-1px;
}
.pf-tabs a:hover{color:var(--cream)}
.pf-tabs a.on{color:var(--flare);border-bottom-color:var(--flare)}

/* The back link is the way out of a profile: without the site nav
   beside it, nothing else leads off this page. */
.rail-back{margin-bottom:8px;color:var(--sand-dim)}
.rail-back:hover{color:var(--cream)}
/*
* The left column, on every page that has one: the site nav on most,
* the profile card and its nav on a profile.
*
* Sticky under the header, and scrolling on its own only when the
* content is taller than the screen - without the max-height the last
* links on a short screen can never be reached, and with an
* unconditional overflow the column scrolls when it does not need to.
*/
.rail,
.pf-aside{
  position:sticky;top:71px;
  max-height:calc(100vh - 76px);overflow-y:auto;
  scrollbar-width:none;overscroll-behavior:contain;
  padding-block:19px 24px;
}
.rail::-webkit-scrollbar,
.pf-aside::-webkit-scrollbar{display:none}

.rail{display:grid;gap:1px}
.pf-aside{display:grid;gap:16px;align-content:start}

button.rail-link{width:100%;background:none;border:0;text-align:left;font:inherit;cursor:pointer}

/* Profile: a column of cards about the person, then the content.
   The wider left column is what lets the card hold a centred avatar,
   the stats row and the actions without cramping any of them. */

.pf-name{display:flex;align-items:center;gap:7px;font-size:var(--fs-lg);font-weight:700;letter-spacing:-.02em}
.pf-handle{margin-top:2px;font-size:var(--fs-sm);color:var(--sand-dim)}
.pf-card .pf-bio{margin-top:12px;font-size:var(--fs)}
.pf-card .pf-fact{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:8px;font-size:var(--fs-sm);color:var(--sand-dim)}
.pf-counts{display:flex;margin-top:16px}
.pf-counts a{flex:1;display:grid;text-decoration:none;font-size:var(--fs-sm);color:var(--sand-dim)}
.pf-counts strong{font-size:var(--fs-lg);color:var(--cream)}

.pf-content{padding:0}
.pf-content-h{display:flex;align-items:center;gap:10px;margin:0 0 18px;font:600 var(--fs-lg)/1.2 var(--font);color:var(--cream)}

@media (max-width:900px){
  /* One column: a sticky card would pin itself over the content
     scrolling beneath it. */
  .pf-aside{position:static;max-height:none;overflow:visible;padding-bottom:0}
}

.pf-grid{columns:3;column-gap:4px}
.pf-cell{position:relative;display:block;margin-bottom:4px;break-inside:avoid;background:var(--ink-2);overflow:hidden;border-radius:2px}
.pf-cell img{display:block;width:100%;height:auto}
.pf-cell-blank{display:grid;place-items:center;aspect-ratio:9/16;color:var(--sand-dim)}
.pf-cell-tag{position:absolute;left:6px;top:6px;color:#fff;filter:drop-shadow(0 1px 2px rgba(0,0,0,.7))}

/* Flat card: name beside the avatar, details below, actions in one row. */
.pf-card{
  display:grid;grid-template-columns:auto minmax(0,1fr);
  grid-template-areas:"av name" "av handle" "bio bio" "fact fact" "counts counts" "acts acts";
  column-gap:14px;
}
.pf-card .pf-avatar{grid-area:av;width:72px;height:72px}
.pf-card .pf-name{grid-area:name;align-self:end}
.pf-card .pf-handle{grid-area:handle;align-self:start}
.pf-card .pf-bio{grid-area:bio}
.pf-card .pf-fact{grid-area:fact}
.pf-counts{grid-area:counts}
.pf-acts{grid-area:acts;display:flex;align-items:center;gap:8px;margin-top:14px}
.pf-acts .btn{flex:1}

@media (max-width:760px){
  .pf-grid{columns:2}
}

/* ============ trim ============ */
.trim{z-index:75;background:#000;display:flex;flex-direction:column}
.trim-top{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:calc(12px + env(safe-area-inset-top)) 12px 12px;
}
.trim-len{
  background:rgba(var(--cream-rgb),.12);color:#fff;font-size:var(--fs-sm);font-weight:700;
  padding:5px 12px;border-radius:20px;font-variant-numeric:tabular-nums;
}
.trim-len.over{background:var(--flare);color:var(--ink)}

.trim-frame{
  flex:1;min-height:0;display:grid;place-items:center;overflow:hidden;
  container-type:size;
}
.trim-video{
  aspect-ratio:1;width:min(100cqw,100cqh);
  object-fit:cover;background:#000;
}

.trim-panel{padding:16px 16px calc(24px + env(safe-area-inset-bottom))}
.trim-hint{font-size:var(--fs-sm);color:rgba(var(--cream-rgb),.65);text-align:center;margin-bottom:14px}

.trim-track{
  position:relative;height:52px;border-radius:var(--r);
  background:rgba(var(--cream-rgb),.12);touch-action:none;
}
.trim-sel{
  position:absolute;top:0;bottom:0;left:0;width:100%;
  border:2px solid var(--flare);border-radius:var(--r);
  background:rgba(var(--flare-rgb),.16);
}
.trim-grip{
  position:absolute;top:-2px;bottom:-2px;width:22px;border:0;
  background:var(--flare);cursor:ew-resize;touch-action:none;
}
.trim-grip::after{
  content:"";position:absolute;left:50%;top:50%;translate:-50% -50%;
  width:2px;height:18px;background:var(--ink);border-radius:2px;
  box-shadow:4px 0 0 var(--ink),-4px 0 0 var(--ink);
}
.trim-grip.left{left:-2px;border-radius:var(--r) 0 0 var(--r)}
.trim-grip.right{right:-2px;border-radius:0 var(--r) var(--r) 0}

.trim-play{position:absolute;top:0;bottom:0;width:2px;background:#fff;pointer-events:none;opacity:.9}

.trim-times{
  display:flex;justify-content:space-between;margin-top:10px;
  font-size:var(--fs-xs);color:rgba(var(--cream-rgb),.6);font-variant-numeric:tabular-nums;
}

/* three buttons after recording need a little more room */
#rec-done{gap:10px;flex-wrap:wrap}
#rec-done .btn{min-width:88px}

/* ---- guest feed on the landing page ---- */
.lp-hero.slim{padding-block:44px 32px;margin-bottom:28px}
.lp-hero.slim h1{font-size:var(--fs-title)}
.lp-hero.slim .lead{margin-top:12px;font-size:var(--fs)}
.lp-hero.slim .lp-cta{margin-top:22px}

.guest-stream .post-acts .act{text-decoration:none}

.lp-feed-end{
  display:grid;justify-items:center;gap:14px;text-align:center;
  padding-block:56px 80px;border-top:1px solid var(--line);margin-top:28px;
}

/* ============ app frame: rail + column ============ */
.frame{
  width:min(1180px,100% - var(--pad)*2);margin-inline:auto;
  display:grid;--c-left:260px;--c-right:240px;--c-gap:32px;grid-template-columns:minmax(0,1fr);gap:var(--c-gap);
  align-items:start;
}
.col{padding-block:0 80px;--col-w:600px;max-width:var(--col-w);width:100%}

/* The feed carries a third column, but only where there is room for it.
   Scoped to a min-width: .frame:has() outranks .frame, so setting this
   unconditionally would beat the narrow-screen rules further down. */
@media (min-width:1101px){
  .frame:has(>main+*){grid-template-columns:var(--c-left) minmax(0,1fr) var(--c-right)}
}
.col-wide{max-width:none}

/* ---- left rail ---- */
.rail-link{
  display:flex;align-items:center;gap:12px;position:relative;
  padding:9px 14px;border-radius:var(--r);
  color:var(--sand);text-decoration:none;font-size:var(--fs);
}
.rail-link:hover{background:rgba(var(--cream-rgb),.04);color:var(--cream)}
/* A line at the edge says where you are without a block of colour. */
.rail-link.on{color:var(--flare);background:none}
.rail-link.on::before{content:'';position:absolute;left:0;top:9px;bottom:9px;width:2px;border-radius:2px;background:var(--flare)}
.rail-link svg{opacity:.75}
.rail-link.on svg,.rail-link:hover svg{opacity:1}
.rail-link svg{flex:0 0 auto}

/* ---- account menu ---- */
.acct{position:relative}
.acct summary{
  list-style:none;cursor:pointer;display:flex;align-items:center;gap:9px;
  padding:5px 6px 5px 5px;border-radius:24px;border:1px solid transparent;
}
.acct summary::-webkit-details-marker{display:none}
.acct summary:hover{border-color:var(--line)}
.acct[open] summary{border-color:var(--line)}
/* One circular icon button, shared by the menu toggle and every
   close control, so there is a single style to change. */
.btn-round{
  display:grid;place-items:center;width:38px;height:38px;flex:none;
  padding:0;border:0;border-radius:50%;cursor:pointer;
  background:rgba(var(--cream-rgb),.06);color:var(--cream);
}
.btn-round:hover{background:rgba(var(--cream-rgb),.12)}
/* .acct summary sets flex + padding for the old avatar row; the round
   button needs neither, and outranks it only when scoped this way. */
.acct summary.btn-round{display:grid;place-items:center;padding:0;gap:0;border:0}
.acct summary.btn-round svg{display:block}
.acct[open] .btn-round{border-color:transparent}
/* Both icons ship; only one shows. No reflow on toggle. */
.acct .ico-close,.acct[open] .ico-menu{display:none}
.acct[open] .ico-close{display:block}
.acct-me{border-bottom:1px solid var(--line);margin-bottom:4px;padding-bottom:12px!important}

.acct-av{width:30px;height:30px;color:rgba(var(--cream-rgb),.6)}
.acct-av svg{width:18px;height:18px}
.acct-name{font-size:var(--fs);color:var(--cream);max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.acct-pop{
  position:absolute;right:0;top:calc(100% + 8px);min-width:230px;z-index:40;
  background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r);
  padding:5px;display:grid;gap:1px;
}
.acct-pop a,.acct-pop button{
  display:flex;align-items:center;gap:10px;width:100%;text-align:left;
  background:none;border:0;color:var(--cream);font-size:var(--fs);
  padding:10px 11px;border-radius:2px;text-decoration:none;
}
.acct-pop a:hover,.acct-pop button:hover{background:rgba(var(--flare-rgb),.12);color:var(--flare)}
.acct-pop form{display:contents}
.acct-pop form::before{
  content:"";display:block;height:1px;background:var(--line);margin:4px 0;
}

/* ---- mobile: rail becomes a bottom bar ---- */
@media (max-width:900px){
  .frame{grid-template-columns:1fr;gap:0}
  .col{padding-block:0 92px;--col-w:100vw;max-width:none;margin-inline:auto;min-width:0}

  .rail{display:none}
  .acct-name{display:none}
}

/* ---- settings ---- */
.set-sec{padding-block:28px;border-bottom:1px solid var(--line)}
.set-sec:last-child{border-bottom:0}
.set-sec h2{font-size:var(--fs-lg);font-weight:600;margin-bottom:6px}
.set-sec .form{margin-top:14px}
.saved{color:var(--gold)}

.field textarea{
  background:transparent;border:1px solid rgba(var(--sand-rgb),.4);border-radius:var(--r);
  padding:12px 14px;color:var(--cream);font:inherit;resize:vertical;
}

.check{display:flex;gap:12px;align-items:flex-start;padding:12px 0;cursor:pointer}
.check input{margin-top:3px;accent-color:var(--flare);width:17px;height:17px;flex:0 0 auto}
.check strong{display:block;font-size:var(--fs);font-weight:500}
.check em{display:block;font-style:normal;font-size:var(--fs-sm);color:var(--sand-dim);margin-top:2px;max-width:46ch}

.blocked-list{list-style:none;display:grid;gap:2px}
.blocked-list li{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:11px 0;border-bottom:1px solid var(--line)}
.blocked-list em{font-style:normal;color:var(--sand-dim)}

/* reactions */
.flirt-wrap{position:relative;flex:1;display:grid}
.act-react{width:18px;height:18px;object-fit:contain}
.flirt-pick{position:absolute;bottom:calc(100% + 8px);left:0;z-index:30;display:flex;gap:2px;padding:8px;background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r);box-shadow:0 8px 28px rgba(0,0,0,.5)}
.flirt-opt{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:56px;padding:6px 4px;background:none;border:0;border-radius:var(--r);color:var(--sand-dim);font:400 var(--fs-xs)/1 var(--font);cursor:pointer}
.flirt-opt img{width:40px;height:40px;object-fit:contain;transition:transform .12s ease}
.flirt-opt:hover img,.flirt-opt:focus-visible img{transform:scale(1.18)}
.flirt-opt.on{background:rgba(var(--flare-rgb),.12);color:var(--flare)}

/* Six 56px columns overflow a 380px screen. Scroll rather than wrap:
   a second row would push the picker over the post above it. */
@media (max-width:480px){
  .flirt-pick{left:0;transform:none;max-width:min(360px,calc(100vw - 32px));overflow-x:auto;scrollbar-width:none;overscroll-behavior-x:contain}
  .flirt-pick::-webkit-scrollbar{display:none}
  .flirt-opt{min-width:52px}
  .flirt-opt img{width:36px;height:36px}
}

/* match moment */
.flirt-match{position:fixed;inset:0;z-index:100;display:grid;place-items:center;padding:var(--pad);background:rgba(var(--ink-rgb),.82)}
.flirt-match-in{max-width:340px;padding:32px 28px;text-align:center;background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r)}
.fm-title{margin:0 0 8px;font:600 var(--fs-xl)/1.2 var(--font);color:var(--flare);letter-spacing:-.01em}
.fm-body{margin:0 0 24px;color:var(--cream)}
.fm-close{display:block;width:100%;margin:12px 0 0;padding:8px;background:none;border:0;color:var(--sand-dim);font:400 var(--fs-sm)/1 var(--font);cursor:pointer}
/* sticker comments */
.reply-row{display:flex;align-items:flex-end;gap:8px}
.reply-tools{display:flex;gap:2px;margin-top:6px}
.sticker-btn{padding:4px;background:none;border:0;border-radius:var(--r);line-height:0;cursor:pointer;opacity:.72;transition:opacity .12s ease,transform .12s ease}
.sticker-btn:hover,.sticker-btn:focus-visible{opacity:1;transform:scale(1.12)}
.sticker-btn.on{opacity:1;background:rgba(var(--flare-rgb),.14)}
.sticker-btn img{width:28px;height:28px;object-fit:contain}
.reply-chosen{position:relative;display:inline-block;margin:0 0 8px}
.reply-chosen img{width:56px;height:56px;object-fit:contain}
.reply-chosen-x{position:absolute;top:-6px;right:-6px;width:20px;height:20px;padding:0;background:var(--ink);border:1px solid var(--line);border-radius:50%;color:var(--sand);font:400 var(--fs-sm)/1 var(--font);cursor:pointer}
.reply-sticker{display:block;width:72px;height:72px;object-fit:contain;margin:4px 0 0}
.reply-gif{display:block;max-width:220px;border-radius:var(--r);margin:4px 0 0}
.post-who{display:flex;flex-wrap:wrap;align-items:center;gap:0 8px}
.post-who .post-name{margin:0}
.post-who .post-meta{flex:0 0 100%;margin:0}
/* people lists */
.people{list-style:none;display:grid;gap:2px}
.person{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:11px 0;border-bottom:1px solid var(--line)}
.person-who{display:flex;align-items:center;gap:12px;color:inherit;text-decoration:none;min-width:0}
.person-av{width:40px;height:40px}
.person-who strong{display:block;font-weight:600}
.person-who em{display:block;font-style:normal;font-size:var(--fs-sm);color:var(--sand-dim)}
.person-acts{display:flex;gap:8px;flex:0 0 auto}
.notif-acts{display:flex;gap:8px;margin-left:auto}
.page-h2{margin:24px 0 8px;font:600 var(--fs)/1.3 var(--font);color:var(--cream)}
/* Shape comes from .btn-round; this only adds what is bell-specific. */
.head-bell{position:relative}
.head-bell.on{color:var(--flare)}
.head-dot{position:absolute;top:4px;right:2px;min-width:16px;padding:0 4px;background:var(--flare);border-radius:var(--r-pill);color:var(--ink);font:700 var(--fs-xs)/16px var(--font);font-style:normal;text-align:center}
.head-acts{display:flex;align-items:center;gap:6px}

/* bell panel: its own scroll, so a long history does not push the
   page around or stretch the panel past the viewport */
.bell-pop{width:340px;max-width:calc(100vw - 24px);padding:0}
.bell-head{padding:14px 16px 10px;font:600 var(--fs)/1 var(--font);color:var(--cream)}
.bell-list{max-height:min(420px,60vh);overflow-y:auto;overscroll-behavior:contain;padding:0 6px 6px}
.bell-row{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:var(--r);color:var(--sand);text-decoration:none}
.bell-row:hover{background:rgba(var(--cream-rgb),.05);color:var(--cream)}
.bell-row.unread{color:var(--cream)}
.bell-row .notif-av{flex:0 0 34px;width:34px;height:34px}
.bell-text{flex:1;min-width:0;font-size:var(--fs-sm);line-height:1.35}
.bell-text em{display:block;font-style:normal;font-size:var(--fs-xs);color:var(--sand-dim);margin-top:1px}
.bell-new{flex:0 0 8px;width:8px;height:8px;border-radius:50%;background:var(--flare)}
.bell-empty{padding:24px 10px;text-align:center;color:var(--sand-dim);font-size:var(--fs-sm)}
.bell-all{display:block;padding:12px;border-top:1px solid var(--line);text-align:center;color:var(--flare);text-decoration:none;font-size:var(--fs-sm)}
.bell-all:hover{background:rgba(var(--flare-rgb),.08)}

/* Mobile nav: its own element, rendered on every page. A floating pill
   rather than a bar welded to the bottom edge - it reads as a control
   sitting on the page. */
.mobile-nav{display:none;transition:translate .22s ease,opacity .22s ease}

@media (max-width:900px){
  /* Separate buttons, not one pill: each action is its own thing to
     hit, and the picture shows between them. */
  .mobile-nav{
    position:fixed;left:50%;translate:-50% 0;
    bottom:calc(12px + env(safe-area-inset-bottom));z-index:30;
    display:flex;justify-content:space-between;padding:0;
    width:calc(100vw - 12px);max-width:420px;
    background:none;border:0;box-shadow:none;
  }
  /* Circles keep their shape; only the Go online pill gives when space is tight. */
  .mnav-link:not(.mnav-post){flex:none}
  .mnav-link{
    position:relative;display:grid;place-items:center;
    width:52px;height:52px;border-radius:50%;color:var(--cream);
    background:rgba(var(--ink-rgb),.72);border:1px solid var(--line);
    box-shadow:0 6px 18px rgba(0,0,0,.4);
    -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
    /* Buttons and links sit side by side in here, so the button's own
       chrome has to go or only half the bar looks flat. */
    padding:0;cursor:pointer;
  }
  .mnav-link.on{background:rgba(var(--flare-rgb),.14);color:var(--flare)}
  .mnav-link.on svg path{fill:currentColor}
  .mnav-dot{
    position:absolute;top:9px;right:11px;width:8px;height:8px;
    border-radius:50%;background:var(--flare);
  }
}

/* composer sheet */
.composer-sheet{z-index:60;background:var(--ink);overflow-y:auto}
.cs-head{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:14px;padding:14px 16px;background:var(--ink);border-bottom:1px solid var(--line);font:600 var(--fs)/1 var(--font);color:var(--cream)}
.cs-close{background:none;border:0;color:var(--sand);font-size:var(--fs-xl);line-height:1;cursor:pointer;padding:0 4px}
.cs-close:hover{color:var(--flare)}
.cs-body{width:min(600px,100% - 32px);margin-inline:auto;padding-block:20px 80px}
.cs-body .composer{background:none;border:0;padding:0}

.cs-open{display:flex;align-items:center;gap:12px;width:100%;margin-bottom:20px;padding:14px 16px;background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r-pill);color:var(--sand-dim);font:inherit;text-align:left;cursor:pointer}
.cs-open:hover{border-color:var(--flare);color:var(--cream)}
.cs-open-av{width:34px;height:34px}

.mnav-post{background:var(--flare);border:0;color:var(--ink);cursor:pointer;padding:0}
.mnav-post:hover{background:var(--gold)}
.mnav-soon{background:none;border:0;padding:0;color:var(--sand);cursor:default;opacity:1;-webkit-appearance:none;appearance:none}
.mnav-av{width:28px;height:28px}
.mnav-link.on .mnav-av{outline:2px solid var(--flare);outline-offset:1px}

/* The post header sits over the foot of the media rather than above
   it: with a tall frame there is no reason to spend a row of the
   screen on a name.

   It has to match the media's own edges - the media breaks out of the
   page gutter on a phone, so the header follows it rather than sitting
   inset by the width of that gutter. */
.card.post{position:relative}

/* Matched to the conversation's avatars below: at 38px the person who
   posted read as smaller than each message they had sent. */
.card.post .post-avatar,
.lb-who .post-avatar{
  width:var(--post-avatar-h);
  height:var(--post-avatar-h);
  flex:0 0 var(--post-avatar-h);
  border-radius:50%;
  border:1.5px solid rgba(var(--cream-rgb),.85);
}

@media (max-width:900px){
  .feed-sound{bottom:auto;top:12px;right:12px}
  .card.post{border-bottom:0}
}
.rail-me-av{width:38px;height:38px}
.rail-me-who{min-width:0}
.rail-me-who strong{display:block;font-weight:600;color:var(--cream);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail-me-who em{display:block;font-style:normal;font-size:var(--fs-sm);color:var(--flare)}

/* reel tray */
.tray{margin:0 0 22px}
.tray-scroll{
  display:flex;gap:10px;overflow-x:auto;
  scroll-snap-type:x proximity;scrollbar-width:none;
  -webkit-overflow-scrolling:touch;
}
.tray-scroll::-webkit-scrollbar{display:none}
.tray-card{
  position:relative;flex:0 0 128px;aspect-ratio:9/16;
  scroll-snap-align:start;border-radius:var(--r);overflow:hidden;
  background:var(--ink-2);text-decoration:none;display:block;
}
.tray-card > img{width:100%;height:100%;object-fit:cover;display:block}
.tray-card::after{
  content:'';position:absolute;inset:auto 0 0 0;height:60%;
  background:linear-gradient(rgba(var(--ink-rgb),0),rgba(var(--ink-rgb),.85));
}
.tray-av{
  position:absolute;top:8px;left:8px;z-index:1;
  width:30px;height:30px;outline:2px solid var(--flare);
}
.tray-name{
  position:absolute;left:8px;right:8px;bottom:8px;z-index:1;
  font-size:var(--fs-sm);font-weight:600;color:#fff;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* The tray breaks out of the gutter like the post media does, so the
   row runs to the screen edge and reads as scrollable. */
@media (max-width:900px){
  .tray-scroll{
    margin-inline:calc(var(--pad) * -1);
    padding-inline:var(--pad);
  }
  .tray-card{flex-basis:112px}
}
/* reel progress */
.reel-bar{position:absolute;top:calc(8px + env(safe-area-inset-top));left:12px;right:12px;z-index:3;height:3px;border-radius:2px;background:rgba(var(--cream-rgb),.28);overflow:hidden}
.reel-bar i{display:block;height:100%;width:0;background:#fff;border-radius:2px;transition:width .28s linear}
/* timeupdate fires a few times a second, so the bar arrives in steps.
   The transition rides between them. It is linear and slightly longer
   than the gap, so the fill keeps moving rather than easing to a stop
   between each update. */

/* the create-story card: the one tile that is always there, so the
   row never renders as an empty strip */
.tray-new{position:relative;border:0;padding:0;cursor:pointer;text-align:left}
.tray-new > img{opacity:.55}
.tray-plus{
  position:absolute;left:50%;top:50%;translate:-50% -50%;z-index:1;
  display:grid;place-items:center;width:42px;height:42px;
  border-radius:50%;background:var(--flare);color:var(--ink);
  font:700 var(--fs-xl)/1 var(--font);
}
.tray-new .tray-name{text-align:center}

/* ============ stories ============ */
.stories{height:100dvh;overflow-y:auto;scroll-snap-type:y mandatory;scrollbar-width:none;background:#000}
.stories::-webkit-scrollbar{display:none}
body:has(.stories){overflow:hidden}

.story-set{position:relative;height:100dvh;scroll-snap-align:start;scroll-snap-stop:always}

/* The strip is the horizontal axis: one person's stories, snapped. */
.story-strip{display:flex;height:100%;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none}
.story-strip::-webkit-scrollbar{display:none}
.story{flex:0 0 100%;height:100%;scroll-snap-align:start;display:grid;place-items:center;background:#000}
.story-img,
.story-video{width:100%;height:100%;object-fit:contain;display:block}

/* One segment per story, so how many are left is visible at a glance. */
.story-bars{position:absolute;top:calc(10px + env(safe-area-inset-top));left:12px;right:12px;z-index:4;display:flex;gap:3px}
.story-bar{flex:1;height:3px;border-radius:2px;background:rgba(var(--cream-rgb),.28);overflow:hidden}
.story-bar i{display:block;height:100%;width:0;background:#fff;border-radius:2px}

.story-head{position:absolute;top:calc(24px + env(safe-area-inset-top));left:12px;right:56px;z-index:4;display:flex;align-items:center;gap:10px}
.story-av{width:34px;height:34px}
.story-who{color:#fff;font-weight:600;text-decoration:none;text-shadow:0 1px 3px rgba(0,0,0,.5)}
.story-when{color:rgba(var(--cream-rgb),.7);font-size:var(--fs-sm)}

/* Tap targets, not buttons you can see. They sit below the header so
   the name and avatar stay clickable. */
.story-tap{position:absolute;top:0;bottom:0;width:32%;z-index:3;background:none;border:0;cursor:pointer}
.story-prev{left:0}
.story-next{right:0}

/* ============ messages ============ */
.thread-list{list-style:none;display:grid;gap:2px}
.thread{
  display:grid;grid-template-columns:auto 1fr auto auto;align-items:center;gap:12px;
  padding:11px 12px;border-radius:var(--r);text-decoration:none;color:inherit;
}
.thread:hover{background:var(--ink-2)}
.thread-av{width:46px;height:46px;background:var(--ink-2);color:var(--sand-dim)}
.thread-who{min-width:0;display:grid;gap:2px}
.thread-name{font-weight:600;color:var(--cream)}
.thread-last{
  font-size:var(--fs-sm);color:var(--sand-dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.thread.unread .thread-last{color:var(--cream)}
.thread-when{font-size:var(--fs-xs);color:var(--sand-dim);white-space:nowrap}
.thread-dot{width:8px;height:8px;border-radius:50%;background:var(--flare)}

.th-head{
  display:flex;align-items:center;gap:10px;padding-bottom:12px;
  border-bottom:1px solid var(--line);margin-bottom:14px;
}
.th-back{color:var(--cream);display:grid;place-items:center}
.th-who{display:flex;align-items:center;gap:9px;color:var(--cream);text-decoration:none;font-weight:600}
.th-av{width:32px;height:32px;background:var(--ink-2);color:var(--sand-dim)}

.th-log{display:grid;gap:8px;align-content:start;padding-bottom:14px}
.msg{
  justify-self:start;
  display:flex;align-items:flex-end;gap:8px;
  max-width:min(82%,520px);
}
.msg.mine{
  justify-self:end;
  flex-direction:row-reverse;
}
.msg-av{
  width:30px;height:30px;
  background:var(--wine);color:var(--sand-dim);
}
.msg-bubble{
  max-width:460px;
  background:var(--ink-2);padding:9px 13px;
  border-radius:16px 16px 16px 4px;
}
.msg.mine .msg-bubble{
  background:var(--flare);color:#fff;
  border-radius:16px 16px 4px 16px;
}
.msg p{font-size:var(--fs);line-height:1.4;overflow-wrap:anywhere}
.msg-when{display:block;font-size:var(--fs-xs);opacity:.65;margin-top:3px}

.th-send{
  position:fixed;
  bottom:0;
  z-index:20;
  width:min(600px,calc(100vw - (var(--pad) * 2)));
  background:var(--ink);
  padding:10px 0;
}
@media (min-width:901px){
  .th-send{
    left:max(
      var(--pad),
      calc((100vw - min(1180px,100vw - (var(--pad) * 2))) / 2 + 292px)
    );
  }
}
@media (max-width:900px){
  .th-send{
    left:var(--pad);
    right:var(--pad);
    width:auto;
    bottom:0;
  }
}
.th-send-box{
  position:relative;
}
.th-send input{
  width:100%;
  background:var(--ink-2);
  border:1px solid var(--line);
  color:var(--cream);
  padding:11px 52px 11px 14px;
  border-radius:var(--r-pill);
  font:inherit;
  box-sizing:border-box;
}
.th-send input:focus{
  outline:2px solid var(--flare);
  outline-offset:-1px;
}
/* The same pill as the feed card's: one send button across the app. */
.th-send-btn{
  position:absolute;
  right:5px;
  top:50%;
  transform:translateY(-50%);
  border:0;
  border-radius:999px;
  display:grid;
  place-items:center;
  background:var(--flare);
  color:var(--ink);
  padding:10px 15px;
  font:700 var(--fs-sm)/1 var(--font);
  cursor:pointer;
}
.th-send-btn:hover{
  filter:brightness(1.05);
}
.th-send-btn:focus-visible{
  outline:2px solid var(--cream);
  outline-offset:2px;
}

/* ============ flirt buddies rail ============ */
.buddies{padding-block:30px 24px;position:sticky;top:71px}
.buddies-card{
  background:var(--ink-2);border:1px solid var(--line);
  border-radius:14px;padding:16px 12px;display:flex;flex-direction:column;max-height:calc(100svh - var(--head-h,71px) - 54px);
}
.buddies-h{
  font:600 var(--fs)/1 var(--font);color:var(--cream);
  margin-bottom:14px;padding-inline:6px;
}
.buddies-none{font-size:var(--fs-sm);color:var(--sand-dim);padding-inline:6px;line-height:1.5}
.buddy-list{list-style:none;display:grid;gap:2px}
.buddy{
  display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;
  padding:7px 6px;border-radius:10px;text-decoration:none;color:var(--cream);
}
.buddy:hover{background:rgba(var(--cream-rgb),.06)}
/* The remove control stays out of the way until the row is under the
   cursor: it is a rare action next to a common one. */
.buddy-x{
  background:none;border:0;padding:2px 6px;font-size:var(--fs-lg);line-height:1;
  color:var(--sand-dim);cursor:pointer;opacity:0;transition:opacity .12s ease;
}
.buddy:hover .buddy-x,.buddy-x:focus-visible{opacity:1}
.buddy-x:hover{color:var(--flare)}
.buddy .buddy-dot{display:inline-block;margin-left:6px;vertical-align:middle}
.buddy-av{
  position:relative;width:44px;height:44px;
  background:var(--ink);color:var(--sand-dim);
  box-shadow:0 0 0 2px var(--flare);
}
/* Presence sits beside the avatar rather than inside it — .buddy-av
   clips to a circle and would clip this with it. Green, not coral:
   coral is the unread dot, and one colour cannot mean two things. */
.buddy-slot{position:relative;display:grid;flex:none}
.buddy-on{
  position:absolute;right:0;bottom:1px;
  width:12px;height:12px;border-radius:50%;
  background:#3FD07A;box-shadow:0 0 0 2px var(--ink-2);
}
.buddy-name{
  display:grid;gap:1px;min-width:0;
  font-size:var(--fs);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--cream);text-decoration:none;
}
.buddy.unread .buddy-name{font-weight:600}
/* Two lines in 240px: who, then what they said and when. */
.buddy-last{
  font-size:var(--fs-sm);color:var(--sand-dim);font-weight:400;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.buddy-when{font-style:normal;margin-left:6px;color:var(--sand-dim);opacity:.7}
.buddy-dot{width:7px;height:7px;border-radius:50%;background:var(--flare)}

/* Below this the third column would squeeze the feed, and /messages is
   the better experience on a narrow screen anyway. */
@media (max-width:1100px){
  .buddies{display:none}
}

/* ---- buddies: tabs and discovery ---- */
.bd-tabs{display:grid;grid-template-columns:1fr 1fr;margin-bottom:12px}
.bd-tab{
  background:none;border:0;border-bottom:2px solid var(--line);
  padding:8px 4px;font:inherit;font-size:var(--fs-sm);color:var(--sand-dim);cursor:pointer;
}
.bd-tab.on{color:var(--flare);border-bottom-color:var(--flare)}
.bd-search{
  display:flex;align-items:center;gap:8px;margin-bottom:12px;
  padding:8px 12px;border-radius:var(--r-pill);
  background:var(--ink);border:1px solid var(--line);color:var(--sand-dim);
}
.bd-search input{
  flex:1;min-width:0;background:none;border:0;color:var(--cream);font:inherit;font-size:var(--fs-sm);
}
.bd-search input:focus{outline:none}
.bd-label{font-size:var(--fs-sm);color:var(--sand-dim);margin:0 6px 6px}
.bd-add{
  background:none;border:1px solid var(--flare);color:var(--flare);
  padding:5px 14px;border-radius:var(--r-pill);font:inherit;font-size:var(--fs-sm);cursor:pointer;
}
.bd-add:hover{background:rgba(var(--flare-rgb),.12)}
.bd-add[disabled]{border-color:var(--line);color:var(--sand-dim);cursor:default;background:none}

/* ---- message requests ---- */
.req-h{
  font:600 var(--fs-sm)/1 var(--font);letter-spacing:.06em;text-transform:uppercase;
  color:var(--sand-dim);margin:0 0 8px;display:flex;align-items:center;gap:8px;
}
.req-n{
  background:var(--flare);color:#fff;border-radius:var(--r-pill);
  padding:1px 7px;font-size:var(--fs-xs);letter-spacing:0;
}
.req-list{margin-bottom:6px}
.req-note{font-size:var(--fs-sm);color:var(--sand-dim);margin:0 0 24px 12px}
.th-note{
  font-size:var(--fs-sm);color:var(--sand-dim);line-height:1.5;
  padding:12px 14px;background:var(--ink-2);border-radius:var(--r);margin-bottom:12px;
}

/* The mark sits with the name rather than replacing it: at 22px the
   letterform reads, but only next to the word it comes from. */

/* "zone" in the site's own face rather than the display one. */

/* ============ admin ============ */
.adm{background:var(--ink);color:var(--cream);font:15px/1.5 var(--font);min-height:100vh}
.adm a{color:var(--flare)}

.adm-top{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:12px 20px;border-bottom:1px solid var(--line);
}
.adm-brand{font-weight:700;color:var(--cream);text-decoration:none}
.adm-brand span{color:var(--sand-dim);font-weight:400}
.adm-out{background:none;border:0;color:var(--sand-dim);font:inherit;cursor:pointer}
.adm-out:hover{color:var(--cream)}

.adm-frame{display:grid;grid-template-columns:190px minmax(0,1fr);gap:28px;
  width:min(1240px,100% - 40px);margin-inline:auto;padding-block:24px 64px;align-items:start}
.adm-nav{display:grid;gap:1px;position:sticky;top:24px}
.adm-nav a{
  padding:9px 12px;border-radius:var(--r);color:var(--cream);
  text-decoration:none;font-size:var(--fs);
}
.adm-nav a:hover{background:var(--ink-2)}
.adm-nav a.on{background:rgba(var(--flare-rgb),.12);color:var(--flare)}

.adm-main{min-width:0}
.adm-h{font:700 var(--fs-xl)/1.2 var(--font);margin-bottom:20px}
.adm-h2{font:700 var(--fs)/1.2 var(--font);margin:32px 0 12px}
.adm-none{color:var(--sand-dim)}
.adm-note{color:var(--sand-dim);font-size:var(--fs-sm);margin-top:10px}
.adm-dim{color:var(--sand-dim)}
.adm-flash{background:rgba(var(--flare-rgb),.12);color:var(--flare);
  padding:10px 14px;border-radius:var(--r);margin-bottom:16px}
.adm-err{background:rgba(var(--flare-rgb),.14);color:var(--flare);
  padding:10px 14px;border-radius:var(--r);margin-bottom:16px}

/* Cards are links where there is somewhere to go, so a number on the
   dashboard is a way into the screen that explains it. */
.adm-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:12px}
.adm-card-n{
  display:grid;gap:4px;padding:16px 18px;background:var(--ink-2);
  border:1px solid var(--line);border-radius:var(--r);
  text-decoration:none;color:var(--cream);
}
a.adm-card-n:hover{border-color:var(--flare)}
.adm-n{font:700 var(--fs-xl)/1 var(--font)}
.adm-l{font-size:var(--fs-sm);color:var(--sand-dim)}

.adm-table{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
.adm-table th{
  text-align:left;font-weight:600;color:var(--sand-dim);font-size:var(--fs-xs);
  text-transform:uppercase;letter-spacing:.05em;padding:0 10px 8px;
}
.adm-table td{padding:10px;border-top:1px solid var(--line);vertical-align:middle}
.adm-table a{text-decoration:none}
.adm-acts form{display:flex;gap:6px;justify-content:flex-end}

.adm-status{font-size:var(--fs-xs);padding:2px 8px;border-radius:var(--r-pill);background:var(--ink-2)}
.adm-active{color:#3FD07A}
.adm-suspended{color:var(--flare)}
.adm-pending{color:var(--sand-dim)}
.adm-tag{font-size:var(--fs-xs);padding:1px 6px;border-radius:var(--r-pill);
  background:rgba(var(--flare-rgb),.14);color:var(--flare);margin-left:4px}

.adm-btn{
  background:var(--ink-2);border:1px solid var(--line);color:var(--cream);
  padding:7px 14px;border-radius:var(--r);font:inherit;font-size:var(--fs-sm);cursor:pointer;
}
.adm-btn:hover{border-color:var(--flare)}
.adm-btn-sm{padding:4px 10px;font-size:var(--fs-sm)}
.adm-btn-go{background:var(--flare);border-color:var(--flare);color:#fff}
.adm-btn-warn:hover{color:var(--flare)}

.adm-bar{display:flex;gap:8px;margin-bottom:18px;flex-wrap:wrap}
.adm-bar input,.adm-bar select{
  background:var(--ink-2);border:1px solid var(--line);color:var(--cream);
  padding:7px 12px;border-radius:var(--r);font:inherit;font-size:var(--fs-sm);
}
.adm-bar input{flex:1;min-width:180px}

.adm-form{display:grid;gap:12px;max-width:340px}
.adm-form label{display:grid;gap:5px;font-size:var(--fs-sm);color:var(--sand-dim)}
.adm-form input{
  background:var(--ink-2);border:1px solid var(--line);color:var(--cream);
  padding:9px 12px;border-radius:var(--r);font:inherit;font-size:var(--fs);
}
.adm-form input:focus{outline:2px solid var(--flare);outline-offset:-1px}
.adm-form-row{grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  align-items:end;max-width:none}

.adm-bare{display:grid;place-items:center;min-height:100vh}
.adm-card{width:min(340px,100% - 40px);padding:28px;
  background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r)}

@media (max-width:760px){
  .adm-frame{grid-template-columns:1fr;gap:18px}
  .adm-nav{position:static;grid-auto-flow:column;overflow-x:auto}
}

/* An AI account says so wherever its name appears. Small, but never
   hidden: the point is that nobody has to wonder. */
.ai-badge{
  display:inline-block;vertical-align:middle;margin-left:6px;
  font:600 var(--fs-xs)/1 var(--font);letter-spacing:.08em;
  padding:3px 6px;border-radius:var(--r-pill);
  background:rgba(var(--sand-rgb),.16);color:var(--sand);
}
.ai-note{
  font-size:var(--fs-sm);color:var(--sand-dim);line-height:1.5;
  padding:10px 14px;background:var(--ink-2);border-radius:var(--r);margin-bottom:12px;
}

/* ---- video call ---- */
.call-sheet{z-index:80;background:#000;display:grid}

#call-remote{width:100%;height:100%;object-fit:cover}
#call-local{
  position:absolute;right:14px;top:14px;width:110px;
  border-radius:10px;object-fit:cover;box-shadow:0 4px 16px rgba(0,0,0,.5);
}
.call-bar{
  position:absolute;left:0;right:0;bottom:calc(24px + env(safe-area-inset-bottom));
  display:grid;justify-items:center;gap:14px;
}
.call-who{color:#fff;font-size:var(--fs);text-shadow:0 1px 4px rgba(0,0,0,.7)}
.call-acts{display:flex;gap:14px}
.call-hang{background:var(--flare);color:var(--ink)}

#live-preview{width:100%;height:100%;object-fit:cover}

/* ---- live on a profile ---- */
.live-card{position:relative;margin-bottom:22px;border-radius:var(--r);overflow:hidden;background:#000}
.live-card video,.live-card iframe{display:block;width:100%;aspect-ratio:16/9;border:0;object-fit:cover}
.live-pill{
  position:absolute;left:12px;top:12px;display:inline-flex;align-items:center;gap:5px;
  padding:5px 10px;border-radius:var(--r-pill);background:var(--flare);color:var(--ink);
  font:700 var(--fs-xs)/1 var(--font);letter-spacing:.04em;
}
.live-cap{position:absolute;left:14px;bottom:12px;color:#fff;text-shadow:0 1px 4px rgba(0,0,0,.8)}
.live-cap strong{display:block;font-size:var(--fs-lg)}
.live-cap em{font-style:normal;font-size:var(--fs-sm);opacity:.85}

/* The iframe swallows clicks, so an overlay carries the link. */
.live-open{position:relative;display:block}
.live-open-hit{position:absolute;inset:0}
.live-open video{aspect-ratio:auto}
.live-mute{position:absolute;right:12px;bottom:12px;background:rgba(0,0,0,.5);color:#fff}
.live-mute.on{background:var(--flare);color:var(--ink)}

/* ---- live in the hint row ---- */
.tray-card.on-air{outline:2px solid var(--flare);outline-offset:-2px}
.tray-card.on-air .tray-av{box-shadow:0 0 0 2px var(--flare)}
.tray-live{
  position:absolute;left:8px;top:8px;z-index:2;
  padding:3px 7px;border-radius:var(--r-pill);background:var(--flare);color:var(--ink);
  font:700 var(--fs-xs)/1 var(--font);letter-spacing:.05em;
}

/* ---- live card in the row ---- */
.tray-eyes{
  position:absolute;right:8px;top:8px;z-index:2;
  display:inline-flex;align-items:center;gap:4px;
  padding:3px 8px;border-radius:var(--r-pill);
  background:rgba(0,0,0,.55);color:#fff;font:600 var(--fs-xs)/1 var(--font);
}
.tray-who{
  position:absolute;left:10px;right:10px;bottom:10px;z-index:2;color:#fff;
  text-shadow:0 1px 4px rgba(0,0,0,.8);
}
.tray-who strong{display:block;font-size:var(--fs)}
.tray-who em{font-style:normal;font-size:var(--fs-xs);opacity:.8;display:block;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tray-card.on-air .tray-name{display:none}

/* ---- broadcaster's screen ---- */
.lv-top{
  position:absolute;left:14px;right:14px;top:calc(14px + env(safe-area-inset-top));
  z-index:3;display:flex;justify-content:space-between;align-items:center;
}
.lv-badge{
  display:inline-flex;align-items:center;gap:7px;
  padding:6px 11px;border-radius:var(--r-pill);background:var(--flare);color:var(--ink);
  font:700 var(--fs-xs)/1 var(--font);letter-spacing:.04em;
}
.lv-badge em{font-style:normal;font-weight:600}
.lv-eyes{
  display:inline-flex;align-items:center;gap:6px;
  padding:6px 11px;border-radius:var(--r-pill);
  background:rgba(0,0,0,.5);color:#fff;font:600 var(--fs-sm)/1 var(--font);
}
.lv-eyes em{font-style:normal}

.lv-setup,.lv-on{
  position:absolute;left:16px;right:16px;z-index:3;
  bottom:calc(24px + env(safe-area-inset-bottom));
  display:grid;gap:12px;justify-items:center;
}

.lv-reply{display:flex;gap:8px;width:min(460px,100%)}
.lv-reply input{
  flex:1;min-width:0;padding:12px 16px;border-radius:var(--r-pill);
  border:1px solid rgba(var(--cream-rgb),.25);background:rgba(0,0,0,.45);
  color:#fff;font:inherit;
}
.lv-reply input::placeholder{color:rgba(var(--cream-rgb),.6)}
.lv-end{background:var(--flare);color:var(--ink);min-width:120px}

/* ---- composer: pick a line ---- */
.cs-line{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;margin-bottom:8px;padding:14px 16px;background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r);color:var(--cream);font:inherit;text-align:left;cursor:pointer}
.cs-line:hover{border-color:var(--flare)}
.cs-line svg{color:var(--flare);flex:0 0 auto}
.cs-lines{max-height:min(46vh,340px);overflow-y:auto;margin-bottom:8px}
.cs-own{display:block;margin-bottom:16px;font-size:var(--fs-sm)}
.chip input[type=file]{position:absolute;width:1px;height:1px;opacity:0}
.chip:focus-within{border-color:var(--flare);color:var(--flare)}
.cs-cats,.cs-cat ul{list-style:none;display:grid;gap:6px}
.cs-cat .linkish{display:block;margin-bottom:10px;font-size:var(--fs-sm)}

/* ---- admin modal ---- */
.adm-modal{border:1px solid var(--line);background:var(--ink-2);color:var(--cream);padding:0;max-width:460px;width:calc(100% - 32px)}
.adm-modal::backdrop{background:rgba(var(--ink-rgb),.72)}
.adm-modal .adm-form{max-width:none;padding:20px;gap:14px}
.adm-modal-head{display:flex;align-items:center;justify-content:space-between;gap:16px}
.adm-modal-head h2{font:700 var(--fs)/1.2 var(--font)}
.adm-modal-foot{display:flex;justify-content:flex-end}
.adm-form select,.adm-form textarea{
  padding:8px 10px;background:var(--ink);border:1px solid var(--line);
  border-radius:var(--r);color:var(--cream);font:inherit;width:100%;
}
.adm-form select:focus,.adm-form textarea:focus{outline:2px solid var(--flare);outline-offset:-1px}
.adm-head-row{display:flex;align-items:center;justify-content:flex-end;margin-bottom:16px}
.adm-check{display:flex;align-items:center;gap:8px;font-size:var(--fs-sm);color:var(--cream)}
.adm-check input{width:auto}
.adm-modal{margin:auto}
.adm-modal input[type=number]{width:100%}
.adm-form select,.adm-bar select{appearance:none;background-image:none;padding-right:12px}
.adm-form input[type=number]{appearance:textfield}
.picks:empty{margin:0}
.line-cat-head{color:var(--sand-dim);margin-bottom:18px;font-size:var(--fs)}
.line-h{font:600 var(--fs-lg)/1.3 var(--font);letter-spacing:-.01em;margin-bottom:4px}
.cs-head{justify-content:flex-end;border-bottom:0}
.thumb-clip{aspect-ratio:1}
.thumb-clip video{width:100%;height:100%;object-fit:cover}
.chip.on{border-color:var(--flare);color:var(--flare)}
.chip[disabled]{opacity:.4;pointer-events:none}
.cs-live{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;margin-top:20px;padding:12px;background:none;border:1px solid var(--line);border-radius:var(--r-pill);color:var(--sand);font:inherit;cursor:pointer}
.cs-live:hover{border-color:var(--flare);color:var(--flare)}
.cs-post{width:100%;margin-top:16px}
.post-media:empty{display:none}
.post-name .js-follow{margin-left:4px}

.feed-cats{display:flex;gap:8px;margin-bottom:18px;min-width:0;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}
.feed-cats::-webkit-scrollbar{display:none}
.feed-cats .chip{flex:0 0 auto;text-decoration:none}

.cat-drop{margin-top:10px;padding:12px;background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r)}
.cat-drop ul{list-style:none;display:grid;gap:4px}
.cat-drop .starter{width:100%;text-align:left;text-decoration:none;padding:9px 12px}
.cat-all{display:block;margin-bottom:8px;color:var(--flare);font-size:var(--fs-sm);text-decoration:none}
.chip.now{border-color:var(--flare);color:var(--flare)}
.cats{position:sticky;top:71px;z-index:20;padding-block:30px 14px;background:var(--ink)}
.head-in{height:100%}

/* A column with no chip row above it provides its own top space: the
   chips carry theirs, so only the pages without them need this. */
/* Not the feed: its stream already starts at the header's edge, and the
   card it restores on load is aligned there too. */
.col:not(:has(.cats, #stream, .room)){padding-top:24px}
.feed-cats{cursor:grab}
.feed-cats:active{cursor:grabbing}
.stream .card:first-child{padding-top:0}

@media (max-width:900px){
  /* The list takes what is left of the screen rather than pushing the
     feed down: ten lines is more than a phone shows at once. */
  .cat-drop{
    position:fixed;left:0;right:0;bottom:0;top:var(--drop-top,139px);
    margin:0;border-radius:0;border-left:0;border-right:0;
    overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;z-index:60;
    padding:16px var(--pad) calc(16px + env(safe-area-inset-bottom));
  }
}
.cat-drop-head{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:8px}
.cat-drop-head .cat-all{margin-bottom:0}
@media (min-width:901px){
  .cat-drop-head .js-drop-close{display:none}
}
/* The lines start where the tag does, so the column reads as one. */
.cat-drop .starter{padding-inline:0}
.card-live .live-pill{position:static}
/* Nothing at all until the first frame: an empty black box for a
   second reads as something failing. */
/* In the layout so the observer can see it, but taking no space and
   showing nothing until the first frame arrives. */
.feed-live{position:absolute;inset:0;background:#000 50% 30%/cover}
.feed-live .live-pill{position:absolute;top:12px;left:12px}
/* Their face while the stream connects: a second of black reads as
   broken, a second of them reads as waiting. */
@media (max-width:1100px){.frame>main~*{display:none}}
.composer:not(.has-line) :is(.composer-foot,.cs-post){display:none}
.mark span em{font-style:normal;color:var(--flare)}
/* A hidden sheet stays hidden: position:fixed can otherwise beat the
   attribute's own display:none for a frame on load. */

/* ---- landing ---- */
.lp{display:grid;justify-items:center;gap:18px;max-width:340px;margin:0 auto;padding:8vh 0 40px;text-align:center}
.lp .mark{pointer-events:none}
.lp-line{color:var(--sand);font-size:var(--fs);margin-bottom:6px}
.lp-form{display:grid;gap:10px;width:100%}
.lp-form input{padding:13px 15px;background:var(--ink-2);border:1px solid var(--line);border-radius:var(--r);color:var(--cream);font:inherit;font-size:var(--fs)}
.lp-form input:focus{outline:2px solid var(--flare);outline-offset:-1px}
.lp-form .btn{width:100%;margin-top:4px}
.lp-alt{color:var(--sand-dim);font-size:var(--fs-sm)}
.lp-acts{display:grid;gap:10px;width:100%}
.lp-acts .btn{width:100%}
.lp-wide{max-width:380px}
.lp-wide .form{width:100%;text-align:left}
.bare-foot{display:flex;flex-wrap:wrap;justify-content:center;gap:8px 16px;padding:32px var(--pad) 40px;font-size:var(--fs-sm);color:var(--sand-dim)}
.bare-foot a{color:inherit;text-decoration:none}
.bare-foot a:hover{color:var(--flare)}

/* A liked heart is the same shape filled in. */
.post-acts .act.on{color:var(--flare)}
.post-acts .act.on svg path{fill:currentColor;stroke:currentColor}

/* ---- feed (phones) ---- */
@media (max-width:900px){
  /* The page scrolls; the header stays put above it. */
  body:has(#stream) .site-head{
    position:fixed;
    top:0;
    left:0;
    right:0;
  }
}

@media (min-width:1px){

  /* svh, not dvh: dvh grows when the URL bar retracts, so a card sized
     in it runs past the bottom of the screen and takes the caption with
     it — under the bar, which is measured against the real viewport. */
  .card.post{
    position:relative;height:100svh;scroll-snap-align:start;
    padding:0;overflow:hidden;background:var(--ink-2);

    /* Rows, not arithmetic. The picture row is fixed, so it never moves
       while someone types; the panel takes what is left and clips its
       oldest messages when the conversation outgrows it. */
    display:grid;

    /* Clearance, identity, picture, panel, clearance. The identity has
       a band of its own, so it never sits on an attachment. */
    grid-template-rows:
      var(--post-media-top)
      var(--post-band-h)
      var(--post-media-share)
      minmax(0, 1fr)
      var(--post-bottom-clear);

    /* The middle two tracks are the picture and the rail; the 1fr on
       either side centres that pair whatever the picture's shape. */
    grid-template-columns:
      1fr
      var(--post-col)
      var(--post-control-gap)
      var(--post-control-w)
      1fr;
  }

  /* The identity sits on the picture rather than above it: the media
     spans its row too, and the band's own track is collapsed. */
  .card.post .post-media{
    grid-row:2 / 4;
    grid-column:1 / -1;
    position:relative;border-radius:0;aspect-ratio:auto;min-height:0;
  }
  .card.post .post-media .gal{border-radius:0}

  .card.post .starter-tag,
  .card.post .post-counts{
    position:relative;z-index:1;margin:0;padding:0 18px;
  }

  .card.post .post-foot-stack{
    grid-row:4;
    grid-column:1 / -1;
    position:relative;
    z-index:2;
  }

  /* The line and who posted it stay; meta (location/time) and counts
     are a tap away on their profile instead. */
  .card.post .post-meta,
  .lb-who .post-meta,
  .card.post .post-counts{display:none}
  .card.post .menu summary{color:var(--cream);filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))}

  .card.post .feed-sound{
    z-index:3;
  }
  .card.post .post-name,
  .lb-who .post-name{font-size:var(--fs)}

  /* The line is the post. It should read from across the room, and
     everything else on the card should defer to it. */
  .card.post .post-body{
    font-size:var(--fs-xl);font-weight:600;line-height:1.2;letter-spacing:-.015em;
    text-wrap:balance;text-shadow:0 2px 12px rgba(0,0,0,.5);
  }
  .card.post .starter-tag{font-size:var(--fs-sm);opacity:.85}

  /* The old row goes: these are the rail now. */
  .card.post .post-acts{display:none}

  /* Actions stay on the visual stage. */

}

.lines-sheet{z-index:60;background:var(--ink);overflow-y:auto;padding-bottom:120px}

/* The row is the link; the accept and decline buttons stay outside it
   so a tap on them is not a navigation. */
.notif-go{display:flex;align-items:center;gap:12px;flex:1;min-width:0;color:inherit;text-decoration:none}

/* [hidden] is the app state, so it wins over any component display rule. */
[hidden]{display:none}

/* Same card, loose on a wide screen: it sits in the column with its
   own edges rather than filling the window like a page. */
@media (min-width:901px){
  .card.post{
    /* Card plus gap is exactly one screen below the header: a gap under
       every card, and the next one starts at the window's edge. */
    --post-card-gap:12px;--post-card-h:calc(100dvh - var(--head-h,71px) - var(--post-card-gap));height:var(--post-card-h);
    border-radius:var(--r);margin-bottom:var(--post-card-gap);
  }
}

/* No double-tap zoom anywhere: a second tap is always a second tap,
   never a magnifier. Pinch still works where it is allowed. */
html{touch-action:manipulation}

/* The panel is wider than the button it hangs off, so on a phone it
   answers to the screen: full width, directly under the header. */
@media (max-width:900px){
  .bell-pop{
    position:fixed;left:8px;right:8px;width:auto;max-width:none;
    top:calc(var(--head-h,64px) + 8px);
  }
  .bell-pop{bottom:calc(var(--bar-h,96px) + 8px);display:flex;flex-direction:column}
  .bell-list{max-height:none;flex:1;min-height:0}
}

/* iOS zooms a field it thinks is too small to read, so nothing that
   takes typing goes under 16px. */
input,textarea,select{font-size:max(16px,1em)}

/* === CONTEXTUAL HEADER START ===
   Focused pages can replace the normal site header with page context.
   Same 71px chrome on desktop and mobile; content adapts inside it.
*/
.ctx-head{
  position:sticky;
  top:0;
  height:71px;
  z-index:30;
  background:var(--ink);
  border-bottom:1px solid var(--line);
}

.ctx-inner{
  width:min(1180px,100% - var(--pad)*2);
  height:71px;
  margin-inline:auto;
  display:flex;
  align-items:center;
  gap:10px;
}

.ctx-back{
  width:38px;
  height:38px;
  flex:0 0 38px;
  display:grid;
  place-items:center;
  border-radius:50%;
  color:var(--cream);
  text-decoration:none;
}

.ctx-back:hover{
  background:rgba(var(--cream-rgb),.06);
}

.ctx-title{
  min-width:0;
  color:var(--cream);
  font:600 var(--fs-lg)/1.2 var(--font);
  letter-spacing:-.01em;
}

.ctx-person{
  min-width:0;
  flex:1;
  display:flex;
  align-items:center;
  gap:9px;
  color:var(--cream);
  text-decoration:none;
  font-weight:600;
}

.ctx-av{
  width:32px;
  height:32px;
  flex:0 0 32px;
  display:grid;
  place-items:center;
  overflow:hidden;
  border-radius:50%;
  background:var(--ink-2);
  color:var(--sand-dim);
}

.ctx-av img{
  width:100%;
  height:100%;
  object-fit:cover;
}

.ctx-name{
  min-width:0;
  display:flex;
  align-items:center;
  gap:6px;
  overflow:hidden;
  white-space:nowrap;
  text-overflow:ellipsis;
}

.ctx-action{
  margin-left:auto;
}

@media (max-width:900px){
  .ctx-head{
    height:64px;
  }

  .ctx-inner{
    width:calc(100% - var(--pad)*2);
    height:64px;
  }

  .ctx-title{
    font-size:var(--fs-lg);
  }

  .ctx-av{
    width:34px;
    height:34px;
    flex-basis:34px;
  }
}
/* === CONTEXTUAL HEADER END === */

/* === THREAD INTERNAL SCROLL START === */
.th-log{
  overflow-y:auto;
  overscroll-behavior-y:contain;
  scrollbar-gutter:stable;
  min-height:0;
}
/* === THREAD INTERNAL SCROLL END === */

/* === MESSAGE WORKSPACE START === */

.msg-workspace{
  width:min(1180px,100%);
  height:100dvh;
  margin-inline:auto;
  display:grid;
  grid-template-columns:340px minmax(0,1fr);
  overflow:hidden;
}

.msg-workspace-list{
  min-width:0;
  height:100dvh;
  display:flex;
  flex-direction:column;
  background:var(--ink);
}

.msg-list-head{
  height:71px;
  flex:0 0 71px;
  padding:0 16px;
  display:flex;
  align-items:center;
  gap:10px;
}

.msg-list-head strong{
  color:var(--cream);
  font:600 var(--fs-lg)/1.2 var(--font);
}

.msg-list-back,
.msg-thread-back{
  width:38px;
  height:38px;
  flex:0 0 38px;
  display:grid;
  place-items:center;
  border-radius:50%;
  color:var(--cream);
  text-decoration:none;
}

.msg-list-back:hover,
.msg-thread-back:hover{
  background:rgba(var(--cream-rgb),.06);
}

.msg-list-scroll{
  min-height:0;
  flex:1;
  overflow-y:auto;
  padding:10px 8px 24px;
  overscroll-behavior-y:contain;
}

.msg-workspace-list .thread.active{
  background:var(--ink-2);
}

.msg-workspace-chat{
  min-width:0;
  height:100dvh;
  display:flex;
  flex-direction:column;
  overflow:hidden;
  background:var(--ink);
}

.msg-thread-head{
  height:71px;
  flex:0 0 71px;
  padding:0 24px;
  display:flex;
  align-items:center;
  gap:10px;
  border-bottom:1px solid var(--line);
}

.msg-thread-person{
  min-width:0;
  flex:1;
  display:flex;
  align-items:center;
  gap:10px;
  color:var(--cream);
  text-decoration:none;
  font-weight:600;
}

.msg-thread-av{
  width:36px;
  height:36px;
  flex:0 0 36px;
  display:grid;
  place-items:center;
  overflow:hidden;
  border-radius:50%;
  background:var(--ink-2);
  color:var(--sand-dim);
}

.msg-thread-av img{
  width:100%;
  height:100%;
  object-fit:cover;
}

.msg-thread-name{
  min-width:0;
  display:flex;
  align-items:center;
  gap:6px;
  overflow:hidden;
  white-space:nowrap;
  text-overflow:ellipsis;
}

.msg-thread-call{
  margin-left:auto;
}

.msg-workspace-chat .th-log{
  flex:1;
  min-height:0;
  height:auto !important;
  margin:0;
  padding:18px 24px;
  overflow-y:auto;
}

.msg-workspace-chat .th-note{
  flex:0 0 auto;
  margin:0;
  padding:10px 24px;
}

.msg-workspace-chat .th-send{
  position:static;
  flex:0 0 auto;
  width:auto;
  padding:10px 24px 16px;
  background:var(--ink);
}

.msg-workspace-empty{
  height:100%;
  display:grid;
  place-items:center;
  color:var(--sand-dim);
  text-align:center;
  padding:24px;
}

/* Mobile remains list -> conversation -> back. */
@media (max-width:900px){
  .msg-workspace{
    width:100%;
    height:100dvh;
    display:block;
  }

  .msg-workspace.inbox-only .msg-workspace-chat{
    display:none;
  }

  .msg-workspace.has-thread .msg-workspace-list{
    display:none;
  }

  .msg-workspace-list,
  .msg-workspace-chat{
    width:100%;
    height:100dvh;
  }

  .msg-list-head,
  .msg-thread-head{
    height:64px;
    flex-basis:64px;
  }

  .msg-thread-head{
    padding-inline:var(--pad);
  }

  .msg-workspace-chat .th-log{
    padding:14px var(--pad);
  }

  .msg-workspace-chat .th-send{
    position:fixed;
    left:var(--pad);
    right:var(--pad);
    bottom:0;
    width:auto;
    padding:10px 0;
  }
}

/* === MESSAGE WORKSPACE END === */

/* === MESSAGE WORKSPACE DESKTOP POLISH START === */
@media (min-width:901px){

  /* Messaging is its own desktop workspace, so use more of the screen. */
  .msg-workspace{
    width:min(1480px,calc(100% - 48px));
    grid-template-columns:300px minmax(0,1fr);
  }

  /* The thread is already visible beside the list on desktop. */
  .msg-thread-back{
    display:none;
  }

  .msg-thread-head{
    padding-inline:28px;
  }

  /*
   * Keep messages visually connected even on a very wide monitor.
   * The pane stays wide; the actual conversation gets a readable width.
   */
  .msg-workspace-chat .th-log,
  .msg-workspace-chat .th-post{
    width:min(900px,100%);
    margin-inline:auto;
    box-sizing:border-box;
    padding-inline:20px;
  }

  /* The picture is the band: padding would leave the anchor's own
     background showing as a shelf either side of it. */
  .msg-workspace-chat .th-post{padding-inline:0}

  .msg-workspace-chat .th-note{
    width:min(900px,100%);
    margin-inline:auto;
    box-sizing:border-box;
  }

  .msg-workspace-chat .th-send{
    width:min(900px,calc(100% - 40px));
    margin-inline:auto;
    padding:10px 0 16px;
    box-sizing:border-box;
  }
}
/* === MESSAGE WORKSPACE DESKTOP POLISH END === */

/* === MESSAGE WORKSPACE FINAL PROPORTIONS START === */
@media (min-width:901px){

  .msg-workspace-chat .th-log,
  .msg-workspace-chat .th-post{
    width:min(760px,100%);
  }

  .msg-workspace-chat .th-note{
    width:min(760px,100%);
  }

  .msg-workspace-chat .th-send{
    width:min(760px,calc(100% - 40px));
  }

  .msg-workspace-list .thread{
    border-radius:10px;
  }

  .msg-workspace-list .thread.active{
    background:rgba(var(--cream-rgb),.07);
  }
}
/* === MESSAGE WORKSPACE FINAL PROPORTIONS END === */

/* === MESSAGE WORKSPACE BOTTOM SPACING START === */
@media (min-width:901px){
  .msg-workspace-chat .th-log{
    padding-bottom:32px;
    scroll-padding-bottom:32px;
  }
}
/* === MESSAGE WORKSPACE BOTTOM SPACING END === */

/* === MOBILE THREAD COMPOSER CLEARANCE START === */
@media (max-width:900px){
  .msg-workspace-chat .th-log{
    box-sizing:border-box;
    padding-bottom:calc(var(--th-send-h,72px) + 16px);
    scroll-padding-bottom:calc(var(--th-send-h,72px) + 16px);
  }
}
/* === MOBILE THREAD COMPOSER CLEARANCE END === */

/* ---- discover filters ---- */
.discover-sheet{
  z-index:70;
  background:rgba(var(--ink-rgb),.82);
  backdrop-filter:blur(8px);
  display:grid;
  place-items:center;
  padding:20px;
}
.discover-sheet[hidden]{display:none}
.discover-panel{
  width:min(620px,100%);
  max-height:min(760px,calc(100dvh - 40px));
  display:flex;
  flex-direction:column;
  overflow:hidden;
  background:var(--ink);
  border:1px solid var(--line);
  border-radius:var(--r);
}
.discover-head{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:18px;
  padding:20px;
  border-bottom:1px solid var(--line);
}
.discover-head strong{
  display:block;
  font:600 var(--fs-lg)/1.1 var(--font);
  color:var(--cream);
}
.discover-head span{
  display:block;
  margin-top:5px;
  color:var(--sand-dim);
  font-size:var(--fs-sm);
}
.discover-body{
  overflow-y:auto;
  overscroll-behavior:contain;
  padding:22px 20px;
}
.discover-group{
  border:0;
  padding:0;
  margin:0 0 28px;
}
.discover-group:last-child{margin-bottom:0}
.discover-group legend{
  margin-bottom:12px;
  color:var(--sand-dim);
  font:600 var(--fs-xs)/1 var(--font);
  text-transform:uppercase;
  letter-spacing:.09em;
}
.discover-options{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
}
.discover-option{
  cursor:pointer;
}
.discover-option input{
  position:absolute;
  opacity:0;
  pointer-events:none;
}
.discover-option span{
  display:block;
  padding:9px 13px;
  border:1px solid var(--line);
  border-radius:var(--r-pill);
  color:var(--sand);
  font-size:var(--fs-sm);
}
.discover-option:hover span{
  border-color:var(--sand-dim);
  color:var(--cream);
}
.discover-option input:checked + span{
  border-color:var(--flare);
  background:rgba(var(--flare-rgb),.12);
  color:var(--flare);
}
.discover-line-list{
  display:grid;
  gap:4px;
}
.discover-line.is-hidden{
  display:none;
}
.discover-line{
  display:flex;
  align-items:flex-start;
  gap:12px;
  padding:12px;
  border:1px solid transparent;
  border-radius:var(--r);
  cursor:pointer;
}
.discover-line:hover{
  background:rgba(var(--cream-rgb),.04);
}
.discover-line:has(input:checked){
  border-color:var(--flare);
  background:rgba(var(--flare-rgb),.08);
}
.discover-line input{
  margin-top:3px;
  accent-color:var(--flare);
}
.discover-line span{
  min-width:0;
}
.discover-line strong{
  display:block;
  color:var(--cream);
  font-size:var(--fs);
}
.discover-line em{
  display:block;
  margin-top:3px;
  color:var(--sand-dim);
  font-size:var(--fs-sm);
  font-style:normal;
  line-height:1.35;
}
.discover-actions{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:16px;
  padding:16px 20px;
  border-top:1px solid var(--line);
}
.discover-clear{
  color:var(--sand);
  font-size:var(--fs-sm);
  text-decoration:none;
}
.discover-clear:hover{color:var(--cream)}

@media (max-width:700px){
  .discover-sheet{
    padding:0;
    place-items:stretch;
    background:var(--ink);
  }
  .discover-panel{
    width:100%;
    max-height:100dvh;
    height:100dvh;
    border:0;
    border-radius:0;
  }
  .discover-head{
    padding-top:calc(18px + env(safe-area-inset-top));
  }
  .discover-actions{
    padding-bottom:calc(16px + env(safe-area-inset-bottom));
  }
}

/* ---- settings hub + shared sheet ---- */
.settings-hub{
  display:grid;
  margin-top:18px;
}

.settings-row{
  width:100%;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:18px;
  padding:17px 2px;
  background:none;
  border:0;
  color:var(--cream);
  font:inherit;
  text-align:left;
  cursor:pointer;
}

.settings-row-copy{
  min-width:0;
}

.settings-row strong{
  display:block;
  font-size:var(--fs);
  font-weight:600;
}

.settings-row em{
  display:block;
  margin-top:3px;
  overflow:hidden;
  color:var(--sand-dim);
  font-size:var(--fs-sm);
  font-style:normal;
  text-overflow:ellipsis;
  white-space:nowrap;
}

.settings-row-arrow{
  flex:0 0 auto;
  color:var(--sand-dim);
  font-size:var(--fs-xl);
  line-height:1;
}

.settings-sheet{
  position:fixed;
  inset:0;
  z-index:80;
  display:grid;
  place-items:center;
  padding:20px;
  background:rgba(0,0,0,.76);
}

.settings-sheet[hidden]{
  display:none;
}

.settings-panel{
  width:min(560px,100%);
  max-height:calc(100dvh - 40px);
  display:flex;
  flex-direction:column;
  overflow:hidden;
  background:var(--ink);
  border:1px solid var(--line);
  border-radius:18px;
  box-shadow:0 24px 70px rgba(0,0,0,.45);
}

.settings-sheet-head{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:16px;
  padding:16px 18px;
  border-bottom:1px solid var(--line);
}

.settings-sheet-head > strong{
  font-size:var(--fs-lg);
  font-weight:600;
}

.settings-sheet-body{
  overflow-y:auto;
  overscroll-behavior:contain;
  padding:20px;
}

.settings-pane[hidden]{
  display:none;
}

.settings-pane .form{
  display:grid;
  gap:18px;
}

.settings-pane select{
  width:100%;
  min-height:46px;
  padding:10px 12px;
  border:1px solid var(--line);
  border-radius:10px;
  background:var(--ink);
  color:var(--cream);
  font:inherit;
}

@media (max-width:700px){
  .settings-sheet{
    padding:0;
    place-items:stretch;
  }

  .settings-panel{
    width:100%;
    height:100dvh;
    max-height:100dvh;
    border:0;
    border-radius:0;
  }

  .settings-sheet-head{
    padding-top:calc(
      16px + env(safe-area-inset-top)
    );
  }

  .settings-sheet-body{
    padding-bottom:calc(
      24px + env(safe-area-inset-bottom)
    );
  }
}

/* ---- discover compact drill navigation ---- */
.discover-head{
  position:relative;
}

.discover-head-copy{
  min-width:0;
  flex:1;
}

.discover-back{
  width:40px;
  height:40px;
  flex:0 0 40px;
  display:grid;
  place-items:center;
  padding:0;
  border:0;
  border-radius:50%;
  background:transparent;
  color:var(--cream);
  font:400 30px/1 var(--font);
  cursor:pointer;
}

.discover-back:hover{
  background:rgba(var(--cream-rgb),.06);
}

.discover-view[hidden]{
  display:none;
}

.discover-section-label{
  margin:4px 2px 10px;
  color:var(--sand-dim);
  font:600 var(--fs-xs)/1 var(--font);
  text-transform:uppercase;
  letter-spacing:.09em;
}

.discover-section-label:not(:first-child){
  margin-top:28px;
}

.discover-filter-row{
  width:100%;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:18px;
  padding:15px 4px;
  border:0;
  background:transparent;
  color:inherit;
  text-align:left;
  cursor:pointer;
}

.discover-filter-row > span:first-child{
  min-width:0;
  display:block;
}

.discover-filter-row strong{
  display:block;
  color:var(--cream);
  font:600 var(--fs)/1.25 var(--font);
}

.discover-filter-row small{
  display:block;
  margin-top:4px;
  overflow:hidden;
  color:var(--sand-dim);
  font:400 var(--fs-sm)/1.3 var(--font);
  text-overflow:ellipsis;
  white-space:nowrap;
}

.discover-chevron{
  flex:0 0 auto;
  color:var(--sand-dim);
  font-size:var(--fs-xl);
  line-height:1;
}

.discover-filter-row:hover strong,
.discover-filter-row:hover .discover-chevron{
  color:var(--flare);
}

.discover-choice-list{
  display:grid;
  gap:4px;
}

.discover-choice{
  position:relative;
  display:flex;
  align-items:center;
  min-height:48px;
  padding:0 14px;
  border:1px solid transparent;
  border-radius:var(--r);
  color:var(--sand);
  cursor:pointer;
}

.discover-choice:hover{
  background:rgba(var(--cream-rgb),.04);
  color:var(--cream);
}

.discover-choice:has(input:checked){
  border-color:var(--flare);
  background:rgba(var(--flare-rgb),.08);
  color:var(--flare);
}

.discover-choice input{
  position:absolute;
  opacity:0;
  pointer-events:none;
}

.discover-choice span{
  font-size:var(--fs);
}

@media (max-width:700px){
  .discover-filter-row{
    padding:17px 4px;
  }

  .discover-choice{
    min-height:52px;
  }
}

/* Inline flirt composer on fullscreen post cards */
@media (min-width:1px){
  .card.post .post-body,
  .card.post .post-quick-bubble p,
  .lb-chat .post-quick-bubble p,
  .th-log .post-quick-bubble p{
    font-size:var(--fs-line);
    font-weight:600;
    line-height:1.22;
    letter-spacing:-.012em;
  }

  .card.post .post-flirt-form,
  .lb-chat .post-flirt-form,
  .room-chat .post-flirt-form{
    display:flex;
    align-items:center;
    gap:6px;
    width:min(100%,520px);
    padding:5px;
    border:1px solid rgba(var(--cream-rgb),.26);
    border-radius:999px;
    background:rgba(var(--ink-rgb),.48);
    backdrop-filter:blur(14px);
    -webkit-backdrop-filter:blur(14px);
  }

  .card.post .post-flirt-input,
  .lb-chat .post-flirt-input,
  .room-chat .post-flirt-input{
    min-width:0;
    flex:1;
    border:0;
    outline:0;
    background:transparent;
    color:var(--cream);
    padding:9px 10px;
    font:500 var(--fs)/1.2 var(--font);
  }

  .card.post .post-flirt-input::placeholder,
  .lb-chat .post-flirt-input::placeholder,
  .room-chat .post-flirt-input::placeholder{
    color:rgba(var(--cream-rgb),.62);
  }

  .card.post .post-flirt-send,
  .lb-chat .post-flirt-send,
  .room-chat .post-flirt-send{
    border:0;
    border-radius:999px;
    background:var(--flare);
    color:var(--ink);
    padding:10px 15px;
    font:700 var(--fs-sm)/1 var(--font);
    cursor:pointer;
  }

  .card.post .post-flirt-send:disabled,
  .lb-chat .post-flirt-send:disabled,
  .room-chat .post-flirt-send:disabled{
    opacity:.55;
    cursor:default;
  }

}

/* === FEED CARD: MEDIA + CONVERSATION ===
   One card structure on every screen. Breakpoints only tune dimensions;
   media, speech and composer keep the same relationship everywhere. */
.card.post{
  /* A floor for the panel, not its height: it grows past this whenever
     the caption or the conversation needs the room. */
  --post-panel-h:180px;
  --post-panel-edge:14px;
  --post-bottom-clear:0px;
}

.card.post .post-media img,
.card.post .post-media video,
.card.post .post-media .gal,
.card.post .post-media .tile{
  width:100%;
  height:100%;
  object-fit:cover;
}

.card.post .post-foot-stack{
  margin:0 var(--post-panel-edge) var(--post-panel-edge);
  min-height:var(--post-panel-h);
  padding:18px;

  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:14px;

  border:1px solid rgba(var(--cream-rgb),.12);
  border-radius:24px;
  background:rgba(var(--ink-rgb),.94);
  box-shadow:0 16px 40px rgba(0,0,0,.24);
}

.card.post .post-body{
  flex:0 1 auto;
  width:100%;
  max-width:24ch;
  margin:0;
  padding:12px 14px;
  border:1px solid rgba(var(--cream-rgb),.10);
  border-radius:18px 18px 18px 6px;
  background:rgba(var(--cream-rgb),.06);
  text-shadow:none;
}

.card.post .post-flirt-form,
.lb-chat .post-flirt-form,
.room-chat .post-flirt-form{
  width:100%;
  background:rgba(var(--cream-rgb),.06);
}

/* The prompt now has its own readable surface. */
.card.post::after{
  display:none;
}

/* Fullscreen mobile keeps clearance for the floating navigation. */
@media (max-width:900px){
  .card.post{
    --post-panel-h:220px;
    --post-panel-edge:12px;
    --post-bottom-clear:var(--bar-h,96px);
  }
}

.card.post .post-conversation-log{
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:10px;
  width:100%;
  min-height:0;
  overflow:hidden;
}

.card.post .post-quick-chat[hidden],
.lb-chat .post-quick-chat[hidden]{
  display:none;
}

.card.post .post-quick-chat,
.lb-chat .post-quick-chat,
.card.post .post-opener{
  display:grid;
  gap:8px;
  width:100%;
  min-height:0;
}

.card.post .post-quick-msg,
.lb-chat .post-quick-msg,
.room-chat .post-quick-msg,
.th-log .post-quick-msg{
  justify-self:start;
  display:flex;
  align-items:flex-end;
  gap:10px;
  max-width:82%;
}

.card.post .post-quick-msg.mine,
.lb-chat .post-quick-msg.mine,
.room-chat .post-quick-msg.mine,
.th-log .post-quick-msg.mine{
  justify-self:end;
  flex-direction:row-reverse;
}

.card.post .post-quick-avatar,
.lb-chat .post-quick-avatar,
.room-chat .post-quick-avatar,
.th-log .post-quick-avatar{
  width:52px;
  height:52px;
  display:grid;
  place-items:center;
  flex:0 0 52px;
  overflow:hidden;
  border-radius:50%;
  background:var(--wine);
  color:rgba(var(--cream-rgb),.72);
  box-shadow:0 0 0 1px rgba(var(--cream-rgb),.12);
}

.card.post .post-quick-avatar img,
.lb-chat .post-quick-avatar img,
.room-chat .post-quick-avatar img,
.th-log .post-quick-avatar img{
  width:100%;
  height:100%;
  object-fit:cover;
}

.card.post .post-quick-bubble,
.lb-chat .post-quick-bubble,
.room-chat .post-quick-bubble,
.th-log .post-quick-bubble{
  padding:10px 13px;
  border:1px solid rgba(var(--cream-rgb),.10);
  border-radius:18px 18px 18px 6px;
  background:rgba(var(--cream-rgb),.06);
}

.card.post .post-quick-msg.mine .post-quick-bubble,
.lb-chat .post-quick-msg.mine .post-quick-bubble,
.room-chat .post-quick-msg.mine .post-quick-bubble,
.th-log .post-quick-msg.mine .post-quick-bubble{
  border-radius:18px 18px 6px 18px;
  border-color:rgba(var(--flare-rgb),.35);
  background:rgba(var(--flare-rgb),.16);
}

.card.post .post-quick-bubble p,
.lb-chat .post-quick-bubble p,
.room-chat .post-quick-bubble p,
.th-log .post-quick-bubble p{
  margin:0;
  overflow-wrap:anywhere;
}

/* Them, thinking: three dots in their own bubble, same shape as a
   real message so it reads as part of the conversation, not a
   separate loading state. */
.card.post .typing-dots,
.lb-chat .typing-dots{
  display:inline-flex;
  align-items:center;
  gap:3px;
  padding:2px 1px;
}
.card.post .typing-dots i,
.lb-chat .typing-dots i{
  width:6px;height:6px;border-radius:50%;
  background:currentColor;
  opacity:.45;
  animation:post-typing-dot 1.2s ease-in-out infinite;
}
.card.post .typing-dots i:nth-child(2),
.lb-chat .typing-dots i:nth-child(2){animation-delay:.15s}
.card.post .typing-dots i:nth-child(3),
.lb-chat .typing-dots i:nth-child(3){animation-delay:.3s}
@keyframes post-typing-dot{
  0%,60%,100%{opacity:.35;transform:translateY(0)}
  30%{opacity:1;transform:translateY(-2px)}
}

.card.post .post-flirt-form,
.lb-chat .post-flirt-form,
.room-chat .post-flirt-form{
  flex:0 0 auto;
}

.card.post .post-flirt-form.is-waiting,
.lb-chat .post-flirt-form.is-waiting,
.room-chat .post-flirt-form.is-waiting{
  opacity:.78;
}

.card.post .post-flirt-form.is-waiting .post-flirt-input,
.lb-chat .post-flirt-form.is-waiting .post-flirt-input,
.room-chat .post-flirt-form.is-waiting .post-flirt-input{
  cursor:default;
}

/* === FEED CARD: MEDIA + CONVERSATION END === */

/* === FEED FLIRT CARD ===
   The card owns a fixed media territory and external action rail.
   The actual attachment keeps its stored aspect ratio. */

.card.post{
  --post-media-edge:18px;
  --post-media-radius:24px;
  --post-control-w:38px;
  --post-control-gap:12px;
  --post-media-top:var(--head-h,71px);

  /* One knob: the band is whatever the avatar needs, so changing the
     avatar per breakpoint moves the band with it. */
  --post-avatar-h:52px;
  --post-band-h:calc(var(--post-avatar-h) + 4px);

  /* How far the identity and the rail sit below the picture's top. */
  --post-rail-drop:24px;

  /* How much of the card the picture takes. The panel gets the rest and
     grows past it when the conversation needs the room. */
  --post-media-share:58svh;

  /* Air between the identity and the top of the picture. */
  --post-band-gap:14px;

  /* The same frame the site header lays itself out in, so the rail ends
     exactly where the header's buttons end and the identity starts
     where the brand starts. */
  --post-frame:min(1180px, 100% - var(--pad) * 2);

  /* One column for the picture, the same width whatever shape the
     picture is. Everything else on the card hangs off its edges, so a
     landscape photo and a portrait reel put the identity and the rail
     in exactly the same place. Capped, so the picture does not sprawl
     on a wide screen. */
  --post-col:min(
    480px,
    var(--post-frame) - var(--post-control-gap) - var(--post-control-w)
  );
}

/* Fixed territory. The final strip on the right belongs to card actions. */
.card.post .post-media{
  margin:0;

  display:flex;
  /* Top of the row, not the middle of it: the identity sits on this
     edge, and a picture floating in the centre leaves it attached to
     nothing. */
  align-items:flex-start;
  justify-content:center;

  overflow:visible;
  border:0;
  border-radius:0;
  background:transparent;
  box-shadow:none;
}

/* Single photos use their stored dimensions as the attachment shape. */
.card.post .post-photo-attachment{
  position:relative;
  display:flex;
  align-items:center;
  justify-content:center;

  width:min(100cqw,100cqh);
  aspect-ratio:1;

  overflow:hidden;
  border:1px solid rgba(var(--cream-rgb),.14);
  border-radius:var(--post-media-radius);
  background:transparent;
  box-shadow:0 16px 40px rgba(0,0,0,.20);
}

.card.post .post-photo-attachment .gal-1,
.card.post .post-photo-attachment .gal-1 .tile{
  width:100%;
  height:100%;
  max-width:none;
  max-height:none;
  border:0;
  border-radius:inherit;
  background:transparent;
  box-shadow:none;
}

.card.post .post-photo-attachment .gal-1 img{
  display:block;
  width:100%;
  height:100%;
  max-width:none;
  max-height:none;
  object-fit:cover;
  object-position:center;
  border-radius:inherit;
}

/* Multi-photo posts keep the existing gallery composition. */
.card.post .post-media .gal:not(.gal-1){
  width:100%;
  height:100%;
  overflow:hidden;
  border:1px solid rgba(var(--cream-rgb),.14);
  border-radius:var(--post-media-radius);
  box-shadow:0 16px 40px rgba(0,0,0,.20);
}

/* Video itself is the attachment. */
.card.post .post-media .feed-reel{
  position:relative;
  width:min(100cqw,100cqh);
  aspect-ratio:1;

  overflow:hidden;
  border:1px solid rgba(var(--cream-rgb),.14);
  border-radius:var(--post-media-radius);

  /* The poster is painted here, not on the video: setting a source
     clears the poster attribute, so JS hands it to this box instead.
     It has to be framed exactly as the video is — cover, centred —
     or the handoff to the first frame is a visible jump. */
  background:transparent center/cover no-repeat;

  box-shadow:0 16px 40px rgba(0,0,0,.20);
}

.card.post .post-media .feed-video{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;
  background:transparent;
}

/* Header now owns only card-level controls such as the menu. */

/* Card's top-left, whatever the post carries — the position posts
   without media already used. Attached to the media it moved with the
   attachment's shape, so a portrait reel and a landscape photo put the
   same avatar in two different places. */
.card.post > .post-identity{
  grid-row:2;
  grid-column:1 / -1;
  justify-self:start;
  margin-left:calc((100% - var(--post-frame)) / 2);
  margin-top:var(--post-rail-drop);
  z-index:4;

  display:flex;
  align-items:center;
  gap:10px;

  min-width:0;
  height:100%;
  padding:0;
  pointer-events:auto;
}

.card.post .post-identity .post-avatar,
.lb-who .post-identity .post-avatar{
  flex:0 0 auto;
}

.card.post .post-identity .post-who,
.lb-who .post-identity .post-who{
  min-width:0;
}

.card.post .post-identity,
.lb-who .post-identity{
  /* Long names must not reach the rail icons or wrap the row: leave
     room for the rail's own width plus its gap off the right edge. */
  max-width:calc(var(--post-frame) - var(--post-control-w) - var(--post-control-gap) - 12px);
}

.card.post .post-identity .post-name,
.lb-who .post-identity .post-name{
  text-shadow:none;
  min-width:0;
}

.card.post .post-identity .post-name a,
.lb-who .post-identity .post-name a{
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
  min-width:0;
}

.card.post .post-identity .verified,
.lb-who .post-identity .verified,
.card.post .post-identity .js-follow,
.lb-who .post-identity .js-follow{
  flex:0 0 auto;
}

/* Sound belongs to the actual video attachment. */
.card.post .post-media .feed-reel > .feed-sound{
  position:absolute;
  top:auto;
  right:var(--pad);
  bottom:var(--pad);
  left:auto;
  z-index:4;
  margin:0;
  width:var(--post-control-w);
  height:var(--post-control-w);
}

/* Like/save continue on the same external axis. */

/* Conversation remains the stable lower surface. */
.card.post .post-foot-stack{
  border-radius:24px 24px 20px 20px;
}

.card.post .post-foot-stack.has-conversation .post-opener{
  display:none;
}

.card.post .post-foot-stack.has-conversation .post-conversation-log{
  justify-content:flex-end;
}
.card.post .post-quick-chat{flex:none}

@media (min-width:901px){
  .card.post{
    --post-media-edge:20px;

    /* The header only overlays the card on a phone, where it is fixed.
       Here it is sticky and the card already begins beneath it, so a
       header's worth of clearance is just empty card. */
    --post-media-top:0px;
  }
}

/* Phones, last so it wins: the block above sets these unconditionally
   and later in the file, and a media query carries no extra weight. */
@media (max-width:900px){
  .card.post{
    /* Narrower card, and the picture is the point: the 52px that reads
       as balanced on a wide screen crowds it here. */

    /* Same button size as the site header's. */
    --post-control-w:38px;
  }
}

/* A live card is a post card: the stream sits in the picture column on
   the same terms as a photo or a reel, rather than filling a box that
   no longer exists. */
.card.post .post-media .feed-live{
  position:relative;
  inset:auto;

  width:auto;
  height:100%;
  max-width:100%;
  max-height:100%;
  aspect-ratio:var(--media-ratio, 9 / 16);

  display:block;
  overflow:hidden;
  border:1px solid rgba(var(--cream-rgb),.14);
  border-radius:var(--post-media-radius);
  background:#000 50% 30%/cover;
}

.card.post .post-media .feed-live video{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center;

  /* Nothing to show until a track arrives; .on is added on playing. */
  opacity:0;
  transition:opacity .2s ease;
}

.card.post .post-media .feed-live.on video{
  opacity:1;
}

.card.post .post-media .feed-live .live-pill{
  position:absolute;
  top:12px;
  left:12px;
  z-index:2;
}

/* === FEED FLIRT CARD END === */

/* ==== live room (views/pages/live.php) ====
   One screen: the stream on the left, a public chat column beside it.
   Last in the file and one class stronger than the card rules, so the
   feed's sizing never wins here. */
.frame.frame-solo,.frame-solo .col{display:block;padding:0;max-width:none;width:100%}
.frame-solo #main,.card.post.live-room{max-width:none;width:100%}
html:has(.live-room),html:has(.live-room) body{height:100%;overflow:hidden}

.card.post.live-room{
  --post-band-h:0px;
  height:calc(100dvh - var(--head-h,71px));
  grid-template-rows:var(--post-media-top) var(--post-band-h) minmax(0,1fr) auto var(--post-bottom-clear);
}

.card.post.live-room .live-chat{
  grid-row:4;grid-column:1 / -1;
  display:flex;flex-direction:column;gap:12px;min-height:0;overflow:hidden;
  margin:0 var(--post-panel-edge) var(--post-panel-edge);
}

/* The only thing on the page that scrolls. */
.card.post.live-room .live-messages{flex:1 1 0;min-height:0;overflow-y:auto;overscroll-behavior:contain;align-content:start}

/* Public chat: everyone on the left with their own avatar. */
.card.post.live-room .post-quick-msg.mine{justify-self:start;flex-direction:row}
.card.post.live-room .post-quick-msg.mine .post-quick-bubble{border-radius:18px 18px 18px 6px}
.card.post.live-room .post-quick-name,
.room-chat .post-quick-name{display:block;font-size:var(--fs-sm);font-weight:600;color:var(--flare)}
.card.post.live-room .lc-time,
.room-chat .lc-time{display:block;margin-top:4px;text-align:right;font-size:var(--fs-xs);color:var(--sand-dim)}
.lc-mute{background:none;border:0;color:var(--sand-dim);font-size:var(--fs-xs);cursor:pointer;align-self:center}
.lc-mute:hover{color:var(--flare)}

/* The stream's shape is unknown and can change: show the whole frame. */
.card.post.live-room .post-media .feed-live{width:100%;height:100%;max-height:none;aspect-ratio:auto;background:#000}
.card.post.live-room .post-media .feed-live video{object-fit:contain}

/* Over the stream: host top-left, LIVE top-right, Go private bottom-left. */
.card.post.live-room .live-host{
  position:absolute;top:12px;left:12px;z-index:2;
  display:flex;align-items:center;gap:8px;max-width:calc(100% - 100px);
  color:#fff;text-decoration:none;text-shadow:0 1px 4px rgba(0,0,0,.8);
}
.card.post.live-room .live-host-name{font-weight:600;font-size:var(--fs);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card.post.live-room .post-media .feed-live .live-pill{left:auto;right:12px}

/* Wide screens: stream aligned with the page frame, a gap, the chat. */
@media (min-width:901px){
  .card.post.live-room{
    --live-chat-w:360px;
    --live-gap:32px;
    --post-col:min(480px, var(--post-frame) - var(--live-gap) - var(--live-chat-w));
    grid-template-columns:calc((100% - var(--post-frame)) / 2) var(--post-col) var(--live-gap) var(--live-chat-w) 1fr;
  }
  .card.post.live-room .live-chat{grid-row:2 / 4;grid-column:4;margin:0 0 18px}
}

/* Phones: stream above, chat below, sharing the screen. */
@media (max-width:900px){
  .card.post.live-room{
    height:100dvh;
    grid-template-rows:var(--post-media-top) var(--post-band-h) minmax(0,1.2fr) minmax(0,1fr) var(--post-bottom-clear);
  }
}

/* Private request waiting box, over the live room. */

/* Incoming call card: who is ringing, Accept or Decline. */
.call-ring{
  position:fixed;left:50%;top:max(16px, env(safe-area-inset-top));transform:translateX(-50%);z-index:1000;
  width:min(360px, 100% - 24px);padding:16px;
  display:grid;grid-template-columns:auto 1fr;gap:12px 14px;align-items:center;
  border:1px solid rgba(var(--cream-rgb),.14);border-radius:24px;
  background:rgba(var(--ink-rgb),.97);box-shadow:0 18px 44px rgba(0,0,0,.45);
}
.call-ring[hidden]{display:none}
.call-ring .cr-av{
  width:52px;height:52px;border-radius:50%;overflow:hidden;display:grid;place-items:center;
  background:var(--wine);color:rgba(var(--cream-rgb),.72);box-shadow:0 0 0 2px var(--flare);
}
.call-ring .cr-av img{width:100%;height:100%;object-fit:cover}
.call-ring .cr-text{margin:0;font-size:var(--fs);font-weight:600;color:var(--cream)}
.call-ring .cr-acts{grid-column:1 / -1;display:grid;grid-template-columns:1fr 1fr;gap:10px}
.call-ring .cr-acts button{padding:12px;border-radius:999px;cursor:pointer;font:700 var(--fs)/1 var(--font)}
.call-ring .cr-decline{border:1px solid rgba(var(--cream-rgb),.2);background:none;color:var(--cream)}
.call-ring .cr-accept{border:0;background:var(--flare);color:var(--ink)}

/* Streamer on a private call: the room stays{
  position:absolute;inset:0;z-index:1;
  display:none;place-items:center;align-content:center;gap:6px;text-align:center;
  background:rgba(var(--ink-rgb),.85);color:var(--cream);
}

/* Private room: the live room's layout, your camera in the corner. */
.card.post.private-room .post-media .feed-live .pr-local{
  position:absolute;right:12px;top:60px;z-index:2;
  width:28%;max-width:150px;height:auto;aspect-ratio:3 / 4;
  object-fit:cover;border-radius:14px;background:#111;
  box-shadow:0 0 0 2px rgba(var(--cream-rgb),.6);
}
.private-room .pr-who{position:absolute;left:12px;right:12px;bottom:72px;z-index:2;margin:0;text-align:center;color:#fff;text-shadow:0 1px 4px rgba(0,0,0,.8)}
.private-room .pr-who:empty{display:none}
.private-room .pr-controls{position:absolute;left:0;right:0;bottom:12px;z-index:2;display:flex;justify-content:center;gap:12px}
.private-room .pr-controls .btn-round{background:rgba(0,0,0,.55);color:#fff}
.private-room .pr-controls .btn-round.off{background:var(--cream);color:var(--ink)}
.private-room .pr-controls .pr-end{background:var(--flare);color:var(--ink)}

/* Audio blocked by the browser: one tap brings it in. */
.private-room .pr-unmute{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:4;
  padding:12px 18px;border:0;border-radius:999px;cursor:pointer;
  background:rgba(0,0,0,.65);color:#fff;font:600 var(--fs)/1 var(--font);
}
.private-room .pr-unmute[hidden]{display:none}

/* Phones: the call is the whole screen. Video edge to edge, the last
   messages and the input over its lower part, three buttons below. */
@media (max-width:900px){
  .card.post.private-room{
    position:fixed;inset:0;z-index:900;
    display:block;height:100dvh;margin:0;padding:0;border-radius:0;
  }
  .card.post.private-room .post-media{position:absolute;inset:0;margin:0}
  .card.post.private-room .post-media .feed-live{border:0;border-radius:0}
  .card.post.private-room .post-media .feed-live .pr-remote{object-fit:cover}

  .card.post.private-room .live-host{top:calc(env(safe-area-inset-top) + 12px)}
  .card.post.private-room .post-media .feed-live .live-pill{top:calc(env(safe-area-inset-top) + 18px)}
  .card.post.private-room .post-media .feed-live .pr-local{top:calc(env(safe-area-inset-top) + 64px);width:26%;max-width:120px}
  .private-room .pr-who{top:calc(env(safe-area-inset-top) + 64px);bottom:auto}
  .private-room .pr-controls{bottom:calc(env(safe-area-inset-bottom) + 12px)}

  .card.post.private-room .live-chat{
    position:absolute;left:0;right:0;z-index:3;
    bottom:calc(env(safe-area-inset-bottom) + 76px);
    margin:0;padding:24px 12px 0;
    background:linear-gradient(transparent, rgba(0,0,0,.45));
  }
  .card.post.private-room .live-messages{
    flex:0 0 auto;
    height:auto;
    max-height:34dvh;
  }
  .card.post.private-room .post-quick-avatar{width:32px;height:32px;flex:0 0 32px}
  .card.post.private-room .post-quick-bubble{padding:6px 10px;background:rgba(0,0,0,.45);border-color:transparent}
  .card.post.private-room .post-quick-msg.mine .post-quick-bubble{background:rgba(var(--flare-rgb),.35)}
}

/* Phones: the live room is the whole screen, like a private call. */
@media (max-width:900px){
  .card.post.live-room{
    position:fixed;inset:0;z-index:900;
    display:block;height:100dvh;margin:0;padding:0;border-radius:0;
  }
  .card.post.live-room .post-media{position:absolute;inset:0;margin:0}
  .card.post.live-room .post-media .feed-live{border:0;border-radius:0}
  .card.post.live-room .post-media .feed-live video{object-fit:cover}

  .card.post.live-room .live-host{top:calc(env(safe-area-inset-top) + 12px)}
  .card.post.live-room .post-media .feed-live .live-pill{top:calc(env(safe-area-inset-top) + 18px)}

  /* Go private and sound sit on the same line{left:12px;bottom:calc(env(safe-area-inset-bottom) + 14px)}
  .card.post.live-room .live-mute{right:12px;bottom:calc(env(safe-area-inset-bottom) + 14px)}

  .card.post.live-room .live-chat{
    position:absolute;left:0;right:0;z-index:3;
    bottom:calc(env(safe-area-inset-bottom) + 72px);
    margin:0;padding:24px 12px 0;
    background:linear-gradient(transparent, rgba(0,0,0,.45));
  }
  /* Positioned from the bottom: the list sizes to its own content, and
     0 1 auto let it shrink to nothing. */
  .card.post.live-room .live-messages{
    flex:0 0 auto;
    height:auto;
    max-height:34dvh;
  }
  .card.post.live-room .post-quick-avatar{width:32px;height:32px;flex:0 0 32px}
  .card.post.live-room .post-quick-bubble{padding:6px 10px;background:rgba(0,0,0,.45);border-color:transparent}
  .card.post.live-room .post-quick-bubble p{font-size:var(--fs)}
  .card.post.live-room .post-quick-msg.mine .post-quick-bubble{background:rgba(var(--flare-rgb),.35)}
}

/* The room's rail: sound and the way into a private call{
  position:absolute;right:12px;bottom:12px;z-index:2;
  display:grid;gap:14px;justify-items:center;
}

@media (max-width:900px){
  /* Chat clears the rail rather than running under it. */
  .card.post.live-room .live-chat{right:76px}
}

/* Phones: split screen. Video on top, chat below it on its own ground,
   rather than floating over the picture. */
@media (max-width:900px){
  .card.post.live-room{display:grid;grid-template-columns:1fr;grid-template-rows:45dvh minmax(0,1fr)}
  .card.post.live-room > *{grid-column:1}

  .card.post.live-room .post-media{position:relative;inset:auto;grid-row:1;min-height:0}
  /* Edge to edge: no column cap, no page padding, no rounded corners. */
  .card.post.live-room .post-media{display:block;padding:0;margin:0}
  .card.post.live-room .post-media .feed-live{
    width:100%;height:100%;max-width:none;border:0;border-radius:0;
  }
  .card.post.live-room .post-media .feed-live video{object-fit:cover}

  .card.post.live-room .live-chat{
    position:relative;inset:auto;grid-row:2;right:auto;
    display:flex;min-height:0;background:none;
    padding:10px 12px calc(env(safe-area-inset-bottom) + 10px);
  }
  .card.post.live-room .live-messages{flex:1 1 auto;height:auto;max-height:none;overflow-y:auto}
  .card.post.live-room .post-quick-avatar{width:40px;height:40px;flex:0 0 40px}
  .card.post.live-room .post-quick-bubble{padding:10px 13px;background:rgba(var(--cream-rgb),.06);border-color:rgba(var(--cream-rgb),.10)}
  .card.post.live-room .post-quick-msg.mine .post-quick-bubble{background:rgba(var(--flare-rgb),.16)}

  /* The private room keeps its overlay controls on the video half. */
  .private-room .pr-controls{bottom:12px}
  .card.post.private-room .post-media .feed-live .pr-local{top:64px}
  .private-room .pr-who{top:64px}
}

/* The owner's own room: preview until they start{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:3;
  padding:14px 28px;border:0;border-radius:999px;cursor:pointer;
  background:var(--flare);color:var(--ink);font:700 var(--fs)/1 var(--font);
}
.card.post.live-room.own-room .post-media .feed-live video{transform:scaleX(-1)}
.card.post.live-room.off-air .live-pill{display:none}

/* Before going live: no LIVE badge, no room, no chat. The lower half
   is the decision to start. */
.card.post.live-room.off-air .live-chat{display:none}
.card.post.live-room .live-setup{display:none}
.card.post.live-room.off-air .live-setup{
  grid-row:4;grid-column:1 / -1;
  display:flex;gap:12px;justify-content:center;align-items:center;
  padding:18px;
}
.card.post.live-room .live-setup[hidden]{display:none}

@media (max-width:900px){
  .card.post.live-room.off-air .live-setup{grid-row:2;align-items:start;padding-top:28px}
}

/* Wide screens: the room fills the window, header included. Video on
   the left edge to edge, chat in its column. */
@media (min-width:901px){
  html:has(.live-room) .site-head,
  html:has(.private-room) .site-head{display:none}

  .card.post.live-room{
    position:fixed;inset:0;z-index:900;
    height:100dvh;margin:0;padding:0;
    grid-template-rows:0 0 minmax(0,1fr) 0 0;
    grid-template-columns:minmax(0,1fr) var(--live-chat-w);
  }
  .card.post.live-room .post-media{
    grid-row:1 / -1;grid-column:1;display:block;margin:0;padding:0;min-height:0;
  }
  .card.post.live-room .post-media .feed-live{
    position:absolute;inset:0;
    width:100%;height:100%;max-width:none;max-height:none;border:0;border-radius:0;
  }
  .card.post.live-room .post-media .feed-live video{
    position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  }

  .card.post.live-room .live-chat,
  .card.post.live-room.off-air .live-setup{
    grid-row:1 / -1;grid-column:2;margin:0;padding:16px;
  }
  .card.post.live-room.off-air .live-setup{
    flex-direction:column;justify-content:center;align-items:stretch;
  }
}

/* The owner's preview element, built at runtime. */
.card.post.live-room .feed-live .pr-preview{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;display:block;background:#000;
}

/* Full bleed for live video: the stream fills the card whatever shape it
   is, cropped rather than letterboxed. Photos and reels stay 1:1. */
.card.post .post-media .feed-live{
  width:100%;
  height:100%;
  max-width:none;
  max-height:none;
  aspect-ratio:auto;
  border:0;
  /* Square against the header, rounded where it meets the panel. */
  border-radius:0 0 var(--post-media-radius) var(--post-media-radius);
}

/* Chats and requests share the column: tabs, not a stack. */
.msg-tabs{
  display:flex;gap:4px;
  padding:10px 14px 0;
}
.msg-tab{
  flex:1;
  display:flex;align-items:center;justify-content:center;gap:6px;
  padding:9px 10px;
  border:0;border-radius:var(--r-pill);
  background:transparent;color:var(--sand-dim);
  font:inherit;font-size:var(--fs-sm);font-weight:600;
  cursor:pointer;
}
.msg-tab.on{
  background:rgba(var(--cream-rgb),.08);
  color:var(--cream);
}
.msg-tab .req-n{
  min-width:18px;padding:0 5px;
  border-radius:var(--r-pill);
  background:var(--flare);color:#fff;
  font-size:var(--fs-xs);line-height:18px;
}

/* The post a conversation belongs to. The avatar circle clips its own
   overflow, so the badge sits on the row rather than inside it. */
.thread{position:relative}
.thread-post{
  position:absolute;
  left:44px;top:50%;margin-top:6px;
  width:20px;height:20px;
  display:grid;place-items:center;
  overflow:hidden;border-radius:6px;
  background:var(--ink-2);color:var(--sand-dim);
  box-shadow:0 0 0 2px var(--ink);
  z-index:1;
}
.thread-post img{width:100%;height:100%;object-fit:cover}
.thread-post svg{width:12px;height:12px}

/* The post the conversation is about, under the header. */
.th-post{
  position:relative;display:block;
  height:96px;
  margin:0 auto 10px;
  box-sizing:border-box;
  border-radius:16px;overflow:hidden;
  background:var(--ink-2);color:var(--cream);text-decoration:none;
}
.th-post img{
  width:100%;height:100%;object-fit:cover;display:block;
}
.th-post-cap{
  position:absolute;left:0;right:0;bottom:0;
  padding:22px 14px 10px;
  background:linear-gradient(transparent,rgba(0,0,0,.75));
  font-size:var(--fs-sm);font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

/* The post's picture in full, whatever shape it was shot in. */
.th-post-wash{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;
  filter:blur(28px) saturate(1.3);
  transform:scale(1.2);
  opacity:.55;
}
.th-post-pic{
  position:relative;
  display:block;
  width:auto;max-width:100%;
  height:100%;
  margin:0 auto;
  object-fit:contain;
}

/* The post a conversation is about: one card, one size, whatever the
   media's shape. */
.th-post{
  display:flex;align-items:center;gap:14px;
  height:auto;padding:10px;
  border:1px solid rgba(var(--cream-rgb),.08);
  border-radius:16px;
  background:rgba(var(--cream-rgb),.04);
}
.th-post-shot{
  position:relative;flex:0 0 auto;
  width:72px;height:90px;
  display:grid;place-items:center;
  overflow:hidden;border-radius:10px;
  background:var(--ink-2);color:var(--sand-dim);
}
.th-post-text{
  min-width:0;display:grid;gap:3px;
}
.th-post-kicker{
  font-size:var(--fs-xs);letter-spacing:.04em;text-transform:uppercase;
  color:var(--sand-dim);
}
.th-post-cap{
  position:static;padding:0;background:none;
  font-size:var(--fs);font-weight:600;color:var(--cream);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.th-post-meta{font-size:var(--fs-xs);color:var(--sand-dim)}

/* Whole picture in the panel: outranks the old band's cover rule. */
.th-post .th-post-pic{
  position:relative;
  width:100%;height:100%;
  object-fit:contain;
}
.th-post .th-post-wash{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;
}

/* The thread header: no rule under it, and when it carries the post
   it grows to fit and runs the column's full width. */
.msg-workspace-chat .msg-thread-head{border-bottom:0}

.msg-workspace-chat .msg-thread-head:has(.th-post-head){
  height:auto;
  flex:0 0 auto;
  min-height:71px;
  padding-block:10px;
}

.msg-workspace-chat .msg-thread-head .th-post-head{
  flex:1;min-width:0;
  width:auto;max-width:none;
  margin:0;padding:0;
  border:0;border-radius:0;background:none;
}

.msg-workspace-chat .msg-thread-head .th-post-shot{
  width:48px;height:60px;border-radius:8px;
}

.th-post-head .th-post-meta{text-decoration:none}
.th-post-head .th-post-meta:hover{color:var(--cream)}

/* Public vibe pages. */
.vibes{width:min(760px,100% - var(--pad) * 2);margin:0 auto;padding:24px 0 64px}
.vibes-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:48px}
.vibes-title{font-size:var(--fs-title);font-weight:700;letter-spacing:-.02em;margin:0 0 10px}
.vibes-lead{font-size:var(--fs-lg);color:var(--sand-dim);margin:0 0 32px;max-width:560px}
.vibes-back{display:inline-block;margin-bottom:14px;color:var(--sand-dim);text-decoration:none;font-size:var(--fs-sm)}
.vibes-back:hover{color:var(--cream)}
.vibes-grid{list-style:none;padding:0;margin:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}
.vibes-card{
  display:grid;gap:6px;padding:20px;
  border:1px solid rgba(var(--cream-rgb),.08);border-radius:18px;
  background:rgba(var(--cream-rgb),.04);
  color:var(--cream);text-decoration:none;
}
.vibes-card:hover{background:rgba(var(--cream-rgb),.08)}
.vibes-card strong{font-size:var(--fs-lg)}
.vibes-card span{font-size:var(--fs-sm);color:var(--sand-dim)}
.vibe-lines{list-style:none;padding:0;margin:0 0 32px;display:grid;gap:10px}
.vibe-lines li{
  justify-self:start;max-width:90%;
  padding:12px 16px;border-radius:18px 18px 18px 6px;
  border:1px solid rgba(var(--cream-rgb),.10);background:rgba(var(--cream-rgb),.06);
  font-size:var(--fs-line);font-weight:600;line-height:1.25;
}
.vibes-cta{margin-bottom:40px}
.vibes-more{display:flex;flex-wrap:wrap;gap:8px}
.vibes-more a{
  padding:8px 14px;border-radius:var(--r-pill);
  background:rgba(var(--cream-rgb),.06);color:var(--sand-dim);
  text-decoration:none;font-size:var(--fs-sm);
}
.vibes-more a:hover{color:var(--cream)}

/* Vibe list in the feed's left column. */
.vibe-rail{display:grid;gap:2px;margin:0 0 12px;min-height:0;overflow-y:auto}
.vibe-rail-item{
  padding:6px 12px 6px 6px;border-radius:10px;
  color:var(--sand-dim);text-decoration:none;font-weight:600;
}
.vibe-rail-item:hover{background:rgba(var(--cream-rgb),.05);color:var(--cream)}
.vibe-rail-item.on{background:rgba(var(--flare-rgb),.14);color:var(--flare)}
.vibe-rail-more{
  width:100%;padding:10px 12px;
  border:1px solid rgba(var(--cream-rgb),.10);border-radius:var(--r-pill);
  background:none;color:var(--cream);font:inherit;font-weight:600;cursor:pointer;
}
.vibe-rail-more:hover{background:rgba(var(--cream-rgb),.05)}
.vibe-col{display:flex;flex-direction:column}
/* The vibe rail beside the feed, wherever the phone row is not used. */
@media (min-width:901px){
  .vibe-col{position:sticky;top:71px;height:calc(100vh - 76px)}
  .frame:has(>.vibe-col+main){grid-template-columns:var(--c-right) minmax(0,1fr)}
}
.vibe-rail-ico{
  display:grid;place-items:center;flex:none;width:34px;height:34px;border-radius:50%;
  background:color-mix(in srgb, var(--vibe, var(--cream)) 16%, transparent);
  font-size:18px;line-height:1;
}
/* Phones: the list becomes a strip of circles down the left edge, on
   the same axis, size (52px, as .mnav-link) and spacing as the bottom
   bar. The bar runs from the strip's axis to the picture's edge. */
@media (max-width:900px){
  /* A row of vibes under the header, scrolling sideways; the feed starts below it. */
  html:has(.vibe-col){--strip-h:92px}
  body .vibe-col{
    display:flex;position:fixed;z-index:25;left:0;right:0;top:var(--head-h,71px);
    height:var(--strip-h);background:var(--ink);
  }
  .vibe-rail{
    display:flex;gap:6px;margin:0 var(--pad);padding:6px 0;
    overflow-x:auto;overflow-y:hidden;scrollbar-width:none;overscroll-behavior:contain;touch-action:pan-x;
    scroll-snap-type:x mandatory;
  }
  .vibe-rail-item{flex:none;flex-direction:column;gap:4px;width:60px;padding:0 0 4px;scroll-snap-align:start}
  .vibe-rail-ico{width:48px;height:48px;font-size:22px}
  .vibe-rail-name{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:1.2}
  .vibe-rail-more{display:none}
}

/* Left rail, tidied to match the vibe rail on the right: same rows,
   same pill for "you are here", same quiet secondary button. The pill
   and the buttons share the outer edge; icons and text share the
   logo's edge. */
.rail{gap:2px}
.rail .rail-me-who em{color:var(--sand-dim)}

.rail .rail-link{
  padding:10px 14px;gap:12px;
  border-radius:10px;
  font-size:var(--fs);font-weight:600;
  color:var(--sand-dim);
}
.rail .rail-link:hover{background:rgba(var(--cream-rgb),.05);color:var(--cream)}
.rail .rail-link.on{background:rgba(var(--flare-rgb),.14);color:var(--flare)}
.rail .rail-link.on::before{content:none}

/* Vibe colours. Each element that shows a vibe sets --vibe; the rest
   is tints of it. */
.vibe-rail-item{display:flex;align-items:center;gap:10px}
.vibe-rail-item[style].on{
  background:color-mix(in srgb, var(--vibe) 16%, transparent);
  color:var(--vibe);
}

.vibes-card{border-left:3px solid var(--vibe, transparent)}
.vibes-card:hover{background:color-mix(in srgb, var(--vibe, var(--cream)) 10%, transparent)}

.vibes-one .vibes-title{color:var(--vibe)}
.vibes-one .vibe-lines li{
  border-color:color-mix(in srgb, var(--vibe) 35%, transparent);
  background:color-mix(in srgb, var(--vibe) 10%, transparent);
}
.vibes-one .vibes-cta{background:var(--vibe);color:var(--ink);border-color:var(--vibe)}
.vibes-more a[style]:hover{color:var(--vibe)}

/* ---- Light theme: what sits on a photo stays as it was ---- */
.card.post > .post-identity,
.lb-who,
.card.post .post-media,
.th-post-shot{
  --cream:#F5F2F4;
  --cream-rgb:245,242,244;
  --sand:#E9E4EC;
  --sand-dim:rgba(245,242,244,.8);
  --line:rgba(245,242,244,.35);
}

.card.post .js-follow:hover{border-color:var(--line);color:var(--sand)}

/* Vibe colours on light: the tint carries the colour, the text stays dark. */
.vibe-rail-item[style].on{color:var(--cream)}
.vibes-one .vibes-title{color:var(--cream)}
.vibes-one .vibes-cta{color:var(--cream)}

/* The mark: one line, in Pacifico. A script face has one weight, so
   no bold — faux-bold on a script smears it. */
.mark,
.mark.mark-stack{
  display:inline-flex;flex-direction:row;align-items:baseline;gap:0;
  font-family:'League Gothic',sans-serif;
  font-weight:400;
  font-size:36px;
  line-height:1;
  letter-spacing:0;
  white-space:nowrap;
}
.mark span,
.mark .mark-line{display:inline;font:inherit}
/* Phones: one step down from PC. At 28px the letters span 21-56px of
   the 71px header and the word is 134px wide, clear of the buttons. */
@media (max-width:900px){
  .mark,
  .mark.mark-stack{font-size:28px}
}

/* The post's line and vibe, on the picture. */
.post-line{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  display:grid;gap:8px;justify-items:start;
  padding:56px 64px 18px 20px;
  background:linear-gradient(transparent,rgba(0,0,0,.6));
  border-radius:0 0 var(--post-media-radius,24px) var(--post-media-radius,24px);
  pointer-events:none;
}
.post-line-text{
  margin:0;color:#fff;
  font-size:var(--fs-line);font-weight:600;line-height:1.2;
  text-wrap:balance;text-shadow:0 1px 8px rgba(0,0,0,.4);
}

/* A post with no picture: the line fills the space, in its vibe. */
.card.post .post-media-text{
  display:grid;align-items:end;
  background:color-mix(in srgb, var(--vibe) 72%, #2B2233);
  /* Square against the header on mobile, rounded on desktop below. */
  border-radius:0 0 var(--post-media-radius,24px) var(--post-media-radius,24px);
}
.post-media-text .post-line{
  position:static;background:none;padding:28px;
}
.post-media-text .post-line-text{font-size:var(--fs-title);text-shadow:none}

/* Desktop: the card sits in a column on a light page, so its top
   corners round to match the bottom. */
@media (min-width:901px){
  .card.post{border-radius:var(--post-media-radius)}
  .card.post .post-media .post-photo-attachment,
  .card.post .post-media .feed-reel,
  .card.post .post-media .feed-live,
  .card.post .post-media-text{
    border-radius:var(--post-media-radius);
  }
}

/* The conversation is part of the card, not a box inside it. */
.card.post .post-foot-stack{
  margin:0;
  /* Sides from --pad, the inset the name and the rail use, so the
     chat lines up with them at every width. */
  padding:0 var(--pad) 16px;
  border:0;
  border-radius:0;
  background:none;
  box-shadow:none;
}

/* Admin: one form per vibe. */
.adm-vibes{display:grid;gap:10px;margin-top:14px}
.adm-vibe{
  display:grid;grid-template-columns:44px 1fr 80px;gap:8px;align-items:center;
  padding:12px;border:1px solid var(--line);border-radius:10px;
}
.adm-vibe input[name=meta_title],
.adm-vibe input[name=meta_desc],
.adm-vibe-foot{grid-column:1 / -1}
.adm-vibe input[type=color]{width:44px;height:36px;padding:0;border:0;background:none}
.adm-vibe-foot{display:flex;align-items:center;gap:12px}

/* Violet is for actions only; "you are here" is neutral. */
.rail .rail-link.on,
.vibe-rail-item.on:not([style]){
  background:rgba(var(--cream-rgb),.06);
  color:var(--cream);
}
.card.post .post-quick-msg.mine .post-quick-bubble,
.lb-chat .post-quick-msg.mine .post-quick-bubble,
.room-chat .post-quick-msg.mine .post-quick-bubble,
.th-log .post-quick-msg.mine .post-quick-bubble{
  background:rgba(var(--cream-rgb),.08);
  border-color:rgba(var(--cream-rgb),.12);
}

/* Write your own: a real field under the list. */
.cs-own{display:grid;gap:8px;margin:18px 0 4px}
.cs-own span{font-size:var(--fs-sm);color:var(--sand-dim)}
.cs-own input{
  width:100%;padding:14px 16px;
  border:1px solid rgba(var(--cream-rgb),.18);border-radius:14px;
  background:var(--ink-2);color:var(--cream);font:inherit;font-size:var(--fs);
}
.cs-own input:focus{outline:none;border-color:var(--flare)}

/* Admin: blocked words as removable chips. */
.adm-terms{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:8px}
.adm-terms li{
  display:flex;align-items:center;gap:6px;
  padding:6px 6px 6px 12px;border:1px solid var(--line);border-radius:var(--r-pill);
}
.adm-terms form{display:contents}
.adm-terms button{
  width:22px;height:22px;border:0;border-radius:50%;
  background:rgba(var(--cream-rgb),.08);color:var(--sand-dim);cursor:pointer;
}
.adm-terms button:hover{color:var(--cream)}
.adm-new{margin-left:6px;padding:2px 8px;border-radius:var(--r-pill);background:var(--flare);color:#fff;font-size:var(--fs-xs);font-weight:700}

/* Composer, one screen: vibe chips, the open vibe's lines, your own. */
.cs-vibes{display:flex;flex-wrap:wrap;gap:8px;margin:4px 0 14px}
.cs-vibe{
  display:inline-flex;align-items:center;gap:8px;
  padding:8px 14px;border:1px solid var(--line);border-radius:var(--r-pill);
  background:none;color:var(--cream);font:inherit;font-size:var(--fs-sm);font-weight:600;cursor:pointer;
}
.cs-vibe::before{content:'';width:8px;height:8px;border-radius:50%;background:var(--vibe)}
.cs-vibe.on{border-color:var(--vibe);background:color-mix(in srgb, var(--vibe) 18%, transparent)}
.cs-cat{list-style:none;padding:0;margin:0 0 6px;display:grid;gap:6px;max-height:280px;overflow-y:auto}
.cs-cat[hidden]{display:none}
.cs-pick{
  width:100%;text-align:left;padding:12px 14px;
  border:1px solid transparent;border-radius:12px;
  background:rgba(var(--cream-rgb),.04);color:var(--cream);
  font:inherit;font-size:var(--fs);cursor:pointer;
}
.cs-pick:hover{background:rgba(var(--cream-rgb),.07)}
.cs-pick.on{border-color:var(--flare);background:rgba(var(--flare-rgb),.10)}
.cs-own[hidden]{display:none}
.adm-new{margin-left:6px;padding:2px 8px;border-radius:var(--r-pill);background:var(--flare);color:#fff;font-size:var(--fs-xs);font-weight:700}

/* The search-or-write field sits above the lines it filters. */
.cs-own{margin:0 0 10px}
.cs-hint{margin:-4px 0 10px;font-size:var(--fs-sm);color:var(--sand-dim)}
.cs-hint[hidden]{display:none}

/* "Use line" inside the field; once used, the field shows it's set. */
.cs-own-box{position:relative;display:block}
.cs-own-box input{padding-right:112px}
.cs-own-use{
  position:absolute;right:6px;top:50%;transform:translateY(-50%);
  padding:9px 14px;border:0;border-radius:var(--r-pill);
  background:var(--flare);color:#fff;font:700 var(--fs-sm)/1 var(--font);cursor:pointer;
}
.cs-own-use[hidden]{display:none}
.cs-own.is-set input{border-color:var(--flare);background:rgba(var(--flare-rgb),.08)}

/* Vibe as a dropdown: the chosen vibe's dot on the left, a chevron right. */
.cs-vibe-pick{position:relative;display:block;margin:4px 0 12px}
.cs-vibe-pick::before{
  content:'';position:absolute;left:16px;top:50%;margin-top:-5px;
  width:10px;height:10px;border-radius:50%;background:var(--vibe);pointer-events:none;
}
.cs-vibe-pick::after{
  content:'';position:absolute;right:18px;top:50%;margin-top:-6px;
  width:8px;height:8px;border-right:2px solid var(--sand-dim);border-bottom:2px solid var(--sand-dim);
  transform:rotate(45deg);pointer-events:none;
}
.cs-vibe-pick select{
  width:100%;-webkit-appearance:none;appearance:none;
  padding:14px 44px 14px 36px;border:1px solid var(--line);border-radius:14px;
  background:var(--ink-2);color:var(--cream);font:inherit;font-size:var(--fs);font-weight:600;cursor:pointer;
}

/* Clear (×) inside a field. Moves left when "Use line" is showing. */
.field-clear{
  position:absolute;right:10px;top:50%;transform:translateY(-50%);
  width:26px;height:26px;display:grid;place-items:center;
  border:0;border-radius:50%;background:rgba(var(--cream-rgb),.10);
  color:var(--sand-dim);font-size:var(--fs);line-height:1;cursor:pointer;
}
.field-clear:hover{color:var(--cream)}
.field-clear[hidden]{display:none}
.cs-own-use:not([hidden]) + .field-clear{right:112px}
.cs-own-box input{padding-right:150px}

/* One size for the main text: menus, tabs, lists, fields, main buttons.
   Change --fs and they all move together. Small print stays smaller. */
.rail .rail-link,
.vibe-rail-item,
.vibe-rail-more,
.msg-tab,
.cs-pick,
.cs-own input,
.cs-vibe-pick select{font-size:var(--fs)}

/* Left rail: as tall as the screen, with the footer pushed to the bottom.
   On a short screen there is no spare room, so it just follows the menu. */
@media (min-width:901px){.rail{display:flex;flex-direction:column;height:calc(100vh - 76px)}}

/* Message notice: slides down from the top, tap to open the chat. */
.notice{
  position:fixed;left:50%;top:calc(env(safe-area-inset-top, 0px) + 12px);z-index:90;
  display:flex;align-items:center;gap:12px;
  width:min(420px, calc(100% - 24px));padding:10px 12px;
  border:1px solid var(--line);border-radius:16px;
  background:var(--ink);color:var(--cream);text-decoration:none;
  box-shadow:0 12px 32px rgba(0,0,0,.16);
  transform:translate(-50%, -140%);opacity:0;pointer-events:none;
  transition:transform .3s ease, opacity .3s ease;
}
.notice.on{transform:translate(-50%, 0);opacity:1;pointer-events:auto}
.notice-av{width:40px;height:40px;flex:none;border-radius:50%;overflow:hidden;background:var(--wine)}
.notice-thumb{width:40px;height:40px;flex:none;border-radius:8px;overflow:hidden}
.notice-av img,.notice-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.notice-text{flex:1;min-width:0;display:grid;gap:2px}
.notice-text strong{font-size:var(--fs-sm)}
.notice-text span{font-size:var(--fs-sm);color:var(--sand-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Phones, like desktop: the feed starts below the fixed header and each card fills what is left. */
@media (max-width:900px){
  body:has(#stream) .stream{margin-top:calc(var(--head-h,71px) + var(--strip-h,0px))}
}

/* ---- lightbox with the post's chat ---- */
.lb-stage{position:relative;width:100%;height:100%;min-height:0;display:grid;place-items:center;overflow:hidden;touch-action:none}
.lb.has-chat{grid-template-columns:min(100dvh, 100vw - 320px) minmax(320px,1fr);grid-template-rows:minmax(0,1fr);place-items:stretch}
.lb.has-chat .lb-track > img{width:100%;height:100%;max-width:none;max-height:none;object-fit:cover}
.lb.has-chat .lb-chat{display:flex;flex-direction:column;min-height:0;overflow-y:auto;scrollbar-width:none;background:var(--ink-2);border-left:1px solid var(--line)}
.lb-chat .post-foot-stack{flex:1;display:flex;flex-direction:column;gap:12px;min-height:0;padding:16px;width:100%;max-width:560px;margin-inline:auto}
.lb-chat .post-quick-chat{flex:1;min-height:0;overflow-y:auto;scrollbar-width:none;gap:12px;align-content:start}
.lb-chat .post-quick-chat::-webkit-scrollbar{display:none}
@media (max-width:600px){
  .lb.has-chat{grid-template-columns:1fr;grid-template-rows:100vw minmax(0,1fr)}
}
.lb-chat::-webkit-scrollbar{display:none}
.lb-chat .post-flirt-form{position:sticky;bottom:0;margin-top:auto;background:var(--ink-2)}
.lb-up{right:18px;bottom:76px;rotate:90deg}
.lb-down{right:18px;bottom:18px;rotate:90deg}
@media (max-width:600px){
  .lb-up,.lb-down{display:none}
}
.lb video{max-width:94vw;max-height:86vh}
.lb.has-chat video{position:absolute;inset:0;width:100%;height:100%;max-width:none;max-height:none;object-fit:cover;background:#000}
.lb-text{width:100%;height:100%;background:var(--vibe)}
.card.post:not(.live-room):not(.private-room){cursor:pointer}
.lb-who{--post-avatar-h:52px;position:absolute;top:18px;left:18px;z-index:1}
.lb-who .post-identity{display:flex;align-items:center;gap:10px}

/* ---- composer: 4:5 crop ---- */
.thumb img{cursor:pointer}
.crop{z-index:90;background:rgba(var(--ink-rgb),.96);display:grid;place-content:center;justify-items:center;gap:16px}
.crop-frame{position:relative;width:min(90vw,420px,calc(100dvh - 160px));aspect-ratio:1;overflow:hidden;border-radius:18px;background:#000;touch-action:none;cursor:grab}
.crop-frame img{position:absolute;top:0;left:0;max-width:none;transform-origin:0 0;user-select:none}
.crop-zoom{width:min(90vw,420px,calc(100dvh - 160px))}
.crop-acts{display:flex;gap:12px}
.crop[hidden]{display:none}

/* Phones: one card per screen, so the picture takes its whole slot and
   the stored square is trimmed to it, whatever the screen's shape. */
@media (max-width:900px){
  .card.post .post-media .feed-live,
  .card.post .post-media .gal:not(.gal-1){width:100%;height:100%;max-width:none;max-height:none;aspect-ratio:auto}
}

/* The part of the lightbox that moves on a drag, and the neighbour
   waiting just past its edge. */
.lb-track{position:absolute;inset:0;display:grid;place-items:center}
.lb-peek{position:absolute;left:0;width:100%;height:100%;background:#000 center/cover no-repeat}

/* ---- chat photo attachment ---- */
.chat-photo-btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  flex:0 0 auto;
  width:34px;
  height:34px;
  border-radius:50%;
  cursor:pointer;
  color:inherit;
  opacity:.78;
}
.chat-photo-btn:hover{opacity:1}
.chat-photo-btn.is-selected{
  background:rgba(var(--cream-rgb),.14);
  opacity:1;
}
.chat-photo-btn.is-disabled{
  opacity:.35;
  pointer-events:none;
}

/* ---- emoji picker ---- */
.emoji-btn{
  flex:none;width:34px;height:34px;display:grid;place-items:center;
  border:0;border-radius:50%;background:none;color:var(--sand-dim);cursor:pointer;
}
.emoji-btn:hover{color:var(--flare)}
.emoji-pop{
  position:fixed;z-index:95;display:grid;grid-template-columns:repeat(6,40px);gap:4px;
  padding:8px;background:var(--ink);border-radius:16px;box-shadow:0 8px 24px rgba(0,0,0,.18);
}
.emoji-pop[hidden]{display:none}
.emoji-pop button{
  width:40px;height:40px;border:0;border-radius:10px;background:none;
  font-size:22px;line-height:1;cursor:pointer;
}
.emoji-pop button:hover{background:var(--ink-2)}
/* Touch devices have an emoji keyboard; the button is for desktop. */
@media (hover: none) and (pointer: coarse){
  .emoji-btn{display:none}
}
/* Outside the feed (lightbox): media fills its frame. */
.card.post .post-media .post-photo-attachment,
.card.post .post-media .feed-reel{width:100%;height:100%;max-width:none;max-height:none;aspect-ratio:auto;border:0;border-radius:0 0 var(--post-media-radius) var(--post-media-radius)}

/* Card: avatar lives on the rail; name and Follow only in the lightbox copy. */
.card.post > .post-identity .post-avatar,
.card.post > .post-identity .post-name > a,
.card.post > .post-identity .js-follow{display:none}

/* Phones, feed. --feed-pic is the picture's width: inset by --pad, capped by
   the height left after header, bar and the 180px chat (= --post-chat-h).
   Header and chat align to its edges; the rail sits --pad inside it.
   Height grows past square up to 4:5. */

/* Her vibe as a status emoji on her avatar; tap to browse that vibe. */
.post-vibe{position:absolute;left:32px;bottom:2px;z-index:1;width:24px;height:24px;display:grid;place-items:center;border-radius:50%;background:color-mix(in srgb, var(--vibe) 35%, var(--ink-2));box-shadow:0 0 0 2px var(--ink-2);font-size:var(--fs-xs);line-height:1;text-decoration:none}
.post-opener .post-quick-msg{position:relative}

/* Message photos inside quick/private chat bubbles. */
.post-quick-bubble .post-quick-image{
  display:block;
  width:min(100%, 320px);
  max-height:360px;
  object-fit:cover;
  border-radius:14px;
}
.post-quick-bubble .post-quick-image + p{
  margin-top:8px;
}

/* Admin bot photo library */
.adm-bot-photo-gallery{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  grid-auto-rows:max-content;
  gap:12px;
  max-height:420px;
  overflow-y:auto;
  padding:2px;
}

.adm-bot-photo-gallery:empty{
  display:none;
}

.adm-bot-photo-item{
  min-width:0;
  overflow:hidden;
  border:1px solid var(--line);
  border-radius:12px;
  background:var(--ink);
}

.adm-bot-photo-item img,
.adm-bot-photo-item video{
  display:block;
  width:100%;
  aspect-ratio:1 / 1;
  object-fit:cover;
}

.adm-bot-photo-meta{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:8px;
  padding:8px;
  font-size:var(--fs-sm);
}

.adm-bot-photo-meta span{
  min-width:0;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}

.adm-bot-photo-meta .adm-btn{
  flex:0 0 auto;
}

.adm-bot-photo-actions{
  display:flex;
  gap:6px;
  flex:0 0 auto;
}

.adm-lightbox{margin:auto;max-width:94vw;max-height:94vh;padding:0;border:0;background:transparent}
.adm-lightbox::backdrop{background:rgba(var(--ink-rgb),.92)}
.adm-lightbox img{display:block;max-width:94vw;max-height:94vh;object-fit:contain}

@media (max-width:520px){
  .adm-bot-photo-gallery{
    grid-template-columns:1fr;
    max-height:360px;
  }
}

/* ============ post card ============ */
/* Its own root, so the older .card.post rules (still used by live
   cards and live rooms) never reach it. */
.vcard{display:grid;gap:12px;margin-bottom:16px;padding:14px;background:var(--ink-2);border:1px solid var(--line);border-radius:18px}
.vcard-head{display:flex;align-items:center;gap:12px}
.vcard .post-identity{display:flex;align-items:center;gap:12px;flex:1;min-width:0}
.vcard .post-avatar{width:48px;height:48px}
.vcard .menu-pop .on{color:var(--flare)}
.vcard-line{margin:0;font-weight:600}
.vcard .post-media{margin:0;aspect-ratio:1}
.vcard .feed-reel{position:relative;height:100%}
.vcard .post-media-text{background:color-mix(in srgb, var(--vibe) 35%, var(--ink-2))}
.vcard-cta{
  display:flex;align-items:center;justify-content:center;gap:8px;min-height:48px;
  border:0;border-radius:var(--r-pill);background:var(--flare);color:#fff;
  font:inherit;font-weight:600;text-decoration:none;cursor:pointer;
}

/* Feed on a wide screen: a grid of cards. The line always takes two
   lines, so pictures and buttons sit level across a row. */
@media (min-width:901px){
  #stream{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:16px;align-items:start}
  #stream > :not(.vcard){grid-column:1 / -1}
  #stream .vcard{margin-bottom:0}
  #stream .vcard-line{
    display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;
    line-height:1.3;min-height:2.6em;
  }
}

/* Main nav lives in the header on a wide screen; phones have the bar. */
.head-nav{display:flex;gap:6px}
.head-nav .btn-round{position:relative}
.head-nav .btn-round.on{color:var(--flare)}
.head-create{display:inline-flex;align-items:center;gap:6px;margin-inline:6px}
@media (max-width:900px){.head-nav,.head-create{display:none}}

/* The links that used to sit under the rail. */
.acct-foot{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:4px;padding:10px 11px 4px;border-top:1px solid var(--line);font-size:var(--fs-xs);color:var(--sand-dim)}
.acct-foot a{display:inline;width:auto;padding:0;color:inherit}

/* One centred column unless a page brings a side column. */
.frame > .col:only-child{justify-self:center}
@media (min-width:901px){
  .frame:has(>.pf-aside){grid-template-columns:var(--c-left) minmax(0,1fr)}
}
.frame:has(>.vibe-col) .col{max-width:none}

/* A restored or stepped-to card lands below the sticky header. */
html:has(#stream){scroll-padding-top:calc(var(--head-h,71px) + var(--strip-h,0px))}

/* Who has joined the conversation: overlapping avatars and a count. */
.vcard-joined{display:flex;align-items:center;gap:10px;font-size:var(--fs-sm);color:var(--sand-dim)}
.vcard-joined-avs{display:flex}
.vcard-joined .post-avatar{width:28px;height:28px;box-shadow:0 0 0 2px var(--ink-2)}
.vcard-joined .post-avatar + .post-avatar{margin-left:-8px}

/* ============ post room ============ */
/* One screen: the post on top, the chat below; only the chat scrolls. */
/* A room is one screen: the page never scrolls, only the chat does. */
body:has(.room){overflow:hidden}
.room-head{display:flex;align-items:center;gap:12px}
.room-who{flex:1;min-width:0}
.room-title{margin:0;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.room-meta{margin:0;font-size:var(--fs-sm);color:var(--sand-dim)}
.room-chat{display:grid;grid-template-rows:minmax(0,1fr);grid-auto-rows:auto;gap:12px;min-height:0}
.room-list{display:grid;align-content:start;gap:10px;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:none}
.room-list::-webkit-scrollbar{display:none}
/* Shared composer styles set display; hidden still means hidden here. */
.room-chat > [hidden]{display:none}

/* Bare pages on phones: a page passes bareMobile to render() and brings
   its own top bar. The site header goes, and --head-h drops to 0 so
   anything sized against the header takes the space back. */
@media (max-width:900px){
  body.bare-mobile{--head-h:0px}
  body.bare-mobile .site-head{display:none}
}

/* A line from the room itself: someone went offline, a join refused. */
.room-note{margin:8px 0;text-align:center;color:var(--sand-dim);font-size:var(--fs-sm)}

/* Vibing now: whoever is behind this card is around right now. */
.vibing{display:inline-flex;align-items:center;gap:5px;color:#1F9D55;font-weight:600}
.vibing::before{content:"";width:7px;height:7px;border-radius:50%;background:#3FD07A}

/* The host: the person the room is about. */
.room-chat .post-quick-msg.is-host .post-quick-bubble{
  background:color-mix(in srgb, var(--flare) 12%, transparent);
  border-color:color-mix(in srgb, var(--flare) 30%, transparent);
}
.host-tag{margin-left:6px;padding:1px 7px;border-radius:var(--r-pill);background:var(--flare);color:#fff;font-size:var(--fs-xs);font-weight:600}

/* Who is in the room: overlapping faces beside the count. */
.room-meta{display:flex;align-items:center;gap:8px}
.room-faces{display:inline-flex}
.room-faces .post-avatar{width:22px;height:22px;box-shadow:0 0 0 2px var(--ink)}
.room-faces .post-avatar + .post-avatar{margin-left:-6px}

/* Bare pages on every screen: the host's own room while online. */
body.bare{--head-h:0px}
body.bare .site-head{display:none}

/* Offline: the card stays, quieter. Purple buttons only ever mean
   someone is here right now. */
.offline{display:inline-flex;align-items:center;gap:5px;color:var(--sand-dim)}
.offline::before{content:"";width:7px;height:7px;border-radius:50%;background:#A39CAD}
.vcard-offline .post-media{opacity:.6;filter:grayscale(.4)}
.vcard-cta-quiet{background:none;color:var(--cream);border:1px solid var(--line)}

/* The main action spelled out: a pill rather than a bare plus. The
   other buttons keep their 52px, so the strip's axis holds. */
.mnav-link.mnav-online{width:auto;padding:0 16px;gap:8px;grid-auto-flow:column;border-radius:var(--r-pill);font:600 14px/1 var(--font);white-space:nowrap;text-decoration:none}
@media (max-width:389px){.mobile-nav{gap:6px}}
@media (max-width:359px){
  .mnav-link.mnav-online{padding:0 12px}
}

/* The photo step: one job, centred. */
.welcome{display:grid;justify-items:center;gap:14px;max-width:420px;margin:0 auto;padding:12vh var(--pad) 40px;text-align:center}
.welcome h1{margin:0;font-size:var(--fs-xl)}
.welcome p{margin:0;color:var(--sand-dim)}
.welcome-form{display:grid;gap:12px;width:100%;margin-top:8px}
.welcome-skip{color:var(--sand-dim);font-size:var(--fs-sm)}

/* Your own portfolio: an upload menu beside the heading, a remove button on each tile. */
.pf-cell-own { position: relative; }
.pf-add{aspect-ratio:1;margin:0 0 4px;border:2px dashed var(--line);background:none}
.pf-add:hover{border-color:var(--flare)}
.pf-add label{display:grid;place-content:center;justify-items:center;gap:6px;height:100%;cursor:pointer;color:var(--sand-dim);font-size:var(--fs-sm)}
.pf-add-plus{font-size:44px;line-height:1;color:var(--flare)}
.pf-cell > a { display: block; }
.pf-cell-x { position: absolute; top: 6px; right: 6px; margin: 0; }
/* Not public yet: only the owner sees these tiles, dimmed and labelled. */
.pf-cell-state {
  position: absolute; left: 6px; bottom: 6px; padding: 2px 7px; border-radius: 999px;
  background: rgba(0, 0, 0, .65); color: #fff; font-size: 11px; font-weight: 600;
}
.pf-cell-own:has(.pf-cell-state) img { opacity: .6; }
.pf-cell-x button {
  width: 24px; height: 24px; border: 0; border-radius: 50%;
  background: rgba(0, 0, 0, .6); color: #fff; font-size: 16px; line-height: 1; cursor: pointer;
}

/* Quick preview: full screen on phones, a panel over the dimmed feed on wider screens. */
.qp{position:fixed;inset:0;z-index:100;overflow-y:auto;overscroll-behavior:contain;background:var(--ink)}
.qp-bar{position:sticky;top:0;z-index:1;display:flex;align-items:center;padding:12px var(--pad);background:var(--ink)}
.qp-back{width:40px;height:40px;border:0;border-radius:50%;background:none;color:var(--cream);display:grid;place-items:center;cursor:pointer}
.qp-body{display:grid;gap:22px;padding:0 var(--pad) 40px}
body:has(.qp:not([hidden])){overflow:hidden}
@media (min-width:761px){
  .qp{padding:40px 20px;background:rgba(0,0,0,.45)}
  .qp-panel{max-width:720px;margin-inline:auto;overflow:hidden;border-radius:var(--r);background:var(--ink)}
}
.vcard{cursor:pointer}
/* Rejected: the whole tile says so, not a pill. */
.pf-cell-state.is-rejected{inset:0;display:grid;place-content:center;gap:6px;padding:16px;border-radius:0;text-align:center;background:rgba(192,57,43,.08);color:#a12d22;font-size:13px}
.pf-cell-state small{font-size:var(--fs-xs);font-weight:400;white-space:normal}
.pf-back{display:grid;color:inherit}

/* Going online: description. */
.cs-extra{display:grid;gap:6px;margin-top:14px;font-size:var(--fs-sm);color:var(--sand)}
.cs-extra em{font-style:normal;color:var(--sand-dim)}
.cs-extra textarea,.cs-extra select{
  width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--ink);color:var(--cream);font:inherit;
}
.vcard-desc{margin-top:6px;font-size:var(--fs-sm);color:var(--sand-dim)}
.cs-show{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;min-width:0;margin:0;padding:0;border:0}
.cs-show[hidden]{display:none}

/* Room stage: the host's camera above the chat. */
.room-stage video,.room-stage .feed-live{position:absolute;inset:0;width:100%;height:100%}
.room-stage video{object-fit:cover}

/* A card whose host is on air: the video over the photo, once it plays. */
.post-media[data-live-feed]{position:relative}
.post-media[data-live-feed] video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .6s ease}
.post-media[data-live-feed].on video{opacity:1}
/* A show is ticketed: its card teases the live picture, it does not give it away. */
.vcard-paid .post-media[data-live-feed] video{filter:blur(8px);transform:scale(1.08)}
/* A show is always on camera: nothing to choose{display:none}

/* Room controls under the video: round buttons, white when off, red to end. */
.room-controls{display:flex;justify-content:center;gap:16px}
.rc-btn{display:grid;place-items:center;width:56px;height:56px;border:0;border-radius:50%;background:var(--ink-2);color:var(--cream);cursor:pointer}
.rc-btn[aria-pressed="false"]{background:var(--cream);color:var(--ink)}
.rc-end{background:#e5484d;color:#fff}
.rc-btn .ico-off,.rc-btn[aria-pressed="false"] .ico-on{display:none}
.rc-btn[aria-pressed="false"] .ico-off{display:grid}
.rc-btn span{display:grid}

/* The camera button's three states: off air, live, paused. */
.js-cam-toggle span{display:none}
.js-cam-toggle[data-state="off"] .ico-start,.js-cam-toggle[data-state="live"] .ico-pause,.js-cam-toggle[data-state="paused"] .ico-play{display:grid}
.js-cam-toggle[data-state="off"],.js-cam-toggle[data-state="paused"]{background:var(--cream);color:var(--ink)}

/* A break: the picture dims and says so, for host and viewers alike. */
.room-stage.is-paused{background:#000 var(--paused-photo) center/cover no-repeat}
.room-stage.is-paused video{opacity:0}
.room-stage.is-paused::after{content:"Paused \00b7 back soon";position:absolute;inset:0;display:grid;place-items:center;background:rgba(0,0,0,.35);color:#fff;font-weight:600}

/* A paused host: the card shows their photo and says so. */
.post-media[data-live-feed].is-paused video{opacity:0}
/* Off air, the host's stage shows their photo until the camera is on. */
.own-stage.off-air{background:#000 var(--paused-photo) center/cover no-repeat}
.room-timer{
  position:absolute;right:12px;top:12px;z-index:2;padding:4px 10px;border-radius:20px;
  background:rgba(0,0,0,.55);color:#fff;font:600 13px/1.4 var(--font);font-variant-numeric:tabular-nums;
}
.room-timer.is-over{background:#e5484d}
.post-media.is-paused.has-frame{background:#000 var(--paused-frame) center/cover no-repeat}
.post-media.is-paused.has-frame img{opacity:0}
/* The status dot: green vibing, red live or a show on, grey paused. */
.vibing.is-live{color:#d6383e}
.vibing.is-live::before{background:#e5484d}
.vibing.is-paused{color:var(--sand-dim)}
.vibing.is-paused::before{background:#A39CAD}

/* A show: the video is the room. Title, chat and controls float over it. */
.room.is-show{position:fixed;inset:0;display:block;max-width:none;padding:0;background:#000}
.room.is-show .room-stage{position:absolute;inset:0;overflow:hidden;background:#000}
.room.is-show .room-head{
  position:absolute;top:0;left:0;right:0;z-index:3;
  padding:calc(12px + env(safe-area-inset-top)) var(--pad) 24px;
  color:#fff;background:linear-gradient(rgba(0,0,0,.55),transparent);
}
.room.is-show .room-meta{color:rgba(255,255,255,.8)}
.room.is-show .room-timer{top:calc(14px + env(safe-area-inset-top));right:auto;left:50%;translate:-50% 0;z-index:4}
.room.is-show .room-chat{
  position:absolute;left:0;bottom:0;z-index:3;width:min(440px,100%);max-height:45%;
  padding:32px var(--pad) calc(14px + env(safe-area-inset-bottom));
  background:linear-gradient(transparent,rgba(0,0,0,.6));
}
.room.is-show .room-list{-webkit-mask-image:linear-gradient(transparent,#000 35%);mask-image:linear-gradient(transparent,#000 35%)}
.room.is-show .post-quick-bubble{background:rgba(0,0,0,.4);border-color:transparent;color:#fff}
.room.is-show.chat-hidden .room-chat{display:none}
.room.is-show .room-controls{
  position:absolute;right:var(--pad);bottom:calc(16px + env(safe-area-inset-bottom));z-index:4;flex-direction:column;
}
/* Phones: the controls stand above the message box, and the messages keep
   a lane clear for them, so nothing covers Send. */
@media (max-width:760px){
  .room.is-show .room-chat{width:100%}
  .room.is-show .room-list{padding-right:76px}
  .room.is-show .room-controls{bottom:calc(84px + env(safe-area-inset-bottom))}
}
.rc-btn{position:relative}
.rc-badge{
  position:absolute;top:-2px;right:-2px;min-width:20px;height:20px;padding:0 5px;border-radius:10px;
  background:#e5484d;color:#fff;font:600 11px/20px var(--font);font-style:normal;text-align:center;
}

/* New show: now or later. */
.cs-when{display:flex;gap:8px}
.cs-when label{flex:1;display:flex;justify-content:center;padding:10px;border:1px solid rgba(127,127,127,.35);border-radius:var(--r);font-weight:600;cursor:pointer}
.cs-when input{position:absolute;opacity:0;pointer-events:none}
.cs-when label:has(input:checked){border-color:var(--flare);color:var(--flare)}
.upcoming{color:var(--flare);font-weight:600}
