/*
 * Blacks Fasteners palette for LibreChat.
 *
 * Two kinds of rule live here, and the difference is the whole history of
 * this file. The first block sets colour custom properties. The second
 * names the selectors LibreChat actually paints from.
 *
 * BLA-628 shipped only the first kind and closed as done, and a visitor
 * still saw stock grey. Renaming a colour only works if something reads
 * that name, and for the three surfaces that carry this brand, nothing
 * did: the send button paints from a utility class, the product links
 * are hardcoded in LibreChat's own bundle, and no rule ever placed the
 * logo on the chat screen at all. Measured on the live page 2026-09-20,
 * before BLA-788: zero elements painted 215 25 32.
 *
 * No focus, outline, font or position rule is set anywhere in this file,
 * so LibreChat's keyboard behaviour, focus rings, labels and landmarks
 * are preserved exactly as shipped. tests/test_librechat_branding.py
 * fails if that stops being true.
 *
 * Palette, taken from chat_demo/web.py so the chat and the product help
 * page carry one identity:
 *   Blacks red   #d71920  ->  215 25 32
 *   Blacks ink   #161616  ->   22 22 22
 *   Deep ink     #0b0b0b  ->   11 11 11
 *   White        #ffffff  ->  255 255 255
 *
 * Measured contrast, so the palette cannot make the chat unreadable:
 *   white lettering on Blacks red is 5.19:1, above the 4.5:1 needed for body
 *   text, so red is safe behind white button labels;
 *   LibreChat's own light body text on the darkened surface is 16.6:1;
 *   Blacks ink on white in the light theme is 18.1:1.
 * Blacks red against the dark surface is only 3.80:1, so red is never used for
 * ordinary text. It stays a fill behind white lettering, a link tint that is
 * lightened first, and a border or focus accent, all of which need 3:1.
 */

:root {
  --blacks-red: 215 25 32;
  --blacks-red-hover: 177 18 25;
  --blacks-red-light: 232 106 111;
  --blacks-red-lighter: 244 160 163;
  --blacks-ink: 22 22 22;
}

/* Dark theme: LibreChat's neutral greys become Blacks ink. */
.dark {
  --gray-900: 11 11 11;
  --gray-875: 16 16 16;
  --gray-850: 22 22 22;
  --gray-800: 26 26 26;
  --gray-700: 38 38 38;
  --gray-650: 46 46 46;
  --link: var(--blacks-red-light);
  --link-hover: var(--blacks-red-lighter);
}

/* Brand accent, in both themes. */
:root, .dark {
  --accent-primary: var(--blacks-red);
  --accent-primary-hover: var(--blacks-red-hover);
  --brand-purple: var(--blacks-red);
  --surface-submit: var(--blacks-red);
  --surface-submit-hover: var(--blacks-red-hover);
}

/* ------------------------------------------------------------------
 * Rules that name what the page paints.
 *
 * The site runs in the light scheme, so light is written explicitly with
 * html:not(.dark) rather than left to :root. That beats the .dark block
 * above on specificity, so neither rule can be undone by the order the
 * two happen to end up in.
 * ------------------------------------------------------------------ */

/* LibreChat does read --link in the light scheme - .text-link and
 * [&_a]:text-link both resolve rgb(var(--link)) - but the theme only ever
 * set it under .dark, so a light visitor kept the stock blue. This covers
 * the product's own link utilities. It does NOT cover links inside an
 * answer; those need the rule below. */
html:not(.dark) {
  --link: var(--blacks-red);
  --link-hover: var(--blacks-red-hover);
}

/* The send button. Its class is bg-text-primary, so it paints from the
 * body-text colour and never reads --surface-submit, which is why setting
 * that name changed nothing. Naming the class is the only way to reach it.
 * White on Blacks red is 5.19:1, above the 4.5:1 body-text bar.
 * :disabled is deliberately left alone: LibreChat dims the button to 10%
 * opacity to say "nothing to send yet", and that affordance is not ours
 * to take away. */
#send-button.bg-text-primary {
  background-color: rgb(var(--blacks-red));
  color: rgb(255 255 255);
}

#send-button.bg-text-primary:hover:not(:disabled) {
  background-color: rgb(var(--blacks-red-hover));
}

/* Links inside an answer - the product links customers actually click.
 * LibreChat hardcodes these in its own bundle, past every colour name:
 *   p.whitespace-pre-wrap a, li a { color: rgb(0,102,204) }
 * so the fix is to out-specify that selector rather than set a variable.
 * Contrast on white: Blacks red 5.19:1, against the stock blue's 5.17:1
 * it replaces, so this is a small improvement and not a regression.
 * The product's own bold and underline are kept, so these links are not
 * distinguished by colour alone.
 * In the dark scheme red is lightened first - #e86a6f on #0b0b0b is
 * 6.30:1, where full Blacks red would be only 3.80:1. */
html:not(.dark) .markdown p.whitespace-pre-wrap a,
html:not(.dark) .markdown li a {
  color: rgb(var(--blacks-red));
}

html:not(.dark) .markdown p.whitespace-pre-wrap a:hover,
html:not(.dark) .markdown li a:hover {
  color: rgb(var(--blacks-red-hover));
}

html.dark .markdown p.whitespace-pre-wrap a,
html.dark .markdown li a {
  color: rgb(var(--blacks-red-light));
}

/* The logo, on the loaded chat screen rather than only on the loading
 * splash a visitor never sees. It rides the 52px bar across the top of
 * the chat panel, which is the one piece of chrome present at every
 * width: it carries the sidebar toggle on a phone and the model name on
 * a desktop.
 *
 * A background image on a pseudo-element is the deliberate choice. It is
 * decorative by definition, so it adds no unnamed image to the
 * accessibility tree and no landmark moves; the page already announces
 * itself, its <title> reads Blacks Fasteners. The bar is a flex row, so
 * the pseudo-element simply becomes its first item. */
main .absolute.top-0.z-10.h-\[52px\]::before {
  content: "";
  display: block;
  flex: 0 0 auto;
  align-self: center;
  width: 148px;
  height: 30px;
  margin-inline-start: 4px;
  background-image: url("/assets/logo.svg");
  background-repeat: no-repeat;
  background-position: left center;
  background-size: contain;
}

/* On a phone the same bar also carries the sidebar toggle, so the mark
 * steps down rather than crowding it out. */
@media (max-width: 640px) {
  main .absolute.top-0.z-10.h-\[52px\]::before {
    width: 104px;
    height: 22px;
  }
}

/* ---------------------------------------------------------------------------
 * Product answers as a grid of tiles (BLA-789).
 *
 * The lookup composes a one-column markdown table, one product per row, which
 * LibreChat renders as a <table> inside .markdown -- the same container the
 * link colours above already reach through, so this hangs off a hook this
 * repository has proved rather than a guessed class name.
 *
 * Built from layout properties only. This file may not set outline, position,
 * z-index, font or line-height: that is the keyboard, focus and text-metric
 * contract from BLA-628, held by test_librechat_branding. Writing this block
 * the obvious way broke it three ways and none of the three were needed --
 * the header is hidden with `display`, and the tiles inherit the chat's own
 * typography, which is the size the visitor already chose.
 *
 * A fallback ladder on purpose: a browser that ignored `display: grid`, or a
 * deploy where this bind-mount failed to appear, still gets a plain table of
 * products with working links rather than the paragraph this ticket removes.
 */

.markdown table {
  display: block;
  width: 100%;
  border: 0;
  border-collapse: separate;
}

/* The header row exists only because a markdown table requires one. It reads
 * "Products", which the sentence above the grid has already said, so it is
 * removed rather than read out a second time. */
.markdown table thead {
  display: none;
}

.markdown table tbody {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 12px;
  width: 100%;
}

.markdown table tbody tr {
  display: flex;
  flex-direction: column;
  border: 1px solid rgb(var(--blacks-ink) / 0.18);
  border-radius: 6px;
  overflow: hidden;
  background: rgb(255 255 255 / 0.04);
}

/* One product per row, four cells: photograph, name, part number, price.
 * They stack because the row is a column, which is what replaced the `<br>`
 * this used to put between them -- LibreChat escapes HTML inside a table
 * cell, so a `<br>` reached the customer as four characters on screen. */
.markdown table tbody td {
  display: block;
  padding: 0 12px;
  border: 0;
}

.markdown table tbody td:nth-child(2) {
  padding-top: 10px;
}

.markdown table tbody td:last-child {
  padding-bottom: 12px;
  opacity: 0.72;
}

/* The photograph cell is the first one. Fixed height and `contain`, so a tall
 * product and a wide one line up instead of setting their own heights. */
.markdown table tbody td:first-child img {
  width: calc(100% + 24px);
  height: 118px;
  margin: -10px -12px 6px;
  object-fit: contain;
  background: #fff;
  padding: 8px;
}

/* The placeholder, for a tile with no stored photograph. No <img> is emitted
 * in that case -- an image with a guessed address is how a broken-image icon
 * reaches a customer -- so there is no element to style and this is drawn on
 * the cell, at the same 118px, so a mixed grid keeps an even top edge. Not a
 * rare branch: BLA-786 has never run, so this is every tile today. */
.markdown table tbody td:first-child::before {
  content: "";
  display: block;
  height: 118px;
  margin: 0 -12px;
  background:
    linear-gradient(135deg, rgb(var(--blacks-ink) / 0.06), rgb(var(--blacks-ink) / 0.12)),
    #f4f4f3;
  border-bottom: 3px solid rgb(var(--blacks-red));
}

/* ...and gone again as soon as there is a real photograph to show. */
.markdown table tbody td:first-child:has(img)::before {
  display: none;
}

/* The name is the link, so the tile heading is what a customer clicks.
 * Markdown already makes it strong; this only holds the underline back. */
.markdown table tbody td strong a {
  text-decoration: none;
}

.markdown table tbody td strong a:hover {
  text-decoration: underline;
}

/* The part number, which is what a trade customer actually orders by. */
.markdown table tbody td:nth-child(3) {
  opacity: 0.78;
}

@media (max-width: 480px) {
  .markdown table tbody {
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  }
}
