/*
 * The three overlays (§7 session sheet, §8 History, §9 ⌘K) and the import
 * review screen (§10).
 *
 * Loaded after styles.css so the import review's restyle lands on top of the
 * older rules for the same class names; every value comes from tokens.css, and
 * there is not a literal colour anywhere in this file.
 *
 * These are the only surfaces in the product that sit over the manuscript, and
 * each one is opened by the author and closes to nothing. Nothing here animates
 * in, and nothing arrives on its own -- the whole point of the session sheet is
 * that findings *do not* interrupt.
 */

.novely-overlay-scrim {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 8vh 24px 24px;
  background: color-mix(in srgb, var(--text) 18%, transparent);
  z-index: 20;
}

.novely-overlay {
  display: flex;
  flex-direction: column;
  max-height: 84vh;
  overflow: auto;
  background: var(--panel);
  color: var(--text);
  font-family: var(--font-ui);
  border: 1px solid var(--border);
  border-radius: var(--r-popover);
  box-shadow: var(--shadow-popover);
}

/* Fixed widths: these are documents to read, not windows to manage. */
.novely-overlay-session,
.novely-overlay-history {
  width: 720px;
  max-width: 100%;
}

.novely-overlay-palette {
  width: 600px;
  max-width: 100%;
}

.novely-overlay-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 20px 24px 14px;
  border-bottom: 1px solid var(--hairline);
}

.novely-overlay-title {
  font-size: var(--size-14);
  font-weight: 500;
  line-height: 1.2;
  color: var(--text);
}

.novely-overlay-meta {
  font-family: var(--font-mono);
  font-size: var(--size-11);
  color: var(--muted-4);
}

.novely-overlay-spacer {
  flex: 1;
}

.novely-overlay-close {
  font-family: var(--font-mono);
  font-size: var(--size-13);
  color: var(--muted-5);
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 2px 4px;
}

.novely-overlay-close:hover {
  color: var(--text);
}

.novely-overlay-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 24px 8px;
}

.novely-group-label {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-4);
}

.novely-overlay-empty {
  margin: 0;
  font-size: var(--size-12-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-3);
}

.novely-overlay-aside {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  line-height: 1.5;
  color: var(--muted-6);
}

.novely-overlay-unrouted {
  padding: 0 24px 16px;
}

.novely-overlay-foot {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 24px 20px;
}

/* --- shared controls ---------------------------------------------------- */

.novely-button-primary {
  font-family: var(--font-ui);
  font-size: var(--size-11-5);
  font-weight: 500;
  color: var(--panel);
  background: var(--text);
  border: 1px solid var(--text);
  border-radius: 15px;
  padding: 8px 16px;
  cursor: pointer;
}

.novely-button-secondary {
  font-family: var(--font-ui);
  font-size: var(--size-11-5);
  color: var(--muted-2);
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: 15px;
  padding: 8px 14px;
  cursor: pointer;
}

.novely-button-secondary:hover {
  border-color: var(--border-hover);
}

.novely-button-primary[disabled],
.novely-button-secondary[disabled] {
  cursor: not-allowed;
  opacity: 0.45;
}

.novely-chip-bordered {
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
  color: var(--muted-2);
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-composer);
  padding: 4px 9px;
  cursor: pointer;
}

.novely-chip-bordered:hover {
  border-color: var(--border-hover);
}

.novely-chip-bordered.novely-chip-on {
  color: var(--panel);
  background: var(--text);
  border-color: var(--text);
}

.novely-text-button {
  font-family: var(--font-ui);
  font-size: var(--size-11);
  color: var(--muted-3);
  background: transparent;
  border: 0;
  padding: 4px 0;
  cursor: pointer;
}

.novely-text-button:hover {
  color: var(--text);
}

.novely-segments {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: 6px;
}

.novely-segment {
  font-family: var(--font-ui);
  font-size: var(--size-11);
  color: var(--muted-3);
  background: transparent;
  border: 0;
  border-radius: var(--r-button);
  padding: 5px 10px;
  cursor: pointer;
}

.novely-segment:hover {
  background: var(--row-hover-strong);
  color: var(--text);
}

.novely-segment-on {
  font-weight: 500;
  color: var(--text);
  background: var(--row-active-strong);
}

/* Kind dots. Colour and nothing else: no label, no badge, no severity. */
.novely-kind-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
  margin-top: 6px;
  background: var(--kind-observed);
}

.novely-kind-dot.novely-kind-proved {
  background: var(--kind-proved);
}

.novely-kind-dot.novely-kind-violated {
  background: var(--kind-violated);
}

.novely-kind-dot.novely-kind-observed {
  background: var(--kind-observed);
}

/* --- session sheet (§7) -------------------------------------------------- */

.novely-finding-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 11px 0;
  border-top: 1px solid var(--hairline);
}

.novely-finding-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.novely-finding-body {
  font-size: var(--size-13-5);
  line-height: 1.5;
  color: var(--prose);
}

.novely-finding-meta {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-5);
}

.novely-finding-actions {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
}

.novely-finding-dismiss {
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
  color: var(--muted-4);
  background: transparent;
  border: 0;
  padding: 4px;
  cursor: pointer;
}

.novely-finding-dismiss:hover {
  color: var(--text);
}

.novely-observed {
  padding-top: 8px;
}

/* Four readings are one grey line, not four rows of work. */
.novely-observed-line {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--hairline);
  padding: 8px 0;
  text-align: left;
  cursor: pointer;
}

.novely-observed-line .novely-kind-dot {
  margin-top: 0;
}

.novely-observed-text {
  flex: 1;
  font-size: var(--size-12-5);
  color: var(--muted-3);
}

.novely-observed-more {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-6);
}

/* --- History (§8) -------------------------------------------------------- */

.novely-history-body {
  display: flex;
  min-height: 0;
}

.novely-session-list {
  width: 268px;
  flex: none;
  border-right: 1px solid var(--hairline);
  padding: 12px 0;
  display: flex;
  flex-direction: column;
}

.novely-session-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  width: 100%;
  padding: 9px 18px;
  background: transparent;
  border: 0;
  border-left: 2px solid transparent;
  text-align: left;
  cursor: pointer;
}

.novely-session-row:hover {
  background: var(--row-hover);
}

/* The same open-row treatment the chapter rail uses; one idea, one look. */
.novely-session-row-on {
  background: var(--row-active);
  border-left-color: var(--text);
}

.novely-session-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.novely-session-title {
  flex: 1;
  font-size: var(--size-12);
  color: var(--muted-1);
}

.novely-session-row-on .novely-session-title {
  font-weight: 500;
  color: var(--text);
}

.novely-session-delta {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-5);
}

.novely-delta-added {
  color: var(--addition);
}

.novely-delta-removed {
  color: var(--deletion);
}

.novely-session-sub {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-5);
}

.novely-history-diff {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px 20px;
}

.novely-diff {
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-family: var(--font-prose);
  font-size: var(--size-14);
  line-height: 1.65;
}

.novely-diff-line {
  margin: 0;
}

.novely-diff-removed {
  color: var(--muted-3);
  text-decoration: line-through;
  text-decoration-color: var(--border);
}

.novely-diff-added {
  color: var(--prose);
  background: var(--addition-wash);
  box-shadow: inset 2px 0 0 var(--addition);
  padding-left: 12px;
}

.novely-diff-same {
  color: var(--muted-2);
}

.novely-history-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding-top: 6px;
  border-top: 1px solid var(--hairline);
}

/* --- ⌘K (§9) ------------------------------------------------------------- */

.novely-palette-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--hairline);
}

.novely-palette-key {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-6);
}

.novely-palette-input {
  flex: 1;
  font-family: var(--font-ui);
  font-size: 15px;
  color: var(--prose);
  background: transparent;
  border: 0;
  outline: none;
  padding: 0;
}

.novely-palette-results {
  display: flex;
  flex-direction: column;
  padding: 10px 0 12px;
}

.novely-command-group {
  display: flex;
  flex-direction: column;
}

.novely-command-group .novely-group-label {
  font-size: var(--size-9-5);
  letter-spacing: 0.08em;
  font-weight: 400;
  color: var(--muted-7);
  padding: 6px 18px 4px;
}

.novely-group-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border: 0;
  background: transparent;
  cursor: pointer;
  text-align: left;
}

.novely-group-chevron {
  color: var(--muted-3);
  font-size: 12px;
}

.novely-command-group + .novely-command-group .novely-group-label {
  padding-top: 12px;
}

.novely-command {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 18px;
  cursor: pointer;
}

.novely-command:hover {
  background: var(--row-hover);
}

.novely-command-on {
  background: var(--row-active);
}

.novely-command-label {
  flex: 1;
  font-size: var(--size-13);
  color: var(--muted-1);
}

.novely-command-on .novely-command-label {
  color: var(--prose);
}

.novely-command-subject {
  color: var(--muted-3);
}

.novely-command-hint {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-5);
}

/* --- import review (§10) ------------------------------------------------- */

/*
 * The screen is a column, and the order of that column is the argument: the
 * book, what pressing Import will do, Import, and only then the handful of
 * things that are leaving the manuscript. The design's left-hand tally is
 * still here -- it is the last row, closed, because on a real novel it says
 * "3,130 stay" and that is not news.
 */

.novely-import {
  width: 100%;
  max-width: 780px;
  margin: 0 auto;
  font-family: var(--font-ui);
  color: var(--text);
}

.novely-review {
  display: flex;
  flex-direction: column;
  gap: 18px;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: var(--r-popover);
  padding: 24px;
}

.novely-review-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--hairline);
}

/*
 * The book, in the size the book deserves. Selected through its parent because
 * the older `styles.css` still styles `.novely-review-head h2` and loads first;
 * two classes beat a class and a tag.
 */
.novely-review-head .novely-review-title {
  margin: 0;
  font-size: var(--size-title);
  font-weight: 500;
  line-height: 1.15;
  color: var(--text);
}

.novely-review-stat {
  margin: 0;
  font-size: var(--size-13);
  color: var(--muted-1);
}

/* The filename the author actually has is 90 characters of parentheses. */
.novely-review-file {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
  line-height: 1.5;
  color: var(--muted-4);
  overflow-wrap: anywhere;
}

.novely-review-verified {
  margin: 4px 0 0;
  font-family: var(--font-mono);
  font-size: var(--size-11);
  color: var(--verified);
}

/* The sentence most authors will read instead of the review. */
.novely-review-plan {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.novely-review-sentence {
  margin: 0;
  font-size: var(--size-14);
  line-height: var(--leading-ui-prose);
  color: var(--prose);
}

.novely-review-plan-note {
  margin: 0;
  font-size: var(--size-11-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-2);
}

/*
 * The row Import sits in.
 *
 * A row, and nothing else: no background, no border, no `position: sticky`.
 * It had all three, from an older copy of this rule in `styles.css` that this
 * one only partly overrode -- so the button arrived inside a full-width band
 * the width of the card, and the band read as the control. An author looking
 * at it could not tell where to press, and pressing the band did nothing,
 * because the button was the 98px of it with the word on.
 */
.novely-review-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding-top: 4px;
}

/* Unmistakably a button: its own shape, its own colour, its own edges. */
.novely-import-go {
  flex: none;
  font-size: var(--size-13);
  padding: 10px 26px;
  border-radius: var(--r-primary);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--text) 18%, transparent);
}

.novely-import-go:hover:not([disabled]) {
  background: var(--secondary);
  border-color: var(--secondary);
}

.novely-review-promise {
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
  color: var(--muted-3);
}

.novely-review-spacer {
  flex: 1;
}

.novely-review-clean {
  margin: 0;
  font-size: var(--size-12);
  color: var(--muted-2);
}

/* --- groups: one row per destination, not per block ---------------------- */

.novely-review-groups {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.novely-review-groups-label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-4);
}

.novely-group {
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  padding: 10px 12px;
}

/* Off is a real state, not a disabled one: the text simply stays put. */
.novely-group-off {
  border-style: dashed;
  border-color: var(--hairline);
}

.novely-group-off .novely-group-count {
  color: var(--muted-4);
  text-decoration: line-through;
  text-decoration-color: var(--border);
}

.novely-group-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.novely-group-count {
  font-size: var(--size-12-5);
  color: var(--secondary);
}

.novely-group-words,
.novely-group-partial {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-4);
}

.novely-group-unsure {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--kind-violated);
}

.novely-group-disclosure {
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
}

.novely-group-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--hairline);
  max-height: 420px;
  overflow-y: auto;
}

/* --- the box that is ticked or not --------------------------------------- */

.novely-group-check,
.novely-line-check {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-ui);
  font-size: var(--size-12);
  color: var(--muted-1);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
}

.novely-group-check .novely-check-box,
.novely-line-check .novely-check-box {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  flex: none;
  font-size: var(--size-10);
  line-height: 1;
  color: var(--panel);
  background: transparent;
  border: 1px solid var(--border-hover);
  border-radius: 4px;
}

.novely-checked .novely-check-box {
  color: var(--panel);
  background: var(--text);
  border-color: var(--text);
}

.novely-group-check.novely-checked .novely-check-label {
  color: var(--text);
}

.novely-group-check:hover .novely-check-box,
.novely-line-check:hover .novely-check-box {
  border-color: var(--text);
}

/* --- a single block, inside an opened group ------------------------------ */

.novely-line {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 6px 4px;
  border-radius: var(--r-row);
}

.novely-line:hover {
  background: var(--row-hover);
}

.novely-line-check {
  padding-top: 2px;
}

.novely-line-weak {
  background: color-mix(in srgb, var(--kind-violated) 6%, transparent);
}

.novely-line-off .novely-line-text {
  color: var(--muted-3);
}

.novely-line-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.novely-line-text {
  margin: 0;
  font-family: var(--font-prose);
  font-size: var(--size-13);
  line-height: 1.5;
  color: var(--secondary);
}

/* Cut material: struck through, because agreeing changes nothing about what
   the chapter says today. */
.novely-line-cut {
  color: var(--muted-3);
  text-decoration: line-through;
  text-decoration-color: var(--border);
}

.novely-line-why {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-4);
}

/* --- the full routing, closed by default --------------------------------- */

.novely-review-all {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 12px;
  border-top: 1px solid var(--hairline);
}

.novely-routing-toggle {
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
  align-self: flex-start;
}

.novely-review-tally {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-width: 260px;
}

.novely-tally-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  padding: 4px 0;
}

.novely-tally-name {
  font-size: var(--size-12);
  color: var(--secondary);
}

.novely-tally-count {
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
  color: var(--muted-4);
}

.novely-verified {
  font-family: var(--font-mono);
  font-size: var(--size-11);
  color: var(--verified);
}

/* --- Models & keys (§7, §9) --------------------------------------------- */

/*
 * A fourth overlay, on the same chrome as the other three: fixed width, opened
 * by the author from the palette, closed to nothing. It is a settings screen,
 * so it costs no permanent pixels — the manuscript keeps them.
 */

.novely-overlay-models {
  width: 720px;
  max-width: 100%;
}

.novely-models-headline {
  margin: 0;
  font-size: var(--size-14);
  color: var(--text);
}

.novely-models-body {
  margin: 0;
  font-size: var(--size-12-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-2);
}

.novely-models-t0 {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  border-top: 1px solid var(--hairline);
}

.novely-models-t0-row,
.novely-models-agent-row,
.novely-models-provider {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px solid var(--hairline);
}

.novely-models-agent {
  font-family: var(--font-mono);
  font-size: var(--size-11-5);
  color: var(--text);
  width: 96px;
  flex: none;
}

.novely-models-what {
  flex: 1;
  font-size: var(--size-12);
  color: var(--muted-3);
}

.novely-models-tier {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-4);
}

.novely-models-provider-name {
  font: inherit;
  font-size: var(--size-13);
  color: var(--text);
  background: transparent;
  border: none;
  padding: 0;
  width: 110px;
  flex: none;
  text-align: left;
  cursor: pointer;
}

.novely-models-provider-on .novely-models-provider-name {
  font-weight: 600;
}

.novely-models-provider-status {
  flex: 1;
  font-family: var(--font-mono);
  font-size: var(--size-11);
  color: var(--muted-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.novely-models-provider-count {
  font-size: var(--size-11);
  color: var(--muted-4);
}

.novely-models-forget,
.novely-models-save {
  font-family: var(--font-ui);
  font-size: var(--size-11-5);
  color: var(--text);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--r-button);
  padding: 3px 10px;
  cursor: pointer;
}

.novely-models-fields {
  display: flex;
  gap: 8px;
  align-items: center;
  padding-top: 6px;
}

.novely-models-key,
.novely-models-endpoint {
  flex: 1;
  font-family: var(--font-mono);
  font-size: var(--size-12);
  color: var(--text);
  background: var(--page);
  border: 1px solid var(--border);
  border-radius: var(--r-button);
  padding: 6px 8px;
}

.novely-models-note {
  margin: 0;
  font-size: var(--size-11);
  line-height: var(--leading-ui-prose);
  color: var(--muted-3);
}

.novely-models-notice {
  margin: 0;
  font-size: var(--size-12);
  color: var(--text);
}

.novely-models-assign {
  font-family: var(--font-mono);
  font-size: var(--size-11-5);
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-button);
  padding: 3px 6px;
  max-width: 260px;
}

.novely-models-ledger {
  list-style: none;
  margin: 0 0 12px;
  padding: 0;
  max-height: 220px;
  overflow: auto;
}

.novely-models-ledger-row {
  font-family: var(--font-mono);
  font-size: var(--size-11);
  color: var(--muted-2);
  padding: 2px 0;
  border-bottom: 1px solid var(--hairline);
}

.novely-models-ledger-failed {
  color: var(--kind-proved);
}

/* --- the chat's composer: what is about to be sent ----------------------- */

/*
 * What this question will send, in a word.
 *
 * Five chips used to sit here and the author pressed one of them. They are
 * gone -- the question decides the scope now -- and this is the half that was
 * doing the work: on the composer and not in a tooltip, because how much of an
 * unpublished book is about to leave the machine is the one thing nobody
 * should have to go and look up (§20.6).
 *
 * Quiet, and one shade louder for the two scopes that are expensive. An
 * author who has just typed the word "pacing" should be able to notice that
 * their whole novel is about to go, without the panel shouting about it.
 */
.novely-composer-sends {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  letter-spacing: 0.04em;
  color: var(--muted-4);
}

.novely-composer-sends[data-scope='book'],
.novely-composer-sends[data-scope='codex'] {
  color: var(--muted-1);
}

/* --- which model answers, chosen where the question is asked ------------- */

.novely-composer-model-row {
  display: flex;
  justify-content: flex-end;
  padding-bottom: 4px;
}

.novely-composer-model {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-3);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 1px 2px;
  max-width: 100%;
  cursor: pointer;
}

.novely-composer-model:hover,
.novely-composer-model:focus-visible {
  color: var(--text);
  border-color: var(--border);
}

/* One model for all six, above the six. */
.novely-models-all-row {
  border-bottom: 1px solid var(--hairline);
  padding-bottom: 10px;
  margin-bottom: 4px;
}

.novely-models-all-row .novely-models-agent {
  color: var(--text);
  font-weight: 500;
}

.novely-chat-refusal {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 12px;
  border-top: 1px solid var(--hairline);
}

.novely-chat-refusal-text {
  font-size: var(--size-11-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-1);
}

.novely-chat-refusal-go {
  align-self: flex-start;
  font-family: var(--font-ui);
  font-size: var(--size-11);
  color: var(--text);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--r-button);
  padding: 2px 8px;
  cursor: pointer;
}

/* -- Search (§12) ---------------------------------------------------------- */

.novely-search-body {
  display: grid;
  gap: 0.75rem;
  padding: 0 1.25rem 1.25rem;
  min-height: 0;
}

.novely-search-field {
  width: 100%;
  min-height: 40px;
  padding: 0 0.75rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: 400 var(--size-14) / 1 var(--font-ui);
}

.novely-search-field:focus-visible {
  outline: 2px solid var(--border-hover);
  outline-offset: 1px;
}

.novely-search-results {
  display: grid;
  gap: 0;
  max-height: 60vh;
  overflow-y: auto;
}

/*
 * A row is the line as it reads in the book, with its provenance underneath in
 * the mono face the rest of the chrome uses for the same job.
 */
.novely-search-row {
  display: grid;
  gap: 0.2rem;
  width: 100%;
  padding: 0.6rem 0.5rem;
  border: 0;
  border-bottom: 1px solid var(--hairline);
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.novely-search-row:hover {
  background: var(--row-hover);
}

/* A hit that is not in a chapter is shown and cannot be jumped to. */
.novely-search-row.is-flat {
  cursor: default;
}

.novely-search-excerpt {
  font: 400 var(--size-14) / 1.45 var(--font-prose);
  color: var(--prose);
}

.novely-search-place {
  font: 400 var(--size-11) / 1 var(--font-mono);
  color: var(--muted-3);
}

/* -- The full review (§6) --------------------------------------------------- */

.novely-review-body {
  display: grid;
  gap: 0.85rem;
  padding: 0 1.25rem 1.25rem;
}

.novely-review-line {
  margin: 0;
  font: 400 var(--size-14) / 1.55 var(--font-ui);
  color: var(--text);
}

/*
 * Where the prose goes, and what stopping means. Quieter than the offer but
 * never hidden behind a disclosure: it is the half of the decision that cannot
 * be taken back.
 */
.novely-review-aside {
  margin: 0;
  font: 400 var(--size-12-5) / 1.5 var(--font-ui);
  color: var(--muted-2);
}

.novely-review-trouble {
  margin: 0;
  padding: 0.6rem 0.8rem;
  border-left: 2px solid var(--deletion);
  font: 400 var(--size-13) / 1.5 var(--font-ui);
  color: var(--text);
}

.novely-review-go,
.novely-review-again,
.novely-review-stop {
  justify-self: start;
  min-height: 34px;
  padding: 0 1rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: transparent;
  color: var(--text);
  font: 500 var(--size-13) / 1 var(--font-ui);
  cursor: pointer;
}

.novely-review-go {
  border-color: transparent;
  background: var(--text);
  color: var(--page);
}

.novely-review-bar {
  height: 3px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
}

/* No animation: the width is the truth, and a bar that eases is a bar that
   is ahead of the work. */
.novely-review-bar-fill {
  display: block;
  height: 100%;
  background: var(--text);
}

/* -- Colours (§9) ---------------------------------------------------------- */

.novely-palette-body {
  display: grid;
  gap: 1.25rem;
  padding: 0 1.25rem 1.25rem;
}

.novely-swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 0.5rem;
}

/*
 * A palette drawn as itself: the page is the ground, the ink a bar on it, the
 * accent its edge and a dot. A list of names says nothing about what "sand"
 * looks like, and choosing a colour is done with the eyes.
 */
.novely-swatch {
  position: relative;
  display: grid;
  align-content: end;
  gap: 5px;
  height: 66px;
  padding: 8px;
  border: 1px solid;
  border-radius: 6px;
  cursor: pointer;
  overflow: hidden;
}

.novely-swatch.is-on {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}

.novely-swatch-ink {
  height: 3px;
  width: 60%;
  border-radius: 2px;
  opacity: 0.85;
}

.novely-swatch-dot {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

.novely-swatch-name {
  font: 400 var(--size-11) / 1 var(--font-ui);
  opacity: 0.9;
}

/* -- three hexes ----------------------------------------------------------- */

.novely-palette-custom {
  display: grid;
  gap: 0.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--hairline);
}

.novely-palette-label {
  margin: 0;
  font: 400 var(--size-11) / 1 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-3);
}

.novely-hex {
  display: grid;
  grid-template-columns: 5rem 9rem 18px 1fr;
  align-items: center;
  gap: 0.5rem;
}

.novely-hex-label {
  font: 400 var(--size-13) / 1 var(--font-ui);
  color: var(--text);
}

.novely-hex-input {
  min-height: 30px;
  padding: 0 0.5rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel);
  color: var(--text);
  font: 400 var(--size-13) / 1 var(--font-mono);
}

/* Wrong, not rejected: the field keeps what was typed and says it is not a
   colour yet, and nothing is applied until it is. */
.novely-hex-input.is-wrong {
  border-color: var(--deletion);
}

.novely-hex-swatch {
  width: 18px;
  height: 18px;
  border: 1px solid var(--border);
  border-radius: 4px;
}

.novely-hex-hint {
  font: 400 var(--size-11-5) / 1.3 var(--font-ui);
  color: var(--muted-3);
}

.novely-palette-note,
.novely-palette-warn {
  margin: 0.25rem 0 0;
  font: 400 var(--size-12) / 1.5 var(--font-ui);
  color: var(--muted-2);
}

.novely-palette-warn {
  color: var(--deletion);
}

.novely-palette-use {
  justify-self: start;
  margin-top: 0.5rem;
  min-height: 30px;
  padding: 0 0.9rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: transparent;
  color: var(--text);
  font: 400 var(--size-12-5) / 1 var(--font-ui);
  cursor: pointer;
}

.novely-palette-use.is-on {
  border-color: transparent;
  background: var(--text);
  color: var(--page);
}

.novely-palette-use[disabled] {
  opacity: 0.45;
  cursor: default;
}

/* --- review mode: walking the notes -------------------------------------- */

.novely-walk {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  font-family: var(--font-ui);
  color: var(--text);
}

.novely-walk-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--hairline);
}

.novely-walk-title {
  font-size: var(--size-11);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--secondary);
}

.novely-walk-count {
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
  color: var(--muted-3);
}

.novely-walk-gap {
  flex: 1;
}

.novely-walk-step,
.novely-walk-close {
  border: 1px solid transparent;
  border-radius: 3px;
  padding: 1px 7px;
  background: transparent;
  color: var(--muted-2);
  font-size: var(--size-12);
  cursor: pointer;
}

.novely-walk-step:hover:not([disabled]),
.novely-walk-close:hover {
  border-color: var(--border);
  color: var(--text);
}

.novely-walk-step[disabled] {
  opacity: 0.3;
  cursor: default;
}

/* The note, and the page it came off. This is the half you read. */
.novely-walk-body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.novely-walk-where {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.novely-walk-chapter {
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--secondary);
  font: 500 var(--size-11) / 1.3 var(--font-ui);
  cursor: pointer;
  text-align: left;
}

.novely-walk-chapter:hover {
  color: var(--text);
  text-decoration: underline;
}

.novely-walk-source,
.novely-walk-tag {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  letter-spacing: 0.03em;
  color: var(--muted-4);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 0 6px;
}

/* Whose note it is, in the colour the margin already uses for the author. */
.novely-walk-source-prose {
  color: var(--secondary);
  border-color: var(--border);
}

.novely-walk-note {
  margin: 0;
  font-size: var(--size-13);
  line-height: var(--leading-ui-prose);
  color: var(--text);
}

/*
 * The prose the note is about.
 *
 * Quiet and set back: the note is what is being read, and this is what it is
 * being read against. It is here rather than only in the manuscript because the
 * manuscript is showing the page, not the sentence.
 */
.novely-walk-context {
  margin: 0;
  padding-left: 10px;
  border-left: 2px solid var(--border);
  font-family: var(--font-prose);
  font-size: var(--size-11-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-2);
}

.novely-walk-empty {
  margin: 0;
  font-size: var(--size-11-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-3);
}

/* --- finishing with one -------------------------------------------------- */

/*
 * Set below the note and its context with a rule above them, because they are
 * pressed after reading both and because one of them deletes something. The
 * line underneath says which -- see `review/view.ts` -- and it is styled to be
 * read rather than skipped past, so it sits at the same size as the context
 * rather than shrinking into fine print.
 */
.novely-walk-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 10px;
  border-top: 1px solid var(--hairline);
}

.novely-walk-buttons {
  display: flex;
  gap: 6px;
}

.novely-walk-do {
  min-height: 26px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: transparent;
  color: var(--text);
  font: 400 var(--size-11-5) / 1 var(--font-ui);
  cursor: pointer;
}

.novely-walk-do:hover {
  border-color: var(--border-hover);
}

/* The one you press most, on a walk whose whole point is getting through. */
.novely-walk-done {
  border-color: transparent;
  background: var(--text);
  color: var(--page);
}

.novely-walk-consequence {
  margin: 0;
  font-size: var(--size-10-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-4);
}

/* --- what to walk -------------------------------------------------------- */

.novely-walk-picker {
  border-top: 1px solid var(--hairline);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.novely-walk-picker-label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-4);
}

.novely-walk-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.novely-walk-chip {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  letter-spacing: 0.03em;
  color: var(--muted-3);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 1px 7px;
  cursor: pointer;
}

.novely-walk-chip:hover {
  border-color: var(--border);
}

.novely-walk-chip.is-on {
  color: var(--text);
  border-color: var(--border-strong);
}

.novely-walk-about-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.novely-walk-about-label {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-4);
}

.novely-walk-about {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 3px 6px;
  background: transparent;
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--size-11);
}

.novely-walk-about:focus-visible {
  outline: none;
  border-color: var(--border-hover);
}

/* The bar's own control for it, on when the walk is. */
.novely-top-walk-on {
  color: var(--text);
}

/* --- on your phone ------------------------------------------------------- */

.novely-phone-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 0 2px;
}

.novely-phone-headline {
  margin: 0;
  font-size: var(--size-13);
  line-height: var(--leading-ui-prose);
  color: var(--text);
}

.novely-phone-heading {
  margin: 0;
  font-size: var(--size-11);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--secondary);
}

.novely-phone-note {
  margin: 0;
  font-size: var(--size-11-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-2);
}

/* The boundary of local-first, said out loud rather than found out. */
.novely-phone-caveat {
  margin: 0;
  font-size: var(--size-11);
  line-height: var(--leading-ui-prose);
  color: var(--muted-4);
}

.novely-phone-url-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

/*
 * The address, big enough to retype from across a desk.
 *
 * This is the one string in the application somebody reads off one screen and
 * types into another, so it is the one string that gets a size of its own.
 */
.novely-phone-url {
  font-family: var(--font-mono);
  font-size: var(--size-14);
  color: var(--text);
  background: var(--row-hover);
  border: 1px solid var(--hairline);
  border-radius: 3px;
  padding: 5px 9px;
  overflow-wrap: anywhere;
}

.novely-phone-copy {
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 3px 9px;
  background: transparent;
  color: var(--muted-2);
  font: 400 var(--size-11) / 1 var(--font-ui);
  cursor: pointer;
}

.novely-phone-copy:hover {
  border-color: var(--border-hover);
  color: var(--text);
}

.novely-phone-steps,
.novely-phone-better {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.novely-phone-better {
  border-top: 1px solid var(--hairline);
  padding-top: 12px;
}

/* A command that wraps is a command somebody retypes wrongly. */
.novely-phone-command {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--size-11);
  line-height: 1.6;
  color: var(--secondary);
  background: var(--row-hover);
  border: 1px solid var(--hairline);
  border-radius: 3px;
  padding: 8px 10px;
  overflow-x: auto;
  white-space: pre;
}

.novely-phone-block {
  display: block;
}

/* --- pairing ------------------------------------------------------------- */

.novely-phone-pairing {
  border-top: 1px solid var(--hairline);
  padding-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.novely-phone-token-label {
  font-family: var(--font-mono);
  font-size: var(--size-10);
  color: var(--muted-4);
}

/* Wraps, unlike an address: it is 43 characters and nobody reads it aloud. */
.novely-phone-token {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--size-11);
  color: var(--secondary);
  background: var(--row-hover);
  border: 1px solid var(--hairline);
  border-radius: 3px;
  padding: 4px 8px;
  overflow-wrap: anywhere;
}

/*
 * The screen a device sees when it is not let in.
 *
 * Its own thing rather than an overlay: there is no application behind it to
 * overlay, and a modal over a broken page would say the page was fine.
 */
.novely-pairing {
  max-width: 30rem;
  margin: 15vh auto 0;
  padding: 0 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-family: var(--font-ui);
  color: var(--text);
}

.novely-pairing-title {
  margin: 0;
  font-size: var(--size-16, 1.05rem);
  font-weight: 500;
}

.novely-pairing-detail {
  margin: 0;
  font-size: var(--size-11-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-2);
}

.novely-pairing-row {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.novely-pairing-field {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 8px 10px;
  background: transparent;
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--size-12);
}

.novely-pairing-field:focus-visible {
  outline: none;
  border-color: var(--border-hover);
}

.novely-pairing-go {
  border: 1px solid var(--text);
  border-radius: var(--r-primary);
  padding: 8px 16px;
  background: var(--text);
  color: var(--panel);
  font: 500 var(--size-11-5) / 1 var(--font-ui);
  cursor: pointer;
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Updates (§16.2)
   
   The plainest panel in the application, on purpose: a sentence, sometimes a
   button, sometimes a caveat. The decision behind it is binary and taken twice
   a year, and anything more would be a dashboard for a yes/no question.
   --------------------------------------------------------------------------- */

.novely-update-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 0 2px;
}

.novely-update-headline {
  margin: 0;
  font-size: var(--size-13);
  line-height: var(--leading-ui-prose);
  color: var(--text);
}

/* The release's own words. Quiet, and never invented when there are none. */
.novely-update-notes {
  margin: 0;
  font-size: var(--size-11-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-2);
  white-space: pre-wrap;
}

.novely-update-note {
  margin: 0;
  font-size: var(--size-11-5);
  line-height: var(--leading-ui-prose);
  color: var(--muted-2);
}

/*
 * Two copies of the application on one machine. Louder than the build line
 * below it, because it is the rarer and more consequential fact: everything
 * else on this panel is about *this* copy, and this is about the other one.
 */
.novely-update-other {
  margin: 0;
  font-size: var(--size-11-5);
  line-height: var(--leading-ui-prose);
  color: var(--kind-violated);
}

/*
 * Which interface this is. Mono, because it is an identifier and not a
 * sentence, and quiet, because it is only ever read when something looks
 * wrong -- which is exactly when it has to be there.
 */
.novely-update-build {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--size-10-5);
  color: var(--muted-4);
}

.novely-update-caveat {
  margin: 0;
  font-size: var(--size-11);
  line-height: var(--leading-ui-prose);
  color: var(--muted-4);
}

.novely-update-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Empty in every state but one, so it must not hold a gap open. */
.novely-update-actions:empty {
  display: none;
}

.novely-update-install,
.novely-update-check {
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 4px 11px;
  background: transparent;
  color: var(--muted-2);
  font: 400 var(--size-11) / 1 var(--font-ui);
  cursor: pointer;
}

/* The one action worth weight: it is the reason the panel was opened. */
.novely-update-install {
  color: var(--text);
  border-color: var(--border-hover);
}

.novely-update-install:hover,
.novely-update-check:hover {
  border-color: var(--border-hover);
  color: var(--text);
}
