/* Trending rail. Fixed to the right of the feed, and only when there is real
   room for it: below this width the feed is the whole point of the screen. */
/* The feed and the rail are one centred row, not a column with something
   pinned to the far right: pinning left a canyon between them on wide
   screens. Sticky rather than fixed, so the rail starts level with the first
   card and stays put on its own. */
.cols{padding-top:70px}
@media (max-width:900px){ .cols{padding-top:64px} }
/* The feed is centred on the window, under the wordmark, and nothing beside it
   is allowed to move it. Between the bottom of the nav breakpoint and the width
   where a 620px column clears the nav, the column narrows instead of shifting. */
.cols main.wrap{margin:0 auto;width:100%;max-width:620px}
@media (min-width:901px) and (max-width:1119px){
  .cols main.wrap{max-width:calc(100vw - 2 * 252px)}
}
#nav-trends{display:none}
@media (max-width:900px){ #nav-trends{display:flex} }
/* Out of the flow entirely, pinned to the right of the centred column, so it
   can never push the feed off the wordmark. It simply stops appearing when
   there is no longer room beside the column. */
.rrail{display:none}
@media (min-width:1240px){
  body.has-rail .rrail{display:block;position:fixed;top:84px;left:calc(50% + 332px);
    width:min(var(--railmax), calc(50vw - 356px));
    max-height:calc(100vh - 104px);overflow-y:auto;scrollbar-width:none;z-index:5}
  .rrail::-webkit-scrollbar{display:none}
}
.tr-card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px 4px 6px}
.tr-card h2{font-size:1.02rem;font-weight:800;margin:0 0 4px;padding:0 12px}
.tr-card .rsub{font-size:.78rem;color:var(--text2);padding:0 12px 8px;margin:0}
/* The rail's own tabs and the panes behind them. */
/* Three tabs, one row, no leftover: each takes a third of the rail. */
.rtabs{padding:0 12px;margin:2px 0 10px;gap:6px;overflow:visible}
.rtabs .psort-chip{flex:1 1 0;min-width:0;padding:9px 4px;font-size:.88rem;text-align:center}
/* A group has no picture, so the rank stands on its own in the same square. */
.rt-flat{background:var(--accent-soft);display:flex;align-items:center;justify-content:center}
.rt-flat .rt-rank{position:static;background:none;color:var(--accent);font-size:1.05rem;backdrop-filter:none}
.rgroup-grid{padding:0 12px 8px}
/* An account row is a trending row with an avatar where the picture goes. */
/* A group or an account, read inside the app: the same column as the feed,
   with the way back at the top of it. */
.pfhead{display:flex;gap:14px;align-items:flex-start;padding:4px 2px 18px}
.pfhead-id{flex:1;min-width:0}
.pfhead-id h1{font-size:1.3rem;font-weight:800;margin:0}
.pfhead-bio{font-size:.94rem;color:var(--text2);line-height:1.45;margin:6px 0 0}
.pfhead-counts{font-size:.86rem;color:var(--text2);margin-top:8px}
.av-lg{width:76px;height:76px;border-radius:20px;font-size:1.7rem}
.rperson{align-items:center;cursor:pointer}
.rperson .rt-txt{flex:1;min-width:0}
/* The follow badge sits proud of the avatar's bottom corner, so the square it
   is in cannot clip. Written against .rperson rather than as its own class,
   because .rt-shot sets overflow:hidden further down the file and a class on
   its own would lose to it. */
.rperson .rt-shot{background:none;overflow:visible}
.av-rail{width:92px;height:92px;border-radius:12px;font-size:1.8rem}
.rperson .follow-btn{flex:none;align-self:center}
.rtrend{display:flex;align-items:flex-start;gap:12px;width:100%;text-align:left;background:none;border:none;color:inherit;cursor:pointer;padding:10px 12px;border-radius:13px;text-decoration:none}
.rtrend:hover{background:var(--accent-soft)}
/* The picture carries the rank, so the number reads at a glance instead of
   hiding in a line of small grey text. */
.rt-shot{position:relative;width:92px;height:92px;flex-shrink:0;border-radius:12px;overflow:hidden;background:var(--line)}
.rt-thumb{width:100%;height:100%;object-fit:cover;display:block}
.rt-rank{position:absolute;top:5px;left:5px;min-width:23px;height:23px;padding:0 6px;border-radius:8px;background:rgba(0,0,0,.66);color:#fff;font-size:.76rem;font-weight:800;display:flex;align-items:center;justify-content:center;line-height:1;backdrop-filter:blur(2px)}
.rt-txt{flex:1;min-width:0;padding-top:2px}
.rtrend .rt-term{display:block;font-weight:700;font-size:1rem;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rtrend .rt-blurb{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:.82rem;line-height:1.35;color:var(--text2);margin-top:3px}
.rtrend .rt-meta{display:block;font-size:.76rem;color:var(--text2);margin-top:4px}
/* The trending card the mobile feed drops in every ten to fifteen klips. A
   rail of its own that scrolls sideways, one klip per tile. */
.tspot{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px 0 12px;margin-bottom:12px}
.tspot h3{font-size:1.02rem;font-weight:800;margin:0 0 2px;padding:0 14px}
.tspot .ts-sub{font-size:.78rem;color:var(--text2);padding:0 14px 11px;margin:0}
.ts-track{display:flex;gap:10px;overflow-x:auto;scroll-snap-type:x mandatory;padding:0 14px 2px;-webkit-overflow-scrolling:touch;scrollbar-width:none;overscroll-behavior-x:contain}
.ts-track::-webkit-scrollbar{display:none}
.ts-tile{flex:0 0 158px;scroll-snap-align:start;background:var(--bg);border:1px solid var(--line);border-radius:14px;overflow:hidden;text-align:left;padding:0;cursor:pointer;color:inherit;display:flex;flex-direction:column}
.ts-tile img,.ts-noimg{width:100%;aspect-ratio:1/1;object-fit:cover;display:block;background:var(--line)}
.ts-body{padding:9px 10px 4px;font-size:.82rem;line-height:1.35;flex:1;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.ts-who{padding:0 10px;font-size:.74rem;color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ts-stats{display:flex;gap:9px;padding:7px 10px 10px;font-size:.72rem;color:var(--text2)}
.ts-stats span{display:inline-flex;align-items:center;gap:3px}
.ts-stats svg{width:12px;height:12px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
@media (min-width:1200px){ .tspot{display:none} }
.tr-card .rempty{padding:2px 12px 10px;font-size:.84rem;color:var(--text2);line-height:1.45}
.tback{display:flex;align-items:center;gap:8px;background:none;border:none;color:var(--text2);cursor:pointer;font-size:.9rem;font-weight:600;padding:0;margin-bottom:12px}
.tback svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.thead{margin-bottom:14px}
.thead h1{font-size:1.5rem;font-weight:800;margin:0}
.thead-sub h2{font-size:1.05rem;font-weight:800;margin:0}
.thead p{margin:3px 0 0;font-size:.86rem;color:var(--text2)}
#app main.wrap{padding-top:0}

/* Left sidebar (desktop) becomes a bottom bar on narrow screens. */
.sidebar{position:fixed;top:0;left:0;bottom:0;width:var(--sidebar);background:var(--card);border-right:1px solid var(--line);display:flex;flex-direction:column;padding:74px 12px 16px;z-index:30}
.snav{display:flex;flex-direction:column;gap:4px;flex:1}
.snav button{display:flex;align-items:center;gap:12px;padding:11px 13px;border-radius:12px;font-size:1rem;font-weight:600;color:var(--text2);text-align:left;width:100%}
.snav button:hover{background:var(--accent-soft);color:var(--text)}
.snav button.active{background:var(--accent);color:#fff}
.snav .sicon{width:20px;height:20px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center}
.snav .sicon svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.sfoot{border-top:1px solid var(--line);padding-top:12px;margin-top:12px}
/* The nav no longer reserves a strip of the page: the feed is centred on the
   window under the wordmark, and the nav floats over the margin beside it.
   The narrow band where a 620px column would reach the nav is handled by
   narrowing the column, not by shoving it sideways. */
body.signed-in{padding-left:0}
@media (max-width:900px){
  body.signed-in{padding-left:0;padding-bottom:64px}
  .sidebar{top:auto;right:0;bottom:0;width:auto;flex-direction:row;border-right:none;border-top:1px solid var(--line);padding:6px 8px;align-items:center;gap:6px}
  .sidebar{padding-top:6px}
  .sidebar .sfoot-label{display:none}
  .snav{flex-direction:row;gap:4px}
  .snav button{flex-direction:column;gap:3px;font-size:.7rem;padding:6px 4px;justify-content:center;text-align:center}
  .snav button.active{background:transparent;color:var(--accent)}
  /* Five items do not fit a bottom bar. Trending takes the Groups slot on
     mobile: the group chip grid lives in the Trending page's Groups tab. */
  #nav-groups{display:none}
}
.hidden{display:none !important}
.vhide{visibility:hidden}
/* An open modal owns the scroll: the page behind it stays put. */
body:has(.modal-back:not(.hidden)),body:has(.gif-back:not(.hidden)){overflow:hidden}
/* The Desk is a desktop tool. */
@media (max-width:900px){ #um-desk{display:none !important} }
/* Admin shortcut on the left of the bar, every page, admin sessions only. */
.h-admin{display:inline-flex;align-items:center;justify-content:center;gap:6px;text-align:center;font-size:.84rem;font-weight:700;padding:7px 13px;border-radius:999px;border:1.5px solid var(--line);color:var(--text2);pointer-events:auto}
.h-admin:hover{border-color:var(--accent);color:var(--accent)}
.h-admin svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
@media (max-width:900px){ .h-admin{display:none} }

/* Topbar: pinned to the top right of the window, same as Kreatr. */
/* The wordmark is the centre line of the whole product: the feed sits under
   it and everything else arranges around it. So it is centred on the window,
   not on whatever space is left over beside the nav. */
header{position:fixed;top:0;left:0;right:0;z-index:90;height:60px;display:flex;align-items:center;pointer-events:none;
  background:color-mix(in srgb, var(--bg) 88%, transparent);backdrop-filter:blur(14px);border-bottom:1px solid var(--line)}
.hbar{position:relative;display:flex;align-items:center;width:100%;max-width:none;margin:0;padding:0 20px;height:60px}
.hbar .logo{position:absolute;left:50%;transform:translateX(-50%);pointer-events:auto}
/* The wordmark used to hide on desktop because the nav carried its own. There
   is one now, here, and it shows at every width. */
@media (max-width:900px){
  header{left:16px;right:16px;top:10px;height:48px;border-radius:24px;padding:0 6px;border-bottom:none}
  .hbar{height:48px;padding:0 8px}
}
.logo{font-weight:800;font-size:1.45rem;letter-spacing:-0.03em;color:var(--accent)}
.logo-img{height:26px;display:block}
.logo-img-lg{height:44px;display:inline-block}
.hactions{display:flex;align-items:center;gap:10px;position:relative;margin-left:auto;pointer-events:auto}
.hprofile{display:flex;align-items:center;gap:10px;border-radius:11px;padding:0}
.icon-btn{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;color:var(--text2)}
.icon-btn:hover{background:var(--accent-soft);color:var(--text)}
.icon-btn svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.user-menu{position:absolute;top:44px;right:0;width:250px;background:var(--card);border:1px solid var(--line);border-radius:16px;box-shadow:0 14px 44px rgba(0,0,0,.24);padding:8px;z-index:40}
.um-head{display:flex;align-items:center;gap:11px;padding:10px 10px 12px}
.um-id{min-width:0}
.um-name{font-weight:700;font-size:.95rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.um-handle{color:var(--text2);font-size:.85rem}
.um-item{display:flex;align-items:center;gap:11px;width:100%;text-align:left;padding:10px;border-radius:11px;font-size:.94rem;font-weight:500;color:var(--text)}
.um-item:hover{background:var(--accent-soft)}
.um-item svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0;color:var(--text2)}

/* Avatars: rounded squares, never circles */
.av{display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;flex-shrink:0;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;-webkit-user-drag:none;object-fit:cover}
.av-sm{width:42px;height:42px;border-radius:13px;font-size:1rem}
.av-xs{width:34px;height:34px;border-radius:11px;font-size:.85rem}

/* Landing */

}
.usp{display:inline-block;background:var(--accent-soft);color:var(--accent);font-weight:600;font-size:.85rem;padding:7px 14px;border-radius:999px;margin-bottom:18px}
.btn{display:inline-block;font-weight:600;border-radius:12px;padding:13px 26px;font-size:1rem;transition:opacity .15s;border:1.5px solid transparent;line-height:1.2}
.btn:active{opacity:.8}
.btn-primary{background:var(--accent);color:#fff}
.btn-ghost{border-color:var(--line);color:var(--text)}
.landing-actions{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}
.landing-links{margin-top:30px;font-size:.85rem;color:var(--text2)}
.landing-links a{color:var(--text2)}
.landing-links a:hover{color:var(--text)}
.landing-links span{margin:0 9px;opacity:.5}

/* Compose */
/* Which feed you are reading, between the composer and the klips. Two words,
   because there are two answers: the whole room, or the part of it you chose. */
.feedpick{display:flex;gap:6px;background:var(--card);border:1px solid var(--line);border-radius:999px;padding:4px;margin:14px 0 16px;width:fit-content;max-width:100%;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}
.feedpick::-webkit-scrollbar{display:none}
.feedpick.hidden{display:none}
.fp-opt{flex:none;border:none;background:none;color:var(--text2);font-weight:700;font-size:.9rem;padding:7px 18px;border-radius:999px;cursor:pointer;line-height:1.2}
.fp-opt:hover{color:var(--text)}
.fp-opt.on{background:var(--accent);color:#fff}
.compose{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);margin:14px 0;padding:14px 14px 10px;display:flex;flex-wrap:wrap;gap:11px;position:relative}
/* Klip stack composer. The parts already written sit to the left as numbered
   spines, so which klip is which is never a guess, and the one being written
   carries its position in the top right the way a photo Stack does. */
.crail{display:flex;flex-direction:column;gap:6px;flex:none;max-height:224px;overflow-y:auto;scrollbar-width:none}
.crail::-webkit-scrollbar{display:none}
.cspine{width:34px;height:42px;border-radius:10px;border:1.5px solid var(--line);background:var(--bg);color:var(--text2);font-weight:800;font-size:.82rem;display:flex;align-items:center;justify-content:center;text-align:center;flex:none;position:relative}
.cspine:hover{border-color:var(--accent);color:var(--accent)}
.cspine.on{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}
.cspine .cs-dot{position:absolute;bottom:5px;left:50%;transform:translateX(-50%);width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.75}
.cpos{position:absolute;top:11px;right:13px;display:flex;align-items:center;gap:4px;z-index:2}
.cpos-n{background:var(--accent-soft);color:var(--accent);font-size:.73rem;font-weight:800;padding:3px 9px;border-radius:999px;text-align:center}
.cpos-x{color:var(--text2);font-size:1.15rem;line-height:1;padding:1px 6px;border-radius:8px}
.cpos-x:hover{color:var(--red);background:var(--line)}
/* Room for the counter, so the first line of text never runs under it. */
.compose.stacked #compose-text{padding-right:80px}
.compose-media{width:100%;display:flex;align-items:center;gap:10px;padding-top:4px}
/* Mention autocomplete: the list of accounts that match what has been typed
   after an @, sitting under the box being typed into. */
.mlist{width:100%;margin-top:9px;border:1px solid var(--line);border-radius:14px;overflow:hidden;background:var(--card)}
.mrow{display:flex;align-items:center;gap:10px;width:100%;padding:9px 12px;text-align:left;background:none;border:none;color:var(--text);cursor:pointer}
.mrow:hover,.mrow.on{background:var(--accent-soft)}
.m-id{min-width:0;display:flex;flex-direction:column}
.m-name{font-weight:700;font-size:.9rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.m-handle{color:var(--text2);font-size:.82rem}
/* A tagged profile reads as a link, not as brand accent. */
.clip-mention,.clip-group{color:var(--link);font-weight:600}
.clip-mention:hover{text-decoration:underline}
.cadd{display:inline-flex;align-items:center;justify-content:center;gap:6px;text-align:center;border:1.5px solid var(--line);color:var(--text);font-weight:700;font-size:.84rem;padding:7px 13px;border-radius:999px;white-space:nowrap;flex:none}
.cadd:hover{border-color:var(--accent);color:var(--accent)}
.cadd svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2.4;stroke-linecap:round}
/* Full-width foot row: the group dropdown's left edge sits flush with the
   avatar's left edge. min-width:0 on the text column stops a long suggestion
   chip from stretching the card and the counter bar with it. */
/* The suggestion chip lives in the flexible middle and truncates; it can
   never push the Klip button, which keeps its place at the right edge. */
.compose textarea{flex:1;border:none;outline:none;background:transparent;resize:none;font-size:1.05rem;line-height:1.45;min-height:56px;padding-top:8px}
.compose-right{flex:1;display:flex;flex-direction:column;min-width:0}
.compose-foot{display:flex;align-items:center;gap:10px;margin-top:8px;width:100%;flex-wrap:nowrap}
.gpick{position:relative}
.gpick-btn{display:flex;align-items:center;gap:5px;background:transparent;border:1px solid var(--line);border-radius:999px;padding:6px 12px;font-size:.85rem;color:var(--text2);max-width:220px}
.gpick-btn:hover{border-color:var(--accent);color:var(--text)}
.gpick-btn.set{border-color:var(--accent);background:var(--accent-soft);color:var(--accent);font-weight:600}
.gpick-btn span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gpick-arrow{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2;flex-shrink:0}
/* Opens downward: the compose box sits at the top of the page, so there is
   never room above it for the list. */
.gpick-pop{position:absolute;top:calc(100% + 8px);left:0;width:270px;max-width:78vw;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:0 12px 40px rgba(0,0,0,.22);z-index:30;overflow:hidden}
.gpick-pop input{width:100%;border:none;border-bottom:1px solid var(--line);background:transparent;padding:11px 13px;outline:none;font-size:.92rem}
.gpick-list{max-height:min(230px, 42vh);overflow-y:auto;padding:5px}
.gpick-item{display:block;width:100%;text-align:left;padding:9px 11px;border-radius:9px;font-size:.92rem;color:var(--text)}
.gpick-item:hover,.gpick-item.active{background:var(--accent-soft)}
/* Sub-groups. A child is indented under its parent in the picker, and marked
   in the chip grid when it is followed through that parent rather than
   directly, so what you are actually following is never a guess. */
.gpick-item.gpick-sub{padding-left:26px}
.group-chip.sub{font-size:.84rem}
.group-chip.via{border-style:dashed;color:var(--accent);border-color:var(--accent)}
.gpick-item.chosen{color:var(--accent);font-weight:700}
.gpick-none{color:var(--text2);font-size:.86rem;padding:12px 11px;text-align:center}
.gsuggest{display:inline-flex;align-items:center;font-size:.84rem;color:var(--text2);min-width:0;overflow:hidden;flex:1 1 0}
/* Italic placeholder while typing, so the row never changes height and the
   selector never gets pushed around. */
.gsuggest .g-wait{font-style:italic;color:var(--text2);opacity:.75;white-space:nowrap}
.gsuggest button{background:var(--accent-soft);color:var(--accent);font-weight:700;border-radius:999px;padding:6px 12px;font-size:.84rem;white-space:nowrap;max-width:150px;overflow:hidden;text-overflow:ellipsis}
.gsuggest button:hover{background:var(--accent);color:#fff}
/* A chosen group reveals an X over its label on hover, click to clear. */
.gpick-btn.set:hover span{opacity:0}
.gpick-btn .g-x{display:none;position:absolute;inset:0;align-items:center;justify-content:center;font-size:1.05rem;font-weight:700}
.gpick-btn.set{position:relative}
.gpick-btn.set:hover .g-x{display:flex}
.gpick-btn.set:hover .gpick-arrow{opacity:0}
.clip-btn{margin-left:auto;background:var(--accent);color:#fff;font-weight:700;border-radius:999px;padding:8px 20px;font-size:.95rem;flex:none;white-space:nowrap}
.clip-btn:disabled{opacity:.45;cursor:default}
.counter-track{height:3px;border-radius:2px;background:var(--line);margin-top:10px;overflow:hidden}
.counter-bar{height:100%;width:0%;background:var(--accent);border-radius:2px;transition:width .15s ease, background-color .35s ease}
.counter-bar.warn{background:var(--yellow)}
.counter-bar.danger{background:var(--red)}
.char-note{font-size:.78rem;color:var(--text2);margin-top:4px;text-align:right;min-height:1em}
.char-note.danger{color:var(--red)}

/* Tabs */
.tabs{display:flex;background:var(--card);border:1px solid var(--line);border-radius:999px;padding:4px;margin-bottom:14px}
.tabs button{flex:1;padding:9px 0;border-radius:999px;font-weight:600;font-size:.95rem;color:var(--text2)}
.tabs button.active{background:var(--accent);color:#fff}

/* Clip cards */
.clip{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px;margin-bottom:12px;position:relative}
.clip-reclip-note{display:flex;align-items:center;gap:11px;color:var(--text2);font-size:.82rem;font-weight:600;margin-bottom:9px}
/* The icon sits in the avatar's column and the label starts where the name
   starts, so the card has two left edges rather than three. 42px is .av-sm
   and 11px is .clip-head's gap: change those and change these. */
.clip-reclip-note .crn-i{width:42px;flex:none;display:flex;justify-content:flex-end}
.clip-reclip-note img{width:14px;height:14px}
.clip-head{display:flex;gap:11px}
.clip-meta{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0;padding-right:26px}
.clip-stackn{background:var(--accent-soft);color:var(--accent);font-size:.68rem;font-weight:800;letter-spacing:.02em;padding:2px 7px;border-radius:999px;text-align:center;flex:none}
.clip-name{font-weight:700;font-size:.98rem}
.badge-img{width:16px;height:16px;vertical-align:text-top}
.clip-handle,.clip-time{color:var(--text2);font-size:.9rem}
.pfl{cursor:pointer}
.pfl:hover .clip-name,a.pfl.clip-handle:hover{text-decoration:underline}
.badge-btn{background:none;border:none;padding:0 0 0 3px;cursor:pointer;line-height:0;vertical-align:text-top}
.badge-pop{position:fixed;z-index:70;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:0 12px 40px rgba(0,0,0,.28);padding:16px;width:290px;max-width:calc(100vw - 24px)}
.badge-pop h3{font-size:.95rem;display:flex;align-items:center;gap:7px;margin-bottom:6px}
.badge-pop h3 img{width:16px;height:16px}
.badge-pop p{font-size:.86rem;color:var(--text2);line-height:1.5}
.badge-pop a.bp-cta{display:block;text-align:center;background:var(--accent);color:#fff;font-weight:600;border-radius:10px;padding:9px 0;margin-top:12px;font-size:.9rem}
.badge-pop .bp-dis{font-size:.75rem;color:var(--text2);margin-top:9px;line-height:1.45}
.badge-pop .bp-x{position:absolute;top:8px;right:10px;background:none;border:none;color:var(--text2);font-size:1.2rem;cursor:pointer;line-height:1}
/* One control per klip, top right. It replaced the report flag and the
   highlighter, so it is always visible rather than revealed on hover: it is
   now the only way to reach report, highlight and delete. */
.clip-menu-btn{position:absolute;top:8px;right:8px;padding:7px;opacity:.5;transition:opacity .15s;z-index:2;line-height:0}
.clip:hover .clip-menu-btn,.clip-menu-btn:focus,.clip-menu-btn[aria-expanded="true"]{opacity:1}
.clip-menu-btn svg{width:17px;height:17px;stroke:var(--text2);fill:var(--text2);stroke-width:0}
.clip-menu{position:absolute;top:38px;right:8px;z-index:20;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:0 12px 40px rgba(0,0,0,.28);padding:6px;min-width:236px;text-align:left;max-width:288px}
.clip-menu button{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:none;border:none;color:var(--text);padding:11px 12px;border-radius:10px;font-size:.93rem;font-weight:600;cursor:pointer}
.clip-menu button:hover{background:var(--accent-soft)}
/* Greyed rather than hidden: the reason it cannot be used is worth showing. */
.clip-menu button[disabled]{opacity:.45;cursor:default}
.clip-menu button[disabled]:hover{background:none}
.clip-menu svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0;color:var(--text2)}
.clip-menu .cm-note{display:block;font-size:.76rem;font-weight:500;color:var(--text2);padding:0 12px 9px;line-height:1.4}
.clip-menu .cm-del,.clip-menu .cm-del svg{color:var(--red)}
/* Highlighted klip: kreatr.link's klip ring, an animated conic gradient
   sweeping around the card for the 24 hours the highlight lives. Browsers
   without @property get the same ring, standing still. */
@property --hl-a{syntax:'<angle>';inherits:false;initial-value:0deg}
.clip.hl{border-color:transparent}
.clip.hl::before{content:'';position:absolute;inset:-3px;border-radius:calc(var(--radius) + 3px);background:conic-gradient(from var(--hl-a,0deg),#7c3aed,#a78bfa,#60a5fa,#7c3aed);z-index:-1;animation:hl-spin 2s linear infinite}
@keyframes hl-spin{to{--hl-a:360deg}}
@media (hover:none){
  .clip-menu-btn{opacity:.6;padding:9px}
  .clip-menu-btn svg{width:19px;height:19px}
}
.drop{display:flex;align-items:center;gap:13px;border:1.5px dashed var(--line);border-radius:14px;padding:13px;margin:16px 0 4px;cursor:pointer;position:relative;transition:border-color .15s,background .15s}
.drop:hover{border-color:var(--accent);background:var(--accent-soft)}
.drop.over{border-color:transparent;box-shadow:0 0 0 2px var(--accent);outline:2px dashed var(--accent);outline-offset:-2px;background:rgba(124,58,237,.07)}
.drop .av{width:56px;height:56px;border-radius:16px;font-size:1.2rem}
.drop-txt{display:flex;flex-direction:column;gap:2px;min-width:0}
.drop-txt strong{font-size:.94rem}
.drop-txt span{font-size:.82rem;color:var(--text2)}
.drop-clear{position:absolute;top:8px;right:10px;font-size:1.2rem;line-height:1;color:var(--text2);padding:2px 6px;border-radius:8px}
.drop-clear:hover{background:var(--line);color:var(--text)}
.drop.busy{opacity:.6;pointer-events:none}
.del-modal{max-width:340px}
.del-acts{display:flex;gap:10px;margin-top:20px}
.del-acts .btn{flex:1;text-align:center;padding:12px 0}
.btn-danger{background:var(--red);color:#fff}

/* Pending delete: the klip stays put while a ten second timer runs, so undo
   costs nothing and the row underneath does not jump until it is really gone. */
.clip.pending-del{position:relative}
.clip.pending-del > *:not(.pd){opacity:.25;pointer-events:none}
.pd{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:14px;background:color-mix(in srgb, var(--card) 88%, transparent);border-radius:var(--radius)}
.pd-ring{position:relative;width:44px;height:44px;flex-shrink:0}
.pd-ring svg{width:44px;height:44px;transform:rotate(-90deg)}
.pd-ring circle{fill:none;stroke-width:3}
.pd-ring .r-bg{stroke:var(--line)}
.pd-ring .r-fg{stroke:var(--red);stroke-linecap:round;stroke-dasharray:119.4;stroke-dashoffset:0;animation:pd-drain 10s linear forwards}
@keyframes pd-drain{to{stroke-dashoffset:119.4}}
.pd-num{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.95rem;color:var(--text)}
.pd-txt{font-size:.92rem;color:var(--text2)}
.pd-undo{font-weight:700;color:var(--accent);padding:8px 14px;border-radius:10px;font-size:.95rem}
.pd-undo:hover{background:var(--accent-soft)}
.clip.collapsing{overflow:hidden;transition:height .3s ease,opacity .25s ease,margin-bottom .3s ease,padding .3s ease;opacity:0;padding-top:0;padding-bottom:0;margin-bottom:0}
.report-reasons{display:flex;flex-direction:column;gap:9px;margin:16px 0 4px}
.report-reasons label{display:block;width:100%;border:1.5px solid var(--line);border-radius:12px;padding:13px 15px;cursor:pointer;font-size:.97rem;font-weight:500;color:var(--text);margin:0;transition:border-color .15s,background .15s,box-shadow .15s,color .15s}
.report-reasons label:hover{border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}
/* Outranks the generic .modal input rule, which would otherwise stretch each
   hidden radio to full width and leave it overlaying the page. */
.modal .report-reasons input{position:absolute;opacity:0;width:1px;height:1px;margin:0;padding:0;border:0;pointer-events:none;clip:rect(0 0 0 0);overflow:hidden}
.report-reasons label.sel{border-color:var(--accent);background:var(--accent);color:#fff;box-shadow:0 0 0 4px var(--accent-soft)}
.clip-body{margin-top:4px;font-size:1.02rem;line-height:1.45;white-space:pre-wrap;word-wrap:break-word;overflow-wrap:anywhere}
.clip-link{color:var(--accent);word-break:break-all}
.clip-tag{display:inline-block;background:var(--accent-soft);color:var(--accent);font-size:.78rem;font-weight:600;padding:3px 10px;border-radius:999px;margin-top:9px}
.clip-main{flex:1;min-width:0}
.linkcard{display:block;border:1px solid var(--line);border-radius:12px;overflow:hidden;margin-top:10px}
.linkcard img{width:100%;max-height:280px;object-fit:cover;display:block}
.linkcard .lc-t{padding:9px 12px;font-size:.9rem;font-weight:600}
.linkcard .lc-d{padding:0 12px 10px;font-size:.82rem;color:var(--text2)}
.actions{display:flex;justify-content:space-between;max-width:340px;margin-top:11px}
.act{display:flex;align-items:center;gap:6px;color:var(--text2);font-size:.85rem;padding:5px;border-radius:8px;transition:background .12s}
.act:hover{background:var(--accent-soft)}
.act img{width:19px;height:19px;display:block}
.act.liked span{color:var(--accent);font-weight:600}
.act.reclipped span{color:var(--accent);font-weight:600}
.act.reserved{opacity:.35;pointer-events:none}
/* Greyed but still tappable: the tap is what explains why it is greyed. */
.act.off{opacity:.35}
.act.saved img{filter:none}
.act.saved{color:var(--accent)}

/* Empty states / suggestions */
.empty{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:22px;text-align:center;color:var(--text2);margin-bottom:12px}
.empty h3{color:var(--text);margin-bottom:6px;font-size:1.05rem}
/* Swipeable profile tile. The row itself slides; the action sits in a layer
   behind it, revealed by the movement. Two trip-wires: past REVEAL the action
   reads as a menu, past COMMIT releasing fires it. Right follows (additive),
   left unfollows (the costly one), so direction stays a language. */
.tile{position:relative;overflow:hidden;border-radius:var(--radius);margin-bottom:10px;touch-action:pan-y}
.tile-bg{position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between;border-radius:var(--radius);opacity:0;transition:opacity .12s}
.tile.dragging .tile-bg,.tile.armed .tile-bg{opacity:1}
.tile.sw-right .tile-bg{background:var(--accent)}
.tile.sw-left .tile-bg{background:var(--red)}
.tile-act{display:flex;align-items:center;gap:7px;padding:0 20px;color:#fff;font-weight:700;font-size:.9rem;opacity:.55;transition:opacity .12s,transform .12s;white-space:nowrap}
.tile.armed .tile-act{opacity:1;transform:scale(1.06)}
.tile-act svg{width:17px;height:17px;stroke:#fff;fill:none;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.tile:not(.sw-right) .act-follow,.tile:not(.sw-left) .act-unfollow{visibility:hidden}
.sugg{position:relative;z-index:1;display:flex;align-items:center;gap:11px;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:12px 14px;text-align:left;cursor:pointer;will-change:transform}
.sugg.settling{transition:transform .26s cubic-bezier(.22,1,.36,1)}
/* Studio */
.st-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:12px}
@media (min-width:900px){.st-tiles{grid-template-columns:repeat(6,1fr)}}
.st-tile{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px 8px;text-align:center}
.st-n{font-weight:800;font-size:1.2rem}
.st-l{color:var(--text2);font-size:.7rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;margin-top:2px}
.st-chart{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px;margin-bottom:12px}
.st-chart-t{font-size:.85rem;font-weight:700;color:var(--text2);margin-bottom:10px}
.st-bars{display:flex;align-items:flex-end;gap:3px;height:70px}
.st-bar{flex:1;height:100%;display:flex;align-items:flex-end}
.st-bar div{width:100%;background:var(--accent);border-radius:3px 3px 0 0;min-height:2px;opacity:.85}
.psort{display:flex;gap:8px;margin:4px 0 12px;overflow-x:auto;scrollbar-width:none}
.psort::-webkit-scrollbar{display:none}
.psort-chip{border:1.5px solid var(--line);border-radius:999px;padding:6px 14px;font-size:.85rem;font-weight:600;color:var(--text2);white-space:nowrap;background:none}
.psort-chip.on{background:var(--accent);border-color:var(--accent);color:#fff}
.st-row{display:block;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:12px 14px;margin-bottom:10px}
.st-row:hover{border-color:var(--accent)}
.st-row-c{font-size:.98rem}
.st-row-m{color:var(--text2);font-size:.82rem;margin-top:5px}
.st-hl{color:var(--accent);font-size:.66rem;font-weight:800;letter-spacing:.04em}

/* Profile settings as a full-width page, not a modal. */
.settings-card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:26px;margin-bottom:16px}
.settings-card h2{margin-bottom:2px}
.settings-card > p{color:var(--text2);font-size:.92rem;margin-bottom:16px}
#app main.wrap.wide{max-width:960px}

.hdrbg-row{display:flex;gap:8px;margin:4px 0 2px}
.hdrbg-row .btn{padding:9px 14px;font-size:.88rem}
/* The live header preview at the top of settings. It is also the background
   drop zone, because the place a photo lands is the honest place to drop it. */
.pf-hero{position:relative;aspect-ratio:648/232;border-radius:14px;border:1.5px dashed var(--line);background-size:cover;background-position:center;display:flex;align-items:flex-start;justify-content:flex-end;padding:10px;cursor:pointer;margin-bottom:0;overflow:hidden}
.pf-hero:hover,.pf-hero.over{border-color:var(--accent)}
.pf-hero .hdr-hint{font-size:.72rem;color:#fff;background:rgba(0,0,0,.55);padding:4px 10px;border-radius:999px;position:relative;z-index:1}
.pf-hero-id{position:absolute;left:0;right:0;bottom:10px;display:flex;justify-content:center;pointer-events:none}
.pf-hero-id .av{width:56px;height:56px;border-radius:15px;box-shadow:0 2px 10px rgba(0,0,0,.35)}
/* The words sit under the banner, left aligned, exactly as the profile lays
   them out. XX and the joined note stand in for numbers this form cannot know. */
.pf-hero-below{display:flex;flex-direction:column;align-items:flex-start;gap:3px;margin:10px 2px 18px;text-align:left}
.pf-hero-below strong{font-size:1.15rem;letter-spacing:-0.01em}
.pf-hero-handle{color:var(--text2);font-size:.85rem;font-weight:500}
.pf-hero-bio{font-size:.9rem;line-height:1.4;margin-top:3px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.pf-hero-bio:empty{display:none}
.pf-hero-link{margin-top:4px;color:var(--accent);font-size:.82rem;font-weight:700;background:var(--accent-soft);padding:4px 13px;border-radius:999px;max-width:88%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-hero-link.hidden{display:none}
.pf-hero-meta{color:var(--text2);font-size:.8rem;margin-top:5px}
/* Profile color swatches in the editor. */
.swatches{display:flex;flex-wrap:wrap;gap:8px;margin:4px 0 2px}
.swatch{width:30px;height:30px;border-radius:10px;border:2px solid transparent;cursor:pointer;flex-shrink:0}
.swatch.auto{background:transparent;border:2px dashed var(--line);color:var(--text2);font-size:.62rem;font-weight:800;display:flex;align-items:center;justify-content:center;letter-spacing:.02em}
.swatch.on{border-color:var(--text);box-shadow:0 0 0 2px var(--card) inset}
.swatch.auto.on{border-style:solid}
/* No color: a crossed circle, so it reads as a choice rather than an empty
   slot. Auto still means match the photo. */
.swatch.none{background:transparent;border:2px solid var(--line);display:flex;align-items:center;justify-content:center;padding:0}
.swatch.none svg{width:20px;height:20px;fill:none;stroke:#dc2626;stroke-width:2;stroke-linecap:round}
.swatch.none svg circle{stroke:var(--text2);stroke-width:1.4}

/* Desktop hover profile card. */
.hcard{position:fixed;z-index:95;width:300px;background:var(--card);border:1px solid var(--line);border-radius:16px;box-shadow:0 16px 48px rgba(0,0,0,.3);overflow:hidden;opacity:0;transition:opacity .15s}
.hcard.show{opacity:1}
.hcard-banner{height:64px}
.hcard-body{padding:0 14px 14px;margin-top:-24px;position:relative}
.hcard-body .av{width:48px;height:48px;border-radius:14px;font-size:1.1rem;box-shadow:0 6px 18px rgba(0,0,0,.3)}
.hcard-name{font-weight:800;margin-top:8px}
.hcard-handle{color:var(--text2);font-size:.88rem}
.hcard-bio{color:var(--text2);font-size:.88rem;margin-top:6px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.hcard-counts{margin-top:8px;font-size:.9rem;color:var(--text2)}
.hcard-counts b{color:var(--text)}
.hcard-flag{position:absolute;top:8px;right:10px;color:#fff;opacity:.7;background:none;border:none;cursor:pointer}
.hcard-flag:hover{opacity:1}
.hcard-flag svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}

/* ---------- Inline replies ---------- */
/* Each reply hangs off an elbow: a line down from what it answers, turning
   across into the reply, with an arrowhead. Nesting indents, so branching
   conversations stay readable. */
.srow{display:flex;align-items:center;gap:9px;margin-top:10px}
.srow .show-replies{margin-top:0}
.show-replies{display:block;margin-top:10px;padding:4px 0;background:none;border:none;font-size:.86rem;font-weight:700;color:var(--accent);cursor:pointer;text-align:left}
/* The See more that ends the first Klip of a stack: a link in the writing,
   not another button under it. */
.see-more{display:inline;margin:0 0 0 3px;padding:0;font-size:inherit;font-weight:600;vertical-align:baseline}
.see-more.gone{display:none}
.show-replies:hover{text-decoration:underline}
#thread-modal .show-replies{display:none}
.replies{margin-top:2px}
/* Thread connectors. One spine runs down the whole set and each klip hangs
   off it on its own elbow, so a stack reads as one continuous run rather than
   a pile of separate hooks. The spine is a background on the row itself,
   which leaves both pseudo-elements free for the elbow and its arrowhead, and
   it stops at the elbow of the last row instead of running past it. */
.rrow{position:relative;padding-left:48px;padding-top:14px;
  background-image:linear-gradient(var(--line),var(--line));
  background-repeat:no-repeat;background-size:2px 100%;background-position:13px 0}
.rrow:last-child{background-size:2px 52px}
.rrow::before{content:'';position:absolute;left:13px;top:14px;width:16px;height:26px;border-left:2px solid var(--line);border-bottom:2px solid var(--line);border-bottom-left-radius:12px;pointer-events:none}
.rrow::after{content:'';position:absolute;left:26px;top:35px;width:7px;height:7px;border-top:2px solid var(--line);border-right:2px solid var(--line);transform:rotate(45deg);pointer-events:none}
.rrow .rrow{padding-left:42px}
/* A thread reads as the Klip it is about: each stack post, then the replies to
   that post, collapsible so a long argument under part two does not bury the
   rest of the stack. */
.tpost{position:relative}
.tpost.replying{border-radius:var(--radius);box-shadow:0 0 0 2px var(--accent-soft)}
.rblock{margin:0}
.rblock-empty{margin:0}
.rtoggle{display:inline-flex;align-items:center;gap:5px;background:none;border:none;color:var(--text2);font-weight:700;font-size:.84rem;padding:6px 0 6px 42px;cursor:pointer;line-height:1}
.rtoggle:hover{color:var(--text)}
.rtoggle-i{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;transition:transform .15s}
.rblock.rcollapsed .rtoggle-i{transform:rotate(-90deg)}
.rblock.rcollapsed > .rkids{display:none}
.rrow .rrow .rrow{padding-left:36px}
.rcard{display:flex;gap:9px;background:var(--bg);border:1px solid var(--line);border-radius:13px;padding:10px 12px}
.rc-main{flex:1;min-width:0}
.rc-meta{font-size:.86rem}
.rc-body{margin-top:3px;font-size:.97rem;line-height:1.45;white-space:pre-wrap;word-wrap:break-word}
.rc-body:empty{display:none}

.ksrc{color:var(--text2);font-size:.78rem;margin-top:9px}
.ksrc a{color:var(--text2);text-decoration:underline;text-underline-offset:2px}
.ksrc a:hover{color:var(--text)}
/* GIF picker: a sheet that rises from the bottom of the screen, wide enough
   to browse rather than a strip tucked under the composer. */
.gif-open{border:2px solid var(--accent);color:var(--accent);background:var(--accent-soft);font-weight:800;font-size:1.15rem;letter-spacing:.04em;border-radius:12px;height:46px;min-width:74px;display:flex;align-items:center;justify-content:center;line-height:1;cursor:pointer;flex-shrink:0;padding:0 14px}
.gif-open:hover{background:var(--accent);color:#fff}
.gif-back{position:fixed;inset:0;z-index:130;background:rgba(0,0,0,.45);opacity:0;transition:opacity .22s ease}
.gif-back.up{opacity:1}
.gif-sheet{position:absolute;left:0;right:0;bottom:0;max-height:78dvh;height:78dvh;display:flex;flex-direction:column;
  background:var(--card);border-top:1px solid var(--line);border-radius:20px 20px 0 0;
  transform:translateY(100%);transition:transform .26s cubic-bezier(.22,.61,.36,1);
  padding-bottom:env(safe-area-inset-bottom)}
.gif-back.up .gif-sheet{transform:translateY(0)}
@media (min-width:760px){ .gif-sheet{left:50%;right:auto;width:620px;transform:translate(-50%,100%)} .gif-back.up .gif-sheet{transform:translate(-50%,0)} }
.gif-grip{padding:10px 0 4px;display:flex;justify-content:center;cursor:grab;touch-action:none;flex:none}
.gif-grip span{width:42px;height:5px;border-radius:999px;background:var(--line);display:block}
.gif-search{display:flex;align-items:center;gap:9px;margin:6px 14px 10px;padding:0 14px;background:var(--bg);border-radius:999px;flex:none}
.gif-search svg{width:19px;height:19px;stroke:var(--text2);fill:none;stroke-width:2;stroke-linecap:round;flex:none}
/* Specific enough to beat the thread modal's generic .modal input rule. */
.gif-search input[type="search"]{flex:1;min-width:0;border:none;background:transparent;padding:13px 0;outline:none;font-size:1rem;color:var(--text);margin:0;border-radius:0}
.gif-search input[type="search"]:focus{border:none}
/* Columns, not a grid: GIFs keep their own proportions and stagger, which is
   what makes a wall of them readable. */
.gif-grid{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:0 12px 14px;column-count:2;column-gap:8px;scrollbar-width:none}
.gif-grid::-webkit-scrollbar{display:none}
@media (min-width:560px){ .gif-grid{column-count:3} }
.gif-cell{border:none;background:var(--bg);padding:0;cursor:pointer;border-radius:12px;overflow:hidden;display:block;width:100%;margin:0 0 8px;break-inside:avoid}
.gif-cell img{width:100%;height:auto;display:block}
.gif-wait{padding:26px 4px;text-align:center;color:var(--text2);font-size:.9rem;column-span:all}
.gif-attached{position:relative;margin-top:10px;display:inline-block}
.gif-attached img{max-height:150px;border-radius:12px;display:block}
.gif-attached .cph-x{top:6px;right:6px}
/* The Alt overlay pinned to the bottom of a photo thumbnail, and its editor.
   ALT with a check means the photo already has one. */
.cph-alt{position:absolute;left:4px;right:4px;bottom:4px;border:none;border-radius:7px;background:rgba(0,0,0,.62);color:#fff;font-size:.62rem;font-weight:800;letter-spacing:.04em;padding:3px 0;cursor:pointer;backdrop-filter:blur(2px)}
.cph-alt.set{background:rgba(124,58,237,.85)}
.alt-modal{max-width:380px}
.alt-modal img{display:block;max-width:100%;max-height:200px;object-fit:contain;margin:0 auto 12px;border-radius:12px}
.alt-hint{font-size:.84rem;color:var(--text2);margin:4px 0 12px;line-height:1.45}
.alt-modal textarea{width:100%;min-height:84px;border:1px solid var(--line);border-radius:12px;background:var(--bg);padding:10px;font-size:.95rem;resize:vertical}
.alt-acts{display:flex;gap:10px;margin-top:14px}
.alt-acts .btn{flex:1;text-align:center;margin:0;width:auto;padding:12px 0;line-height:1.2}

/* Compose attachments */
.cph-btn{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:50%;color:var(--text2);background:none;border:none;cursor:pointer;flex-shrink:0}
.cph-btn:hover{background:var(--accent-soft);color:var(--accent)}
.cph-btn svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* The compose photo button is the same size as the GIF button. */
.cph-big{height:46px;min-width:74px;width:auto;border-radius:12px;border:2px solid var(--accent);background:var(--accent-soft);color:var(--accent);padding:0 14px}
.cph-big:hover{background:var(--accent);color:#fff}
.cph-big svg{width:26px;height:26px;stroke-width:2}
.cph-count{font-size:.79rem;color:var(--text2);padding:6px 2px 0}
.cph-count strong{color:var(--text);font-weight:700}
.cph-count.full strong{color:var(--accent)}
.cstrip{display:flex;gap:8px;overflow-x:auto;padding:10px 0 2px;scrollbar-width:none}
.cstrip::-webkit-scrollbar{display:none}
.cph{position:relative;flex-shrink:0;width:72px;height:72px;border-radius:12px;overflow:hidden;border:1px solid var(--line);cursor:grab}
.cph img{width:100%;height:100%;object-fit:cover;display:block}
.cph-x{position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;background:rgba(0,0,0,.6);color:#fff;border:none;font-size:.85rem;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center}
.compose.over{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}

/* ---------- Pull to refresh ---------- */
.ptr{position:fixed;top:0;left:50%;transform:translate(-50%,-54px);z-index:85;width:44px;height:44px;border-radius:50%;background:var(--card,#fff);box-shadow:0 4px 14px rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center;opacity:0;pointer-events:none}
.ptr svg{width:28px;height:28px;display:block}
.ptr-c{stroke:#9ca3af;transition:stroke .12s}
.ptr.past .ptr-c{stroke:#7c3aed}
.ptr.spin svg{animation:ptr-spin .8s linear infinite}
@keyframes ptr-spin{to{transform:rotate(360deg)}}

/* ---------- Photo Stack ---------- */
/* The frame is full width and sized to the photos it holds, never cropping
   them: JS measures the tallest photo and sets the aspect ratio, capped at
   4:5 so one very tall photo cannot take over the feed. Anything taller than
   the frame is letterboxed by object-fit:contain rather than cut. 4:5 is
   also the starting ratio, so a stack reserves its space before the first
   photo has loaded. */
/* A physical card stack: top photo full, next cards peeking beneath. ~90%
   width, centered, visible margins; the chrome only exists for 2+ photos. */
.stackwrap{margin-top:12px;position:relative;padding-bottom:24px}
.stack{position:relative;width:100%;margin:0 auto;aspect-ratio:4/5}
.scard{position:absolute;inset:0;border-radius:14px;overflow:hidden;border:1px solid rgba(128,128,128,.35);box-shadow:0 8px 24px rgba(0,0,0,.28);background:var(--card);transition:transform .28s ease,opacity .28s ease;touch-action:pan-y;cursor:grab}
.scard img{width:100%;height:100%;object-fit:contain;display:block;pointer-events:none;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;-webkit-user-drag:none}
.scard.p0{transform:translateY(0) scale(1);opacity:1}
.scard.p1{transform:translateY(11px) scale(.955);opacity:1;filter:brightness(.9)}
.scard.p2{transform:translateY(20px) scale(.91);opacity:1;filter:brightness(.82)}
.scard.pback{transform:translateY(20px) scale(.91);opacity:0;pointer-events:none}
.stack-count{position:absolute;top:10px;right:10px;background:rgba(0,0,0,.55);color:#fff;font-size:.74rem;font-weight:700;padding:3px 9px;border-radius:999px;z-index:20;pointer-events:none}
.kphoto{margin-top:12px}
.kphoto img{max-width:100%;border-radius:14px;border:1px solid rgba(128,128,128,.3);display:block;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;-webkit-user-drag:none}
.kgif img{max-height:280px}
.lightbox{position:fixed;inset:0;background:rgba(0,0,0,.93);z-index:120;display:flex;align-items:center;justify-content:center;touch-action:none}
.lightbox img{max-width:95vw;max-height:92vh;transform-origin:center;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;-webkit-user-drag:none}
.lb-count{position:fixed;top:18px;left:50%;transform:translateX(-50%);z-index:121;background:rgba(0,0,0,.55);color:#fff;font-size:.78rem;font-weight:700;padding:4px 11px;border-radius:999px;text-align:center;pointer-events:none}
/* The photos sit side by side on one track and the track follows the finger
   1:1, so a swipe drags the next photo into view instead of jumping to it at
   a threshold. */
.lb-track{position:absolute;top:0;left:0;height:100%;display:flex;will-change:transform}
.lb-slide{flex:none;height:100%;display:flex;align-items:center;justify-content:center}
.lightbox-x{position:fixed;top:14px;right:16px;color:#fff;font-size:2rem;line-height:1;background:none;border:none;cursor:pointer;z-index:121;padding:6px 10px}

/* Undo lives in the toast, not a confirm dialog: act now, forgive after. */
.toast.with-undo{padding:9px 9px 9px 18px;display:flex;align-items:center;gap:14px;pointer-events:auto}
.toast-undo{background:var(--bg);color:var(--accent);font-weight:700;font-size:.86rem;padding:7px 15px;border-radius:999px}
.sugg-info{flex:1;min-width:0}
.sugg-name{font-weight:700;font-size:.95rem}
.sugg-bio{color:var(--text2);font-size:.84rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.follow-btn{border:1.5px solid var(--accent);color:var(--accent);font-weight:600;border-radius:999px;padding:6px 16px;font-size:.86rem;flex-shrink:0}
.follow-btn.on{background:var(--accent);color:#fff}

/* Follow-from-the-avatar: a circled plus pinned to the bottom-left corner of
   any profile picture the viewer does not follow. Tapping it follows, flashes
   a Followed overlay over the picture, and the plus goes away. */
.av-wrap{position:relative;display:inline-flex;flex-shrink:0;align-self:flex-start}
.av-follow{position:absolute;bottom:-5px;left:-5px;width:20px;height:20px;border-radius:50%;background:var(--accent);display:flex;align-items:center;justify-content:center;border:2px solid var(--card);box-shadow:0 1px 4px rgba(0,0,0,.3);z-index:2;cursor:pointer}
.av-follow svg{width:11px;height:11px;stroke:#fff;stroke-width:2.6;fill:none;stroke-linecap:round}
.av-follow:active{transform:scale(.88)}
.av-done{position:absolute;inset:0;border-radius:13px;background:rgba(124,58,237,.9);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;opacity:0;transition:opacity .25s;pointer-events:none;z-index:3}
.av-wrap .av-xs+.av-done,.av-wrap.xs .av-done{border-radius:11px}
.av-done.show{opacity:1}
.av-done svg{width:13px;height:13px;stroke:#fff;stroke-width:2.6;fill:none;stroke-linecap:round;stroke-linejoin:round}
.av-done span{font-size:7px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#fff}
.empty .btn{padding:9px 20px;font-size:.9rem;margin:14px 5px 0}
.group-grid{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:12px}
.group-chip{border:1.5px solid var(--line);border-radius:999px;padding:7px 15px;font-size:.88rem;font-weight:600;color:var(--text)}
.group-chip.on{background:var(--accent);border-color:var(--accent);color:#fff}

/* Modal */
.modal-back{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:50;display:flex;align-items:center;justify-content:center;padding:16px;overscroll-behavior:contain}
/* A modal taller than the screen scrolls inside itself; the page behind it
   never moves. */
.modal{background:var(--card);border-radius:20px;padding:24px;width:100%;max-width:400px;max-height:calc(100svh - 32px);overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.modal h2{font-size:1.25rem;margin-bottom:4px}
.modal p{color:var(--text2);font-size:.9rem;margin-bottom:16px}
/* The settings page hosts the same form the modal used to, so it needs the
   same field treatment. */
.modal label,.settings-card label{display:block;font-size:.82rem;font-weight:600;color:var(--text2);margin:12px 0 5px}
.modal input,.settings-card input:not([type=file]):not([type=checkbox]){width:100%;border:1.5px solid var(--line);border-radius:11px;padding:11px 13px;background:transparent;outline:none;font-size:1rem;color:var(--text)}
.modal input:focus,.settings-card input:focus{border-color:var(--accent)}
.field-note{font-size:.8rem;margin-top:5px;min-height:1em;color:var(--text2)}
.field-note.ok{color:#16a34a}
.field-note.bad{color:var(--red)}
.modal .btn-primary{width:100%;margin-top:18px;text-align:center}
.modal .btn-primary:disabled{opacity:.5}
.settings-card .btn-primary{width:100%;margin-top:18px;text-align:center}
.settings-card .btn-primary:disabled{opacity:.5}

.thread-box{max-width:560px;max-height:86vh;overflow-y:auto;padding:16px}
.thread-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}
.thread-head h2{font-size:1.1rem}
.x-btn{font-size:1.5rem;color:var(--text2);line-height:1;padding:4px 10px}
.reply-note{color:var(--text2);font-size:.85rem;margin:10px 0 6px}
.reply-compose{display:flex;gap:10px;margin-top:12px;border-top:1px solid var(--line);padding-top:14px}
.reply-compose .compose-right{flex:1}
.reply-compose textarea{width:100%;border:none;outline:none;background:transparent;resize:none;font-size:1rem;line-height:1.4;min-height:44px}
.thread-replies .clip{border-left:3px solid var(--accent-soft)}
.disc-note{background:var(--accent-soft);color:var(--accent);border-radius:var(--radius);padding:11px 14px;font-size:.86rem;font-weight:600;margin-bottom:12px}
.loadmore{text-align:center;color:var(--text2);padding:18px 0 40px;font-size:.9rem}
.share-modal{max-width:440px;text-align:center}
.share-modal h2{margin-bottom:14px}
.share-preview{width:100%;max-width:300px;margin:0 auto 18px;border-radius:14px;overflow:hidden;border:1px solid var(--line);background:var(--bg)}
.share-preview img{display:block;width:100%;height:auto}
/* Both buttons are the same box. .modal .btn-primary makes a primary button
   full width with a top margin, which is right for a form and wrong for a
   pair side by side, so it is undone here. */
.share-actions{display:flex;gap:10px;align-items:stretch}
.share-actions .btn{flex:1 1 0;width:auto;margin:0;text-align:center;padding:12px 0;line-height:1.2;min-height:0}
.share-busy{color:var(--text2);font-size:.9rem;padding:40px 0}
.a2hs{position:fixed;left:12px;right:12px;bottom:12px;z-index:55;display:flex;align-items:center;gap:12px;background:var(--card);border:1px solid var(--line);border-radius:16px;box-shadow:0 12px 40px rgba(0,0,0,.22);padding:12px 14px;max-width:520px;margin:0 auto}
.a2hs-icon{width:42px;height:42px;border-radius:11px;flex-shrink:0}
.a2hs-txt{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.a2hs-txt strong{font-size:.94rem}
.a2hs-txt span{font-size:.82rem;color:var(--text2);line-height:1.35}
.a2hs-acts{display:flex;align-items:center;gap:4px;flex-shrink:0}
.a2hs .btn{padding:9px 16px;font-size:.9rem}
.a2hs-x{color:var(--text2);font-size:1.35rem;line-height:1;padding:4px 8px;border-radius:8px}
.a2hs-x:hover{background:var(--line);color:var(--text)}
@media (max-width:900px){.a2hs{bottom:74px}}
.toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);background:var(--text);color:var(--bg);padding:10px 20px;border-radius:999px;font-size:.9rem;z-index:60;opacity:0;transition:opacity .25s;pointer-events:none;max-width:calc(100vw - 28px);white-space:nowrap}
/* Clears the bottom bar, same as the install banner. */
@media (max-width:900px){ .toast{bottom:78px} }
.toast.show{opacity:1}

/* ---------- Skeletons ---------- */
/* One primitive. Every shape is sizes on top of it. The bar tints from the
   page's own text color, so it inverts with the theme by itself: no media
   query, and no way to paint white bars onto a white page when the OS
   preference and the chosen theme disagree. */
.kb{position:relative;overflow:hidden;border-radius:7px;background:#e4e7ec;background:color-mix(in srgb, currentColor 11%, transparent)}
.kb::after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,rgba(255,255,255,.34),transparent);animation:kshine 1.25s ease-in-out infinite}
@keyframes kshine{100%{transform:translateX(100%)}}
@media (prefers-reduced-motion: reduce){ .kb::after{animation:none} }
.kskel{pointer-events:none}
.krow{display:flex;align-items:center;gap:11px}
.kcol{flex:1;min-width:0;display:flex;flex-direction:column;gap:7px}
/* Boot outline: the real layout classes, so the shapes land where the content
   will. Shown only while a cached session says this reader is signed in. */
#boot{display:none}
html.sess-pending #boot{display:block}
#boot main.wrap{padding-top:70px}
@media (max-width:900px){ #boot main.wrap{padding-top:64px} }
#boot .kn{display:flex;align-items:center;gap:12px;padding:11px 13px}
@media (max-width:900px){ #boot .kn{flex-direction:column;gap:5px;padding:6px 4px;flex:1} #boot .boot-logo{display:none} }
