/* Atlas — Fred's editor (#/, the screen login lands on).

   The view reads top to bottom inside the SIDEBAR: search, MODE TABS, the
   selected mode's own files above a hard rule, and the shared base (core /
   knowledge / methodology) below it. The base block is drawn inset behind the
   mode colour's rail — it is one set of files that every mode re-frames, which
   is what its caption says.

   Colour is declared once, as --f / --f-soft / --f-line. Swatches, file rows,
   chips, badges, breadcrumb segments and the folder picker all read those
   variables off the nearest .folder-* / .mode-hue-* ancestor, so a colour is
   defined in exactly one place. The base hues are far apart on purpose (burnt
   orange / forest green / ocean blue): the owner found the mock's
   core-vs-methodology and knowledge-vs-modes indistinguishable.

   Modes have no fixed colour, because there is no fixed set of them: a mode
   takes a hue by its position in the tree (folders.js), so two modes are
   never the same colour. Hue 0 is the violet the mode layer has always worn,
   which is why the default mode looks unchanged. The five sit in the gaps the
   base folders leave — violet, rose, teal, bronze, graphite — and only ever
   appear together as the dots in the tab strip; below it exactly one is on
   screen. There are FIVE rather than four because board task 20 put an "add a
   mode" button in the strip: a fifth mode used to mean hand-editing the content
   repo, and now a therapist can make one in a second — at which point wrapping
   round to violet would break the rule above on the very first use. */

.mode-hue-0         { --f: #6d28d9; --f-soft: #f2ebfd; --f-line: #d6c4f5; }
.mode-hue-1         { --f: #be185d; --f-soft: #fdeaf1; --f-line: #f6c6d9; }
.mode-hue-2         { --f: #0f766e; --f-soft: #e2f2f0; --f-line: #b4dcd7; }
.mode-hue-3         { --f: #a16207; --f-soft: #fbf0da; --f-line: #eed9a6; }
.mode-hue-4         { --f: #475569; --f-soft: #eef1f5; --f-line: #cbd5e1; }

.folder-core        { --f: #c2410c; --f-soft: #fdeade; --f-line: #f2c9a8; }
.folder-knowledge   { --f: #15803d; --f-soft: #e2f3e8; --f-line: #b7dcc3; }
.folder-methodology { --f: #0f6ba8; --f-soft: #e4f0f9; --f-line: #b5d6ec; }

/* --- Workspace shell --------------------------------------------------------- */

/* Wider than the reading column: the workspace is a sidebar plus an editor, not
   prose. Set as the shared `--main-max` rather than as a `max-width` here — the
   base rule centres with padding now, and capping this box as well would shrink
   the workspace by the gutter twice over (see `.app-main` in app.css). */
.app-main.view-fred {
  --main-max: 1560px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding-bottom: 20px;
}

.view-fred .view { flex: 1; min-height: 0; display: flex; }

.fred-workspace {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
}

.fred-topbar { flex: none; display: flex; align-items: center; gap: 12px; }
.fred-topbar .page-title { font-size: 23px; }
.fred-topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* --- Backup badge (board task 19) ---------------------------------------------

   "Is Fred's content anywhere but this laptop?" — the only thing in this topbar
   that is about the content being SAFE rather than about editing it. It reads as
   a status, not as another action: a dot, a word, and the detail on click.

   Exactly one state is quiet. `is-ok` is the only one wearing the accent; off /
   unknown are amber and failed is red, because all three mean the therapist's
   work exists in one place only. There is no state that looks like nothing. */

.fred-backup {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-soft);
  white-space: nowrap;
  cursor: pointer;
}

.fred-backup:hover { border-color: var(--text-soft); }
.fred-backup-dot { width: 7px; height: 7px; flex: none; border-radius: 50%; background: currentColor; }

.fred-backup.is-ok { color: var(--accent-strong); border-color: var(--accent-soft); background: var(--accent-soft); }
.fred-backup.is-pending,
.fred-backup.is-off,
.fred-backup.is-unknown { color: var(--warn-text); border-color: var(--warn-border); background: var(--warn-bg); }
.fred-backup.is-failed { color: var(--danger-strong); border-color: var(--danger); background: var(--danger-soft); }

/* A failing push is the one state worth an animated dot: it is the only one that
   is actively losing something, and the badge is small enough to be missed. */
.fred-backup.is-failed .fred-backup-dot { animation: fred-backup-pulse 1.6s ease-in-out infinite; }

@keyframes fred-backup-pulse { 50% { opacity: 0.25; } }

@media (prefers-reduced-motion: reduce) {
  .fred-backup.is-failed .fred-backup-dot { animation: none; }
}

.fred-backup-facts { margin: 12px 0 0; display: grid; grid-template-columns: auto 1fr; gap: 4px 14px; }
.fred-backup-facts dt { color: var(--text-soft); font-size: 12.5px; }
.fred-backup-facts dd { margin: 0; font-size: 12.5px; word-break: break-all; }

.fred-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 276px minmax(0, 1fr) 360px;
  gap: 16px;
}

.fred-grid.assistant-collapsed { grid-template-columns: 276px minmax(0, 1fr); }

/* The drawer's scrim and panel are position:fixed, but their wrapper would
   still take a row (and a gap) in the workspace's flex column. */
.fred-workspace > .drawer-root { display: contents; }
.fred-grid .assistant-panel { position: static; max-height: none; height: 100%; top: auto; }

/* --- Sidebar ------------------------------------------------------------------ */

.fred-sidebar { display: flex; flex-direction: column; min-height: 0; overflow: hidden; padding: 0; }
/* No border-bottom of its own: the mode tabs' coloured rule below is the head's
   bottom edge, and two stacked lines there looked like a mistake. */
/* What this column is, said once (owner, 2026-07-27). Above the search rather
   than beside it: it captions everything below, including the mode tabs. */
.fred-sidebar-title { flex: none; padding: 12px 12px 8px; background: var(--surface-2); }
.fred-sidebar-heading {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 15px;
  margin: 0;
  color: var(--accent-strong);
}
.fred-sidebar-sub { margin: 3px 0 0; font-size: 11.5px; line-height: 1.4; color: var(--text-soft); }
.fred-sidebar-head { flex: none; padding: 0 12px; background: var(--surface-2); }
.fred-search { font-size: 13.5px; padding: 6px 10px; }
.fred-tree { flex: 1; min-height: 0; overflow-y: auto; padding: 10px 10px 14px; }
.fred-sidebar-foot { flex: none; padding: 10px 12px; border-top: 1px solid var(--border); }
.fred-no-match { padding: 0 4px; }

/* --- Mode tabs (the ONE picker, in the sidebar) --------------------------------

   The mode is this view's top-level context, so it gets real tabs — and they sit
   with the files they scope: under the search, directly above that mode's own
   files (owner, 2026-07-26). The rule under them is the selected mode's colour,
   the same colour the base rail and the breadcrumb carry, so it is also the line
   that opens the mode's block. It is pulled out to the head's full width because
   a rule that stops short of the sidebar edges does not read as an edge.

   The strip NEVER wraps (owner): it pans sideways by drag or wheel
   (mode-tabs.js). Two modes fit this column comfortably; from three it pans,
   which is why the tabs are sized tighter than a page-wide strip would be. */

/* The negative margin + matching padding put the rule on the sidebar's full
   width while the tabs themselves stay on the search box's left edge.

   A flex ROW, because add/remove are pinned beside the strip rather than inside
   it: a control that pans out of sight is a control nobody can reach. The strip
   takes the space that is left and pans within it. */
.fred-modes-bar {
  flex: none;
  display: flex;
  align-items: flex-end;
  gap: 4px;
  margin: 9px -12px 0;
  padding: 0 12px;
  border-bottom: 3px solid var(--f);
}

.fred-modes-strip {
  flex: 1;
  min-width: 0;
  display: flex;
  gap: 5px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  touch-action: pan-x;
  /* Dragging the strip must pan it, not select the tab labels. mode-tabs.js
     cannot suppress that in JS any more: it only takes the pointer capture once
     a drag is real, because capturing earlier stole the tabs' own clicks. */
  user-select: none;
}

/* Making and unmaking a mode (board task 20). Quiet until hovered: they sit next
   to the one control on this screen that is used constantly, and a delete that
   shouts is a delete that gets clicked. */
.fred-modes-controls { flex: none; display: flex; gap: 2px; padding-bottom: 4px; }

.fred-modectl {
  flex: none;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  font: inherit;
  font-size: 12px;
  line-height: 1;
  color: var(--text-soft);
  opacity: 0.65;
  cursor: pointer;
}

.fred-modectl:hover { opacity: 1; color: var(--f); background: var(--f-soft); border-color: var(--f-line); }
.fred-modectl-remove:hover { color: var(--danger); background: var(--danger-soft); border-color: var(--danger); }

.fred-modes-strip::-webkit-scrollbar { height: 5px; }
.fred-modes-strip::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 3px; }

.fred-modetab {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: transparent;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-soft);
  padding: 6px 11px 7px;
  white-space: nowrap;
  cursor: pointer;
}

.fred-modetab:hover { color: var(--f); background: var(--f-soft); }

.fred-modetab.is-active {
  background: var(--f-soft);
  border-color: var(--f-line);
  color: var(--f);
  box-shadow: inset 0 3px 0 var(--f);
}

/* Mode names are lowercase slugs everywhere they are stored; the capital is
   presentation, never a display name mapped onto a different slug. */
.fred-modetab-name { text-transform: capitalize; }

.fred-modetab-dot {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 50%;
  background: var(--f);
  opacity: 0.4;
}

.fred-modetab.is-active .fred-modetab-dot { opacity: 1; }

.fred-swatch {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  background: var(--f);
  flex: none;
}

/* The selected mode's own layer, at the top of the tree: just the files that
   make it up. It carries no caption — the selected TAB is directly above it, in
   this same colour, and repeating the mode's name below it said nothing new and
   pushed the tree down. */

.fred-mode-block { margin-bottom: 2px; }
.fred-lock { font-size: 12px; flex: none; }

/* The hard separator. Everything below it is the base every mode re-frames. */

.fred-separator { margin: 10px 0 12px; }

.fred-separator-rule {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--f) 0%, var(--f) 62%, var(--f-line) 100%);
}

.fred-separator-caption { padding: 7px 4px 0; cursor: help; }

.fred-base-label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-soft);
}

/* The base block is inset behind the mode colour's rail: you are editing it
   from inside the selected mode, and it is not a peer of that mode. */
.fred-base { padding-left: 10px; border-left: 2px solid var(--f-line); }

.fred-folder { margin-bottom: 10px; }

.fred-folder-head {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 3px 4px 5px;
  border-bottom: 1px solid var(--f-line);
  margin-bottom: 4px;
  cursor: help;
}

.fred-folder-name {
  flex: 1;
  min-width: 0;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--f);
}

.fred-folder-count {
  font-size: 11px;
  font-weight: 600;
  color: var(--f);
  background: var(--f-soft);
  border-radius: 999px;
  padding: 0 7px;
}

.fred-add {
  flex: none;
  border: 0;
  background: transparent;
  color: var(--f);
  font: inherit;
  font-size: 13px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 5px;
  cursor: pointer;
  opacity: 0.65;
}

.fred-add:hover { opacity: 1; background: var(--f-soft); }
.fred-folder-empty { margin: 0 0 2px 6px; font-size: 12.5px; color: var(--text-soft); font-style: italic; }

/* File rows carry their folder's colour on the left edge. */

.fred-files { display: flex; flex-direction: column; gap: 2px; padding-bottom: 4px; }

.fred-file {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  text-align: left;
  border: 1px solid transparent;
  border-left: 3px solid var(--f-line);
  background: transparent;
  font: inherit;
  font-size: 13.5px;
  color: var(--text);
  padding: 5px 8px 5px 9px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  cursor: pointer;
}

.fred-file:hover { background: var(--f-soft); border-left-color: var(--f); }

.fred-file.is-open {
  background: var(--f-soft);
  border-color: var(--f-line);
  border-left-color: var(--f);
  font-weight: 600;
  color: var(--f);
}

.fred-file-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fred-dirty { color: var(--warn-text); font-size: 11px; flex: none; }

.fred-used {
  flex: none;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--f);
  background: var(--f-soft);
  border: 1px solid var(--f-line);
  border-radius: 999px;
  padding: 0 6px;
  white-space: nowrap;
}

.fred-mode-files { padding: 0 6px 2px 10px; }

/* --- Main pane ------------------------------------------------------------------ */

.fred-main { display: flex; flex-direction: column; min-height: 0; overflow: hidden; padding: 0; }

.fred-empty {
  margin: auto;
  padding: 40px 32px;
  text-align: center;
  max-width: 420px;
}

.fred-empty-title { font-family: var(--font-display); font-weight: 500; font-size: 20px; margin: 0 0 6px; }

.fred-file-head { flex: none; padding: 12px 16px 10px; border-bottom: 1px solid var(--border); }
.fred-head-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.fred-breadcrumb { display: flex; align-items: baseline; gap: 5px; min-width: 0; flex-wrap: wrap; }
.fred-crumb { font-size: 13px; color: var(--f); font-weight: 600; }
.fred-crumb.is-file { font-size: 16px; color: var(--text); font-weight: 600; }
.fred-crumb-sep { color: var(--border-strong); }

/* The file crumb as a RENAME control (board task 87): a page's Russian name is
   edited where the name is, not from a menu somewhere else. It must read as the
   crumb it replaces — same size, same weight, same colour — so `button` is
   stripped back to text and the only addition is the pencil.

   Not a hover-reveal: on a touchscreen there is no hover, so a control that only
   appears under a pointer does not exist at the width this is most used at
   (footgun 60). The pencil is quiet rather than hidden. */
.fred-crumb-rename {
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  font: inherit; font-size: 16px; font-weight: 600; color: var(--text);
  display: inline-flex; align-items: baseline; gap: 6px;
  min-width: 0; text-align: left;
}
.fred-crumb-rename .fred-crumb-text { min-width: 0; overflow-wrap: anywhere; }
.fred-crumb-pencil { font-size: 12px; color: var(--f); opacity: 0.75; }
.fred-crumb-rename:hover .fred-crumb-pencil,
.fred-crumb-rename:focus-visible .fred-crumb-pencil { opacity: 1; }

.fred-unsaved { text-transform: none; letter-spacing: 0; }

/* Which version, and when it was written — the far end of the breadcrumb's line
   (owner, 2026-07-27). `margin-left: auto` pushes it right; because the row
   wraps, on a phone it drops onto its own line instead of being clipped. */
.fred-version {
  margin-left: auto;
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 12px;
  color: var(--text-soft);
  white-space: nowrap;
}
.fred-version-no { font-weight: 700; color: var(--text); }
.fred-version-sep { color: var(--border-strong); }
.fred-version-new { font-style: italic; }

.fred-chip-row { display: flex; flex-direction: column; gap: 5px; margin-top: 8px; }
.fred-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

.fred-chips-label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-soft);
}

.fred-ref-chip {
  border: 1px solid var(--f-line);
  background: var(--f-soft);
  color: var(--f);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  padding: 1px 10px;
  cursor: pointer;
}

.fred-ref-chip:hover { background: #fff; border-color: var(--f); }

/* Wraps at EVERY width, not just on a phone: the pane is `overflow: hidden`, so
   a row of six controls that does not fit is silently sliced off at the right
   edge - and it was, at 820px, taking Save with it while the click still
   "worked" (board task 22, caught in a screenshot, now measured by the walk).
   Wrapping costs nothing at a width where the row already fits. */
.fred-tab-bar {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}

/* The tabs wrap for the same reason the bar does: a draft adds a fourth one,
   and `.tabs` is a flex row inside a pane that clips rather than scrolls. */
.fred-tab-bar .tabs { flex: 1; flex-wrap: wrap; }
.fred-tab-bar .tab { display: inline-flex; align-items: center; gap: 6px; }

.fred-tab-count {
  font-size: 10.5px;
  font-weight: 700;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 6px;
}

.tab.active .fred-tab-count { background: var(--accent-soft); border-color: var(--border-strong); }
/* Wraps, and may shrink below its content, for the reason the bar above it does:
   a draft adds a fourth action (Discard draft) and at 390px that pushed Save
   past the pane's right edge, where `overflow: hidden` cut it off in silence.
   `flex: 0 1 auto` + `min-width: 0` is what lets it fold instead of overflow;
   `flex: none` cannot. Caught by the walk's own box check, not by eye. */
.fred-head-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  flex: 0 1 auto;
  min-width: 0;
}
/* No padding of its own except at the foot. The page's left/right margins live
   on the PANES below, because the writing toolbar has to run edge to edge and a
   sticky child cannot escape its parent's padding to do it — it is clamped to
   the containing block's content box, so a negative margin is silently undone
   and leaves a strip of paper above the toolbar (owner, 2026-07-31, second
   round: "there is this white gap in between"). */
.fred-pane-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0 0 18px; position: relative; }
.fred-pane[hidden] { display: none; }

/* The page's own margins, carried by everything that is NOT the toolbar strip. */
.fred-pane, .locked-notice, .draft-notice { margin-left: 16px; margin-right: 16px; }
.locked-notice, .draft-notice { margin-top: 14px; }

/* --- the rich-text editor (js/richtext/) --------------------------------------
   The PAPER is the whole signal that what is on screen can be changed (owner,
   2026-07-31): a page is read on sepia and written on white. It is on the BODY
   rather than the surface so the notices above the text sit on the same paper,
   and so a therapist can tell reading from writing out of the corner of their
   eye without reading a tab label.

   Nothing else changes between the two. The colour is the ONLY difference —
   pressing Edit must not move a word, add a rule, or reflow a line. */
.fred-pane-body { background: #fbf6ea; }
.fred-pane-body.is-editing { background: var(--surface); }

/* The strip the writing tools live in. It is in the flow of the body in EVERY
   tab, so its height is reserved whether or not the tools are on screen; the
   toolbar inside it is hidden with `visibility`, which keeps the box. That is
   what stops Edit pushing the document down the screen.

   It is the body's FIRST child and the body has no top padding, so it sits
   flush under the tab bar with nothing between them — the toolbar is that bar
   growing a second row, not a panel floating on the page (owner, 2026-07-31:
   "the top of the edit bar is aligning with the bottom of the bar above").
   Sticky at `top: 0` keeps it there on a long file. Do NOT reach for a negative
   margin here: a sticky box is clamped to its containing block's content box,
   so the pull is undone and the gap comes back.

   `margin-bottom` is the document's own headroom, in BOTH modes — the strip is
   reserved either way, so this is the space above the first line whether you
   are reading or writing. The owner asked for about ten pixels more of it than
   the first cut had: text crammed against the tools reads as an accident.

   It takes no pointer events itself: while reading it is an invisible band
   across the top of the page, and it must not swallow a click or a selection. */
.rt-slot {
  position: sticky;
  top: 0;
  z-index: 3;
  margin-bottom: 24px;
  pointer-events: none;
}

/* Wears the tab bar's own colour, and has only the edge it shares with the
   document: side and top borders would draw the box back in. */
.rt-toolbar {
  display: flex;
  flex-wrap: wrap;                  /* footgun 34: a row that cannot fold gets sliced */
  align-items: center;
  gap: 6px;
  padding: 6px 16px;
  background: var(--surface-2);
  border: 0;
  border-bottom: 1px solid var(--border);
  pointer-events: auto;
  visibility: hidden;
  opacity: 0;
  transform: translateY(-8px);
  /* `visibility` is what takes the hidden toolbar out of the tab order and off
     the accessibility tree; it flips at the END of the slide out and at the
     START of the slide in, hence the two transitions. */
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0.18s;
}

.fred-pane-body.is-editing .rt-toolbar {
  visibility: visible;
  opacity: 1;
  transform: none;
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s;
}

@media (prefers-reduced-motion: reduce) {
  .rt-toolbar, .fred-pane-body.is-editing .rt-toolbar { transition: none; }
}

.rt-group { display: flex; align-items: center; gap: 4px; flex: 0 1 auto; min-width: 0; }
.rt-extras { margin-left: auto; gap: 6px; }
.rt-extra { position: relative; display: inline-flex; }

.rt-style {
  font-size: 12.5px;
  padding: 3px 6px;
  width: auto;
  min-width: 118px;
  background: var(--surface);
}

.rt-btn {
  min-width: 30px;
  height: 28px;
  padding: 0 8px;
  font-size: 13px;
  line-height: 1;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  cursor: pointer;
}

.rt-btn:hover { background: var(--accent-soft); border-color: var(--border-strong); }
.rt-btn[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--border-strong); }
.rt-btn:disabled { opacity: 0.45; cursor: default; }
.rt-bold { font-weight: 800; }
.rt-italic { font-style: italic; font-family: var(--font-display); }
.rt-underline { text-decoration: underline; }
.rt-file { display: none; }

.rt-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  min-width: 200px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
}
.rt-menu[hidden] { display: none; }
.rt-menu-item {
  text-align: left;
  padding: 8px 12px;
  font-size: 13px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text);
}
.rt-menu-item:hover { background: var(--accent-soft); }

/* No box of its own — no border, no background, no padding. The reading view
   has none of those either, and the whole point is that the words do not move
   when the tab does. The paper underneath (`.fred-pane-body`) is what changes. */
.rt-surface {
  line-height: 1.6;
  outline: none;
}
/* Dimmed rather than re-papered: a background here would draw the box back in
   and make a locked file the one place Edit still shifts the layout. */
.rt-surface.is-readonly { color: var(--text-soft); }
/* Dimmed but still LIVE: `pointer-events: none` here would take Download away
   with the writing controls, and taking a copy of a locked file is exactly what
   a lock should still allow. `disabled` on each writing control does the work. */
.rt-toolbar.is-readonly .rt-writes { opacity: 0.45; }

/* Dropping a document anywhere on the open page replaces it (board task 53), so
   the hint covers the whole pane rather than marking a target to aim at. */
.fred-drop-hint {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;             /* or it eats the drop it is advertising */
  background: rgba(251, 246, 234, 0.92);
  border: 2px dashed var(--accent-strong);
  border-radius: var(--radius-sm);
  font-weight: 600;
  color: var(--accent-strong);
  text-align: center;
  padding: 20px;
}
.fred-drop-hint[hidden] { display: none; }

/* Highlight words in the page and this appears under them: the way to ask the
   assistant about one passage rather than the whole file (owner, 2026-07-31).
   Absolutely placed inside the scrolling body, so it travels with the words it
   belongs to; `file-pane.js` positions it and hides it on a scroll. */
.fred-discuss {
  position: absolute;
  z-index: 7;
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: #fff;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
  white-space: nowrap;
}
.fred-discuss:hover { filter: brightness(1.08); }
.fred-discuss[hidden] { display: none; }

/* An AI draft is unmistakable or it is dangerous: what is on screen is NOT the
   file, and one press of Save makes it so. Hence a whole-pane frame rather than
   a badge alone (docs/SYSTEM-INTENT.md, "AI authoring drafts").

   An INSET SHADOW, not a border: a real border adds two pixels to the box, so a
   draft arriving reflowed the document under the therapist's eyes — the same
   jump Edit used to cause. A shadow is drawn inside the box it already had. */
.fred-pane-body.is-draft {
  box-shadow: inset 0 0 0 2px var(--warn-border);
  border-radius: var(--radius-sm);
  background: var(--warn-bg);
}

/* ...but WRITING still gets white paper, draft or not (owner, 2026-07-31: "I
   clicked back to edit and it's still in sepia"). Both rules are one class
   deep, so the later one won and a draft made Edit the one place the paper did
   not change - which is the whole signal that the page can be typed on. The
   draft's own signal is the frame, the badge and the notice, none of which
   this touches. Written as a compound selector so it wins on specificity
   rather than on the order these two blocks happen to be in. */
.fred-pane-body.is-draft.is-editing { background: var(--surface); }

.fred-draft-badge {
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  color: var(--warn-text);
  font-weight: 700;
}

.draft-notice {
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  margin-bottom: 12px;
  font-size: 12.5px;
  line-height: 1.5;
}

/* --- somebody else is on this page (board task 74) --------------------------
   Quieter than every other notice in this pane on purpose. A colleague having
   the page open is NEWS, not a warning: nothing is wrong and nothing of the
   author's is at risk, and a line that shouts would train them to close it. It
   picks up the draft notice's warm background only once their save has actually
   landed under unsaved words, which is the one state that needs a decision. */
/* A row rather than a block since round two: the line now carries an ACTION —
   "View changes" — and an announcement about somebody else's save with no way
   to see it is a notification a therapist learns to ignore within a day. */
.coedit-notice {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 6px 12px;
  margin-top: 14px;
  margin-bottom: 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}

.coedit-notice.is-behind {
  background: var(--warn-bg);
  border-color: var(--warn-border);
  color: inherit;
}

/* --- the page in Russian (the bilingual design) -----------------------------
   The Russian is a RENDERING of the English, not a second file, and the pane
   says so quietly: the words themselves are drawn by exactly the same rules as
   the Read pane (`.fred-read-body` is on the prose here too, so a page does not
   change typeface when it changes language), with one line of provenance above
   them and a banner only when there is something to decide. */
.fred-render-origin { margin: 0 0 10px; }

/* The two states that are not the page: waiting for a translation, and a page
   that has none. Given the read pane's own minimum height so that the pane does
   not jump when the words arrive. */
.fred-render-state { min-height: 30vh; padding-top: 8px; }
.fred-render-working { font-size: 15px; margin: 0 0 4px; }
.fred-render-working::after {
  content: "…";
  animation: render-waiting 1.4s steps(4, end) infinite;
}
@keyframes render-waiting { 0% { opacity: 0.25; } 50% { opacity: 1; } 100% { opacity: 0.25; } }

/* Warm rather than red: the English having moved on is news, and a failed
   translation costs nothing that was not derived - the same reasoning the
   co-editing line above it is drawn by. */
.fred-render-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  margin: 0 0 12px;
  font-size: 12.5px;
  line-height: 1.5;
}

.fred-render-older { border-top: 1px solid var(--border); padding-top: 10px; }

/* --- "what Fred is given" (board task 64) ----------------------------------
   The one screen in Atlas that shows text as the MODEL receives it. Everywhere
   else a therapist reads prose; here they are looking at the wire, so the
   blocks are monospace and unrendered on purpose — prettifying them would
   defeat the point of the screen. */
/* `.drawer-body` is a flex COLUMN with a fixed height, so anything in it that
   can shrink will — and the stage switch was squashed to a one-pixel line the
   first time this ran, present in the DOM and impossible to click. The list is
   the only thing that scrolls; everything above it holds its size. Same shape
   as the history drawer's `.history-list` rule, and the same footgun. */
/* Wider than the other drawers. Fred's pages are hard-wrapped at 76 characters
   (app/fred/templates.py), so a narrow panel wraps every source line a second
   time and the shape of the prompt — which is the whole reason to be looking
   at it — is lost in the raggedness. */
.drawer-prompt .drawer { width: min(760px, 96vw); }

/* --- the segmented switch ------------------------------------------------------
   MOVED here, and renamed, when Atlas's own diff was deleted (board task 74
   round two). These rules used to be called `.fred-diff-switch` / `.fred-diff-view`
   because the Changes / Before / After control was the first thing that needed
   them — but the prompt drawer's stage switch has been borrowing them all along,
   and deleting them with the diff would have quietly unstyled a screen in a
   different feature. A shared control should not be named after one caller. */
.fred-switch {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface);
}

.fred-switch-option {
  padding: 4px 12px;
  font-size: 12.5px;
  background: none;
  border: 0;
  border-right: 1px solid var(--border);
  color: var(--text-soft);
  cursor: pointer;
}
.fred-switch-option:last-child { border-right: 0; }
.fred-switch-option:hover { background: var(--accent-soft); }
.fred-switch-option[aria-pressed="true"] {
  background: var(--accent-soft);
  color: var(--text);
  font-weight: 600;
}

.prompt-stages, .prompt-summary, .drawer-prompt .drawer-body > p { flex: none; }
.prompt-stages { margin: 10px 0; align-self: flex-start; }
.prompt-summary { margin: 0 0 12px; }
.prompt-blocks { flex: 1; min-height: 0; overflow-y: auto; }

.prompt-block {
  margin-bottom: 12px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

/* A therapist's own page is the thing they can act on, so it is the one that
   wears the accent. Everything else recedes: it is context, not a task. */
.prompt-block.prompt-page { border-left-color: var(--accent); }
.prompt-block.prompt-safety, .prompt-block.prompt-lock {
  border-left-color: var(--warn-border);
}

.prompt-block-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 7px 11px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}

.prompt-kind {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-soft);
}

.prompt-path { font-weight: 600; font-size: 13px; overflow-wrap: anywhere; }
.prompt-block-head .badge { margin-left: auto; }

/* Capped and scrollable per block: the whole prompt is longer than any drawer,
   and a long page must not bury the block after it. `pre-wrap` because these
   are hard-wrapped at 76 characters already — a horizontal scrollbar on every
   block would make the screen unreadable. */
.prompt-text {
  margin: 0;
  padding: 9px 11px;
  max-height: 30vh;
  overflow-y: auto;
  font-family: var(--font-mono, ui-monospace, "Cascadia Mono", "Consolas", monospace);
  font-size: 11.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  background: var(--surface);
  color: var(--text);
}

/* --- the comparison tab (board task 74 round two) ---------------------------
   ONE comparison surface, and it is `prism-ui`'s DiffView: an AI draft, the
   therapist's own unsaved typing and a colleague's arriving version are all read
   through the same component. Atlas drew its own before, twice over, and two
   diffs meant a therapist learning two grammars for the same idea.

   Everything below is either LAYOUT (which is Atlas's) or a token MAPPED onto
   Atlas's palette in this one place, as `prism-ui`'s README asks. Atlas's rules
   are unlayered and Prism's are in `@layer prism`, so these win without
   `!important` and without a specificity fight. */

.fred-compare-head { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.fred-compare-who { font-weight: 600; margin: 0; }

/* The comparison is older than the text in the editor. Not rebuilt under the
   therapist — that would void every resolution they had already made — so it is
   said, with the button beside it. */
.fred-compare-stale {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 6px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  background: var(--warn-bg);
}

/* No Russian could be made for the two other versions, so what is on screen is
   the English pair and every control that would act on a merge is disabled
   (board task 88). Its own rule rather than a borrowed `.fred-compare-stale`:
   they look alike and they say different things, and a class named after one
   caller is exactly the trap footgun 97 records. This one is a REFUSAL that has
   a way out, so it wears the danger surface and carries the retry. */
.fred-compare-degraded {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 6px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  background: var(--danger-soft);
}

/* The component fills the box it is given, and this is the box. Bounded so the
   actions below can never leave the screen: a decision the therapist cannot
   reach is worse than a comparison that has to be scrolled. */
.fred-compare-view .prism-diff-view {
  height: min(52vh, 460px);

  /* Fred's pages are PROSE, not code. Prism defaults to its mono token because
     most diffs are source; one line here is a whole paragraph a therapist
     wrote, and setting it in monospace makes their own writing look like
     somebody else's output. */
  --prism-diff-font-family: var(--font-body, system-ui, sans-serif);
  --prism-diff-font-size: 14px;
  --prism-diff-line-height: 24px;

  /* Atlas's palette, mapped once. The greens and reds Prism ships are fine in
     isolation and wrong beside Fred's sepia paper. */
  --prism-diff-add-bg: var(--accent-soft);
  --prism-diff-del-bg: var(--danger-soft);
  --prism-diff-conflict-ours-bg: var(--accent-soft);
  --prism-diff-conflict-theirs-bg: var(--warn-bg);
  --prism-diff-conflict-border: var(--warn-border);
}

/* FOOTGUN 93, MOVED HERE AND NOT DELETED. The rule it replaces read
   `.reconcile-diff .diff-del .diff-text { text-decoration: none; }` and it
   existed because Atlas's own diff struck removed lines through — correct when a
   `−` row is a line an AI draft proposes to REMOVE, and a lie in a comparison of
   two versions that BOTH exist, where it drew a colleague's paragraph as already
   condemned directly above a button offering to keep it. Every DOM assertion
   passed; only a screenshot showed it.

   `prism-ui` never strikes anything through, so today this rule changes nothing.
   It stays anyway, and pointed at the whole comparison surface rather than at
   one selector, because what it protects is not a Prism default — it is the
   CLAIM that inside this tab nothing is drawn as already lost. The next person
   to style `del`, or to add strikethrough to Fred's markdown, must not be able
   to reach in here without meeting this comment. `u` is excluded deliberately:
   underline is content a therapist typed, not a verdict on it. */
.fred-compare-view :not(u) { text-decoration-line: none; }

.fred-compare-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  margin-top: 10px;
}

/* --- one line of Fred's markdown, drawn as prose ----------------------------
   `views/fred/prose-line.js` renders the rows, so a therapist reads their own
   writing rather than `##` and `**`. The typography deliberately echoes the
   reading view: headings in the display face, the same accent — because this is
   the same page, being compared. */
.fred-prose { display: inline; }
:is(.fred-prose-h1, .fred-prose-h2, .fred-prose-h3, .fred-prose-h4) {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--accent-strong);
}
.fred-prose-h1 { font-size: 1.25em; }
.fred-prose-h2 { font-size: 1.15em; }
.fred-prose-h3 { font-size: 1.05em; }
.fred-prose-marker { color: var(--text-soft); margin-right: 0.5ch; }

/* The tab a colleague's version is waiting behind. A dot, not a colour change:
   the tab bar already carries state, and a second red thing in it reads as an
   error rather than as news. */
.tab.is-attention::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--warn-border);
  display: inline-block;
  margin-left: 6px;
  vertical-align: middle;
}

.fred-coedit-view { margin-left: auto; }

/* --- reading and writing look the SAME ------------------------------------------
   Board task 53. The reading view and the editing surface share every
   typographic rule, because "edit in place" is only true if pressing Edit does
   not move a single word. The one thing that changes is the paper: white to
   read, sepia to write on. Never split these two selectors. */
:is(.fred-read-body, .rt-surface) { font-size: 15px; max-width: 760px; min-height: 52vh; }
:is(.fred-read-body, .rt-surface) :is(h1, h2, h3, h4) {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--accent-strong);
  margin: 1.2em 0 0.4em;
}
:is(.fred-read-body, .rt-surface) h1 { font-size: 22px; }
:is(.fred-read-body, .rt-surface) h2 { font-size: 18px; }
:is(.fred-read-body, .rt-surface) :is(h3, h4) { font-size: 15.5px; }
:is(.fred-read-body, .rt-surface) > :first-child { margin-top: 0; }
:is(.fred-read-body, .rt-surface) p { margin: 0.6em 0; }
:is(.fred-read-body, .rt-surface) :is(ul, ol) { margin: 0.5em 0; padding-left: 22px; }
:is(.fred-read-body, .rt-surface) code {
  background: var(--surface-2);
  border-radius: 4px;
  padding: 0 4px;
  font-size: 0.92em;
}
.fred-read-body { line-height: 1.6; }

.fred-refs { max-width: 720px; }
.fred-ref-block { margin-bottom: 18px; }
.fred-ref-heading { font-size: 13px; margin: 0 0 8px; color: var(--text-soft); }

/* --- New-file dialog ---------------------------------------------------------------- */

.fred-new-form { display: block; }
.fred-folder-picker { display: flex; gap: 8px; margin: 0 0 16px; }

.fred-folder-pick {
  flex: 1;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text-soft);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 7px 6px;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.fred-folder-pick:hover { border-color: var(--f); color: var(--f); }
.fred-folder-pick.is-active { background: var(--f-soft); border-color: var(--f); color: var(--f); box-shadow: inset 0 0 0 1px var(--f); }

/* --- History drawer extras ------------------------------------------------------------ */

/* .tabs sets flex:1, which would stretch inside the drawer's flex column. */
.history-scope { flex: none; margin-bottom: 6px; }

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

   SYSTEM-INTENT -> "Responsive layout". Two breakpoints, one rule at both: a
   panel that no longer fits as a COLUMN becomes a panel in the drawer. It is
   the same drawer the history and the documents preview use (js/drawer.js);
   views/fred/panels.js does the moving, this file only decides the width at
   which it happens. Nothing is duplicated and nothing is hidden — the tree in
   the drawer is the same tree, with the mode tabs still inside it.

   1100 — the assistant leaves the grid; sidebar + editor stay side by side.
    720 — the file tree leaves too; the editor has the screen to itself. */

.fred-tree-toggle { display: none; } /* phone only — see below */

@media (max-width: 1100px) {
  .fred-grid, .fred-grid.assistant-collapsed { grid-template-columns: 276px minmax(0, 1fr); }

  /* The panel fills the drawer: its own card frame would be a second border
     inside the drawer's, and the drawer's × already collapses it. Its heading
     goes for the same reason — the drawer is already titled "Authoring
     assistant", and the two sat eight pixels apart saying it twice. What is
     left of the head is New conversation, kept right-aligned so the control
     does not move when the panel docks and undocks. */
  .drawer-assistant .drawer-body { padding: 0; }
  .drawer-assistant .assistant-collapse { display: none; }
  .drawer-assistant .assistant-title { display: none; }
  .drawer-assistant .assistant-head { padding-left: 12px; }
  .drawer-assistant .assistant-head .btn { margin-left: auto; }
  .drawer-assistant .assistant-panel {
    flex: 1;
    min-height: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  .drawer-assistant .assistant-thread { max-height: none; }
}

@media (max-width: 720px) {
  .fred-grid, .fred-grid.assistant-collapsed { grid-template-columns: minmax(0, 1fr); }
  .fred-tree-toggle { display: inline-flex; }

  /* Three controls and a title do not fit one 390px row in English and are not
     close in Russian, so the row wraps rather than clipping or scrolling. */
  .fred-topbar { flex-wrap: wrap; }
  .fred-topbar-actions { flex-wrap: wrap; }
  .fred-topbar .page-title {
    font-size: 19px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .drawer-tree .drawer-body { padding: 0; }
  .drawer-tree .fred-sidebar {
    flex: 1;
    min-height: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .fred-pane-body { padding: 0 0 16px; }
  .fred-pane, .locked-notice, .draft-notice { margin-left: 12px; margin-right: 12px; }
  .locked-notice, .draft-notice { margin-top: 12px; }
  .rt-toolbar { padding-left: 12px; padding-right: 12px; }
  .fred-file-head { padding: 10px 12px 8px; }
  .fred-empty { padding: 32px 20px; }
}

/* "No documents attached", where the chips would be. It is a real line rather
   than an empty row, because the empty row was invisible and a therapist asked
   the assistant about a book it had never been given (owner, 2026-08-21). Quiet
   enough to ignore while typing, present enough to answer "can it see my book?"
   without pressing anything. */
.assistant-none { display: inline-block; padding: 2px 0; line-height: 1.4; }
