/*
 * Styles for the ask page's chat window.
 *
 * Kept as a separate static file rather than inlined in the template: the
 * widget is embedded as an iframe that reloads on every page navigation on
 * the host site (see views.py, VISITOR_COOKIE), so a cacheable file avoids
 * re-downloading identical CSS on every reload.
 *
 * Colors and shapes are declared once below as custom properties and used
 * everywhere else by name, rather than repeated as literals through the
 * file. That keeps the palette consistent by construction, and leaves one
 * place to change if a given clinic ever wants its own accent color.
 *
 * The window itself carries no border-radius or shadow: it is built to fill
 * whatever box the embedding iframe gives it edge to edge. The floating,
 * rounded-card look comes from the host page's own CSS on that iframe
 * element (border-radius, box-shadow, overflow: hidden) — the same way
 * every embeddable chat widget works, because the content can't round or
 * shadow a frame it doesn't control the outside of.
 */

:root {
  /* Brand accent: the header bar, the visitor's own messages, citation
     links, the send button. The real value for every configured site lives
     in that site's own accent-<site>.css (see ragservice/views.py, which
     links it in alongside this file); what's set here is only the fallback
     for a site that has none — see ask.html's comment on the second <link>. */
  --color-primary: #2a6;
  --color-on-primary: #fff;
  --color-on-primary-muted: rgba(255, 255, 255, 0.92);

  /* The accent darkened until it carries text: white text on it (header,
     the visitor's bubbles, buttons), or it as text on the tinted window
     (links, "Napsat vzkaz ordinaci"). A clinic's own color is often too
     light for that — in review, white on gynekologie's #74c5c1 was 2:1
     against the 4.5:1 WCAG AA asks of text. 55% is enough for the lightest
     accent in use; a clinic with a darker accent can set a milder share in
     its own accent-<site>.css, so its color is darkened only as much as it
     needs. The plain --color-primary stays for what carries no text: the
     tint, glows and borders. tests/test_chat_window_contrast.py measures
     every clinic's result. */
  --color-primary-strong: color-mix(in srgb, var(--color-primary) 55%, #000);
  --color-on-primary-wash: rgba(255, 255, 255, 0.18);

  /* The accent as a diagonal gradient — lighter top-left, darker
     bottom-right — for the header, the visitor's bubbles and the buttons.
     Built from --color-primary-strong rather than --color-primary, and only
     ever darker than it: every one of these surfaces carries white text, and
     the gradient's old lightening toward #fff at the top-left made that text
     unreadable on a light accent. Every rule that uses it sets a plain
     --color-primary-strong background first, as the fallback for a browser
     without color-mix(). */
  --gradient-primary: linear-gradient(
    135deg,
    var(--color-primary-strong) 0%,
    color-mix(in srgb, var(--color-primary-strong) 80%, #000) 100%
  );
  /* A soft glow in the accent color, for shadows that should read as "lit"
     rather than as a gray drop shadow. */
  --color-primary-glow: color-mix(in srgb, var(--color-primary) 35%, transparent);
  /* A light tint of the accent behind the message list — strong enough that
     the list no longer reads as a bare white sheet, light enough that body
     text on it keeps full contrast. */
  --color-primary-tint: color-mix(in srgb, var(--color-primary) 9%, #fff);
  /* The accent at low opacity, for the soft glows in the list's corners. */
  --color-primary-glow-soft: color-mix(in srgb, var(--color-primary) 18%, transparent);

  /* Body text and secondary/tertiary text (debug figures, captions). */
  --color-text: #1a1a1a;
  /* All three were lighter (#888, #999, #aaa) and fell below 4.5:1 on the
     tinted window — in review the "Moment, malé strpení…" status line was
     hard to read. Now only slightly apart, all of them readable. */
  --color-muted: #5c5c5c;
  --color-faint: #5f5f5f;
  --color-faint-alt: #5f5f5f;
  /* The notice above the greeting: quieter than body text, but well above
     the 4.5:1 contrast --color-muted (#888) fell short of — in review the
     notice was too faint to read. */
  --color-notice-text: #555;

  /* Surfaces and borders. */
  --color-page: #fff;
  --color-surface: #f5f7f6;
  --color-border: #ccc;
  --color-border-light: #e5e5e5;

  /* The rate-limit banner. */
  --color-danger: #a33;
  --color-danger-bg: #fdf3f3;
  --color-danger-border: #f0d8d8;

  /* Corner radii shared by the compose bar's controls and the chat bubbles. */
  --radius-control: 20px;
  --radius-bubble: 14px;

  /* The horizontal inset every section applies for itself. The header and
     compose bar's own backgrounds need to reach the window's edges, so this
     can no longer live as padding on <body> the way a plain document's
     would. */
  --inset: 1rem;
}


/*
 * Page layout: one column, viewport height. A header that never moves, a
 * scrolling message list in between, and the compose bar pinned under it —
 * the layout every chat interface uses, so the box you type into never
 * drifts away as the conversation grows.
 */

body {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  height: 100vh;
  max-width: 720px;
  margin: 0 auto;
  /* The accent tint behind the whole window, with two soft glows of the
     accent in opposite corners, so the window has some depth and warmth
     instead of being flat white. On body rather than on the message list,
     so the conversation and the compose bar under it lie on one continuous
     surface; only the header sits on top, in its own gradient. The browser
     carries a body background out to the whole viewport, so it also fills
     the sides of a window wider than max-width. A plain tint goes first as
     the fallback for a browser without color-mix(). */
  background: var(--color-primary-tint);
  background:
    radial-gradient(circle at 0% 0%, var(--color-primary-glow-soft), transparent 55%),
    radial-gradient(circle at 100% 100%, var(--color-primary-glow-soft), transparent 50%),
    var(--color-primary-tint);
  color: var(--color-text);
  font-family: system-ui, sans-serif;
}

/*
 * The header bar: who the visitor is talking to, and a way to hand the
 * widget back to its launcher bubble.
 */

.chat-header {
  position: relative;
  overflow: hidden;
  flex: none;
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .85rem var(--inset);
  background: var(--color-primary-strong);
  background: var(--gradient-primary);
  color: var(--color-on-primary);
  box-shadow: 0 4px 14px var(--color-primary-glow);
  /* Above the message list, so its glow falls onto the list, not under it. */
  z-index: 1;
}

/* A band of light that sweeps across the header once when the window
   loads — the same sweep the teaser bubble gets in chat-widget.js, so opening the
   chat feels like a continuation of the invitation. pointer-events: none
   keeps it from ever catching a click meant for the header's buttons. */
.chat-header::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -60%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .35), transparent);
  pointer-events: none;
  animation: header-shine 1.2s ease-out .35s 1 both;
}

@keyframes header-shine {
  from { left: -60%; }
  to { left: 130%; }
}

.chat-header-icon {
  position: relative;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-on-primary-wash);
}

/* A small green "online" dot on the assistant's avatar: the familiar sign
   that someone is there to answer right now. The white ring separates it
   from whichever accent color the header has. */
.chat-header-icon::after {
  content: "";
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 9px;
  height: 9px;
  border: 2px solid #fff;
  border-radius: 50%;
  background: #3ccf73;
}

@media (prefers-reduced-motion: reduce) {
  .chat-header::after {
    animation: none;
    display: none;
  }
}

.chat-header-text {
  flex: 1 1 auto;
  min-width: 0;
}

.chat-header-title {
  font-size: .95rem;
  font-weight: 700;
  line-height: 1.3;
}

.chat-header-subtitle {
  overflow: hidden;
  color: var(--color-on-primary-muted);
  font-size: .75rem;
  line-height: 1.3;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.chat-header-close,
.chat-header-expand {
  flex: none;
  display: flex;
  padding: .3rem;
  border: 0;
  background: none;
  color: var(--color-on-primary-muted);
  cursor: pointer;
}

.chat-header-close:hover,
.chat-header-expand:hover {
  color: var(--color-on-primary);
}

/* While the window is enlarged the control stays lit, so it reads as a
   toggle that is currently on rather than a button that did nothing. */
.chat-header-expand.is-enlarged {
  color: var(--color-on-primary);
}

.store {
  flex: none;
  margin: 0;
  padding: .5rem var(--inset) 0;
  color: var(--color-muted);
  font-size: 11px;
}

.store code {
  font-size: 11px;
}

.tuning {
  color: var(--color-faint-alt);
  font-size: 10px;
}

.limit {
  flex: none;
  margin: 0 var(--inset) .6rem;
  padding: .7rem .9rem;
  border: 1px solid var(--color-danger-border);
  border-radius: 6px;
  background: var(--color-danger-bg);
  color: var(--color-danger);
}

/*
 * The message list. flex: 1 so it takes whatever height the header and the
 * compose bar leave it; min-height: 0 overrides flexbox's default of never
 * shrinking a child below its content size, which without this would grow
 * the list instead of scrolling it.
 */

#chat {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: .9rem;
  padding: .8rem var(--inset) 1rem;
  /* No fill of its own: the list lies on the window's tint (see
     body), the same as the compose bar under it. */
}

/* Each new message slides up and fades in, so a new turn is noticed
   without a jump. Messages already in the thread on page load get it too,
   which reads as the conversation settling into place. */
.message {
  display: flex;
  flex-direction: column;
  animation: message-in .3s ease-out both;
}

@keyframes message-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .message {
    animation: none;
  }
}

/*
 * Visitor on the right, assistant on the left — the one convention every
 * chat surface shares, so which side a bubble sits on tells you who wrote
 * it before you have read a word of it.
 */

.message.visitor {
  align-self: flex-end;
  align-items: flex-end;
  max-width: 85%;
}

.message.assistant {
  align-self: flex-start;
  width: 100%;
}

.message.visitor p {
  margin: 0;
  padding: .55rem .9rem;
  border-radius: var(--radius-bubble) var(--radius-bubble) 3px var(--radius-bubble);
  background: var(--color-primary-strong);
  background: var(--gradient-primary);
  color: var(--color-on-primary);
  box-shadow: 0 4px 12px var(--color-primary-glow);
  white-space: pre-wrap;
  /* The same size as the answer, so the two sides of the conversation
     read as one text. */
  font-size: 15px;
  line-height: 1.4;
}

.answer {
  box-sizing: border-box;
  padding: .8rem 1rem;
  border-radius: 3px var(--radius-bubble) var(--radius-bubble) var(--radius-bubble);
  /* White on the tinted list, so the answer stands out as a card. */
  background: var(--color-page);
  border: 1px solid color-mix(in srgb, var(--color-primary) 12%, transparent);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--color-primary) 10%, rgba(0, 0, 0, .04));
  white-space: pre-wrap;
  /* In review the answer read as large type in long lines. 15px suits a
     chat bubble; 65ch caps a line where the eye still finds the next one,
     which only matters when the chat is opened in a full-size tab — in the
     400px widget the bubble is narrower than that anyway. */
  font-size: 15px;
  line-height: 1.5;
  max-width: 65ch;
}

/*
 * Sits inside an empty .answer while retrieval and the first model token are
 * still on their way, so the bubble reads as "working on it" rather than
 * nothing having happened yet. Removed by the same write that puts real text
 * in the bubble (see ask.js) — no separate hide step.
 */
.typing {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: .2rem 0;
}

.typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-faint);
  animation: typing-bounce 1.2s infinite ease-in-out;
}

.typing span:nth-child(2) { animation-delay: .15s; }
.typing span:nth-child(3) { animation-delay: .3s; }

@keyframes typing-bounce {
  0%, 60%, 100% { transform: translateY(0); opacity: .4; }
  30% { transform: translateY(-4px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .typing span {
    animation: none;
    opacity: .6;
  }
}

/*
 * Citation markers ([1], [2]) sitting inline in an answer. Rendered as a small
 * raised superscript so they stay out of the way of the sentence they hang off
 * — the reference number matters far less than the prose, and these are on
 * their way out of the UI entirely. The font-size / line-height / position
 * trio is the browser's own recipe for <sup>: it lifts the marker without
 * adding height to the line it sits on. white-space: nowrap keeps "[1]" from
 * being split across a line break.
 */
.citation {
  color: var(--color-primary-strong);
  text-decoration: none;
  font-weight: 600;
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
  top: -0.5em;
  white-space: nowrap;
}

.citation:hover {
  text-decoration: underline;
}

/* The address a visitor asked for ("pošli mi odkaz na ceník"), appended by
   append_requested_link. Unlike a citation it is the answer itself, so it is
   drawn full size and underlined — it has to look clickable at a glance. */
.answer-link {
  color: var(--color-primary-strong);
  font-weight: 600;
  text-decoration: underline;
  word-break: break-all;
}

.sources {
  margin: .5rem .2rem 0;
}

.sources h2 {
  margin: 0 0 .3rem;
  color: var(--color-faint);
  font-size: .8rem;
  font-weight: 600;
}

.sources li {
  color: var(--color-faint);
  font-size: .8rem;
}

/*
 * The clinic's ready-made questions under the greeting (ask.html), styled
 * like the chips in the launcher's teaser (chat-widget.js) so the visitor
 * recognises them: softly tinted in the clinic color, with the speech-bubble
 * corner of an assistant message, filling with the clinic gradient on hover.
 * They slide in one after another just after the greeting appears.
 * Every control starts from the button's own look being reset — font and
 * text-align included, which a <button> does not inherit by default.
 */
.suggestions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .45rem;
  margin-top: -.3rem;
}

.suggestion {
  max-width: 85%;
  padding: .5rem .85rem;
  border: 1px solid color-mix(in srgb, var(--color-primary) 30%, transparent);
  border-radius: 3px var(--radius-bubble) var(--radius-bubble) var(--radius-bubble);
  background: var(--color-primary-tint);
  background: color-mix(in srgb, var(--color-primary) 10%, var(--color-page));
  box-shadow: 0 2px 6px color-mix(in srgb, var(--color-primary) 15%, transparent);
  color: var(--color-text);
  font: inherit;
  font-size: .9rem;
  font-weight: 500;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, transform .15s ease, box-shadow .15s ease;
  animation: suggestion-in .35s ease-out .25s both;
}

.suggestion:nth-child(2) { animation-delay: .35s; }
.suggestion:nth-child(3) { animation-delay: .45s; }
.suggestion:nth-child(4) { animation-delay: .55s; }

@keyframes suggestion-in {
  from { opacity: 0; transform: translateX(-10px); }
  to { opacity: 1; transform: translateX(0); }
}

.suggestion:hover {
  background: var(--color-primary-strong);
  background: var(--gradient-primary);
  color: var(--color-on-primary);
  transform: translateY(-1px);
  box-shadow: 0 6px 14px var(--color-primary-glow);
}

.suggestion:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--color-primary-glow);
}

@media (prefers-reduced-motion: reduce) {
  .suggestion {
    animation: none;
  }

  .suggestion:hover {
    transform: none;
  }
}

.empty {
  margin: 0 0 .4rem;
  color: var(--color-muted);
}

/* The notice above the greeting (AI, not a doctor, stored conversation —
   see ask.html). Deliberately quieter than a message: small, muted, no
   bubble, so it is read once and then stays out of the conversation's way.
   flex: none so a long thread never squeezes it inside the scrolling #chat. */
.ai-notice {
  flex: none;
  margin: 0;
  padding: .55rem .75rem;
  border: 1px solid var(--color-primary-glow);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.6);
  color: var(--color-notice-text);
  font-size: .75rem;
  line-height: 1.4;
}

/* The stored-conversation line of the notice, on a line of its own under
   a thin rule, so it is not lost at the end of the AI sentence. */
.ai-notice-storage {
  display: block;
  margin-top: .35rem;
  padding-top: .35rem;
  border-top: 1px solid var(--color-primary-glow);
}

/*
 * The compose bar. flex: none keeps it its own height regardless of what
 * #chat is doing; it sits at the bottom simply because it is the last flex
 * child and #chat has already claimed the space above it.
 */

form {
  flex: none;
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .7rem var(--inset) .85rem;
  /* No fill, dividing line or shadow of its own: the bar lies on
     the window's tint (see body) like the conversation above it, so the
     window reads as one surface under the header rather than a list with
     a separate box stuck to its bottom. Only the input box stands out. */
}

input[name="q"] {
  flex: 1;
  padding: .6rem .9rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-control);
  /* White on the tinted bar, with a faint accent shadow, so the box you
     type into is the clearest thing at the bottom of the window. */
  background: var(--color-page);
  box-shadow: 0 2px 6px color-mix(in srgb, var(--color-primary) 12%, transparent);
  font-size: 1rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}

/* While typing, the input is ringed in the accent color instead of the
   browser's default blue outline, which clashes with every clinic palette. */
input[name="q"]:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-glow);
}

/*
 * A round icon button rather than a labelled one: the compose bar is the one
 * place in the window narrow enough on a phone-width panel that a text
 * button ("Zeptat se") competes with the input for room. The arrow is
 * universal enough not to need a label of its own; the accessible name comes
 * from the button's aria-label in the template.
 */
.send-button {
  flex: none;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: var(--color-primary-strong);
  background: var(--gradient-primary);
  color: var(--color-on-primary);
  box-shadow: 0 4px 12px var(--color-primary-glow);
  cursor: pointer;
  transition: transform .15s ease;
}

.send-button:not(:disabled):hover {
  transform: scale(1.08);
}

/* Disabled while an answer is still being written (see setWaiting in
 * ask.js): faded, so it reads as "not now" rather than as broken. */
.send-button:disabled {
  opacity: 0.5;
  cursor: default;
}

/* "Napsat vzkaz ordinaci" (see ask.html and ask.js). The bar is a quiet
   text button under the compose bar — an offer, not a second input. While
   the form is open, body gets .is-writing-message and the conversation and
   compose bar step aside, so the form has the whole window; they come back
   unchanged when it closes. */
.clinic-message-bar {
  flex: none;
  display: flex;
  justify-content: center;
  margin-top: -.5rem;
  padding: 0 var(--inset) .6rem;
}

.clinic-message-bar[hidden],
.clinic-message-form[hidden] {
  display: none;
}

/* A way out that is always there, not a call to action: in the clinic's
   colour so it can be found, but with no fill or border, so it never competes
   with the filled offer button under an answer (.message-offer-open), which
   appears exactly when writing to the clinic is the right next step. */
.clinic-message-open {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .25rem .6rem;
  border: 0;
  border-radius: var(--radius-control);
  background: none;
  color: var(--color-primary-strong);
  font: inherit;
  font-size: .8rem;
  font-weight: 500;
  cursor: pointer;
}

.clinic-message-open:hover,
.clinic-message-open:focus-visible {
  outline: none;
  text-decoration: underline;
  text-underline-offset: 3px;
}

body.is-writing-message #chat,
body.is-writing-message form:not(.clinic-message-form) {
  display: none;
}

/* Overrides the bare `form` rule above, which lays the compose bar out as
   one row; this form is a column that scrolls when the window is small. */
form.clinic-message-form {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: .45rem;
  padding: .9rem var(--inset) 1rem;
}

.clinic-message-heading {
  margin: 0;
  font-size: 1rem;
}

.clinic-message-intro {
  margin: 0 0 .3rem;
  color: var(--color-muted);
  font-size: .8rem;
  line-height: 1.4;
}

.clinic-message-field {
  display: flex;
  flex-direction: column;
  gap: .2rem;
  font-size: .8rem;
  color: var(--color-muted);
}

.clinic-message-field input,
.clinic-message-field textarea {
  padding: .5rem .7rem;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  background: var(--color-page);
  color: var(--color-text);
  font: inherit;
  font-size: .95rem;
}

.clinic-message-field textarea {
  resize: vertical;
}

.clinic-message-field input:focus,
.clinic-message-field textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-glow);
}

.clinic-message-check {
  display: flex;
  align-items: flex-start;
  gap: .45rem;
  font-size: .8rem;
  line-height: 1.35;
}

.clinic-message-check input {
  margin: .1rem 0 0;
  accent-color: var(--color-primary);
}

.clinic-message-error {
  margin: -.2rem 0 0;
  color: var(--color-danger);
  font-size: .78rem;
}

.clinic-message-actions {
  display: flex;
  justify-content: space-between;
  gap: .6rem;
  margin-top: .4rem;
}

.clinic-message-cancel,
.clinic-message-send {
  padding: .55rem .9rem;
  border-radius: var(--radius-control);
  font: inherit;
  font-size: .9rem;
  cursor: pointer;
}

.clinic-message-cancel {
  border: 1px solid var(--color-border);
  background: var(--color-page);
  color: var(--color-text);
}

.clinic-message-send {
  border: 0;
  background: var(--color-primary-strong);
  background: var(--gradient-primary);
  color: var(--color-on-primary);
  font-weight: 600;
}

.clinic-message-send:disabled {
  opacity: .6;
  cursor: default;
}

/* The choice between a question and a booking request at the top of the
   message form. A plain fieldset would draw a frame around two lines. */
.clinic-message-kind {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  margin: 0;
  padding: 0;
  border: 0;
}

.clinic-message-kind legend {
  margin-bottom: .3rem;
  padding: 0;
  font-size: .8rem;
  font-weight: 600;
}

.clinic-message-kind small {
  color: var(--color-muted);
}

/* "Shall we pass this on to the clinic?" under an answer (ask.js,
   showMessageOffer). Set apart from the answer by a thin rule, so it reads
   as an offer from the chat and not as part of what the documents say. */
.message-offer {
  margin-top: .6rem;
  padding-top: .55rem;
  border-top: 1px solid color-mix(in srgb, var(--color-primary) 20%, transparent);
}

.message-offer p {
  margin: 0 0 .45rem;
  font-size: .85rem;
  line-height: 1.4;
}

/* Filled like the send button: this is the one step the offer asks for, so
   it has to read as the action, not as another line of the answer. */
.message-offer-open {
  padding: .5rem 1rem;
  border: 0;
  border-radius: var(--radius-control);
  background: var(--color-primary-strong);
  background: var(--gradient-primary);
  color: var(--color-on-primary);
  box-shadow: 0 4px 12px var(--color-primary-glow);
  font: inherit;
  font-size: .9rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease;
}

.message-offer-open:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 14px var(--color-primary-glow);
}

@media (prefers-reduced-motion: reduce) {
  .message-offer-open {
    transition: none;
  }

  .message-offer-open:hover {
    transform: none;
  }
}

.message-offer-open:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--color-primary-glow);
}
