/* Contract: contracts/web/rules.md
 * account, multi-select, drag and drop, dialogs, uploads, sign-in
 *
 * 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.
 */
/* ---------- account + invites ---------- */
.ghost.tiny { padding: 2px 8px; font-size: 11.5px; }

.dlg {
  border: 1px solid var(--line); border-radius: 12px; padding: 22px;
  background: var(--panel); color: var(--ink); width: min(440px, 92vw);
}
.dlg::backdrop { background: rgba(0,0,0,.55); }
.dlg h3 { margin: 0 0 14px; font-size: 15px; }
.dlg h4 { margin: 18px 0 8px; font-size: 12px; color: var(--ink-dim); font-weight: 600; }
.dlg label { display: block; font-size: 12px; color: var(--ink-dim); margin-bottom: 12px; }
.dlg input, .dlg select, .dlg textarea {
  width: 100%; margin-top: 4px; padding: 8px 10px;
  background-color: var(--panel-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 8px; font: inherit; font-size: 13px;
}
.dlg select { height: 36px; padding: 0 32px 0 10px; }
/* Resizable upward only. An idea is one line most of the time and five when it
   is a good one, and a box that cannot grow is a box people stop putting the
   fifth line in. Horizontal resize is off because it would drag out past the
   dialog it is sitting in. */
.dlg textarea { resize: vertical; min-height: 68px; line-height: 1.45; }
/* A row in Preferences: the words on the left, the control on the right.
   Written as `.dlg .prefrow` rather than `.prefrow` on purpose — `.dlg label`
   above is a class plus an element and outranks a bare class, so the flat
   selector would lose the display and the label would keep stacking. */
.dlg .prefrow {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  font-size: 13px; color: var(--ink); margin-bottom: 14px;
}
/* Undoes the full-width rule above, which is right for a dialog whose fields
   are stacked and wrong for one whose fields sit beside their labels. */
.dlg .prefrow select { width: auto; min-width: 170px; margin-top: 0; flex: none; }
.dlg .prefrow input[type="checkbox"] {
  width: 18px; height: 18px; margin-top: 0; padding: 0; flex: none; accent-color: var(--accent);
}
/* The sentence under a setting belongs to the setting, not to the next one. */
.dlg .prefrow + .note { margin: -8px 0 18px; }

#invlink { font: 12px ui-monospace, SFMono-Regular, Menlo, monospace; margin-bottom: 8px; }
.dlgactions { display: flex; gap: 8px; }
.inviterow {
  display: flex; align-items: center; gap: 10px; justify-content: space-between;
  padding: 6px 0; border-top: 1px solid var(--line); font-size: 12.5px;
}
/* ---------- multi-select ----------
   No checkbox: the card is the target and a click on it is the gesture, the way
   the Finder has it. See selection.js.

   Selected looks like an orange wash and a ring in the same colour. The wash is
   what actually reads across a page of sixty thumbnails — a ring alone is four
   hairlines you have to go looking for — and the ring is what says where the
   card ends, since a photograph covers most of the tint it is sitting on. */
.card { position: relative; }
.card.picked {
  background: color-mix(in srgb, var(--accent) 15%, var(--panel));
  border-color: var(--accent);
  outline: 2px solid var(--accent); outline-offset: -2px;
}
/* The letterbox around a picture that does not fill its square, which on a tall
   or wide asset is most of the card.

   Not the cutouts, though. Their square is the transparency checkerboard, and
   what that is for is showing the exact colour behind the artwork — tinting it
   orange would answer the one question it exists to answer with a lie. Those
   cards say "selected" with the ring and the wash under the caption instead.
   background-color rather than the shorthand for the same reason: the shorthand
   clears background-image, and the checkerboard is one. */
.card.picked .shot:not(.alpha-bg) {
  background-color: color-mix(in srgb, var(--accent) 15%, var(--panel-2));
}

/* Where the keyboard is standing.
 *
 * Deliberately NOT the same mark as `picked` above, and deliberately outside
 * the card rather than inside it. Arrowing moves the selection with the focus,
 * so most of the time these two are the same card and one ring would be enough
 * — but not all of the time: a placeholder for work in flight can be arrived at
 * and cannot be selected, and cmd-clicking elsewhere leaves the caret behind.
 * An outer ring in the ink colour reads as "you are here" beside an inner
 * accent ring that reads as "this is chosen", and a card wearing both says both.
 *
 * Written after .card.picked because the two selectors tie on specificity and
 * this one has to win the outline. */
.card:focus-visible,
.pendcard:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* The bar along the bottom of the window was here: `position: fixed`, centred,
   floating over the last rows of the grid, with a measured height published as
   `--selfloor` so the grid could reserve room for what it covered. It is gone.
   What acts on a selection is the panel on the right and the right-click menu.

   ---------- the verbs at the top of the bulk panel ----------
   A wrapping row rather than a column: these are six short words and a column
   of them would push the form that is the panel's actual subject off the
   screen. Ghost buttons, because none of them is the thing you came here to
   do — the form below is. */
.bulkverbs {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 12px 0 4px; padding-bottom: 14px; border-bottom: 1px solid var(--line);
}
.bulkverbs .ghost { padding: 6px 11px; font-size: 12.5px; }

.tagcommon { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.tagchip {
  padding: 3px 9px; font: inherit; font-size: 11.5px; cursor: pointer;
  background: var(--panel-2); color: var(--ink-dim);
  border: 1px solid var(--line); border-radius: 999px;
}
.tagchip:hover { color: var(--ink); border-color: var(--accent); }

/* ---------- drag and drop ---------- */
.dropveil {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  background: light-dark(rgba(246,245,242,.86), rgba(20,20,26,.86));
  backdrop-filter: blur(2px);
  /* The veil must never eat the drop event it exists to advertise. */
  pointer-events: none;
}
/* A class setting `display` outranks the UA rule for [hidden], so without this
   the veil stays up forever after the first drag — a curtain over the whole
   app that no amount of setting .hidden will lift. */
.dropveil[hidden], .uploads[hidden] { display: none; }
.dropveil-inner {
  display: grid; gap: 6px; justify-items: center; text-align: center;
  padding: 32px 44px; border-radius: 16px;
  border: 2px dashed var(--accent); background: var(--panel);
}
.dropveil-inner strong { font-size: 17px; }
.dropveil-inner span { font-size: 13px; color: var(--ink-dim); }

.uploads {
  position: fixed; right: 18px; bottom: calc(18px + var(--floor, 0px)); z-index: 55;
  width: min(380px, calc(100vw - 36px));
  max-height: min(52vh, 520px); overflow: auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0,0,0,.28); padding: 14px 16px;
}
.uploads-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 10px;
}
.uploads-head strong { font-size: 13.5px; }
.uprow {
  display: grid; grid-template-columns: 1fr auto; gap: 3px 10px;
  padding: 7px 0; border-top: 1px solid var(--line); font-size: 12.5px;
}
.upname { overflow-wrap: anywhere; }
.upsize { color: var(--ink-dim); white-space: nowrap; font-variant-numeric: tabular-nums; }
.upbar {
  grid-column: 1 / -1; height: 3px; border-radius: 2px;
  background: var(--panel-2); overflow: hidden;
}
.upbar i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .18s; }
.uprow.ok .upbar i  { background: var(--ok); }
.uprow.ok .upsize   { color: var(--ok); }
.uprow.bad .upbar i { background: var(--accent); width: 100% !important; }
.uprow.bad .upsize  { color: var(--accent); }

/* ---------- MCP access dialog ---------- */
.nomargin { margin-top: 0; }
/* Amber, not red: this is a "you only get one look" caution, not a failure. */
.warn-note {
  margin: 0 0 14px; padding: 10px 12px; font-size: 12.5px; line-height: 1.5;
  color: var(--ink); background: light-dark(#fdf3dc, #33290f);
  border: 1px solid var(--warn); border-radius: 8px;
}
.advanced { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }
.advanced summary {
  font-size: 12.5px; color: var(--ink-dim); cursor: pointer; margin-bottom: 8px;
}
.advanced summary:hover { color: var(--ink); }
#mcpurl, #mcpurl2, #mcpauth {
  font: 12px ui-monospace, SFMono-Regular, Menlo, monospace;
  overflow-wrap: anywhere;
}

/* ---------- upload status ---------- */
.chip {
  padding: 5px 10px; border-radius: 999px; font: inherit; font-size: 12px;
  background: var(--panel-2); color: var(--ink-dim);
  border: 1px solid var(--line); cursor: pointer; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.chip:hover { color: var(--ink); }
/* Amber, not red: a queue nobody is draining needs attention, not alarm. */
.chip.warn { color: var(--warn); border-color: var(--warn); }
.inforow {
  display: flex; align-items: baseline; gap: 12px; justify-content: space-between;
  padding: 7px 0; border-top: 1px solid var(--line); font-size: 12.5px;
}
.inforow span:first-child { color: var(--ink-dim); }
.inforow span:last-child { font-variant-numeric: tabular-nums; text-align: right; }
.failrow {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 10px;
  padding: 8px 0; border-top: 1px solid var(--line); font-size: 12px;
}
.failkey { font-weight: 560; overflow-wrap: anywhere; }
.failwhen { color: var(--ink-dim); white-space: nowrap; }
.failerr {
  grid-column: 1 / -1; color: var(--accent);
  font: 11.5px ui-monospace, SFMono-Regular, Menlo, monospace; overflow-wrap: anywhere;
}

.state { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; font-weight: 700; }
.state.waiting { color: var(--warn); }
.state.used    { color: var(--ok); }
.state.expired { color: var(--ink-dim); }

/* ---------- sign-in page ---------- */
body.centred { display: grid; place-items: center; min-height: 100vh; }
.auth { width: min(430px, 90vw); text-align: center; padding: 30px; }
.brand.big { justify-content: center; margin-bottom: 22px; }
.brand.big .mark { width: 26px; height: 26px; }
.brand.big h1 { font-size: 19px; }
.lede { color: var(--ink-dim); font-size: 14.5px; line-height: 1.6; margin: 0 0 20px; }
.btn.wide { width: 100%; padding: 12px; font-size: 14px; }
.note { color: var(--ink-dim); font-size: 12.5px; margin: 14px 0 0; }
.err { color: var(--accent); font-size: 13px; margin: 14px 0 0; }

@media (max-width: 720px) {
  .bar { flex-wrap: wrap; height: auto; padding: 10px 14px; gap: 10px; }
  .searchwrap { order: 3; width: 100%; flex-basis: 100%; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); padding: 14px; }
}

/* ============================================================
   Restructured chrome: property tabs, header tools, card chips,
   endless scroll. Everything below replaces the old .modes/.who row.
   ============================================================ */

:root { --inspector-w: 380px; }

