/* Contract: contracts/web/rules.md
 * the request workspace — asking for what is not in the archive yet
 *
 * 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.
 */

/* THIS WAS 09-japanese.css, and for 220 of its 252 lines it was not about
   Japanese at all.
 *
 * One file, one subject, is the rule everywhere else here — four basenames are
 * deliberately shared between src/ and web/ precisely so a name tells you what
 * a thing is. This one said "Japanese" and held the entire request workspace,
 * so the day somebody goes looking for why a thread renders the way it does,
 * the file they need is the one file they have no reason to open.
 *
 * The split is exactly that and nothing else. Source order is unchanged — the
 * Japanese rule still loads immediately before these, in the same slot, so the
 * cascade this whole set of files is careful about is untouched.
 *
 * It also stopped two pages carrying it for nothing: login.html and share.html
 * load the Japanese sheet for its one :lang(ja) font stack and have no request
 * workspace on them at all. Every selector below is .req*, #req* or
 * body.in-requests — none of it could ever have matched there.
 */

/* --- requests -----------------------------------------------------------
   Asking the archive for something that does not exist yet.

   There was a band of cards above the grid here — forty lines of it — and it is
   gone with web/request-band.js. Everything a request does is drawn once now, in
   the workspace further down this file. */

/* Pictures a request is drawn from. Thumbnails and not filenames, because the
   question somebody is answering when they glance at this — "is that the right
   Saggo?" — is one only the picture can answer.

   There was a dialog above this and it is gone with web/requests.js: the
   question it asked, the exchange it drew, and its own copy of this strip. The
   way in is now the line at the foot of the screen (web/css/11-assistant.css) and
   the exchange is the workspace further down this file. What is left here is
   what BOTH of those still use. */
.reqrefs-strip {
  display: flex; gap: 8px; flex-wrap: wrap;
}
.reqrefs-strip:empty { display: none; }

.reqref {
  position: relative; width: 72px;
  display: flex; flex-direction: column; gap: 3px;
}
.reqref img {
  width: 72px; height: 72px; object-fit: contain;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px;
}
.reqref-name {
  font-size: 10px; color: var(--ink-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Always visible rather than revealed on hover: this is used on an iPad, where
   there is no hover and a control that needs one is a control that does not
   exist. */
.reqref-x {
  position: absolute; top: -6px; right: -6px;
  width: 20px; height: 20px; padding: 0; line-height: 1;
  border-radius: 50%; border: 1px solid var(--line);
  background: var(--panel); color: var(--ink); font-size: 11px;
  cursor: pointer;
}
.reqref-x:hover { background: var(--accent); color: #fff; border-color: var(--accent); }

/* ---------- the request workspace ----------
   Requests stopped being a dialog and became a place. The argument is in
   web/requests-view.js; the layout consequence is that the grid column is
   given over to a two-pane surface — threads down the left, one thread open on
   the right — and the inspector goes away, because nothing here is an asset. */
body.in-requests .workspace { grid-template-columns: var(--sidebar-w) minmax(0, 1fr); }
body.in-requests .inspector { display: none; }
/* The filter row, for the reason spelled out at length beside the matching rule
 * in 12-work-board.css. There used to be a second one here — the selection bar
 * — and it went with the bar. */
body.in-requests #filters { display: none; }

/* While the workspace is up, the folder you were in stops LOOKING like the thing
   on screen — because it is not. Two lit rows in one sidebar is a sidebar that
   cannot say where you are, and "All files" wearing the accent over a screen
   with no files on it is the version somebody reports as a bug.
   The folder itself is not deselected, only unlit: leaving the workspace has to
   put you back where you were, not at the top of the archive. */
body.in-requests #folderlist .frow.on {
  background: transparent; border-color: transparent;
  color: var(--ink-dim); font-weight: inherit;
}
body.in-requests #folderlist .frow.on .fico { opacity: .75; }
body.in-requests #folderlist .frow.on .fn { background: var(--panel-2); color: var(--ink-dim); }
body.in-requests #folderlist .frow.on:hover { background: var(--panel-2); color: var(--ink); }

.requestview {
  /* Column 2 to the end, explicitly. The grid still counts three columns and a
     hidden .results does not give its track back, so without this the whole
     workspace lands in the inspector's 340px. */
  grid-column: 2 / -1;
  display: grid; grid-template-columns: 280px minmax(0, 1fr);
  min-width: 0; min-height: 0;
}
.requestview[hidden] { display: none; }

.reqside {
  display: flex; flex-direction: column; gap: 8px;
  padding: 16px 12px; overflow-y: auto; min-height: 0;
  background: var(--panel); border-right: 1px solid var(--line);
}
.reqnew { width: 100%; }
.reqthreads { display: flex; flex-direction: column; gap: 4px; }

/* The shelf, at the foot of the list and only when there is something on it.
   Quiet on purpose: it is a place things are kept, not a place to be drawn to. */
.reqshelf {
  margin-top: 4px; padding: 8px 10px; width: 100%;
  border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--ink-dim);
  font: inherit; font-size: 12px; text-align: left; cursor: pointer;
}
.reqshelf:hover { background: var(--panel-2); color: var(--ink); }
.reqshelf.on { color: var(--ink); }
.reqshelf[hidden] { display: none; }

/* One thread in the list. Two lines: what was asked, and what it is waiting on.
   The second is what makes the list scannable — a column of requests all
   reading "a video of Saggo" is a column you have to open one by one. */
.reqthread {
  display: flex; flex-direction: column; gap: 3px; width: 100%;
  padding: 9px 10px; border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--ink-dim);
  font: inherit; text-align: left; cursor: pointer;
}
.reqthread:hover { background: var(--panel-2); color: var(--ink); }
.reqthread.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.reqthread-asked {
  font-size: 13px; color: var(--ink); line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.reqthread.on .reqthread-asked { color: #fff; }
.reqthread-state { font-size: 11px; opacity: .8; }
/* The one state that wants somebody. Everything else is reported, not asked. */
.reqthread.escalated:not(.held) .reqthread-state { color: var(--warn); }
.reqthread.on .reqthread-state { color: rgba(255,255,255,.85); }
/* Selected AND asking. Written out rather than left to the two rules above,
   which tie on specificity — :not(.held) counts, so the warn colour was landing
   on the accent fill and the one row somebody had opened was the one row whose
   state could not be read. */
.reqthread.escalated.on:not(.held) .reqthread-state { color: rgba(255,255,255,.9); }
/* On the shelf. Dimmed rather than struck through or greyed out: nothing has
   happened to it, and it goes back to full weight the moment anybody speaks. */
.reqthread.archived { opacity: .55; }
.reqthread.archived.on { opacity: 1; }

.reqwork { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.reqempty {
  margin: auto; max-width: 380px; padding: 32px;
  color: var(--ink-dim); font-size: 13px; line-height: 1.6; text-align: center;
}
.reqpane { display: flex; flex-direction: column; min-height: 0; flex: 1; }

.reqhead {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 14px 20px; border-bottom: 1px solid var(--line);
}
.reqhead strong { display: block; font-size: 14px; line-height: 1.35; }
.reqhead-actions { display: flex; gap: 8px; flex: none; }
.reqhead-actions .ghost { height: 30px; padding: 0 12px; font-size: 12px; }

/* The log itself, drawn as a chat. Scrolls; the compose box below it does not.
   The gap is the line spacing between messages, so it is tighter than the
   panel's usual rhythm — a conversation reads as one thing, and 14px of air
   between two sentences somebody typed a second apart reads as two. */
.reqlog {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 18px 20px; display: flex; flex-direction: column; gap: 10px;
}
.reqlog-entry { max-width: min(68%, 560px); }
.reqlog-text { margin: 0; font-size: 13.5px; line-height: 1.5; }
.reqlog-label { margin: 0 0 6px; font-size: 11px; color: var(--ink-dim); }
/* When, under the bubble it belongs to. Small enough to be skipped and there
   when a thread turns out to span months, which is what picking one back up
   means. */
.reqlog-when {
  display: block; margin-top: 4px; font-size: 10.5px; color: var(--ink-dim);
}

/* Who said it, as a side and a colour rather than as a name on screen — one
   studio, and a label beside an answer turns a working note into a record of
   who got it wrong. Yours on the right, the archive's on the left, which is the
   arrangement every chat has taught everybody to read without being told. */
.reqlog-entry.said { margin-left: auto; text-align: right; }
.reqlog-entry.said .reqlog-text {
  display: inline-block; text-align: left;
  padding: 9px 12px; border-radius: 14px 14px 3px 14px;
  background: var(--accent); color: #fff;
}
.reqlog-entry.said .reqlog-pics { justify-content: flex-end; }
.reqlog-entry.ask .reqlog-text {
  display: inline-block;
  padding: 9px 12px; border-radius: 14px 14px 14px 3px;
  background: var(--panel-2); border: 1px solid var(--warn);
}
/* Not a message from anybody: the archive saying what happened. Down the middle
   and full width, so it reads as a line in the transcript rather than as a
   third party with opinions. */
.reqlog-entry.note {
  max-width: none; align-self: center; text-align: center;
  color: var(--ink-dim);
}
.reqlog-entry.note .reqlog-text { color: var(--ink-dim); font-size: 12px; }
.reqlog-entry.bad .reqlog-text { color: var(--accent); }
/* The archive's own doubt about a picture it just made, where that picture's
   label would otherwise be. The accent rather than a red of its own: this is
   not an error — the file exists and is in the archive — it is the one line in
   the thread that wants reading before the picture under it. */
.reqlog-entry.made.bad .reqlog-label { color: var(--accent); font-size: 12px; font-weight: 560; }

.reqlog-pics { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.reqlog-pics .reqref { width: 74px; }

/* What the archive found when somebody asked what it holds, and the size is the
   whole difference between an answer and a list of hashes. A reference strip is
   74px because those are pictures the thread is already about — you know what
   they are, they are there to say the thread has them. These are pictures
   somebody is being asked to CHOOSE between, sight unseen, and at 74px the
   choice is between four green rectangles and the names are elided to
   "saggo-sup…", which is the interface asking a question it has made
   unanswerable.

   Full width for the same reason. Twelve of these wrapping inside 68% of the
   pane is a column; across the pane it is a strip you read in one pass. */
.reqlog-entry.found { max-width: none; }
.reqlog-found { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.reqlog-found .reqref { width: 132px; }
/* Restated, for the reason the result width is: `.reqref img` is a fixed 72px
   square and wins the cascade over the container above it. */
.reqlog-found .reqref img { width: 132px; height: 132px; }
.reqlog-found .reqref-name { font-size: 11px; }
/* A candidate you can take. It has to LOOK answerable, or the strip reads as
   six things the archive is showing off rather than six things it is asking
   about — and somebody who does not know a picture is tappable answers in words
   and goes to fetch one, which is the walk this was built to remove. The accent
   on hover and focus rather than a caption under each one: twelve captions
   saying "choose this" is not an interface, it is a form. */
.reqref.choosable { cursor: pointer; }
.reqref.choosable img { transition: border-color .12s, transform .12s; }
.reqref.choosable:hover img,
.reqref.choosable:focus-visible img { border-color: var(--accent); transform: translateY(-2px); }
.reqref.choosable:hover .reqref-name { color: var(--ink); }
/* How to answer with one of them. Under the strip rather than over it: the
   pictures are the answer and this is the footnote, and a line of instructions
   above six thumbnails reads as the interface explaining itself before it has
   shown you anything. */
.reqlog-hint { margin: 8px 0 0; font-size: 11.5px; color: var(--ink-dim); }
/* What the thread asked for, not an input to it, so it is drawn at a size you
   can actually judge. A thread may hold several of these now — each one sits
   where it happened, with whatever was said next below it. */
.reqlog-entry.made { max-width: none; }
.reqlog-result { margin-top: 4px; }
.reqlog-result .reqref { width: 260px; }
/* The width has to be restated here. `.reqref img` is a fixed 72px square —
   right for a strip of references, and it quietly won the cascade over the
   260px container above, so what the thread called its result was drawn at
   thumbnail size for as long as the rule existed. */
.reqlog-result img { width: 100%; height: auto; max-height: 320px; border-radius: 10px; }

.reqcompose {
  flex: none; padding: 12px 20px 16px; border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 8px;
}
.reqcompose[hidden] { display: none; }
#reqsay { width: 100%; resize: vertical; font: inherit; }
/* The one state that cannot take words: a worker has it, and anything said now
   would be overwritten by whatever the generation does. Dimmed rather than
   removed — a box that disappears is a box somebody goes looking for. */
#reqsay:disabled { opacity: .6; cursor: not-allowed; }
.reqcompose-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
/* Pushed to the far end, away from Send. It is the button you press when the
   conversation is not working, and having it next to the one you press when it
   is makes a slip expensive. */
.reqcompose-actions #reqhandover { margin-left: auto; }

/* Narrow: the thread list becomes a strip above the thread rather than a
   column beside it. Two 280px columns do not fit on a phone and the thread is
   the part somebody came to read. */
@media (max-width: 760px) {
  .requestview { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
  .reqside { border-right: 0; border-bottom: 1px solid var(--line); max-height: 34vh; }
}
