/*
 * Brand overrides on top of Bootstrap 5.3. Loaded *after* bootstrap.min.css — the
 * layout lists both files explicitly rather than using stylesheet_link_tag :app,
 * because Propshaft sorts alphabetically and "application" would land first.
 *
 * Bootstrap 5.3 components read their own component-level custom properties, so
 * setting --bs-primary alone changes almost nothing visible. Each component we
 * actually use needs its own vars set, which is what most of this file is.
 */

:root {
  --brand: #b4451f;
  --brand-dark: #8f3617;
  --brand-tint: #fbeee7;

  --bs-primary: #b4451f;
  --bs-primary-rgb: 180, 69, 31;
  --bs-link-color: #b4451f;
  --bs-link-color-rgb: 180, 69, 31;
  --bs-link-hover-color: #8f3617;
  --bs-body-bg: #fdfbf7;
  --bs-body-color: #16130f;
  --bs-border-color: #e8e1d6;
  --bs-border-radius: 14px;
  --bs-border-radius-sm: 10px;
  --bs-font-sans-serif: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, Roboto, sans-serif;
}

/* Bootstrap's .bg-body-tertiary is the admin page ground; keep it warm rather than grey. */
:root, [data-bs-theme="light"] {
  --bs-tertiary-bg: #f6f1e8;
  --bs-secondary-bg: #f1ebe0;
}

.btn-primary {
  --bs-btn-bg: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand-dark);
  --bs-btn-hover-border-color: var(--brand-dark);
  --bs-btn-active-bg: var(--brand-dark);
  --bs-btn-active-border-color: var(--brand-dark);
  --bs-btn-disabled-bg: var(--brand);
  --bs-btn-disabled-border-color: var(--brand);
}

.btn-outline-primary {
  --bs-btn-color: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand);
  --bs-btn-hover-border-color: var(--brand);
  --bs-btn-active-bg: var(--brand-dark);
  --bs-btn-active-border-color: var(--brand-dark);
}

.text-bg-primary { background-color: var(--brand) !important; }

.form-control:focus, .form-select:focus, .form-check-input:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 .25rem rgba(var(--bs-primary-rgb), .2);
}

.form-check-input:checked {
  background-color: var(--brand);
  border-color: var(--brand);
}

h1, h2, h3 { letter-spacing: -0.02em; }

/* --- Marketing page ------------------------------------------------------ */

/*
 * The banner is the hero's ground rather than a picture beside the copy: it is texture,
 * not information.
 *
 * `100% auto` from the top, deliberately not `cover`. Cover scales to fill both axes, so
 * on any viewport narrower or taller than the artwork it crops the sides or the top — and
 * the artwork's "Hosto AI" wordmark lives in the top-left corner, where a crop bisects it.
 * Fitting to the width instead means the image is never cropped horizontally and never
 * from the top, at any viewport: the wordmark stays whole and stays proportional.
 *
 * The trade is that below roughly 1400px the image no longer reaches the bottom of the
 * hero. --banner-ground is the artwork's own cream, sampled from its bottom edge, so the
 * strip beneath it continues the same colour and the join doesn't read as an edge. It
 * doubles as the fallback ground if the image never loads.
 *
 * The scrim above it is the load-bearing part — the artwork is busy through the middle,
 * where the headline sits, and the copy has to stay readable over it. It fades to the body
 * background at the bottom so the hero still runs into the section beneath it.
 */
.hero-section {
  --banner-ground: #fcf9ec;

  background-color: var(--banner-ground);
  background-image:
    linear-gradient(180deg,
      rgba(253, 251, 247, .52) 0%,
      rgba(253, 251, 247, .70) 55%,
      var(--bs-body-bg) 100%),
    url("/assets/hosto-banner-000bde16.jpg");
  background-size: auto, 100% auto;
  background-position: top center;
  background-repeat: no-repeat;
}

.eyebrow {
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: .75rem;
  font-weight: 600;
  color: var(--brand);
}

/* --- Sandbox chat -------------------------------------------------------- */

/* Bootstrap has no bubble component, and the thread needs a scroll container. */
.chat-thread {
  min-height: 18rem;
  max-height: 30rem;
  overflow-y: auto;
}

/* The inbox's thread fills whatever height the console pane gives it. A modifier rather
   than a change to .chat-thread, because the sandbox's fixed max-height is what keeps its
   card sitting beside the business-data column. */
.chat-thread--fill {
  min-height: 0;
  max-height: none;
  flex: 1 1 auto;
  padding: 1rem;
}

.chat-bubble {
  max-width: 85%;
  padding: .6rem .9rem;
  border-radius: var(--bs-border-radius);
}

/* chat_markup emits paragraphs and lists, each carrying a bottom margin so they space
   against each other. The last one would otherwise leave a gap inside the bubble. */
.chat-bubble > :last-child { margin-bottom: 0; }

.chat-bubble--user {
  margin-left: auto;
  background: var(--brand);
  color: #fff;
}

.chat-bubble--assistant {
  background: var(--bs-tertiary-bg);
}

.context-dump {
  max-height: 26rem;
  overflow: auto;
  white-space: pre-wrap;
  font-size: .8rem;
}

/* Typing indicator — kept from the previous stylesheet, Bootstrap has no equivalent. */
.thinking { display: flex; gap: .3rem; padding: .75rem .25rem 0; }
.thinking .dot { width: 6px; height: 6px; border-radius: 50%; background: #8b847c; animation: blink 1.2s infinite; }
.thinking .dot:nth-child(2) { animation-delay: .2s; }
.thinking .dot:nth-child(3) { animation-delay: .4s; }
@keyframes blink { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

/* display: flex/grid on a component would otherwise beat the hidden attribute */
[hidden] { display: none !important; }

/* --- Inbox console ------------------------------------------------------- */

/* The console fills whatever the navbar leaves. Done by making the body a column flexbox
   rather than by subtracting a hardcoded navbar height — the navbar grows a second line
   when a client user's name is long, and a magic number would leave the composer hanging
   below the fold exactly then. */
body.has-console {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

body.has-console .inbox-shell { flex: 1 1 auto; min-height: 0; }

/* Three grid children — rail, list, and the frame holding the thread and its sidebar.
   The sidebar is not a column here: it lives inside that frame, because a turbo-frame can
   only replace one element and swapping threads has to change both panes at once. */
.inbox-shell {
  display: grid;
  grid-template-columns: 13rem 22rem minmax(0, 1fr);
  /* One explicit row that takes all the height. Without it the row is auto-sized, and any
     stray child starts a second one — which the default `align-content: stretch` then pays
     for out of the same free space, pushing the panes down the page. */
  grid-template-rows: minmax(0, 1fr);
  background: var(--bs-body-bg);
  overflow: hidden;
}

/* Exactly such a stray child: `turbo_stream_from` emits one of these per client the viewer
   can see, and a grid makes items of everything. They render nothing — they exist to open a
   socket — so take them out of the layout rather than trying to place them in it. */
.inbox-shell > turbo-cable-stream-source { display: none; }

/* Below lg the four columns become one scrolling page. A three-pane console has nowhere
   to go on a phone, and staff triaging on one need the list more than the chrome. */
@media (max-width: 991.98px) {
  body.has-console { display: block; height: auto; overflow: visible; }

  .inbox-shell {
    grid-template-columns: 1fr;
    overflow: visible;
  }
}

.inbox-rail {
  border-right: 1px solid var(--bs-border-color);
  padding: .75rem .5rem;
  overflow-y: auto;
  background: var(--bs-tertiary-bg);
}

.inbox-rail__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  padding: .45rem .65rem;
  border-radius: .5rem;
  color: var(--bs-body-color);
  text-decoration: none;
  font-size: .9rem;
}

.inbox-rail__item:hover { background: rgba(0, 0, 0, .04); }

.inbox-rail__item.active {
  background: var(--brand-tint);
  color: var(--brand-dark);
  font-weight: 600;
}

.inbox-rail__count {
  font-size: .75rem;
  color: var(--bs-secondary-color);
  font-variant-numeric: tabular-nums;
}

.inbox-rail__item.active .inbox-rail__count { color: inherit; }

.inbox-list {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--bs-border-color);
}

.inbox-list__header {
  padding: .75rem;
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}

.inbox-list__scroll { overflow-y: auto; flex: 1 1 auto; }

/* A chip rather than a segmented control: it toggles one narrowing on and off and pairs
   with any rail queue. The three-button group that used to sit here asked the same question
   the rail asks, which is how a filter and a tab could contradict each other. */
.inbox-chip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .25rem .6rem;
  border: 1px solid var(--bs-border-color);
  border-radius: 999px;
  background: var(--bs-body-bg);
  color: var(--bs-secondary-color);
  font-size: .78rem;
  text-decoration: none;
}

.inbox-chip:hover { border-color: var(--brand); color: var(--brand-dark); }

.inbox-chip--on { background: var(--brand); border-color: var(--brand); color: #fff; }

.inbox-chip--on:hover { color: #fff; }

.inbox-row {
  display: flex;
  gap: .65rem;
  padding: .7rem .75rem;
  /* The status stripe lives in this border, so every row reserves the width whether or not
     it has one to show — otherwise the text of an `ai_handling` row would sit 3px left of
     its neighbours and the list would look ragged. */
  border-left: 3px solid transparent;
  border-bottom: 1px solid var(--bs-border-color);
  text-decoration: none;
  color: var(--bs-body-color);
}

.inbox-row:hover { background: var(--bs-tertiary-bg); }

.inbox-row--active { background: var(--brand-tint); }

/* Read down the edge of the list without stopping to read the badges. Same colour meanings
   as the badges themselves, which are the ones the rest of /admin already uses. */
.inbox-row--overdue { border-left-color: var(--bs-danger); }
.inbox-row--needs-staff { border-left-color: var(--bs-warning); }
.inbox-row--with-staff { border-left-color: var(--bs-info); }
.inbox-row--done { border-left-color: transparent; opacity: .68; }

/* An escalation's age is the whole point of the overdue state, so it is not muted like the
   rest of the row's meta line. */
.inbox-row__waiting {
  display: block;
  margin-top: .15rem;
  font-size: .72rem;
  font-weight: 600;
  color: var(--bs-warning-text-emphasis);
}

.inbox-row--overdue .inbox-row__waiting { color: var(--bs-danger-text-emphasis); }

/* The row is a link, so everything inside it is inline by default. */
.inbox-row__body { display: block; min-width: 0; flex: 1 1 auto; }

.inbox-row__top { display: flex; justify-content: space-between; gap: .5rem; align-items: baseline; }

.inbox-row__name { font-weight: 600; font-size: .92rem; display: block; }

.inbox-row__time { font-size: .72rem; color: var(--bs-secondary-color); flex-shrink: 0; }

.inbox-row__preview,
.inbox-row__meta {
  display: block;
  font-size: .8rem;
  color: var(--bs-secondary-color);
}

.inbox-row__meta { margin-top: .15rem; font-size: .72rem; }

/* A turbo-frame is display: block by default, and this one has to be a row of two panes. */
.inbox-detail { display: flex; min-width: 0; overflow: hidden; }

.inbox-blank {
  margin: auto;
  text-align: center;
  padding: 2rem;
  max-width: 24rem;
}

.inbox-thread {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
}

.inbox-thread__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .75rem 1rem;
  border-bottom: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}

.inbox-banner {
  padding: .45rem 1rem;
  font-size: .85rem;
  text-align: center;
  flex-shrink: 0;
}

.inbox-banner--bot { background: #f3c04a; color: #4a3a10; }

.inbox-banner--human { background: var(--brand-tint); color: var(--brand-dark); }

.inbox-composer {
  padding: .75rem 1rem 1rem;
  border-top: 1px solid var(--bs-border-color);
  flex-shrink: 0;
}

/* A staff reply is ours, so it keeps the outgoing side, but a person's words should not be
   mistakable for the assistant's when someone reads back through a thread. */
.chat-bubble--staff { background: var(--brand-dark); }

.inbox-sidebar {
  border-left: 1px solid var(--bs-border-color);
  padding: 1rem .9rem;
  overflow-y: auto;
  background: var(--bs-tertiary-bg);
  flex-shrink: 0;
  width: 17rem;
}

@media (max-width: 991.98px) {
  .inbox-detail { flex-direction: column; }
  .inbox-sidebar { width: auto; border-left: 0; border-top: 1px solid var(--bs-border-color); }
  .chat-thread--fill { max-height: 60vh; }
}

.inbox-facts { margin: 0; font-size: .82rem; }

.inbox-facts dt {
  color: var(--bs-secondary-color);
  font-weight: 500;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-top: .7rem;
}

.inbox-facts dd { margin: 0; }

/* --- Avatars --- */

.inbox-avatar { position: relative; display: inline-block; width: 2.5rem; height: 2.5rem; flex-shrink: 0; }

.inbox-avatar__img,
.inbox-avatar__initials {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .02em;
}

.inbox-avatar__channel {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 1.05rem;
  height: 1.05rem;
  border-radius: 50%;
  border: 2px solid var(--bs-body-bg);
  color: #fff;
  font-size: .5rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.inbox-avatar__channel--instagram { background: #c13584; }

.inbox-avatar__channel--messenger { background: #0084ff; }
