/* Contract: contracts/web/rules.md
 * the folder sidebar and everything a folder does
 *
 * Part of what was style.css — 1700 lines in one file. The parts load in a fixed
 * order and MUST stay in it: the cascade is decided by source order and
 * specificity exactly as it was, because this is a split and not a rewrite.
 *
 * There are deliberately no @layer rules. Layering is the tidier shape and it
 * would have changed behaviour — a later layer beats an earlier one regardless
 * of specificity, and this stylesheet has at least one pair, `body.app > .bar`
 * written above `.bar`, where the MORE specific rule comes first and wins on
 * specificity. Putting those two in different layers silently reverses them.
 * Splitting the file is worth doing on its own; changing the cascade is a
 * separate decision that wants somebody looking at the screen.
 */
/* ---------- folder sidebar ---------- */
.workspace { grid-template-columns: var(--sidebar-w) 1fr var(--inspector-w); }

.sidebar {
  display: flex; flex-direction: column; gap: 8px;
  padding: 16px 12px; overflow-y: auto;
  background: var(--panel); border-right: 1px solid var(--line);
}
.sidebar[hidden] { display: none; }
.folderlist { display: flex; flex-direction: column; gap: 2px; }

.frow {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 9px 10px; border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--ink-dim);
  font: inherit; font-size: 13.5px; text-align: left; cursor: pointer;
}
.frow:hover { background: var(--panel-2); color: var(--ink); }
.frow.on { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 560; }
.frow.all { margin-bottom: 6px; }
.fico { flex: none; width: 18px; height: 18px; opacity: .75; }
.frow.on .fico { opacity: 1; }
.fname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fn {
  flex: none; min-width: 20px; padding: 0 6px; border-radius: 9px;
  background: var(--panel-2); color: var(--ink-dim);
  font-size: 11px; font-variant-numeric: tabular-nums; text-align: center;
}
.frow.on .fn { background: rgba(255,255,255,.26); color: #fff; }
.fempty { margin: 6px 4px 2px; font-size: 12px; line-height: 1.5; color: var(--ink-dim); }

.newfolder {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 10px; border: 1px dashed var(--line); border-radius: 9px;
  background: transparent; color: var(--ink-dim);
  font: inherit; font-size: 13.5px; cursor: pointer;
}
.newfolder:hover { color: var(--accent); border-color: var(--accent); }
.newfolder span { font-size: 16px; line-height: 1; }

.sidenote {
  /* `auto` on the top margin, once, so the note and everything under it — which
     is the Trash — are pushed to the floor of the sidebar together. */
  margin: auto 4px 0; padding-top: 12px; border-top: 1px solid var(--line);
  font-size: 11.5px; line-height: 1.5; color: var(--ink-dim);
}

/* ---------- dragging assets into folders ---------- */
.droptarget {
  background: color-mix(in srgb, var(--accent) 18%, transparent) !important;
  border-color: var(--accent) !important; color: var(--ink) !important;
}
/* While a drag is in flight every target is outlined, so the answer to "can I
   drop this here?" is on screen before the pointer arrives. */
body.dragging-assets .frow:not(.all), body.dragging-assets .newfolder {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}
.dragghost {
  position: fixed; top: -1000px; left: -1000px;
  padding: 7px 12px; border-radius: 8px;
  background: var(--accent); color: #fff; font: 600 12.5px/1 ui-sans-serif, system-ui, sans-serif;
}

/* ---------- the bar shown inside a folder ---------- */
.folderbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 14px 20px; border-bottom: 1px solid var(--line);
  background: var(--panel-2);
}
.folderbar[hidden] { display: none; }
.folderbar-who { display: flex; flex-direction: column; gap: 1px; margin-right: auto; min-width: 0; }
.folderbar-who strong { font-size: 15px; }
.folderbar-who .note { margin: 0; }
.folderbar-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.folderbar .btn, .folderbar .ghost { height: 34px; padding: 0 14px; font-size: 13px; }

/* ---------- folder membership in the inspector ---------- */
.infolders { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 12px; }
.infolders-label { font-size: 12px; color: var(--ink-dim); }
.tag.link { border: 1px solid var(--line); cursor: pointer; font: inherit; font-size: 11.5px; color: var(--ink); }
.tag.link:hover { border-color: var(--accent); color: var(--accent); }
.tag.link:disabled { opacity: .6; cursor: default; border-color: var(--line); color: var(--ink-dim); }

/* One button per character. Wraps rather than scrolls, because a cast shot can
   carry six names and none of them should be the one you cannot see. */
.charhunt { display: flex; flex-wrap: wrap; gap: 5px; }

/* Where a cutout came from, and what has been cut out of this. Same visual
   weight as the folder list above: both answer "what else is this connected
   to", and neither is more important than the picture. */
.lineage { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 12px; }
.lineage-made { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; width: 100%; }
.lineage-label { font-size: 12px; color: var(--ink-dim); }
.lineage-op { font-size: 11.5px; color: var(--ink-dim); }
.lineage-failed { font-size: 11.5px; color: var(--warn); }

/* ---------- the add-files picker ---------- */
/* Scoped to [open] on purpose. A bare `display: flex` here outranks the user
   agent's `dialog:not([open]) { display: none }`, and the picker then sits
   permanently on top of the grid — the same trap the drop veil fell into. */
.dlg.wide { width: min(980px, 94vw); max-height: 88vh; }
.dlg.wide[open] { display: flex; flex-direction: column; gap: 12px; }
.pickfilters { display: flex; gap: 10px; flex-wrap: wrap; }
.pickfilters #pickq {
  flex: 1; min-width: 220px; height: var(--control-h); padding: 0 14px;
  background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 9px; font: inherit; font-size: 14px;
}
.pickfilters #pickq:focus { outline: none; border-color: var(--accent); }
/* Undoes .dlg select's full-width rule — in here it sits beside the search box. */
.pickfilters select { flex: none; width: auto; min-width: 180px; height: var(--control-h); }
.pickgrid {
  flex: 1; min-height: 200px; overflow-y: auto;
  display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
  padding: 4px 2px;
}
.ptile {
  display: flex; flex-direction: column; gap: 5px; padding: 0;
  background: none; border: 0; cursor: pointer; color: var(--ink); font: inherit; text-align: left;
}
.pshot {
  position: relative; aspect-ratio: 1; border-radius: 8px; overflow: hidden;
  background: var(--panel-2); border: 2px solid transparent;
  display: flex; align-items: center; justify-content: center;
}
.pshot img { width: 100%; height: 100%; object-fit: contain; }
.ptile.on .pshot { border-color: var(--accent); }
/* A tick, so "chosen" survives being looked at on a dark thumbnail. */
.ptile.on .pshot::after {
  content: '✓'; position: absolute; top: 5px; left: 5px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--accent); color: #fff;
  font-size: 12px; font-weight: 700; display: grid; place-items: center;
}
.ptype {
  position: absolute; right: 5px; bottom: 5px; padding: 1px 5px; border-radius: 4px;
  font-size: 9.5px; font-weight: 700;
  background: color-mix(in srgb, var(--panel) 84%, transparent);
  color: var(--ink-dim); backdrop-filter: blur(6px);
}
.pname {
  font-size: 11px; line-height: 1.3; color: var(--ink-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pickmore { align-self: center; }
.dlgactions.sticky { border-top: 1px solid var(--line); padding-top: 12px; }

/* ---------- the "nothing was lost" line ---------- */
.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(18px + var(--floor, 0px)); z-index: 70;
  max-width: min(640px, calc(100vw - 36px)); padding: 11px 18px;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--ok); border-radius: 11px;
  box-shadow: 0 10px 30px rgba(0,0,0,.3);
  font-size: 13px; line-height: 1.45; text-align: center;
}
.toast[hidden] { display: none; }
/* A way back, offered on the sentence rather than after it. Inline so the line
   still reads as one thing being said; see note() in web/messages.js for why
   there is never a second box. */
.toastdo {
  margin-left: 12px; padding: 3px 10px;
  background: none; color: var(--accent); border: 1px solid var(--accent);
  border-radius: 8px; font: inherit; font-size: 12.5px; font-weight: 600;
  cursor: pointer; white-space: nowrap;
}
.toastdo:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }

/* The selection bar used to sit here too and the toast stepped over it. The bar
   is gone, so the toast keeps its own gap whatever is selected. */

/* A menu that opens upward, for anything pinned near the bottom of the window. */
.menu.up { top: auto; bottom: calc(100% + 6px); max-height: 320px; overflow-y: auto; }

/* ---------- icon-only type chips ----------
   Five glyphs read faster than five words once learned and cost a fifth of the
   width, which is what let status go back to being a dropdown beside them. The
   label survives as the tooltip and the accessible name — an icon-only control
   that says nothing to a screen reader is a control that does not exist. */
.chip-toggle.iconic {
  width: var(--control-h); padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.chip-toggle.iconic svg { width: 20px; height: 20px; }

/* ---------- starred projects, and the rows that are not folders ---------- */
/* A project row wears the same shape as a folder row because it is the same
   gesture — click to stand in it — and differs only by the pin, which is the
   one thing that says why it has a row at all. */
.frow.project .fico { width: 15px; height: 15px; }

/* The wall, and the bin. Neither is a place you scroll to: the first sits under
   the lists it summarises, the second is nailed to the floor of the sidebar,
   which is the one position that says "bin" without a word. `margin-top: auto`
   on a flex column is what does the nailing — the sidenote above it gives up
   the auto margin it used to hold for exactly this reason. */
.gridentry { color: var(--ink-dim); }
.gridentry .fname { flex: none; }
.trashentry { margin-top: 10px; }
.trashentry .fico { width: 17px; height: 17px; }

/* ---------- the inspector with several things selected ---------- */
.bulkstrip { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.bulkthumb {
  width: 54px; height: 54px; border-radius: 7px; overflow: hidden;
  background: var(--panel-2); display: grid; place-items: center;
}
.bulkthumb img { width: 100%; height: 100%; object-fit: cover; }
.bulkmore {
  width: 54px; height: 54px; border-radius: 7px;
  background: var(--panel-2); color: var(--ink-dim);
  display: grid; place-items: center; font-size: 12.5px; font-weight: 600;
}
.edit.bulk { border-top: 0; padding-top: 0; }
.edit.bulk .note { margin: -4px 0 12px; }
/* The selection bar floats over the bottom of the screen, and the bulk form's
   Apply button is the last thing in a panel that reaches it. Give the panel
   room to scroll past. */
body.selecting .inspector { padding-bottom: 96px; }

/* ---------- "are these the same thing?" ----------
   Sits above the grid rather than in a dialog: it is an offer, not a
   question that has to be answered before anything else can happen. */
.suggestbar {
  margin: 14px 20px 0; padding: 14px 16px;
  background: var(--panel); border: 1px solid var(--ok); border-radius: 12px;
}
.suggest-top {
  display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.suggest-top > div:first-child { flex: 1; min-width: 240px; }
.suggest-top strong { font-size: 14px; }
.suggest-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.suggest-actions .btn, .suggest-actions .ghost { height: 34px; padding: 0 14px; font-size: 13px; }

.suggest-list {
  display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  max-height: 260px; overflow-y: auto;
}
.stile {
  display: flex; flex-direction: column; gap: 3px; padding: 0;
  background: none; border: 0; color: var(--ink); font: inherit;
  text-align: left; cursor: pointer; opacity: .45;
}
.stile.on { opacity: 1; }
.sshot {
  position: relative; aspect-ratio: 1; border-radius: 8px; overflow: hidden;
  background: var(--panel-2); border: 2px solid transparent;
  display: grid; place-items: center;
}
.sshot img { width: 100%; height: 100%; object-fit: contain; }
.stile.on .sshot { border-color: var(--ok); }
.stile.on .sshot::after {
  content: '✓'; position: absolute; top: 4px; left: 4px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--ok); color: #08120c;
  font-size: 11px; font-weight: 700; display: grid; place-items: center;
}
.sname {
  font-size: 10.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The reason it was suggested, on the tile. A suggestion you cannot check is
   just an instruction. */
.swhy { font-size: 9.5px; color: var(--ink-dim); line-height: 1.25; }

/* While checking, the folder sidebar is gone and the grid takes its column. */
body.reviewing .workspace { grid-template-columns: 1fr var(--inspector-w); }

