/* ===========================================================================
   Data Tomo — Proposals
   ===========================================================================

   Loaded after app.css AND after instructions.css, which is deliberate: the
   shared Data Tomo primitives live in the shared section at the top of
   instructions.css and this surface uses them directly, by their `ins-`
   names. Do not restate them here.

   Reuse from instructions.css, do not redefine:
     .ins-card / .ins-card-h / .ins-card-b   the card shell
     .ins-dot[-confirmed|-needs-update]      review-state dots
     .ins-kind[-metric|-dimension|-rule]     kind badges
     .ins-tag                                tag pills
     .ins-pr-note[-stale|-error]             the PR notice, and the 409/502 variants
     .ins-btn[-small|-ghost|-danger]         buttons (a bare Pico button is azure)
     .ins-chip                               aria-pressed toggles
     .ins-empty, .ins-sr, .ins-mono, .ins-stack, .ins-pane
     the --ins-* tokens on :root

   NAMING. Everything defined in THIS file is prefixed `prop-`, with no
   exceptions. app.css is 4,419 lines of unprefixed class names and the
   prototype already hit one collision (a `.tomo` label matching a `.tomo`
   grid rule); assume every short word is taken.

   WRITE SEMANTICS, for whoever builds this surface:
     - Approve MERGES the proposal's pull request. It is the irreversible
       half; word the button and its confirmation accordingly.
     - Approve returns `reconciled` — false means the merge landed but this
       database has not caught up yet. Say that, rather than showing stale
       content as if it were current.
     - Reject CLOSES the pull request.
     - 502 on either means GitHub was unreachable and NOTHING changed.
     - 409 means the proposal was already approved or rejected by someone
       else, or it predates PR-backed proposals and has no PR to act on.

   ---------------------------------------------------------------------------
   This file is intentionally empty below this header. The Proposals surface
   appends its own component styles here: the proposal card, origin badge,
   rationale, the diff, the four view switchers (What changed / Whole
   instruction / Edit / Test with Data Tomo) and the action bar.
   ========================================================================= */


/* ===========================================================================
   Nav badge
   ---------------------------------------------------------------------------
   ABSOLUTELY POSITIONED ON PURPOSE, and this is the only rule in this file
   that reaches outside the page.

   The nav budget has no room for it. Measured in the real app: seven tabs fit
   one row at 1280px with 21px spare, and an in-flow badge costs about that
   much on its own — so a queue with anything in it would push Data Syncs and
   Sync History onto a second row, and the nav would change height whenever
   someone approved the last proposal. Pinned into the link's own right
   padding it costs zero layout width and the row is exactly as wide with a
   badge as without one.

   `position: relative` has to go on the link, which lives in app.css and
   belongs to another agent; scoping it to this one href changes nothing else.
   ========================================================================= */

#main-nav a[href="#/proposals"] { position: relative; }

.prop-nav-count {
  position: absolute;
  top: 2px;
  right: 1px;
  min-width: 15px;
  padding: 0 4px;
  border-radius: 99px;
  background: var(--ins-accent);
  color: #fff;
  font-family: var(--ins-font-mono);
  font-size: 0.55rem;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
  pointer-events: none;
}

/* LTA-134 moved the Proposals link INTO the Review dropdown, where the
   absolute pin above (which exists to cost the nav row zero width) would
   float the badge over the item's own text. Inside a menu there is no width
   budget to protect, so it becomes an ordinary in-flow chip matching
   `.review-item-count` beside it. The rule above is left untouched: the link
   is still styled for the nav row if it is ever moved back. */
#main-nav .review-menu .prop-nav-count {
  position: static;
  margin-left: auto;
  background: #e8f0ec;
  color: #2c5f4a;
  font-size: 0.6rem;
  line-height: 1rem;
  padding: 0 0.45rem;
}


/* ===========================================================================
   The proposal card
   ========================================================================= */

.prop-list { display: flex; flex-direction: column; gap: 20px; }

.prop-card { margin: 0; }

/* --- Header band: who, where from, when ---------------------------------- */

.prop-h {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 15px 20px;
  background: var(--ins-card-head);
  border-bottom: 1px solid var(--ab-border-light);
}

.prop-who {
  font-size: 0.8rem;
  color: var(--ins-text-muted);
}

.prop-who b {
  color: var(--ins-text-body);
  font-weight: 600;
}

.prop-ago {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--ins-text-muted);
  white-space: nowrap;
}

/* Origin badge. A proposal raised inside a conversation and one typed by a
   person are reviewed differently — the first has a question behind it that
   the corpus failed to answer — so the two are told apart at a glance and in
   words, never by colour alone. */

.prop-origin {
  padding: 4px 10px;
  border-radius: 5px;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.prop-origin-bot { background: #fbf0dd; color: #8a6116; }
.prop-origin-human { background: var(--ins-accent-soft); color: var(--ins-accent); }

/* --- Target + rationale --------------------------------------------------- */

.prop-rationale {
  margin: 0;
  padding: 16px 20px;
  border-bottom: 1px solid var(--ab-border-light);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ins-text-body);
}

.prop-target {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}

.prop-target b {
  color: var(--ab-text);
  font-weight: 600;
  word-break: break-word;
}

/* --- The four view switchers ---------------------------------------------
   Buttons are .ins-chip from instructions.css, driven by aria-pressed. Only
   the row around them is defined here. "Test with Data Tomo" renders DISABLED
   rather than hidden: the chat backend does not exist yet (LTA-78), and a
   control that is visibly unavailable with a reason on it keeps the design
   honest where a missing one would quietly lose it. */

.prop-views {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 13px 20px;
  border-bottom: 1px solid var(--ab-border-light);
}

.prop-views .ins-chip[disabled] {
  opacity: .5;
  cursor: not-allowed;
  border-style: dashed;
}

.prop-views .ins-chip[disabled]:hover {
  border-color: var(--ab-border);
  color: var(--ab-text-secondary);
}

/* The wrapper exists so the tooltip survives: a disabled button swallows its
   own mouse events in some browsers and never shows a title. */
.prop-why { display: inline-flex; }

.prop-views-note {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--ins-text-muted);
}

/* --- What changed --------------------------------------------------------- */

.prop-diff {
  font-family: var(--ins-font-mono);
  font-size: 0.72rem;
  line-height: 1.7;
}

.prop-diff > div {
  padding: 2px 20px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Sign prefixes are rendered into the text, so the colours here are a second
   signal rather than the only one. */
.prop-del { background: #fbeaea; color: #8f2020; }
.prop-add { background: #e8f3ec; color: #1e5c3d; }
.prop-ctx { color: var(--ins-text-muted); }

.prop-gap {
  background: var(--ab-bg);
  color: var(--ins-text-muted);
  font-style: italic;
  border-top: 1px solid var(--ab-border-light);
  border-bottom: 1px solid var(--ab-border-light);
}

/* --- Whole instruction ----------------------------------------------------
   The reason this view exists: a diff is not enough to approve on. Somebody
   merging a change to a definition has to be able to read the definition. */

.prop-file {
  margin: 0;
  padding: 18px 20px;
  background: #22333d;
  color: #dbe6ee;
  font-family: var(--ins-font-mono);
  font-size: 0.72rem;
  line-height: 1.65;
  white-space: pre;
  overflow-x: auto;
}

.prop-foot {
  margin: 0;
  padding: 12px 20px;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--ins-text-muted);
  border-top: 1px solid var(--ab-border-light);
}

.prop-body { padding: 16px 20px 0; }

/* --- Edit ----------------------------------------------------------------- */

.prop-textarea {
  display: block;
  width: 100%;
  margin: 0;
  padding: 18px 20px;
  border: 0;
  border-radius: 0;
  background: var(--ab-surface);
  color: var(--ins-text-body);
  font-size: 0.72rem;
  line-height: 1.65;
  resize: vertical;
  overflow-x: auto;
}

.prop-textarea:focus {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--ins-accent);
}

.prop-edit-status { padding: 0 20px; }

.prop-edit-status .ins-pr-note { margin: 0 0 4px; }

.prop-ok {
  display: inline-block;
  padding-bottom: 4px;
  font-size: 0.75rem;
  color: var(--ab-success);
}

.prop-amend {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 14px 20px;
  border-top: 1px solid var(--ab-border-light);
  background: var(--ins-card-head);
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--ins-text-muted);
}

.prop-amend > span { flex: 1; min-width: 220px; }

/* --- Confirm / reject prompts --------------------------------------------
   Approve is the irreversible half — it merges — so it asks once before it
   does. Reject asks for the note that closes the pull request. */

.prop-prompt {
  padding: 16px 20px;
  border-top: 1px solid var(--ab-border-light);
  background: var(--ins-card-head);
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--ins-text-body);
}

.prop-prompt p { margin: 0 0 12px; }

.prop-prompt label {
  display: block;
  margin-bottom: 8px;
  font-size: 0.75rem;
  color: var(--ins-text-muted);
}

.prop-note {
  width: 100%;
  margin-bottom: 12px;
  padding: 10px 12px;
  border: 1px solid var(--ab-border);
  border-radius: 8px;
  background: var(--ab-surface);
  font-family: var(--ab-font-body);
  font-size: 0.8rem;
}

.prop-note:focus {
  outline: none;
  border-color: var(--ins-accent);
  box-shadow: 0 0 0 2px var(--ins-accent-soft);
}

.prop-prompt-acts { display: flex; gap: 10px; flex-wrap: wrap; }

/* --- Action bar ----------------------------------------------------------- */

.prop-acts {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 16px 20px;
  border-top: 1px solid var(--ab-border-light);
}

.prop-acts-note {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--ins-text-muted);
}

/* --- Resolved ------------------------------------------------------------
   A merge that did not reconcile is still a merge. It reads as a completed
   approval with a caveat, never as a failure — the change is live in the repo
   and only this app's cache is behind. */

.prop-resolved {
  display: flex;
  gap: 12px;
  align-items: baseline;
  padding: 18px 20px;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--ab-success);
}

.prop-resolved-caveat { color: #7a5a06; background: #fdf4e3; }

.prop-resolved-mark { font-size: 0.9rem; }

.prop-resolved b { font-weight: 700; }

.prop-resolved-target {
  font-family: var(--ins-font-mono);
  font-size: 0.7rem;
  color: var(--ins-text-muted);
}


/* ===========================================================================
   Narrow screens
   ---------------------------------------------------------------------------
   At 400px the header band, the switchers and the action bar each wrap; the
   two panes that cannot wrap — the rendered file and the editor — scroll
   inside themselves, so the page body never scrolls sideways.
   ========================================================================= */

@media (max-width: 640px) {
  .prop-h,
  .prop-views,
  .prop-acts,
  .prop-amend { padding-left: 15px; padding-right: 15px; }

  .prop-ago,
  .prop-views-note,
  .prop-acts-note { margin-left: 0; }

  .prop-rationale,
  .prop-body,
  .prop-foot,
  .prop-prompt,
  .prop-file,
  .prop-textarea { padding-left: 15px; padding-right: 15px; }

  .prop-diff > div { padding-left: 15px; padding-right: 15px; }
}

/* ── Testing a proposal against Data Tomo (LTA-100) ─────────────────────── */
.prop-test { display: flex; flex-direction: column; gap: 14px;
  padding: 16px 20px; border-top: 1px solid var(--ab-border-light); }
.prop-test-lead { margin: 0; font-size: 0.9rem; color: var(--ab-text-muted); }
.prop-test-busy { margin: 0; font-size: 0.9rem; color: var(--ab-text-muted); }
.t-turn { display: flex; gap: 11px; align-items: flex-start; }
/* Fixed width, so the speaker column is a straight edge down the transcript
   instead of resizing with whatever each turn contains. */
.t-who { flex: 0 0 96px; width: 96px; text-align: center; align-self: flex-start;
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-top: 2px; padding: 3px 0; border-radius: 5px;
  font-size: 12px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.t-who.you { background: #e8edf1; color: #2c3e50; }
.t-who.bot { background: #e7f0ea; color: #2c5f4a; }
.t-body { flex: 1; min-width: 0; }
.t-body p { margin: 0 0 9px; } .t-body p:last-child { margin: 0; }
.suggest { display: flex; flex-direction: column; gap: 10px;
  padding: 13px 16px; border: 1px solid #cfe0d6; background: #f2f8f4; border-radius: 8px; }
.suggest .sh { font-size: 13px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: #2c5f4a; }
.suggest .sd { font-size: 1rem; line-height: 1.5; }
.suggest pre { margin: 0; padding: 12px 14px; border-radius: 7px;
  background: #22333d; color: #dbe6ee; font-size: 14px; line-height: 1.65;
  overflow-x: auto; white-space: pre-wrap; word-break: break-word; }
.suggest pre .add { color: #9ad3a8; display: block; }
.suggest pre .del { color: #e8a0a0; display: block; }
.suggest pre .ctx { color: #8fa4b3; display: block; }
.suggest .sa { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.t-ask { display: flex; gap: 10px; align-items: center;
  padding: 11px 14px; border: 1px solid var(--ab-border); border-radius: 8px;
  background: var(--ab-surface); }
.t-ask input { flex: 1; min-width: 0; border: 0; background: none;
  font-family: inherit; font-size: 1rem; }
.t-ask input:focus { outline: none; }
.t-ask .hint { color: var(--ab-text-muted); font-family: var(--ins-font-mono, monospace); }
.t-sugg { display: flex; gap: 8px; flex-wrap: wrap; }
.t-sugg button { padding: 6px 13px; border: 1px solid var(--ab-border);
  border-radius: 99px; background: var(--ab-surface);
  font-size: 0.9rem; color: var(--ab-text-muted); }
.t-sugg button:hover:not(:disabled) { border-color: #2c5f4a; color: #2c5f4a; }
.applied { display: flex; gap: 9px; align-items: center;
  font-size: 1rem; font-weight: 600; color: #2c5f4a; }
