/* Text direction in the staff chat, without a fork of LibreChat.
 *
 * LibreChat sets ONE direction for the whole page from the interface language
 * (`<html dir="rtl">` in Farsi), and every message inherits it. Staff answers mix
 * Farsi and English, so that is wrong for every English paragraph, and code read
 * right to left is unreadable.
 *
 * `unicode-bidi: plaintext` gives each paragraph the direction of its own first
 * strong letter (what `dir="auto"` does per element), and `text-align: start`
 * aligns it to that side. A Farsi paragraph that starts with an English word
 * therefore reads left to right; `dir="auto"` has the same limit. A list keeps
 * its markers on the page's side; only the item text follows its own direction.
 *
 * The second half mirrors interface parts that stay left to right on a Farsi
 * page. Those rules start with `[dir="rtl"]`, so an English page is untouched.
 * One part is left to LibreChat, because its menu library computes the position
 * on each open and CSS cannot move it: the model sub-menu opens to the right
 * (and its arrow follows). The scroll-to-bottom button stays on the left on
 * purpose: LibreChat puts it at the column's logical end, over the send button.
 * There it covers the start of code lines; on the right it would cover the start
 * of Farsi lines, which are most of the text.
 *
 * The selectors are LibreChat's own class names (v0.8.8). An upgrade that renames
 * them makes this file match nothing: the chat looks as it did before, it does
 * not break. Repeat the text-direction checks after each upgrade.
 *
 * docker-compose.yml mounts this file into LibreChat's assets and links it from
 * the page at start.
 */

/* A message (a person's own text sits in `.markdown` directly) and each block of an answer. */
.markdown,
.markdown :is(p, li, h1, h2, h3, h4, h5, h6, blockquote) {
  unicode-bidi: plaintext;
  text-align: start;
}

/* A table cell keeps the word order of its own text, but a column aligns to one
 * side: the table's. `start` would follow each cell's first letter, so an English
 * cell sat on the left of a Farsi column. */
.markdown :is(th, td) {
  unicode-bidi: plaintext;
  text-align: match-parent;
}

/* The message box: each line takes the direction of what is typed on it. */
#prompt-textarea {
  unicode-bidi: plaintext;
  text-align: start;
}

/* An empty line has no strong letter, and `plaintext` then falls back to left to
 * right: on a Farsi page the caret and the placeholder sat on the left. While the
 * placeholder shows (LibreChat always sets one), the box takes the page's side.
 * The box carries its own `dir` from LibreChat's "chat direction" setting (`ltr`
 * by default, apart from the interface language), so `isolate` alone kept it on
 * the left; the direction must be set too. */
[dir="rtl"] #prompt-textarea:placeholder-shown {
  direction: rtl;
  unicode-bidi: isolate;
}

/* Code is left to right in every language: a block (in an answer or a tool call)... */
.markdown pre,
.markdown pre *,
pre:has(> code.hljs),
pre > code.hljs {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: left;
}

/* ...and a span inside a sentence, kept as one left-to-right run. */
.markdown :not(pre) > code {
  direction: ltr;
  unicode-bidi: isolate;
}

/* The chat list. Its list library puts `direction: ltr` inline on the list, so
 * only `!important` wins. Pinned chats are not in that list and were right. */
[dir="rtl"] .ReactVirtualized__List {
  direction: rtl !important;
}

/* Menus (a chat's … menu, the model selector) render outside the page's
 * layout and read left to right; set their direction explicitly. A menu with
 * a search box is a dialog, not a menu, to the menu library. Their icons keep
 * a right margin, which belongs between icon and label on the left. */
[dir="rtl"] :is([role="menu"], .popover-ui, [role="dialog"]:has(.peer[role="combobox"])) {
  direction: rtl;
}

[dir="rtl"] :is([role="menu"], .popover-ui) .mr-2 {
  margin-right: 0;
  margin-left: 0.5rem;
}

[dir="rtl"] :is([role="menu"], .popover-ui) kbd.ml-auto {
  margin-left: 0;
  margin-right: auto;
}

/* The model selector's search box: the text follows what is typed, and the
 * floating label sits on the right, also after it moves up over the border. */
[dir="rtl"] .peer[role="combobox"] {
  unicode-bidi: plaintext;
  text-align: start;
}

[dir="rtl"] .peer[role="combobox"] ~ label {
  left: auto;
  right: 0.625rem;
}

[dir="rtl"] .peer[role="combobox"]:not(:placeholder-shown) ~ label {
  left: auto;
  right: 0.375rem;
}

/* The conversation navigator: the bar moves to the left edge. Its hover preview
 * is a fixed tooltip whose inline `right` a script sets to the bar column's left
 * edge plus 8px (the column is `w-14`, 56px). `translate` composes with the
 * inline `transform`, so a shift of the preview's own width plus 56px plus two
 * 8px gaps puts it 8px to the right of the column. */
[dir="rtl"] nav[aria-keyshortcuts="Shift+Alt+M"] {
  right: auto;
  left: 0.5rem;
}

[dir="rtl"] body > [role="tooltip"]:has(> p.line-clamp-3) {
  translate: calc(100% + 72px) 0;
}

/* Modal titles align to the right. */
[dir="rtl"] [role="dialog"] h2 {
  text-align: start;
}

/* Tables: LibreChat draws each cell's left border, the last cell's right border
 * and the outer corners by physical side. Mirror them. The resets come first, so
 * a one-column table keeps both of its top and both of its bottom corners. */
[dir="rtl"] .markdown :is(th, td) {
  border-left-width: 0;
  border-right-width: 1px;
}

[dir="rtl"] .markdown :is(th, td):last-child {
  border-left-width: 1px;
}

[dir="rtl"] .markdown th:first-child,
[dir="rtl"] .markdown tbody tr:last-child td:first-child {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

[dir="rtl"] .markdown th:last-child,
[dir="rtl"] .markdown tbody tr:last-child td:last-child {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

[dir="rtl"] .markdown th:first-child {
  border-top-right-radius: 0.75rem;
}

[dir="rtl"] .markdown th:last-child {
  border-top-left-radius: 0.75rem;
}

[dir="rtl"] .markdown tbody tr:last-child td:first-child {
  border-bottom-right-radius: 0.75rem;
}

[dir="rtl"] .markdown tbody tr:last-child td:last-child {
  border-bottom-left-radius: 0.75rem;
}
