/* Fhellow tone overlay for LibreChat: a warm neutral palette, no fork.
 *
 * LibreChat themes in two layers: semantic tokens (--surface-*, --text-*,
 * --border-*) that all resolve to a primitive ramp (--white, --gray-20 …
 * --gray-900) defined on :root. Overriding the ~14 primitives therefore
 * restyles every surface, including ones this file never names. That is why
 * it is a handful of lines instead of the 35-token semantic list, and why a new
 * upstream surface inherits the tone instead of appearing stark white.
 *
 * The lightness steps of the upstream ramp are preserved, so every existing
 * text-on-surface contrast pair keeps its ratio; only the hue moves, from a
 * cool grey to a warm neutral.
 *
 * Loaded by a <link> that generate_frontend_index.py injects into a copy of the
 * image's own index.html. Nothing in LibreChat's source is modified.
 */

/* ============================================================================
   Fhellow brand: NAKWAN (낙관 · the seal) — Korean legal-heritage identity.
   Hanji-paper warmth, 먹 (ink) black, and 인주 (seal) red as the one assertive
   accent. Celadon + ochre are available as secondary accents. See branding board.
   ============================================================================ */
/* Keep vertical overscroll inside the app and its message viewport. */
html, body, #root, .scrollbar-gutter-stable {
  overscroll-behavior-y: none;
}

:root {
  /* Anchors: hanji paper + 먹 ink. */
  --fh-paper: #f1e9d9;   /* hanji */
  --fh-ink: #14110d;     /* 먹 ink */

  /* Warm hanji -> ink ramp (same lightness steps as upstream's cool ramp, so
     every text-on-surface contrast pair keeps its ratio; only the hue moves). */
  --white: #ffffff;      /* cards, dialogs, composer — raised white surfaces */
  --gray-20: #f3efe8;
  --gray-50: #efeae0;    /* sidebar / subtle surface (warm gray) */
  --gray-100: #e8e2d6;
  --gray-200: #ddd6c8;   /* border-light */
  --gray-300: #cdc4b2;   /* border-medium */
  --gray-400: #9a8d70;
  --gray-500: #5f5748;
  --gray-600: #454034;
  --gray-700: #302c24;
  --gray-800: #211e18;
  --gray-850: #1a1712;
  --gray-900: var(--fh-ink);

  /* Second neutral set, warmed to match. */
  --gizmo-gray-500: #6b6250;
  --gizmo-gray-600: #514a3c;
  --gizmo-gray-950: #1a1712;

  /* Accent = 인주 seal red. Replaces LibreChat's violet everywhere. */
  --fh-clay: #b23127;
  --brand-purple: var(--fh-clay);

  /* Secondary brand accents (used by a few Fhellow components). */
  --fh-celadon: #5e7e6e;
  --fh-ochre: #a8823c;

  --fh-radius: 0.75rem;
}

/* Hybrid surfaces: a warm off-white background/thread (subtle hanji warmth) with
   white cards/dialogs and a warm-gray sidebar, so the UI has real depth instead of
   one flat beige. Sidebar = --surface-secondary = --gray-50 (#efeae0) via the ramp. */
html {
  --surface-chat: #fbf9f4;
  --surface-primary: #fbf9f4;
  --header-primary: #fbf9f4;
  --presentation: #fbf9f4;
  --surface-dialog: #ffffff;
}

/* Dark side: warm brown-black rather than blue-black, keeping the hanji/ink feel. */
.dark {
  --surface-chat: #241f18;
  --surface-primary: #1c1813;
  --presentation: #1c1813;
  --header-primary: #1c1813;
}

/* Dark-mode modals use bg-surface-primary, which is nearly the page colour, so a
   dialog (e.g. create-project) blends into the backdrop. Lift it off with a
   visible border, a slightly elevated warm surface, and a deeper shadow. Light
   mode is unaffected — there dialogs are already white via --surface-dialog. */
.dark [role="dialog"] {
  background-color: #2a241c;
  border: 1px solid var(--border-heavy);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.6);
}

/* Composer and message cards: a touch more radius, a lighter border. Scoped to
   the token so it cannot fight upstream's utility classes on specificity. */
form textarea,
form [class*="rounded"] {
  border-radius: var(--fh-radius);
}

/* Send is an ACTION, so it uses celadon ("go"), not the seal red — red is reserved
   for identity (avatar, favicon, citation marks) so it never reads as "danger". */
button[data-testid="send-button"]:not(:disabled) {
  background-color: var(--fh-celadon);
  border-color: var(--fh-celadon);
  color: #ffffff;
}

button[data-testid="send-button"]:not(:disabled):hover {
  filter: brightness(0.94);
}

/* Reduce the cool blue in focus rings so they sit in the same family. */
:root {
  --ring: var(--gray-400);
  --ring-primary: var(--gray-500);
}

/* No web font ships with Fhellow (licensed faces cannot be bundled, and the
   artifact CSP blocks font CDNs anyway), so the stack stays system-native with
   Korean coverage. Only the palette's warmth is matched: no other product's
   typeface is imitated, and no other product's mark appears anywhere. */
:root {
  --fh-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Apple SD Gothic Neo",
    "Pretendard", "Noto Sans KR", "Malgun Gothic", sans-serif;
}

body {
  font-family: var(--fh-sans);
}

/* --- Fhellow: hide scoped-out composer buttons (MCP only) ---
   Attach files is KEPT — document upload is core to the legal workflow (per the
   Aug 26 meeting: keep account, chat history, document attachment). MCP is out of scope.
   The *=MCP catch-all hides any MCP control (MCP Servers, MCP Settings, …) in any
   state, since MCP is entirely out of scope for Fhellow. */
[aria-label="MCP Servers"],
[aria-label*="MCP" i],
[aria-label*="mcp" i] {
  display: none !important;
}

/* --- Fhellow: hide the footer (LibreChat version + "Every AI for Everyone" + links) ---
   The footer div carries role="contentinfo" (stable ARIA landmark). CUSTOM_FOOTER
   can't blank it (LibreChat strips empty values), so we hide the element. */
div[role="contentinfo"] {
  display: none !important;
}

/* --- Fhellow: hide the Tools dropdown button in the composer --- */
#tools-dropdown-button,
[aria-label="Tools Options"] {
  display: none !important;
}

/* --- Fhellow: hide left-sidebar controls (per request) ---
   Bookmarks (sidebar nav) and the sidebar "Attach Files" entry. Scoped by their
   exact aria-labels so the COMPOSER paperclip — "Attach File Options" /
   #attach-file-menu-button — is unaffected and document attachment still works. */
[aria-label="Bookmarks"],
#bookmark-nav-menu-button,
[aria-label="Attach Files"],
[aria-label="파일 첨부"] {   /* ko-KR localizes this aria-label; the English match above misses it */
  display: none !important;
}

/* --- Fhellow: hide the "Temporary Chat" toggle (top-right of the header) --- */
[aria-label="Temporary Chat"] {
  display: none !important;
}

/* --- Fhellow: remove whole Settings tabs (per S5 wireframe, red-dashed) ---
   Chat, Speech, and Data controls are cut entirely. Account keeps profile and
   deletion; Security and General's direction are removed by patch_upstream.py. The settings
   dialog is a Radix Tabs group; each trigger's id ends with `-trigger-<value>`
   and each panel's with `-content-<value>`, where value is the SettingsTabValues
   enum (chat, speech, data) — never localized. Matching the id suffix + role
   keeps this locale-independent (ko-KR translates the LABEL text only). */
[role="tab"][id$="-trigger-chat"],
[role="tab"][id$="-trigger-speech"],
[role="tab"][id$="-trigger-data"],
[role="tabpanel"][id$="-content-chat"],
[role="tabpanel"][id$="-content-speech"],
[role="tabpanel"][id$="-content-data"] {
  display: none !important;
}

/* Stock previews keep the registry. The pinned Settings panel wraps both tabs
   and search in vertical Tabs; control anchors select only removed rows. */
[role="dialog"] [class~="md:w-[900px]"] > [data-orientation="vertical"] section:has(button[aria-controls="two-factor-authentication-dialog"], button[aria-label="Manage Backup Codes"]),
[role="dialog"] [class~="md:w-[900px]"] > [data-orientation="vertical"] .px-4.py-3:has(#chat-direction-label, button[aria-controls="two-factor-authentication-dialog"], button[aria-label="Manage Backup Codes"]) {
  display: none !important;
}

/* Generic hide utility used by the enhancer. */
.fh-hide {
  display: none !important;
}

/* Hide LibreChat's Temporary Chat toggle. Fhellow conversations are always saved
   (encrypted), so an unsaved/ephemeral chat mode doesn't apply. Keyed off the
   stable Lucide icon class, not translated text (ko-KR safe). The matching
   "Temporary Chat by default" setting lives in the already-hidden Chat tab. */
button:has(svg.lucide-message-circle-dashed) {
  display: none !important;
}

/* Hide LibreChat's Bookmark(s) control. The Radix BookmarkIcon carries no stable
   class, so match the path's `d`; hide the interactive element wrapping it. */
button:has(svg path[d^="M3 2.5C3 2.22386"]),
a:has(svg path[d^="M3 2.5C3 2.22386"]),
[role="menuitem"]:has(svg path[d^="M3 2.5C3 2.22386"]),
[role="button"]:has(svg path[d^="M3 2.5C3 2.22386"]) {
  display: none !important;
}

/* The pinned chat constructors emit the seal before greeting animation starts. */
svg.fh-chat-brand[data-fhellow-brand-context="landing"] {
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
}
@media (min-width: 640px) {
  svg.fh-chat-brand[data-fhellow-brand-context="landing"] {
    width: 2.25rem;
    height: 2.25rem;
  }
}
/* Fhellow: the seal replaces LibreChat's greeting icon, which LibreChat wraps in a
   white `rounded-full` frame whose faint ring is a `shadow-stroke` box-shadow drawn
   on the wrapper's ::after. Our mark is square, so clear the frame's fill/shadow and
   remove the ::after stroke — only the seal shows. */
.shadow-stroke:has(> svg.fh-chat-brand[data-fhellow-brand-context="landing"]) {
  background: transparent !important;
  box-shadow: none !important;
  border: 0 !important;
}
.shadow-stroke:has(> svg.fh-chat-brand[data-fhellow-brand-context="landing"])::after {
  content: none !important;
  box-shadow: none !important;
}

/* --- Fhellow: hide the Export (options) button, top-right of a conversation --- */
#export-menu-button,
[aria-label="Export options"] {
  display: none !important;
}

/* --- Fhellow: chat-bubble layout — user's messages RIGHT, Fhellow's LEFT ---
   Each message turn carries `.user-turn` or `.agent-turn`. We right-align the
   user turn and wrap its text in a clay-tinted bubble; Fhellow's stays left. */
/* The user message is a right-packed block: [avatar][name] then the bubble.
   We shrink the user's content column and right-justify the row, so the avatar
   stays LEFT of the name and the whole group hugs the right edge. */
/* Match the message row by the *presence* of an aria-label, not its text — the
   ko-KR locale localizes "Message from …" so an English-text selector misses. */
[aria-label]:has(> .user-turn) {
  justify-content: flex-end;
}
[aria-label]:has(> .user-turn) > .user-turn {
  width: auto !important;
  max-width: 82%;
}
.user-turn .markdown.message-content {
  width: fit-content;
  max-width: 100%;
  padding: 0.5rem 0.95rem;
  border-radius: 1.15rem 1.15rem 0.35rem 1.15rem;
  background: var(--gray-100);
}
.dark .user-turn .markdown.message-content {
  background: var(--gray-800);
}

/* --- Fhellow: the 출처 block, moved below the answer ---
   fhellow-sources.js finds the citations whose link goes to MOLEG / law.go.kr,
   copies each one whole into a `.fh-sources` block after the message body, and
   hides the paragraph it came from. The verifiable source is the product's
   trust story, so it gets real UI weight - and a citation is only verifiable
   while its text and its link stay on the same line. */

/* A citation that moved into the box, and the "---" + "출처" heading once
   nothing is left under it (JS adds this class; React re-renders drop it and
   the next scan puts it back). */
.fh-src-line-hidden,
.fh-src-inline-hidden {
  display: none !important;
}

.fh-sources {
  margin: 0.65rem 0 0.15rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--gray-300);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  /* Full width so the dashed rule stays the same width whether a group is open
     or collapsed — otherwise the box shrinks to its content when the lists fold
     away and the rule narrows with it. */
  width: 100%;
  box-sizing: border-box;
}

.fh-sources-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.fh-sources-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gray-400);
}

/* Composer capability chip: sits next to the paperclip in the input bar to show
   the Korean Law (MOLEG) service is available. Injected by fhellow-sources.js. */
.fh-composer-chip {
  /* Inline inside the input, just before the textarea (where "Message Fhellow" is). */
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.25rem 0.55rem;
  margin: 0 0.4rem 0 0.15rem;
  border-radius: 999px;
  background: var(--gray-20);
  border: 1px solid var(--gray-300);
  color: var(--gray-600);
  white-space: nowrap;
  cursor: default;
  user-select: none;
  flex: none;
}

.fh-composer-chip .fh-composer-ico {
  color: var(--fh-clay);
  font-size: 0.95em;
}

/* On narrow composers, keep just the icon to save room. */
@media (max-width: 520px) {
  .fh-composer-chip .fh-composer-txt { display: none; }
}

/* The groups, one per search the citations came from: statutes, web pages, the
 * firm's own documents. Each group carries a plain-text heading (the chip pill
 * was dropped). */
/* The heading is a <summary>: click (or Enter/Space) folds the group's list
   open and closed. Hide the browser's default disclosure triangle — we draw our
   own caret that rotates with the open state. */
.fh-source-head {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  width: fit-content;                /* border wraps only the button, not the row */
  padding: 0.28rem 0.6rem;
  border: 1px solid var(--border-medium);  /* theme-aware: flips in dark mode */
  border-radius: 8px;
  background: transparent;           /* match the surrounding UI in both themes */
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-secondary, #625c55);
  cursor: pointer;
  user-select: none;
  list-style: none;
}
.fh-source-head::-webkit-details-marker { display: none; }
.fh-source-chevron {
  flex: none;
  width: 18px;
  height: 18px;
  fill: currentColor;
  color: var(--gray-400);
  transition: transform 0.18s ease;
}
/* Keyed off .fh-open (not [open]): the open attribute lingers through a collapse
   so the content isn't hidden mid-animation; .fh-open is what the JS toggles in
   sync with the body, so the chevron turns with it. */
.fh-source-group.fh-open > .fh-source-head .fh-source-chevron {
  transform: rotate(90deg);
}

/* Smooth open/close: the body is a one-row grid that animates 0fr↔1fr. The list
   needs overflow:hidden + min-height:0 so the collapsing row clips it cleanly. */
.fh-source-body {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 0.18s ease, opacity 0.18s ease;
}
.fh-source-group.fh-open > .fh-source-body {
  grid-template-rows: 1fr;
  opacity: 1;
}
.fh-source-body > .fh-sources-list {
  overflow: hidden;
  min-height: 0;
}
@media (prefers-reduced-motion: reduce) {
  .fh-source-body { transition: none; }
  .fh-source-chevron { transition: none; }
}
.fh-sources-groups {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.fh-source-group {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

/* One citation per row, in the order the answer met them. A column, not a
 * wrapping row of chips: the line has to be readable as a sentence, and a
 * reader matching [L12] in the body against the footer scans down a column. */
.fh-sources-list {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.fh-source-line {
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--gray-500);
  word-break: keep-all;
  overflow-wrap: anywhere;   /* the URL is long and must not push the column */
}

/* A link the box does not turn into a button (a non-law source) keeps the clay
 * accent and stays a link. */
.fh-source-line a[href]:not(.fh-source-btn) {
  color: var(--fh-clay);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.fh-source-line a[href]:not(.fh-source-btn):hover {
  filter: brightness(0.9);
}

/* [L2] and [W2] inside the answer. Same colour as the links in the 출처 rows,
 * but dotted rather than solid: several solid underlines standing mid-sentence
 * stop the prose from being readable. The marker only has to say it can be
 * pressed - where it goes is already said below it. */
a.fh-marker-link {
  color: var(--fh-clay);
  text-decoration: underline dotted;
  text-underline-offset: 2px;
  white-space: nowrap;   /* `[L2]` 가 줄바꿈으로 쪼개지면 번호가 아니라 글자가 된다 */
}

a.fh-marker-link:hover {
  text-decoration: underline;
  filter: brightness(0.9);
}

.dark .fh-source-line {
  color: var(--gray-400);
}

/* The law.go.kr link, as a button at the end of its own line. Sized to sit in
 * the line rather than to be a row of its own: a row of these was the shape
 * this replaced, and there every button said "원문 보기" and none of them said
 * which citation it opened. */
.fh-source-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-left: 0.35rem;
  padding: 0.12rem 0.5rem;
  border-radius: 0.45rem;
  background: var(--fh-celadon);
  color: #ffffff !important;
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.5;
  text-decoration: none !important;
  border: 1px solid transparent;
  white-space: nowrap;
  vertical-align: baseline;
  transition: filter 0.15s ease;
}

.fh-source-btn:hover {
  filter: brightness(0.94);
  text-decoration: none !important;
}

.fh-source-btn .fh-src-ico {
  font-size: 0.95em;
  line-height: 1;
}

.fh-source-btn .fh-src-arrow {
  opacity: 0.85;
  transition: transform 0.15s ease;
}

.fh-source-btn:hover .fh-src-arrow {
  transform: translate(1px, -1px);
}

/* White ink in both themes: the dark-brown ink read muddy on celadon. */
.dark .fh-source-btn {
  color: #ffffff !important;
}

/* ── Answer typography: one consistent font + clean paragraph rhythm ──────────
 * The message body renders model markdown. These rules give every answer a
 * single Korean-first font stack, roomy line-height, real spacing between
 * paragraphs, and keep-all word breaking so Korean never snaps mid-word.
 * Heading / list / blockquote rules only take effect when the model emits
 * Markdown (##, -, >); on plain-text answers the font + paragraph spacing
 * still apply, which is the bulk of the readability win.
 */
.markdown.message-content {
  font-family: "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic",
               -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 15.5px;
  line-height: 1.78;              /* Korean legal prose needs the air */
  letter-spacing: -0.003em;
  word-break: keep-all;           /* don't break Korean words at line ends */
  overflow-wrap: anywhere;        /* long URLs / case numbers still wrap */
}

/* Keep table values together while descriptions can wrap beside them. */
@media screen {
  .markdown.message-content :is(td, th) {
    overflow-wrap: normal;
  }

  .markdown.message-content :is(td, th) .fh-table-value {
    display: inline-block;
    white-space: nowrap;
    overflow-wrap: normal;
    word-break: normal;
    vertical-align: baseline;
  }

  .markdown.message-content .markdown-table-wrapper {
    min-width: 0;
    max-width: 100%;
    overflow-x: auto;
  }
}

/* paragraph rhythm — the main fix for the wall-of-text look */
.markdown.message-content p { margin: 0 0 0.95em; }
.markdown.message-content p:last-child { margin-bottom: 0; }

/* Section headings when the model emits Markdown (#, ##, ### or a setext
 * underline). Pin the family to the body stack and cap every level — otherwise
 * a stray heading falls through to LibreChat's prose default (~2.25em in a
 * different heading font), which reads as one paragraph "jumping" bigger. */
.markdown.message-content h1,
.markdown.message-content h2,
.markdown.message-content h3,
.markdown.message-content h4,
.markdown.message-content h5,
.markdown.message-content h6 {
  font-family: inherit !important;   /* never fall back to a serif heading font */
  font-weight: 700;
  line-height: 1.4;
  margin: 1.4em 0 0.5em;
}
.markdown.message-content h1 { font-size: 1.25em !important; }
.markdown.message-content h2 { font-size: 1.16em !important; }
.markdown.message-content h3 { font-size: 1.06em !important; }
.markdown.message-content h4,
.markdown.message-content h5,
.markdown.message-content h6 { font-size: 1em !important; }

/* lists */
.markdown.message-content ol,
.markdown.message-content ul { margin: 0.6em 0 0.95em; padding-left: 1.3em; }
.markdown.message-content li { margin: 0.3em 0; }
/* Bullet + number markers follow the body text color (black in light, white in
 * dark) — kept neutral; green is reserved for the source/hyperlink buttons. */
.markdown.message-content li::marker { color: currentColor; }

/* statute quotations, when the model uses a blockquote */
.markdown.message-content blockquote {
  margin: 0.9em 0;
  padding: 0.45em 1em;
  border-left: 3px solid var(--fh-clay);
  background: color-mix(in srgb, var(--fh-clay) 8%, transparent);
  border-radius: 0 8px 8px 0;
}

/* ── Login / auth screen ─────────────────────────────────────────────────────
 * The auth layout root is `.min-h-screen.flex-col.bg-white` (dark: bg-gray-900).
 * Put it on the Fhellow font stack, and recolor the primary "Continue" submit
 * from LibreChat's emerald to celadon so "proceed" is one color across the
 * product (matches Send). Scoped to the auth root so the rest of the app is
 * untouched. */
.min-h-screen.flex-col.bg-white {
  font-family: "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic",
               -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.min-h-screen.flex-col.bg-white button[type="submit"] {
  background-color: var(--fh-celadon) !important;
  color: #ffffff !important;
}
.min-h-screen.flex-col.bg-white button[type="submit"]:hover {
  background-color: color-mix(in srgb, var(--fh-celadon) 88%, #000) !important;
}

/* ── Sidebar chat list: title-only rows ──────────────────────────────────────
 * Every conversation uses the one Fhellow endpoint, so the per-row endpoint
 * icon is an identical robot on every line — pure noise. Drop it and let the
 * titles run full width. Scoped to the conversation-row icon only, so the
 * assistant avatar and landing seal are untouched. */
[data-testid="convo-icon"] { display: none !important; }

/* ── Response actions: keep only Copy and Read aloud ─────────────────────────
 * The buttons under an assistant response (LibreChat HoverButtons) have no
 * stable id of their own, so each is matched by a locale-independent hook so a
 * ko-KR label change can't unhide it:
 *  - Fork: the lucide icon class `.lucide-git-fork`.
 *  - Edit: the pencil icon's SVG path prefix (its `d`), same technique as the
 *    Bookmarks hide above.
 *  - Thumbs 👍/👎: matched by `title` in both Korean (default) and English —
 *    these carry no icon class or unique path to key off, so this is the
 *    fallback the codebase already uses (see "Attach Files" / "파일 첨부").
 * Scoped to the message list so an "Edit" elsewhere (prompts, settings) is
 * untouched. Copy (복사) and Read aloud (읽어주기) are left in place. */
[data-testid="messages-view"] button:has(svg.lucide-git-fork),
[data-testid="messages-view"] button:has(svg path[d^="M13.2929 4.29291"]),
[data-testid="messages-view"] button[title="좋아요"],
[data-testid="messages-view"] button[title="Love this"],
[data-testid="messages-view"] button[title="개선 필요"],
[data-testid="messages-view"] button[title="Needs improvement"] {
  display: none !important;
}
