/* reporter
   In-app bug reporting: the drawer, and marking up a screenshot.

   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. */

/* ---------------- in-app reporting ---------------- */

/* ---------------- the launcher ---------------- */
/* Three doors, not one door and a lobby. The large one is what people open
   this for daily; the two beside it are occasional, and sized to say so.

   Every property the global `button, .button` rule sets has to be undone here
   — padding, background, border, colour — AND the background it sets on
   :hover, which is the half that gets forgotten and leaves a black tile with
   an invisible mark on it. */
.reporter-launcher {
  position: fixed; right: 22px; bottom: 22px; z-index: 40;
  display: flex; align-items: center; gap: 6px;
}

.reporter-launch {
  display: grid; place-items: center;
  padding: 0; line-height: 0; cursor: pointer;
  background: var(--surface);
  border: 1px solid var(--line-2);
  color: var(--ink-3);
  box-shadow: 0 2px 10px rgba(20, 20, 18, .10);
  transition: background .16s ease, border-color .16s ease,
              color .16s ease, transform .16s ease;
}
.reporter-launch:hover { background: var(--paper); color: var(--ink); transform: translateY(-1px); }
.reporter-launch:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }

/* The one they came for. Amber, because that is what the assistant is marked
   with everywhere else in the app. */
.reporter-launch.is-main {
  width: 56px; height: 56px; border-radius: 17px;
  color: var(--signal); border-color: var(--signal-line);
}
.reporter-launch.is-main:hover {
  background: var(--signal-bg); border-color: var(--signal); color: var(--signal);
}

.reporter-launch-stack { display: flex; flex-direction: column; gap: 6px; }
.reporter-launch.is-small { width: 25px; height: 25px; border-radius: 8px; }

/* 25px is a small thing to hit with a thumb. The mark stays that size and the
   reach around it does not: this widens the target to roughly 37 by 31
   without moving anything on screen, and stops short of the gap so the two
   never overlap. */
.reporter-launch.is-small::after {
  content: ""; position: absolute; inset: -3px -6px;
}
.reporter-launch.is-small { position: relative; }

.reporter-launch svg { display: block; }

@media (max-width: 720px) {
  .reporter-launcher { right: 14px; bottom: 14px; }
}

.reporter-panel { position: fixed; inset: 0; z-index: 60; }
.reporter-scrim {
  position: absolute; inset: 0; background: rgba(20,20,18,.22);
  opacity: 0; transition: opacity .22s ease;
}

/* --- opening and closing --- */
/* The drawer comes from the right edge, which is where the button that opens
   it lives — so it reads as that button unfolding rather than as a dialog
   arriving from nowhere. The scrim fades a little faster than the sheet
   slides, so the page is already settling as the panel lands.
   
   The curve is fast-out: most of the distance is covered early and the last
   few pixels ease in. A symmetrical ease makes a 520px drawer feel slow at
   both ends.
   
   `.is-open` is added a frame AFTER the panel stops being `hidden` — a
   transition needs a rendered "from" state, and an element that was
   display:none has never had one. */
.reporter-panel.is-open .reporter-scrim { opacity: 1; }

.reporter-sheet {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(520px, 100vw);
  transform: translateX(100%);
  transition: width .18s ease, transform .28s cubic-bezier(.32, .72, 0, 1);
  display: flex; flex-direction: column;
  overflow-y: auto;
  background: var(--surface);
  border-left: 1px solid var(--line-2);
  box-shadow: -18px 0 44px rgba(20,20,18,.16);
  padding: 20px;
}

.reporter-panel.is-open .reporter-sheet { transform: translateX(0); }

/* Closing is quicker than opening. Getting out of the way should not be
   something you wait for. */
.reporter-panel:not(.is-open) .reporter-sheet { transition-duration: .18s, .2s; }

/* Motion is the whole point of this, so honouring the preference means
   turning it off rather than shortening it. */
@media (prefers-reduced-motion: reduce) {
  .reporter-scrim, .reporter-sheet { transition: none; }
}

/* Wider while marking up: the screenshot is the artefact, and every extra
   pixel is one less thing you have to zoom to see. A conversation gains
   nothing from the same width — long lines are harder to read, not easier. */
.reporter-panel.is-marking .reporter-sheet { width: min(760px, 100vw); }

.reporter-close {
  position: absolute; top: 12px; right: 14px; z-index: 2;
  display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 6px;
  background: none; border: none; padding: 0;
  font-size: 20px; line-height: 1;
  color: var(--ink-3); cursor: pointer;
}
/* Dark disc, light glyph — rather than the global black hover landing behind
   ink-coloured text and reading as a filled square. */
.reporter-close:hover, .reporter-close:focus-visible {
  background: var(--ink); color: #fff;
}

/* A display rule beats the hidden attribute, so anything given display:grid or
   display:flex stops being hideable. This caught the choices, and then caught
   the form when it gained display:flex — so it's said once, for every view,
   rather than per class. */
.reporter [hidden] { display: none !important; }

/* --- what each view is --- */
/* The same shape as the assistant panel's own header, because they are the
   same kind of thing: a mark, a name, and one line saying what happens here.
   The launcher goes straight in now, so nothing else tells you what you
   opened. */
.reporter-head {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 26px 0 12px;
  border-bottom: 1px solid var(--line);
}
.reporter-head-mark {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: 8px;
  background: var(--paper); color: var(--ink-2);
  border: 1px solid var(--line-2);
}
.reporter-head h2 {
  margin: 0; font: 600 14px var(--ui); letter-spacing: -0.01em; color: var(--ink);
}
.reporter-head p {
  margin: 2px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--ink-3);
}

/* --- marking up --- */

.reporter-toolbar {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 7px 8px; margin: 12px 0 8px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 9px;
}

/* Every control on the strip is the same square, so the icons line up on one
   grid instead of each sitting wherever its own artwork lands. */
.reporter-tool {
  display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 6px;
  border: none; background: none; color: var(--ink-2); cursor: pointer;
  padding: 0;
}
.reporter-tool:hover { background: var(--surface); color: var(--ink); }
.reporter-tool.is-on { background: var(--ink); color: #fff; }

.reporter-divider { width: 1px; height: 18px; background: var(--line-2); }
.reporter-tools { display: flex; gap: 2px; }

.reporter-colours { display: flex; gap: 5px; }
.reporter-swatch {
  width: 15px; height: 15px; border-radius: 50%; padding: 0;
  background: var(--swatch); border: none;
  box-shadow: 0 0 0 1px rgba(0,0,0,.14); cursor: pointer;
}
.reporter-swatch.is-on { box-shadow: 0 0 0 1.5px var(--surface), 0 0 0 3px var(--ink); }

.reporter-status { font-size: 11.5px; color: var(--ink-3); margin: 0 0 10px 2px; }
/* Wraps to its own line rather than being clipped when the strip is full. */
.reporter-tool-actions { display: flex; gap: 10px; margin-left: auto; }

.reporter-shot {
  position: relative; padding: 7px;
  background: var(--paper); border: 1px solid var(--line); border-radius: 10px;
}
/* A window onto the picture rather than the whole picture squeezed to fit:
   at panel width a full page is unreadable, so it can be bigger than its
   frame and scrolled. */
.reporter-viewport {
  overflow: auto; max-height: 46vh; border-radius: 4px;
  background: var(--surface);
  overscroll-behavior: contain;
}
.reporter-shot canvas {
  display: block; cursor: crosshair; touch-action: none;
  box-shadow: 0 1px 3px rgba(20,20,18,.1);
}
.reporter-shot canvas.is-picking { cursor: default; }
.reporter-shot canvas.is-panning { cursor: grab; }
.reporter-shot canvas.is-panning:active { cursor: grabbing; }

.reporter-textsize { display: flex; gap: 2px; }
.reporter-a { font: 600 15px var(--ui); line-height: 1; }
.reporter-a.is-small { font-size: 11px; }

.reporter-zoom { display: flex; align-items: center; gap: 1px; }
.reporter-zoom-level {
  min-width: 42px; height: 28px; padding: 0 4px;
  border: none; background: none; cursor: pointer;
  font: 500 11.5px var(--mono); color: var(--ink-2);
  border-radius: 6px;
}
.reporter-zoom-level:hover { background: var(--surface); color: var(--ink); }
/* Sized to itself, not to the form: a global full-width input rule stretched
   this across the whole picture, so it never looked anchored to the click. */
.reporter-text-entry {
  position: absolute; transform: translate(-4px, -50%);
  font: 500 13px var(--ui);
  padding: 4px 8px; border: 1px solid var(--ink); border-radius: 5px;
  background: #fff; z-index: 3;
  width: 210px; min-width: 0; max-width: 210px;
  box-shadow: 0 2px 8px rgba(20,20,18,.18);
}

/* The description is the part people actually have to compose, so it gets the
   room. */
.reporter-fields { margin-top: 16px; }
.reporter-field-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 6px;
}
.reporter-fields label { display: block; margin: 0; }

.reporter-dictate {
  display: flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: 999px;
  border: 1px solid var(--line-2); background: var(--paper);
  font: 500 11.5px var(--ui); color: var(--ink-2); cursor: pointer;
}
.reporter-dictate:hover { background: var(--surface); border-color: var(--ink-3); color: var(--ink); }
/* Listening has to be unmistakable — a microphone that's on and doesn't look
   it is worse than no microphone. */
.reporter-dictate.is-listening {
  background: var(--danger); border-color: var(--danger); color: #fff;
}
.reporter-dictate.is-listening svg { animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }
.reporter-fields textarea { width: 100%; min-height: 130px; resize: vertical; }

/* Three options is a choice, not a form control with a label above it. */
.reporter-severity { display: flex; gap: 6px; margin-top: 10px; }
.reporter-pill { flex: 1; }
.reporter-pill input { position: absolute; opacity: 0; pointer-events: none; }
.reporter-pill span {
  display: block; text-align: center; cursor: pointer;
  padding: 7px 6px; border-radius: 7px;
  border: 1px solid var(--line-2); background: var(--paper);
  font-size: 12.5px; color: var(--ink-2);
}
.reporter-pill input:checked + span {
  background: var(--ink); border-color: var(--ink); color: #fff;
}
.reporter-pill input:focus-visible + span { outline: 2px solid var(--signal); outline-offset: 2px; }

.reporter-actions {
  display: flex; justify-content: space-between; align-items: center;
  gap: 14px; margin-top: auto; padding-top: 16px;
  border-top: 1px solid var(--line);
}
.reporter-fineprint { font-size: 11px; margin: 0; line-height: 1.5; }
.reporter-form { display: flex; flex-direction: column; flex: 1; padding-top: 26px; }

@media (max-width: 560px) {
  .reporter-sheet { width: 100vw; padding: 16px; }
}

.report-shot { max-width: 100%; border: 1px solid var(--line); border-radius: 8px; }
.report-errors {
  font: 400 11.5px var(--mono); background: var(--paper); padding: 10px;
  border-radius: 6px; overflow-x: auto; white-space: pre-wrap; margin: 0;
}
.report-meta { font: 400 12px var(--mono); text-align: right; word-break: break-all; }

/* What the interview produced, shown back so nobody has to trust it. */
.run-filed { margin: 0; display: grid; gap: 14px; }
.run-filed dt {
  font: 500 11px/1 var(--ui); letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 5px;
}
.run-filed dd { margin: 0; font-size: 14.5px; line-height: 1.6; }
