/* ── Tabler icon font base sizing ─────────────────────────────────────────── */
.ti {
  font-size: 1rem;
  line-height: 1;
  vertical-align: middle;
}

/* ── Design tokens ───────────────────────────────────────────────────────────
   Consolidated from two :root blocks and extended with spacing, radius,
   shadow, and type-size scales. Grouped by category for discoverability. */

:root {
  /* ── Typography ─────────────────────────────────────────────────────── */
  --body-font: Georgia, "Times New Roman", serif;
  --code-font: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;

  --font-size-xs: 0.65rem;
  --font-size-sm: 0.7rem;
  --font-size-md: 0.8rem;
  --font-size-lg: 0.9rem;
  --font-size-xl: 1rem;
  --font-size-2xl: 1.5rem;
  --font-size-3xl: 2rem;
  --font-size-4xl: 3rem;

  /* ── Color: brand ───────────────────────────────────────────────────── */
  --body-bg: #fff;
  --body-color: #222;
  --link-color: #7a2e1f;
  --link-color-hover: #5a1f12;
  --muted-color: #666;
  --error-color: #b91c1c;
  --success-color: #15803d;

  /* ── Color: inputs ──────────────────────────────────────────────────── */
  --input-border: #d1d5db;
  --input-border-focus: #7a2e1f;
  --input-bg: #fff;

  /* ── Color: cards ───────────────────────────────────────────────────── */
  --card-border: #e5e7eb;
  --card-bg: #fff;

  /* ── Color: buttons ─────────────────────────────────────────────────── */
  --btn-primary-bg: #7a2e1f;
  --btn-primary-color: #fff;
  --btn-primary-hover-bg: #5a1f12;

  --btn-secondary-bg: #fff;
  --btn-secondary-color: #7a2e1f;
  --btn-secondary-border: #7a2e1f;
  --btn-secondary-hover-bg: #fdf5f4;

  /* ── Color: anchor (comment highlights in the editor) ───────────────── */
  --anchor-bg: #fffbcc;
  --anchor-bg-hover: #fff099;
  --anchor-outline: #b88a1a;

  /* ── Color: post-it ─────────────────────────────────────────────────── */
  --postit-bg: #fffbcc;
  --postit-border: #e8d84a;
  --postit-id-color: #888;
  --postit-archive-hover-color: #333;

  /* ── Color: page-nav ────────────────────────────────────────────────── */
  --page-nav-color: #888;
  --page-nav-hover-color: #333;
  --page-nav-disabled-color: #ccc;
  --mobile-margin-border: #ddd;

  /* ── Spacing (rem-based) ────────────────────────────────────────────── */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;

  /* ── Radius ─────────────────────────────────────────────────────────── */
  --radius: 4px;
  --radius-pill: 999px;

  /* ── Shadow ─────────────────────────────────────────────────────────── */
  --shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.15);
  --shadow-md: 0 3px 10px rgba(0, 0, 0, 0.22);
  --shadow-lg: 0 6px 20px rgba(0, 0, 0, 0.3);

  /* ── Post-it component aliases ──────────────────────────────────────── */
  --postit-shadow: var(--shadow-sm);

  /* ── Layout ─────────────────────────────────────────────────────────── */
  --margin-width: 30ch;
  --gap: var(--space-6);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: 18px;
  line-height: 1.6;
}

body {
  margin: 0;
  padding: var(--space-6) var(--space-4);
  font-family: var(--body-font);
  color: var(--body-color);
  background: var(--body-bg);
}

/* The editor page needs the header and toolbar to span the full viewport
   width, so we remove the default body padding and let those elements manage
   their own internal spacing. The .editor-layout grid restores the content
   column constraint. */
body.editor-body-page {
  padding: 0;
}

h1,
h2,
h3,
h4 {
  font-weight: normal;
  line-height: 1.25;
}

h1 {
  font-size: var(--font-size-3xl);
  margin-bottom: var(--space-1);
}

p {
  margin: 1em 0;
}

a:link,
a:visited {
  color: var(--link-color);
  text-decoration: underline;
}

a:hover,
a:focus {
  color: var(--link-color-hover);
}

code {
  font-family: var(--code-font);
  font-size: 0.88em;
}

/* Shared form input style. */
input[type="email"],
input[type="password"],
input[type="text"] {
  width: 100%;
  padding: var(--space-2) 0.65rem;
  border: 1px solid var(--input-border);
  border-radius: var(--radius);
  font-family: var(--body-font);
  font-size: var(--font-size-xl);
  background: var(--input-bg);
  color: var(--body-color);
  transition: border-color 0.15s;
}

input[type="email"]:focus,
input[type="password"]:focus,
input[type="text"]:focus {
  outline: none;
  border-color: var(--input-border-focus);
}

/* Base textarea style. Scoped textareas (post-it reply, import modal) ship
   their own rules and override these via specificity. */
textarea {
  width: 100%;
  padding: var(--space-2) 0.65rem;
  border: 1px solid var(--input-border);
  border-radius: var(--radius);
  font-family: var(--body-font);
  font-size: var(--font-size-xl);
  background: var(--input-bg);
  color: var(--body-color);
  transition: border-color 0.15s;
  box-sizing: border-box;
  resize: vertical;
}

textarea:focus {
  outline: none;
  border-color: var(--input-border-focus);
}

label {
  display: block;
  margin-bottom: 0.3rem;
  font-size: var(--font-size-lg);
  color: var(--muted-color);
}

/* Shared button base. Pair with .btn-primary or .btn-secondary. */
.btn {
  display: inline-block;
  padding: var(--space-2) 1.25rem;
  font-family: var(--body-font);
  font-size: var(--font-size-xl);
  line-height: 1.25;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.btn-primary {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border-color: var(--btn-primary-bg);
}

.btn-primary:link,
.btn-primary:visited {
  color: var(--btn-primary-color);
  text-decoration: none;
}

.btn-primary:hover,
.btn-primary:focus {
  background: var(--btn-primary-hover-bg);
  border-color: var(--btn-primary-hover-bg);
  color: var(--btn-primary-color);
  text-decoration: none;
}

.btn-secondary {
  background: var(--btn-secondary-bg);
  color: var(--btn-secondary-color);
  border-color: var(--btn-secondary-border);
}

.btn-secondary:link,
.btn-secondary:visited {
  color: var(--btn-secondary-color);
  text-decoration: none;
}

.btn-secondary:hover,
.btn-secondary:focus {
  background: var(--btn-secondary-hover-bg);
  color: var(--btn-secondary-color);
  text-decoration: none;
}

/* Centred single-column card used by auth pages. */
.auth-card {
  max-width: 400px;
  margin: 4rem auto;
  padding: var(--space-6);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  background: var(--card-bg);
}

/* Wider variant for the settings page: the critique-guidelines textarea
   needs room to breathe and the auth-card 400px cap leaves it cramped. */
.auth-card--wide {
  max-width: 720px;
}

.auth-card h1 {
  margin: 0 0 var(--space-5) 0;
  font-size: var(--font-size-2xl);
  text-align: center;
}

.form-row {
  margin-bottom: var(--space-4);
}

.form-actions {
  display: flex;
  justify-content: center;
  margin-top: 1.25rem;
}

.form-help {
  text-align: center;
  margin-top: var(--space-3);
  color: var(--muted-color);
  font-size: var(--font-size-lg);
}

.form-error {
  color: var(--error-color);
  margin-bottom: var(--space-3);
  text-align: center;
  font-size: var(--font-size-lg);
}

/* Button that looks like a plain text link, used where a <form> submit must
   visually match an <a> element (e.g. the logout link in set_anthropic_key). */
.btn-link {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--link-color);
  cursor: pointer;
  text-decoration: underline;
}

.btn-link:hover,
.btn-link:focus {
  color: var(--link-color-hover);
}

/* Brand logo image used in the editor toolbar, documents header, and settings
   page. height:100% fills the stretched toolbar button; width:auto preserves
   the SVG's aspect ratio without distortion. The cap keeps it from growing
   too large on pages where the containing element isn't constrained — sized
   so the L glyph reads as a real brand mark, not an incidental icon. */
.brand-logo {
  height: 100%;
  max-height: 40px;
  width: auto;
  display: block;
}

/* Home page centred layout. */
.home-container {
  max-width: 55ch;
  margin: 4rem auto;
  text-align: center;
}

.home-container h1 {
  font-size: var(--font-size-4xl);
  font-style: italic;
  margin-bottom: var(--space-2);
}

.home-actions {
  display: flex;
  gap: var(--space-4);
  justify-content: center;
  margin-top: var(--space-6);
}

/* Monospace value display (e.g. masked API key). */
.mono-value {
  font-family: var(--code-font);
  font-size: var(--font-size-md);
  color: var(--muted-color);
}

.key-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: var(--space-3);
  font-size: var(--font-size-lg);
  color: var(--muted-color);
}

/* Documents list page. */
.documents-page {
  margin: var(--space-3) auto var(--space-6);
  padding: 0 var(--space-4);
}

.documents-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-6);
}

/* Top-left logo link on the settings page, matching the documents-header
   left-edge position visually. */
.settings-home-link {
  padding: var(--space-3) var(--space-4);
}

.documents-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-xl);
}

.documents-table th {
  text-align: left;
  font-weight: normal;
  font-size: var(--font-size-lg);
  color: var(--muted-color);
  border-bottom: 1px solid var(--card-border);
  padding: 0.4rem 0.5rem;
}

.documents-table td {
  padding: 0.6rem 0.5rem;
  border-bottom: 1px solid var(--card-border);
  vertical-align: middle;
}

.document-title-cell {
  width: 55%;
}

/* Visibility pill (lock/globe) shown to the right of the document title. The
   pill shape and muted palette keep it from competing with the title. */
.document-visibility-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-left: var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--card-border);
  color: var(--muted-color);
  vertical-align: 1px;
}

/* Mode pill (OUTLINE) shown to the right of the document title.
   Same shape as the visibility pill but uses text instead of an icon. */
.document-mode-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: var(--space-2);
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  background: var(--card-border);
  color: var(--muted-color);
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  vertical-align: 1px;
  white-space: nowrap;
}

.document-updated-cell {
  width: 25%;
  color: var(--muted-color);
  font-size: var(--font-size-lg);
}

.document-actions-cell {
  width: 20%;
  text-align: right;
  white-space: nowrap;
}

/* Inline icon action buttons used inside table rows. */
.btn-inline,
.btn-inline:link,
.btn-inline:visited {
  background: none;
  border: none;
  padding: var(--space-1);
  color: var(--muted-color);
  cursor: pointer;
  margin-left: var(--space-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  line-height: 0;
}

.btn-inline:hover,
.btn-inline:focus {
  color: var(--link-color);
  background: var(--card-border);
}

.btn-inline--danger:hover,
.btn-inline--danger:focus {
  color: var(--error-color);
  background: var(--card-border);
}

.delete-form,
.duplicate-form {
  display: inline;
}

/* Rename form row — hidden by default, toggled via JS. */
.rename-form {
  display: none;
}

.rename-form--visible {
  display: table-row;
}

.rename-form-inner {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  padding: var(--space-2) 0;
}

.rename-form-inner input[type="text"] {
  flex: 1;
}

/* Empty state for the documents list. */
.documents-empty {
  text-align: center;
  margin-top: 4rem;
  color: var(--muted-color);
}

.documents-empty p {
  margin-bottom: var(--space-5);
}

.documents-empty-actions {
  display: flex;
  gap: var(--space-3);
  justify-content: center;
}

/* Header action buttons group — keeps New document and Import side by side. */
.documents-header-actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
}

/* ── New-document split-button (documents page header and empty-state) ──── */

.new-doc-split-group {
  display: inline-flex;
  align-items: stretch;
  position: relative;
  flex-shrink: 0;
}

/* Primary half — looks like .btn-primary but without a right border so the
   two halves read as one continuous block. */
.new-doc-primary-btn {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2) 1.25rem;
  font-family: var(--body-font);
  font-size: var(--font-size-xl);
  line-height: 1.25;
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border: 1px solid var(--btn-primary-bg);
  border-right: none;
  border-radius: var(--radius) 0 0 var(--radius);
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s;
}

.new-doc-primary-btn:link,
.new-doc-primary-btn:visited {
  color: var(--btn-primary-color);
  text-decoration: none;
}

.new-doc-primary-btn:hover,
.new-doc-primary-btn:focus {
  background: var(--btn-primary-hover-bg);
  color: var(--btn-primary-color);
  text-decoration: none;
}

/* Chevron half — smaller padding, subtle white left divider so the
   boundary between the two halves reads clearly. */
.new-doc-chevron-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-2) 0.5rem;
  font-family: var(--body-font);
  font-size: var(--font-size-xl);
  line-height: 1.25;
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border: 1px solid var(--btn-primary-bg);
  border-left: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 0 var(--radius) var(--radius) 0;
  cursor: pointer;
  transition: background 0.15s;
}

.new-doc-chevron-btn:hover,
.new-doc-chevron-btn:focus {
  background: var(--btn-primary-hover-bg);
  color: var(--btn-primary-color);
}

/* Dropdown menu — positioned below the chevron, hidden by default. */
.new-doc-menu {
  display: none;
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 4px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  z-index: 50;
  min-width: 150px;
  padding: 0.25rem 0;
}

.new-doc-menu.is-open {
  display: block;
}

.new-doc-menu-item {
  display: block;
  padding: 0.5rem 0.75rem;
  font-family: var(--body-font);
  font-size: var(--font-size-xl);
  color: var(--body-color);
  text-decoration: none;
  white-space: nowrap;
}

.new-doc-menu-item:link,
.new-doc-menu-item:visited {
  color: var(--body-color);
  text-decoration: none;
}

.new-doc-menu-item:hover,
.new-doc-menu-item:focus {
  background: var(--card-border);
  color: var(--body-color);
  text-decoration: none;
}

/* Editor toolbar — sticky bar above the ProseMirror area. nowrap + overflow-x
   keeps all buttons on one line; narrow viewports scroll horizontally rather
   than wrapping the last button onto a second row. Full-viewport-width with
   internal horizontal padding to align visually with the header. The
   border-bottom here (not on the header) creates a single shared underline
   for the unified header+toolbar band. */
.editor-toolbar {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: var(--space-1);
  padding: 0.4rem var(--space-3);
  border-bottom: 1px solid var(--card-border);
  position: sticky;
  top: 0;
  background: var(--body-bg);
  /* 11 = one above .postit.wide (10) so wide post-its in the margin column
     don't paint over the sticky toolbar when scrolled. .editor-header sits
     one higher (12) so its mobile hamburger dropdown still wins over us. */
  z-index: 11;
}

.toolbar-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.2rem 0.4rem;
  font-family: var(--body-font);
  font-size: var(--font-size-md);
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--body-color);
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
  flex-shrink: 0;
}

/* Override the global a:link/a:visited/a:hover/a:focus rules, which would
   otherwise paint anchor-flavoured toolbar buttons in link-red with an
   underline. All four pseudo-classes must be listed; omitting any one lets
   the global rule win on that state. */
.toolbar-btn:link,
.toolbar-btn:visited {
  color: var(--body-color);
  text-decoration: none;
}

.toolbar-btn:hover,
.toolbar-btn:focus-visible {
  background: var(--card-border);
  color: var(--body-color);
  text-decoration: none;
  outline: none;
}

.toolbar-btn.is-active {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border-color: var(--btn-primary-bg);
}

.toolbar-btn:disabled,
.toolbar-btn:disabled:hover,
.toolbar-btn:disabled:focus-visible {
  opacity: 0.35;
  cursor: not-allowed;
  background: transparent;
  color: var(--body-color);
  border-color: transparent;
}

.toolbar-separator {
  width: 1px;
  background: var(--card-border);
  margin: 0.1rem 0.2rem;
  align-self: stretch;
}

/* Editor title styled as a large heading. appearance/box-shadow resets strip
   the browser's native input chrome (inset shadow, rounded corners on Safari,
   etc.) that would otherwise show through despite border:none. The selector
   uses input.editor-title-input (specificity 0,1,1) to beat the shared
   input[type="text"] rule (also 0,1,1) by source order. */
input.editor-title-input {
  flex: 1;
  min-width: 0;
  appearance: none;
  -webkit-appearance: none;
  box-shadow: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 0.2rem 0;
  font-family: Georgia, "Times New Roman", serif;
  font-size: var(--font-size-3xl);
  font-weight: normal;
  color: var(--body-color);
  background: transparent;
  width: auto;
  transition: border-color 0.15s;
}

input.editor-title-input:hover {
  border-bottom-color: var(--card-border);
}

input.editor-title-input:focus {
  outline: none;
  border-bottom-color: var(--input-border-focus);
}

/* Dark-mode overrides. Defined even though there is no theme toggle yet —
   they are harmless and ready for luc-rulck. */

:root[data-theme="dark"] {
  --anchor-bg: #4a3a15;
  --anchor-bg-hover: #5c4a1a;
  --anchor-outline: #d4b056;
  --postit-bg: #4a3a15;
  --postit-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
  --postit-border: #7a6020;
  --postit-id-color: #8a8a8c;
  --postit-archive-hover-color: #c8c6c2;
  --page-nav-color: #8a8a8c;
  --page-nav-hover-color: #c8c6c2;
  --page-nav-disabled-color: #3a3a3c;
  --mobile-margin-border: #2c2c2e;
}

@media (min-width: 1100px) {
  :root {
    --main-width: 70ch;
    --margin-width: 40ch;
  }
}

/* ── Two-column editor layout ────────────────────────────────────────────────
   The editor page uses a two-column grid: the ProseMirror area on the left,
   the margin column (post-its) on the right. On narrow viewports the grid
   collapses to a single column and post-its stack below the editor. */

.editor-layout {
  display: grid;
  grid-template-columns: var(--main-width, 55ch) var(--margin-width);
  column-gap: var(--gap);
  max-width: calc(var(--main-width, 55ch) + var(--gap) + var(--margin-width));
  margin: 0 auto;
  padding: var(--space-6) var(--space-4);
}

@media (max-width: 700px) {
  .editor-layout {
    grid-template-columns: 1fr;
  }
}

/* Outline mode hides the margin column entirely (no post-its in outline
   mode), so collapse its grid track instead of leaving a ~40ch corridor of
   wasted space — that corridor pushes the layout past the viewport once
   the chat sidebar takes its share. */
body.outline-mode .editor-layout {
  grid-template-columns: var(--main-width, 55ch);
  max-width: var(--main-width, 55ch);
}

/* The outline-mode rule above wins over the generic .editor-layout mobile
   rule on specificity, so re-collapse to a single fluid track on narrow
   viewports — otherwise the fixed 55ch track overflows the viewport. */
@media (max-width: 700px) {
  body.outline-mode .editor-layout {
    grid-template-columns: 1fr;
    max-width: none;
  }
}

.editor-layout .editor-body {
  min-width: 0;
}

.margin-column {
  grid-column: 2;
  position: relative;
}

@media (max-width: 700px) {
  .margin-column {
    display: none;
  }
}

/* ── Anchor highlights ───────────────────────────────────────────────────────
   Ported from graphe. The mark renders as <mark class="anchor" data-comment-id="…">
   inside the Tiptap editor's contenteditable area. */

mark.anchor {
  background: var(--anchor-bg);
  color: inherit;
  border-radius: var(--radius);
  padding: 0 1px;
  cursor: default;
  /* Top/bottom lines via box-shadow rather than outline so adjacent marks
     with the same highlight merge into one continuous line. Box-shadow, like
     outline, does not affect layout. */
  box-shadow: 0 -1px 0 transparent, 0 1px 0 transparent;
  transition: background 0.15s, box-shadow 0.15s;
}

mark.anchor:hover {
  background: var(--anchor-bg-hover);
  box-shadow: 0 -1px 0 var(--anchor-outline), 0 1px 0 var(--anchor-outline);
}

/* ── Post-it notes ───────────────────────────────────────────────────────────
   Ported from graphe. Absolutely positioned within .margin-column on desktop;
   static on mobile. */

.postit {
  position: absolute;
  width: 100%;
  right: 0;
  background: var(--postit-bg);
  border: 1px solid var(--postit-border);
  box-shadow: var(--postit-shadow);
  border-radius: var(--radius);
  padding: 0.6rem var(--space-3);
  font-size: 0.82rem;
  line-height: 1.45;
  transform: rotate(-1.5deg);
  transform-origin: top left;
  transition: box-shadow 0.25s, background 0.25s, top 0.3s ease-out, width 0.25s, opacity 0.2s ease;
}

.postit:hover,
.postit.active {
  background: var(--anchor-bg-hover);
  box-shadow: var(--shadow-md);
}

/* Without a matching anchor mark in the editor, the post-it can't be
   positioned and would snap to top:0, pushing other post-its around.
   Fading it out and making it non-interactive prevents both visual
   noise and accidental interaction with dead comment threads. */
.postit.orphaned {
  opacity: 0;
  pointer-events: none;
}

@media (max-width: 700px) {
  .postit {
    position: static;
    width: auto;
    max-width: var(--main-width, 55ch);
    margin: var(--space-4) 0;
    transform: none;
  }
}

/* Wide state: triggered when a truncated reply is clicked or the reply
   textarea is focused. The post-it grows leftward into the prose column so
   the user can read without the margin-column width constraint. Higher z-index
   and stronger shadow sell the "lifted off the page" feel.
   right: 0 keeps the post-it anchored to its right edge (the margin column's
   left boundary) while left: auto lets the wider width extend leftward into
   the prose. The synchronous arrangePostits() call at toggle time gives
   approximately correct positions immediately; a transitionend listener
   corrects them once the animation finishes. */
@media (min-width: 701px) {
  .postit.wide {
    width: var(--main-width, 70ch);
    z-index: 10;
    box-shadow: var(--shadow-lg);
    /* The base rule rotates around top-left. When wide, the post-it grows
       leftward from right:0, so the pivot must be at the right edge to keep
       the right side anchored to the margin column boundary. */
    transform-origin: top right;
  }

  .postit.wide:hover,
  .postit.wide.active {
    box-shadow: var(--shadow-lg);
  }
}

/* When a post-it is expanded (whether narrow or wide), unclamp all reply
   bodies so the full thread is readable. The reply unclamp moved here from
   .postit.wide because .expanded is the class that tracks the focused/
   anchor-aligned state; .wide is now purely about width/z-index/shadow. */
.postit.expanded .postit-reply-body {
  display: block;
  -webkit-line-clamp: unset;
  max-height: none;
}

/* Clicking a truncated reply when the post-it is already expanded does
   nothing, so drop the pointer affordance. */
.postit.expanded .postit-reply-body.truncated {
  cursor: default;
}

/* Title bar (author label + controls). */
.postit-id {
  font-size: var(--font-size-sm);
  color: var(--postit-id-color);
  font-family: var(--code-font);
  margin-bottom: 0.3rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  user-select: none;
  gap: var(--space-1);
}

.postit-id-text {
  flex: 1;
}

/* Controls group (delete button) in the post-it header. */
.postit-controls {
  display: flex;
  align-items: center;
  gap: 0.1rem;
}

.postit-archive {
  background: none;
  border: none;
  padding: 0 0.2rem;
  cursor: pointer;
  color: var(--postit-id-color);
  line-height: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.postit-archive:hover {
  color: var(--postit-archive-hover-color);
}

.postit-body > :first-child {
  margin-top: 0;
}

.postit-body > :last-child {
  margin-bottom: 0;
}

/* Replies stacked below the root body. */
.postit-replies {
  margin-top: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.postit-reply {
  border-top: 1px solid var(--postit-border);
  padding-top: 0.4rem;
}

.postit-reply-author {
  font-size: var(--font-size-xs);
  color: var(--postit-id-color);
  font-family: var(--code-font);
  margin-right: 0.15rem;
}

.postit-reply-body > :first-child {
  margin-top: 0;
}

.postit-reply-body > :last-child {
  margin-bottom: 0;
}

/* Reply bodies are clamped to 2 lines at narrow width so long AI replies
   don't dominate the margin. JS measures overflow after DOM insertion and
   only adds cursor/role/tabindex/truncated-class when the text actually
   overflows. Unclamping is handled by the .postit.wide descendant rule above —
   the whole thread opens at once when the post-it widens.
   Using max-height instead of -webkit-line-clamp so that inline children
   (the "L: "/"U: " prefix and the first paragraph of body text) flow
   together on the same line. */
.postit-reply-body {
  overflow: hidden;
  display: block;
  max-height: 2.9em; /* 2 lines × 1.45 line-height */
}

/* Pointer cursor only on truncated replies when the post-it is narrow.
   The wide override lives in the @media (min-width: 701px) block with the
   other .postit.wide rules. */
.postit-reply-body.truncated {
  cursor: pointer;
}

/* Reply form. Hidden when the post-it is contracted (no .expanded). */
.postit-reply-form {
  margin-top: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.postit:not(.expanded) .postit-reply-form {
  display: none;
}

.postit-reply-form textarea {
  width: 100%;
  padding: 0.3rem 0.4rem;
  font-family: var(--body-font);
  font-size: var(--font-size-md);
  border: 1px solid var(--postit-border);
  border-radius: var(--radius);
  background: var(--body-bg);
  color: var(--body-color);
  resize: none;
  overflow: hidden;
}

.postit-reply-form textarea:focus {
  outline: none;
  border-color: var(--input-border-focus);
}

.postit-reply-submit {
  align-self: flex-end;
  padding: 0.2rem 0.6rem;
  font-family: var(--body-font);
  font-size: 0.75rem;
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
}

.postit-reply-submit:hover {
  background: var(--btn-primary-hover-bg);
}

/* ── Page navigation (▲/▼) ───────────────────────────────────────────────────
   Fixed pair at the bottom-right of the viewport. Hidden when no post-its. */

.page-nav {
  position: fixed;
  bottom: var(--space-5);
  right: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  z-index: 20;
}

.page-nav.empty {
  display: none;
}

.page-nav button {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-size: 1.1rem;
  color: var(--page-nav-color);
  line-height: 1;
  font-family: var(--body-font);
}

.page-nav button:hover {
  color: var(--page-nav-hover-color);
}

.page-nav button[disabled] {
  color: var(--page-nav-disabled-color);
  cursor: default;
  pointer-events: none;
}

/* ── Mobile post-it overlay ─────────────────────────────────────────────────
   On narrow viewports the margin column is hidden; tapping an anchor mark
   opens the thread in a full-screen <dialog>. The actual .postit DOM node is
   moved into the dialog so reply forms and event listeners keep working. */

#postit-overlay {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  overflow: auto;
}

#postit-overlay::backdrop {
  background: rgba(0, 0, 0, 0.5);
}

#postit-overlay .postit-overlay-close {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  background: rgba(0, 0, 0, 0.55);
  border: none;
  border-radius: 50%;
  font-size: 1.5rem;
  cursor: pointer;
  z-index: 10;
  color: #fff;
  width: 3rem;
  height: 3rem;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

#postit-overlay .postit {
  width: 100%;
  max-width: min(100%, 32rem);
  margin: 4rem auto 1rem auto;
  transform: none;
  border-radius: var(--radius);
}

/* Inside the overlay the post-it is always expanded, so unclamp all reply
   bodies so the full thread is readable. */
#postit-overlay .postit .postit-reply-body {
  display: block;
  -webkit-line-clamp: unset;
  max-height: none;
}

#postit-overlay .postit .postit-reply-body.truncated {
  cursor: default;
}

/* The reply form is hidden by default on collapsed post-its (the
   .postit:not(.expanded) rule above). Inside the overlay the thread is
   always considered open, so always show the reply box. */
#postit-overlay .postit .postit-reply-form {
  display: flex;
}

@media (min-width: 701px) {
  #postit-overlay {
    display: none;
  }
}

/* ── Mobile comment affordance ────────────────────────────────────────────────
   Floating button that appears when the text cursor is inside a comment mark
   on a narrow viewport. Tapping it opens the full-screen thread overlay. */

.comment-affordance {
  position: fixed;
  bottom: calc(var(--space-5) + 3.5rem);
  right: var(--space-5);
  z-index: 30;
  display: none;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border: none;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-md);
}

.comment-affordance.visible {
  display: flex;
}

@media (min-width: 701px) {
  .comment-affordance {
    display: none !important;
  }
}

.editor-header {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  padding: 0.5rem 0.75rem;
  gap: 1rem;
  background: var(--body-bg);
  /* Without an explicit stacking context, absolutely-positioned post-its
     in the margin column paint on top of the header (positioned-over-static
     paint order). Relative + z-index puts the header above them where the
     layouts overlap. 12 = one above .editor-toolbar (11) so the mobile
     hamburger dropdown — which lives inside the header's stacking context —
     paints above the sticky formatting toolbar below. The toolbar in turn
     sits above .postit.wide (10). */
  position: relative;
  z-index: 12;
}

.editor-header-left {
  display: flex;
  align-items: stretch;
  gap: 0.75rem;
  flex: 1;
  min-width: 0;
}

.editor-actions {
  display: flex;
  align-items: stretch;
  gap: 0.25rem;
  white-space: nowrap;
  position: relative;
}

.editor-menu {
  display: flex;
  align-items: stretch;
  gap: 0.25rem;
  white-space: nowrap;
}

.editor-menu-btn {
  display: none;
}

/* The Tabler icon font shipped with the project is a hand-curated subset and
   does not include a hamburger glyph. We use the Unicode trigram U+2630 (☰)
   as text instead; bump the size so it visually matches the 1rem icon font
   icons, which render heavier than the unicode glyph at the same size. */
.editor-menu-icon {
  font-size: 1.25rem;
  line-height: 1;
}

.editor-menu-label {
  display: none;
}

@media (max-width: 700px) {
  .editor-menu-btn {
    display: inline-flex;
  }

  .editor-menu {
    display: none;
  }

  .editor-menu.is-open {
    display: flex;
    flex-direction: column;
    position: absolute;
    right: 0.75rem;
    top: 100%;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
    z-index: 50;
    min-width: 200px;
    padding: 0.25rem 0;
    gap: 0;
    white-space: normal;
  }

  .editor-menu.is-open > .toolbar-btn {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    border-radius: 0;
    border: none;
    padding: 0.5rem 0.75rem;
    min-height: 44px;
    justify-content: flex-start;
    font-size: var(--font-size-xl);
    align-self: auto;
  }

  .editor-menu.is-open > a.toolbar-btn {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    border-radius: 0;
    border: none;
    padding: 0.5rem 0.75rem;
    min-height: 44px;
    justify-content: flex-start;
    font-size: var(--font-size-xl);
    align-self: auto;
    text-decoration: none;
    color: var(--body-color);
  }

  .editor-menu.is-open > a.toolbar-btn:hover {
    background: var(--card-border);
  }

  .editor-menu.is-open .editor-menu-label {
    display: inline;
  }

  .editor-menu.is-open .toolbar-separator {
    width: 100%;
    height: 0;
    border-top: 1px solid var(--card-border);
    margin: 0;
    align-self: auto;
  }

  .editor-menu.is-open .editor-auth-form {
    display: block;
    align-self: auto;
  }

  .editor-menu.is-open .editor-auth-form .toolbar-btn {
    width: 100%;
    justify-content: flex-start;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    min-height: 44px;
    border-radius: 0;
    border: none;
    font-size: var(--font-size-xl);
  }
}

/* Stretch the back/import/export buttons to match the tall title input.
   Without this, the icons sit centred in a small box and waste the vertical
   space the title's 2rem font-size already claims. */
.editor-header .toolbar-btn {
  align-self: stretch;
}

.editor-auth-form {
  display: flex;
  align-self: stretch;
  margin: 0;
}

/* The login icon is shown to all anonymous visitors on the editor
   (landing and public read-only). Filled red (matching the Critique button)
   so it reads as the page's primary call-to-action. The :link/:visited
   overrides are needed because .toolbar-btn:link already resets anchor
   colour to body-color. */
.toolbar-btn--login,
.toolbar-btn--login:link,
.toolbar-btn--login:visited {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border-color: var(--btn-primary-bg);
}

.toolbar-btn--login:hover,
.toolbar-btn--login:focus {
  background: var(--btn-primary-hover-bg);
  color: var(--btn-primary-color);
  border-color: var(--btn-primary-hover-bg);
}

/* Small colored dot indicating save state. Hidden until there is something
   to show (no lastSavedAt and no failure = invisible). */
.save-dot {
  display: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--success-color);
  flex-shrink: 0;
  margin-right: 0.25rem;
  /* Override the toolbar's align-items: stretch so the 8px dot doesn't
     stretch to the full header height and pin to the top. */
  align-self: center;
  opacity: 1;
  transition: opacity 1s ease;
}

.save-dot.is-visible {
  display: inline-block;
}

/* Applied 5s after a successful save so the green confirmation doesn't
   linger in the toolbar forever. Cleared on any new save activity. */
.save-dot.is-fading {
  opacity: 0;
}

.save-dot.is-failed {
  background: var(--error-color);
  cursor: pointer;
}

/* The ProseMirror contenteditable area. */
.editor-body .ProseMirror {
  min-height: 60vh;
  outline: none;
  font-family: var(--body-font);
  font-size: 1rem;
  line-height: 1.7;
  color: var(--body-color);
}

.editor-body .ProseMirror p {
  margin: 0.75em 0;
}

.editor-body .ProseMirror h1,
.editor-body .ProseMirror h2,
.editor-body .ProseMirror h3 {
  font-weight: normal;
  line-height: 1.25;
  margin: 1.5em 0 0.5em;
}

.editor-body .ProseMirror code {
  font-family: var(--code-font);
  font-size: 0.88em;
  background: #f5f5f5;
  padding: 0.1em 0.3em;
  border-radius: 2px;
}

.editor-body .ProseMirror pre {
  background: #f5f5f5;
  padding: 1em;
  border-radius: 3px;
  overflow-x: auto;
}

.editor-body .ProseMirror pre code {
  background: none;
  padding: 0;
}

.editor-body .ProseMirror blockquote {
  border-left: 3px solid var(--card-border);
  margin: 1em 0;
  padding-left: 1em;
  color: var(--muted-color);
}

.editor-body .ProseMirror ul,
.editor-body .ProseMirror ol {
  padding-left: 1.5em;
}

.editor-body .ProseMirror a {
  color: var(--link-color);
}

/* ── Critique split-button ──────────────────────────────────────────────── */

.critique-split-group {
  display: inline-flex;
  align-items: stretch;
  position: relative;
  flex-shrink: 0;
}

/* Both halves of the split-button are painted in the primary red so
   Critique reads as the page's main call-to-action — same look as the
   selected toolbar buttons (.toolbar-btn.is-active), just permanent.
   Hover styles are overridden here so they win against the generic
   .toolbar-btn:hover rule in main.css (equal specificity, later wins). */
.critique-primary-btn,
.critique-chevron-btn {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border-color: var(--btn-primary-bg);
}

.critique-primary-btn:hover,
.critique-primary-btn:focus,
.critique-chevron-btn:hover,
.critique-chevron-btn:focus {
  background: var(--btn-primary-hover-bg);
  color: var(--btn-primary-color);
  border-color: var(--btn-primary-hover-bg);
}

.critique-primary-btn {
  border-right: none;
  border-radius: 3px 0 0 3px;
  padding-right: 0.35rem;
}

/* Faint white divider between the two halves; the previous card-border
   line disappeared once both halves went red. */
.critique-chevron-btn {
  border-left: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 0 3px 3px 0;
  padding: 0.2rem 0.3rem;
}

/* Popover anchored below the split-button group. position: fixed (rather
   than absolute) so it isn't clipped by the toolbar's overflow-x: auto;
   coordinates are computed in JS from the chevron's bounding rect. */
.critique-popover {
  position: fixed;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 4px;
  padding: 0.75rem 1rem;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  z-index: 50;
  min-width: 200px;
  white-space: nowrap;
}

.critique-popover.hidden {
  display: none;
}

.critique-slider-label {
  display: block;
  font-size: 0.8rem;
  color: var(--muted-color);
  margin-bottom: 0.4rem;
  font-family: var(--body-font);
}

.critique-slider {
  width: 100%;
  cursor: pointer;
  accent-color: var(--btn-primary-bg);
}

.critique-ticks {
  display: flex;
  justify-content: space-between;
  margin-top: 0.2rem;
}

.critique-tick {
  font-size: 0.7rem;
  color: var(--muted-color);
  font-family: var(--code-font);
  cursor: default;
}

.critique-tick-label {
  font-size: 0.78rem;
  color: var(--body-color);
  margin-top: 0.35rem;
  font-family: var(--body-font);
  text-align: center;
}

.critique-popover-row {
  margin-top: 0.6rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--card-border);
}

.critique-popover-row.hidden {
  display: none;
}

.critique-popover-action {
  background: none;
  border: none;
  padding: 0;
  font-size: 0.82rem;
  color: var(--link-color);
  cursor: pointer;
  font-family: var(--body-font);
  text-align: left;
  width: 100%;
}

.critique-popover-action:hover {
  text-decoration: underline;
}

.critique-popover-danger-button {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 3px;
  padding: 0.3rem 0.5rem;
  font-size: 0.82rem;
  color: var(--body-color);
  cursor: pointer;
  font-family: var(--body-font);
  text-align: left;
  width: 100%;
}

.critique-popover-danger-button:hover {
  background: var(--card-border);
}

.critique-popover-danger-button.is-confirming {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border-color: var(--btn-primary-bg);
}

.critique-popover-danger-button.is-confirming:hover {
  background: var(--btn-primary-hover-bg);
  color: var(--btn-primary-color);
}

/* ── Critique overlay (full-screen "Thinking…" modal) ───────────────────── */

.critique-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
}

.critique-overlay-box {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 6px;
  padding: 2rem 2.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
}

.critique-overlay-message {
  margin: 0;
  font-size: 1rem;
  color: var(--body-color);
}

.critique-overlay-message-secondary {
  margin: 0;
  font-size: 0.85rem;
  color: var(--body-muted, #6b7280);
  font-style: italic;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 30ch;
}

/* Simple CSS spinner. */
.critique-spinner {
  width: 28px;
  height: 28px;
  border: 3px solid var(--card-border);
  border-top-color: var(--btn-primary-bg);
  border-radius: 50%;
  animation: critique-spin 0.8s linear infinite;
}

@keyframes critique-spin {
  to { transform: rotate(360deg); }
}

/* ── Stale-edit banner ───────────────────────────────────────────────────── */

.stale-banner {
  background: #fef3c7;
  border-bottom: 1px solid #f59e0b;
  color: #78350f;
  padding: 0.6rem 1rem;
  font-size: 0.9rem;
  font-family: var(--body-font);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  position: sticky;
  top: 0;
  z-index: 100;
}

.stale-banner .btn {
  font-size: 0.85rem;
  padding: 0.3rem 0.9rem;
}

/* ── Critique error banner ───────────────────────────────────────────────── */

.critique-error-banner {
  background: #fef2f2;
  border: 1px solid #fca5a5;
  color: var(--error-color);
  padding: 0.5rem 2.5rem 0.5rem 0.75rem;
  font-size: 0.9rem;
  position: relative;
  font-family: var(--body-font);
}

.critique-error-close {
  position: absolute;
  right: 0.5rem;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  font-size: 1.1rem;
  color: var(--error-color);
  line-height: 1;
  padding: 0 0.2rem;
}

/* ── Critique toast ──────────────────────────────────────────────────────── */

.critique-toast {
  position: fixed;
  bottom: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  background: var(--body-color);
  color: var(--body-bg);
  padding: 0.5rem 1.25rem;
  border-radius: 4px;
  font-size: 0.88rem;
  font-family: var(--body-font);
  z-index: 300;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
  pointer-events: none;
}

/* Import modal overlay. */
.import-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

.import-modal-overlay.hidden {
  display: none;
}

.import-modal {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 4px;
  padding: 2rem;
  max-width: 520px;
  width: 90%;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

.import-modal h2 {
  margin: 0 0 0.75rem;
  font-size: 1.2rem;
}

.import-modal p {
  margin: 0 0 1rem;
  font-size: 0.9rem;
  color: var(--muted-color);
}

.import-modal textarea {
  width: 100%;
  height: 200px;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--input-border);
  border-radius: 3px;
  font-family: var(--code-font);
  font-size: 0.85rem;
  resize: vertical;
  margin-bottom: 1rem;
  background: var(--input-bg);
  color: var(--body-color);
}

.import-modal textarea:focus {
  outline: none;
  border-color: var(--input-border-focus);
}

.import-modal-actions {
  display: flex;
  gap: 0.75rem;
  justify-content: flex-end;
}

/* Row that holds the "Choose file…" button and the drag-drop hint. */
.import-file-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
  font-size: 0.88rem;
  color: var(--muted-color);
}

/* Highlighted when a file is dragged over the overlay. */
.import-modal-overlay.is-dragover .import-modal {
  border: 2px dashed var(--btn-primary-bg);
  background: var(--input-bg);
}

/* Inline error shown inside the modal for validation failures. */
.import-modal-error {
  color: var(--error-color);
  font-size: 0.88rem;
  margin-bottom: 0.75rem;
  min-height: 1.2em;
}

.import-modal-error:empty {
  display: none;
}

/* ── Revision scrubber ─────────────────────────────────────────────────── */

.revision-scrubber {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--card-bg);
  border-top: 1px solid var(--card-border);
  padding: 1rem 1.25rem;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  overflow: visible;
}

.revision-scrubber.hidden {
  display: none;
}

.revision-scrubber-track {
  position: relative;
  flex: 1;
  height: 48px;
  overflow: visible;
}

/* Thin horizontal baseline. */
.revision-scrubber-track::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--card-border);
  transform: translateY(-50%);
}

/* Vertical lines at each revision timestamp. */
.revision-mark {
  position: absolute;
  top: 50%;
  width: 2px;
  height: 14px;
  background: var(--muted-color);
  transform: translate(-50%, -50%);
  cursor: pointer;
}

/* Widened invisible hit area so hover/click targets are easier to grab.
   The visual line stays 2px; this ::after spans more px centered on it. */
.revision-mark::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 100%;
  transform: translate(-50%, -50%);
}

.revision-mark:hover {
  background: var(--body-color);
}

.revision-mark.selected {
  background: var(--btn-primary-bg);
}

.revision-mark-now {
  background: var(--error-color);
}

/* Draggable circular handle. Positioned by JS via left style. */
.revision-scrubber-handle {
  position: absolute;
  top: 50%;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--btn-primary-bg);
  transform: translate(-50%, -50%);
  cursor: grab;
  z-index: 2;
}

.revision-scrubber-handle:active {
  cursor: grabbing;
}

/* Tooltip used both during drag and on mark hover. JS sets `left` in
   pixels to the tooltip's clamped left edge, so no translateX shift here. */
.revision-handle-tooltip {
  position: absolute;
  bottom: calc(50% + 13px);
  left: 0;
  white-space: pre-line;
  max-width: 300px;
  font-size: 0.75rem;
  color: var(--body-color);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  padding: 0.2rem 0.4rem;
  border-radius: 3px;
  pointer-events: none;
  opacity: 0;
  z-index: 3;
  transition: opacity 0.1s ease;
}

.revision-handle-tooltip.visible {
  opacity: 1;
}

/* ── Editor page wrapper ──────────────────────────────────────────────────────
   Wraps .editor-layout and .outline-sidebar in a flex row so the sidebar
   participates in layout instead of being pinned to the viewport edge with
   position:fixed. The editor centres in the leftover space via margin:auto.
   On narrow viewports the row collapses to a column so the sidebar stacks
   below the editor. */
.editor-page {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
}

@media (max-width: 700px) {
  .editor-page {
    flex-direction: column;
    /* Override the desktop align-items: flex-start so children stretch to
       fill the viewport width. Without this, .editor-layout's max-width
       (~85ch) becomes its actual width on narrow phones, overflowing the
       body. */
    align-items: stretch;
  }
}

/* ── Outline chat sidebar ──────────────────────────────────────────────────── */

/* Sticky within the flex row so the chat stays visible while the document
   scrolls. top:2.5rem clears the sticky toolbar. The height subtracts the
   full unscrolled header+toolbar band so the sidebar doesn't force extra
   scroll or clip the chat input at scrollTop:0. 6.5rem is sized to the
   actual rendered band: .editor-header is ~3.93rem (padding 1rem + 2rem
   title input with its line-height and 2px border) and .editor-toolbar is
   ~2.52rem (padding 0.8rem + 0.8rem buttons with line-height and 1px
   border) — together ≈6.45rem, plus a small safety margin. Visually
   identical to the old 5.5rem at scrollTop:0; the old value forced ~15px
   of permanent vertical overflow because it under-reserved the band. The
   visual rule that separates the editor body from the sidebar is NOT this
   element's border-left — see .outline-rule below — because that rule
   needs to keep reaching the viewport bottom even when the header scrolls
   out and the sidebar bottom rises with it. */
.outline-sidebar {
  position: sticky;
  top: 2.5rem;
  height: calc(100vh - 6.5rem);
  width: min(32rem, 40vw);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  background: var(--body-bg);
  padding: var(--space-3);
  min-height: 0;
  z-index: 5;
}

/* The vertical rule separating the editor body from the outline sidebar.
   Decoupled from .outline-sidebar so it can reach the viewport bottom on
   tall documents without forcing the sidebar (and its chat input) to grow
   on scroll — which would cause jank. Mechanics:
     - align-self: stretch makes the rule as tall as the .editor-page flex
       row, which equals the tallest sibling (usually .editor-layout).
     - max-height caps it at one viewport minus the toolbar so it never
       extends past the visible area when the document is tall.
     - position: sticky with top:2.5rem keeps it pinned just below the
       sticky toolbar once the page scrolls past it.
   For short documents the row is short, the rule stretches with it, and no
   sticking is needed — bottom of rule sits next to bottom of sidebar, no
   gap, no extra page scroll. For tall documents the rule sticks and always
   reaches the viewport bottom, even after the header has scrolled away.
   Only displayed in outline mode (where the right column exists). */
.outline-rule {
  display: none;
  flex-shrink: 0;
  width: 1px;
  background: var(--card-border);
  position: sticky;
  top: 2.5rem;
  align-self: stretch;
  max-height: calc(100vh - 2.5rem);
}

body.outline-mode .outline-rule {
  display: block;
}

@media (max-width: 700px) {
  /* On narrow viewports the sidebar stacks below the editor with a
     border-top instead of a left rule, so this element has no role. */
  body.outline-mode .outline-rule {
    display: none;
  }
}

@media (max-width: 700px) {
  .outline-sidebar {
    position: static;
    height: auto;
    width: auto;
    border-left: none;
    border-top: 1px solid var(--card-border);
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    max-height: 50vh;
  }
}

/* "Start drafting" button on the editor toolbar (replaces the critique
   button in outline mode). Painted in the primary red so it reads as the
   page's main call-to-action — same look as .critique-primary-btn but
   with a full border-radius since it isn't a split-button. */
.outline-promote-toolbar-btn {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  border-color: var(--btn-primary-bg);
  flex-shrink: 0;
}

.outline-promote-toolbar-btn:hover,
.outline-promote-toolbar-btn:focus {
  background: var(--btn-primary-hover-bg);
  color: var(--btn-primary-color);
  border-color: var(--btn-primary-hover-bg);
}

.outline-chat-messages {
  flex: 1;
  /* Without min-height: 0, the default min-height: auto on flex items keeps
     the messages list at its content height, which prevents the textarea's
     vertical resize handle from doing anything (no room to grow into). */
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.outline-chat-message {
  padding: var(--space-2);
  border-radius: var(--radius);
  font-size: 0.85rem;
  line-height: 1.45;
  max-width: 90%;
  white-space: pre-wrap;
  word-break: break-word;
}

.outline-chat-message--user {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-color);
  align-self: flex-end;
}

.outline-chat-message--assistant {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  align-self: flex-start;
}

.outline-chat-input-area {
  border-top: 1px solid var(--card-border);
  padding-top: var(--space-2);
}

.outline-chat-input-area textarea {
  width: 100%;
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  padding: var(--space-2);
  font-size: 0.85rem;
  font-family: var(--body-font);
  resize: vertical;
  background: var(--input-bg);
  color: var(--body-color);
}

.outline-chat-input-area textarea:focus {
  outline: none;
  border-color: var(--input-border-focus);
}

.outline-chat-error {
  color: var(--error-color);
  font-size: 0.8rem;
  margin-top: var(--space-1);
  min-height: 1.2em;
}

.outline-chat-input-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

/* Spinner for chat loading state */
.outline-spinner {
  display: inline-block;
  width: 1em;
  height: 1em;
  border: 2px solid var(--card-border);
  border-top-color: var(--btn-primary-bg);
  border-radius: 50%;
  animation: outline-spin 0.6s linear infinite;
  vertical-align: middle;
  flex-shrink: 0;
}

@keyframes outline-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ── Marketing pages ────────────────────────────────────────────────────────
   Centered reading column for /about/, /why-lucid/, etc.
   Max-width ~640px (≈35.5ch at 18px) keeps line length comfortable.
   Line-height 1.8 is generous without feeling loose.
   Body already supplies font-family, color, and horizontal padding, so we
   only add the column constraint and breathing room. */
.marketing-page {
  max-width: 640px;
  margin: 0 auto;
  line-height: 1.8;
}

/* Small logo link at the top of each marketing page. */
.marketing-wordmark {
  display: block;
  text-decoration: none;
  margin-bottom: var(--space-6);
}

.marketing-wordmark:hover {
  opacity: 0.85;
}

/* .brand-logo defaults to height: 100% with max-height: 40px, built for
   fixed-height toolbar parents. On a marketing page there's no fixed-height
   parent, so height: 100% collapses. Set an explicit height so the logo
   renders at the same size as in the rest of the app. */
.marketing-wordmark .brand-logo {
  height: 40px;
  max-height: none;
}

/* ── Landing-page marketing link strip (footer) ────────────────────────────
   Single discreet line of links below the editor on /. Visible only in
   landing mode (anonymous visitor on the landingpage doc). */
.landing-marketing-links {
  text-align: center;
  font-size: var(--font-size-sm);
  color: var(--muted-color);
  padding: var(--space-4) 0;
}

.landing-marketing-links a,
.landing-marketing-links a:link,
.landing-marketing-links a:visited {
  color: var(--muted-color);
}

.landing-marketing-links a:hover,
.landing-marketing-links a:focus {
  color: var(--link-color-hover);
}

/* ── No-JS banner ─────────────────────────────────────────────────────────
   Shown only when JavaScript is disabled. The server-rendered doc HTML
   inside #editor-mount remains readable; this banner tells the user why
   they can't edit or comment. */
.noscript-banner {
  padding: var(--space-3) var(--space-4);
  margin: var(--space-3) auto;
  max-width: 720px;
  background: var(--muted-bg-color, #fff8e1);
  border: 1px solid var(--muted-color);
  border-radius: 4px;
  font-size: var(--font-size-sm);
  text-align: center;
}
