/* Atlas — view-specific styles: login, list pages, chat, notes, documents,
   responsive rules. Base lives in app.css; Fred's editor — including the
   rich-text surface that replaced EasyMDE — is in fred.css. */

/* --- Login -------------------------------------------------------------- */

.login-wrap { display: flex; justify-content: center; padding-top: 9vh; }
.login-card { width: 100%; max-width: 400px; padding: 36px 36px 32px; text-align: center; }
.login-brand { font-family: var(--font-display); color: var(--accent-strong); font-size: 34px; margin: 0 0 22px; font-weight: 500; }
.login-form { text-align: left; }
/* The link to the client's own app (board task 48). Quiet on purpose: it is a
   signpost for whoever is switching hats, not a call to action. */
.login-other-door { margin: 20px 0 0; font-size: 13px; }
.login-other-door a { color: var(--text-soft); }

/* --- List pages (sessions, documents) ------------------------------------- */

.panel { padding: 20px 22px; }
.item-list { display: flex; flex-direction: column; gap: 8px; }

.item-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

a.item-card:hover { border-color: var(--accent); box-shadow: 0 2px 8px rgba(73, 105, 92, 0.1); }
.item-main { display: flex; flex-direction: column; min-width: 0; }
.item-title { font-weight: 600; font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.item-sub { color: var(--text-soft); font-size: 12.5px; }
.item-badges { display: flex; align-items: center; gap: 6px; flex: none; }

/* --- Drawer shell (js/drawer.js: Fred's history, the documents preview) ------- */

.drawer-scrim {
  position: fixed;
  inset: 0;
  background: rgba(48, 42, 34, 0.45);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.22s ease, visibility 0.22s;
  z-index: 50; /* below modals (60), above everything else */
}

.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 520px;
  max-width: 90vw;
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: -14px 0 44px rgba(0, 0, 0, 0.16);
  transform: translateX(102%);
  visibility: hidden;
  transition: transform 0.25s ease, visibility 0.25s;
  z-index: 55;
  display: flex;
  flex-direction: column;
}

.drawer-open .drawer-scrim { opacity: 1; visibility: visible; }
.drawer-open .drawer { transform: none; visibility: visible; }

.drawer-head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 14px 12px 22px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}

.drawer-title {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.drawer-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 14px 22px 18px;
}

.drawer-body .history-list { flex: 1; min-height: 0; max-height: none; }

/* --- Editor chrome (shared with fred.css) ---------------------------------- */

.tab-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}

.tabs { display: flex; gap: 4px; flex: 1; }

.tab {
  border: 1px solid transparent;
  background: transparent;
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-soft);
  padding: 6px 14px;
  border-radius: 999px;
  cursor: pointer;
}

.tab:hover { color: var(--text); }
.tab.active { background: var(--surface); color: var(--accent-strong); border-color: var(--border-strong); }

/* A tab that is on screen and cannot be used RIGHT NOW (board task 86): the
   Russian view before its translation has arrived, or after one failed. That is
   state, and state is drawn as disabled — a control that vanished when a
   network call failed would read as a feature being withdrawn. Permissions are
   the other question and are drawn by not building the tab at all (board task
   49). Kept faint but legible rather than invisible: `opacity` alone still
   answers `is_visible()` true, so the harness asserts on `disabled`. */
.tab:disabled { opacity: 0.45; cursor: not-allowed; }
.tab:disabled:hover { color: var(--text-soft); }

.locked-notice {
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  color: var(--warn-text);
  font-size: 13.5px;
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  margin-bottom: 12px;
}

/* --- History (rendered inside the drawer, shell above) ----------------------- */

.history-list { display: flex; flex-direction: column; gap: 6px; margin: 12px 0; max-height: 46vh; overflow-y: auto; }

.history-item {
  display: flex;
  flex-direction: column;
  gap: 3px;
  text-align: left;
  width: 100%;
  border: 1px solid var(--border);
  background: #fff;
  border-radius: var(--radius-sm);
  padding: 8px 11px;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.history-item:hover { border-color: var(--accent); }
.history-item.selected { border-color: var(--accent); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }

.history-top { display: flex; gap: 8px; align-items: baseline; min-width: 0; }

.sha {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--surface-2);
  border-radius: 5px;
  padding: 1px 6px;
  flex: none;
}

.history-item.selected .sha { background: #fff; }
.history-msg { font-size: 13px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.history-meta { color: var(--text-soft); font-size: 12px; }
.history-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* The end of a paged list (board task 84): either the way to older commits or
   the sentence saying there are none. Inside `.history-list` so it scrolls with
   the rows; `flex: none` so it keeps its height when the rows fill the box. */
.history-older { flex: none; align-self: center; margin-top: 2px; }
.history-beginning { flex: none; text-align: center; margin: 6px 0 2px; }

/* --- Saved versions of the whole of Fred (board task 18) --------------------- */

/* The same rows as the history list, with the number where the sha goes: a
   version is chosen by "v3, two days ago", and the commit is identity rather
   than the thing being read. */
.version-save-row { display: flex; margin: 10px 0 2px; }
.fred-save-version { flex: 0 1 auto; min-width: 0; }
.version-item .history-meta { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }

.version-number {
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  color: var(--accent-strong);
  flex: none;
}

/* --- File view (a past version, shown from the history drawer) ------------------- */

.file-view {
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.55;
  background: #fbf9f5;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin: 0;
  overflow-x: auto;
  padding: 14px 16px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* --- Chat: the therapist's chat PAGE ----------------------------------------------

   The conversation itself - thread, bubbles, typing, composer, the AI banner - is
   in css/chat.css, shared with the client's app (board task 48). What is here is
   the page the therapist reads it inside: a header with the mode being tested,
   the commit it pinned and who it is with. A client has none of that. */

.app-main.view-chat { overflow: hidden; display: flex; flex-direction: column; padding-bottom: 20px; }
.view-chat .view { flex: 1; min-height: 0; display: flex; flex-direction: column; }

.chat-layout { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 12px; width: 100%; max-width: 860px; margin: 0 auto; }
.chat-header { flex: none; display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; }
.chat-header-main { min-width: 0; }
.chat-title { font-family: var(--font-display); font-size: 21px; margin: 2px 0 6px; font-weight: 500; }
.chat-header-actions { display: flex; gap: 8px; flex: none; padding-top: 4px; }

/* The mode being tested is a CONTROL, not a label (board task 25). It sits in the
   chip row and reads as one of the chips, so the header still gives one line of
   context instead of growing a second row of furniture around it. Bounded width:
   a mode is a therapist's own slug, and a long one has to ellipsise rather than
   push the row past a 390px screen, where `overflow: hidden` clips it in silence. */
.mode-switch { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.mode-switch-label { font-size: 12.5px; color: var(--text-soft); white-space: nowrap; }
.mode-switch select { max-width: 42vw; padding-right: 4px; }

/* --- What Atlas is spending (board task 73) --------------------------------------
   The owner's page and nobody else's: `Section.USAGE` is held by the `dev` row
   alone, so the nav link is hidden and the route 404s for every other account.
   Numbers only - there is no column in `ai_calls` that could hold a sentence, so
   there is nothing here to style that a client said. */
.usage-totals { padding: 22px 24px; margin-bottom: 14px; }
.usage-headline { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.usage-amount {
  font-family: var(--font-display); font-size: 34px; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.usage-amount-label { color: var(--text-soft); font-size: 13px; }

/* Where the money went, as a row of small stacks. Wraps rather than scrolls:
   there are seven purposes at most and they are all short. */
.usage-breakdown {
  display: flex; flex-wrap: wrap; gap: 8px 26px; margin-top: 16px;
  padding-top: 14px; border-top: 1px solid var(--border);
}
.usage-purpose { display: flex; flex-direction: column; gap: 1px; }
.usage-purpose-name { font-size: 12px; color: var(--text-soft); }
.usage-purpose-cost { font-size: 15px; font-variant-numeric: tabular-nums; }
.usage-purpose-calls { font-size: 11.5px; color: var(--text-soft); }
.usage-partial { margin-top: 12px; color: var(--warn-text); }

/* The log itself. Its own scroller, because a table is the one thing on this
   surface that genuinely cannot fold at 390px - and a page that scrolls
   sideways as a whole is worse than a table that does (CODING-STANDARDS). */
.usage-table-wrap { overflow-x: auto; }
.usage-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.usage-table th {
  text-align: left; font-size: 11.5px; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--text-soft); font-weight: 600;
  padding: 0 12px 8px 0; white-space: nowrap;
}
.usage-table td { padding: 7px 12px 7px 0; border-top: 1px solid var(--border); }
.usage-row:hover { background: var(--surface-2); }
.usage-when, .usage-who { white-space: nowrap; }
.usage-purpose-cell { white-space: nowrap; }
.usage-model { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-soft); }
.usage-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.usage-cost { font-weight: 600; }
.usage-truncated { margin-top: 12px; }

/* --- The conversation's meter (board tasks 71 + 72) ------------------------------
   One discreet line: how far into the conversation you are, and what it has cost.
   Worn by BOTH surfaces a therapist writes on - Test Fred and the authoring
   assistant - from one component, `js/meter.js`.

   It lives in views.css and not in chat.css DELIBERATELY. chat.css is shared with
   the client's app (board task 48) and views.css is not loaded there at all, so
   an end user could not be shown what their conversation costs the practice even
   if a future change imported the module by mistake. The owner's ruling was that
   they must never see it; this is the second lock on that, behind the first one,
   which is that `static/client/` does not import the module.

   Deliberately quiet: 12px, soft text, no border, no background. It is a thing
   you glance at, not a thing you read - the real numbers are on #/usage. */
.chat-meter {
  flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: 7px;
  font-size: 12px; color: var(--text-soft); line-height: 1.5;
  /* Pulled up under the header rather than given a margin of its own: it is a
     caption on the conversation, not a band across the page. */
  margin: -6px 0 0;
}
.meter-part { white-space: nowrap; }
.meter-sep { color: var(--border-strong); }
.meter-cost { font-variant-numeric: tabular-nums; }

/* Approaching a cap. Amber, not red: nothing has gone wrong and nothing is
   broken - the conversation is simply nearly as long as it is allowed to get,
   which until now a therapist only discovered by being refused mid-sentence. */
.meter-part.is-near { color: var(--warn-text); font-weight: 600; }

/* At 390px the four parts wrap to two lines rather than being clipped: the
   pane is `overflow: hidden`, so a row that cannot fold disappears in silence
   (FIXER-NOTES footgun 34). */
@media (max-width: 480px) {
  .chat-meter { gap: 5px; font-size: 11.5px; }
}

/* --- Notes ---------------------------------------------------------------------- */

.notes-card { padding: 22px 24px; margin-top: 14px; }
.notes-section { margin-bottom: 20px; }
.notes-header { font-size: 15.5px; margin: 0 0 8px; color: var(--accent-strong); }

.notes-area {
  width: 100%;
  font: inherit;
  font-size: 14px;
  line-height: 1.55;
  padding: 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  resize: vertical;
  background: #fff;
  min-height: 110px;
}

.notes-area:focus { outline: var(--focus-ring); border-color: var(--accent); }
.notes-actions { display: flex; justify-content: flex-end; }

.empty-card {
  padding: 30px;
  text-align: center;
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

/* --- People (board task 65) ---------------------------------------------------------

   A four-column row - who / role / status / tools - that becomes two stacked
   blocks on a phone. The status pill is the only colour on the page, because
   "can this person log in" is the one thing the page exists to answer and
   everything else is detail you read afterwards. */

.people-actions { display: flex; gap: 10px; align-items: center; padding: 16px 18px; margin: 16px 0 18px; flex-wrap: wrap; }

.people-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.people-row:last-child { border-bottom: 0; }

.people-who { flex: 1; min-width: 0; }
.people-name { display: flex; align-items: baseline; gap: 8px; font-weight: 600; }
.people-email { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.people-role { flex: 0 0 110px; font-size: 13px; }
.people-status { flex: 0 0 170px; display: flex; flex-direction: column; gap: 2px; }
.people-expires { font-size: 12px; }
.people-tools { flex: none; display: flex; gap: 6px; }

/* "you" beside your own name: the row you must not be able to revoke, and the
   only one whose Revoke button is absent rather than refused. */
.people-you {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-soft);
  font-weight: 500;
}

.pill {
  display: inline-block;
  align-self: flex-start;
  font-size: 12px;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid transparent;
}
.pill-active { background: var(--accent-soft); color: var(--accent-strong); border-color: var(--accent); }
.pill-invited { background: var(--warn-bg); color: var(--warn-text); border-color: var(--warn-border); }
.pill-expired,
.pill-revoked { background: var(--danger-soft); color: var(--danger-strong); border-color: var(--danger); }

/* A revoked row is legible but plainly out of service - greyed, not hidden,
   because restoring it is one of the two things you come here to do. */
.people-row.is-revoked .people-who { opacity: 0.6; }

.people-form { display: flex; flex-direction: column; gap: 12px; }
.people-form .field { display: flex; flex-direction: column; gap: 4px; }
.people-form .field-label { font-size: 13px; color: var(--text-soft); }

/* The link is unrecoverable once this dialog closes - the server keeps only a
   hash - so it is shown wide, selectable and in mono, like something you are
   meant to take away rather than glance at. */
.invite-panel { display: flex; flex-direction: column; gap: 12px; }
.invite-link { font-family: var(--font-mono); font-size: 13px; }

/* --- Documents --------------------------------------------------------------------- */

/* Board task 68. The size rides the existing subtitle line rather than earning
   a chip of its own - the owner asked for this to stay clutter-free, and a
   number you read in passing is not a control. The ONE thing that does get its
   own mark is a document too big to send, because that is the fact he could not
   see until he pressed send. */
.doc-toobig {
  display: inline-block;
  margin-top: 3px;
  font-size: 12px;
  font-weight: 600;
  color: var(--danger-strong);
}

/* An attach row that cannot be picked still has to be readable - it is the row
   explaining WHY, and greying it into the background hides the explanation. */
.attach-row[disabled] { opacity: 0.55; cursor: not-allowed; }

.upload-card { display: flex; gap: 12px; align-items: center; padding: 16px 18px; margin: 16px 0 18px; flex-wrap: wrap; }
.file-input { flex: 1; min-width: 220px; font-size: 14px; color: var(--text-soft); }
.doc-row .btn { flex: none; }
.doc-actions { display: flex; align-items: center; gap: 6px; flex: none; }

/* The chevron: the visual cue that a row can expand (owner, 2026-09-07), in a
   column of its own so titles never shift left or right between rows that have
   one and rows that do not - `visibility`, not `display`, keeps the column. */
.doc-chevron {
  flex: none;
  width: 14px;
  text-align: center;
  color: var(--text-soft);
  font-size: 18px;
  line-height: 1;
  visibility: hidden;
  transition: transform 0.15s ease;
}
.doc-row.is-expandable .doc-chevron { visibility: visible; }
.doc-entry.is-open .doc-chevron { transform: rotate(90deg); color: var(--accent-strong); }
/* The count, and the way to the document's page. */
.doc-pill { text-decoration: none; white-space: nowrap; }
.doc-pill:hover { filter: brightness(0.95); }

/* The title area EXPANDS the row to what has been written about the document
   (2026-09-06) when there is something to show; the buttons beside it do not.
   A button inside a button is invalid, so the row is a div and this is the
   control. A row with nothing written keeps the same shape with no control. */
.doc-open {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.doc-open[aria-expanded="true"] .item-title { color: var(--accent-strong); }
.doc-open-still { cursor: default; }
.doc-open-still:hover .item-title { color: inherit; }

.doc-open:hover .item-title { color: var(--accent); }
.doc-open:focus-visible { outline: var(--focus-ring); outline-offset: 3px; border-radius: 4px; }
.doc-row.is-previewing { border-color: var(--accent); background: var(--surface-2); }

/* A row that has been written about EXPANDS (2026-09-06): the panel hangs off
   the card's bottom edge, squared off so the two read as one thing, and lists
   each section as a link to the page with that tab open. */
.doc-entry { display: flex; flex-direction: column; }
.doc-entry.is-open > .doc-row { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.doc-expand {
  padding: 8px 14px 10px;
  border: 1px solid var(--border);
  border-top: 0;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  background: var(--surface-2);
}
.doc-expand[hidden] { display: none; }
.doc-section-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.doc-section-link { display: flex; flex-direction: column; text-decoration: none; color: inherit; min-width: 0; }
.doc-section-link .item-title { font-size: 14px; }
.doc-section-link:hover .item-title { color: var(--accent); }
.doc-expand-page { display: inline-block; margin-top: 8px; font-size: 13.5px; color: var(--accent-strong); text-decoration: none; }
.doc-expand-page:hover { text-decoration: underline; }

/* Two groups on the list once somebody has shared something (board task 35).
   A shared row carries the accent down its left edge as well as its own
   heading: the group says where it came from, the stripe survives scrolling. */
.group-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-soft);
  margin: 18px 0 8px;
}
.panel-body > .group-title:first-child { margin-top: 0; }
.doc-row-shared { border-left: 3px solid var(--accent); background: var(--surface-2); }
.btn-shared { border-color: var(--accent); color: var(--accent-strong); }

/* Share dialog */
.share-list { list-style: none; margin: 12px 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.share-person { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.share-name { font-weight: 600; font-size: 14px; }
.share-email { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-add { display: flex; gap: 8px; align-items: center; margin-top: 12px; }
.share-picker { flex: 1; min-width: 0; }

/* Reading pane: wider than the history drawer, and the viewer fills it. */
.drawer-wide .drawer { width: 780px; }
.drawer-preview .drawer-body { padding: 0; }

/* The reading pane fills the drawer body, which does not scroll itself. */
.doc-pane { flex: 1; min-height: 0; display: flex; flex-direction: column; }

/* --- The editor (views/documents/editor.js) ---------------------------------------
   ONE set of rules for the two things written ABOUT a document: the reader's
   private study notes in the drawer, and the practice's named sections on the
   document's own page. They are the same sitting, so they are the same shape.

   The text is drawn ONCE, on Fred's rich-text surface (`.rt-surface`), and
   Edit changes two things: the paper (sepia to white, Fred's own signal) and
   whether the surface takes typing. The formatting tools appear in the button
   row, so nothing below it moves (owner, 2026-09-06). */
.doc-md { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.doc-md-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.doc-md-bar[hidden] { display: none; }
.doc-md-paper {
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  background: #fbf6ea;
  border: 1px solid transparent;
  font-size: 14.5px;
  line-height: 1.6;
}
.doc-md-paper[hidden] { display: none; }
.doc-md.is-editing .doc-md-paper { background: var(--surface); border-color: var(--border); }
.doc-md.is-draft .doc-md-paper { border-color: var(--warn-border); background: var(--warn-bg); }
/* Reading is the surface locked, not dimmed: Fred greys a locked page, a
   section is simply being read. */
.doc-md .rt-surface.is-readonly { color: inherit; }
.doc-md .rt-surface { min-height: 1.6em; }
.doc-md .rt-surface h2 { font-size: 16px; margin: 16px 0 6px; }
.doc-md .rt-surface h3 { font-size: 14.5px; margin: 14px 0 6px; }
.doc-md .rt-surface p, .doc-md .rt-surface ul, .doc-md .rt-surface ol { margin: 0 0 10px; }
.doc-md .rt-surface ul, .doc-md .rt-surface ol { padding-left: 22px; }
.doc-md .rt-surface > :last-child { margin-bottom: 0; }
/* The formatting tools live in the button row, and only while editing. Fred's
   sheet hides `.rt-toolbar` until its own pane says editing; this is the
   equivalent say-so here, without the slide - the row is already on screen. */
.doc-md-tools { display: inline-flex; min-width: 0; }
.doc-md-tools .rt-toolbar {
  visibility: visible; opacity: 1; transform: none; transition: none;
  padding: 0; background: transparent; border: 0;
}
.doc-md-uploading { display: inline-flex; }

/* "Draft with AI" and the switch that decides WHICH AI, as one unit: they are
   one decision, and the button on its own would not say that a choice exists. */
.doc-md-drafting { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* Replacing a document keeps its id, so it keeps its shares and everybody's
   notes. That is the whole reason Replace is worth offering and the whole
   reason it needs saying out loud before the click. */
.doc-dup-warning {
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  font-size: 13px;
  color: var(--warn-text);
}
.doc-md-when { margin-left: auto; }

/* An AI draft is marked as one until it is saved: what is on screen is a
   suggestion about the therapist's own writing, not yet their record of it. */
.doc-md-drafthint {
  margin: 0;
  padding: 8px 12px;
  font-size: 13px;
  border-radius: var(--radius-sm);
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  color: var(--warn-text);
}
.doc-md-drafthint[hidden], .doc-md-empty[hidden] { display: none; }


/* --- A document's own page (views/documents/book.js, 2026-09-06) -------------------
   Breadcrumb, the document's facts, and a tab bar of the sections the practice
   named. The tabs WRAP: a book can carry a dozen headings, and a row that clips
   is a row that hides one (footgun 22). */
.book-nav { margin-bottom: 10px; }
.book-back { text-decoration: none; }

/* Who wrote what (2026-09-07): the name in bold, and a control rather than a
   word - pressing it opens that person's changes. */
.doc-author {
  border: 0; background: none; padding: 0; margin: 0; font: inherit; font-weight: 700;
  color: var(--text); cursor: pointer; text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.doc-author:hover { color: var(--accent-strong); }
.doc-changes { display: flex; flex-direction: column; gap: 16px; }
.doc-change-head { margin: 0 0 6px; font-size: 14px; }
/* The host wears `.fred-compare-view` so fred.css's prose mapping applies -
   body font, Atlas's palette, and the "nothing is drawn as already lost" guard
   (footgun 93) - and only the height is its own: a card, not a pane. */
.doc-change-diff { border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.doc-change-diff.fred-compare-view .prism-diff-view { height: min(40vh, 320px); }
.doc-change-show { margin: 10px; }

.book-head { display: flex; align-items: flex-start; gap: 12px 18px; flex-wrap: wrap; }
.book-head-main { flex: 1; min-width: 240px; }
.book-title { overflow-wrap: anywhere; }
.book-facts { margin: 4px 0 6px; }
.book-actions { display: flex; gap: 8px; flex: none; align-items: center; }

.book-panel { padding: 0; overflow: hidden; }
.book-tabs { border-radius: var(--radius) var(--radius) 0 0; }
.book-tabs .tabs { flex-wrap: wrap; }
.book-tab { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.book-add { flex: none; margin-left: auto; }
.book-pane { padding: 16px 22px 20px; }
.book-empty { padding: 26px 10px; text-align: center; }
.book-empty .empty-note { margin: 0; }

/* The "add a section" dialog: the names already in use, as chips to press. */
.doc-section-chips { display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0 4px; }
.doc-section-chip { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.doc-preview-frame {
  flex: 1;
  min-height: 0;
  width: 100%;
  border: 0;
  background: var(--surface-2);
}

.doc-preview-fallback {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 30px;
  text-align: center;
  color: var(--text-soft);
}

/* --- Client records (board task 16) --------------------------------------------------

   The list borrows the item-card row every other list uses. The RECORD is the
   only new shape: a run of sessions, each one a heading and the notes taken in
   it, read top to bottom. Deliberately not cards-inside-cards - it is one
   document about one person, and a border per session would fight that. */

.client-new { display: flex; gap: 12px; align-items: center; padding: 16px 18px; margin: 16px 0 18px; flex-wrap: wrap; }
.client-new-name { flex: 1; min-width: 200px; }

.record-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }

.record-list { display: flex; flex-direction: column; }

.record-entry { padding: 18px 0; border-top: 1px solid var(--border); }
.record-entry:first-child { border-top: none; padding-top: 4px; }

.record-entry-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.record-date { font-weight: 600; font-size: 14px; }

/* Pushed to the trailing edge so the date and the badges read as one group and
   the ways OUT of the record read as another. */
.record-entry-links { display: flex; gap: 14px; margin-left: auto; }
.record-link { font-size: 12.5px; color: var(--accent-strong); text-decoration: none; }
.record-link:hover { text-decoration: underline; }

.record-section { margin-bottom: 14px; }
.record-header { font-size: 14px; margin: 0 0 4px; color: var(--accent-strong); }
.record-body { font-size: 14px; line-height: 1.55; }
.record-body p { margin: 0.35em 0; }
.record-body ul, .record-body ol { margin: 0.35em 0; padding-left: 20px; }
.record-body code { background: rgba(0, 0, 0, 0.07); border-radius: 4px; padding: 0 4px; font-size: 0.92em; }

.record-nonote { margin: 0; }

/* --- Responsive ---------------------------------------------------------------------

   SYSTEM-INTENT -> "Responsive layout" (board task 22). The app SHELL is the
   part every screen shares, so its breakpoints live here; Fred's editor decides
   its own in fred.css, and the rule there is the same one: something that no
   longer fits as a column becomes a panel in the drawer.

   Two shell widths. 960 tightens the gutters. 700 is where the header stops
   being one row: `body` is `overflow: hidden`, so a header that overflows is
   CLIPPED rather than scrolled, and Log out would simply be off the side of the
   phone. It wraps to two rows instead - identity and account on top, the nav
   underneath it - because a hamburger would be a second navigation pattern for
   three links that fit. */

@media (max-width: 960px) {
  .app-main { padding: 20px 18px 40px; }
  .app-header { padding: 0 18px; gap: 16px; }
}

/* Between a laptop and a phone the header still tries to hold the brand, every
   nav link, the account name and Log out on ONE 60px row — and from seven links
   it cannot. Adding Spend (board task 73) put Log out at 810..870 in an 820px
   window, where `body { overflow: hidden }` cuts it off in silence: no
   scrollbar, no error, and `is_visible()` still true (footgun 22).

   The answer is the one the phone block below already gives, one width up: the
   nav takes a row of its own. It is a better row than a squeezed one anyway —
   seven links at 14px do not want to be shrunk, they want somewhere to go.
   Desktop is untouched, which is why this is a MAX-width and not a change to
   the base rule. */
@media (max-width: 1080px) and (min-width: 701px) {
  .app-header {
    height: auto;
    min-height: 60px;
    flex-wrap: wrap;
    gap: 2px 20px;
    padding: 6px 24px 0;
  }
  .app-nav { order: 3; width: 100%; flex-wrap: wrap; gap: 4px 18px; }
  .app-nav a { padding: 4px 2px 8px; }
}

@media (max-width: 700px) {
  .app-main { padding: 16px 14px 32px; }

  .app-header {
    height: auto;
    min-height: 56px;
    flex-wrap: wrap;
    gap: 6px 14px;
    padding: 8px 14px;
  }

  /* Last in the order and full width, so it takes the second row on its own
     rather than wherever it happens to stop fitting beside the brand. It wraps
     as well: the header is `overflow: hidden`, so a fourth link (Clients, board
     task 16) that no longer fits would be CLIPPED rather than pushed down. */
  .app-nav { order: 3; width: 100%; gap: 4px 18px; flex-wrap: wrap; }
  .app-nav a { padding: 2px 2px 6px; }

  /* The header is a rationed row at this width: brand + account + Log out only
     just fit on it, and the version badge pushed them onto a third row - 39px of
     an 844px phone spent on a number you look up rather than read. It is the
     least urgent thing here, so it is the thing that goes. `/health` still
     answers on a phone, and docs/INSTALL.md says so. */
  .app-version { display: none; }

  .header-right { gap: 10px; }
  /* Kept, not hidden: a therapist and a supervisor share a laptop, and which
     account is signed in is the thing you check before you type. Truncated
     because a real name is longer than "Therapist One". */
  .user-name { max-width: 38vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  .login-card { padding: 28px 22px 24px; }
  .login-brand { font-size: 30px; }

  /* The bubble's own phone rule moved to css/chat.css with the element it is
     about - the client's app needs it and must not load this file. */
  .chat-header { flex-wrap: wrap; }
  .chat-header-actions { margin-left: auto; }

  /* Title above, buttons below-right: side by side, an ellipsised filename is
     all the therapist gets to identify what they are about to delete. The
     buttons WRAP too (2026-09-06): "Sections · N" made five of them, and a row
     of actions that grows by one gets sliced at the card's edge (footgun 34) -
     Delete was the one hanging off the right of a 390px screen. */
  .doc-row { flex-wrap: wrap; }
  /* The chevron stays ON the title's line (a `min-width: 100%` title pushed it
     onto a line of its own above, seen in the 2026-09-07 phone screenshots);
     the title takes the rest of that line and the buttons wrap below. */
  .doc-open { flex: 1 1 0; min-width: 0; }
  .doc-actions { flex: 1 1 100%; flex-wrap: wrap; justify-content: flex-end; }

  /* Name and email take the first line; role, status and the buttons share the
     second. The fixed column widths above would otherwise squeeze the email to
     an ellipsis on a phone - and the email is how you tell two colleagues with
     the same first name apart. */
  .people-row { flex-wrap: wrap; gap: 8px 12px; }
  .people-who { min-width: 100%; }
  .people-role { flex: none; }
  .people-status { flex: none; flex-direction: row; align-items: baseline; gap: 6px; }
  .people-tools { margin-left: auto; }
}
