/* content.css — P5 content screens (Upload, Feed, File explorer, Details, Profile).
   Ported from the gallery (the visual law); tokens only; reuses the P3 primitives
   and never redefines what primitives.css / shell.css already own. Built up one
   surface at a time as P5 lands. */

/* ── Upload sheet (P5.11) ────────────────────────────────────────────────── */
.fl{display:block;font-size:12px;color:var(--muted);margin:var(--s2) 0 5px}   /* P12: tightened 14→8 to match the V1 dialog density */
.fl:first-child{margin-top:0}
/* drop area — real dropzone (click to pick, drag to drop); once files are chosen
   it collapses to the compact "name · N files" summary the gallery shows. */
.dropzone{background:var(--surface);border:1px dashed var(--line2);border-radius:var(--r);padding:16px 14px;text-align:center;font-size:var(--fs-sm);color:var(--muted);cursor:pointer;transition:border-color var(--t),background var(--t)}   /* P12: 22→16 vertical */
.dropzone:hover,.dropwrap.over .dropzone{border-color:var(--ink);background:var(--plate)}
.dropzone .ic{width:22px;height:22px;color:var(--soft);margin-bottom:6px}
/* the whole dropwrap accepts a drop (so it registers before AND after files are chosen); it
   flashes a ring while a drag is over it */
.dropwrap{border-radius:var(--r)}
.dropwrap.over .dropchosen{outline:1px dashed var(--ink);outline-offset:2px}
/* chosen-files state (renderChosen) — a header row + a scrollable file list + flatten toggle */
.dropchosen{background:var(--surface);border-radius:var(--r);padding:12px 14px;display:flex;flex-direction:column;gap:8px}
.chosenhd{display:flex;align-items:center;gap:8px;font-size:var(--fs-sm);color:var(--soft)}
.chosenhd b{color:var(--ink);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chosenhd .ic{color:var(--muted);flex:none}
.chosenhd .chosentot{color:var(--muted);font-size:var(--fs-xs);font-variant-numeric:tabular-nums;flex:none}
/* P22: each row is editable — an inline rename input + a per-file tag editor. Taller list; a row
   is a column (name line + tags). Affordance comes from the field borders, not row dividers. */
.chosenlist{max-height:300px;overflow-y:auto;display:flex;flex-direction:column;gap:10px}
.chosenrow{display:flex;flex-direction:column;gap:6px;font-size:var(--fs-xs);color:var(--soft)}
.chosenrow .cnhead{display:flex;align-items:center;gap:8px;min-width:0}
.chosenrow .cndir{flex:none;max-width:38%;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;direction:rtl;text-align:left}
.chosenrow .chosenname{flex:1;min-width:0;background:var(--bg);border:1px solid var(--line2);border-radius:var(--r);padding:4px 8px;font-size:var(--fs-xs);color:var(--ink)}
.chosenrow .chosenname:focus{outline:none;border-color:var(--ink)}
.chosenrow .cs{flex:none;color:var(--muted);font-variant-numeric:tabular-nums}
/* the per-row tag editor sits under the name; hide its multi-line hint to keep rows compact
   (typing still recolours a recognised type in the input — that affordance stays) */
.chosenrow .cntags .tageditor{gap:6px}
.chosenrow .cntags .taghint{display:none}
.chosenmore{font-size:var(--fs-mi);color:var(--muted);padding-top:2px}
/* P23: the subfolder-tags section in a folder upload — same rows as the file list, a labelled group */
.chosenfolders{margin-top:var(--s3)}
.chosensec{font-size:var(--fs-mi);font-weight:600;color:var(--muted)}
.chosenfolders .cndir{max-width:none;direction:ltr}
.dropchosen .flatten{display:flex;align-items:center;gap:8px;font-size:var(--fs-xs);color:var(--soft);cursor:pointer;margin-top:2px}
.dropsummary{background:var(--surface);border-radius:var(--r);padding:14px;font-size:12px;color:var(--muted);text-align:center}
.dropsummary b{color:var(--soft);font-weight:600}
/* "Add details" disclosure — fast post keeps it collapsed */
.addmore{margin-top:var(--s3)}   /* P12: 16→12 */
.addmore>summary{list-style:none;display:flex;align-items:center;gap:7px;cursor:pointer;font-size:var(--fs-sm);font-weight:600;color:var(--soft);padding:8px 0;user-select:none}
.addmore>summary::-webkit-details-marker{display:none}
.addmore>summary .ic{transition:transform var(--t);color:var(--muted)}
.addmore[open]>summary .ic{transform:rotate(180deg)}
.addmore>summary:hover{color:var(--ink)}
/* storage-impact line — which storage the bytes draw (cohesive with the details
   Storage row + the tree footer) */
.ustore{display:flex;align-items:center;gap:7px;font-size:var(--fs-xs);color:var(--muted);background:var(--surface);border-radius:var(--r);padding:8px 10px;margin-top:8px}
.ustore .ic{color:var(--soft);flex:none}.ustore b{color:var(--soft);font-weight:600}
/* .uprogress removed — upload progress is now the P16 .uplwidget bar (primitives.css) */

/* ── Feed / explorer shared pane (P5.1/P5.4) ─────────────────────────────── */
.pane{flex:1;min-width:0;display:flex;flex-direction:column;background:var(--paper);overflow:hidden;position:relative}
.panehd{flex:none;height:46px;display:flex;align-items:center;gap:var(--s4);padding:0 var(--s4);background:var(--surface)}   /* P18: unified header height 46 + --s4 inset */
.panehd .wm{font-weight:700;font-size:var(--fs-xl)}
.panehd .title{font-weight:600;font-size:var(--fs-lg)}
.panehd nav{margin-left:auto;display:flex;gap:var(--s4)}
.toolbar{position:relative;flex:none;display:flex;align-items:center;gap:var(--s2);padding:var(--s3) var(--s4);background:var(--paper);flex-wrap:wrap}
.toolbar .field{flex:1;min-width:170px;max-width:340px}
/* P27/P34/P38 (2026-08-31) — the search field's autocomplete helper wraps the field so the popover
   can anchor under it; the wrapper (not the inner field) is the toolbar's actual flex item now. */
.searchcombo{position:relative;flex:1;min-width:170px;max-width:340px}
.searchcombo .field.searchbar{max-width:none}
.searchcombo .pop{position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:12;width:auto;
  background:var(--paper);border-radius:var(--r);box-shadow:0 8px 24px rgba(0,0,0,.16),0 0 0 1px var(--line);overflow:hidden;padding:4px 0}
.searchcombo .poprow{display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:6px 10px;font-size:var(--fs-sm);color:var(--soft);cursor:default}
.searchcombo .poprow b{color:var(--ink);font-weight:600}
.searchcombo .poprow .hl{margin-left:auto;color:var(--muted);font-size:var(--fs-mi)}
.searchcombo .poprow:hover,.searchcombo .poprow.hi{background:var(--surface)}
.searchcombo .poprow:hover b,.searchcombo .poprow.hi b{color:var(--ink)}
.searchcombo .exacsw{width:8px;height:8px;border-radius:2px;flex:none}
/* the filter rail (P27/P34/P38) — one --mod chip per committed modifier; the row itself costs zero
   height when empty ([hidden] wins over the flex display below). Sits between the toolbar and the
   body, its own thin row so it never competes with the toolbar's Sort/Group/view controls. */
.exmods{flex:none;display:flex;flex-wrap:wrap;gap:6px;padding:0 var(--s4) var(--s3)}
.exmods[hidden]{display:none}
/* owner 2026-09-01: was a --mod (muted mauve) chip — still read as "just another colour" next to
   the monochrome system (CANON prime directive: the ONLY colour is the member hue + --danger).
   INVERTED ink instead — the same idiom already used for an active/pressed state (.btn:active,
   .iconbtn:active, selected nav) — reads as "this filter is ON" without adding a hue. */
.mchip{display:inline-flex;align-items:center;gap:5px;background:var(--ink);
  color:var(--on-ink);border-radius:var(--r);padding:3px 4px 3px 8px;font-size:var(--fs-xs);font-weight:600;white-space:nowrap}
.mchip .k{opacity:.72;font-weight:600}
.mchip .x{display:grid;place-items:center;width:18px;height:18px;border-radius:2px;color:inherit;opacity:.75}
.mchip .x:hover{background:color-mix(in srgb,var(--on-ink) 25%,transparent);opacity:1}
.mchip .x .ic{width:11px;height:11px}
/* owner 2026-08-31: the explorer toolbar search field reads too tall next to its own row — the
   toolbar's buttons/iconbtns are all ~26px, the field stuck up past them. Thin it to match (scoped
   to the toolbar, not the shared .searchbar class other screens use — "the file explorer gets away
   with it", not necessarily the standalone /search screen or the quick-switcher).
   owner 2026-09-01: thinner still — match .btn's own padding (3px, not 4px) so the field's total
   box height comes out equal to a toolbar button's (3px*2 + 12px*1.3 line-height + 2px border ≈
   23.6px both ways), not just close to it. */
.toolbar .field.searchbar{padding:3px 9px}
/* owner 2026-08-31: a hairline under the toolbar so it's obvious where the selectable pane begins
   (vs the chrome above, where a drag just highlights). B31: a file browser isn't text — marquee/drag
   must not highlight filenames (Finder/Drive). */
.panebody{flex:1;overflow-y:auto;padding:var(--s4);position:relative;user-select:none;box-shadow:inset 0 1px 0 var(--line)}
.panebody input,.panebody textarea,.panebody [contenteditable]{user-select:text}   /* but a real field (inline rename) stays selectable */
/* B31: the drag token — a small kind icon (not the card thumbnail). Rendered off-screen so
   setDragImage can snapshot it; square badge for the count (round is avatars/dots only). */
.dragghost{position:fixed;top:-1000px;left:-1000px;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;background:var(--paper);border:1px solid var(--line2);border-radius:var(--r);color:var(--ink)}
.dragghost .dgcount{position:absolute;top:-6px;right:-6px;min-width:16px;height:16px;padding:0 3px;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;background:var(--ink);color:var(--on-ink);font-size:10px;font-weight:600;border-radius:var(--r)}
/* B10 — marquee (rubber-band) select rectangle + a drop target while dragging a file onto a card */
.marquee{position:absolute;z-index:4;background:color-mix(in srgb,var(--ink) 8%,transparent);border:1px solid var(--line2);border-radius:2px;pointer-events:none}
/* C22: a drop target fills + rings its media (a confident "this will receive"), and a pill overlay
   names the action. Folder = "Move N here", file = "New folder". */
.card.droptarget .media{position:relative;background:color-mix(in srgb,var(--ink) 12%,var(--surface));box-shadow:inset 0 0 0 2px var(--ink)}
.card.droptarget .media > *{opacity:.35}
.droppill{position:absolute;left:50%;bottom:10px;transform:translateX(-50%);z-index:4;opacity:1!important;display:inline-flex;align-items:center;gap:5px;
  background:var(--ink);color:var(--on-ink);font-size:var(--fs-mi);font-weight:600;padding:3px 9px;border-radius:var(--r);white-space:nowrap;pointer-events:none}
.droppill .ic{width:12px;height:12px;color:var(--on-ink)}
.seclabel{color:var(--muted);font-size:var(--fs-xs);font-weight:600;margin:0 0 var(--s3)}

/* ── P13: file-channel header (V2 + owner tweaks) ─────────────────────────────
   A slim dedicated path line (breadcrumb only), the filter set + view/hidden controls grouped
   to the right of the search in the toolbar, and New folder + Upload floated bottom-right. */
.expath{flex:none;display:flex;align-items:center;min-height:30px;padding:var(--s2) var(--s4);background:var(--paper)}   /* P18: --s4 inset to align with the toolbar + body below. B36: --paper (not --surface) so the path line reads as one surface with the toolbar + body — a --surface step here showed as a stray lighter bar across the top in dark mode (--surface #171717 on --paper #0A0A0A chrome). */
.expath .crumbs{flex-wrap:nowrap;overflow:hidden}
.crumbs .crumbroot.home{display:inline-flex;align-items:center;color:var(--soft);padding:0}
.crumbs .crumbroot.home:hover{color:var(--ink)}
.toolbar .tbfilters{display:flex;align-items:center;gap:var(--s2);margin-left:auto;flex-wrap:wrap;justify-content:flex-end}
.toolbar .tbfilters .hdctl{margin-left:2px}
/* bottom-right floating action cluster — the bare square eski buttons (plain New folder +
   primary Upload), no backing box; each button carries its own fill so it reads over the grid. */
.exfab{position:absolute;right:var(--s5);bottom:calc(30px + var(--s3));display:flex;gap:var(--s2);z-index:5}   /* C17: lifted above the status strip */
.pane.hasfab .panebody{padding-bottom:52px}
/* C17 status strip — a --surface step at the pane foot; item count / selection tally / current sort */
.exstatus{flex:none;height:30px;display:flex;align-items:center;gap:var(--s3);padding:0 var(--s4);background:var(--surface);color:var(--muted);font-size:var(--fs-xs);font-variant-numeric:tabular-nums}
.exstatus .stsel{color:var(--ink);font-weight:600}
.exstatus .sp{flex:1}
.exstatus .stsort{display:inline-flex;align-items:center;gap:6px}
.exstatus .stsort .ic{width:13px;height:13px}

/* ── File explorer (P5.4): nested tree + views ───────────────────────────── */
.explayout{flex:1;min-width:0;display:flex;overflow:hidden}
.explayout .pane{flex:1;min-width:0}
/* C29 docked info panel — a right column (Drive's "i" sidebar); reuses the .meta rows from the
   details viewer so the fields are identical. Separates from the pane by a hairline. */
.exinfo{display:none}
.explayout.hasinfo .exinfo{flex:none;width:300px;min-width:0;background:var(--paper);box-shadow:-1px 0 0 var(--line);display:flex;flex-direction:column;min-height:0}
.exihead{flex:none;display:flex;align-items:center;justify-content:space-between;padding:var(--s3) var(--s4);position:relative}
.exihead::after{content:"";position:absolute;left:var(--hair-inset);right:var(--hair-inset);bottom:0;height:1px;background:var(--line)}
.exititle{font-size:var(--fs-sm);font-weight:600;color:var(--ink)}
.exiscroll{flex:1;min-height:0;overflow-y:auto;padding:var(--s4)}
.exiprev{aspect-ratio:16/11;border-radius:var(--r);overflow:hidden;background:var(--surface);display:grid;place-items:center;margin-bottom:var(--s4)}
.exiprev.exipico{color:var(--muted)} .exiprev.exipico .ic{width:40px;height:40px}
.exiprev img{width:100%;height:100%;object-fit:cover}
.exiname{font-size:var(--fs);font-weight:600;color:var(--ink);line-height:1.3;margin-bottom:var(--s3);overflow-wrap:anywhere}
.exisec{margin-top:var(--s3)}
.exilabel{font-size:var(--fs-mi);text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:600;margin-bottom:7px}
.exifoot{flex:none;display:flex;gap:7px;padding:var(--s3) var(--s4);position:relative}
.exifoot::before{content:"";position:absolute;left:var(--hair-inset);right:var(--hair-inset);top:0;height:1px;background:var(--line)}
.exifoot .btn{flex:1}
.exiempty{padding:var(--s5) var(--s4);color:var(--muted);font-size:var(--fs-sm);text-align:center;display:flex;flex-direction:column;gap:5px}
@media(max-width:900px){.exinfo{width:250px}}
.explayout .panehd{justify-content:space-between}
.filetree{flex:none;width:212px;background:var(--surface);overflow-y:auto;padding:8px 6px;display:flex;flex-direction:column}
/* B28: drag handle to resize the folder-tree column */
.exresizer{flex:none;width:6px;cursor:col-resize;position:relative;background:transparent;touch-action:none}
.exresizer::before{content:"";position:absolute;top:0;bottom:0;left:2px;width:1px;background:var(--line);opacity:0;transition:opacity var(--t)}
.exresizer:hover::before,.exresizer.drag::before{opacity:1;width:2px;background:var(--ink)}
.ftbottom{margin-top:auto}
.fthd{display:flex;align-items:center;justify-content:space-between;font-size:var(--fs-xs);color:var(--muted);font-weight:600;padding:4px 8px 8px}
.ftrow{display:flex;align-items:center;gap:6px;width:100%;text-align:left;padding:6px 8px;border-radius:var(--r);font-size:var(--fs-sm);color:var(--soft);cursor:pointer}
.ftrow:hover{background:var(--plate)}
.ftrow.on{background:var(--plate);color:var(--ink);font-weight:600}
.ftrow .tw{width:13px;height:13px;flex:none;color:var(--muted);transition:transform var(--t)}
.ftrow.open .tw{transform:rotate(0deg)}.ftrow:not(.open) .tw{transform:rotate(-90deg)}
.ftrow .fic{color:var(--muted);flex:none}.ftrow.on .fic{color:var(--ink)}
.ftrow .fn{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ftrow .ftmeta{margin-left:auto;font-size:10px;color:var(--muted);flex:none}
.ftrow .ftlock{margin-left:auto;width:12px;height:12px;color:var(--muted);flex:none}
.ftrow.archived{opacity:.5}
.ftsep{height:1px;background:var(--line);margin:6px 8px}
.ftrow.lvl0{padding-left:8px}.ftrow.lvl1{padding-left:22px}.ftrow.lvl2{padding-left:36px}.ftrow.lvl3{padding-left:50px}
/* Move-to-folder picker (bulk bar / card menu): the destination tree in a scroll
   well reuses .ftrow. A locked folder can't receive files, so its row is disabled. */
.movetree{max-height:240px;overflow:auto;background:var(--surface);border-radius:var(--r);padding:6px;margin-top:2px}
.movetree .ftrow[disabled]{opacity:.45;cursor:not-allowed}
.ulab{display:block;font-size:var(--fs-sm);color:var(--soft);margin-bottom:2px}
.ulab b{color:var(--ink);font-weight:600}
.svnote{display:flex;align-items:center;gap:6px;margin-top:8px;font-size:var(--fs-xs);color:var(--muted)}
.svnote .ic{flex:none;color:var(--muted)}
/* Explorer filter chrome: an active filter (with selections) reads as filled chrome
   and carries its count; the multi-select menu gets a fixed-width check gutter so the
   labels line up whether or not a row is ticked. */
.btn.exfilter.on{background:var(--plate);color:var(--ink)}
.btn.exfilter .fc{opacity:.55;margin-left:2px;font-variant-numeric:tabular-nums}
.menu button.fclear{color:var(--muted);font-size:var(--fs-xs)}
/* Trash smart-folder (gallery B19): a retention notice + Empty over soft-deleted rows,
   each with a days-left countdown (danger-red near expiry) and hover Restore/Delete. */
.trashnote{display:flex;align-items:center;gap:10px;padding:9px 12px;background:var(--surface);border-radius:var(--r);margin:0 0 var(--s3);font-size:var(--fs-sm);color:var(--soft)}
.trashnote .ic{color:var(--muted)}
.trashnote .btn{margin-left:auto}
.trrow{display:flex;align-items:center;gap:12px;padding:8px 6px;box-shadow:inset 0 -1px 0 var(--line)}
.trrow .tmed{width:34px;height:34px;flex:none;border-radius:var(--r);background:var(--surface);display:grid;place-items:center;color:var(--muted);overflow:hidden}
.trrow .tmed img{width:100%;height:100%;object-fit:cover}
.trrow .tinfo{min-width:0;flex:1}
.trrow .trname{font-size:var(--fs-sm);color:var(--soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.trrow .tsub{font-size:var(--fs-xs);color:var(--muted)}
.trrow .tleft{font-size:var(--fs-xs);color:var(--muted);flex:none}
.trrow .tleft.warn{color:var(--danger)}
.trrow .tacts{display:flex;gap:6px;flex:none;opacity:0;transition:opacity var(--t)}
.trrow:hover .tacts{opacity:1}
.ftfoot{margin-top:6px;padding:10px 8px 6px;font-size:var(--fs-xs);color:var(--muted)}
.ftfoot .bar{margin:6px 0 4px}
.crumbs{display:flex;align-items:center;gap:7px;font-size:var(--fs-sm);color:var(--muted);min-width:0;flex-wrap:wrap}
.crumbs button{color:var(--soft)}.crumbs button:hover{color:var(--ink)}
.crumbs b{color:var(--ink)}.crumbs .sl{color:var(--line2)}
.crumbs .crumbmore{padding:0 3px;font-weight:700;letter-spacing:1px;line-height:1}   /* C30: overflow "…" opener */
/* C-out: a crumb segment accepting a dragged file/folder — the same invert-on-drop idiom as a
   card's .droptarget, scaled to a breadcrumb's small text button instead of a full media tile. */
.crumbs button.droptarget{background:var(--ink);color:var(--on-ink);border-radius:var(--r);padding:1px 6px;margin:-1px -6px}
.hdctl{margin-left:auto;display:flex;align-items:center;gap:var(--s2)}
/* P32 · density slider (replaces the Grid/List dropdown). A compact range flanked by a rows icon
   (dense/list end) and a grid icon (large end). The thumb is a SQUARE (--r) ink handle, not a native
   round one — the "round is avatars/presence-dots only" rule holds. */
.densityctl{display:flex;align-items:center;gap:7px;color:var(--muted)}
.densityctl .dic{display:inline-flex}
.densityctl .dsm .ic{width:11px;height:11px}
.densityctl .dlg .ic{width:16px;height:16px}
.densityrange{-webkit-appearance:none;appearance:none;width:92px;height:16px;background:transparent;cursor:pointer;margin:0}
.densityrange::-webkit-slider-runnable-track{height:3px;background:var(--line2);border-radius:var(--r)}
.densityrange::-moz-range-track{height:3px;background:var(--line2);border-radius:var(--r)}
.densityrange::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:10px;height:14px;border-radius:var(--r);background:var(--ink);margin-top:-6px}
.densityrange::-moz-range-thumb{width:10px;height:14px;border:none;border-radius:var(--r);background:var(--ink)}
.densityrange:hover::-webkit-slider-runnable-track{background:var(--soft)}
.densityrange:hover::-moz-range-track{background:var(--soft)}
.exview[hidden]{display:none}
/* P24 server search: the transient "Searching…" state + the paged "Load more" footer.
   P35: the spinning search icon is retired — a slim indeterminate bar + a rising-ellipsis
   label reads calmer and shares the app's one indeterminate-motion vocabulary. */
.searchloading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s3);padding:var(--s6) 0;color:var(--muted);font-size:var(--fs-sm)}
.searchloading .indetbar{width:min(220px,60%)}
.loadmorewrap{display:flex;justify-content:center;padding:var(--s4) 0 var(--s5)}
.foldercard .media.fold{display:grid;place-items:center;background:var(--paper1);color:var(--muted)}   /* one step off the --surface band, like file tiles */
/* owner 2026-09-01 fix: was `.foldercard .media.fold .ic` (a descendant selector), which — with NO
   scoping — also matched the hover ⋯ button's icon nested inside .cardacts (also a .media.fold
   descendant), blowing it up to 34px in a 26px button and beating .cardacts .ic{width:15px} on raw
   specificity (4 classes vs 2) regardless of source order. The child combinator scopes this to the
   folder GLYPH only (the one direct-child <svg class="ic"> of .media.fold); .cardacts .ic (below)
   now wins for the button's own icon, undamaged. This is the "select button is all messed up" bug —
   the more-button's 3rd dot was rendering ~4px outside its own dark pill. */
.foldercard .media.fold>.ic{width:34px;height:34px}

/* ── P23 card tags (folders, and files since owner 2026-09-01) ──────────────────
   Reuses the P11 .tchip soft chip (untyped = grey, typed = its colour). On a card the preview is
   ONE line (first few + "+N") so every card is the same height; the full set + editing live in the
   tags popover (hover/click "+N" — see explorer.js wireTagTrigger). `.card` covers both — a folder
   card is always `.card.foldercard`, a file card is `.card` alone — so one rule serves both without
   a second near-duplicate for files. */
.foldercard{position:relative}
/* single-line preview inside the band's .frow (tags left, file-count right) — nowrap keeps every
   card the same height. No top margin: it's a row cell now, not stacked under the name.
   owner 2026-09-01 fix: this used to be nowrap+overflow:hidden with every chip (tags AND "+N") at
   flex:none — content overflows a nowrap row off its RIGHT edge, and "+N" is the LAST chip, so it
   was the very first thing clipped away the instant the tags before it didn't fit (long tag words,
   or a narrower card) — the opposite of what's needed. A mid-word CSS ellipsis-shrink was tried and
   rejected: shrinking chips unevenly could reduce a short tag like "wip" to one unreadable letter.
   Fixed properly in JS instead (fitTagsRow in explorer.js, called after the row is in the DOM, where
   real measured widths are available): it drops WHOLE tags from the end — never a partial, truncated
   one — bumping "+N"'s count until the row actually fits. overflow:hidden here is only a safety net
   for that pass; it should never actually be the thing doing the clipping. */
.card .cardfoot .ftags{display:flex;flex-wrap:nowrap;gap:5px;align-items:center;overflow:hidden;min-width:0}
.card .cardfoot .ftags .tchip{font-size:var(--fs-mi);padding:1px 6px;flex:none}
/* "+N more" → opens the tags popover (hover or click) */
.ftmore{font-size:var(--fs-mi);font-weight:600;color:var(--muted);padding:1px 6px;border-radius:var(--r);background:var(--surface);flex:none}
.ftmore:hover{background:var(--plate);color:var(--ink)}
/* list-row tag preview: inline after the folder name. flex:none — it must NEVER shrink to make
   room; .flnmtxt (the filename) is the one that truncates when the Name column narrows. */
.flntags{margin-top:0;margin-left:var(--s3);overflow:hidden;flex:none}
.flntags .tchip{font-size:var(--fs-mi);padding:1px 6px}
/* tags popover (a floating .menu variant → inherits the float shadow) */
.ftpop{padding:10px 12px;min-width:220px;max-width:280px}
.ftpophd{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s2);margin-bottom:9px}
.ftpopname{font-size:var(--fs-sm);font-weight:600;color:var(--ink)}
.ftpopcount{font-size:var(--fs-mi);color:var(--muted);white-space:nowrap}
.ftpop .ftseclabel{font-size:var(--fs-xs);font-weight:600;color:var(--muted);margin-bottom:6px}
.ftpop .ftags{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:9px}
.ftempty{font-size:var(--fs-xs);color:var(--muted)}
/* the colon-aware add input inside Properties */
.ftaddfield{padding:3px 8px}
.ftaddfield input{font-size:var(--fs-xs)}

/* P23/owner: every LARGE-view card fills its grid cell, so a row's cards are all the tallest card's
   height (was inline-block → content height, which tiled unevenly once tags varied). */
.masonry.even.exlarge .card{display:flex;flex-direction:column;height:100%;margin-bottom:0}
/* Group-by (grid): a labelled section per bucket (Kind/Type/Uploader/Date), each its own grid.
   owner 2026-09-01: collapsible (the .egcaret button) + selectable-as-a-whole (clicking the header
   row itself selects every item in the group, Windows-Explorer style) — see groupHeader in
   explorer.js. .masonry.collapsed hides the section's body; the header always stays. */
.exgroup{margin-bottom:var(--s5)}
.exgroup:last-child{margin-bottom:0}
.exgrouphd{display:flex;align-items:center;gap:var(--s2);margin:0 0 var(--s3);color:var(--muted);font-size:var(--fs-xs);font-weight:600;letter-spacing:.02em;cursor:pointer;border-radius:var(--r);padding:2px var(--s2);margin-left:calc(var(--s2) * -1)}
.exgrouphd:hover{background:var(--surface);color:var(--ink)}
.exgrouphd .egc{color:var(--line2);font-variant-numeric:tabular-nums}
.egcaret{width:20px;height:20px;flex:none}
.egcaret .ic{transition:transform var(--t)}
.egcaret.collapsed .ic{transform:rotate(-90deg)}
.exgroup .masonry.collapsed{display:none}
/* list view */
/* P14 · LIST density (Windows "Details"): a column per field. .nowho drops the Uploader column
   (personal files have no uploader). Rows select on click / open on double-click like the other
   densities; a selected row is a background step (rows aren't cards, so no outline). */
/* contain:layout style — same reasoning as .card above; a list of hundreds of rows shouldn't force
   a layout recheck outside the one row that changed (hover/select/inline-rename). */
.flrow{display:grid;grid-template-columns:minmax(200px,1.6fr) 84px 88px 120px 96px;gap:14px;align-items:center;padding:8px 12px;font-size:var(--fs-sm);color:var(--soft);border-radius:var(--r);cursor:pointer;contain:layout style}
.exlist.nowho .flrow{grid-template-columns:minmax(200px,1.8fr) 84px 88px 96px}
/* DIRECT children only (was `.flrow span`, a descendant selector — it also matched every span
   NESTED inside .flnm, incl. the tag chip's own spans, clipping their text independently of the
   row). Owner bug (2026-09-01, "tags in this example" clip when Details opens): narrowing the Name
   column shrank .flnm as a whole, and this rule's overflow:hidden clipped the WHOLE flex box —
   filename, icon and tag chip together — at whatever pixel it ran out of room, instead of letting
   just the filename truncate. .flnm is excluded below so its child .flnmtxt can do that instead. */
.flrow>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums}
.flrow>span.flnm{overflow:visible;text-overflow:clip;white-space:normal}
.flrow+.flrow{box-shadow:inset 0 1px 0 var(--line)}
.flrow:hover:not(.flhd){background:var(--surface)}
.flrow.sel{background:var(--plate)}
.flrow.sel:hover{background:var(--plate)}
.flrow.droptarget{outline:2px solid var(--ink);outline-offset:-2px}
.flrow.ishidden{opacity:.55}.flrow.ishidden:hover{opacity:1}
.flrow.cutdim{opacity:.5}.flrow.cutdim:hover{opacity:.75}
/* list-mode Group-by (owner 2026-09-01, matches .exgrouphd in the grid): collapsible + selectable-
   as-a-whole, same as the grid — overrides the grid template/hover the other .flrow rules set (it's
   a section header, not a data row). .flgroup wraps each group's own rows so the caret can hide/show
   them as one unit; .collapsed hides it. */
.exlist .flrow.flgrouphd{display:flex;align-items:center;gap:var(--s2);padding:10px 12px 4px;cursor:pointer;color:var(--muted);font-size:var(--fs-xs);font-weight:600;letter-spacing:.02em}
.exlist .flrow.flgrouphd:hover{background:var(--surface);color:var(--ink)}
.flgrouphd .egc{color:var(--line2);font-variant-numeric:tabular-nums}
.flgroup.collapsed{display:none}
.flhd{font-size:var(--fs-xs);color:var(--muted);font-weight:600;letter-spacing:.02em}
/* C6: click a column header to sort by it; a caret on the active column shows the direction. */
.flhd span{cursor:pointer;display:inline-flex;align-items:center;gap:4px;overflow:visible}
.flhd span:hover{color:var(--soft)}
.flhd span.on{color:var(--ink)}
.flhd .sortcar{width:12px;height:12px;color:var(--ink);transition:transform var(--t)}
.flnm{display:inline-flex;align-items:center;gap:8px;font-weight:500;color:var(--ink);min-width:0}
.flnm .ic{color:var(--muted);flex:none}
/* the filename itself is the ONLY thing in .flnm allowed to shrink/truncate — the star, icon and
   tag-preview chip all stay flex:none, so narrowing the Name column (e.g. opening Details) eats
   into the name text, never into the tag chip sitting after it. */
/* flex-GROW:0 is load-bearing (found in an eski-polish sweep, 2026-09-01): flex:1 here made the
   filename stretch to fill the ENTIRE Name column whenever it was shorter than the column's
   allocated width (Name is minmax(200px,1.6fr|1.8fr) — usually far wider than a short name needs),
   shoving the trailing tag-chip preview (.flntags, flex:none, right after this in the DOM) off to
   the column's far edge instead of sitting next to the name — "Saved from servers  ......  + tag"
   with a huge gap, for every row whose name didn't happen to already fill the column. flex-SHRINK:1
   is what the earlier clipping fix (narrow-column truncation, e.g. Details panel open) actually
   needed — grow was never required for that and only caused this. */
.flnmtxt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:0 1 auto;min-width:0}
/* C31: newFolder()'s inline name edit — a plain field-styled input dropped in place of the static
   name (grid card .fname or list row .flnmtxt), sized to read as "this text became editable", not
   as a whole new control. --ink border (not --line2) so it reads active/focused immediately, no
   separate :focus-within step needed since it's focused the instant it mounts. */
.inlineedit{width:100%;min-width:0;font:inherit;font-size:var(--fs-sm);font-weight:600;color:var(--ink);
  background:var(--paper);border:1px solid var(--ink);border-radius:var(--r);padding:1px 4px;outline:none}
/* B33: the per-row star toggle in list view — muted at rest, gold when starred (matches the grid). */
.flstar{flex:none;width:20px;height:20px;display:grid;place-items:center;border-radius:var(--r);color:var(--line2);opacity:.6;transition:color var(--t),opacity var(--t)}
.flstar .ic{width:14px;height:14px}
.flrow:hover .flstar{opacity:1}
.flstar:hover{color:var(--star)}
.flstar.on{opacity:1;color:var(--star)}
.flstar.on .ic{fill:currentColor}

/* (The "Small icons" density was cut 2026-08-31 — only Grid + List remain; its .exsmall/.smallcard
   rules were removed with it.) */
/* over-cap / locked banner */
.capbanner{display:flex;align-items:center;gap:10px;padding:9px var(--s5);background:var(--m1);color:#fff;font-size:var(--fs-sm)}
.capbanner[hidden]{display:none}
.capbanner .ic{flex:none;color:#fff}
.capbanner .btn{margin-left:auto;background:rgba(255,255,255,.16);color:#fff}
.capbanner .btn:hover{background:rgba(255,255,255,.28)}
/* (The bulk-action selbar — B32, an ink bar overlaying the toolbar on selection — was retired
   2026-09-01: it occluded the toolbar's own controls and read as disconnected chrome. The
   selection count lives in .exstatus (below) and bulk actions are a right-click away — openBulkMenu
   in explorer.js.) */
/* card selection + hover actions (grid) */
/* contain:layout+style isolates each card from the rest of the grid — a hover/select/tag-chip-fit
   change inside one card no longer forces the browser to re-check layout across the other hundreds
   of siblings (OPTIMIZATION.md/"general jank": no CSS containment anywhere). layout ONLY, never
   paint/content-visibility here: .card.sel::before below deliberately paints outside the card's own
   box (a -6px halo) and paint containment would clip it. */
.card{position:relative;z-index:0;contain:layout style}
.card .media{position:relative;border-radius:var(--r)}   /* C16: media rounds to the chrome radius */
/* C16 (owner-approved "new cards"): a selected card is the WHOLE tile — a --plate fill + a 2px ink
   ring drawn BEHIND the content (::before, so the media/title never shift), with CONCENTRIC corner
   radii for balance: media = --r (3px); the selection halo sits 6px outside, so its radius = --r + 6
   = 9px (concentric, curves stay parallel); the corner check is --r chrome. */
.card.sel::before{content:"";position:absolute;inset:-6px;z-index:-1;background:var(--plate);border-radius:9px;box-shadow:inset 0 0 0 2px var(--ink);pointer-events:none}   /* decorative — must NOT catch the marquee: its -6px halo would otherwise block starting a rubber-band in the gap next to a selected card */
/* B33 (owner 2026-08-31): the corner select-checkbox was removed — it collided with the star (both
   top-left) and read as a "weird white square". Selection shows via the .card.sel ring; you
   multi-select by click / ⌘-click / marquee. The ⋯ hover cluster stays top-right. */
.cardacts{position:absolute;top:6px;right:6px;z-index:3;display:none;gap:3px}
.card:hover .cardacts{display:flex}
.cardacts button{width:26px;height:26px;display:grid;place-items:center;border-radius:var(--r);background:rgba(20,20,20,.55);color:#fff;cursor:pointer;transition:background var(--t),color var(--t)}
.cardacts button:hover{background:rgba(20,20,20,.85)}
.cardacts button:active{background:#fff;color:#131313}
.cardacts .ic{width:15px;height:15px}
/* B33: ONE star, top-left, click-to-toggle — the indicator AND the toggle (they used to be an
   indicator top-left + a separate hover-action top-right that swapped on hover). A ghost star fades
   in on card hover so you can star; a starred card keeps it visible + gold-filled. --r radius (round
   is avatars/dots only). */
.cardstar{position:absolute;top:6px;left:6px;z-index:3;width:24px;height:24px;display:grid;place-items:center;border-radius:var(--r);
  background:color-mix(in srgb,var(--paper) 60%,transparent);color:var(--muted);cursor:pointer;
  opacity:0;transition:opacity var(--t),color var(--t),background var(--t)}
.cardstar .ic{width:16px;height:16px}
/* C32: always-on status badges (hidden/public on files, locked on folders), bottom-right of the
   thumbnail — clear of the star (top-left) and the hover ⋯ (top-right). A quiet chip, square at --r. */
.card .media .cardbadges{position:absolute;right:6px;bottom:6px;z-index:2;display:flex;gap:4px}
.card .media .cbadge{display:grid;place-items:center;width:19px;height:19px;border-radius:var(--r);
  background:color-mix(in srgb,var(--paper) 82%,transparent);color:var(--soft)}
.card .media .cbadge .ic{width:12px;height:12px}
.card:hover .cardstar{opacity:1}
.cardstar:hover{color:var(--star);background:color-mix(in srgb,var(--paper) 82%,transparent)}
.cardstar.on{opacity:1;color:var(--star)}
.cardstar.on .ic{fill:currentColor}
/* the Starred quick-filter toggle (in line with the filters): gold when active */
.iconbtn.exstar.on{color:var(--star);background:var(--plate)}
/* a pressed icon toggle (e.g. Show-hidden) reads as filled chrome */
.iconbtn.on{background:var(--plate);color:var(--ink)}
/* #55 a hidden/utility work, revealed by Show-hidden, reads dimmed (same signal as an
   archived tree row) — no new chrome, just lowered presence. */
.card.ishidden{opacity:.55}
.card.ishidden:hover{opacity:1}
/* C4: a card on the Cut clipboard reads dimmed — "already on its way out" — same idiom as
   Finder/Explorer's cut-dim. Same opacity language as .ishidden above, on purpose. */
.card.cutdim{opacity:.5}
.card.cutdim:hover{opacity:.75}
.card .media img.shot{object-fit:cover}
.who .uchip{margin-right:2px}

/* ── Details pane (P5.5) — the ONE media viewer (CANON §C.7, eski-style §5) ──
   The arena: media takes the room (left, grows), a fixed ~380px info rail right,
   on a scrim (no drop shadow). Ported verbatim from gallery.html and scoped under
   .sheet so the generic names (.meta/.row/.foot/.cmt/.by/.tx) never leak (the
   leaked-.msg trap). The media-player pieces (.dmbigplay/.dmtransport/.tbtn/
   .navarrow) are the P3 primitives — reused, not redefined. */
.sheet{position:fixed;z-index:81;inset:0;display:grid;place-items:center;padding:var(--s4);background:rgba(0,0,0,.55)}
:root:not([data-theme="light"]) .sheet,
:root[data-theme="dark"] .sheet{background:rgba(0,0,0,.66)}
.sheet .card2{width:min(1360px,96vw);height:min(880px,94vh);background:var(--paper);border-radius:var(--r);display:flex;overflow:hidden}
.sheet .dmedia{flex:1;min-width:0;background:var(--paper1);display:flex;align-items:center;justify-content:center;position:relative;padding:40px}
.sheet .dmedia.bare{padding:0}
.sheet .dmedia>img{max-width:100%;max-height:100%;object-fit:contain}
.sheet .dmedia>.dmplayer{width:100%;height:100%;background:none}
.sheet .dmedia>.dmplayer .dmmedia{height:100%}
.sheet .dmedia>.dmplayer video{height:100%;object-fit:contain}
/* type card fills the well (never a small top-left box, never a fake thumb) */
.sheet .dtype{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;color:var(--muted)}
.sheet .dtype .ic,.sharedview .dtype .ic{width:46px;height:46px}
.sheet .dtype .ext,.sharedview .dtype .ext{font-size:var(--fs-xl);font-weight:700;letter-spacing:.05em;color:var(--soft)}
.sheet .dtype .nb,.sharedview .dtype .nb{font-size:11px;color:var(--muted)}
/* PDF: the browser's own renderer fills the well, no chrome of ours needed */
.sheet .dpdf,.sharedview .dpdf{width:100%;height:100%;border:0;background:var(--paper)}
/* text/markdown/json/… preview: real monospace text, wrapped and scrollable, never HTML-rendered
   (fillMedia sets it via textContent only — see the comment there on why). Left-aligned unlike the
   centered dtype card since this IS the content, not a placeholder. */
.sheet .dtext,.sharedview .dtext{position:absolute;inset:0;margin:0;overflow:auto;padding:28px 32px;
  font:13px/1.6 ui-monospace,'SF Mono',Consolas,monospace;color:var(--ink);background:var(--paper);
  white-space:pre-wrap;word-break:break-word;text-align:left}
/* info rail */
.sheet .dinfo{flex:none;width:380px;min-width:0;display:flex;flex-direction:column;overflow:hidden;background:var(--paper)}
.sheet .dtop{position:relative;flex:none;display:flex;align-items:center;gap:6px;padding:var(--s3) var(--s4)}
.sheet .dtop::after{content:"";position:absolute;left:var(--hair-inset);right:var(--hair-inset);bottom:0;height:1px;background:var(--line)}
.sheet .dtop .sp{margin-left:auto}
.sheet .dfilename{font-size:var(--fs-xs);color:var(--soft);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sheet .scroll{flex:1;overflow-y:auto;padding:0 var(--s4) var(--s4)}
.sheet .dinfo h2{font-size:var(--fs-lg);font-weight:600;margin:var(--s4) 0 var(--s3)}
/* dense are.na metadata: key left (muted), value right (ink) */
/* meta/tags rows are shared by the details pane (.sheet), the shared-link viewer (.sharedview),
   and the explorer's own docked details rail (.exinfo, C29) — one definition, three scopes, so
   they can't drift apart. BUG (2026-09-01, owner: "the details side panel is styled horribly") —
   .exinfo was added to the CONTAINER rule below when C29 landed but never to the .row/.k/.v rules
   that actually lay a row out, so the docked panel's label and value rendered as plain inline
   content with zero flex/gap between them (literally touching: "LocationMy files", "AddedAug 12").
   metaRows() (screens/details.js) is the ONE shared builder for all three surfaces — this was
   always a CSS scoping gap, never a markup difference. */
.sheet .meta,.sharedview .meta,.exinfo .meta{display:flex;flex-direction:column;gap:var(--s1);margin:0 0 var(--s3);font-size:var(--fs-sm)}
/* B29: align the key to the TOP so a long value can wrap cleanly beside it (was center + a
   nowrap/ellipsis value that truncated long filenames). */
.sheet .meta .row,.sharedview .meta .row,.exinfo .meta .row{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;min-height:22px}
.sheet .meta .k,.sharedview .meta .k,.exinfo .meta .k{flex:none;color:var(--muted);font-size:var(--fs-xs);line-height:1.35;padding-top:1px}
.sheet .meta .v,.sharedview .meta .v,.exinfo .meta .v{flex:1;min-width:0;color:var(--ink);text-align:right;line-height:1.35;overflow-wrap:anywhere;word-break:break-word}
.sheet .metalink,.exinfo .metalink{padding:0;font-weight:600;color:var(--ink);font-size:var(--fs-sm);cursor:pointer}
.sheet .metalink:hover,.exinfo .metalink:hover{text-decoration:underline}
.sheet .loccrumb,.exinfo .loccrumb{display:inline-flex;align-items:center;gap:5px;justify-content:flex-end;flex-wrap:wrap}
.sheet .loccrumb button,.exinfo .loccrumb button{color:var(--soft);line-height:1.2;display:inline-flex;align-items:center;gap:4px}
.sheet .loccrumb button:hover,.exinfo .loccrumb button:hover{color:var(--ink)}
.sheet .loccrumb .ic,.exinfo .loccrumb .ic{width:13px;height:13px;color:var(--muted)}
.sheet .loccrumb .sl,.exinfo .loccrumb .sl{color:var(--line2)}
/* sections (tags, comments) */
.sheet .dsec,.sharedview .dsec{margin-top:var(--s4)}
.sheet .dsec .lb,.sharedview .dsec .lb{color:var(--muted);font-size:var(--fs-xs);font-weight:600;margin-bottom:8px}
.sheet .chips,.sharedview .chips{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.sheet .addtag{width:22px;height:22px;display:grid;place-items:center;border-radius:var(--r);color:var(--muted);cursor:pointer}
.sheet .addtag:hover{background:var(--surface);color:var(--ink)}
.sheet .addtag .ic{width:13px;height:13px}
/* comment styles removed with post-commenting (P4, 2026-08-30) */
/* footer actions — inset hairline on top, buttons share width */
.sheet .foot{position:relative;flex:none;padding:var(--s3) var(--s4);display:flex;gap:var(--s2)}
.sheet .foot::after{content:"";position:absolute;left:var(--hair-inset);right:var(--hair-inset);top:0;height:1px;background:var(--line)}
.sheet .foot .btn{flex:1;justify-content:center}
/* folder navigation list in the rail */
.sheet .flist{display:flex;flex-direction:column;gap:2px;max-height:340px;overflow-y:auto}
.sheet .flist .fi{display:flex;align-items:center;gap:9px;padding:6px 8px;border-radius:var(--r);cursor:pointer;font-size:var(--fs-sm);text-align:left;width:100%}
.sheet .flist .fi:hover{background:var(--surface)}
.sheet .flist .fi.on{background:var(--plate)}
.sheet .flist .fi .fth{width:28px;height:28px;border-radius:3px;background:var(--plate);flex:none;display:grid;place-items:center;color:var(--muted)}
.sheet .flist .fi .fn{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media(max-width:760px){.sheet .card2{flex-direction:column}.sheet .dmedia{min-height:42vh;flex:none}.sheet .dinfo{width:100%}}

/* ── Shared-link viewer (P5.16, CANON #40) — a standalone read-only page ────────
   Ported from the gallery. Covers the rail (it isn't inside the shell): a share link
   opens ONLY the shared item, no way to browse the rest of the server. Media reuses the
   details-pane dispatch (fillMedia → .dtype in the well); meta/tags rows are the shared
   .meta/.dsec/.chips defined above. NO member hue (anon / out-of-server). */
/* Share dialog (#39) link-management rows — a stack of active links, each a readonly URL
   field + Copy + Revoke, plus a Create-link button. Lives inside a .modal .ubody. */
.sharelinks{display:flex;flex-direction:column;gap:8px;margin-top:2px}
.sharelinks .sharerow2{display:flex;align-items:center;gap:8px}
.sharelinks .sharerow2 .field{flex:1;min-width:0}
.sharelinks .sharerow2 .field input{min-width:0}
.sharelinks .sharenone{font-size:var(--fs-sm);color:var(--muted)}
/* invite-management rows: the link+actions row, then a small usage/expiry line beneath it. */
.sharelinks .invitem{display:flex;flex-direction:column;gap:3px}
.sharelinks .invmeta{font-size:var(--fs-xs);color:var(--muted);padding-left:2px}
/* invite-by-handle: suggested-people rows (ported from the gallery invite modal). A
   person here is NOT a server member yet, so the name stays neutral bold — the member
   hue is server-scoped and doesn't apply to a non-member. */
.shareppl{display:flex;flex-direction:column;gap:2px;margin-top:6px}
.sharerow{display:flex;align-items:center;gap:10px;padding:6px 4px}
.sharerow .nm{flex:1;min-width:0;font-size:var(--fs-sm);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sharerow .nm b{font-weight:600}
.sharerow .nm .acc{color:var(--muted);font-weight:400;margin-left:5px}
.sharerow .invited{font-size:var(--fs-xs);color:var(--muted);display:inline-flex;align-items:center;gap:5px}
.sharenone{font-size:var(--fs-sm);color:var(--muted)}
/* server-settings icon/cover picker (ported from gallery). The cover is a wide rectangle, the
   icon a smaller ink square — both radius --r (chrome), both crop to fill. */
.frow{margin-bottom:2px}
.coverpick{display:flex;gap:10px;align-items:center;margin-top:4px}
.coverpick .cv{width:132px;height:78px;background:var(--paper1);border-radius:var(--r);display:grid;place-items:center;color:var(--muted);overflow:hidden}
.coverpick .cv.icon{width:64px;height:64px;background:var(--ink);color:var(--on-ink);font-weight:700;font-size:var(--fs-lg)}
.coverpick .cv img{width:100%;height:100%;object-fit:cover}
/* Edit-profile banner well (gallery .epbanner) — a wide preview with the upload button pinned
   bottom-right; the picked/stored banner fills it. Media stays square (--r), no round. */
.epbanner{height:84px;background:var(--paper1) center/cover no-repeat;border-radius:var(--r);display:flex;align-items:flex-end;justify-content:flex-end;padding:8px;margin-bottom:10px}
/* audit log — a read-only moderation feed; rows separate by row, not borders. */
.auditlist{display:flex;flex-direction:column;max-height:340px;overflow:auto;margin:-4px -4px 0}
.auditlist .arow{display:flex;align-items:flex-start;gap:10px;padding:8px 6px;border-radius:var(--r)}
.auditlist .arow:hover{background:var(--surface)}
.auditlist .aic{flex:none;width:22px;height:22px;display:grid;place-items:center;color:var(--muted)}
.auditlist .abd{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.auditlist .atx{font-size:var(--fs-sm);color:var(--soft)}
.auditlist .atx b{color:var(--ink);font-weight:600}
.auditlist .asub{font-size:var(--fs-xs);color:var(--muted)}
.auditlist .atime{flex:none;font-size:var(--fs-xs);color:var(--muted)}

.sharedview{position:fixed;inset:0;z-index:70;display:flex;flex-direction:column;background:var(--paper);overflow-y:auto}
.sharedview .svhd{flex:none;display:flex;align-items:center;gap:var(--s3);padding:0 var(--s4);height:46px;background:var(--surface)}   /* P18: unified header */
.sharedview .svhd .brand{font-weight:700;font-size:var(--fs-lg);letter-spacing:.02em}
.sharedview .svhd .svctx{font-size:var(--fs-sm);color:var(--muted)}
.sharedview .svhd .svacts{margin-left:auto;display:flex;gap:var(--s2)}
.sharedview .svbody{flex:1;display:grid;grid-template-columns:1fr 340px;gap:var(--s5);padding:var(--s5);width:100%;max-width:1180px;margin:0 auto}
.sharedview .svmedia{position:relative;background:var(--paper1);border-radius:var(--r);min-height:440px;display:flex;align-items:center;justify-content:center;padding:var(--s5)}
.sharedview .svmedia.bare{padding:0}
.sharedview .svmedia>img{max-width:100%;max-height:100%;object-fit:contain}
.sharedview .svmedia>.dmplayer{width:100%;height:100%;background:none}
.sharedview .svmedia .dtype{position:static;height:auto;background:none;display:flex;flex-direction:column;align-items:center;gap:12px;color:var(--muted)}
.sharedview .svmeta h1{font-size:var(--fs-xl);font-weight:600;margin-bottom:var(--s4)}
.sharedview .svbody.svexpired{display:block;text-align:center;max-width:460px}
.sharedview .deadshare{padding:calc(var(--s5)*2) 0;text-align:center}
.sharedview .deadshare .deadicon{width:64px;height:64px;border-radius:var(--r);background:var(--plate);display:grid;place-items:center;margin:0 auto var(--s3)}
.sharedview .deadshare .deadicon .ic{width:26px;height:26px;color:var(--muted)}
.sharedview .deadshare h1{font-size:var(--fs-xl);font-weight:600}
.sharedview .deadshare .lead{color:var(--muted);font-size:var(--fs-sm);margin-top:var(--s2)}
@media(max-width:760px){.sharedview .svbody{grid-template-columns:1fr}}

/* ── Notifications (P7.3, CANON §C) — in-app notification list ──────────────────
   Ported from the gallery. Unread rows carry an ink dot; per-row ✓ + "Mark all read". */
.notif{flex:1;min-width:0;display:flex;flex-direction:column;background:var(--paper)}
.notif .notifhd{flex:none;min-height:56px;display:flex;align-items:center;gap:var(--s4);padding:var(--s3) var(--s5);background:var(--surface);flex-wrap:wrap}
.notif .notifhd .t{font-weight:600;font-size:var(--fs-lg)}
.notif .ntabs{display:flex;gap:var(--s4)}
.notif .ntab{color:var(--soft);font-size:var(--fs-sm);padding-bottom:2px;cursor:pointer}
.notif .ntab.on{color:var(--ink);font-weight:600;box-shadow:inset 0 -2px 0 var(--ink)}
.notif .notifhd .mark{margin-left:auto;font-size:var(--fs-xs);color:var(--muted);cursor:pointer}
.notif .notifhd .mark:hover{color:var(--ink)}
.notif .npanel{flex:1;overflow-y:auto;padding:var(--s3) var(--s5) var(--s5)}
.notif .nrow{position:relative;display:flex;gap:var(--s3);padding:11px var(--s3) 11px var(--s4);border-radius:var(--r);cursor:pointer}
.notif .nrow:hover{background:var(--surface)}
.notif .nrow.unread::before{content:"";position:absolute;left:6px;top:50%;transform:translateY(-50%);width:7px;height:7px;border-radius:50%;background:var(--ink)}
.notif .nrow .nic{flex:none;width:30px;height:30px;border-radius:50%;background:var(--surface);color:var(--soft);display:grid;place-items:center}
.notif .nrow:hover .nic{background:var(--plate)}
.notif .nrow .nbd{flex:1;min-width:0}
.notif .nrow .ntx{font-size:var(--fs-sm);color:var(--soft)}.notif .nrow .ntx b{color:var(--ink);font-weight:600}
.notif .nrow .nctx{font-size:var(--fs-xs);color:var(--muted);margin-top:2px}
.notif .nrow .quote{margin-top:6px;font-size:var(--fs-xs);color:var(--soft);padding-left:10px;box-shadow:inset 2px 0 0 var(--line)}
.notif .nrow time{font-size:var(--fs-xs);color:var(--muted);flex:none}
.notif .nrow .nacts{position:absolute;top:7px;right:7px;display:none;gap:2px;background:var(--paper);border-radius:var(--r)}
.notif .nrow:hover .nacts{display:flex}
.notif .nrow .nacts button{width:26px;height:26px;display:grid;place-items:center;color:var(--muted);border-radius:var(--r);transition:background var(--t),color var(--t)}
.notif .nrow .nacts button:hover{background:var(--surface);color:var(--ink)}
/* P1: .emptystate now centers globally (shell.css) — the per-pane margin:auto patch is gone. */

/* ── Messages + Friends (P7.1, CANON §C) — DM thread list + friends panel ──────
   Ported from the gallery. The .dmlist is a channel-width column; the right pane swaps
   between a conversation (P7.2) and the friends panel. No member hue (outside any server). */
.screen[data-screen="dms"]{display:flex;flex:1;min-height:0;overflow:hidden}
.dmlist{flex:none;width:var(--chan);background:var(--surface);display:flex;flex-direction:column;overflow:hidden}
.dmlist .hd{height:46px;flex:none;display:flex;align-items:center;padding:0 var(--s4);background:var(--plate);font-weight:600;font-size:var(--fs-sm)}   /* P18: 46px */
.dmadd{padding:var(--s3)}
.dmrows{flex:1;overflow-y:auto;padding:0 var(--s2)}
.dmrow .pendlbl{margin-left:auto;color:var(--muted);font-size:var(--fs-xs)}   /* P5: outgoing request label */
.dmrow{display:flex;align-items:center;gap:var(--s2);padding:7px var(--s2);border-radius:var(--r);cursor:pointer;transition:background var(--t)}
.dmrow:hover,.dmrow.on{background:var(--plate)}
.dmrow .nm{font-size:var(--fs-sm);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dmrow .dmtrail{margin-left:auto;display:flex;align-items:center;gap:4px;flex:none}
.dmrow .dmtrail>.ic{color:var(--muted)}
.dmrow .more2{color:var(--muted);opacity:0;flex:none;display:grid;place-items:center;width:22px;height:22px;border-radius:var(--r)}
.dmrow:hover .more2{opacity:1}
.dmrow .more2:hover{background:var(--surface);color:var(--ink)}
.dmrow.group .gav{display:flex;flex:none}
.dmrow.group .gav .av{margin-left:-8px;box-shadow:0 0 0 2px var(--surface)}
.dmrow.group .gav .av:first-child{margin-left:0}
.dmsec{padding:8px 14px 4px;color:var(--muted);font-size:var(--fs-xs);font-weight:600}
.dmnone{padding:14px;color:var(--muted);font-size:var(--fs-sm)}
.dmright{flex:1;min-width:0;display:flex}
.dmmain{flex:1;min-width:0;display:flex;flex-direction:column;background:var(--paper)}
.dmmain .mainhd{flex:none;height:46px;display:flex;align-items:center;gap:var(--s3);padding:0 var(--s4);background:var(--surface)}   /* P18: unified header */
.dmmain .mainhd .t{font-weight:600}.dmmain .mainhd .sub{color:var(--muted);font-size:var(--fs-sm)}
/* P1: .emptystate now centers globally (shell.css) — the per-pane margin:auto patch is gone. */
/* P5: the standalone Friends panel (.friends/.frhd/.frtabs/.frrow…) was removed — friends now
   live inline in the .dmlist column. Its CSS is gone with it; .rbtn (accept/decline) stays. */
.rbtn{width:26px;height:26px;display:grid;place-items:center;border-radius:var(--r);background:var(--surface);color:var(--soft);transition:background var(--t),color var(--t)}
.rbtn:hover{background:var(--plate);color:var(--ink)}
.rbtn.ok:hover{color:var(--m3)}.rbtn.no:hover{color:var(--m1)}
/* Quick-switcher (⌘K) — a global jump palette overlaid near the top (above menus, below toasts) */
.qs{position:fixed;inset:0;z-index:92;display:flex;justify-content:center;padding-top:12vh;background:rgba(0,0,0,.4)}
.qsbox{width:min(560px,92vw);max-height:60vh;display:flex;flex-direction:column;background:var(--paper);border-radius:var(--r);overflow:hidden;box-shadow:0 12px 48px rgba(0,0,0,.3)}
.qshd{flex:none;display:flex;align-items:center;gap:9px;padding:8px 12px;background:var(--surface)}
.qshd .ic{color:var(--muted)}
.qshd input{flex:1;background:none;border:none;color:var(--ink);font-size:var(--fs-sm)}
.qshd input:focus{outline:none}
.qslist{overflow-y:auto;padding:6px}
.qsrow{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:var(--r);cursor:pointer}
.qsrow.on{background:var(--plate)}
.qsic{width:26px;height:26px;display:grid;place-items:center;color:var(--soft);flex:none}
.qsav{width:26px;height:26px;flex:none;display:grid;place-items:center;border-radius:var(--r);background:var(--ink);color:var(--on-ink);font-size:10px;font-weight:700}
.qsbd{display:flex;flex-direction:column;min-width:0}
.qslabel{font-size:var(--fs-sm);font-weight:600;color:var(--ink)}
.qssub{font-size:var(--fs-xs);color:var(--muted)}
.qsnone{padding:14px;color:var(--muted);font-size:var(--fs-sm)}
/* Inline message edit — the .tx body swaps to this input (Enter save / Esc cancel) */
.editrow{margin-top:2px}
.editinput{width:100%;max-width:520px;background:var(--paper1);border:1px solid var(--line2);border-radius:var(--r);padding:6px 10px;color:var(--ink);font-size:var(--fs-sm)}
/* Manage-roles checklist (modal) — role colour swatch is SQUARE (round = avatars/dots only) */
.rolelist{display:flex;flex-direction:column;gap:2px}
.rolerow{display:flex;align-items:center;gap:10px;padding:8px;border-radius:var(--r);cursor:pointer;font-size:var(--fs-sm)}
.rolerow:hover{background:var(--surface)}
.rolerow .rsw{width:10px;height:10px;flex:none;border-radius:var(--r)}
/* Roles editor (§C.16): two-column modal — roles list + the selected role's editor.
   Widen the modal only when it holds the editor (the .modal.wide default is 440px). */
.modal:has(.roleseditor){width:min(700px,95vw)}
.roleseditor{display:flex;gap:var(--s4);min-height:360px;max-height:min(66vh,540px)}
.rolescol{flex:none;width:186px;display:flex;flex-direction:column;gap:8px;min-height:0}
.rolescolhd{display:flex;align-items:center;gap:8px}
.rolescolhd b{flex:1;font-size:var(--fs-sm);font-weight:600}
.rolescol .rolelist{overflow-y:auto;min-height:0}
.rolerow .rnm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rolerow .rdef{font-size:var(--fs-xs);color:var(--muted);flex:none}
.rolerow.on{background:var(--plate);color:var(--ink);font-weight:600}
.roleedit{flex:1;min-width:0;overflow-y:auto;padding-left:var(--s4);box-shadow:inset 1px 0 0 var(--line)}
.swatches{display:grid;grid-template-columns:repeat(10,1fr);gap:5px;margin-top:4px}
.swatch{width:100%;aspect-ratio:1;border-radius:var(--r);cursor:pointer;box-shadow:inset 0 0 0 1px rgba(0,0,0,.10)}
.swatch.on{box-shadow:0 0 0 2px var(--paper),0 0 0 4px var(--ink)}
.pgh{font-size:var(--fs-xs);color:var(--muted);font-weight:600;margin:14px 0 4px;text-transform:uppercase;letter-spacing:.03em}
.permrow{display:flex;align-items:center;gap:10px;padding:6px 2px;cursor:pointer;font-size:var(--fs-sm);color:var(--soft)}
.permrow .pl{flex:1}
.permrow .rsw{width:10px;height:10px;flex:none;border-radius:var(--r)}
.permrow:hover{color:var(--ink)}
.permlist{display:flex;flex-direction:column;gap:1px;max-height:300px;overflow-y:auto}
.rhint{font-size:var(--fs-xs);color:var(--muted);margin-bottom:4px}
/* New-message friend picker (modal) */
.nmlist{display:flex;flex-direction:column;gap:2px;max-height:320px;overflow-y:auto}
.nmrow{display:flex;align-items:center;gap:10px;padding:7px 8px;border-radius:var(--r);cursor:pointer}
.nmrow:hover{background:var(--surface)}
.nmrow .nmname{font-size:var(--fs-sm);font-weight:600}

/* ── Profile (P5.10, CANON §C.10) — hero + shelf tabs + card grid ──────────────
   Ported from the gallery. The avatar is round (people are round); shelf tabs use
   the 2px ink underline like every tab strip; NO member hue anywhere (public). */
.prof{flex:1;min-width:0;overflow-y:auto;background:var(--paper)}
.phero{padding:var(--s5) var(--s5) var(--s4)}
/* K2: uploaded profile banner — a cover band above the identity row (chrome radius, media-fit).
   Only present when the profile has a banner_key (.hasbanner), so a bannerless hero is unchanged. */
.phero .pbanner{height:150px;margin-bottom:var(--s4);border-radius:var(--r);background:var(--paper1) center/cover no-repeat}
.phero .top{display:flex;gap:var(--s5);align-items:flex-start}
.phero .who h1{font-size:var(--fs-xl);font-weight:600}
.phero .who .handle{color:var(--muted);font-size:var(--fs-sm)}
.phero .who .bio{margin-top:var(--s2);max-width:520px;color:var(--soft);font-size:var(--fs-sm)}
.phero .actions{margin-left:auto;display:flex;gap:var(--s2)}
/* P15: viewer status line (presence dot + text) + the owner's inline status editor */
.phero .who .pstat{display:flex;align-items:center;gap:6px;margin-top:var(--s2);color:var(--soft);font-size:var(--fs-sm)}
.pstatusedit{display:flex;align-items:center;gap:var(--s2);margin-top:var(--s3);max-width:520px}
.pstatusedit .field{flex:1;min-width:0}
.ptabs2{display:flex;gap:var(--s5);padding:0 var(--s5);background:var(--surface)}
.ptab2{display:flex;align-items:center;gap:7px;padding:13px 0;color:var(--soft);position:relative;cursor:pointer}
.ptab2:hover{color:var(--ink)}
.ptab2 .ic{width:15px;height:15px;color:var(--muted)}
.ptab2 .ct{color:var(--muted);font-size:var(--fs-xs)}
.ptab2.on{color:var(--ink);font-weight:600}
.ptab2.on .ic{color:var(--ink)}
.ptab2.on::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--ink)}
.ptab2:focus-visible{outline:none;box-shadow:inset 0 -2px 0 var(--ink)}
.pbody{padding:var(--s5)}

/* ── Explorer Feed view (P5.8) — flattened previewable subtree, Instagram-style server
   media preview wall (CANON §C.6). The inline comment thread was cut with post-commenting
   (P4, 2026-08-30); the media + meta stay. */
/* (P14: the old Feed/media-wall view mode was removed — its .filefeed/.ff* styles with it —
   in favour of the three densities (list/small/large). The media-preview wall may return as a
   separate surface post-beta.) */

/* ── User settings (§C.10, screens/usersettings.js) — a left setnav + a panel. Distinct from
   server settings. Panes separate by background step; the active nav row is plate+ink+600
   (the selected-nav convention), never a pill. ────────────────────────────────────────── */
/* Fills the stage like the explorer: a nav column anchored to the left on a background
   step (--surface, so it separates from the panel with no border), the panel on --paper
   taking the rest. Panel CONTENT is capped for readability + left-aligned — never centred
   in a void. All spacing from --s tokens. */
:is(.usersettings,.serversettings){height:100%;display:flex;overflow:hidden}
:is(.usersettings,.serversettings) .setwrap{display:flex;flex:1;min-width:0}
:is(.usersettings,.serversettings) .setnav{flex:none;width:var(--chan);background:var(--surface);overflow-y:auto;padding:var(--s4) var(--s2);display:flex;flex-direction:column;gap:2px}
:is(.usersettings,.serversettings) .setback{display:flex;align-items:center;gap:7px;color:var(--muted);font-size:var(--fs-xs);font-weight:600;padding:6px var(--s2);border-radius:var(--r);margin-bottom:var(--s2);transition:color var(--t),background var(--t)}
:is(.usersettings,.serversettings) .setback:hover{color:var(--ink);background:var(--plate)}
:is(.usersettings,.serversettings) .setback .ic{transform:rotate(180deg)}   /* arrow points back/left */
:is(.usersettings,.serversettings) .setrow{display:flex;align-items:center;gap:9px;text-align:left;padding:6px var(--s2);border-radius:var(--r);color:var(--soft);font-size:var(--fs-sm);transition:background var(--t),color var(--t)}
:is(.usersettings,.serversettings) .setrow .ic{color:var(--muted)}
:is(.usersettings,.serversettings) .setrow:hover{background:var(--plate);color:var(--ink)}
:is(.usersettings,.serversettings) .setrow.on{background:var(--plate);color:var(--ink);font-weight:600}
:is(.usersettings,.serversettings) .setrow.on .ic{color:var(--ink)}
:is(.usersettings,.serversettings) .setpanel{flex:1;min-width:0;overflow-y:auto;padding:var(--s5)}
:is(.usersettings,.serversettings) .setpanel>div{max-width:560px}
:is(.usersettings,.serversettings) .sethead{margin-bottom:var(--s4)}
:is(.usersettings,.serversettings) .sethead h1{margin:0;font-size:var(--fs-xl);font-weight:600}
:is(.usersettings,.serversettings) .sethead p{margin:var(--s1) 0 0;color:var(--muted);font-size:var(--fs-sm)}
:is(.usersettings,.serversettings) .setcard{background:var(--surface);border-radius:var(--r);padding:var(--s4)}
:is(.usersettings,.serversettings) .setcard+.setcard,.usersettings .setactions{margin-top:var(--s3)}
:is(.usersettings,.serversettings) .setcard .ulab{display:block;margin-bottom:var(--s2)}
:is(.usersettings,.serversettings) .setrow2:last-child{border-bottom:0 !important}

/* ── Global search screen (/search, screens/search.js) — jump across servers, channels,
   people. Rows on background steps, active row inverts like the quick-switcher. ────────── */
.search .searchbig{flex:1;max-width:520px}
/* was --fs-lg; owner call 2026-08-30 — every search bar shares the one dense height */
.search .searchbig input{font-size:var(--fs-sm)}
.search .srchgrp{margin-bottom:var(--s4)}
.search .srchrow{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:8px 10px;border-radius:var(--r);color:var(--soft);transition:background var(--t),color var(--t)}
.search .srchrow:hover{background:var(--surface);color:var(--ink)}
.search .srchrow.on{background:var(--plate);color:var(--ink)}
.search .srchrow .info{min-width:0;display:flex;flex-direction:column;line-height:1.25}
.search .srchrow .info b{font-size:var(--fs-sm);font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.search .srchrow .info .sub{font-size:var(--fs-xs);color:var(--muted)}
.search .qsav.sq{flex:none;width:28px;height:28px;border-radius:var(--r);background:var(--surface);color:var(--soft);display:grid;place-items:center;font-size:var(--fs-xs);font-weight:700}
.search .qsav.sq .ic{color:var(--muted)}
