/* Vaki's own palette, light first. A guest opens this on a phone outdoors in
   daylight, often on a bad connection, which is the opposite of the dark slate
   the first version used. Dark still follows the guest's own setting. */
:root {
  --ground:#EAF1F1; --surface:#FFFFFF; --raised:#F3F8F8; --ink:#0D1618;
  --muted:#52676A; --hairline:#D3DFDF;
  --aurora:#0C7A5E; --aurora-soft:rgba(12,122,94,.10);
  --bad:#A0342A; --bad-soft:rgba(160,52,42,.10);
  /* A company's colours (app.js applyTheme) replace these; with no theme they are today's look. */
  --brand-button:var(--aurora); --brand-button-text:var(--surface);
  --brand-header:var(--surface); --brand-header-text:var(--ink); --brand-header-muted:var(--muted);
  --brand-bg:var(--surface); --brand-text:var(--ink);
  --brand-bubble:var(--aurora); --brand-bubble-text:var(--surface);
  --display:"Bricolage Grotesque","Segoe UI",system-ui,sans-serif;
  --body:"Hanken Grotesk",system-ui,-apple-system,sans-serif;
}
@media (prefers-color-scheme: dark) {
  :root {
    --ground:#080D0F; --surface:#0F1719; --raised:#16211F; --ink:#E8F0F0;
    --muted:#8CA2A4; --hairline:#223032;
    --aurora:#4FDCAE; --aurora-soft:rgba(79,220,174,.12);
    --bad:#F08A7C; --bad-soft:rgba(240,138,124,.12);
  }
}

* { box-sizing: border-box; }
body {
  margin: 0; background: var(--ground); color: var(--brand-text);
  font-family: var(--body); font-size: 16px; line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.chat {
  max-width: 680px; margin: 0 auto; height: 100dvh;
  display: flex; flex-direction: column; background: var(--brand-bg);
}
@media (min-width: 720px) {
  .chat { height: min(100dvh, 900px); margin-block: max(0px, calc((100dvh - 900px) / 2));
          border: 1px solid var(--hairline); border-radius: 16px; overflow: hidden; }
}

header { padding: 16px 18px 12px; border-bottom: 1px solid var(--hairline); }
.chat > header { background: var(--brand-header); color: var(--brand-header-text); }
header h1 { font-family: var(--display); font-weight: 600; font-size: 18px; margin: 0; letter-spacing: -.3px; }
header p { margin: 3px 0 0; color: var(--muted); font-size: 13.5px; }
.chat > header #tagline { color: var(--brand-header-muted); }
.disclosure {
  margin-top: 10px !important; font-size: 12px; color: var(--muted);
  background: var(--raised); border-radius: 8px; padding: 7px 10px;
}

.messages {
  flex: 1; overflow-y: auto; padding: 18px;
  display: flex; flex-direction: column; gap: 10px;
  overscroll-behavior: contain;
}
.msg {
  padding: 11px 14px; border-radius: 14px; max-width: 85%;
  white-space: pre-wrap; line-height: 1.5; font-size: 15.5px;
  overflow-wrap: anywhere;
}
.msg.bot strong { font-weight: 600; }
/* The source line under a canned answer: a quiet footnote on its own line, never the size of the answer. */
.msg.bot a.source { display: block; margin-top: 2px; padding: 4px 0; min-height: 24px; box-sizing: border-box; font-size: 12px; line-height: 1.4; color: var(--muted); text-decoration: none; white-space: normal; overflow-wrap: anywhere; }
.msg.bot a.source:hover, .msg.bot a.source:focus-visible { text-decoration: underline; }
.msg.bot a.source .source-icon { font-size: 11px; }
.msg.user { align-self: flex-end; background: var(--brand-bubble); color: var(--brand-bubble-text); border-bottom-right-radius: 5px; }
/* The opening line and the unavailable notice are not replies the server holds, so they are not `.msg.bot`, but they look like one. */
.msg.bot, .msg.greeting, .msg.notice { align-self: flex-start; background: var(--raised); border-bottom-left-radius: 5px; }
.composer[hidden], #tagline[hidden], #disclosure[hidden] { display: none; }
/* An error is not a reply. It must not look like one. */
.msg.error { align-self: flex-start; background: var(--bad-soft); color: var(--bad); border-left: 2px solid var(--bad); }

/* The confirm step. Deliberately looks like an action, not like a message:
   pressing it is the moment a real place is taken. */
.confirmbar { align-self: flex-start; display: flex; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.confirmbar button {
  font: inherit; font-size: 15px; font-weight: 600; cursor: pointer;
  padding: 10px 16px; border-radius: 12px; border: 1px solid transparent;
}
.confirm-yes { background: var(--brand-button); color: var(--brand-button-text); }
.confirm-no { background: transparent; color: var(--muted); border-color: var(--hairline); }
.confirmbar button:focus-visible { outline: 2px solid var(--aurora); outline-offset: 2px; }

/* The recommend step's quick replies: they wrap, and a long label breaks rather than widening the chat. */
.choicebar { align-self: flex-start; display: flex; gap: 8px; flex-wrap: wrap; margin-top: 2px; max-width: 100%; }
.choice {
  font: inherit; font-size: 15px; font-weight: 600; cursor: pointer; text-align: left;
  min-height: 44px; padding: 10px 14px; border-radius: 12px; border: 1px solid var(--aurora);
  background: transparent; color: inherit; max-width: 100%; overflow-wrap: anywhere;
}
.choice:focus-visible { outline: 2px solid var(--aurora); outline-offset: 2px; }

/* Three dots rather than a literal ellipsis character, so it reads as activity
   rather than as the assistant having said "..." */
.msg.pending { display: flex; gap: 4px; align-items: center; padding: 15px 16px; }
.msg.pending i { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); animation: pulse 1.2s infinite; }
.msg.pending i:nth-child(2) { animation-delay: .18s; }
.msg.pending i:nth-child(3) { animation-delay: .36s; }
@keyframes pulse { 0%,60%,100% { opacity:.25 } 30% { opacity:1 } }
@media (prefers-reduced-motion: reduce) { .msg.pending i { animation: none; opacity: .6 } }

.composer {
  display: flex; gap: 9px; padding: 12px 14px;
  border-top: 1px solid var(--hairline);
  padding-bottom: max(12px, env(safe-area-inset-bottom));
}
.composer input {
  flex: 1; padding: 12px 14px; border-radius: 11px;
  border: 1px solid var(--hairline); background: var(--ground); color: var(--ink);
  font: inherit; min-width: 0;
}
.composer input:focus { outline: 2px solid var(--aurora); outline-offset: 1px; border-color: transparent; }
.composer button {
  padding: 12px 18px; border: 0; border-radius: 11px;
  background: var(--brand-button); color: var(--brand-button-text);
  font: 600 15px/1 var(--body); cursor: pointer;
}
.composer button:disabled { opacity: .5; cursor: default; }
.composer button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* The Book button under a reply that names a tour (src/bookWindow.ts). Same
   visual weight as the confirm step: it is an action, not a message. */
.bookbar { align-self: flex-start; display: flex; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.bookbar button {
  font: inherit; font-size: 15px; font-weight: 600; cursor: pointer;
  padding: 10px 16px; border-radius: 12px; border: 1px solid var(--aurora);
  background: var(--aurora-soft); color: var(--ink); text-align: left;
}
.bookbar button:focus-visible { outline: 2px solid var(--aurora); outline-offset: 2px; }
/* Whose trip it is, when the operator's file says. A small line under the name, in words, never colour alone. */
.bookbar .originbadge {
  display: block; margin-top: 4px; font-size: 12px; font-weight: 600; letter-spacing: .02em; opacity: .75;
}

/* The booking window: a panel over the chat. Bokun's own widget sits inside it. */
.bookpanel {
  position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column;
  background: var(--surface); color: var(--ink);
}
.bookpanel-head {
  display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  border-bottom: 1px solid var(--hairline);
}
.bookpanel-title { flex: 1; min-width: 0; font-weight: 600; font-size: 15px; overflow-wrap: anywhere; }
.bookpanel-head button, .bookpanel-head a {
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; text-decoration: none;
  padding: 8px 12px; border-radius: 10px; border: 1px solid var(--hairline);
  background: transparent; color: var(--ink);
}
.bookpanel-head button:focus-visible, .bookpanel-head a:focus-visible { outline: 2px solid var(--aurora); outline-offset: 2px; }
.bookpanel-body { flex: 1; overflow-y: auto; padding: 12px 14px; background: var(--surface); }
.bookpanel-status { margin: 0 0 10px; font-size: 13.5px; color: var(--muted); }
.bookpanel-note { margin: 12px 0 0; font-size: 12px; color: var(--muted); }
.bookpanel-fallback { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.bookpanel-fallback a {
  font-size: 15px; font-weight: 600; text-decoration: none; padding: 11px 16px; border-radius: 12px;
  background: var(--brand-button); color: var(--brand-button-text);
}

/* Report: small and quiet, under the input, never louder than the chat. */
.reportbtn {
  display: inline-flex; align-items: center; gap: 5px;
  font: inherit; font-size: 12.5px; color: var(--muted); cursor: pointer;
  background: transparent; border: 0; border-radius: 8px;
  min-height: 32px; padding: 4px 8px;
}
.reportbtn:hover { color: var(--ink); text-decoration: underline; }
.reportbtn:focus-visible { outline: 2px solid var(--aurora); outline-offset: 1px; }
.reportbtn[hidden] { display: none; }
.reportfoot { display: flex; flex: none; justify-content: center; padding: 0 14px max(6px, env(safe-area-inset-bottom)); }
.reportfoot:has(> [hidden]) { display: none; }

.reportsheet-backdrop {
  position: fixed; inset: 0; z-index: 60; display: flex; align-items: flex-end; justify-content: center;
  background: rgba(8, 13, 15, .55);
}
.reportsheet {
  width: 100%; max-width: 520px; max-height: 92dvh; overflow-y: auto;
  background: var(--surface); color: var(--ink);
  border-radius: 16px 16px 0 0; padding: 16px 16px max(16px, env(safe-area-inset-bottom));
  box-shadow: 0 -8px 30px rgba(0, 0, 0, .25);
}
@media (min-width: 720px) {
  .reportsheet-backdrop { align-items: center; }
  .reportsheet { border-radius: 16px; }
}
.reportsheet:focus { outline: none; }
.reportsheet-title { font-family: var(--display); font-size: 18px; font-weight: 600; margin: 0 0 10px; }
.reportform fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.reportform legend { font-weight: 600; font-size: 15px; padding: 0; margin-bottom: 6px; }
.reportreason {
  display: flex; align-items: center; gap: 10px; min-height: 44px;
  padding: 6px 10px; border: 1px solid var(--hairline); border-radius: 10px; margin-bottom: 6px; cursor: pointer;
}
.reportreason:has(input:checked) { border-color: var(--aurora); background: var(--aurora-soft); }
.reportreason:focus-within { outline: 2px solid var(--aurora); outline-offset: 1px; }
.reportreason input { width: 20px; height: 20px; margin: 0; accent-color: var(--aurora); flex: none; }
.reportnote { display: block; margin-top: 10px; font-size: 14px; }
.reportnote span { display: block; margin-bottom: 4px; color: var(--muted); }
.reportnote textarea {
  width: 100%; font: inherit; font-size: 16px; padding: 10px 12px; resize: vertical;
  border: 1px solid var(--hairline); border-radius: 10px; background: var(--ground); color: var(--ink);
}
.reportnote textarea:focus { outline: 2px solid var(--aurora); outline-offset: 1px; border-color: transparent; }
.reportstatus { min-height: 1.2em; margin: 8px 0 0; font-size: 13.5px; color: var(--bad); }
.reportthanks { font-weight: 600; margin: 0 0 6px; }
.reportactions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.reportactions button {
  font: inherit; font-size: 15px; font-weight: 600; cursor: pointer;
  min-height: 44px; padding: 10px 16px; border-radius: 12px; border: 1px solid transparent;
}
.report-send { background: var(--brand-button); color: var(--brand-button-text); }
.report-cancel { background: transparent; color: var(--muted); border-color: var(--hairline) !important; }
.reportactions button:disabled { opacity: .5; cursor: default; }
.reportactions button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* A phone keyboard is up (public/app.js followTheKeyboard): the chat is exactly the part of the screen the guest
   can see, so the message box and Send stay above the keyboard. The tagline and the assistant notice give way
   first when the room is short; the notice is back as soon as the keyboard closes. */
html.kb, html.kb body { overflow: hidden; }
html.kb .chat {
  position: fixed; left: 0; right: 0; top: var(--vvt, 0px);
  height: var(--vvh, 100dvh); margin: 0 auto; border-radius: 0; border-width: 0 1px;
}
html.kb-short header { padding: 8px 14px 6px; }
html.kb-short header p { display: none; }
html.kb-tiny header { display: none; }

/* A short window (a phone on its side, a wide window only 400px tall): the header and the composer take less room
   so the conversation keeps most of it. The assistant notice stays, smaller; only the tagline, which the message
   box placeholder repeats, goes. */
@media (max-height: 520px) {
  header { padding: 6px 14px 4px; }
  header h1 { font-size: 16px; }
  header #tagline { display: none; }
  .disclosure { margin-top: 6px !important; padding: 3px 8px; font-size: 11px; line-height: 1.35; }
  .disclosure.recorded-note { margin-top: 0 !important; padding: 0 8px; }
  .composer { padding: 8px 12px; padding-bottom: max(8px, env(safe-area-inset-bottom)); }
  .composer input, .composer button { padding-block: 9px; }
  .reportfoot { padding-bottom: max(2px, env(safe-area-inset-bottom)); }
  .reportfoot .reportbtn { min-height: 28px; }
}
html.kb-short .composer { padding: 8px 12px; }
html.kb-short .composer input, html.kb-short .composer button { padding-block: 9px; }
html.kb-short .reportfoot { display: none; }

/* Under 300px of height there is only room for the conversation, so the Report link is hidden. */
@media (max-height: 300px) { .reportfoot { display: none; } }

/* Hand-off form (public/handoffform.js): an inline card in the conversation, never a dialog.
   Positioned so its hidden field (absolute) stays inside it instead of making the whole page scroll. */
.hfform {
  position: relative; align-self: stretch; width: 100%; max-width: 100%; margin: 4px 0 6px;
  padding: 12px; border: 1px solid var(--hairline); border-radius: 14px; background: var(--raised);
}
.hf-title { margin: 0 0 8px; font-family: var(--display); font-weight: 600; font-size: 16px; overflow-wrap: anywhere; }
.hf-hint { margin: 0 0 6px; font-size: 13.5px; color: var(--muted); overflow-wrap: anywhere; }
.hf-field { margin: 0 0 8px; }
.hf-label { display: block; margin-bottom: 3px; font-size: 14px; color: var(--muted); overflow-wrap: anywhere; }
.hf-input {
  display: block; width: 100%; min-width: 0; font: inherit; font-size: 16px; min-height: 44px; padding: 9px 12px;
  border: 1px solid var(--hairline); border-radius: 10px; background: var(--surface); color: var(--ink);
}
.hf-input:focus { outline: 2px solid var(--aurora); outline-offset: 1px; border-color: transparent; }
.hf-input[aria-invalid="true"] { border-color: var(--bad); }
.hf-message { resize: vertical; min-height: 76px; }
.hf-error { margin: 3px 0 0; font-size: 13.5px; color: var(--bad); }
.hf-error[hidden] { display: none; }
.hf-consent { margin: 4px 0 8px; font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }
.hf-status { min-height: 1.2em; margin: 0 0 6px; font-size: 13.5px; color: var(--bad); }
.hf-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.hf-actions button {
  font: inherit; font-size: 15px; font-weight: 600; cursor: pointer; flex: 1 1 auto;
  min-height: 44px; padding: 10px 16px; border-radius: 12px; border: 1px solid transparent;
}
.hf-send { background: var(--brand-button); color: var(--brand-button-text); }
.hf-no { background: transparent; color: var(--muted); border-color: var(--hairline) !important; }
.hf-actions button:disabled { opacity: .5; cursor: default; }
.hf-actions button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.hf-thanks { align-self: flex-start; margin: 4px 0 6px; padding: 10px 14px; border-radius: 12px; background: var(--aurora-soft); font-weight: 600; overflow-wrap: anywhere; }
@media (max-width: 360px) { .hfform { padding: 10px; } .hf-actions button { flex-basis: 100%; } }

/* A very short window (phone on its side): the two notes (assistant, recorded) shrink a little more so the
   conversation keeps its room. Neither is hidden: guests are still told it is an assistant and that the chat is recorded. */
@media (max-height: 360px) {
  .disclosure { margin-top: 3px !important; padding: 2px 8px; font-size: 10px; line-height: 1.25; }
}
