/* Styles for the site-wide chat widget (see chat-widget.js).
   Unlike site-nav.css, this cannot lean on the --beacon, --text-… and --line
   custom properties: the widget loads on the React app-router pages too,
   and those custom properties are only ever defined on the static page's
   :root. Every colour below is hardcoded from the same palette instead, so
   the widget looks identical no matter which page it is bolted onto. */

.luminary-chat-launcher {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 2147483000;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: none;
  background: #171b2c;
  color: #b8842b;
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 6px 20px rgba(23, 27, 44, 0.35);
}

.luminary-chat-launcher:hover {
  background: #232842;
}

.luminary-chat-launcher:focus-visible {
  outline: 2px solid #b8842b;
  outline-offset: 2px;
}

.luminary-chat-panel {
  position: fixed;
  right: 20px;
  bottom: 88px;
  z-index: 2147483000;
  width: 360px;
  max-width: calc(100vw - 40px);
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  background: #ffffff;
  color: #171b2c;
  border: 1px solid rgba(184, 132, 43, 0.24);
  border-radius: 12px;
  box-shadow: 0 20px 48px rgba(23, 27, 44, 0.28);
  font-family: "IBM Plex Sans", sans-serif;
  overflow: hidden;
  /* Without this, a scroll gesture that runs out of transcript to scroll
     "chains" into the page behind the sheet, so the page jumps underneath
     an ostensibly modal panel. Contain it here even though the panel
     itself doesn't scroll, since chaining can otherwise still bubble up
     through it from the scrollers nested inside. */
  overscroll-behavior: contain;
}

/* The panel is shown and hidden through its `hidden` property, and without
   this it was never actually hidden. The UA rule is [hidden] { display: none },
   an attribute selector, which ties on specificity with the .luminary-chat-panel
   class above — and on a tie the author stylesheet wins, so `display: flex` beat
   it and an empty panel sat over the foot of every page, undismissable because
   the close button only sets the same property again. Matching the class here
   puts the hidden state back in front. */
.luminary-chat-panel[hidden] {
  display: none;
}

.luminary-chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid rgba(184, 132, 43, 0.24);
  flex-shrink: 0;
}

.luminary-chat-title {
  font-size: 15px;
  font-weight: 600;
  color: #171b2c;
}

.luminary-chat-close {
  border: none;
  background: transparent;
  color: #656b80;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 6px;
}

.luminary-chat-close:hover {
  color: #171b2c;
}

.luminary-chat-close:focus-visible,
.luminary-chat-send:focus-visible,
.luminary-chat-cta:focus-visible {
  outline: 2px solid #b8842b;
  outline-offset: 2px;
}

.luminary-chat-body {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
  padding: 14px 16px 16px;
  gap: 10px;
  overflow-y: auto;
  /* Stop an end-of-scroll gesture here from chaining into the page behind
     the sheet, and keep the old-iOS momentum-scroll feel. The transcript
     nested inside is the usual scroller, but this one still scrolls when a
     short viewport squeezes the offer row and composer together. */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.luminary-chat-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.luminary-chat-input-area textarea {
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 14px;
  color: #171b2c;
  background: #ffffff;
  border: 1px solid rgba(184, 132, 43, 0.24);
  border-radius: 6px;
  padding: 10px 12px;
}

.luminary-chat-input-area textarea:focus-visible {
  outline: 2px solid #b8842b;
  outline-offset: 1px;
}

.luminary-chat-send {
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #ffffff;
  background: #171b2c;
  border: none;
  border-radius: 6px;
  padding: 11px 14px;
  cursor: pointer;
}

.luminary-chat-send:hover {
  background: #232842;
}

.luminary-chat-send:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Chat transcript ---------------------------------------------------- */

.luminary-chat-messages {
  flex: 1;
  min-height: 120px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Same reasoning as .luminary-chat-body: this is the scroller that
     actually reaches its end most often (the transcript growing past the
     visible area), so it's the one most likely to leak a scroll into the
     page underneath without this. */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.luminary-chat-bubble {
  max-width: 88%;
  padding: 9px 12px;
  border-radius: 10px;
  font-size: 13px;
  line-height: 1.5;
  word-wrap: break-word;
  white-space: pre-wrap;
}

.luminary-chat-bubble a {
  color: #b8842b;
}

.luminary-chat-bubble-assistant {
  align-self: flex-start;
  background: #f4f0e6;
  color: #171b2c;
  border: 1px solid rgba(184, 132, 43, 0.24);
}

.luminary-chat-bubble-user {
  align-self: flex-end;
  background: #171b2c;
  color: #ffffff;
}

/* Errors and the server's own apology. Deliberately not styled as an
   assistant bubble: these are never stored in the transcript and never sent
   back to the model (see showNotice in chat-widget.js), so they should not
   look like something the assistant said. */
.luminary-chat-bubble-notice {
  align-self: stretch;
  max-width: 100%;
  background: #fdf6e9;
  color: #5c4415;
  border: 1px solid rgba(184, 132, 43, 0.45);
}

.luminary-chat-typing {
  opacity: 0.7;
}

.luminary-chat-input-area {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  flex-shrink: 0;
}

.luminary-chat-input-area textarea {
  flex: 1;
  resize: none;
}

.luminary-chat-handoff {
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  text-align: center;
}

.luminary-chat-handoff p {
  margin: 0;
  font-size: 13px;
  color: #3d4359;
}

.luminary-chat-cta {
  display: inline-block;
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  color: #ffffff;
  background: #171b2c;
  border-radius: 6px;
  padding: 11px 14px;
}

.luminary-chat-cta:hover {
  background: #232842;
}

/* Persistent clarity-call offer -------------------------------------- */

/* Shown once the visitor has had a real reply (see showOffer in
   chat-widget.js). Sits as its own flex child of .luminary-chat-body,
   never inside .luminary-chat-messages, so it never scrolls away with the
   transcript; flex-shrink: 0 for the same reason the input area needs it —
   .luminary-chat-body is a column flexbox that would otherwise squeeze this
   row to make room for a growing transcript. */
.luminary-chat-offer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-shrink: 0;
  padding-top: 10px;
  border-top: 1px solid rgba(184, 132, 43, 0.24);
}

.luminary-chat-offer p {
  margin: 0;
  font-size: 13px;
  color: #3d4359;
}

/* Full-width sheet below 480px, matching how mobile chat widgets commonly
   behave so the panel isn't a cramped rectangle floating over the page. */
@media (max-width: 480px) {
  .luminary-chat-panel {
    right: 8px;
    left: 8px;
    /* This resolves to 0px unless the page opts into
       viewport-fit=cover (neither public/index.html nor Next's default
       layout does today, so env() is inert right now); it stays here so
       the widget is still correct the day one of them does. */
    bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    width: auto;
    max-width: none;
    /* Plain vh fallback for browsers with no dvh support. Deliberately not
       chained with the dvh/custom-property declarations below: var() is
       valid at parse time even when what it resolves to is not, so a
       browser that understands custom properties but not dvh would still
       let the var() declaration win the cascade, compute to `none` at
       computed-value time, and let the transcript grow the sheet past the
       top of the screen. The @supports gate below is what actually keeps
       this declaration in effect on those browsers. */
    max-height: 75vh;
  }

  .luminary-chat-launcher {
    right: 16px;
    /* Same reasoning as the panel's `bottom` above: inert today, correct if
       viewport-fit=cover is ever added. */
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  }

  /* The launcher sitting next to an already-open full-width sheet is just
     clutter on a phone; the header's close button is the way out. */
  html.luminary-chat-open .luminary-chat-launcher {
    display: none;
  }

  /* iOS Safari zooms the whole page in on focus of any control below 16px,
     which leaves the sheet half off-screen until the visitor zooms back
     out. 16px is the documented threshold, not an arbitrary bump. */
  .luminary-chat-input-area textarea {
    font-size: 16px;
  }

  /* The glyph stays the same size; only the hit area grows to this
     project's 44px touch-target minimum (see tests/e2e/static-nav.spec.ts
     for the same rule applied to the nav toggle). Flexbox keeps the ×
     visually centred without needing to touch its font-size. */
  .luminary-chat-close {
    min-width: 44px;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }

  .luminary-chat-send {
    min-height: 44px;
  }

  .luminary-chat-cta {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* Only browsers that support dvh get the dvh/custom-property max-height:
   gating on the same feature the value itself depends on is what makes this
   degrade instead of silently breaking. A plain declaration chain can't do
   this — var() is valid at parse time even when what it resolves to isn't,
   so the var() declaration would always win the cascade regardless of
   whether the browser actually supports dvh, and on one that doesn't, the
   property computes to `none` instead of falling back to the 75vh above it.
   The custom property is kept current by the visualViewport handling in
   chat-widget.js, which accounts for the on-screen keyboard. */
@supports (height: 1dvh) {
  /* Every width, not just the sheet layout. A phone in landscape is around
     844x390, so it is wide enough to take the desktop rules while still
     having an on-screen keyboard that covers the composer. chat-widget.js
     only sets this custom property on the desktop layout when a keyboard is
     actually up, so with no keyboard this resolves to the 70dvh default and
     nothing about the desktop panel changes. */
  .luminary-chat-panel {
    max-height: var(--luminary-chat-max-h, 70dvh);
  }

  @media (max-width: 480px) {
    .luminary-chat-panel {
      max-height: var(--luminary-chat-max-h, 75dvh);
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .luminary-chat-launcher,
  .luminary-chat-panel,
  .luminary-chat-send,
  .luminary-chat-cta {
    transition: none;
  }
}
