/* R20CS tier list - styling.
 *
 * Palette and type are lifted from the r20cs.com landing page so this reads as the same product:
 * off-white ground, near-black ink, one orange accent, Inter. The Asiimov nod is in the geometry
 * rather than the colour - skewed cuts, thin stripe clusters, stencil-ish uppercase labels - which
 * keeps the tier colours themselves free to do their job.
 */

/* THEME_TOKENS (src/theme.ts) is ALSO embedded now, via pages.ts's shell() alongside the shared
 * site header (M, 2026-08-29) - it supplies the ROLE tokens this file never had (--ink, --surface,
 * --nav-idle...) that the header needs. It is not a replacement for what is declared here: THEME_
 * TOKENS keeps --orange/--near-black/--white/--off-white/--muted/--grey-inactive FIXED across
 * themes by design (its own comment: "the colour-NAMED tokens are literal and never change") and
 * flips separate role tokens instead, while every existing tier-list rule below was built the
 * other way - referencing --white/--off-white/--near-black directly.
 *
 * Dark-only (2026-08-30, M: "remove light mode from r20cs.com"). This used to be a light :root
 * plus a :root[data-theme="dark"] override - --white is "surface", --off-white is "ground",
 * --near-black is "ink" - now merged into one set of values (the ones that used to be the dark
 * override; the ground is sampled straight from M's dark artwork, #191a1d, not picked by eye, so
 * the flat colour behind the image and the image itself are the same charcoal).
 *
 * A handful of components use --near-black as an actual DARK colour rather than as ink (the player,
 * the placeholder tile). Those invert the wrong way against this flip and are pinned explicitly
 * further down - now as plain unconditional rules instead of a :root[data-theme="dark"] override,
 * since there is only one state to pin them against.
 *
 * :root:root, not :root, for the 5 overloaded names (found live, 2026-08-30 - the login card
 * rendered as a light card instead of dark the moment the [data-theme="dark"] block above was
 * removed). This file loads BEFORE the inline THEME_TOKENS+HEADER_CSS block in the page (see
 * pages.ts's shell()), and THEME_TOKENS keeps its OWN --white/--near-black/--off-white/--muted/
 * --grey-inactive fixed at their literal-colour (light) values by design - equal-specificity
 * :root rules resolve by source order, so THEME_TOKENS loading second always used to win for
 * these 5 names. The old [data-theme="dark"] attribute selector accidentally gave this block a
 * specificity edge that masked the collision entirely; doubling :root restores that edge without
 * depending on an attribute nothing sets any more. */
:root:root{
  --orange:#ff6500;
  --near-black:#f2f0ec;     /* ink     */
  --dark-panel:#12171b;
  --white:#212429;          /* surface */
  --off-white:#191a1d;      /* ground - sampled from bg-dark.jpg */
  --muted:#8d949c;
  --grey-inactive:#454b53;
  --line:rgba(242,240,236,.12);
  --tile:104px;          /* square image edge; one number drives the whole board */
}

*,*::before,*::after{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;font-family:"Inter","Segoe UI",system-ui,sans-serif;
  background:var(--off-white);color:var(--near-black);
  -webkit-font-smoothing:antialiased;
}

/* R20CS background art (M, 2026-08-25).
 *
 * Fixed rather than scrolling: the decoration lives around the EDGES of the artwork, so letting it
 * scroll would drag the cats and paw prints up behind the board and then leave plain colour below
 * on a long list. Fixed keeps the framing where it was drawn.
 *
 * The flat --off-white stays as the body background underneath, so the page never flashes white
 * before the image arrives and still looks right if it never does. Only the editor and home pages
 * carry it - the login screen is deliberately the dark card on near-black. */
.page-home,.page-editor{
  background-image:url("/assets/tierlist/bg-dark.jpg");
  background-size:cover;
  background-position:center;
  background-attachment:fixed;
  background-repeat:no-repeat;
}
img{display:block;max-width:100%}
button{font-family:inherit;cursor:pointer}

.paw{width:1em;height:1em;fill:currentColor;flex:none}
.muted{color:var(--muted)}


/* ---------- buttons ---------- */
.btn-primary{
  display:inline-flex;align-items:center;gap:8px;border:0;background:var(--orange);color:#fff;
  font-weight:800;font-size:13px;letter-spacing:.06em;text-transform:uppercase;
  padding:11px 18px;clip-path:polygon(0 0,100% 0,100% 100%,9px 100%);transition:filter .12s ease;
}
.btn-primary:hover{filter:brightness(1.08)}
.btn-primary:active{filter:brightness(.94)}
.btn-ghost{
  display:inline-flex;align-items:center;gap:7px;background:transparent;color:var(--near-black);
  border:1px solid var(--line);font-weight:700;font-size:12px;letter-spacing:.06em;text-transform:uppercase;
  padding:10px 14px;transition:border-color .12s ease,color .12s ease;
}
.btn-ghost:hover{border-color:var(--near-black)}
.btn-ghost.danger:hover{border-color:#c8402f;color:#c8402f}
:focus-visible{outline:2px solid var(--orange);outline-offset:2px}

/* ---------- login ----------
 * This used to be the ENTIRE body (no header existed yet), so grid+place-items:center on body
 * full-page-centred the one card with nothing else to account for. The shared header (M,
 * 2026-08-29) is now body's first child too, and centring every grid item - header included -
 * stretched/centred the header's own row instead of leaving it pinned at the top like every other
 * page (M: "the header is sitting way too much down"). Flex column + auto margins on the card
 * fixes it: the header takes only its content height, the card absorbs the rest of the space. */
.page-login{display:flex;flex-direction:column;min-height:100vh;background:var(--near-black)}
.login-wrap{width:min(92vw,380px);margin:auto}
.login-card{
  background:var(--white);padding:30px 28px 26px;display:flex;flex-direction:column;gap:12px;
  clip-path:polygon(0 0,100% 0,100% calc(100% - 18px),calc(100% - 18px) 100%,0 100%);
}
.login-label{font-size:11px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:var(--muted)}
.login-card input{
  font-family:inherit;font-size:15px;padding:11px 12px;border:1px solid var(--line);
  background:var(--off-white);color:var(--near-black);
}
.login-card input:focus{outline:2px solid var(--orange);outline-offset:0;border-color:transparent}
.login-card .btn-primary{justify-content:center;margin-top:4px}
.login-error{min-height:16px;margin:0;font-size:12.5px;color:#c8402f;font-weight:600}
.login-warn{margin:4px 0 0;font-size:12px;line-height:1.5;color:var(--muted)}
.login-warn code{background:var(--off-white);padding:1px 5px;font-size:11.5px}
.login-lede{margin:0;font-size:13.5px;line-height:1.5;color:var(--muted)}
.login-card a.btn-primary{justify-content:center;margin-top:4px;text-decoration:none}

/* ---------- ownership / quota chrome ---------- */
.home-head-r{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.cap-note{font-size:11.5px;font-weight:700;color:var(--muted);letter-spacing:.02em;white-space:nowrap}
.readonly-note{font-size:12.5px;color:var(--muted);margin:0 0 14px;font-style:italic}

/* ---------- editor sub-bar ----------
 * The backlink and save-state used to live in this tool's own header. The shared header (M,
 * 2026-08-29) is a fixed 3-column grid with no room carved out for a per-page extra - see header.ts's
 * own comment on why it is a grid, not a flex row - so this is a small bar of its own above the
 * title instead of a per-page special case bolted onto the shared one. */
.editor-subbar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px}
.backlink{font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);text-decoration:none}
.backlink:hover{color:var(--near-black)}
.savestate{font-size:11px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}
.savestate b{color:#3fa45b}
.savestate[data-state="saving"]{color:var(--orange)}
.savestate[data-state="failed"]{color:#c8402f;cursor:pointer}

/* ---------- home ---------- */
.home-wrap{max-width:960px;margin:0 auto;padding:34px 22px 70px}
.home-head{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:22px}
.home-head h1{margin:0;font-size:26px;font-weight:900;letter-spacing:-.01em}
.list-grid{display:grid;gap:12px}
.list-card{
  background:var(--white);border:1px solid var(--line);padding:16px 18px;
  display:flex;align-items:center;gap:16px;
  clip-path:polygon(0 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,0 100%);
}
.list-card .lc-main{flex:1;min-width:0}
.list-card h3{margin:0 0 4px;font-size:16px;font-weight:800}
.list-card .lc-meta{font-size:11.5px;color:var(--muted);display:flex;gap:14px;flex-wrap:wrap}
.list-card .lc-code{
  font-size:11px;font-weight:800;letter-spacing:.12em;color:var(--orange);
  border:1px solid rgba(255,101,0,.35);padding:3px 7px;
}
.list-card.inactive{opacity:.6}
.lc-inactive-tag{font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.empty-state{
  background:var(--white);border:1px dashed var(--line);padding:40px 24px;text-align:center;color:var(--muted);
}
.empty-state .paw{width:26px;height:26px;opacity:.25;margin:0 auto 10px}

/* ---------- editor ---------- */
.editor-wrap{max-width:1600px;margin:0 auto;padding:22px 22px 90px}
.title-row{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
.list-title{
  margin:0;font-size:30px;font-weight:900;letter-spacing:-.02em;text-transform:uppercase;
  cursor:text;padding:2px 6px;margin-left:-6px;
}
.list-title:hover{background:rgba(255,101,0,.1)}
.list-title-input{
  font:inherit;font-size:30px;font-weight:900;letter-spacing:-.02em;text-transform:uppercase;
  border:0;border-bottom:2px solid var(--orange);background:transparent;padding:2px 6px;margin-left:-6px;
  color:inherit;width:min(100%,620px);
}
.list-code{font-size:11px;font-weight:800;letter-spacing:.14em;color:var(--muted)}
.toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:18px 0 20px}
.upload-status{font-size:12px;color:var(--muted);font-weight:600}
.upload-hint{font-size:11.5px;color:var(--muted);letter-spacing:.02em}

/* Full-page drop target. Pointer-events stay off so it can never swallow a click, and it only
   becomes visible while files are actually being dragged over the window. */
.drop-overlay{
  position:fixed;inset:0;z-index:60;display:none;place-items:center;pointer-events:none;
  background:rgba(17,20,24,.72);
}
.drop-overlay.on{display:grid}
.drop-overlay div{
  border:3px dashed var(--orange);padding:34px 54px;text-align:center;background:rgba(17,20,24,.5);
}
.drop-overlay b{display:block;color:var(--white);font-size:22px;font-weight:900;letter-spacing:.04em;text-transform:uppercase}
.drop-overlay span{display:block;margin-top:6px;color:var(--grey-inactive);font-size:12.5px;letter-spacing:.08em;text-transform:uppercase}

/* Surfaces sit slightly translucent over the background art, so it reads through the page instead
   of only showing at the edges. Kept high enough (86-92%) that tile edges and text never fight the
   pattern behind them - a background you cannot see is pointless, and one you can see THROUGH the
   content is worse. */
.page-editor .tier-row,
.page-editor .unranked-drop{background:rgba(33,36,41,.82)}
.page-home .list-card,
.page-home .empty-state{background:rgba(33,36,41,.86)}

/* Components that use --near-black as a real DARK colour rather than as ink. Now that --near-black
   is permanently the "ink" value (2026-08-30, dark-only), these need pinning unconditionally or
   they'd resolve to a near-white background instead of a dark one. */
.player,
.song-lib{background:#0e1013;border:1px solid rgba(242,240,236,.1)}
/* .page-login is the same trap: "deliberately the dark card on near-black" (see its own comment
   above) predates the dark-only palette entirely, so --near-black meaning ink (near-white) left
   the signed-out view a washed-out cream void instead of the intended dark ground - found live
   2026-08-29 (M: "bro what is that view on tierlist when you are not logged in"). */
.page-login{background:#0e1013}

/* These are permanently light-on-dark components, so they reference --white and --grey-inactive
   meaning "light text". Pinned to literals rather than the tokens directly, since those tokens
   are also used elsewhere to mean "dark surface" - which is exactly what happened to the
   transport icons when this was first written. */
.player-title,
.pbtn,
.drop-overlay b{color:#f2f0ec}
.pvol::-webkit-slider-thumb{background:#f2f0ec}
.pvol::-moz-range-thumb{background:#f2f0ec}
.song-lib-head,
.song-row-name,
.song-lib-add,
.drop-overlay span{color:#a8b0b8}
.song-row-name:hover{color:#f2f0ec}
/* --grey-inactive's tile-placeholder meaning is too dark to read text in here. */
.unranked-head .count{color:#6c737b}
.tile-placeholder,
.pp-avatar{background:#0e1013}
.tile{background:var(--grey-inactive)}
.drop-overlay{background:rgba(10,11,13,.8)}
.modal-back{background:rgba(10,11,13,.62)}
.login-warn code{background:rgba(242,240,236,.08)}


/* ---------- board ---------- */
.board{display:flex;flex-direction:column;gap:6px}
.tier-row{display:flex;align-items:stretch;background:var(--white);border:1px solid var(--line)}
.tier-label{
  flex:none;width:96px;display:flex;align-items:center;justify-content:center;
  font-weight:900;color:#fff;letter-spacing:.02em;position:relative;padding:6px 8px;text-align:center;
}
/* Tier names are free text now, so the type steps down by length instead of every row shrinking to
   fit the longest name that might ever be typed. */
.tier-label .tier-name{line-height:1.05;word-break:break-word;hyphens:auto}
.tier-label.len-s .tier-name{font-size:26px}
.tier-label.len-m .tier-name{font-size:16px;letter-spacing:.04em}
.tier-label.len-l .tier-name{font-size:12.5px;letter-spacing:.06em;text-transform:uppercase}
.tier-label.len-xl .tier-name{font-size:10.5px;letter-spacing:.05em;text-transform:uppercase}

/* Cog sits in the corner of the label and only appears on hover or keyboard focus, so it never
   competes with the tier name itself. */
.tier-cog{
  position:absolute;top:3px;right:9px;width:20px;height:20px;padding:0;border:0;background:transparent;
  color:#fff;opacity:.45;transition:opacity .12s ease;display:grid;place-items:center;
}
.tier-cog svg{width:15px;height:15px;fill:currentColor}
/* Visible at rest rather than hover-only: it is the only way to discover that tiers can be renamed,
   and a control nobody can see is a feature nobody uses. */
.tier-row:hover .tier-cog,.tier-cog:focus-visible{opacity:1}
.tier-cog:hover{color:#fff;transform:rotate(25deg);transition:opacity .12s ease,transform .18s ease}

/* Tier settings popover */
.tier-pop{
  position:absolute;z-index:70;background:var(--white);border:1px solid var(--line);
  padding:14px;width:246px;box-shadow:0 14px 34px rgba(17,20,24,.22);
  clip-path:polygon(0 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,0 100%);
}
.tier-pop-label{display:block;font-size:10.5px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-bottom:5px}
.tier-pop-input{
  width:100%;font:inherit;font-size:14px;font-weight:700;padding:8px 10px;margin-bottom:12px;
  border:1px solid var(--line);background:var(--off-white);color:var(--near-black);
}
.tier-pop-input:focus{outline:2px solid var(--orange);outline-offset:0;border-color:transparent}
.tier-pop-swatches{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px;align-items:center}
.tier-pop-swatches .swatch{width:24px;height:24px;border:2px solid transparent;padding:0;cursor:pointer}
.tier-pop-swatches .swatch.on{border-color:var(--near-black)}
.tier-pop-color{width:30px;height:24px;padding:0;border:1px solid var(--line);background:none;cursor:pointer}
.tier-pop-acts{display:flex;gap:8px;justify-content:flex-end}
.tier-pop-acts button{padding:8px 14px;font-size:11.5px}
/* The thin diagonal cut on the label's inner edge is the Asiimov detail - one shape, repeated. */
.tier-label::after{
  content:"";position:absolute;right:-1px;top:0;bottom:0;width:10px;background:inherit;
  clip-path:polygon(0 0,100% 0,0 100%);
}
.row-items{
  flex:1;min-width:0;display:flex;flex-wrap:wrap;align-content:flex-start;gap:5px;padding:6px;
  min-height:calc(var(--tile) + 12px);position:relative;
}
/* Paw watermark, only while a row is genuinely empty. */
.row-items:empty::before{
  content:"";position:absolute;left:14px;top:50%;transform:translateY(-50%);
  width:30px;height:30px;opacity:.11;
  background:currentColor;
  -webkit-mask:var(--paw-mask) center/contain no-repeat;mask:var(--paw-mask) center/contain no-repeat;
}
:root{
  --paw-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cellipse cx='12' cy='15.5' rx='5.4' ry='4.6'/%3E%3Cellipse cx='5.6' cy='9.9' rx='2.5' ry='3.1'/%3E%3Cellipse cx='10.2' cy='6.6' rx='2.4' ry='3.2'/%3E%3Cellipse cx='15.4' cy='6.9' rx='2.4' ry='3.2'/%3E%3Cellipse cx='19.3' cy='10.6' rx='2.4' ry='3'/%3E%3C/svg%3E");
}
.row-items.dragover{background:rgba(255,101,0,.07);box-shadow:inset 0 0 0 2px rgba(255,101,0,.5)}

.add-tier{
  width:100%;margin-top:8px;padding:9px;background:transparent;border:1px dashed var(--line);
  color:var(--muted);font-size:11.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  transition:border-color .12s ease,color .12s ease;
}
.add-tier:hover{border-color:var(--orange);color:var(--orange)}

.tier-pop-struct{display:flex;gap:6px;margin-bottom:12px}
.tier-pop-mini{
  flex:1;padding:7px 4px;font-size:10.5px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;
  background:transparent;border:1px solid var(--line);color:var(--near-black);
}
.tier-pop-mini:hover:not(:disabled){border-color:var(--near-black)}
.tier-pop-mini:disabled{opacity:.35;cursor:default}
.tier-pop-mini.danger{color:#c8402f}
.tier-pop-mini.danger:hover:not(:disabled){border-color:#c8402f}

/* ---------- tiles ---------- */
.tile{
  width:var(--tile);aspect-ratio:1/1;flex:none;position:relative;background:var(--grey-inactive);
  cursor:grab;user-select:none;
}
.tile img{width:100%;height:100%;object-fit:cover;pointer-events:none}
.tile.dragging{opacity:.35;cursor:grabbing}
/* Applied a tick after dragstart - see the note in app.js about why it cannot be immediate. */
.tile.drag-hidden{display:none}
/* The clone that follows a finger. Fixed so it tracks the viewport, and pointer-events:none so it
   never intercepts the elementFromPoint lookup underneath it. */
.tile-ghost{position:fixed;z-index:80;pointer-events:none;opacity:.9;transform:scale(1.06);
  box-shadow:0 10px 26px rgba(0,0,0,.45);margin:0}
/* Without this the browser claims the gesture for scrolling before the first pointermove lands.
   Applied unconditionally rather than under a coarse-pointer query: a touchscreen laptop reports a
   FINE pointer, and touch-action has no effect on mouse input anyway. Scrolling still works
   everywhere that is not a tile - the row padding, the labels, the page margins. */
.tile{touch-action:none}
.tile.selected{outline:3px solid var(--orange);outline-offset:-3px}
/* Submitter name across the bottom of a Steam profile tile.
   The scrim belongs to the label, not the tile, so a manual picture is never dimmed by it. */
.tile-who{
  position:absolute;left:0;right:0;bottom:0;padding:9px 4px 3px;
  font-size:9.5px;font-weight:800;line-height:1.1;color:#fff;text-align:center;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  background:linear-gradient(to top,rgba(8,10,12,.92),rgba(8,10,12,.7) 55%,rgba(8,10,12,0));
  pointer-events:none;text-shadow:0 1px 2px rgba(0,0,0,.8);
}
/* Dim it while a tile is selected so the delete control in the same corner stays legible. */
.tile.selected .tile-who{opacity:.5}

.tile-del{
  position:absolute;top:3px;right:3px;width:22px;height:22px;border:0;border-radius:0;
  background:rgba(17,20,24,.82);color:#fff;font-size:13px;line-height:1;font-weight:800;
  display:none;align-items:center;justify-content:center;
}
.tile.selected .tile-del{display:flex}
.tile-del:hover{background:#c8402f}

/* The drop placeholder: a hollow square exactly the size of a tile, so the layout does not jump
   when the tile lands. */
.placeholder{
  width:var(--tile);aspect-ratio:1/1;flex:none;border:2px dashed var(--orange);
  background:rgba(255,101,0,.08);pointer-events:none;
}

/* ---------- unranked ---------- */
.unranked-block{margin-top:26px}
.unranked-head{
  margin:0 0 8px;font-size:12px;font-weight:900;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);
  display:flex;align-items:center;gap:8px;
}
.unranked-head .count{font-weight:700;letter-spacing:.06em;color:var(--grey-inactive)}
.unranked-drop{background:var(--white);border:1px solid var(--line);min-height:150px}

/* ---------- music player ----------
   Docked bottom-right rather than a full-width bar: the board already uses the whole page width,
   and a bar would sit on top of the Unranked row. */
.player{
  position:fixed;right:18px;bottom:18px;z-index:40;width:236px;
  background:var(--near-black);color:var(--white);padding:11px 13px 12px;
  box-shadow:0 12px 30px rgba(17,20,24,.3);
  clip-path:polygon(0 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,0 100%);
}
.player-head{display:flex;align-items:center;gap:8px;margin-bottom:9px;min-width:0}
.player-cat{width:19px;height:19px;flex:none;fill:var(--orange)}
.player.playing .player-cat{animation:cat-bob .8s ease-in-out infinite}
@keyframes cat-bob{0%,100%{transform:translateY(0) rotate(-4deg)}50%{transform:translateY(-2px) rotate(4deg)}}
@media (prefers-reduced-motion:reduce){.player.playing .player-cat{animation:none}}
.player-title{
  font-size:11.5px;font-weight:700;letter-spacing:.03em;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;color:var(--white);flex:1;min-width:0;
}
.player-cog{
  width:20px;height:20px;flex:none;padding:0;border:0;background:transparent;color:rgba(255,255,255,.55);
  display:grid;place-items:center;transition:color .12s ease,transform .18s ease;
}
.player-cog svg{width:15px;height:15px;fill:currentColor}
.player-cog:hover{color:#fff;transform:rotate(25deg)}

/* Song library, opening upward so it never covers the transport controls. */
/* Positioned by script against the player, and parented to the body - see the note in app.js about
   the player clip-path clipping its own descendants. */
.song-lib{
  position:absolute;z-index:41;
  background:var(--near-black);padding:11px 12px;
  box-shadow:0 -10px 28px rgba(17,20,24,.34);
}
.song-lib-head{font-size:10px;font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:var(--grey-inactive);margin-bottom:8px}
.song-lib-list{max-height:190px;overflow-y:auto;margin-bottom:9px}
.song-lib-empty{font-size:11.5px;color:var(--muted);padding:6px 0}
.song-row{display:flex;align-items:center;gap:6px;padding:4px 0}
.song-row-name{
  flex:1;min-width:0;font-size:11.5px;color:var(--grey-inactive);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;cursor:pointer;
}
.song-row-name:hover{color:#fff}
.song-row.on .song-row-name{color:var(--orange);font-weight:800}
.song-row-del{
  width:18px;height:18px;flex:none;border:0;background:transparent;color:rgba(255,255,255,.35);
  font-size:14px;line-height:1;padding:0;display:grid;place-items:center;
}
.song-row-del:hover{color:#ff8b7a}
.song-lib-add{
  width:100%;border:1px dashed rgba(255,255,255,.28);background:transparent;color:var(--grey-inactive);
  font-size:11px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;padding:8px;
}
.song-lib-add:hover{border-color:var(--orange);color:var(--orange)}
.song-lib-status{font-size:10.5px;color:var(--muted);min-height:14px;margin-top:6px;text-align:center}

.player-controls{display:flex;align-items:center;gap:6px}
.pbtn{
  width:28px;height:28px;flex:none;border:0;background:rgba(255,255,255,.08);color:var(--white);
  font-size:12px;line-height:1;display:grid;place-items:center;padding:0;transition:background .12s ease;
}
.pbtn:hover{background:rgba(255,255,255,.18)}
.pbtn.play{background:var(--orange);width:32px;height:32px;font-size:13px}
.pbtn.play:hover{filter:brightness(1.1);background:var(--orange)}
.pvol{
  flex:1;min-width:0;height:4px;margin-left:4px;-webkit-appearance:none;appearance:none;
  background:rgba(255,255,255,.22);cursor:pointer;
}
.pvol::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;background:var(--white);border:0;cursor:pointer}
.pvol::-moz-range-thumb{width:12px;height:12px;background:var(--white);border:0;cursor:pointer}
@media (max-width:720px){.player{right:10px;bottom:10px;width:200px}}

/* ---------- profile review ---------- */
.mode-chip{
  font-size:10px;font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:var(--orange);
  border:1px solid rgba(255,101,0,.4);padding:3px 8px;
}
.range-select{
  font-family:inherit;font-size:11.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  padding:10px 10px;border:1px solid var(--line);background:var(--white);color:var(--near-black);cursor:pointer;
}

/* Placeholder for a profile Steam gave us no avatar for. Dark square, orange mark, faint paw -
   never a broken image icon. */
.tile-placeholder{
  background:var(--near-black);position:relative;
}
.tile-placeholder::after{
  content:"";position:absolute;inset:0;
  background:var(--orange);opacity:.5;
  -webkit-mask:var(--paw-mask) center/44% no-repeat;mask:var(--paw-mask) center/44% no-repeat;
}

.profile-pop{
  position:absolute;z-index:70;background:var(--white);border:1px solid var(--line);
  padding:16px;width:250px;text-align:center;box-shadow:0 14px 34px rgba(17,20,24,.22);
  clip-path:polygon(0 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,0 100%);
}
.pp-avatar{width:76px;height:76px;margin:0 auto 10px;background:var(--near-black);position:relative;overflow:hidden}
.pp-avatar img{width:100%;height:100%;object-fit:cover}
.pp-avatar.pp-fallback::after{
  content:"";position:absolute;inset:0;background:var(--orange);opacity:.5;
  -webkit-mask:var(--paw-mask) center/46% no-repeat;mask:var(--paw-mask) center/46% no-repeat;
}
.pp-name{font-size:15px;font-weight:800;word-break:break-word;margin-bottom:2px}
.pp-privacy{font-size:10.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--orange);margin-bottom:6px}
.pp-meta{font-size:11.5px;color:var(--muted);line-height:1.6;margin-bottom:12px}
.pp-acts{display:flex;flex-direction:column;gap:7px}
.pp-acts .btn-ghost{justify-content:center;text-decoration:none;padding:9px 12px;font-size:11.5px}

/* create-list modal */
.modal-h{margin:0 0 14px;font-size:18px;font-weight:900;letter-spacing:-.01em}
.type-opts{display:flex;flex-direction:column;gap:8px;margin-bottom:16px}
.type-opt{
  text-align:left;padding:11px 13px;border:1px solid var(--line);background:var(--off-white);
  color:var(--near-black);transition:border-color .12s ease,background .12s ease;
}
.type-opt b{display:block;font-size:13px;font-weight:800;letter-spacing:.02em}
.type-opt span{display:block;font-size:11.5px;color:var(--muted);margin-top:2px}
.type-opt.on{border-color:var(--orange);background:rgba(255,101,0,.08)}
.type-opt:hover{border-color:var(--near-black)}

/* ---------- modal ---------- */
.modal-back{position:fixed;inset:0;background:rgba(17,20,24,.55);display:grid;place-items:center;z-index:50}
.modal-back[hidden]{display:none}
.modal{
  background:var(--white);padding:24px 24px 18px;width:min(92vw,400px);
  clip-path:polygon(0 0,100% 0,100% calc(100% - 14px),calc(100% - 14px) 100%,0 100%);
}
.modal p{margin:0 0 18px;font-size:14.5px;line-height:1.5}
.modal-acts{display:flex;gap:10px;justify-content:flex-end}

@media (max-width:720px){
  :root{--tile:74px}
  .tier-label{width:66px}
  .editor-wrap{padding:16px 12px 70px}
  .home-head{flex-direction:column;align-items:flex-start}
}
