
:root{
  /* Lifted wholesale from the admin site so the two read as one project. The two panel
     steps are deliberately far apart: when they were close, a nested surface looked like a
     rendering artefact rather than a level. */
  --bg:#0b0d11; --panel:#14181f; --panel2:#1b212a; --line:#262d38; --line2:#333c4a;
  --fg:#e8ebf1; --dim:#8892a3; --accent:#5aa2ff; --accent2:#7c6cff;
  /* The brand red. Deliberately NOT --bad: that one means "something went wrong" and is
     already spoken for by NSFW tags and failed recoveries. This is a half-step warmer and
     pinker, which keeps it in the same saturation register as the blue and the violet —
     red→violet→blue is a continuous sweep, so the r reads as one end of the existing
     gradient rather than a colour pasted on top of it. */
  --brandr:#ff5a6e;
  --good:#3fb950; --bad:#f2585b; --warn:#d29922; --radius:12px;
  --shadow:0 1px 2px rgba(0,0,0,.4), 0 8px 24px -12px rgba(0,0,0,.7);
  --shadow-lift:0 2px 6px rgba(0,0,0,.45), 0 18px 40px -14px rgba(0,0,0,.85);
  --ease:cubic-bezier(.2,.7,.3,1);
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--fg);
  font:15px/1.5 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  -webkit-font-smoothing:antialiased;
  /* Two very faint accent washes anchored along the top. Flat #0b0d11 across a wide
     window reads as dead space; this gives the page a light source without becoming a
     decoration you notice. Fixed so it doesn't slide while scrolling. */
  /* A third, fainter wash in the brand red sits just under the wordmark's corner, so the
     r has something to belong to instead of being the only warm thing on a cool page.
     Half the opacity of the others — at full strength it tints the whole header pink. */
  background-image:
    radial-gradient(520px 300px at 3% -10%, rgba(255,90,110,.055), transparent 72%),
    radial-gradient(900px 500px at 12% -8%, rgba(90,162,255,.07), transparent 70%),
    radial-gradient(800px 460px at 88% -12%, rgba(124,108,255,.06), transparent 70%);
  background-attachment:fixed;
}
/* Anything that moves, moves the same way. */
a,button,.chip,.tile,.seg .k,nav a,.gal figure{
  transition:background-color .16s var(--ease), border-color .16s var(--ease),
             color .16s var(--ease), transform .16s var(--ease), box-shadow .16s var(--ease)}
/* Keyboard focus must never be invisible just because hover looks good. */
a:focus-visible,button:focus-visible,input:focus-visible,.tile:focus-visible{
  outline:2px solid var(--accent);outline-offset:2px;border-radius:6px}
a{color:var(--accent);text-decoration:none}
button,input{font:inherit;color:inherit}

/* ONE BASE STYLE FOR EVERY FORM CONTROL.
   Every context used to style its own — .auth input, .panel input, .removal select — so a
   control added anywhere else inherited `color: inherit` from the rule above and kept the
   browser's WHITE background: the page's light text on white, unreadable, which is exactly
   what happened to the member search. A base rule means a new input is right by default and
   a context only overrides what is genuinely different about it.

   Colours come from the tokens the wordmark is built from: --accent is the blue of the
   `-cover`, --accent2 the violet it sits next to, --brandr the red of the `r`. */
input,select,textarea{
  background:var(--panel);
  /* White, not --fg. The body text is #e8ebf1, which is right for reading a paragraph
     against the page but sits a shade low against the darker panel a field is drawn on —
     and what somebody has just typed is the one thing on screen they need to be certain
     they read correctly. */
  color:#fff;
  border:1px solid var(--line);
  border-radius:9px;
  padding:10px 12px;
  font:inherit;
  /* Without this, a select on a dark ground is drawn by the platform in ITS colours —
     which on most systems means the light theme, whatever the page says. */
  color-scheme:dark;
}
/* --dim, not --dimmer: a placeholder is instruction text, and at 3.8:1 the fainter token
   was below the threshold for anything but large type. */
input::placeholder,textarea::placeholder{color:var(--dim);opacity:1}
input:focus,select:focus,textarea:focus{
  outline:none;
  border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(90,162,255,.16);
}
/* A checkbox is not a text field and should not get a text field's box. */
input[type=checkbox],input[type=radio]{
  padding:0;border-radius:4px;accent-color:var(--accent);
}
input[type=file]{padding:8px;color:var(--dim)}
button{background:none;border:0;cursor:pointer}

/* The header drops in once on load and then stays put. Its children arrive just behind
   it, so the bar settles before its contents do rather than everything appearing at once. */
header{position:sticky;top:0;z-index:20;background:rgba(11,13,17,.82);
  animation:drop .5s var(--ease) both;
  transition:background-color .3s var(--ease),box-shadow .3s var(--ease),
             border-color .3s var(--ease)}
/* .hgroup is now a wrapper, so the stagger has to reach INTO it — targeting only direct
   children of .hbar would animate the group as one block and skip the brand and nav. */
.hbar>*,.hgroup>*{animation:slide .44s var(--ease) backwards}
.hspace{animation:none}
.brand{animation-delay:.08s}
nav{animation-delay:.14s}
#q{animation-delay:.2s}
/* Scrolled state. The bar is translucent over the page, so once content is passing behind
   it, it needs to sit more firmly on top — deeper tint, a real shadow, a brighter rule. */
header.stuck{background:rgba(11,13,17,.94);border-bottom-color:var(--line2);
  box-shadow:0 1px 0 rgba(255,255,255,.04),0 10px 30px -18px #000}
header.stuck .hbar{padding-top:8px;padding-bottom:8px}
.hbar{transition:padding .25s var(--ease)}
/* Base state. The blur is unconditional — it is what makes the bar readable over a
   scrolling grid at all; only the tint, rule and shadow change when stuck. */
header{backdrop-filter:blur(14px) saturate(1.3);
  -webkit-backdrop-filter:blur(14px) saturate(1.3);
  border-bottom:1px solid var(--line);
  box-shadow:0 1px 0 rgba(255,255,255,.03),0 8px 24px -20px #000}
/* The gap has to stay symmetric on both sides of the search field — .hgroup and .hspace
   are equal-flex, so an uneven gap would push the field off the centreline. */
.hbar{display:flex;gap:40px;align-items:center;padding:10px 16px;max-width:1500px;
  margin:0 auto;flex-wrap:wrap}
/* Stacked: wordmark, tagline underneath. A column rather than a baseline-aligned pair, so
   the tagline hangs off the wordmark instead of competing with the nav for the same row. */
/* flex:0 0 auto — the wordmark is a logo and never gets compressed to make room for
   anything else. Without it the brand is just another flex item and the r, the -cover and
   the strapline get squeezed apart as the window narrows. */
.brand{position:relative;display:inline-flex;flex-direction:column;
  align-items:flex-start;gap:1px;line-height:1.12;flex:0 0 auto}
.wm{font-weight:700;letter-spacing:.5px;font-size:17px;display:inline-flex;
  white-space:nowrap}
.brand em{white-space:nowrap}
.wm b{font-weight:inherit;-webkit-background-clip:text;background-clip:text;
  color:transparent}
/* The r. Its own short gradient rather than a flat fill — a solid swatch next to the
   sheening half would look like a different material. */
/* background-IMAGE, not the `background` shorthand. The shorthand resets background-clip
   to border-box, which un-clips the text and paints the gradient as a solid rectangle with
   invisible letters on top of it. Every "my gradient text turned into a box" is this. */
.wm b.r{background-image:linear-gradient(150deg,#ff8494,var(--brandr) 55%,#e8455f);
  text-shadow:0 0 14px rgba(255,90,110,.30)}
/* The gradient is drawn at 220% and slid across, so the wordmark has a slow sheen
   travelling through it rather than sitting still. 9s because anything quicker reads as
   a loading indicator — this is meant to be noticed once and then ignored. It now starts
   on the brand red, so the sweep runs red → violet → blue and the r is where the gradient
   begins rather than a separate mark beside it. */
.wm b.c{background-image:linear-gradient(92deg,var(--brandr),var(--accent2) 30%,
    var(--accent) 62%,var(--accent2));
  background-size:220% 100%;animation:sheen 9s linear infinite}
.brand:hover .wm b.c{animation-duration:2.2s}
.brand em{font-style:normal;color:var(--dim);font-weight:400;font-size:10.5px;
  letter-spacing:.7px;text-transform:uppercase;opacity:0;
  animation:fade .5s ease .5s forwards}
/* Brand and nav travel together on the left; the balancer opposite them is what lets the
   search sit on the page's centreline instead of drifting with the wordmark's width. */
/* min-width:auto, NOT 0. With min-width:0 a flex item is allowed to shrink below its own
   content, which is exactly how "Subreddits" ended up sitting under the search box instead
   of pushing it away. Letting the group keep its intrinsic width means the layout runs out
   of room honestly, and the breakpoint below catches it. */
.hgroup{display:flex;align-items:center;gap:46px;flex:1 1 0;min-width:max-content}
.hspace{flex:1 1 0;min-width:0}
nav{display:flex;gap:4px;flex:0 0 auto}
nav a{padding:6px 12px;border-radius:999px;color:var(--dim);position:relative}
nav a.on{background:var(--panel2);color:var(--fg);box-shadow:inset 0 0 0 1px var(--line)}
nav a:hover{color:var(--fg);background:rgba(255,255,255,.04);transform:translateY(-1px)}
nav a:active{transform:translateY(0)}
/* The active pill gets a hairline of accent underneath it. Drawn as a pseudo-element that
   scales out from the centre, so moving between tabs reads as the marker travelling
   rather than two separate things blinking. */
nav a::after{content:'';position:absolute;left:12px;right:12px;bottom:1px;height:2px;
  border-radius:2px;background:linear-gradient(90deg,var(--accent),var(--accent2));
  transform:scaleX(0);transition:transform .26s var(--ease);
  box-shadow:0 0 10px -1px rgba(90,162,255,.9)}
nav a.on::after{transform:scaleX(1)}
/* Fixed basis rather than a min-width that grows on focus: the field is now the page's
   centre mark, and something that changes width would shift the whole bar's balance. */
#q{flex:0 1 330px;min-width:160px;background:var(--panel);border:1px solid var(--line);
  border-radius:999px;padding:8px 16px;outline:none;text-align:center;
  transition:border-color .18s var(--ease),box-shadow .18s var(--ease),
             background-color .18s var(--ease)}
#q:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(90,162,255,.15);
  background:var(--panel2);text-align:left}

main{max-width:1500px;margin:0 auto;padding:20px 16px 60px}
h1{font-size:22px;margin:0 0 4px;letter-spacing:-.2px}
h1 .u{color:var(--dim);font-weight:400}
.sub{color:var(--dim);font-size:14px;margin:0 0 20px}
.crumb{color:var(--dim);font-size:13px;margin:0 0 12px}

/* The lit-card treatment: a one-pixel highlight along the top edge is what makes a dark
   surface read as lit from above instead of as a flat rectangle. */
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px;margin-bottom:18px;box-shadow:var(--shadow);position:relative}
.card::before{content:'';position:absolute;inset:0 0 auto;height:1px;
  border-radius:var(--radius) var(--radius) 0 0;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.07) 18%,
    rgba(255,255,255,.07) 82%,transparent)}
h2{font-size:13px;margin:0 0 12px;letter-spacing:.5px;text-transform:uppercase;color:var(--dim)}

.note{border-left:3px solid var(--warn);background:rgba(210,153,34,.09);
  border:1px solid rgba(210,153,34,.30);border-left-width:3px;border-radius:10px;
  padding:11px 14px;margin:0 0 20px;font-size:13.5px;color:var(--dim)}
.note .h{display:block;font-weight:700;color:var(--warn);margin-bottom:3px}
.note b{color:var(--fg)}
.note code{background:rgba(0,0,0,.35);padding:1px 6px;border-radius:5px;font-size:12.5px}

.stats{font-size:12.5px;color:var(--dim);display:flex;gap:14px;flex-wrap:wrap;
  align-items:center;margin:0 0 20px}
.stats b{color:var(--fg);font-weight:600;font-variant-numeric:tabular-nums;font-size:15px}
.stats>span{display:inline-flex;gap:6px;align-items:center;background:var(--panel);
  border:1px solid var(--line);border-radius:999px;padding:6px 14px;box-shadow:var(--shadow)}

.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(190px,1fr))}
.tile{background:var(--panel);border:1px solid var(--line);border-radius:11px;
  overflow:hidden;display:block;color:inherit;box-shadow:var(--shadow)}
.tile:hover{border-color:var(--line2);transform:translateY(-2px);box-shadow:var(--shadow-lift)}
.tile .ph{aspect-ratio:1/1;background:#0a0c0f;display:flex;align-items:center;
  justify-content:center;overflow:hidden;position:relative}
.tile img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .35s var(--ease);filter:saturate(.94)}
.tile:hover img{transform:scale(1.03)}
.tile:hover .meta .t{color:var(--accent)}
.tile .meta{padding:9px 11px}
.tile .meta .t{font-size:13.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.tile .meta .s{font-size:12px;color:var(--dim);display:flex;gap:8px;flex-wrap:wrap;
  align-items:center;margin-top:2px}

/* The gallery. Same lift as the admin site: the tile you point at comes forward and its
   picture pushes in slightly under the frame. Small numbers on purpose — at this size
   anything more turns a wall of thumbnails into a fairground. */
.gal{display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(170px,1fr))}
.gal figure{margin:0;position:relative;background:#0a0c0f;border-radius:10px;
  overflow:hidden;box-shadow:var(--shadow);isolation:isolate}
.gal figure:hover,.gal figure:focus-within{transform:translateY(-2px);
  box-shadow:var(--shadow-lift);z-index:2}
.gal figure .ph{width:100%;aspect-ratio:1/1;display:flex;align-items:center;
  justify-content:center}
.gal figure img{width:100%;aspect-ratio:1/1;object-fit:cover;display:block;
  transition:transform .3s var(--ease),filter .25s var(--ease);filter:saturate(.97)}
.gal figure:hover img{transform:scale(1.03);filter:saturate(1.03)}
/* Ring drawn on top of the image so the zoom can't creep past the rounded corner. */
.gal figure::after{content:'';position:absolute;inset:0;border-radius:10px;
  pointer-events:none;box-shadow:inset 0 0 0 1px rgba(255,255,255,.05);
  transition:box-shadow .16s var(--ease)}
.gal figure:hover::after{box-shadow:inset 0 0 0 1px rgba(90,162,255,.5)}
.gal figcaption{position:absolute;left:0;right:0;bottom:0;padding:22px 9px 8px;
  font-size:11.5px;
  background:linear-gradient(transparent,rgba(0,0,0,.55) 35%,rgba(0,0,0,.92));
  opacity:0;transform:translateY(4px);
  transition:opacity .18s var(--ease),transform .18s var(--ease)}
.gal figure:hover figcaption,.gal figure:focus-within figcaption{opacity:1;transform:none}
.gal figcaption .t{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gal figcaption .s{display:block;color:var(--dim);margin-top:2px}
.gal figure.nsfw::before{content:'NSFW';position:absolute;top:6px;left:6px;z-index:1;
  background:rgba(242,88,91,.85);color:#fff;border-radius:6px;padding:1px 6px;
  font-size:10.5px;font-weight:700;letter-spacing:.4px}
.badge{position:absolute;top:6px;right:6px;background:rgba(0,0,0,.65);border-radius:6px;
  padding:1px 6px;font-size:11px;z-index:1}

.tag{font-size:11px;padding:2px 8px;border-radius:99px;background:#1d3a5c;color:#9fd0ff}
.tag.n{background:#3a1420;color:#ffb3b5}

/* The account report. The meter is the one number people actually read. */
.rrow{display:flex;flex-wrap:wrap;gap:22px;margin-bottom:4px}
.ritem .v{font-size:20px;font-weight:650;font-variant-numeric:tabular-nums}
.ritem .l{color:var(--dim);font-size:12px;margin-top:1px}
.ritem.ok .v{color:var(--good)} .ritem.bad .v{color:var(--bad)}
.meter{height:6px;background:#0c0f13;border-radius:99px;overflow:hidden;
  margin:12px 0 0;display:flex;box-shadow:inset 0 0 0 1px rgba(255,255,255,.04)}
.meter i{display:block;height:100%;width:0;transition:width .85s var(--ease) .18s}
.meter i.ok{background:linear-gradient(90deg,var(--accent),var(--accent2));
  box-shadow:0 0 12px -2px rgba(90,162,255,.7)}
.meter i.bad{background:var(--bad)}
.meter i.other{background:var(--line2)}
.rhead{color:var(--dim);font-size:12.5px;margin-top:10px;font-style:italic}

.seg{display:flex;border:1px solid var(--line);border-radius:8px;overflow:hidden;
  margin:0 0 14px}
.seg .k{background:var(--panel2);border:0;border-right:1px solid var(--line);
  padding:8px 14px;color:var(--dim);white-space:nowrap}
.seg .k:last-child{border-right:0}
.seg .k:hover{color:var(--fg)}
.seg .k.on{background:var(--accent);color:#06121f;font-weight:600}
.seg .k b{font-weight:inherit;opacity:.6;margin-left:5px}

/* Subreddit chips on a profile. A profile can span dozens, so the bar scrolls rather than
   pushing the gallery off the screen. */
.chips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 14px;max-height:104px;overflow-y:auto}
.chip{background:#0a0c0f;border:1px solid var(--line);color:var(--dim);border-radius:999px;
  padding:3px 11px;font-size:12px;white-space:nowrap}
.chip:hover{color:var(--fg);border-color:var(--line2);background:#131820}
.chip:active{transform:translateY(1px)}
.chip.on{border-color:var(--accent);color:var(--fg);background:rgba(90,162,255,.14);
  box-shadow:0 0 0 1px rgba(90,162,255,.25),0 4px 14px -8px rgba(90,162,255,.9)}
.chip b{color:var(--fg);font-weight:600}

/* The pager. Links, not buttons — the page number belongs in the URL, so a shared link
   opens the page that was shared and the back button walks pages instead of leaving. */
.pager{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:26px 0 8px;
  padding-top:18px;border-top:1px solid var(--line)}
.pg{display:inline-flex;align-items:center;justify-content:center;min-width:34px;
  height:34px;padding:0 10px;border:1px solid var(--line);border-radius:8px;
  background:var(--panel2);color:var(--dim);font-size:13px;font-variant-numeric:tabular-nums}
.pg:hover{color:var(--fg);border-color:var(--line2);background:#131820}
.pg.on{border-color:var(--accent);color:var(--fg);background:rgba(90,162,255,.14);
  font-weight:600}
.pg.off{opacity:.35}
.pager .gap{color:var(--dim);padding:0 2px}
.pgi{color:var(--dim);font-size:12.5px;margin-left:auto}
@media (max-width:560px){.pgi{margin-left:0;width:100%;order:9}}
.empty{color:var(--dim);padding:56px 0;text-align:center}
.empty h2{color:var(--fg);font-weight:600;font-size:16px;margin:0 0 6px;
  text-transform:none;letter-spacing:0}
footer{max-width:1500px;margin:0 auto;padding:0 16px 40px;color:var(--dim);font-size:12px}

/* ---- motion --------------------------------------------------------------------------
   The stagger index is CAPPED by the renderer: a profile here can be 800 files, and an
   uncapped 22ms step would put the last one eighteen seconds away. Everything past the cap
   arrives together, which is fine — it is far below the fold. */
@keyframes rise{from{opacity:0;transform:translateY(10px) scale(.985)}
  to{opacity:1;transform:none}}
@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes slide{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
@keyframes shimmer{from{background-position:-380px 0}to{background-position:380px 0}}
@keyframes breathe{0%,100%{opacity:.34}50%{opacity:.6}}
@keyframes drop{from{transform:translateY(-100%)}to{transform:none}}
@keyframes sheen{to{background-position:220% 0}}
main{animation:fade .26s var(--ease) both}
.tile,.gal figure{animation:rise .42s var(--ease) backwards;
  animation-delay:calc(var(--i,0) * 22ms)}
h1{animation:slide .34s var(--ease) both}
.sub,.crumb{animation:slide .34s var(--ease) .04s both}
.note{animation:slide .4s var(--ease) .02s both}
.stats>span{animation:rise .4s var(--ease) backwards;
  animation-delay:calc(var(--i,0) * 45ms)}
.card{animation:rise .44s var(--ease) .06s both}
.seg .k:active{transform:scale(.97)}
/* The placeholder breathes very slightly — enough that the grid doesn't read as a wall of
   dead boxes while there is no media server, not enough to be a distraction. */
.ph svg{animation:breathe 3.4s ease-in-out infinite;color:var(--line2)}

/* Skeletons while a page loads. Better than the word "Loading" because the layout doesn't
   jump when the real tiles replace them. */
.sk{background:var(--panel);border:1px solid var(--line);border-radius:11px;
  overflow:hidden;box-shadow:var(--shadow);animation:fade .2s both}
.sk .b{background:linear-gradient(90deg,var(--panel2) 0%,#232a35 50%,var(--panel2) 100%);
  background-size:380px 100%;animation:shimmer 1.25s linear infinite}
.sk .b1{aspect-ratio:1/1}
.sk .b2{height:11px;margin:12px 11px 0;border-radius:4px;width:58%}
.sk .b3{height:9px;margin:9px 11px 14px;border-radius:4px;width:38%}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition:none!important;animation:none!important}
  .tile:hover,.gal figure:hover{transform:none}
  .tile:hover img,.gal figure:hover img{transform:none}
  .meter i{transition:none!important}
  #q:focus{background:var(--panel)}
  nav a:hover{transform:none}
  nav a::after{transition:none}
  .brand em{opacity:1}
}
/* A side-by-side window is the case that broke: too narrow for a centred search, too wide
   to be treated as a phone. Perfect centring is the first thing to give up — below this the
   balancer goes and the search simply takes the space left over. */
@media(max-width:1080px){
  .hbar{gap:22px}
  .hgroup{gap:26px}
  .hspace{display:none}
  #q{flex:1 1 180px;text-align:left}
}
@media(max-width:780px){
  /* Two rows: brand and nav on the first, search filling the second. */
  .hbar{gap:10px}
  .hgroup{flex:1 1 100%;min-width:0;gap:16px;justify-content:space-between}
  #q{flex:1 1 100%}
  /* The nav scrolls rather than wrapping, so the bar keeps a predictable height. The brand
     is flex:0 0 auto above, so this only ever eats into the nav. */
  nav{overflow-x:auto;scrollbar-width:none}
  nav::-webkit-scrollbar{display:none}
}
@media(max-width:460px){
  .hgroup{flex-wrap:wrap;gap:10px}
  nav{width:100%}
}

/* ======================================================================================
   ACCOUNTS
   Everything below belongs to the half of the site that knows who you are. It reuses the
   panel, line and accent tokens from the top of this file rather than introducing a
   second palette — a signed-in control must read as part of the same object as the tile
   it sits on, not as a widget bolted to it.
   ====================================================================================== */

/* ---- the forms ---- */
.auth{max-width:420px;margin:min(9vh,90px) auto;animation:slide .4s var(--ease) backwards}
.auth h1{margin:0 0 6px}
.auth .lede{color:var(--dim);margin:0 0 22px;line-height:1.5}
.auth label{display:block;margin:14px 0 6px;font-size:13px;color:var(--dim)}
.auth input{width:100%;padding:11px 13px;background:var(--panel);border:1px solid var(--line);
  border-radius:9px;color:var(--fg)}
.auth input:focus{border-color:var(--accent);outline:none;
  box-shadow:0 0 0 3px rgba(90,162,255,.14)}
.auth .go{width:100%;margin-top:20px;padding:11px;border-radius:9px;font-weight:640;
  background:var(--accent);color:#08121f;border:0}
.auth .go:hover{filter:brightness(1.08)}
.auth .go[disabled]{opacity:.55;cursor:default;filter:none}
.auth .alt{margin-top:18px;color:var(--dim);font-size:14px;text-align:center}
.auth .alt a{margin-left:4px}
/* A form's answer must never move the fields it belongs to — a message appearing above
   the button pushes it out from under a finger already on the way down. Reserved space. */
.msg{min-height:20px;margin-top:14px;font-size:14px;line-height:1.45}
.msg.bad{color:var(--bad)}
.msg.good{color:var(--good)}
.hint{color:var(--dim);font-size:12.5px;margin-top:5px}

/* ---- the bell and the account button ---- */
.hact{display:flex;align-items:center;gap:6px;flex:0 0 auto}
.iconbtn{position:relative;display:grid;place-items:center;width:36px;height:36px;
  border-radius:9px;color:var(--dim);border:1px solid transparent}
.iconbtn:hover{background:var(--panel2);color:var(--fg);border-color:var(--line)}
.iconbtn.on{color:var(--fg);background:var(--panel2);border-color:var(--line)}
/* The count sits ON the bell rather than beside it, so the header's height never changes
   between having notifications and not. */
.dot{position:absolute;top:2px;right:2px;min-width:16px;height:16px;padding:0 4px;
  border-radius:999px;background:var(--brandr);color:#fff;font-size:10.5px;font-weight:700;
  line-height:16px;text-align:center;box-shadow:0 0 0 2px var(--bg)}
.who{display:flex;align-items:center;gap:8px;padding:5px 11px 5px 6px;border-radius:999px;
  border:1px solid var(--line);background:var(--panel);color:var(--fg);font-size:13.5px}
.who:hover{border-color:var(--line2);background:var(--panel2)}
.who .av{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;
  font-size:11.5px;font-weight:700;color:#08121f;
  background:linear-gradient(135deg,var(--accent),var(--accent2))}

.seg.nsfwseg{margin-top:8px}
.seg.nsfwseg .k.on.n-only{border-color:var(--bad);color:var(--bad);
  background:rgba(242,88,91,.09)}
.chipnote{font-family:ui-monospace,monospace;font-size:11.5px;color:var(--dim);
  align-self:center;margin-left:4px}
/* The chosen chips read as chosen, not merely hovered — several can be on at once now, so
   the difference has to survive being repeated across a row. */
.chip.on{border-color:var(--accent);color:var(--accent);background:rgba(90,162,255,.1)}

/* A tile whose profile has left the catalogue — taken down, or not yet uploaded. Kept
   visible rather than hidden: somebody starred it, and silently dropping it from their own
   list is worse than saying where it went. */
.tile.gone{opacity:.55}
.tile.gone .ph{filter:grayscale(1)}
.s .following{color:var(--accent)}

/* ---- members ---- */
.face{width:26px;height:26px;border-radius:50%;object-fit:cover;flex:0 0 auto;
  display:grid;place-items:center;font-size:12px;font-weight:700;color:#08121f;
  background:linear-gradient(135deg,var(--accent),var(--accent2))}
.face.big{width:84px;height:84px;font-size:32px}
.mhead{display:flex;gap:20px;align-items:flex-start;flex-wrap:wrap;margin-bottom:6px}
.mwho{flex:1;min-width:240px}
.mwho h1{margin:0 0 4px;display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.mbio{white-space:pre-wrap;word-break:break-word;line-height:1.55;margin:8px 0 0;
  max-width:60ch}
.avrow{display:flex;gap:18px;align-items:flex-start;flex-wrap:wrap;margin-bottom:14px}
#biof textarea{width:100%;max-width:520px;padding:10px 12px;background:var(--bg);
  border:1px solid var(--line);border-radius:9px;color:var(--fg);font:inherit;
  line-height:1.5;resize:vertical}
#biof textarea:focus{border-color:var(--accent);outline:none}

.shead{font-family:inherit;font-size:13px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--dim);margin:22px 0 10px;font-weight:600}
.subhits{margin-bottom:20px}
.subhits .chip b{color:var(--dim);font-weight:600;margin-left:5px}

/* a member's own comments, on their page */
.hist{margin-top:28px}
.hist h2{font-size:19px;margin:0 0 4px}
.histlist{display:flex;flex-direction:column;gap:2px;margin-top:12px}
.histrow{display:flex;flex-direction:column;gap:3px;padding:11px 13px;border-radius:10px;
  border:1px solid transparent;color:var(--fg)}
.histrow:hover{background:var(--panel);border-color:var(--line)}
.hbody{white-space:pre-wrap;word-break:break-word;line-height:1.5;font-size:14.5px}
.hmeta{color:var(--dim);font-size:12.5px}
.warnline{color:var(--warn)}

/* conversations */
.convo{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:11px;
  border:1px solid transparent;color:var(--fg)}
.convo:hover{background:var(--panel);border-color:var(--line)}
.convo.unseen{background:rgba(90,162,255,.06);border-color:rgba(90,162,255,.18)}
.ctext{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.cname{font-weight:620;font-size:14.5px}
.cprev{color:var(--dim);font-size:13px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.dot.inline{position:static;display:inline-block;margin-left:4px;box-shadow:none}

/* the thread itself */
.thread{display:flex;flex-direction:column;gap:9px;max-height:58vh;overflow-y:auto;
  padding:4px 2px 10px}
.tbar{display:flex;align-items:center;gap:9px;padding-bottom:8px;
  border-bottom:1px solid var(--line);margin-bottom:6px}
.tbar a{font-weight:620}
.tbar .btn{margin-left:auto}
.tbar .btn + .btn{margin-left:0}
.bubble{max-width:min(74%,560px);padding:9px 13px;border-radius:14px;
  border:1px solid var(--line);background:var(--panel)}
.bubble.mine{align-self:flex-end;background:rgba(90,162,255,.13);
  border-color:rgba(90,162,255,.28)}
.btext{white-space:pre-wrap;word-break:break-word;line-height:1.5;font-size:14.5px}
.bwhen{color:var(--dim);font-size:11.5px;margin-top:3px}

.found{margin-top:10px;max-height:46vh;overflow-y:auto;display:flex;
  flex-direction:column;gap:2px}
.foundrow{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:9px;
  color:var(--fg);border:1px solid transparent}
.foundrow:hover{background:var(--panel2);border-color:var(--line)}
.fname{font-weight:600;flex:1;min-width:0}

/* the report sheet, which reuses the lightbox backdrop */
.sheet{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  padding:22px 24px;max-width:460px;width:calc(100% - 32px);margin:auto;
  box-shadow:var(--shadow-lift)}
.sheet h2{margin:0 0 4px;font-size:19px}
.sheet .lede{color:var(--dim);font-size:14px;margin:0 0 14px;line-height:1.5}
.sheet label{display:block;margin:12px 0 6px;font-size:13px;color:var(--dim)}
.sheet input,.sheet select,.sheet textarea{width:100%;background:var(--bg)}
.sheet textarea{line-height:1.5;resize:vertical}
.lb.on:has(.sheet){display:grid;place-items:center;grid-template-rows:1fr}

/* ---- the admin's removal inbox ----
   Laid out as messages rather than as table rows: each one is a person writing a paragraph,
   and a table would cut it into a cell. Unanswered ones carry a warm rule down the side, so
   the pile can be read at a glance without any counting. */
.msgs{display:flex;flex-direction:column;gap:12px;margin-top:14px}
.msg2{border:1px solid var(--line);border-left:3px solid var(--line2);border-radius:10px;
  padding:14px 16px;background:var(--panel2)}
.msg2.unread{border-left-color:var(--brandr);background:rgba(255,90,110,.045)}
.msg2 header{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;margin-bottom:6px}
.msg2 .why{font-weight:620;font-size:14.5px}
.msg2 .when{color:var(--dim);font-size:12.5px;margin-left:auto}
.msg2 .state{font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  border:1px solid var(--line2);border-radius:5px;padding:1px 7px;color:var(--dim)}
.msg2 .state.s-new{color:var(--brandr);border-color:var(--brandr)}
.msg2 .state.s-done{color:var(--good);border-color:var(--good)}
.msg2 .about{color:var(--dim);font-size:13px;margin-bottom:8px}
.msg2 .said{margin:0 0 10px;padding:10px 13px;background:var(--bg);border-radius:8px;
  border:1px solid var(--line);white-space:pre-wrap;word-break:break-word;
  font-size:14.5px;line-height:1.55}
.msg2 .replyto{font-size:13px;color:var(--dim);margin-bottom:10px}
.msg2 .by{font-size:12.5px;color:var(--dim);margin-bottom:8px;font-style:italic}
.note.warn2{border-left:3px solid var(--warn);padding-left:14px}
.note.warn2 .h{color:var(--warn)}

.switch{display:flex;gap:9px;align-items:flex-start;padding:11px 12px;
  border:1px solid var(--line);border-radius:11px;background:var(--panel2);
  cursor:pointer;max-width:70ch}
/* Sized to sit with the text rather than tower over it, and the gap tightened to match:
   at 12px with a 20px box the tick floated in the middle of the row. */
.switch input[type=checkbox]{width:17px;height:17px;min-width:17px;max-width:17px;
  margin:2px 0 0;padding:0;flex:0 0 auto;accent-color:var(--accent)}
.switch span{font-size:14px;color:var(--dim);line-height:1.5}
.switch b{color:var(--fg)}
.msg2 .rsaid{margin:0 0 10px;padding:10px 13px;background:var(--bg);border-radius:8px;
  border:1px solid var(--line);white-space:pre-wrap;word-break:break-word;
  font-size:14.5px;line-height:1.55}

.tabs{display:flex;gap:4px;margin:14px 0 4px;border-bottom:1px solid var(--line)}
.tab{padding:8px 14px;border-radius:8px 8px 0 0;color:var(--dim);font-size:14px;
  font-weight:560;border:1px solid transparent;border-bottom:none;margin-bottom:-1px}
.tab:hover{color:var(--fg)}
.tab.on{color:var(--fg);background:var(--panel2);border-color:var(--line);
  border-bottom:1px solid var(--panel2)}
.tab b{font-weight:700;color:var(--brandr);margin-left:3px}
.tab.on b{color:var(--accent)}
.msg2.settled{opacity:.72}
.msg2.settled:hover{opacity:1}
.newdot{font-size:12px;background:var(--brandr);color:#fff;border-radius:999px;
  padding:2px 9px;margin-left:6px;vertical-align:middle;font-weight:700}

/* ---- the removal form ---- */
.removal{max-width:560px}
.removal .opt{color:var(--dim);font-weight:400}
.auth .opt{color:var(--dim);font-weight:400}
.linkish{color:var(--accent);text-decoration:underline;font:inherit;padding:0}
.qrwrap{display:inline-block;padding:10px;background:#fff;border-radius:10px;margin:8px 0 4px}
.qrwrap canvas{display:block;image-rendering:pixelated}
.bykey{margin-top:6px}
.bykey summary{cursor:pointer;color:var(--dim);font-size:13.5px}
.bykey summary:hover{color:var(--fg)}

.steps{margin:0 0 14px;padding-left:20px;max-width:62ch;line-height:1.6}
.steps li{margin:8px 0}
.secret{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:15px;
  letter-spacing:.06em;background:var(--panel2);border:1px solid var(--line2);
  border-radius:8px;padding:10px 13px;margin:7px 0 5px;user-select:all;word-break:break-all}
.codes{margin-top:14px;padding:14px 16px;border-radius:10px;
  border:1px solid var(--warn);background:var(--warn-soft);font-size:14px;line-height:1.55}
.codes pre{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:14px;
  background:var(--bg);border:1px solid var(--line);border-radius:8px;padding:12px 14px;
  margin:10px 0;user-select:all}

.pwgen{display:flex;align-items:center;gap:8px;margin-top:8px;flex-wrap:wrap}
.pwout{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;
  background:var(--panel2);border:1px solid var(--line);border-radius:7px;
  padding:5px 9px;user-select:all;word-break:break-all}
.auth .hint b{color:var(--warn);font-weight:600}
.removal .req{color:var(--warn);font-weight:400}
.removal textarea{width:100%;padding:11px 13px;background:var(--panel);
  border:1px solid var(--line);border-radius:9px;color:var(--fg);font:inherit;
  line-height:1.5;resize:vertical}
.removal textarea:focus{border-color:var(--accent);outline:none;
  box-shadow:0 0 0 3px rgba(90,162,255,.14)}
.removal .alt{text-align:left;font-size:13px;line-height:1.5}
.removal select{width:100%;padding:11px 13px;background:var(--panel);
  border:1px solid var(--line);border-radius:9px;color:var(--fg);font:inherit}
.removal select:focus{border-color:var(--accent);outline:none;
  box-shadow:0 0 0 3px rgba(90,162,255,.14)}
#foot a{color:var(--dim);text-decoration:underline;text-underline-offset:2px}
#foot a:hover{color:var(--accent)}

/* ---- the lightbox ----
   Fixed, full-viewport, above everything. The backdrop is nearly opaque rather than a light
   scrim: this is a viewer, and the page behind it should stop competing for attention. */
.lb{position:fixed;inset:0;z-index:100;display:none;background:rgba(6,8,11,.94);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}
/* minmax(0, 1fr), NOT 1fr.
   A `1fr` row still has an automatic MINIMUM size, so a picture taller than the window
   makes the row grow to fit it instead of shrinking to the space available — the caption
   gets pushed off the bottom and the image is cut off, which is why a tall photograph had
   to be opened in a new tab to be seen whole. minmax(0, …) is what lets the row actually
   shrink, and only then does max-height on the image mean anything. */
.lb.on{display:grid;grid-template-rows:minmax(0,1fr) auto;animation:fade .18s var(--ease)}
@keyframes fade{from{opacity:0}to{opacity:1}}
body.lbopen{overflow:hidden}
/* flex rather than grid+place-items: `min-height:0` on a flex child is the reliable way to
   say "you may be smaller than your contents", and the picture is the only child. */
.lbstage{display:flex;align-items:center;justify-content:center;min-height:0;
  overflow:hidden;padding:52px 60px 8px}
.lbstage img,.lbstage video{
  /* Both dimensions bounded, and neither forced — the picture shrinks to whichever of the
     two runs out first and keeps its proportions either way. */
  max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;
  border-radius:8px;background-size:cover;background-position:center;
  box-shadow:0 20px 60px -20px rgba(0,0,0,.9)}
.lbbar{display:flex;gap:16px;align-items:center;justify-content:space-between;
  flex-wrap:wrap;padding:14px 22px 20px;max-width:1200px;margin:0 auto;width:100%}
.lbmeta{min-width:0;flex:1}
.lbt{font-weight:600;font-size:15px;overflow-wrap:anywhere}
.lbs{color:var(--dim);font-size:12.5px;margin-top:3px}
.lbacts{display:flex;gap:8px;flex-wrap:wrap}
.lbclose,.lbnav{position:absolute;z-index:2;display:grid;place-items:center;
  width:42px;height:42px;border-radius:50%;color:#fff;background:rgba(255,255,255,.09);
  border:1px solid rgba(255,255,255,.16)}
.lbclose:hover,.lbnav:hover{background:rgba(255,255,255,.18)}
.lbclose{top:14px;right:16px}
.lbclose svg,.lbnav svg{width:19px;height:19px}
.lbnav{top:50%;transform:translateY(-50%)}
.lbnav.prev{left:14px}
.lbnav.next{right:14px;transform:translateY(-50%) rotate(180deg)}
.lbclose:focus-visible,.lbnav:focus-visible{outline:2px solid #fff;outline-offset:2px}
/* Only a signed-in viewer gets the pointer, because only they can open anything. */
.gal figure.openable{cursor:zoom-in}
@media(max-width:700px){
  .lbstage{padding:52px 10px 6px}
  .lbnav{width:36px;height:36px}
  .lbnav.prev{left:6px} .lbnav.next{right:6px}
}

/* ---- the sign-in prompt that stands in for a pager ---- */
.lock{margin:26px 0 0;padding:20px 22px;border-radius:var(--radius);
  border:1px solid var(--line);background:var(--panel);
  display:flex;gap:18px;align-items:center;flex-wrap:wrap;
  box-shadow:var(--shadow)}
.lock .lockmsg{flex:1;min-width:240px;color:var(--dim);line-height:1.55;font-size:14.5px}
.lock .lockmsg b{color:var(--fg);font-weight:640}
.lockacts{display:flex;gap:8px;flex-wrap:wrap}

/* ---- moderation ----
   The take-down control sits beside the star, same size and same corner behaviour, so a
   tile has one row of controls rather than a moderation feature bolted onto it. Red only
   on hover: an admin browsing their own library should not see a wall of red boxes. */
.hide{position:absolute;top:8px;right:46px;z-index:3;width:32px;height:32px;border-radius:9px;
  display:grid;place-items:center;color:#fff;background:rgba(11,13,17,.62);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  border:1px solid rgba(255,255,255,.14);opacity:0;transform:scale(.9)}
.tile:hover .hide,.gal figure:hover .hide,.hide:focus-visible{opacity:1;transform:none}
.hide:hover{background:rgba(242,88,91,.9);border-color:var(--bad)}
.hide svg{width:16px;height:16px}
.hide[disabled]{opacity:.5}
.role{font-family:ui-monospace,monospace;font-size:11.5px;padding:2px 8px;border-radius:5px;
  border:1px solid var(--line2);color:var(--dim)}
.role.r-admin{color:var(--accent);border-color:var(--accent)}
.role.r-banned{color:var(--bad);border-color:var(--bad)}
.role.r-owner{color:var(--brandr);border-color:var(--brandr)}
/* The owner's row is marked in the brand colour and pinned to the top by the query that
   builds the list, so it cannot be sorted or scrolled away from. */
.ownerrow{background:rgba(255,90,110,.05)}
.ownerrow td{border-bottom-color:var(--line2)}
.ownertag{font-family:ui-monospace,monospace;font-size:10px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--brandr);border:1px solid var(--brandr);
  border-radius:4px;padding:1px 5px;margin-left:5px;vertical-align:middle}
td.dim,.dim{color:var(--dim)}
.rowacts{display:flex;gap:6px;flex-wrap:wrap}
.ok2{color:var(--good)}
.pend{color:var(--warn);font-size:12px}
.tw{overflow-x:auto;border:1px solid var(--line);border-radius:9px;margin-top:12px}
.tw table{border-collapse:collapse;width:100%;font-size:13.5px}
.tw th,.tw td{padding:9px 12px;text-align:left;border-bottom:1px solid var(--line);
  vertical-align:top}
.tw th{font-size:11px;letter-spacing:.07em;text-transform:uppercase;color:var(--dim);
  background:var(--panel2);font-weight:600}
.tw tr:last-child td{border-bottom:0}
@media(max-width:780px){ .hide{opacity:1;transform:none} }

/* ---- Other sources panel, the NSFW switch, and the report ---- */
.card.sources .lede,.card.report .lede{color:var(--dim);margin:0 0 16px;font-size:14.5px;
  max-width:62ch;line-height:1.55}
/* High on the page now, above the pictures, so it is tightened up: this is a strip that
   says where else this person posts, not a panel to read. */
.card.sources{padding:14px 16px;margin-top:14px}
.card.sources h2{font-size:13px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--dim);margin:0 0 3px}
.card.sources .lede{margin:0 0 11px;font-size:13.5px}
.card.sources .srcitem{padding:11px 13px}
.card.sources .sname{font-size:14px}
.card.sources .scount{margin:1px 0 9px;font-size:12.5px}

/* ---- reddit link + profile score, in the h1 ---- */
/* ======================================================================================
   A MEMBER'S PAGE
   Steam's shape: a banner the person chose, their picture sitting over the seam of it, and
   their name and score on the banner rather than under it.

   Every background is a gradient and every effect is a keyframe. Nothing here downloads —
   a decorated profile weighs exactly what a bare one does, which is the whole reason these
   are presets and not uploads.
   ====================================================================================== */
.mbanner{position:relative;height:190px;border-radius:16px 16px 0 0;overflow:hidden;
  background:linear-gradient(135deg,#1b2130,#0d1017)}
.mbanner.custom{background-size:cover;background-position:center}
/* The wash that keeps the name readable. z-index so an effect layer can sit ABOVE it —
   rain whose splats land under a 94%-opaque gradient is rain nobody can see. The sash sits
   above both at z-index 2. */
.mbanner::after{content:'';position:absolute;inset:0;z-index:0;
  background:linear-gradient(to top,rgba(11,13,17,.94) 4%,rgba(11,13,17,.35) 46%,
    rgba(11,13,17,.1))}
.mb-midnight{background:linear-gradient(135deg,#0b1a3a,#123a6b 45%,#0a1226)}
.mb-ember   {background:linear-gradient(135deg,#3a0d14,#8f2233 45%,#2a0a10)}
.mb-violet  {background:linear-gradient(135deg,#241046,#6a3ad1 48%,#1a0c33)}
.mb-abyss   {background:linear-gradient(160deg,#04141a,#0b4a5c 40%,#03282f 70%,#020b0e)}
.mb-rose    {background:linear-gradient(135deg,#3d0f2b,#c2417f 50%,#2a0a1e)}
.mb-forest  {background:linear-gradient(135deg,#0a2416,#1f6b3a 45%,#07180f)}
.mb-gold    {background:linear-gradient(135deg,#3a2a05,#c9962a 48%,#241a03)}
.mb-ice     {background:linear-gradient(135deg,#0d2733,#5fb6d4 46%,#0a1a22)}
.mb-vapor   {background:linear-gradient(120deg,#2a1247,#d94f8c 38%,#4fc7e8 72%,#1a0f2e)}
.mb-static  {background:
  repeating-linear-gradient(115deg,#12151c 0 3px,#171b24 3px 6px),
  linear-gradient(135deg,#141821,#0c0f15)}

/* ---- effects: one layer over the banner, never over the text ---- */
.mfx{position:absolute;inset:0;pointer-events:none;z-index:1}
@media (prefers-reduced-motion:reduce){ .mfx{animation:none !important} }

.fx-drift{background-image:
  radial-gradient(2px 2px at 20% 30%,rgba(255,255,255,.55),transparent),
  radial-gradient(2px 2px at 72% 18%,rgba(255,255,255,.4),transparent),
  radial-gradient(1.6px 1.6px at 45% 68%,rgba(255,255,255,.45),transparent),
  radial-gradient(1.6px 1.6px at 88% 55%,rgba(255,255,255,.35),transparent),
  radial-gradient(2px 2px at 12% 78%,rgba(255,255,255,.3),transparent);
  background-size:340px 340px;animation:fxdrift 26s linear infinite}
@keyframes fxdrift{from{background-position:0 0}to{background-position:340px -340px}}

.fx-shimmer{background:linear-gradient(105deg,transparent 38%,rgba(255,255,255,.16) 50%,
  transparent 62%);background-size:280% 100%;animation:fxsheen 5.5s ease-in-out infinite}
@keyframes fxsheen{0%{background-position:130% 0}60%,100%{background-position:-30% 0}}

/* Rain, after arickle's CodePen (XKjMZY), adapted from a full viewport to a 190px banner.
   Three earlier attempts tiled a gradient, and every one of them failed the same way: a
   tiled background is a GRID. Change the spacing and it is a dense grid or a sparse grid,
   but the eye reads the regularity either way and rain is not regular.
   Real drops instead, each at its own random left, its own delay and its own duration, so
   no two fall together and the pattern never repeats. Each carries a stem — a hairline that
   fades in towards its head, which is what makes it read as falling rather than as a dash —
   and a splat that opens at the floor as the stem winks out.
   The falling element is `transform`, not `background-position`, so this animates on the
   compositor rather than repainting the banner sixty times a second. */
/* THE BACK ROW ONLY. The pen draws two: a front row at full strength and a back row that
   is fainter, lands short of the floor and is positioned from the right instead of the
   left. The back row alone is the one that reads as weather behind the person rather than
   rain in front of the camera, and on a 190px strip two rows is just clutter. Half opacity
   and a raised floor are what put it behind. */
.fx-rain{overflow:hidden;inset:0 0 26px 0;opacity:.5}
/* `rainfall`, NOT `drop`. The header's entrance animation was already called `drop`, and
   @keyframes live in one global namespace with the last definition winning — so naming
   these `drop` silently retargeted the header to translateY(var(--fall, 236px)) and pushed
   it 236px down the page on every route. Nothing in either rule mentioned the other. */
.fx-rain .drop{position:absolute;bottom:100%;width:11px;height:46px;pointer-events:none;
  animation:rainfall 1s linear infinite}
@keyframes rainfall{
  0%{transform:translateY(0)}
  /* Falls for three quarters of the cycle, then waits out the rest where it landed — that
     pause is the window the splat plays in. */
  75%{transform:translateY(var(--fall,236px))}
  100%{transform:translateY(var(--fall,236px))}}
.fx-rain .stem{width:1px;height:60%;margin-left:5px;
  background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(255,255,255,.42));
  animation:stem 1s linear infinite}
@keyframes stem{0%,65%{opacity:1} 75%,100%{opacity:0}}
.fx-rain .splat{width:11px;height:7px;border-top:2px dotted rgba(255,255,255,.42);
  border-radius:50%;opacity:1;transform:scale(0);animation:splat 1s linear infinite}
@keyframes splat{
  0%,80%{opacity:1;transform:scale(0)}
  90%{opacity:.5;transform:scale(1)}
  100%{opacity:0;transform:scale(1.5)}}

.fx-embers{background-image:
  radial-gradient(2.4px 2.4px at 18% 88%,rgba(255,150,60,.85),transparent),
  radial-gradient(2px 2px at 54% 92%,rgba(255,110,40,.7),transparent),
  radial-gradient(2.6px 2.6px at 78% 85%,rgba(255,180,80,.6),transparent),
  radial-gradient(1.8px 1.8px at 34% 95%,rgba(255,130,50,.7),transparent);
  background-size:300px 300px;animation:fxembers 9s linear infinite}
@keyframes fxembers{from{background-position:0 300px;opacity:0}
  18%{opacity:1} 82%{opacity:1} to{background-position:40px -60px;opacity:0}}

.fx-aurora{background:
  radial-gradient(60% 90% at 22% 10%,rgba(90,255,200,.28),transparent 60%),
  radial-gradient(50% 80% at 74% 4%,rgba(124,108,255,.3),transparent 62%);
  filter:blur(6px);animation:fxaurora 13s ease-in-out infinite alternate}
@keyframes fxaurora{from{transform:translate3d(-6%,0,0) scaleY(1)}
  to{transform:translate3d(7%,0,0) scaleY(1.22)}}

.fx-grid{background-image:
  linear-gradient(rgba(255,255,255,.09) 1px,transparent 1px),
  linear-gradient(90deg,rgba(255,255,255,.09) 1px,transparent 1px);
  background-size:34px 34px;animation:fxgrid 18s linear infinite;
  mask-image:linear-gradient(to top,#000,transparent 78%)}
@keyframes fxgrid{from{background-position:0 0}to{background-position:34px 34px}}

/* ---- avatar frames ---- */
/* The frame is a ring drawn AROUND the picture, so it has to be sized by the picture
   rather than given a size of its own — grid + place-items keeps the two concentric
   whatever the picture turns out to be. It had a fixed 112px against a .face.big of 84px,
   which left 14px of empty ring all the way round. */
.mface{position:relative;border-radius:50%;padding:4px;flex:0 0 auto;
  display:grid;place-items:center;line-height:0}
.mface > .face{display:block}
.fr-ring{box-shadow:0 0 0 3px var(--accent),0 0 0 7px rgba(90,162,255,.18)}
.fr-glow{box-shadow:0 0 0 2px rgba(255,255,255,.16),0 0 26px 4px rgba(124,108,255,.75)}
.fr-gradient{background:conic-gradient(from 0deg,var(--brandr),var(--accent2),
  var(--accent),var(--brandr));animation:frspin 7s linear infinite}
@keyframes frspin{to{transform:rotate(360deg)}}
/* The ring spins; the face inside it must not. */
.fr-gradient > *{animation:frspin 7s linear infinite reverse}
.fr-pulse{box-shadow:0 0 0 3px var(--good)}
.fr-pulse::after{content:'';position:absolute;inset:-3px;border-radius:50%;
  border:2px solid var(--good);animation:frpulse 2.4s ease-out infinite}
@keyframes frpulse{from{transform:scale(1);opacity:.85}
  to{transform:scale(1.35);opacity:0}}
.fr-gilded{background:linear-gradient(135deg,#f5d372,#8a6a1c 45%,#f7e5a8 70%,#7d5f16);
  box-shadow:0 0 18px rgba(220,180,80,.45)}

/* ---- the header that sits on the banner ---- */
.mhead.steam{display:block;margin:0 0 26px;background:var(--panel);
  border:1px solid var(--line);border-radius:16px;overflow:hidden}
.msash{display:flex;align-items:flex-end;gap:18px;padding:0 22px 18px;margin-top:-62px;
  position:relative;z-index:2}
.msash .mwho{padding-bottom:4px;min-width:0}
.msash h1{margin:0 0 4px;font-size:26px;line-height:1.15}
.mbody{padding:0 22px 20px}
.mbody .mbio{margin:0;font-size:14.5px;line-height:1.6;max-width:70ch;
  white-space:pre-wrap;word-break:break-word}
/* Sizes the PICTURE; the frame follows it. `.face` and not `.av`, because an uploaded
   picture is an <img class="face"> and only an initial is a <span class="face av"> — the
   old selector styled the fallback and left every real avatar at 84px inside its ring. */
.mface.big > .face{width:104px;height:104px;font-size:38px}
@media (max-width:620px){
  .mbanner{height:140px}
  .msash{margin-top:-48px;gap:13px;padding:0 15px 15px}
  .mface.big > .face{width:80px;height:80px;font-size:30px}
  .msash h1{font-size:21px}
}

/* ---- the picker in settings ---- */
.bgup{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 11px}
.bgup .hint{margin:0;flex:1 1 240px}
.bgprev{margin:0 0 14px;border:1px solid var(--line);border-radius:12px;overflow:hidden;
  max-width:620px}
.bgprevimg{height:130px;background-size:cover;background-position:50% 50%;
  background-color:#0c0f15}
.bgprevbar{display:flex;align-items:center;gap:12px;padding:9px 12px;
  background:var(--panel2);font-size:12.5px;color:var(--dim)}
.bgprevbar input[type=range]{flex:1;accent-color:var(--accent);width:auto;padding:0;
  background:none;border:0}
.looks{display:grid;gap:9px;grid-template-columns:repeat(auto-fill,minmax(112px,1fr));
  margin:0 0 20px}
.look{position:relative;height:62px;border-radius:10px;overflow:hidden;cursor:pointer;
  border:2px solid transparent;background:var(--panel2);display:block;padding:0}
.look:hover{border-color:var(--line2)}
.look.on{border-color:var(--accent);box-shadow:0 0 0 3px rgba(90,162,255,.2)}
.look .swatch{position:absolute;inset:0}
.look .nm{position:absolute;left:0;right:0;bottom:0;padding:3px 6px;font-size:11px;
  color:#fff;background:linear-gradient(to top,rgba(0,0,0,.8),transparent);
  text-align:left}
.look.none .swatch{background:
  repeating-linear-gradient(45deg,#191d26 0 7px,#12151c 7px 14px)}
.lookrow{margin:0 0 6px;font-size:13px;font-weight:600;color:var(--dim);
  text-transform:uppercase;letter-spacing:.06em}

/* ---- the account menu ---- */
.whowrap{position:relative}
.who .chev{width:14px;height:14px;opacity:.6;margin-left:-2px}
.whomenu{position:absolute;right:0;top:calc(100% + 8px);min-width:236px;z-index:40;
  background:var(--panel);border:1px solid var(--line2);border-radius:12px;padding:6px;
  box-shadow:var(--shadow-lift);animation:drop .16s var(--ease) both}
.whomenu a,.whomenu button{display:flex;align-items:center;gap:11px;width:100%;
  padding:9px 10px;border-radius:8px;color:var(--fg);text-decoration:none;
  font:inherit;text-align:left;border:0;background:none;cursor:pointer}
.whomenu a:hover,.whomenu button:hover{background:var(--panel2)}
.whomenu svg{width:17px;height:17px;flex:0 0 auto;color:var(--dim)}
.whomenu span{display:flex;flex-direction:column;gap:1px;min-width:0}
.whomenu b{font-size:13.5px;font-weight:600}
.whomenu i{font-style:normal;font-size:11.5px;color:var(--dim)}
.whomenu #whoout,.whomenu button:last-child{margin-top:4px;padding-top:11px;
  border-top:1px solid var(--line)}
.whomenu button:last-child svg,.whomenu button:last-child b{color:var(--bad)}

.btn.sm.out.reddit{display:inline-flex;align-items:center;gap:6px}
.btn.sm.out.reddit svg{width:14px;height:14px}
.btn.sm.out.reddit:hover{border-color:#ff6a33;color:#ff6a33}
h1 .reddit{display:inline-flex;align-items:center;gap:5px;margin-left:12px;
  padding:4px 10px 4px 8px;border-radius:999px;vertical-align:middle;
  font-size:12.5px;font-weight:500;letter-spacing:.01em;text-decoration:none;
  color:var(--dim);background:var(--panel);border:1px solid var(--line);
  transition:color .15s,border-color .15s,background .15s,transform .12s var(--ease)}
h1 .reddit svg{width:15px;height:15px;flex:0 0 auto}
h1 .reddit:hover{color:#ff6a33;border-color:#ff6a33;background:rgba(255,106,51,.09);
  transform:translateY(-1px)}
h1 .pscore{display:inline-block;margin-left:9px;padding:3px 10px;border-radius:999px;
  vertical-align:middle;font-size:13px;font-weight:600;font-variant-numeric:tabular-nums;
  color:var(--dim);background:var(--panel);border:1px solid var(--line)}
h1 .pscore.pos{color:var(--good);border-color:rgba(63,185,80,.4);
  background:rgba(63,185,80,.1)}
h1 .pscore.neg{color:var(--bad);border-color:rgba(242,88,91,.4);
  background:rgba(242,88,91,.1)}

/* ---- the up/down/flag bar under a tile ---- */
.votes{display:flex;align-items:center;gap:2px;margin-top:7px}
.vb{display:grid;place-items:center;width:26px;height:26px;padding:0;flex:0 0 auto;
  border:0;border-radius:7px;background:none;color:var(--dim);cursor:pointer;
  transition:color .13s,background .13s,transform .1s var(--ease)}
.vb svg{width:15px;height:15px}
.vb:hover{background:rgba(255,255,255,.07);color:var(--fg)}
.vb:active{transform:scale(.88)}
.vb.up.on{color:var(--good);background:rgba(63,185,80,.14)}
.vb.down.on{color:var(--bad);background:rgba(242,88,91,.14)}
.vb.flag{margin-left:auto}
.vb.flag:hover{color:var(--warn)}
.vb.del:hover{color:var(--bad);background:rgba(242,88,91,.14)}
.sptalk{margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
.sptalk .sub{margin:0 0 10px;font-size:13px}
.sptalk .cbox textarea{min-height:70px}
.sptalk .cm{padding:9px 0}
/* The bar under a comment is a smaller thing than the one under a picture. */
.cm .votes{margin-top:6px}
.cm .vb{width:23px;height:23px}
.cm .vb svg{width:13px;height:13px}
.cm .vscore{font-size:12px;min-width:20px}
.vscore{min-width:24px;text-align:center;font-size:12.5px;font-weight:600;
  font-variant-numeric:tabular-nums;color:var(--dim)}
.vscore.pos{color:var(--good)}
.vscore.neg{color:var(--bad)}
.sheet .opt{font-weight:400;color:var(--dim)}

.points{margin:7px 0 0;display:flex;align-items:center;gap:8px}
.points .pv{font-size:17px;font-weight:700;font-variant-numeric:tabular-nums;
  padding:2px 11px;border-radius:999px;color:var(--dim);
  background:var(--panel);border:1px solid var(--line)}
.points .pv.pos{color:var(--good);border-color:rgba(63,185,80,.4);
  background:rgba(63,185,80,.1)}
.points .pv.neg{color:var(--bad);border-color:rgba(242,88,91,.4);
  background:rgba(242,88,91,.1)}
.points .pl{font-size:13px;color:var(--dim)}

/* ---- the two review tables ---- */
.rows{display:flex;flex-direction:column;gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:10px;overflow:hidden}
.rhead,.rrow2{display:grid;gap:10px;align-items:center;padding:9px 12px;
  background:var(--panel);
  grid-template-columns:minmax(90px,1.1fr) minmax(90px,1.2fr) auto 62px 84px auto}
.rhead{background:var(--panel2);font-size:11.5px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--dim)}
.rrow2{font-size:13.5px}
.rrow2 .badge{position:static;justify-self:start}
.rrow2 .racts{display:flex;gap:6px;justify-content:flex-end}
.rrow2 .state{font-size:11.5px}
.state.s-dead{color:var(--warn)}
@media (max-width:760px){
  .rhead{display:none}
  .rrow2{grid-template-columns:1fr 1fr;row-gap:6px}
  .rrow2 .racts{grid-column:1/-1;justify-content:flex-start}
}
/* The page a crawler and a JavaScript-less visitor get. Replaced by the app the moment it
   runs, so nobody with a browser sees it for more than an instant — but it is REAL text
   that is really served, not markup hidden for robots. It says what the site is and how to
   get something removed, and it names nobody.
   It exists because the body was <main id="app"></main> and a crawler saw six words of
   navigation. A site with nothing to read cannot be found by anybody looking for what it
   does — only by somebody who already knows the address. */
.intro{max-width:70ch;padding:8px 0 40px}
.intro h1{font-size:26px;margin:0 0 14px}
.intro h2{font-size:17px;margin:26px 0 8px}
.intro p{line-height:1.65;color:var(--fg);margin:0 0 12px}

.adminnav{margin:0 0 20px}
.adminnav .k{font-size:13.5px}
.subpost.admin{border-color:var(--line2)}
.subpost.admin.gone{opacity:.66;border-style:dashed}
.subpost.admin .spfoot{flex-wrap:wrap;gap:8px}
.subpost.admin .sphead{flex-wrap:wrap}
.csearch{display:flex;gap:8px;margin:0 0 14px;max-width:480px}
.csearch input{flex:1 1 auto;margin:0}
.cmrows{display:flex;flex-direction:column;gap:10px}
.cmrow{background:var(--panel);border:1px solid var(--line);border-radius:10px;
  padding:11px 13px}
.cmrow.gone{opacity:.72;border-style:dashed}
.cmrow header{display:flex;align-items:center;flex-wrap:wrap;gap:7px;
  font-size:12.5px;margin-bottom:7px}
.cmrow header .au{font-weight:600;color:var(--fg);text-decoration:none}
.cmrow header .au:hover{color:var(--accent)}
.cmrow header .when{margin-left:auto;color:var(--dim)}
.cmrow blockquote{margin:0;font-size:14px;line-height:1.55;white-space:pre-wrap;
  word-break:break-word}
.cmrow.gone blockquote{text-decoration:line-through;color:var(--dim)}
.cmrow .rowacts{margin-top:8px}

.clock{font-size:11.5px;font-weight:700;padding:2px 8px;border-radius:999px;
  color:var(--good);background:rgba(63,185,80,.12);border:1px solid rgba(63,185,80,.35)}
.clock.soon{color:var(--warn);background:rgba(210,153,34,.13);
  border-color:rgba(210,153,34,.4)}
.clock.over{color:#fff;background:var(--bad);border-color:var(--bad)}
.signed{font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--dim);
  border:1px solid var(--line2);border-radius:999px;padding:2px 8px}

.inbox .slink{margin:7px 0 0;font-size:13px;word-break:break-all}
.inbox .slink a{color:var(--accent)}
.hosts{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin:0 0 14px;
  font-size:13.5px;color:var(--dim)}
.hostbox{display:inline-flex;align-items:center;gap:6px;cursor:pointer}
.hostbox input{width:auto;margin:0}
.hosts .hint2{flex:1 1 100%;font-size:12px;color:var(--dim);opacity:.85}
.btn.sm.good{border-color:var(--good);color:var(--good)}

/* ---- community submissions ---- */
.subs{margin-top:34px;padding-top:26px;border-top:1px solid var(--line)}
.subs h2{margin:0 0 4px;font-size:19px}
.subs .sub{margin:0 0 14px}
.subs .empty.sm{padding:22px;font-size:14px;color:var(--dim)}
.subform{display:block;max-width:560px;margin:6px 0 20px;padding:16px;
  background:var(--panel);border:1px solid var(--line);border-radius:12px}
.subform label{display:block;margin:0 0 5px;font-size:13px;font-weight:600}
.subform label .opt{font-weight:400;color:var(--dim)}
.subform input{width:100%;margin:0 0 13px}
.subform .subnote2{margin:0 0 13px;font-size:12.5px;color:var(--dim);line-height:1.5}
/* A submission is a small post — who added it, what is in it, and what people made of it.
   Laid out as a column of posts rather than a grid of tiles because the person who added it
   is part of the thing, and a tile has nowhere to put them. */
.subposts{display:flex;flex-direction:column;gap:16px}
.subpost{background:var(--panel);border:1px solid var(--line);border-radius:14px;
  padding:14px 15px 12px}
.sphead{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.sphead .who{display:inline-flex;align-items:center;gap:8px;text-decoration:none;
  color:var(--fg);font-size:13.5px;font-weight:600}
.sphead .who:hover .nm{color:var(--accent)}
.sphead .av{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;
  font-size:12px;font-weight:700;color:#08121f;flex:0 0 auto;
  background:linear-gradient(135deg,var(--accent),var(--accent2))}
.sphead .badge{position:static}
.sphead .when{margin-left:auto;font-size:12px;color:var(--dim)}
.spnote{margin:0 0 11px;font-size:14px;line-height:1.5}
.spshots{display:grid;gap:4px;grid-template-columns:repeat(4,1fr)}
.spshots.n1{grid-template-columns:minmax(0,340px)}
.spshots.n2{grid-template-columns:repeat(2,1fr)}
.spshots.n3{grid-template-columns:repeat(3,1fr)}
.spshot{display:block;position:relative;aspect-ratio:1/1;overflow:hidden;
  border-radius:9px;background:#0c0c11}
.spshots.n1 .spshot{aspect-ratio:4/3}
.spshot img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .3s var(--ease)}
.spshot:hover img{transform:scale(1.05)}
.spmore{display:grid;place-items:center;aspect-ratio:1/1;border-radius:9px;
  background:var(--panel2);color:var(--dim);font-size:13px;font-weight:600;
  text-decoration:none}
.spmore:hover{color:var(--fg);background:var(--line)}
.spfoot{display:flex;align-items:center;gap:14px;margin-top:10px}
.spfoot .votes{margin-top:0}
.spsrc{margin-left:auto;font-size:12px;color:var(--dim);text-decoration:none}
.spsrc:hover{color:var(--accent)}
.subs.only{margin-top:22px;padding-top:0;border-top:0}
.subs .lede2{margin:0 0 14px;color:var(--dim);font-size:14px;line-height:1.55;
  max-width:66ch}
/* Set apart from the where-from filters beside it: those narrow the catalogue, this leaves
   it for something else entirely. */
.seg .k.sep{margin-left:10px;position:relative}
.seg .k.sep::before{content:'';position:absolute;left:-6px;top:7px;bottom:7px;width:1px;
  background:var(--line2)}
.seg.justsubs{justify-content:flex-start}
.seg .k.sep.on{background:var(--accent2);color:#0b0616;font-weight:600}
.srclist{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.srcitem{border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px;
  background:var(--panel2);border-left-width:3px}
.srcitem.s-redgifs{border-left-color:var(--brandr)}
.srcitem.s-erome{border-left-color:var(--warn)}
.srcitem.s-imgur{border-left-color:var(--good)}
.srcitem .sname{font-weight:640;font-size:15px}
.srcitem .scount{color:var(--dim);font-size:13px;margin:2px 0 11px;
  font-variant-numeric:tabular-nums}
.sacts{display:flex;gap:7px;flex-wrap:wrap}
.btn.sm{padding:5px 11px;font-size:12.5px}
.btn.out{color:var(--dim)}
.btn.out:hover{color:var(--fg)}
.reportbody{white-space:pre-wrap;word-break:break-word;font:12.5px/1.65 ui-monospace,
  SFMono-Regular,Menlo,Consolas,monospace;background:var(--bg);border:1px solid var(--line);
  border-radius:9px;padding:14px 16px;max-height:60vh;overflow:auto;margin:14px 0 0;
  color:var(--dim)}
.srclink{color:inherit;text-decoration:none}
.srclink:hover{color:var(--accent);text-decoration:underline}

/* ---- source badges and the source filter ----
   Each host gets its own hue so a grid of mixed origins is readable at a glance rather
   than needing the caption read. They sit in the same saturation register as the existing
   accent and brand colours, so they read as part of the palette instead of a legend
   pasted on top of it. */
.badge.gif{background:rgba(124,108,255,.85)}
.badge.src{right:auto;left:8px;font-size:9.5px;letter-spacing:.04em;text-transform:uppercase}
.badge.src.redgifs{background:rgba(255,90,110,.9)}
.badge.src.erome{background:rgba(210,153,34,.9)}
.badge.src.imgur{background:rgba(63,185,80,.85)}
.seg.srcs{margin-top:8px}
.seg.srcs .k.on.s-redgifs{border-color:var(--brandr);color:var(--brandr)}
.seg.srcs .k.on.s-erome{border-color:var(--warn);color:var(--warn)}
.seg.srcs .k.on.s-imgur{border-color:var(--good);color:var(--good)}

/* ---- the star ---- */
/* Sits over the corner of a tile. Invisible until the tile is hovered or the thing is
   already starred — a grid of 120 tiles each wearing a permanent control is noise. */
.star{position:absolute;top:8px;right:8px;z-index:3;width:32px;height:32px;border-radius:9px;
  display:grid;place-items:center;color:#fff;background:rgba(11,13,17,.62);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  border:1px solid rgba(255,255,255,.14);opacity:0;transform:scale(.9)}
.tile:hover .star,.gal figure:hover .star,.star:focus-visible,.star.on{opacity:1;transform:none}
.star:hover{background:rgba(11,13,17,.85)}
.star.on{color:var(--warn)}
.star svg{width:17px;height:17px}
.star.on svg{fill:currentColor}
/* The tile and figure are the positioning context the star hangs off. */
.tile,.gal figure{position:relative}

/* Unfollow, in the corner of a tile on the Following page. Same shape and behaviour as the
   star it sits beside: hidden until the tile is hovered, so a wall of tiles is not a wall
   of controls. */
.unfollow{position:absolute;top:8px;right:46px;z-index:3;width:32px;height:32px;
  border-radius:9px;display:grid;place-items:center;color:#fff;
  background:rgba(11,13,17,.62);backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,.14);
  opacity:0;transform:scale(.9)}
.tile:hover .unfollow,.unfollow:focus-visible{opacity:1;transform:none}
.unfollow:hover{background:rgba(242,88,91,.9);border-color:var(--bad)}
.unfollow svg{width:16px;height:16px}
.unfollow[disabled]{opacity:.5}
@media(max-width:780px){ .unfollow{opacity:1;transform:none} }

/* ---- follow / request buttons ---- */
.actions{display:flex;gap:9px;flex-wrap:wrap;margin:16px 0 4px}
.btn{padding:8px 15px;border-radius:9px;border:1px solid var(--line);background:var(--panel);
  color:var(--fg);font-size:14px;font-weight:560;display:inline-flex;align-items:center;gap:7px}
.btn:hover{border-color:var(--line2);background:var(--panel2)}
.btn.pri{background:var(--accent);color:#08121f;border-color:transparent}
.btn.pri:hover{filter:brightness(1.08);background:var(--accent)}
.btn.on{border-color:var(--accent);color:var(--accent);background:rgba(90,162,255,.09)}
.btn svg{width:15px;height:15px}
.btn[disabled]{opacity:.55;cursor:default}

/* ---- comments ---- */
.talk{margin-top:34px}
.talk h2{margin:0 0 4px;font-size:19px}
.talk .sub{margin:0 0 18px}
.cbox textarea{width:100%;min-height:84px;resize:vertical;padding:12px 13px;
  background:var(--panel);border:1px solid var(--line);border-radius:11px;color:var(--fg);
  font:inherit;line-height:1.5}
.cbox textarea:focus{border-color:var(--accent);outline:none;
  box-shadow:0 0 0 3px rgba(90,162,255,.14)}
.cbox .row{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:9px}
.cbox .count{color:var(--dim);font-size:12.5px}
.cbox .count.over{color:var(--bad)}
.clist{display:flex;flex-direction:column;gap:2px;margin-top:24px}
.cm{padding:14px 2px;border-top:1px solid var(--line);animation:slide .3s var(--ease) backwards}
.cm .head{display:flex;align-items:center;gap:9px;margin-bottom:7px}
.cm .av{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;
  font-size:12px;font-weight:700;color:#08121f;flex:0 0 auto;
  background:linear-gradient(135deg,var(--accent),var(--accent2))}
.cm .who2{font-weight:620;font-size:14px}
.cm .when{color:var(--dim);font-size:12.5px}
/* white-space:pre-wrap is what makes the paragraphs a person typed survive, without any
   markup being interpreted — the text is set with textContent, never innerHTML. */
.cm .body{white-space:pre-wrap;word-break:break-word;line-height:1.55;font-size:14.5px}
.cm.gone .body{color:var(--dim);font-style:italic}
.cm .tools{margin-left:auto;display:flex;gap:4px;opacity:0}
.cm:hover .tools,.cm:focus-within .tools{opacity:1}
.cm .tools button{color:var(--dim);font-size:12.5px;padding:3px 7px;border-radius:6px}
.cm .tools button:hover{color:var(--fg);background:var(--panel2)}
.cm .tools button.del:hover{color:var(--bad)}
.cm .av.none{background:var(--line2);color:var(--dim)}
/* Under the message, not beside the timestamp. It is a footnote about the text rather than
   part of who said it and when, and putting it in the header made the byline read as though
   the AUTHOR had been edited. */
.cm .edited{margin-top:5px;font-size:11.5px;color:var(--dimmer);font-style:italic}

/* Editing happens where the comment is, at the size the comment is, so the thread does not
   jump about when a box opens in the middle of it. */
.editing{margin-top:6px}
.editbox{width:100%;padding:10px 12px;background:var(--bg);border:1px solid var(--accent);
  border-radius:9px;color:var(--fg);font:inherit;line-height:1.5;resize:vertical;
  box-shadow:0 0 0 3px rgba(90,162,255,.13)}
.editbox:focus{outline:none}
.editrow{display:flex;align-items:center;gap:8px;margin-top:8px}
.editrow .count{color:var(--dim);font-size:12px;margin-right:auto;
  font-variant-numeric:tabular-nums}
.confirming{display:flex;align-items:center;gap:8px;margin-top:9px;padding:8px 11px;
  border-radius:8px;background:rgba(242,88,91,.08);border:1px solid rgba(242,88,91,.3);
  font-size:13.5px}
.confirming span{margin-right:auto}

/* ---- the bell page and the lists ---- */
.nlist{display:flex;flex-direction:column;gap:2px;margin-top:18px}
.nrow{display:flex;align-items:center;gap:13px;padding:14px 14px;border-radius:11px;
  border:1px solid transparent;color:var(--fg)}
.nrow:hover{background:var(--panel);border-color:var(--line)}
.nrow.unseen{background:rgba(90,162,255,.055);border-color:rgba(90,162,255,.16)}
.nrow .ic{width:34px;height:34px;border-radius:9px;display:grid;place-items:center;
  background:var(--panel2);color:var(--accent);flex:0 0 auto}
.nrow .txt{flex:1;min-width:0}
.nrow .txt b{font-weight:640}
.nrow .when{color:var(--dim);font-size:12.5px;margin-top:2px}
.rowlist{display:flex;flex-direction:column;gap:2px;margin-top:18px}
.rrow2{display:flex;align-items:center;gap:12px;padding:13px 14px;border-radius:11px;
  border:1px solid var(--line);background:var(--panel)}
.rrow2 .n{font-weight:620}
.rrow2 .state{margin-left:auto;font-size:12.5px;padding:3px 10px;border-radius:999px;
  border:1px solid var(--line2);color:var(--dim)}
.rrow2 .state.done{color:var(--good);border-color:rgba(63,185,80,.4)}
.rrow2 .state.taken{color:var(--warn);border-color:rgba(210,153,34,.4)}
.rrow2 .state.refused{color:var(--bad);border-color:rgba(242,88,91,.4)}

/* ---- the account page ---- */
.panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);
  padding:20px 22px;margin-top:18px}
.panel h2{margin:0 0 4px;font-size:17px}
.panel .lede{color:var(--dim);font-size:14px;margin:0 0 14px;line-height:1.5}
/* Field labels only. A .switch is a label too, and this rule outranked its display:flex
   on specificity — so the row fell back to block, the tick sat on its own line and the
   text wrapped underneath it. Same shape of bug as .panel input above: a broad selector
   written for text fields quietly reaching a control that is not one. */
.panel label:not(.switch){display:block;margin:12px 0 6px;font-size:13px;color:var(--dim)}
/* Text fields only. This used to be every input in a panel, which caught the checkbox in
   the settings switch and stretched it to a 340px-wide box with the label overlapping it —
   the tick was a third of the row and the gap either side of it looked enormous because it
   was. A checkbox is not a text field and must not inherit a text field's geometry. */
.panel input:not([type=checkbox]):not([type=radio]):not([type=file]){
  width:100%;max-width:340px;padding:10px 12px;background:var(--bg);
  border:1px solid var(--line);border-radius:9px;color:var(--fg)}
.panel input:focus{border-color:var(--accent);outline:none}
.panel.danger{border-color:rgba(242,88,91,.32)}
.panel.danger h2{color:var(--bad)}
.btn.bad{border-color:rgba(242,88,91,.4);color:var(--bad)}
.btn.bad:hover{background:rgba(242,88,91,.1);border-color:var(--bad)}

@media(max-width:780px){
  .auth{margin:5vh auto;padding:0 4px}
  /* No hover on a touch screen, so a control that only appears on hover never appears.
     Stars are permanent here instead. */
  .star{opacity:1;transform:none}
  .cm .tools{opacity:1}
}
