/* assistant panel
   The assistant's drawer: thread, bubbles, composer.

   Loaded by `stylesheet_link_tag :app`, which includes every .css under
   app/assets sorted by filename — so the NUMBER PREFIX IS THE CASCADE ORDER.
   Renaming a file moves it in the cascade. */

/* ======================================================================
   The assistant panel
   ----------------------------------------------------------------------
   A chat, but an ERP's chat. Bubbles carry the conversation; the LOOKUPS
   are not bubbles — they sit between them as evidence, in the same mono
   this app uses for anything measured. That is the whole idea: everywhere
   else a chat window hides its tool use, and here the point of the thing
   is that you can see what it looked at.

   No new colours. Identity comes from placement and weight: the company's
   amber tints what you said, the assistant answers on paper with a
   hairline, and the mark is the only thing that speaks for the machine.
   ====================================================================== */

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

#assistant_panel { display: flex; flex-direction: column; flex: 1; min-height: 0; }

/* --- the head: what this is, and which conversation --- */
.ap-head {
  display: flex; align-items: center; gap: 10px;
  padding: 0 0 12px;
  border-bottom: 1px solid var(--line);
}
.ap-titles { flex: 1; min-width: 0; display: grid; gap: 1px; }
.ap-subtitle {
  font-size: 12.5px; color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The switcher sits under the title rather than replacing it: which
   conversation you are in is a different question from what this panel is. */
.ap-bar { display: flex; align-items: center; gap: 6px; padding: 10px 0 0; }
.ap-rename-open {
  display: grid; place-items: center; flex: none;
  width: 30px; height: 30px; padding: 0; border-radius: 8px;
  border: 0; background: none; color: var(--ink-3); cursor: pointer;
}
.ap-rename-open:hover { background: var(--paper); color: var(--ink); }
.ap-rename { display: flex; align-items: center; gap: 8px; padding: 10px 0 0; }
.ap-rename input { flex: 1; min-width: 0; }
.ap-mark {
  display: grid; place-items: center;
  width: 26px; height: 26px; flex: none; border-radius: 8px;
  background: var(--signal-bg); color: var(--signal);
  border: 1px solid var(--signal-line);
}
.ap-title { font: 600 14px var(--ui); letter-spacing: -0.01em; }
.ap-sessions { flex: 1; min-width: 0; }
.ap-sessions select {
  width: 100%; max-width: 100%;
  font: 400 12.5px var(--ui); color: var(--ink-2);
}
.ap-new {
  flex: none; font: 500 12.5px var(--ui); color: var(--ink-3);
  text-decoration: none; padding: 5px 9px; border-radius: var(--r);
}
.ap-new:hover { background: var(--paper); color: var(--ink); }

/* --- the thread --- */
.ap-thread {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 16px 2px; display: flex; flex-direction: column; gap: 12px;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) { .ap-thread { scroll-behavior: auto; } }

.ap-turn { display: flex; gap: 8px; align-items: flex-end; max-width: 100%; }
.ap-turn.is-you { justify-content: flex-end; }
.ap-avatar {
  display: grid; place-items: center;
  width: 22px; height: 22px; flex: none; margin-bottom: 2px;
  border-radius: 7px; color: var(--signal);
  background: var(--signal-bg); border: 1px solid var(--signal-line);
}

.ap-bubble {
  max-width: 82%; padding: 10px 13px;
  border-radius: 14px; font-size: 14px; line-height: 1.55;
  overflow-wrap: anywhere;
}
/* One rhythm for everything a model can put in a bubble, and no trailing gap
   under whichever element happens to come last. */
.ap-bubble > * { margin: 0 0 8px; }
.ap-bubble > :last-child { margin-bottom: 0; }

/* A heading inside an answer is a label for the lines under it, not a section
   of a document — so it is weight and colour, not size. */
.ap-h { font-weight: 600; letter-spacing: -0.01em; }
.ap-h + ul, .ap-h + ol, .ap-h + .ap-table { margin-top: -4px; }

/* 20px, not the browser's 40: a bubble is 82% of a 600px panel, and four
   characters of indent is four characters the answer does not get. */
.ap-bubble ul, .ap-bubble ol { margin: 8px 0; padding-left: 20px; }
.ap-bubble li { margin: 2px 0; }
.ap-bubble li:last-child { margin-bottom: 0; }
.ap-bubble li > ul, .ap-bubble li > ol { margin: 3px 0 0; }
.ap-bubble li::marker { color: var(--ink-3); }

.ap-bubble code {
  font: 400 12.5px var(--mono); background: var(--paper);
  border: 1px solid var(--line); border-radius: 4px; padding: 1px 5px;
}
.ap-bubble hr { border: 0; border-top: 1px solid var(--line); }

/* Answers about a business come out as tables often enough to be worth
   rendering properly. It scrolls sideways rather than squeezing: five columns
   crushed into a drawer is worse than five columns you can push. */
.ap-table { overflow-x: auto; }
.ap-table table { border-collapse: collapse; font-size: 13px; min-width: 100%; }
.ap-table th, .ap-table td {
  padding: 5px 10px 5px 0; text-align: left; white-space: nowrap;
  border-bottom: 1px solid var(--line);
}
.ap-table th {
  font: 500 11px var(--ui); text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-3); border-bottom-color: var(--line-2);
}
.ap-table tr:last-child td { border-bottom: 0; }

/* What you said: the company's own colour, and the corner that points back
   at you. */
.is-you .ap-bubble {
  background: var(--signal-bg);
  border: 1px solid var(--signal-line);
  border-bottom-right-radius: 5px;
  color: var(--ink);
}
/* What it said: paper and a hairline. Quieter than your own words, because
   it is answering rather than asking. */
.is-them .ap-bubble {
  background: var(--surface);
  border: 1px solid var(--line);
  border-bottom-left-radius: 5px;
}

.ap-files { margin: 8px 0 0; padding-left: 16px; font-size: 12.5px; color: var(--ink-2); }

/* --- what it found, as somewhere to go --- */
/* Underlined rather than coloured: an answer can name six records, and six
   coloured words in a paragraph is a ransom note. The line is enough, and it
   thickens under the cursor. */
.ap-link {
  color: inherit; text-decoration: underline;
  text-decoration-color: var(--signal); text-underline-offset: 2px;
  text-decoration-thickness: 1.5px;
}
.ap-link:hover { color: var(--signal); text-decoration-thickness: 2px; }
.ap-link:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; border-radius: 3px; }

/* --- when it needs you to choose --- */
/* Under its question, indented to the same place its words start, so the
   buttons read as part of what it said rather than as a toolbar. */
.ap-choices {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: -4px 0 0 30px;
}
.ap-choice {
  padding: 7px 12px; border-radius: 999px;
  border: 1px solid var(--signal-line); background: var(--surface);
  font: 500 13px var(--ui); color: var(--ink); cursor: pointer;
  text-align: left;
}
.ap-choice:hover { background: var(--signal-bg); border-color: var(--signal); }
.ap-choice:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }

/* --- working --- */
.ap-thinking { display: flex; gap: 5px; align-items: center; padding: 13px; }
.ap-thinking span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--ink-3);
  animation: ap-blink 1.3s ease-in-out infinite;
}
.ap-thinking span:nth-child(2) { animation-delay: .18s; }
.ap-thinking span:nth-child(3) { animation-delay: .36s; }
@keyframes ap-blink {
  0%, 80%, 100% { opacity: .25; transform: translateY(0); }
  40%           { opacity: 1;   transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
  .ap-thinking span { animation: none; opacity: .5; }
}

.ap-stopped {
  margin: 0; padding: 10px 13px; border-radius: var(--r);
  background: var(--danger-bg); color: var(--danger); font-size: 13px;
}

/* --- empty --- */
.ap-empty { margin: auto 0; text-align: center; color: var(--ink-3); padding: 20px 10px; }
.ap-empty-mark {
  display: grid; place-items: center; margin: 0 auto 12px;
  width: 38px; height: 38px; border-radius: 12px;
  background: var(--signal-bg); color: var(--signal); border: 1px solid var(--signal-line);
}
.ap-empty p { margin: 0; font-size: 14px; color: var(--ink-2); }
.ap-empty-note { margin-top: 5px !important; font-size: 12.5px !important; color: var(--ink-3) !important; }

/* --- the composer --- */
.ap-ask { border-top: 1px solid var(--line); padding-top: 12px; }
.ap-files-chosen {
  font: 400 12px var(--mono); color: var(--ink-3);
  padding: 0 4px 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ap-ask-row {
  display: flex; align-items: flex-end; gap: 6px;
  border: 1px solid var(--line-2); border-radius: 12px;
  padding: 6px 6px 6px 8px; background: var(--surface);
}
.ap-ask-row:focus-within { border-color: var(--signal); box-shadow: 0 0 0 3px var(--signal-bg); }
.ap-ask-row textarea {
  flex: 1; border: 0; outline: 0; resize: none; background: none;
  font: 400 14px/1.5 var(--ui); color: var(--ink);
  padding: 7px 2px; max-height: 168px;
}
/* The row is the field. The generic `textarea:focus` ring would draw a second
   one INSIDE it — a box within a box — so it is turned off here: the row's own
   :focus-within border is what says the composer has focus. */
.ap-ask-row textarea:focus { box-shadow: none; border-color: transparent; }
/* padding: 0 is load-bearing. The app's generic `button` rule sets
   `padding: 8px 15px`, and with box-sizing: border-box that leaves a 32px
   button with a TWO pixel content box — so a 16px icon has nowhere to sit and
   comes out looking off-centre no matter how the box is centred. */
.ap-icon-button {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px; padding: 0; border-radius: 9px;
  border: 0; background: none; color: var(--ink-3); cursor: pointer;
}
.ap-icon-button svg, .ap-send svg { display: block; }
.ap-icon-button:hover { background: var(--paper); color: var(--ink); }
.ap-icon-button.is-on { background: var(--danger-bg); color: var(--danger); }
.ap-send {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px; padding: 0; border-radius: 9px;
  border: 0; background: var(--ink); color: #fff; cursor: pointer;
}
.ap-send:hover { background: var(--signal); }
.ap-icon-button:focus-visible, .ap-send:focus-visible {
  outline: 2px solid var(--signal); outline-offset: 2px;
}

/* --- the drawer, holding a conversation --- */
/* Wider while talking, for the same reason it widens while marking up: the
   thread is the artefact, and evidence in a narrow column is unreadable. */
.reporter-panel.is-talking .reporter-sheet { width: min(600px, 100vw); }
.reporter-assistant { display: flex; flex-direction: column; flex: 1; min-height: 0; padding-top: 26px; }
.reporter-assistant turbo-frame { display: flex; flex-direction: column; flex: 1; min-height: 0; }

/* --- the feature request form --- */
.reporter-feature { display: flex; flex-direction: column; gap: 16px; padding-top: 26px; }
.reporter-feature .field { display: block; }
.reporter-feature .field > span {
  display: block; margin-bottom: 6px;
  font: 500 13px var(--ui); color: var(--ink);
}
.reporter-feature textarea { width: 100%; resize: vertical; }
.feature-actions { display: flex; justify-content: flex-end; }

/* Working: the composer says so rather than accepting a question that would
   arrive in the middle of an answer. */
.ap-ask-row textarea:disabled { background: none; color: var(--ink-3); cursor: default; }
.ap-send:disabled { background: var(--line-2); cursor: default; }
.ap-send:disabled:hover { background: var(--line-2); }

/* The panel's contents fill the frame; the frame fills the drawer. */
.ap { display: flex; flex-direction: column; flex: 1; min-height: 0; }

.ap-bubble strong { font-weight: 600; }

/* --- a record the assistant proposed --- */
/* Not a flash. A flash is something that happened; this is something waiting
   on you, and it stays until you deal with it. The company's amber down the
   left edge is the same signal the panel uses, so the two read as one system.
   Deliberately above the page head rather than inside it: what this record IS
   has to be settled before anyone reads its number. */
.proposal {
  display: flex; gap: 14px; align-items: flex-start;
  margin: 0 0 20px; padding: 15px 18px;
  background: var(--signal-bg);
  border: 1px solid var(--signal-line);
  border-left: 3px solid var(--signal);
  border-radius: var(--r);
}
.proposal-mark {
  display: grid; place-items: center; flex: none;
  width: 30px; height: 30px; border-radius: 9px;
  background: var(--surface); color: var(--signal);
  border: 1px solid var(--signal-line);
}
.proposal-body { flex: 1; min-width: 0; }
.proposal h2 { margin: 0; font: 600 14px var(--ui); letter-spacing: -0.01em; }
.proposal p { margin: 5px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.proposal-from q { font-style: italic; }
.proposal-check { color: var(--ink-2); }
.proposal-actions { display: flex; gap: 8px; flex: none; align-items: center; }

@media (max-width: 720px) {
  .proposal { flex-wrap: wrap; }
  .proposal-actions { width: 100%; }
}

/* Turning an order down, folded away.
   Not a second button beside Approve: the two are not a pair of equal answers.
   Approving is what happens to almost all of them, and refusing wants a reason
   typed — which is a form, and a form that is always open reads as a question
   being asked of every quote. */
.proposal-refuse { margin: -12px 0 20px; }
.proposal-refuse > summary { cursor: pointer; font-size: 13px; color: var(--ink-3); }
.proposal-refuse > summary:hover { color: var(--ink); }
.proposal-refuse form { margin-top: 10px; max-width: 520px; }

/* What a proposal wears where a person's record would say DRAFT. */
.badge-proposed {
  background: var(--signal-bg); color: var(--signal);
  border-color: var(--signal-line);
}

/* --- what the conversation made --- */
/* Heavier than a bubble on purpose: this is the one thing in the thread that
   is not talk. It sits full width rather than in a speech lane, because it did
   not come from either side of the conversation — it is the outcome of it. */
.ap-draft {
  align-self: stretch;
  border: 1px solid var(--signal-line);
  border-left: 3px solid var(--signal);
  border-radius: var(--r);
  background: var(--surface);
  padding: 12px 14px;
}
.ap-draft-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.ap-draft-kind {
  font: 500 10.5px var(--ui); text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink-3);
}
.ap-draft-state {
  font: 500 10.5px var(--ui); text-transform: uppercase; letter-spacing: .06em;
  color: var(--signal);
}
.ap-draft-title { margin: 5px 0 0; font: 600 14px var(--mono); color: var(--ink); }
.ap-draft-facts { margin: 3px 0 0; font-size: 12.5px; color: var(--ink-2); }
.ap-draft-actions { display: flex; align-items: center; gap: 10px; margin-top: 11px; }
.ap-draft-actions form { margin: 0; }

/* Once it has been decided the card is a record of what happened, not a thing
   asking for attention. */
.ap-draft.is-settled { border-color: var(--line); border-left-color: var(--line-2); }
.ap-draft.is-settled .ap-draft-state { color: var(--ok); }

/* --- something happened --- */
/* Not a bubble: nobody said this. A quiet line across the thread, with rules
   either side, so the eye reads it as a change of state rather than a turn. */
.ap-event {
  display: flex; align-items: center; gap: 10px;
  margin: 2px 0; font-size: 12px; color: var(--ink-3);
  text-align: center; justify-content: center;
}
.ap-event::before, .ap-event::after {
  content: ""; flex: 1; height: 1px; background: var(--line);
}

/* --- something it wants to do, waiting on you --- */
/* Reads like the draft card because it is the same kind of moment, but amber
   all through rather than only at the edge: a draft has already happened and
   is sitting there, while this has not happened at all. */
.ap-pending {
  align-self: stretch;
  border: 1px solid var(--signal); border-radius: var(--r);
  background: var(--signal-bg);
  padding: 12px 14px;
}
.ap-pending-kind {
  font: 500 10.5px var(--ui); text-transform: uppercase; letter-spacing: .07em;
  color: var(--signal);
}
.ap-pending-what { margin: 5px 0 0; font-size: 14px; line-height: 1.45; color: var(--ink); }
.ap-pending-note { margin: 3px 0 0; font-size: 12.5px; color: var(--ink-2); }
.ap-pending-actions { display: flex; align-items: center; gap: 10px; margin-top: 11px; }
.ap-pending-actions form { margin: 0; }

/* A run whose process died. Said in the thread where the dots were, so it
   reads as what happened to that question rather than as a page-level error
   about something else. */
.ap-bubble.ap-stalled {
  background: var(--signal-bg);
  border: 1px solid var(--signal-line);
  color: var(--ink-2);
  font-size: 13.5px;
}
