/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* ---------------------------------------------------------------------------
 * Static-preview reflow guard (on-load layout stability)
 *
 * The document page server-renders a static preview into
 * `.doc-static-preview .ProseMirror` (see app/services/document_preview_html.rb
 * and app/frontend/pages/documents/show.tsx) using the SAME .milkdown/.ProseMirror
 * classes as the live Milkdown editor. ProseMirror's base stylesheets
 * (@milkdown/kit -> prosemirror-view + prosemirror-tables) ship as CSS imported
 * inside the editor island (app/frontend/editor/milkdown_editor.tsx). In a Vite
 * production build that CSS lands in the code-split `show-*.css` chunk, which is
 * INJECTED BY JS only after the editor chunk loads — a few hundred ms after first
 * paint. So the preview first paints with browser defaults (white-space: normal,
 * table-layout: auto) and then those rules retroactively restyle the shared
 * .ProseMirror, reflowing the preview: a markdown table flips auto -> fixed
 * (equal columns, cells wrap, ~+175px), and blockquotes/lists/paragraphs re-wrap
 * (normal -> break-spaces, ~+30px each). Measured on prod: table 497px -> 672px.
 *
 * Fix: replicate exactly the layout-affecting properties ProseMirror injects, in
 * THIS render-blocking Rails-pipeline stylesheet (served as the <link> in dev and
 * prod alike), so the preview's geometry is fully determined at first paint and
 * matches the editor's eventual state — no auto->fixed / normal->break-spaces jump.
 *
 * Scoped to .doc-static-preview so the live editor's own styling is untouched.
 * Keep these in sync with node_modules/@milkdown/prose/lib/view/style/prosemirror.css
 * and node_modules/@milkdown/prose/lib/tables/style/tables.css.
 * ------------------------------------------------------------------------- */

/* prosemirror-view base: text wrapping. Without this the preview wraps as
   white-space: normal and blockquote/list/paragraph lines grow when the
   editor's break-spaces is injected. */
.doc-static-preview .ProseMirror {
  word-wrap: break-word;
  white-space: break-spaces;
}

/* prosemirror-tables base: the big one. A markdown table defaults to
   table-layout: auto (content-sized columns) until the editor injects fixed +
   width:100%, which redistributes columns to equal widths, wraps cells, and
   grows the table ~175px. Pin the final geometry from first paint. */
.doc-static-preview .ProseMirror table {
  border-collapse: collapse;
  table-layout: fixed;
  width: 100%;
  overflow: hidden;
}

.doc-static-preview .ProseMirror td,
.doc-static-preview .ProseMirror th {
  vertical-align: top;
  box-sizing: border-box;
  position: relative;
}

.doc-static-preview .ProseMirror td:not([data-colwidth]),
.doc-static-preview .ProseMirror th:not([data-colwidth]) {
  min-width: var(--default-cell-min-width);
}

/* prosemirror-view base: list items are positioned for marker handling. */
.doc-static-preview .ProseMirror li {
  position: relative;
}

/* Fenced code is spatial content. Match the live editor before hydration so
   indentation and side-by-side annotations scroll locally instead of wrapping
   into misleading rows on narrow screens. */
:is(.milkdown, .doc-static-preview) .ProseMirror pre code {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  white-space: pre;
}

/* Shared by the server preview and the live node view. Controls are outside
   the editable <code> and are never part of the stored document. */
.milkdown .ProseMirror pre:has(.code-block-toolbar) {
  /* Breakout blocks cross the prose-width handle's invisible hit area. */
  z-index: 6;
}
.milkdown .ProseMirror pre:has(.code-block-destinations[open]) { z-index: 7; }
.milkdown .ProseMirror .code-block-toolbar {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 0.75rem;
  font: 0.75rem/1.5 var(--font-ui, sans-serif);
  white-space: normal;
  color: var(--ink-soft);
  user-select: none;
}
.milkdown .ProseMirror .code-block-toolbar[hidden],
.milkdown .ProseMirror .code-block-destinations[hidden] { display: none; }
.milkdown .ProseMirror .code-block-type,
.milkdown .ProseMirror .code-block-copy,
.milkdown .ProseMirror .code-block-destinations summary {
  min-height: 30px;
  padding: 0.2rem 0.4rem;
  border: 1px solid transparent;
  border-radius: 4px;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.milkdown .ProseMirror .code-block-type { margin-right: auto; max-width: 45%; }
.milkdown .ProseMirror .code-block-type:not(:disabled) { appearance: auto; }
.milkdown .ProseMirror .code-block-type:disabled { opacity: 1; cursor: default; appearance: none; }
@media (hover: none), (pointer: coarse) {
  .milkdown .ProseMirror .code-block-type { font-size: 1rem; }
}
.milkdown .ProseMirror .code-block-copy:hover,
.milkdown .ProseMirror .code-block-destinations summary:hover { color: var(--ink); border-color: var(--line); }
.milkdown .ProseMirror .code-block-toolbar :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.milkdown .ProseMirror .code-block-destinations summary { list-style: none; }
.milkdown .ProseMirror .code-block-destinations summary::-webkit-details-marker { display: none; }
.milkdown .ProseMirror .code-block-destination-list {
  position: absolute;
  z-index: 10;
  right: 0;
  top: 100%;
  min-width: 9rem;
  padding: 0.3rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface-raised, white);
  box-shadow: 0 4px 15px #0001;
}
.milkdown .ProseMirror .code-block-destination-list a { display: block; padding: 0.5rem; color: var(--ink); text-decoration: none; }
.milkdown .ProseMirror .code-block-destination-list a:hover { background: var(--code-bg); }
.milkdown .ProseMirror .code-block-destination-hint { max-width: 13rem; padding: 0.5rem; }
.milkdown .ProseMirror .code-block-status {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}
.milkdown .ProseMirror pre[data-language='prompt'] code {
  font-family: var(--font-ui, sans-serif);
  font-size: 1rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
 * Table-block typography — the single copy, serving BOTH the live editor and
 * the static preview (the preview wraps tables in the editor's
 * .milkdown-table-block/.table-wrapper structure; see DocumentPreviewHtml).
 * It lives here rather than in the code-split editor chunk because the
 * preview paints before any JS, and both layers must resolve identical
 * geometry from first paint. app/frontend/editor/table_block.css keeps only
 * the editing chrome (handles, popover, grips).
 *
 * Typography follows Rutter/Tschichold and Tailwind Typography's prose
 * tables: horizontal rules only (no vertical rules, no outer frame, no
 * zebra), smaller UI sans with tabular numerals, header weight instead of a
 * background fill.
 * ------------------------------------------------------------------------- */
:is(.milkdown, .doc-static-preview) .ProseMirror {
  --default-cell-min-width: 6ch;
}

:is(.milkdown, .doc-static-preview) .milkdown-table-block {
  display: block;
}

/* Scroll affordance: thin scrollbars where supported; on touch the cut-off
   last column is the (classic) signal. A static right-edge fade was
   considered and rejected — CSS can't tell overflowing wrappers from
   fitting ones, and fading a fully-visible table reads as a bug. */
:is(.milkdown, .doc-static-preview) .milkdown-table-block .table-wrapper {
  overflow-x: auto;
  max-width: 100%;
  scrollbar-width: thin;
}

:is(.milkdown, .doc-static-preview) .milkdown-table-block table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-ui);
  font-size: 0.875em;
  line-height: 1.45;
  font-variant-numeric: lining-nums tabular-nums;
}

:is(.milkdown, .doc-static-preview) .milkdown-table-block th,
:is(.milkdown, .doc-static-preview) .milkdown-table-block td {
  border: none;
  border-bottom: 1px solid var(--line);
  padding: 0.5em 0.75em;
  vertical-align: baseline;
}

/* Commonmarker emits <thead><tr><th> in the preview; the editor marks header
   rows with data-is-header. Style both shapes identically. */
:is(.milkdown, .doc-static-preview) .milkdown-table-block tr[data-is-header] th,
.doc-static-preview .milkdown-table-block thead th {
  font-weight: 600;
  border-bottom: 1px solid var(--ink-faint);
  vertical-align: bottom;
}

:is(.milkdown, .doc-static-preview) .milkdown-table-block th:first-child,
:is(.milkdown, .doc-static-preview) .milkdown-table-block td:first-child {
  padding-inline-start: 0;
}

:is(.milkdown, .doc-static-preview) .milkdown-table-block th:last-child,
:is(.milkdown, .doc-static-preview) .milkdown-table-block td:last-child {
  padding-inline-end: 0;
}

/* ---------------------------------------------------------------------------
 * Header presence-bar reserved lane (on-load layout stability)
 *
 * The document header's people cluster (.doc-header-people in
 * app/frontend/pages/documents/show.tsx) holds: PresenceBar · provenance
 * chip · identity chip. Human peers join via Yjs awareness over the websocket,
 * so they CANNOT be server-rendered — they fade in a beat after first paint.
 * Before this, the empty bar took zero width, so the first peer (0→N avatars +
 * "N here") widened the cluster and shoved the Edit/Share/⋯ controls left.
 *
 * Fix: reserve a fixed-width lane for .presence-bar in THIS render-blocking
 * Rails-pipeline stylesheet, so the lane's geometry is determined at first
 * paint. Avatars then appear WITHIN the lane (acceptable) instead of pushing
 * the neighbouring controls (a layout shift, not acceptable). The bar always
 * renders now (even empty, data-empty) so the lane exists from the first frame.
 *
 * The lane sits on the cluster's open LEFT edge — beside the header's flexible
 * middle space — so while empty it reads as ordinary whitespace instead of a
 * dead gap between the viewer's name and Share. Contents right-align so
 * arriving avatars hug the identity chip.
 *
 * Scoped to .presence-bar in the header; the editor body is untouched. The
 * Vite stylesheet (app/frontend/entrypoints/application.css) styles the bar's
 * internals (avatars, count) — these rules only pin the lane width.
 * ------------------------------------------------------------------------- */
.doc-header-people .presence-bar {
  /* Room for a couple of overlapping 28px avatars + the "N here" count, so a
   * small group fits without reflow; larger groups collapse into the +N
   * overflow chip, which also stays within the lane. */
  min-width: 7.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.45rem;
}

/* The empty bar reserves its lane but shows nothing — no stray gap from the
 * inherited flex gap on a childless box. */
.doc-header-people .presence-bar[data-empty] {
  gap: 0;
}

/* Compact (mobile) header: 24px avatars, max 3 — a tighter lane. */
.doc-header-people .presence-bar--compact {
  min-width: 5rem;
}
