/* RSG Tool Library — light-first, airy. Dark is a toggle, not the default.
   Surfaces are deliberately far apart in luminance so cards actually read as cards. */
:root{
  --bg:#f4f6f9;          /* page */
  --surface:#ffffff;     /* cards, columns, nav */
  --raised:#f8fafc;      /* inputs, chips, subtle fills */
  --line:#e3e8ef;        /* hairlines */
  --line-2:#cfd6e0;      /* stronger borders (inputs) */
  --txt:#171a1f;
  --dim:#616a76;
  --accent:#2f6bdb;
  --accent-soft:#eaf1ff;
  --gold:#b4740a;
  --gold-soft:#fdf3e0;
  --bad:#c0392f;
  --bad-soft:#fdeceb;
  --good:#1f7a4d;
  --good-soft:#e8f6ee;
  --shadow:0 1px 2px rgba(16,24,40,.05), 0 1px 3px rgba(16,24,40,.06);
  --shadow-lift:0 2px 4px rgba(16,24,40,.06), 0 8px 20px rgba(16,24,40,.08);
  --r:12px;              /* card radius */
  --r-sm:8px;
}
:root[data-theme="dark"]{
  --bg:#14161a;
  --surface:#1e2127;
  --raised:#262a31;
  --line:#2f343d;
  --line-2:#3b414b;
  --txt:#e9ecf1;
  --dim:#9aa4b2;
  --accent:#6ea8fe;
  --accent-soft:#1d2b45;
  --gold:#ffd479;
  --gold-soft:#3a3016;
  --bad:#ff9b9b;
  --bad-soft:#3a2326;
  --good:#7ddba3;
  --good-soft:#16301f;
  --shadow:0 1px 2px rgba(0,0,0,.3);
  --shadow-lift:0 4px 20px rgba(0,0,0,.4);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--bg);color:var(--txt);
  font:15px/1.65 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Inter,sans-serif;
  -webkit-font-smoothing:antialiased;
}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}

/* ── nav ─────────────────────────────────────────────────────────────── */
nav{
  display:flex;align-items:center;gap:6px;flex-wrap:wrap;
  padding:11px 22px;background:var(--surface);
  border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:20;
}
nav>a{padding:6px 11px;border-radius:var(--r-sm);color:var(--dim);font-weight:500}
nav>a:hover{background:var(--raised);color:var(--txt);text-decoration:none}
nav .brand{font-weight:650;color:var(--txt);font-size:15.5px;margin-right:10px;padding-left:0}
nav .brand:hover{background:none}
nav .spacer{flex:1}
nav .who{font-size:12.5px;color:var(--dim);padding:0 6px}
nav .add{background:var(--accent);color:#fff;font-weight:600;padding:7px 14px}
nav .add:hover{background:var(--accent);filter:brightness(.94);color:#fff;text-decoration:none}
.badge{background:var(--gold-soft);color:var(--gold);border-radius:20px;padding:1px 7px;font-size:11.5px;font-weight:700}

/* ── layout ──────────────────────────────────────────────────────────── */
main{padding:30px 22px 80px;max-width:1440px;margin:0 auto}
h1{font-size:26px;line-height:1.25;font-weight:650;margin:0 0 6px;letter-spacing:-.01em}
h2{font-size:17px;font-weight:620;margin:34px 0 12px;letter-spacing:-.005em}
h3{font-size:13px;font-weight:600;color:var(--dim);margin:0 0 8px;text-transform:none;letter-spacing:0}
p{margin:0 0 12px}
.hint{color:var(--dim);font-size:13.5px}
.inline{display:inline}
.mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:12.5px}

/* ── controls ────────────────────────────────────────────────────────── */
button,.btn{
  background:var(--surface);color:var(--txt);border:1px solid var(--line-2);
  border-radius:var(--r-sm);padding:8px 14px;cursor:pointer;font:inherit;font-size:14px;
  transition:background .12s,border-color .12s,box-shadow .12s;
}
button:hover,.btn:hover{background:var(--raised);border-color:var(--dim);text-decoration:none}
button.primary,.btn.primary{background:var(--accent);color:#fff;border-color:var(--accent);font-weight:600}
button.primary:hover,.btn.primary:hover{filter:brightness(.94);background:var(--accent);color:#fff}
button.danger{border-color:color-mix(in srgb,var(--bad) 45%,transparent);color:var(--bad);background:var(--surface)}
button.danger:hover{background:var(--bad-soft);border-color:var(--bad)}
button.linkish{background:none;border:none;color:var(--dim);padding:0;font-size:13px;text-decoration:underline}
button.linkish:hover{background:none;color:var(--txt)}

input,select,textarea{
  background:var(--surface);color:var(--txt);border:1px solid var(--line-2);
  border-radius:var(--r-sm);padding:9px 11px;font:inherit;font-size:14px;width:100%;
}
input:focus,select:focus,textarea:focus{
  outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);
}
textarea{resize:vertical;min-height:84px;line-height:1.6}
label{display:block;font-size:13px;font-weight:550;color:var(--txt);margin:16px 0 5px;text-transform:none;letter-spacing:0}

.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:20px;box-shadow:var(--shadow)}
.err{background:var(--bad-soft);border:1px solid color-mix(in srgb,var(--bad) 30%,transparent);color:var(--bad);padding:11px 14px;border-radius:var(--r-sm);margin:12px 0}
.ok{background:var(--good-soft);border:1px solid color-mix(in srgb,var(--good) 30%,transparent);color:var(--good);padding:11px 14px;border-radius:var(--r-sm);margin:12px 0;word-break:break-all}
.centered{max-width:400px;margin:11vh auto}

/* ── language + theme switches ───────────────────────────────────────── */
.langsw{display:inline-flex;border:1px solid var(--line-2);border-radius:20px;overflow:hidden;margin:0 4px}
.langsw a{padding:3px 10px;font-size:11.5px;font-weight:600;color:var(--dim);background:transparent}
.langsw a:hover{color:var(--txt);background:var(--raised);text-decoration:none}
.langsw a.on{background:var(--accent);color:#fff}
.langtop{text-align:right;max-width:400px;margin:11vh auto -10vh}
.themebtn{background:none;border:1px solid var(--line-2);border-radius:20px;width:32px;height:26px;
  padding:0;font-size:13px;line-height:1;color:var(--dim)}
.themebtn:hover{background:var(--raised)}


/* ── row density: S / M / L ──────────────────────────────────────────────
   One set of variables drives the whole row, so a mode is a handful of numbers
   rather than three copies of the layout. Set on <html> before first paint. */
:root{
  --dn-pad-y:4px; --dn-pad-l:5px; --dn-th-w:72px; --dn-th-h:48px;
  --dn-name:13px; --dn-sum:11.5px; --dn-stack:row; --dn-align:baseline;
  --dn-gap:9px; --dn-rowgap:4px; --dn-ph:13px;
}
:root[data-density="s"]{
  --dn-pad-y:2px; --dn-pad-l:4px; --dn-th-w:33px; --dn-th-h:24px;
  --dn-name:12.5px; --dn-sum:11px; --dn-rowgap:3px; --dn-ph:9px;
}
:root[data-density="l"]{
  --dn-pad-y:8px; --dn-pad-l:7px; --dn-th-w:156px; --dn-th-h:102px;
  --dn-name:14.5px; --dn-sum:12.5px; --dn-stack:column; --dn-align:flex-start;
  --dn-gap:3px; --dn-rowgap:6px; --dn-ph:24px;
}
/* at L the thumbnail is already legible, so the hover popup would just be in the way */
:root[data-density="l"] .tr-pop{display:none !important}

.densw{display:inline-flex;border:1px solid var(--line-2);border-radius:7px;overflow:hidden}
.densw button{
  background:var(--surface);border:0;border-right:1px solid var(--line);
  padding:0 9px;height:30px;font-size:12px;font-weight:600;color:var(--dim);border-radius:0;
}
.densw button:last-child{border-right:0}
.densw button:hover{background:var(--raised);color:var(--txt)}
.densw button.on{background:var(--accent);color:#fff}

/* ── pipeline board ──────────────────────────────────────────────────── */
.lane-label{font-size:12.5px;font-weight:600;color:var(--dim);text-transform:none;letter-spacing:0;margin:26px 0 10px}
.board{display:flex;gap:14px;overflow-x:auto;padding-bottom:12px;align-items:flex-start}
.col{
  flex:0 0 250px;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;box-shadow:var(--shadow);
}
.col>h4{
  margin:0;padding:12px 14px 11px;font-size:13.5px;font-weight:620;
  display:flex;align-items:center;gap:2px;border-bottom:1px solid var(--line);
}
.col>h4 span:last-child{margin-left:auto;color:var(--dim);font-weight:500;font-size:12.5px}
/* the well is tinted so white cards inside it actually read as cards */
.col .items{padding:10px;display:flex;flex-direction:column;gap:8px;min-height:30px;background:var(--bg)}
.tcard{
  display:block;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-sm);padding:11px 13px;color:var(--txt);box-shadow:var(--shadow);
  transition:box-shadow .13s,border-color .13s,transform .13s;
}
.tcard:hover{border-color:var(--line-2);box-shadow:var(--shadow-lift);text-decoration:none;transform:translateY(-1px)}
.tcard b{font-weight:600;font-size:13.5px;display:block;line-height:1.4;word-break:break-word}
.tcard .meta{font-size:12.5px;color:var(--dim);margin-top:3px;display:block}
.sdot{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:8px;flex:none}

.pill{display:inline-block;font-size:11.5px;font-weight:600;padding:2px 9px;border-radius:20px;background:var(--raised);color:var(--dim);border:1px solid var(--line)}
.pill.wip{background:var(--gold-soft);color:var(--gold);border-color:transparent}
.pill.deprecated{background:var(--bad-soft);color:var(--bad);border-color:transparent}
.pill.ed{background:var(--accent-soft);color:var(--accent);border-color:transparent}

/* ── unified find bar + tool rows (board = search) ───────────────────── */
.findbar{
  display:flex;gap:10px;align-items:center;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:12px 14px;box-shadow:var(--shadow);
  /* --navh is measured at runtime, so this stays flush even when the nav wraps */
  position:sticky;top:var(--navh,62px);z-index:10;margin-bottom:8px;
}
.findbar #find{flex:1 1 340px;font-size:15.5px;padding:10px 14px}
.findbar select{width:auto;flex:0 0 auto}
.findbar .gapchk{margin:0;display:flex;align-items:center;gap:6px;font-size:13px;font-weight:500;white-space:nowrap}
.findbar .gapchk input{width:auto}
.findcount{margin-left:auto;font-size:13px;color:var(--dim);white-space:nowrap}

.lanewrap[hidden],.stagesec[hidden],.trow[hidden],.emptyrow[hidden]{display:none}
.stagesec{margin-bottom:18px}
.stagehead{
  margin:0 0 8px;padding:2px 0 2px 11px;font-size:14px;font-weight:620;
  display:flex;align-items:center;gap:2px;
}
.stagehead .cnt{margin-left:auto;color:var(--dim);font-weight:500;font-size:12.5px}
.rows{display:flex;flex-direction:column;gap:var(--dn-rowgap)}
.emptyrow{padding:8px 14px;font-size:13px}

/* background Drive publish status — a failed sync has to be visible, or someone thinks
   their tool shipped when it didn't */
.dstate{border-radius:var(--r-sm);padding:8px 10px;margin-bottom:10px;font-size:13px;
  border:1px solid var(--line);background:var(--bg)}
.dstate .dmsg{margin-top:4px;word-break:break-word}
.d-queued,.d-running{border-color:#e0a83c66}
.d-ok{border-color:#6ec07866}
.d-failed{border-color:var(--bad);background:color-mix(in srgb,var(--bad) 8%,transparent)}

/* delete affordance: present but quiet — it only gains colour on hover, so a row of
   content doesn't read as a row of destructive buttons */
/* rows reviewed since you last looked — the point of the page is spotting these */
.justin td{background:var(--accent-soft)}
.justin td:first-child{box-shadow:inset 3px 0 0 var(--accent)}

.delx{margin-left:6px}
.xbtn{
  background:none;border:0;padding:0 4px;cursor:pointer;line-height:1;
  color:var(--dim);opacity:.45;font-size:12px;transition:opacity .12s,color .12s;
}
.xbtn:hover{opacity:1;color:var(--bad)}
.trow{
  display:flex;align-items:center;gap:10px;line-height:1.25;
  background:var(--surface);border:1px solid var(--line);border-radius:6px;
  padding:var(--dn-pad-y) 9px var(--dn-pad-y) var(--dn-pad-l);color:var(--txt);box-shadow:var(--shadow);
  transition:border-color .12s,box-shadow .12s,transform .12s;
}
.trow:hover{border-color:var(--line-2);box-shadow:var(--shadow-lift);text-decoration:none;transform:translateY(-1px)}
/* The title link is stretched over the whole row, so the row stays one big click target
   while the quick-action buttons remain real, separately clickable controls (an <a>
   inside an <a> is invalid and breaks middle-click / open-in-new-tab). */
.trow{position:relative}
.tr-link{color:inherit;text-decoration:none}
.tr-link::after{content:"";position:absolute;inset:0;z-index:0}
/* Fenced off from the status icons, which are information rather than controls — side by
   side at the same weight, nothing read as clickable. */
.tr-actions{position:relative;z-index:1;display:flex;gap:4px;flex:0 0 auto;
  margin-left:2px;padding-left:9px;border-left:1px solid var(--line)}
.qbtn{
  display:inline-flex;align-items:center;justify-content:center;gap:4px;
  height:21px;padding:0 7px;border-radius:5px;text-decoration:none;
  font-size:12px;font-weight:600;line-height:1;white-space:nowrap;
  border:1px solid var(--line-2);background:var(--raised);color:var(--txt);
  transition:border-color .12s,color .12s,background .12s,box-shadow .12s;
}
.qbtn:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-soft)}
/* download is the one people come to a row for — make it unmistakably a button */
.qbtn.dl{background:var(--accent);border-color:var(--accent);color:#fff}
.qbtn.dl:hover{background:#2559b8;border-color:#2559b8;color:#fff;box-shadow:var(--shadow)}
.qbtn .qico{font-size:13px}

.tr-thumb{flex:0 0 auto;width:var(--dn-th-w);height:var(--dn-th-h);border-radius:5px;overflow:hidden;position:relative;
  display:flex;align-items:center;justify-content:center;background:var(--bg);
  border:1px solid var(--line)}
.tr-thumb img{width:100%;height:100%;object-fit:cover;display:block}
/* Hovering the thumbnail shows the shot at a useful size. This is how the row stays
   thin without the picture being decorative — the detail costs no vertical space. */
.tr-pop{display:none;position:absolute;left:0;top:calc(100% + 6px);z-index:40;
  width:260px;border:1px solid var(--line-2);border-radius:8px;overflow:hidden;
  background:var(--surface);box-shadow:var(--shadow-lift);pointer-events:none}
.tr-pop img{width:100%;height:auto;display:block;aspect-ratio:3/2;object-fit:cover;background:var(--bg)}
.tr-thumb:hover .tr-pop{display:block}
/* flipped by JS when there isn't room below — a CSS nth-child guess was wrong,
   since a section holding one tool would flip it upward even at the top of the page */
.tr-thumb.flip .tr-pop{top:auto;bottom:calc(100% + 6px)}

/* most tools have no screenshot — the placeholder is the common case, not the exception */
.tr-ph{display:flex;align-items:center;justify-content:center;width:100%;height:100%;
  font-weight:700;font-size:var(--dn-ph);
  color:hsl(var(--h) 55% 45%);background:hsl(var(--h) 55% 45% / .13)}
@media (prefers-color-scheme: dark){ .tr-ph{color:hsl(var(--h) 60% 70%)} }
:root[data-theme="dark"] .tr-ph{color:hsl(var(--h) 60% 70%)}
:root[data-theme="light"] .tr-ph{color:hsl(var(--h) 55% 45%)}

.tr-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:var(--dn-stack);
  align-items:var(--dn-align);gap:var(--dn-gap);overflow:hidden}
.tr-name{font-weight:600;font-size:var(--dn-name);display:flex;align-items:center;gap:6px;
  flex:0 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tr-sum{font-size:var(--dn-sum);color:var(--dim);flex:1 1 auto;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* the right-hand block is fixed content (stages, tags, author, buttons); the description
   is what shrinks, so it must be allowed to go narrower than its text */
.tr-side{min-width:0}
.tr-stages{display:flex;gap:4px;flex-wrap:nowrap}
.stchip{border:1px solid;border-radius:20px;padding:1px 7px;font-size:10.5px;font-weight:600;
  white-space:nowrap;line-height:1.5}
:root[data-density="s"] .stchip{font-size:9.5px;padding:0 5px}
.tr-side{display:flex;align-items:center;gap:10px;flex:0 0 auto}
.tr-stages{display:flex;gap:4px}
.tr-tags{display:flex;gap:4px;align-items:center}
.chip.sm{font-size:11.5px;padding:1px 8px}
.tr-owner{font-size:11.5px;color:var(--dim);min-width:84px;text-align:right;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tr-icons{display:flex;gap:6px;font-size:11.5px;min-width:66px;justify-content:flex-end;
  color:var(--dim);opacity:.62}
.tr-icons .gap{color:var(--gold)}
@media(max-width:820px){
  .tr-side{gap:8px}
  .tr-owner,.tr-tags{display:none}
}

/* ── grids / search ──────────────────────────────────────────────────── */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px}
.filters{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end;margin:14px 0 26px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:16px 18px;box-shadow:var(--shadow)}
.filters label{margin:0 0 5px}
.filters>div{min-width:140px}
.filters input,.filters select{width:auto;min-width:140px}

/* ── tool page ───────────────────────────────────────────────────────── */
.cols{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:28px;align-items:start}
@media(max-width:960px){.cols{grid-template-columns:1fr}}
.chips{display:flex;gap:6px;flex-wrap:wrap;margin:8px 0}
.chip{background:var(--surface);border:1px solid var(--line-2);border-radius:20px;padding:3px 11px;font-size:12.5px}
.shots{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:12px}
.shots img{width:100%;border-radius:var(--r-sm);background:var(--raised);display:block;border:1px solid var(--line)}
.cap{font-size:12.5px;color:var(--dim);margin-top:5px}
.md{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:22px 26px;box-shadow:var(--shadow)}
.md :first-child{margin-top:0}
.md :last-child{margin-bottom:0}
.md h1,.md h2{font-size:18px;font-weight:620;margin:26px 0 10px;color:var(--txt)}
.md h3,.md h4{font-size:15px;font-weight:620;margin:20px 0 8px;color:var(--txt);text-transform:none}
.md p,.md li{line-height:1.7}
.md ol,.md ul{padding-left:22px}
.md li{margin:4px 0}
.md code{background:var(--raised);border:1px solid var(--line);padding:1.5px 5px;border-radius:5px;font-size:.9em}
.md pre{background:var(--raised);border:1px solid var(--line);padding:14px 16px;border-radius:var(--r-sm);overflow:auto}
.md pre code{background:none;border:none;padding:0}
.md blockquote{margin:14px 0;padding:2px 0 2px 16px;border-left:3px solid var(--line-2);color:var(--dim)}
.md img,.docprev img{max-width:100%;border-radius:var(--r-sm);border:1px solid var(--line)}
.md table{margin:14px 0}

.log{border-left:2px solid var(--line);padding-left:18px}
.log .entry{margin-bottom:16px}
.log .v{font-weight:700;color:var(--accent)}
.log .when{font-size:12.5px;color:var(--dim);margin-left:6px}

table{width:100%;border-collapse:collapse;font-size:14px}
th,td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);vertical-align:middle}
th{font-size:12.5px;font-weight:600;color:var(--dim);text-transform:none;letter-spacing:0}
tbody tr:hover td,tr:hover td{background:var(--raised)}

.row{display:flex;gap:12px;align-items:center}
.row>*{flex:1}
.row>.narrow{flex:0 0 150px}
.sub{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:18px;margin-bottom:14px;box-shadow:var(--shadow)}
.diff{font-size:12.5px;background:var(--raised);border:1px solid var(--line);border-radius:var(--r-sm);padding:12px 14px;overflow:auto;max-height:300px;line-height:1.6}
.diff .add{color:var(--good)}
.diff .rem{color:var(--bad)}

/* ── feedback ────────────────────────────────────────────────────────── */
.fbitem{background:var(--surface);border:1px solid var(--line);border-left:3px solid var(--line-2);
  border-radius:var(--r-sm);padding:13px 16px;margin-bottom:10px;box-shadow:var(--shadow)}
.fbitem.fb-issue{border-left-color:var(--bad)}
.fbitem.fb-tip{border-left-color:var(--good)}
.fbitem.fb-note{border-left-color:var(--accent)}
.fbhead{display:flex;gap:9px;align-items:center;font-size:13px;margin-bottom:5px}
.fbbody{white-space:pre-wrap;font-size:14px;line-height:1.65}
.pill.fbk-issue{background:var(--bad-soft);color:var(--bad);border-color:transparent}
.pill.fbk-tip{background:var(--good-soft);color:var(--good);border-color:transparent}
.pill.fbk-note{background:var(--accent-soft);color:var(--accent);border-color:transparent}

/* ── doc editor ──────────────────────────────────────────────────────── */
.doced{border:1px solid var(--line-2);border-radius:var(--r);overflow:hidden;background:var(--surface);box-shadow:var(--shadow)}
.dtabs{display:flex;align-items:center;gap:5px;padding:8px 10px;background:var(--raised);border-bottom:1px solid var(--line);flex-wrap:wrap}
.dtab{background:transparent;border:1px solid transparent;color:var(--dim);border-radius:var(--r-sm);padding:5px 12px;font-size:13px}
.dtab.on{background:var(--surface);border-color:var(--line-2);color:var(--txt);font-weight:600}
.tb{background:transparent;border:1px solid transparent;color:var(--dim);border-radius:6px;padding:4px 8px;font-size:13px;min-width:30px}
.tb:hover{border-color:var(--line-2);color:var(--txt);background:var(--surface)}
.dsep{width:1px;height:18px;background:var(--line-2);margin:0 4px}
.doced textarea{border:none;border-radius:0;background:var(--surface);min-height:360px;
  font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:13px;line-height:1.7;padding:18px}
.doced textarea:focus{box-shadow:none}
.docprev{border:none;border-radius:0;min-height:360px;max-height:62vh;overflow:auto;box-shadow:none}

/* the chosen cover, shown on the tool page so it is obvious which image represents the
   tool everywhere else. Sized to hint at the card face rather than dominate the page. */
.coverwrap{display:flex;align-items:flex-end;gap:10px;margin:0 0 14px}
.coverwrap img{width:220px;max-width:45vw;aspect-ratio:3/2;object-fit:cover;
  border:1px solid var(--line);border-radius:var(--r-sm);display:block;box-shadow:var(--shadow)}

/* ── card view ────────────────────────────────────────────────────────────
   A fourth mode on the same switch rather than a separate page: the markup is the
   row's, so the live filtering, the counter and the stage/tag data all keep working
   untouched. Cards just re-flow the same element as a grid and promote the image. */
.cardface{display:none}
:root[data-density="c"] .rows{
  display:grid;gap:12px;
  grid-template-columns:repeat(auto-fill,minmax(210px,1fr));
}
:root[data-density="c"] .trow{
  flex-direction:column;align-items:stretch;padding:0;gap:0;overflow:hidden;
  border-radius:var(--r);
}
:root[data-density="c"] .trow:hover{transform:translateY(-2px);box-shadow:var(--shadow-lift)}
/* the image + title become the card face; the row's own thumb and summary step aside */
:root[data-density="c"] .cardface{
  display:block;position:relative;aspect-ratio:3/4;background:var(--bg);
}
:root[data-density="c"] .cardface img{width:100%;height:100%;object-fit:cover;display:block}
:root[data-density="c"] .cardface .tr-ph{width:100%;height:100%;font-size:40px}
:root[data-density="c"] .cardname{
  /* The link covers the whole image, with the text sitting at the bottom -- so the click
     target is the card, not just the title. A stretched ::after would not do it: .cardname
     is itself positioned, so inset:0 resolves against the title strip. */
  position:absolute;inset:0;
  display:flex;flex-direction:column;justify-content:flex-end;align-items:flex-start;gap:3px;
  padding:26px 10px 9px;
  color:#fff;line-height:1.25;
  /* fades out well before the top, so the picture is not dimmed -- it only has to keep the
     title legible over an arbitrary screenshot */
  background:linear-gradient(to top,rgba(0,0,0,.85) 0,rgba(0,0,0,.5) 22%,transparent 46%);
  text-shadow:0 1px 3px rgba(0,0,0,.6);
  text-decoration:none;
  transition:background .16s;
}
:root[data-density="c"] .cardname:hover{text-decoration:none;color:#fff}
:root[data-density="c"] .cardtitle{font-size:13.5px;font-weight:650}

/* The summary appears on hover.
   Its space is reserved at all times and only opacity changes, so the card never resizes and
   the grid never reflows under the cursor. An earlier version animated max-height together
   with -webkit-line-clamp; that combination did not behave -- the declared display was being
   dropped -- and fading a fixed box is both simpler and impossible to get wrong. */
:root[data-density="c"] .cardsum{
  font-size:11.5px;font-weight:400;line-height:1.35;
  height:4.05em;overflow:hidden;      /* ~3 lines, longer summaries are simply clipped */
  /* Readable at rest and emphasised on hover, rather than hidden until hover. Degrading this
     way means the description is never unreachable -- if hover never fires (touch, keyboard
     navigation, a stylus) the text is still there, just quieter. */
  opacity:.72;transition:opacity .15s ease;
}
:root[data-density="c"] .trow:hover .cardsum{opacity:1}
/* darken further while the summary is showing, or four lines of white text over a bright
   screenshot is unreadable */
:root[data-density="c"] .trow:hover .cardname{
  background:linear-gradient(to top,rgba(0,0,0,.9) 0,rgba(0,0,0,.72) 45%,rgba(0,0,0,.15) 100%);
}
/* touch devices get no hover, so show it there rather than hiding it forever */
@media (hover: none){
  :root[data-density="c"] .cardsum{opacity:.9}
}
:root[data-density="c"] .tr-thumb,
:root[data-density="c"] .tr-main{display:none}
:root[data-density="c"] .tr-side{
  display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 10px 9px;min-width:0;
}
:root[data-density="c"] .tr-stages{flex-wrap:wrap}
:root[data-density="c"] .tr-owner{min-width:0;text-align:left;flex:1 1 100%;order:-1}
:root[data-density="c"] .tr-tags{display:none}
:root[data-density="c"] .tr-icons{min-width:0}
:root[data-density="c"] .tr-actions{margin-left:auto;padding-left:0;border-left:0}

/* a grouped submission: one person, one tool, several pieces -- approved as a unit */
.grouphdr{
  display:flex;align-items:center;gap:14px;justify-content:space-between;flex-wrap:wrap;
  background:var(--accent-soft);border:1px solid color-mix(in srgb,var(--accent) 25%,transparent);
  border-radius:var(--r-sm);padding:11px 14px;margin:14px 0 6px;
}
