/* The review, in the spirit of ispell-buffer in Emacs: monospace text in a
   window with a header line, the choices and the log in windows of their
   own, a status bar, and an echo area that turns into a typing line.

   Everything is scoped under .fly-root. A host page themes it by setting
   --fly-* on any ancestor: bg fg dim line bar-bg bar-fg head-bg accent
   accent-fg region cursor-bg cursor-fg kept-line
   changed-bg changed-fg error font scheme. The --_* names below are private: they hold the defaults. */

.fly-root {
  color-scheme: var(--fly-scheme, light dark);

  --_bg:         var(--fly-bg,         light-dark(#fdfdfc, #1e2025));
  --_fg:         var(--fly-fg,         light-dark(#1d1d1f, #d6d8dc));
  --_dim:        var(--fly-dim,        light-dark(#5f6268, #9aa0a9));
  --_line:       var(--fly-line,       light-dark(#b9bbc0, #3b3f47));
  --_bar-bg:     var(--fly-bar-bg,     light-dark(#d9dade, #353942));
  --_bar-fg:     var(--fly-bar-fg,     light-dark(#15161a, #e8eaee));
  --_head-bg:    var(--fly-head-bg,    light-dark(#eceef0, #292c33));
  --_accent:     var(--fly-accent,     light-dark(#1f5fa8, #7db4ec));
  --_accent-fg:  var(--fly-accent-fg,  light-dark(#ffffff, #10141a));
  --_region:     var(--fly-region,     light-dark(#cfe0f5, #3a4d6b));
  --_cursor-bg:  var(--fly-cursor-bg,  light-dark(#ffe28a, #86651a));
  --_cursor-fg:  var(--fly-cursor-fg,  light-dark(#1d1d1f, #fff6d6));
  --_changed-bg: var(--fly-changed-bg, light-dark(#d5ecd0, #23402b));
  --_changed-fg: var(--fly-changed-fg, light-dark(#14481b, #b4e6ac));
  --_kept-line:  var(--fly-kept-line,  light-dark(#15803d, #4ade80));
  --_error:      var(--fly-error,      light-dark(#a4262c, #ff8f8f));
  --_font:       var(--fly-font, ui-monospace, "JetBrains Mono", "DejaVu Sans Mono",
                                 "Cascadia Mono", Menlo, Consolas, monospace);

  box-sizing: border-box;
  height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--_bg);
  color: var(--_fg);
  border: 1px solid var(--_line);
  font-family: var(--_font);
  font-size: 0.95rem;
  line-height: 1.5;
  /* A phone does not enlarge some blocks of text and not others. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

.fly-root *,
.fly-root *::before,
.fly-root *::after {
  box-sizing: border-box;
  scrollbar-width: thin;
  scrollbar-color: var(--_line) transparent;
}

.fly-root ::selection { background: var(--_region); }

/* Faces: what the review does to the text. */

.fly-root .proposed {
  text-decoration: underline;
}

.fly-root .retained {
  text-decoration: underline var(--_kept-line);
}

.fly-root .changed {
  background: var(--_changed-bg);
  color: var(--_changed-fg);
}

.fly-root .unplaced {
  color: var(--_error);
  text-decoration: underline wavy var(--_error);
}

.fly-root .cursor {
  background: var(--_cursor-bg);
  color: var(--_cursor-fg);
  /* A cursor that wraps keeps its glow on every line it spans. */
  box-decoration-break: clone;
}

.fly-root .document [data-role="site"] {
  cursor: pointer;
}

/* The review: windows from top to bottom. The DOM lists the status first;
   `order` puts the status bar and the echo area last. */

.fly-root .review,
.fly-root .finished,
.fly-root .setup {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.fly-root .pane     { order: 1; }
.fly-root .menu     { order: 2; }
.fly-root .log      { order: 3; }
.fly-root .status   { order: 4; }
.fly-root .typing,
.fly-root .keys     { order: 5; }

/* The text. The pane scrolls, so the header line stays in view. */

.fly-root .pane {
  flex: 1 1 0;
  min-height: 5rem;
  overflow: auto;
}

.fly-root .pane > .label {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 0 1ch;
  background: var(--_head-bg);
  box-shadow: inset 0 -1px 0 var(--_line);
  white-space: pre;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fly-root .document {
  margin: 0;
  padding: 0.75rem 1ch 1.5rem;
  max-width: 78ch;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  font: inherit;
}

/* The choices, listed below the text. The decided one wears the same face as
   the text it changed. */

.fly-root .menu {
  max-height: 40%;
  overflow: auto;
  border-top: 1px solid var(--_line);
}

.fly-root .menu::before,
.fly-root .log::before {
  display: block;
  padding: 0 1ch;
  background: var(--_head-bg);
  color: var(--_dim);
  box-shadow: inset 0 -1px 0 var(--_line);
  white-space: normal;
}

.fly-root .menu::before { content: "Choices"; }

.fly-root .choice {
  padding: 0.1rem 1ch;
}

.fly-root .menu .choice[data-choice] { cursor: pointer; }
.fly-root .menu .choice[data-choice]:hover { background: var(--_region); }

.fly-root .reason {
  padding-left: 4ch;
  color: var(--_dim);
}

.fly-root .choice.decided {
  background: var(--_changed-bg);
  color: var(--_changed-fg);
}

.fly-root .choice.decided .reason { color: inherit; }

/* The session log: a window of seven lines that scrolls, its header kept in
   view. Its lines are laid out from the bottom up, so it opens on the newest
   and stays there as more arrive until the reader scrolls up. */

.fly-root .log {
  display: flex;
  flex-direction: column;
  height: calc(7lh + 1px);
  border-top: 1px solid var(--_line);
  color: var(--_dim);
}

.fly-root .log::before {
  content: "Log";
  flex: none;
}

.fly-root .log .lines {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column-reverse;
  overflow-y: auto;
}

.fly-root .log pre {
  flex: none;
  margin: 0;
  padding: 0 1ch;
  font: inherit;
}

/* The status bar. */

.fly-root .status {
  padding: 0 1ch;
  background: var(--_bar-bg);
  color: var(--_bar-fg);
  border-top: 1px solid var(--_line);
  white-space: pre;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The echo area shows the keys, and gives way to the typing line. */

.fly-root .keys {
  padding: 0 1ch;
  color: var(--_dim);
}

.fly-root .review:has(.typing) .keys { display: none; }

.fly-root .typing {
  display: flex;
  align-items: baseline;
  gap: 1ch;
  padding: 0 1ch;
}

.fly-root .typing > .label {
  flex: none;
  color: var(--_accent);
  font-weight: 700;
  white-space: nowrap;
}

.fly-root .typing input {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: inherit;
  caret-color: var(--_accent);
  font: inherit;
}

/* A field under 16px makes a phone zoom in when it takes the focus. */
@media (pointer: coarse) {
  .fly-root .typing input,
  .fly-root textarea { font-size: max(16px, 1em); }
}

.fly-root .typing:focus-within {
  outline: 2px solid var(--_accent);
  outline-offset: -2px;
}

/* The finished review: two windows, the text and the log, each with a header
   line that carries its Download button. */

.fly-root .finished > h2 {
  margin: 0;
  padding: 0.75rem 1ch 0;
  font: inherit;
  font-weight: 700;
}

.fly-root .finished > p {
  margin: 0;
  padding: 0 1ch;
}

.fly-root .finished > .actions {
  padding: 0.5rem 1ch 0.75rem;
}

.fly-root .file {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--_line);
}

.fly-root .file > .label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1ch;
  padding: 0 1ch;
  background: var(--_head-bg);
  box-shadow: inset 0 -1px 0 var(--_line);
}

.fly-root .file > pre {
  flex: 1;
  margin: 0;
  padding: 0.5rem 1ch;
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  font: inherit;
}

/* Buttons are plain boxes that invert under the pointer. */

.fly-root button {
  padding: 0 1ch;
  border: 1px solid var(--_line);
  border-radius: 0;
  background: var(--_bar-bg);
  color: var(--_bar-fg);
  font: inherit;
  cursor: pointer;
}

.fly-root button:hover {
  border-color: var(--_accent);
  background: var(--_accent);
  color: var(--_accent-fg);
}

.fly-root button:focus-visible {
  outline: 2px solid var(--_accent);
  outline-offset: 1px;
}

/* The setup: what is chosen so far, and where the proposals come from. */

.fly-root .setup > h2 {
  margin: 0;
  padding: 0.75rem 1ch 0;
  font: inherit;
  font-weight: 700;
}

.fly-root .setup .fields,
.fly-root .setup .options,
.fly-root .setup .actions {
  padding: 0.25rem 1ch;
}

/* The setup form: each field is a label and its control, and every label
   shares one column, so the controls line up. The box takes the rest of its
   row, up to a measure that reads well, and grows with what is typed (where
   the browser can) to a share of the screen, then scrolls. A narrow screen
   stacks each label over its control. */

.fly-root .setup .form {
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: 1ch;
  align-items: start;
  padding: 0.25rem 1ch;
}

.fly-root .setup .form > .submenu { grid-column: 1 / -1; }

.fly-root .setup .form textarea {
  box-sizing: border-box;
  width: 100%;
  max-width: 72ch;
  min-height: 3lh;
  max-height: 40vh;
  font: inherit;
  resize: vertical;
  field-sizing: content;
}

@media (max-width: 40rem) {
  .fly-root .setup .form { grid-template-columns: 1fr; }
}

/* A file dragged over the page: the form says where it will land. */

body.fly-dragging .fly-root .setup .form {
  outline: 2px dashed var(--_accent);
  outline-offset: -2px;
}

.fly-root .option {
  padding: 0 1ch;
  cursor: pointer;
}

.fly-root .option:hover { background: var(--_region); }

.fly-root .option.chosen {
  background: var(--_cursor-bg);
  color: var(--_cursor-fg);
}

.fly-root .setup .note { color: var(--_dim); }

/* Whether a source answers, beside it, and where sources are looked for. */

.fly-root .reach { color: var(--_dim); }
.fly-root .reach.reached { color: var(--_kept-line); }
.fly-root .reach.unreachable { color: var(--_error); }
.fly-root .option.chosen .reach { color: inherit; }

.fly-root .setup .places {
  padding: 0.25rem 1ch;
  color: var(--_dim);
}

.fly-root .setup .offer {
  display: flex;
  align-items: baseline;
  gap: 1ch;
  margin-left: 3ch;
}

/* A list of models or prompts to click. The models are a submenu of the
   option chosen: set in under its label, behind a rule. Each row is a
   button: boxed, and lit under the pointer. */

.fly-root .submenu {
  margin: 0 0 0.25rem 3ch;
  padding-left: 1ch;
  border-left: 1px solid var(--_line);
}

.fly-root .setup .choices {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 0.25rem 0;
}

.fly-root .setup .choices .title { color: var(--_dim); }

.fly-root .setup .choice {
  padding: 0 1ch;
  border: 1px solid var(--_line);
  border-radius: 3px;
  cursor: pointer;
}

.fly-root .setup .choice:hover { background: var(--_region); }

.fly-root .setup .choice.chosen {
  background: var(--_cursor-bg);
  color: var(--_cursor-fg);
}

/* Before and instead of a review. */

.fly-root .loading {
  padding: 0.75rem 1ch;
  color: var(--_dim);
}

.fly-root .failure {
  margin: 0.75rem 1ch;
  padding-left: 1ch;
  border-left: 3px solid var(--_error);
}

.fly-root .failure h2 {
  margin: 0;
  color: var(--_error);
  font: inherit;
  font-weight: 700;
}

.fly-root .failure pre {
  margin: 0.5rem 0 0;
  font: inherit;
  white-space: pre-wrap;
}

/* The legend's keys press themselves; they look like the text they were. */

.fly-root .keys .key.pressable { cursor: pointer; }
.fly-root .keys .key.pressable:hover { background: var(--_region); }

/* A phone gives the room to the text and the choices; the status line still says what happened. */
@media (pointer: coarse) {
  .fly-root .review .log { display: none; }
}
