

/*
 * MarkdownEditor — textarea-based markdown composer with an Edit /
 * Preview tab. Visually thin (no border, transparent bg) so callers
 * can wrap it in whatever surface they want.
 */

/* Wrap = a single bordered field. Tabs sit inline at the top, the
   textarea (or preview) fills the middle, and the toolbar + slot
   for consumer actions sit on a thin top-border separator at the
   bottom. focus-within deepens the border to ink and adds a soft
   ring so the field reads as the active editing surface. The
   `.is-display-post` variant strips this chrome (article body is
   flush with title above + post-body below). */
.md-editor-wrap {
  position: relative;
  display: block;
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  outline: none;
  transition: border-color 120ms ease, box-shadow 120ms ease;
  /* The topbar is position:sticky (top:0, ~56px tall + 1px border).
     Without scroll-margin-top, scrollIntoView({ block: 'start' })
     puts the wrap top at viewport top — hidden behind the topbar
     so the Edit/Preview tabs disappear. Reserve topbar height as
     scroll margin so the wrap parks just BELOW the topbar instead. */
  scroll-margin-top: 64px;
}
/* Focus is just a one-step border darken — no ring. The composer
   is already a large bordered block; a 3px shadow on top reads as
   a "modal-ish" interruption. The textarea cursor + caret are the
   primary affordance that the editor is active. */
.md-editor-wrap:focus-within {
  border-color: var(--ink-dim);
}

/* ─── Edit / Preview tabs ─────────────────────────────────────────
   Inline at the top of the field — no full-width background band.
   Active tab gets a light pill background (rule-soft); inactive
   tabs are quiet text. */

.md-tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 8px 10px 0;
  background: transparent;
}

.md-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  /* Cancel framework `<button>` height/min-height/line-height so
     the tab sizes to its own padding. Without these the tab
     inherits the framework's button-height (36px) and reads as
     a chunky boxed button rather than a tight tab chip. */
  height: auto;
  min-height: 0;
  line-height: 1;
  padding: 6px 10px;
  background: transparent;
  border: 0;
  color: var(--ink-dim);
  cursor: pointer;
  border-radius: 6px;
  letter-spacing: 0.01em;
  transition: color 100ms, background 100ms;
}
.md-tab:hover {
  color: var(--ink-soft);
  background: transparent;
  border-color: transparent;
}
.md-tab.is-active {
  color: var(--ink);
  background: var(--rule-soft);
}
.md-tab:active {
  background: var(--rule-soft);
  border-color: transparent;
  transform: none;
}
.md-tab:focus,
.md-tab:focus-visible {
  outline: none;
  box-shadow: none;
}

/* Single shortcut hint, right-anchored on the tab bar. Matches the
   topbar palette's kbd-badge treatment: two compact <kbd> pills
   with the modifier glyph + key, then a quiet "to toggle" label. */
.md-tabs-hint {
  margin-left: auto;
  margin-right: 0.5rem;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-family: var(--font-sans);
  font-size: 0.6875rem;
  color: var(--ink-faint);
}

.md-kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 0.3125rem;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  color: var(--ink-soft);
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 4px;
  line-height: 1;
}

.md-tabs-hint-label {
  margin-left: 0.0625rem;
}

/* ─── Bottom action row ───────────────────────────────────────────
   Subtle top-border separator between the textarea and the
   tools/actions. Tools (</>, link, timestamp) on the left; the
   consumer's slot (Post / Cancel / Save) sits on the right. */
.md-footer {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 8px 10px 8px 8px;
  background: transparent;
  border-top: 1px solid var(--rule-soft);
}

.md-footer-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  margin-left: auto;
}

/* Toolbar chips (</> code, link, timestamp, etc). Minimal icon
   buttons: transparent, no border. Hover lifts to light-gray bg
   so the affordance reads on tap without competing with the
   textarea. */
.md-toolbar-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  box-sizing: border-box;
  width: 30px;
  height: 30px;
  padding: 0;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-dim);
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  transition: color 100ms, background 100ms;
}

.md-toolbar-chip:hover {
  color: var(--ink);
  background: var(--rule-soft);
}

.md-toolbar-chip:active {
  background: var(--rule);
}

/* SVG inside any toolbar chip — center the visual via flex
   (already inline-flex on parent) and force display:block so
   browser default inline alignment doesn't pull baseline. */
.md-toolbar-chip svg {
  display: block;
}

/* Disabled state — used by the timestamp chip when there's no
   video context on the page. Visible but muted so users still know
   the affordance exists. */
.md-toolbar-chip.is-disabled,
.md-toolbar-chip[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}
.md-toolbar-chip.is-disabled:hover,
.md-toolbar-chip[disabled]:hover {
  background: transparent;
  color: var(--ink-dim);
}

/* Footer chips packed as a button group with a small gap. */
.md-footer .md-toolbar-chip + .md-toolbar-chip {
  margin-left: 1px;
}

/* Slot anchor — Post / Cancel / Save sits at the right edge. */
.md-footer-actions {
  margin-left: auto;
}

@media (max-width: 480px) {
  .md-tabs    { padding: 6px 8px 0; }
  .md-footer  { padding: 6px 8px 6px 6px; }
  .md-toolbar-chip { width: 28px; height: 28px; }
}

/* ─── Edit surface (textarea) ─────────────────────────────────────
   Plain mono textarea. We auto-grow it on input via JS; the CSS
   provides the floor (min-height) and the comfortable typography. */

/* Both surfaces share the same min-height via --md-min-height so
   toggling Edit ↔ Preview doesn't change the panel size. Consumers
   set --md-min-height on .md-editor-wrap (or any ancestor) to size
   the editor for their context (top-of-thread composer is roomy,
   inline reply is small, post body is tall). */
.md-textarea {
  display: block;
  width: 100%;
  min-height: var(--md-min-height, 0);
  /* Typography + padding are overridable via CSS vars so each
     consumer can match the textarea to its OWN published-view
     style AND ensure the textarea's text + Preview's prose land
     at exactly the same coordinates (left edge, line-height, font
     size). Defaults match the comment display (.cmt-body). */
  font-family: var(--md-textarea-font, var(--font-sans));
  font-size: var(--md-textarea-size, 0.875rem);
  line-height: var(--md-textarea-line-height, 1.55);
  padding: var(--md-pad-y, 0.625rem) var(--md-pad-x, 0.875rem);
  color: var(--ink);
  background: var(--bg);                    /* always white */
  border: none;
  outline: none;
  margin: 0;
  resize: none;
  overflow: hidden;
  caret-color: var(--ink);
  -webkit-text-size-adjust: 100%;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.md-textarea::placeholder {
  color: var(--ink-dim);
}

/* ─── Preview surface ────────────────────────────────────────────
   Renders the same HTML the published page renders. Inherits the
   site's prose styling from app/shared/styles/syntax-highlight.css and
   anywhere else a .post-body chain lives. We use a stable class
   name (.md-preview) plus the published-output class (.post-body)
   on the inner element via render-post.ts's wrapper, so syntax-
   highlight and prose typography Just Work. */

.md-preview {
  display: block;
  width: 100%;
  min-height: var(--md-min-height, 0);  /* match .md-textarea so Edit↔Preview doesn't jump in size */
  font-family: var(--font-sans);
  font-size: 1em;
  line-height: 1.6;
  color: var(--ink);
  word-wrap: break-word;
  background: var(--bg);
  padding: 0.875rem 1rem;
}

.md-preview > :first-child { margin-top: 0; }
.md-preview > :last-child  { margin-bottom: 0; }

/* Block-level prose styling for the rendered preview. Mirrors the
   .post-body styling in posts/show so a Preview-tab render matches
   the published page. Token coloring inside `pre.code-fence` comes
   from app/shared/styles/syntax-highlight.css (loaded site-wide). */

.md-preview h1, .md-preview h2, .md-preview h3,
.md-preview h4, .md-preview h5, .md-preview h6 {
  font-family: var(--font-sans);
  font-weight: var(--font-semibold);
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: 1.5rem 0 0.625rem;
  line-height: 1.25;
}
.md-preview h1 { font-size: 1.625rem; }
.md-preview h2 { font-size: 1.375rem; }
.md-preview h3 { font-size: 1.125rem; }

.md-preview p {
  margin: 0 0 1rem;
}

.md-preview a {
  color: var(--accent-deep);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.md-preview a:hover { color: var(--accent); }

.md-preview ul, .md-preview ol {
  margin: 0.5rem 0 1rem;
  padding-left: 1.5rem;
}
.md-preview li { margin: 0.25rem 0; }

.md-preview blockquote {
  border-left: 3px solid var(--rule);
  padding: 0.25rem 0 0.25rem 1rem;
  color: var(--ink-soft);
  margin: 1.25rem 0;
  font-style: italic;
}

/* Inline `code` — light pill, JetBrains Mono. */
.md-preview :not(pre) > code {
  font-family: var(--font-mono);
  font-size: 0.875rem;
  background: var(--bg-panel);
  padding: 0.0625rem 0.375rem;
  border-radius: 3px;
  color: var(--ink);
}

/* Fenced code block — dark terminal surface. The token coloring
   inside is provided by app/shared/styles/syntax-highlight.css's
   `pre.code-fence .tok-*` rules. We control the BLOCK chrome here. */
.md-preview pre.code-fence {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  line-height: 1.6;
  /* bg + fg come from app/shared/styles/syntax-highlight.css (VSCode Dark+). */
  padding: 1rem 1.25rem;
  border-radius: var(--radius-lg, 8px);
  overflow-x: auto;
  margin: 1.25rem 0;
}
.md-preview pre.code-fence code {
  background: transparent;
  padding: 0;
  color: inherit;
  font-size: inherit;
}

.md-preview hr {
  border: none;
  border-top: 1px solid var(--rule);
  margin: 1.5rem 0;
}

.md-preview img {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius-md);
}

.md-preview table {
  width: 100%;
  border-collapse: collapse;
  margin: 1rem 0;
  font-size: 0.875rem;
}
.md-preview th, .md-preview td {
  border-bottom: 1px solid var(--rule-soft);
  padding: 0.4375rem 0.625rem;
  text-align: left;
}
.md-preview th { font-weight: var(--font-semibold); }

/* Display-toggle: when the wrap has .is-preview, swap the textarea
   for the preview surface. The toolbar STAYS visible (just dimmed
   + non-interactive) so the chrome feels stable when toggling
   modes — same panel anatomy on both sides, just the writing
   surface changes. */
.md-editor-wrap                 .md-preview  { display: none; }
.md-editor-wrap.is-preview      .md-preview  { display: block; }
.md-editor-wrap.is-preview      .md-textarea { display: none; }
.md-editor-wrap.is-preview      .md-toolbar  {
  opacity: 0.4;
  pointer-events: none;
  user-select: none;
}

/* ─── Display variants ───────────────────────────────────────────
   'comment' (default) keeps the bordered-field chrome from
   .md-editor-wrap above. 'post' is the article body composer:
   borderless and flush so body text sits at the same x as the
   .quiet-title above and the published .post-body below. The
   tabs/footer keep their inline layout but the page chrome
   (editor toolbar, sticky band) provides the visible frame. */
.md-editor-wrap.is-display-post {
  --md-textarea-size:        1rem;
  --md-textarea-line-height: 1.7;
  --md-pad-x: 0;
  --md-pad-y: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
}
.md-editor-wrap.is-display-post:focus-within {
  border-color: transparent;
  box-shadow: none;
}
.md-editor-wrap.is-display-post .md-tabs   { padding-left: 0; padding-right: 0; }
.md-editor-wrap.is-display-post .md-footer { padding-left: 0; padding-right: 0; border-top-color: transparent; }

/* ─── @ mention popover ───────────────────────────────────────────
   Floating list anchored above (or below, when above doesn't fit)
   the textarea. position:fixed + JS-set top/left so the popover
   escapes any ancestor overflow:hidden / overflow:clip context —
   the thread-composer wraps its children with overflow:hidden to
   clip rounded corners, which would otherwise clip our popover.
   We don't measure caret position; the popover anchors to the
   textarea's bounding box like Slack/Discord/Linear do. */
.md-mention-pop {
  /* position:fixed escapes ancestor overflow:hidden contexts. JS
     positions it in viewport coords from the textarea caret (mirror-
     div trick), with a fallback to "below editor wrap" if caret
     coords can't be measured. */
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
  /* Compact autocomplete-style float: narrow enough that the rest
     of the line (and any text below the caret) stays visible while
     the user is mid-mention. Mobile gets the tightest cap. */
  min-width: 240px;
  max-width: min(340px, calc(100vw - 1rem));
  max-height: 240px;
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md, 6px);
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12), 0 2px 6px rgba(15, 23, 42, 0.06);
  padding: 0.25rem;
}

@media (max-width: 480px) {
  .md-mention-pop {
    min-width: 220px;
    max-width: min(280px, calc(100vw - 1rem));
    max-height: 200px;
  }
}

/* The popover's parent (.md-editor-wrap) needs position:relative so
   `position: absolute` on the popover anchors to the wrap. The
   existing rule already sets position: relative on .md-editor-wrap. */

/* Row wraps the primary picker button + an optional "+ m:ss" time
   chip. Hover/selected styling sits on the row so both the main
   button and the timestamp chip share the highlight. The
   selected-state left accent bar is rendered as a ::before so it
   reaches edge-to-edge — an inset box-shadow on a rounded row
   gets clipped at the top/bottom corners and reads as broken. */
.md-mention-row {
  position: relative;
  display: flex;
  align-items: stretch;
  border-radius: var(--radius-sm, 4px);
  transition: background 60ms;
}

.md-mention-row:hover,
.md-mention-row.is-selected {
  background: var(--bg-soft);
}

.md-mention-row.is-selected::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2px;
  background: var(--accent);
  border-top-left-radius: var(--radius-sm, 4px);
  border-bottom-left-radius: var(--radius-sm, 4px);
}

/* The primary picker button — fills most of the row width. */
.md-mention-pick {
  flex: 1;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: 0.5rem;
  padding: 6px 10px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm, 4px);
  cursor: pointer;
  text-align: left;
  font-family: var(--font-sans);
  font-size: 13.5px;
  color: var(--ink);
}

/* Timestamp chip on video-post rows. Mono font + accent color so it
   reads as a quick action button distinct from the main picker. */
.md-mention-time {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  padding: 0 10px;
  margin: 4px 4px 4px 0;
  font-family: var(--font-sans);
  font-size: 11.5px;
  color: var(--accent-deep);
  background: var(--accent-soft);
  border: none;
  border-radius: var(--radius-sm, 4px);
  cursor: pointer;
  white-space: nowrap;
  transition: background 60ms;
}

.md-mention-time:hover {
  background: #d6e6f7;
}

/* "Open profile" shortcut on user rows. Subtle until hovered; opens
   the user page in a new tab. Sits at the right edge of the row so
   tapping the main button (left) inserts the mention while a tap on
   this corner navigates to the profile. */
.md-mention-open {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  margin: 4px 4px 4px 0;
  border-radius: var(--radius-sm, 4px);
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--ink-dim);
  text-decoration: none;
  cursor: pointer;
  transition: background 60ms, color 60ms;
}

.md-mention-open:hover {
  background: var(--bg-panel);
  color: var(--accent-deep);
}

.md-mention-label {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 220px;
}

.md-mention-detail {
  font-size: 12px;
  color: var(--ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.md-mention-kind {
  font-family: var(--font-sans);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  color: var(--ink-dim);
  flex-shrink: 0;
}

.md-mention-row.md-mention-user .md-mention-kind { color: #2f855a; }
.md-mention-row.md-mention-post .md-mention-kind { color: #4f7fd1; }
/* Override post chip when this is a video post (we surface "video"
   as the kind label rather than "post"). */
.md-mention-row.md-mention-post:has(.md-mention-kind:not(:empty))
  .md-mention-kind:where([class*=" "], [class^=" "]) { /* noop selector */ }
