/* WOHAA student chat — shell, bubbles and composer.
 *
 * Plain CSS on purpose. `tailwind.config.js` scans ./templates/**\/*.html only,
 * so a Tailwind class used from static/js/wohaa_chat.js would never be
 * generated — the chat JS therefore only ever writes classes defined here.
 * That also lets team_chat.html drop the runtime Tailwind CDN, which parsed
 * the DOM on every mutation of a page that mutates per character.
 *
 * The brand colours below were previously defined in a
 * <style type="text/tailwindcss"> block, which ONLY compiles under that CDN.
 * They live here now so removing the CDN cannot silently un-style the header.
 *
 * Colours are CSS custom properties so the appearance settings (dark mode,
 * background and accent presets) can override them without touching any rule.
 */

:root {
  --woh-purple: #582C83;
  --woh-orange: #F58220;
  --woh-orange-dark: #d9701a;
  --woh-header-lilac: #f5f1fa;

  --chat-bg: #f8fafc;
  --chat-surface: #ffffff;
  --chat-border: #e2e8f0;
  --chat-text: #1f2937;
  --chat-text-muted: #64748b;

  --user-bubble-bg: #e3f2fd;
  --user-bubble-border: #bbdefb;
  --user-bubble-text: #1a237e;
  --assistant-bubble-bg: #fff3e0;
  --assistant-bubble-border: #ffe0b2;
  --assistant-bubble-text: #333333;
}

* { box-sizing: border-box; }

/* The UA stylesheet's `[hidden] { display: none }` loses to any class that
   sets `display`, so `.history-banner` — which is `display: flex` — rendered
   despite its `hidden` attribute. Everything toggled by `.hidden = true` here
   is in that position, so the rule is stated once, up front. */
[hidden] { display: none !important; }

/* ---- Shell -------------------------------------------------------------
 * One flex column, one scroll container. Everything that is not the message
 * list is flex-shrink:0, so no rule anywhere needs to know the header's
 * height. The old layout subtracted a hardcoded 64px from 100vh for a header
 * that was 96px tall, then reserved a further 70px of margin for a composer
 * that was not actually fixed — which is what clipped the bottom of the list.
 */

html { height: 100%; }

body.wohaa-chat {
  margin: 0;
  padding: 0;
  /* --vh is maintained in JS from visualViewport; on mobile the browser's
     100vh does not shrink when the keyboard opens, which pushed the composer
     off-screen. The plain 100vh is the fallback for the first paint. */
  height: 100vh;
  height: calc(var(--vh, 1vh) * 100);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  font-family: 'Poppins', sans-serif;
  color: var(--chat-text);
  background-color: var(--chat-bg);
}

.panel-container {
  position: relative;
  width: 100%;
  flex: 1;
  min-height: 0;      /* without this a flex item refuses to shrink below its
                         content and the scroll container never scrolls */
  overflow: hidden;
}

.left-panel {
  position: absolute;
  inset: 0;
  background-color: var(--chat-bg);
}

.chat-container {
  height: 100%;
  overflow-y: auto;
  min-height: 0;
  padding: 1.5rem 1rem;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
}

/* padding-bottom is what allows the newest message to be scrolled all the way
   to the top of the viewport even when it is the last thing in the list.
   Without it scrollIntoView({block:"start"}) has nothing to scroll into. */
.chat-window {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 800px;
  margin: 0 auto;
  padding-bottom: 70vh;
}

/* ---- Header ------------------------------------------------------------ */

.chat-header {
  flex-shrink: 0;
  background-color: var(--woh-header-lilac);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  z-index: 50;
}

.chat-header-inner {
  max-width: 80rem;
  margin: 0 auto;
  padding: 0.9rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.chat-brand {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--woh-purple);
  text-decoration: none;
  white-space: nowrap;
}

.chat-brand span {
  font-weight: 300;
  color: var(--woh-orange);
}

/* position:relative anchors the settings popover, which is absolute at
   top:100% of this. */
.chat-nav {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* The header's gear: same hit area as the composer's send button, but it
   should read as part of the bar rather than as a second primary action. */
.chat-icon-button-plain {
  width: 40px;
  height: 40px;
  border-color: transparent;
  background-color: transparent;
}

.chat-icon-button-plain svg { width: 22px; height: 22px; }
.chat-icon-button-plain:hover:not(:disabled) { background-color: rgba(88, 44, 131, 0.1); }

.chat-nav-btn {
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 500;
  color: #fff;
  background-color: var(--woh-orange);
  border: none;
  border-radius: 9999px;
  padding: 0.5rem 1.25rem;
  cursor: pointer;
  text-decoration: none;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  transition: background-color 0.2s ease, transform 0.2s ease;
}

.chat-nav-btn:hover {
  background-color: var(--woh-orange-dark);
  transform: scale(1.05);
}

.chat-nav-link {
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--woh-purple);
  background: none;
  border: none;
  cursor: pointer;
  text-decoration: none;
  padding: 0.5rem 0.75rem;
  border-radius: 6px;
}

.chat-nav-link:hover { background-color: rgba(88, 44, 131, 0.08); }

@media (max-width: 640px) {
  .chat-header-inner { padding: 0.75rem 1rem; }
  .chat-brand { font-size: 1.15rem; }
  .chat-nav-btn { font-size: 0.85rem; padding: 0.45rem 0.9rem; }
}

/* ---- Message bubbles --------------------------------------------------- */

.user-message,
.assistant-message {
  font-size: 1.05rem;
  line-height: 1.5;
  padding: 0.875rem 1.25rem;
  border-radius: 15px;
  margin: 0.25rem 0;
  max-width: 80%;
  white-space: pre-wrap;
  word-break: break-word;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.user-message {
  align-self: flex-end;
  margin-left: auto;
  background-color: var(--user-bubble-bg);
  border: 2px solid var(--user-bubble-border);
  color: var(--user-bubble-text);
}

.assistant-message {
  align-self: flex-start;
  margin-right: auto;
  background-color: var(--assistant-bubble-bg);
  border: 2px solid var(--assistant-bubble-border);
  color: var(--assistant-bubble-text);
}

/* A backend failure used to render as an ordinary assistant reply, so a
   student could not tell "the AI said this" from "this did not work". */
.assistant-message.error-message {
  background-color: #fef2f2;
  border-color: #fecaca;
  color: #991b1b;
}

.user-message a,
.assistant-message a {
  color: #1d4ed8;
  text-decoration: underline;
}

.message-image {
  max-width: 100%;
  border-radius: 10px;
  cursor: pointer;
  display: block;
}

.message-image:hover { opacity: 0.9; }

/* The pending row is a bare flex child, not a bubble — it should not look
   like something the assistant said. */
.message-pending {
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.25rem;
  color: var(--chat-text-muted);
  font-style: italic;
}

.message-loading {
  width: 32px;
  height: 32px;
}

/* ---- Composer ----------------------------------------------------------
 * A plain flex sibling. It was previously declared three times — fixed;bottom
 * at one point, sticky;top at another, and the later rule won, so it was
 * anchored to nothing at all.
 */

/* The bar spans the viewport; only its contents are constrained to the
   message column's width, so the surface and the top border reach both
   edges however wide the window is. */
.textbox-container {
  flex-shrink: 0;
  background-color: var(--chat-surface);
  border-top: 2px solid var(--woh-purple);
  padding: 0.9rem 1rem;
  /* keeps the composer clear of the iOS home indicator */
  padding-bottom: calc(0.9rem + env(safe-area-inset-bottom, 0px));
}

.composer-row {
  display: flex;
  gap: 0.75rem;
  align-items: flex-end;
  max-width: 800px;
  margin: 0 auto;
  width: 100%;
}

.expandable-textbox {
  flex: 1;
  min-height: 50px;
  max-height: 120px;
  overflow-y: auto;          /* max-height used to clip instead of scroll */
  padding: 12px 20px;
  border: 3px solid var(--woh-purple);
  border-radius: 25px;
  font-family: inherit;
  font-size: 1.15rem;
  line-height: 1.4;
  resize: none;
  outline: none;
  background-color: var(--chat-surface);
  color: inherit;
}

.expandable-textbox:focus { border-color: var(--woh-orange); }
.expandable-textbox::placeholder { color: #94a3b8; }
.expandable-textbox:disabled { background-color: #e2e8f0; cursor: not-allowed; }

.chat-icon-button {
  flex-shrink: 0;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 2px solid var(--woh-purple);
  background-color: var(--chat-surface);
  color: var(--woh-purple);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background-color 0.2s ease, transform 0.1s ease;
}

.chat-icon-button svg { width: 24px; height: 24px; }
.chat-icon-button:hover:not(:disabled) { background-color: var(--woh-header-lilac); }
.chat-icon-button:active:not(:disabled) { transform: scale(0.95); }
.chat-icon-button:disabled { opacity: 0.45; cursor: not-allowed; }

@media (max-width: 640px) {
  .textbox-container { padding: 0.6rem 0.75rem; }
  .composer-row { gap: 0.5rem; }
  .expandable-textbox { font-size: 1rem; min-height: 45px; padding: 10px 16px; }
  .chat-icon-button { width: 45px; height: 45px; }
  .chat-icon-button svg { width: 20px; height: 20px; }
  .user-message, .assistant-message { max-width: 90%; font-size: 1rem; }
}

/* ---- Image lightbox ---------------------------------------------------- */

.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.85);
  z-index: 1000;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.modal-overlay.open { display: flex; }

.modal-content {
  position: relative;
  max-width: 90%;
  max-height: 90vh;
}

.modal-content > img {
  max-width: 100%;
  max-height: 90vh;
  object-fit: contain;
  border-radius: 8px;
  display: block;
}

.close-modal {
  position: absolute;
  top: -2.5rem;
  right: 0;
  background: none;
  border: none;
  color: #fff;
  font-size: 2.5rem;
  line-height: 1;
  cursor: pointer;
}

.close-modal:hover { color: #cbd5e1; }

/* ==== Appearance settings ==============================================
 *
 * Everything below is driven by data-attributes on <html>/<body>, written by
 * applySettings() in wohaa_chat.js and, before first paint, by the inline
 * script in templates/wohaa/_chat_prepaint.html.
 *
 * The ids here must stay in step with UI_SETTINGS_ALLOWED in
 * wohaa_api/wohaa_engine.py, the tables in wohaa_chat.js and the TINT map in
 * _chat_prepaint.html. Nothing enforces that; change one, change all four.
 */

/* ---- Fonts -------------------------------------------------------------
 * OpenDyslexic is self-hosted rather than pulled from fonts.cdnfonts.com the
 * way sgpt does it. Two reasons: font-src in wohaa/middleware.py is 'self',
 * so a CDN would be silently blocked in the browser while passing every test;
 * and this is a children's product, so one fewer third party seeing their IP
 * on every page load is worth two files.
 */
@font-face {
  font-family: 'OpenDyslexic';
  src: url("../fonts/OpenDyslexic-Regular.209dda5cb267.woff2") format('woff2');
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: 'OpenDyslexic';
  src: url("../fonts/OpenDyslexic-Bold.df553171a66f.woff2") format('woff2');
  font-weight: 700;
  font-display: swap;
}

/* The `*` is deliberate: a dyslexia-friendly face that applies to the body
   but not to the message bubbles would be no help at all. */
body[data-font="opendyslexic"],
body[data-font="opendyslexic"] * { font-family: 'OpenDyslexic', sans-serif !important; }

body[data-font="lexend"],
body[data-font="lexend"] * { font-family: 'Lexend', 'Poppins', sans-serif !important; }

/* ---- Text size ---------------------------------------------------------
 * On <html>, so it scales every rem in the sheet at once rather than needing
 * a size rule per element.
 */
html[data-textsize="small"] { font-size: 87.5%; }
html[data-textsize="large"] { font-size: 112.5%; }

/* ---- Reading tint (the Irlen overlay) ----------------------------------
 * The point is a wash over the whole reading surface, so every panel between
 * the body and the text has to become transparent — otherwise the tint sits
 * behind an opaque white chat area and does nothing.
 */
body.tint-active { background-color: var(--tint-color) !important; }

body.tint-active .chat-header,
body.tint-active .panel-container,
body.tint-active .left-panel,
body.tint-active .chat-container,
body.tint-active .textbox-container,
body.tint-active .settings-panel { background-color: transparent !important; }

body.tint-active .chat-header { border-bottom: 1px solid rgba(0, 0, 0, 0.1); }
body.tint-active .assistant-message,
body.tint-active .user-message { background-color: rgba(255, 255, 255, 0.55); }
body.tint-active .expandable-textbox,
body.tint-active .chat-icon-button { background-color: rgba(255, 255, 255, 0.6); }

/* ---- Dark mode ---------------------------------------------------------
 * Mutually exclusive with the tint (normalizeSettings enforces it) — both
 * own the body background, and together they produce mud.
 */
body.dark-mode {
  --chat-bg: #0f172a;
  --chat-surface: #1e293b;
  --chat-border: #334155;
  --chat-text: #e2e8f0;
  --chat-text-muted: #94a3b8;
  --woh-header-lilac: #1e293b;
  --woh-purple: #c4a5e8;
  --user-bubble-bg: #1e3a5f;
  --user-bubble-border: #2c5282;
  --user-bubble-text: #dbeafe;
  --assistant-bubble-bg: #292524;
  --assistant-bubble-border: #44403c;
  --assistant-bubble-text: #e7e5e4;
}

body.dark-mode .user-message a,
body.dark-mode .assistant-message a { color: #93c5fd; }
body.dark-mode .expandable-textbox::placeholder { color: #64748b; }
body.dark-mode .assistant-message.error-message {
  background-color: #450a0a;
  border-color: #7f1d1d;
  color: #fecaca;
}

/* ---- Background presets ------------------------------------------------ */
body:not(.dark-mode)[data-bg="cream"]    { --chat-bg: #fffbeb; }
body:not(.dark-mode)[data-bg="mint"]     { --chat-bg: #ecfdf5; }
body:not(.dark-mode)[data-bg="sky"]      { --chat-bg: #eff6ff; }
body:not(.dark-mode)[data-bg="lavender"] { --chat-bg: #f5f3ff; }
body:not(.dark-mode)[data-bg="blush"]    { --chat-bg: #fdf2f8; }
body:not(.dark-mode)[data-bg="sand"]     { --chat-bg: #fefce8; }
body:not(.dark-mode)[data-bg="grey"]     { --chat-bg: #f1f5f9; }

/* The two gradients paint on .left-panel — a gradient on a scrolling
   container would repeat down the scroll — so the scroll area goes clear. */
body:not(.dark-mode)[data-bg="sunrise"] .left-panel {
  background-image: linear-gradient(160deg, #fff1f2, #ffe4e6, #fef3c7);
}
body:not(.dark-mode)[data-bg="ocean"] .left-panel {
  background-image: linear-gradient(160deg, #ecfeff, #cffafe, #ede9fe);
}
body:not(.dark-mode)[data-bg="sunrise"] .chat-container,
body:not(.dark-mode)[data-bg="ocean"] .chat-container { background-color: transparent; }

/* ---- Accent presets ---------------------------------------------------- */
body[data-accent="orange"] { --woh-purple: #c2410c; }
body[data-accent="blue"]   { --woh-purple: #1d4ed8; --woh-orange: #2563eb; --woh-orange-dark: #1e40af; }
body[data-accent="green"]  { --woh-purple: #15803d; --woh-orange: #16a34a; --woh-orange-dark: #166534; }
body[data-accent="pink"]   { --woh-purple: #be185d; --woh-orange: #db2777; --woh-orange-dark: #9d174d; }
body[data-accent="teal"]   { --woh-purple: #0f766e; --woh-orange: #0d9488; --woh-orange-dark: #115e59; }

/* ==== Settings panel ==================================================== */

.settings-panel {
  position: absolute;
  top: 100%;
  right: 1rem;
  z-index: 60;
  width: 300px;
  max-width: calc(100vw - 2rem);
  max-height: 70vh;
  overflow-y: auto;
  display: none;
  padding: 0.75rem 1rem;
  background-color: var(--chat-surface);
  border: 1px solid var(--chat-border);
  border-radius: 12px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
  text-align: left;
}

.settings-panel.visible { display: block; }

.settings-section { padding: 0.6rem 0; border-bottom: 1px solid var(--chat-border); }
.settings-section:last-child { border-bottom: none; }

.settings-heading {
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--chat-text-muted);
  margin-bottom: 0.5rem;
}

.settings-swatches { display: flex; flex-wrap: wrap; gap: 8px; }

.settings-swatch {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid var(--chat-border);
  cursor: pointer;
  padding: 0;
  font-size: 0.8rem;
  line-height: 1;
  color: var(--chat-text-muted);
  background-color: transparent;
}

.settings-swatch:hover { transform: scale(1.08); }
.settings-swatch.active {
  border-color: var(--woh-purple);
  box-shadow: 0 0 0 2px rgba(88, 44, 131, 0.25);
}

.settings-options { display: flex; flex-wrap: wrap; gap: 8px; }

.settings-option {
  flex: 1 1 auto;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--chat-border);
  border-radius: 8px;
  background-color: transparent;
  color: inherit;
  font-size: 0.9rem;
  cursor: pointer;
}

.settings-option:hover { border-color: var(--woh-purple); }
.settings-option.active {
  border-color: var(--woh-purple);
  color: var(--woh-purple);
  font-weight: 600;
}

/* ==== Chat history (read only) ========================================== */

.history-backdrop {
  position: fixed;
  inset: 0;
  background-color: rgba(15, 23, 42, 0.35);
  z-index: 70;
}

.history-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 340px;
  max-width: 90vw;
  z-index: 80;
  display: flex;
  flex-direction: column;
  background-color: var(--chat-surface);
  border-left: 1px solid var(--chat-border);
  box-shadow: -8px 0 24px rgba(0, 0, 0, 0.12);
  transform: translateX(100%);
  transition: transform 0.25s ease;
}

.history-panel.visible { transform: translateX(0); }

.history-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem;
  border-bottom: 1px solid var(--chat-border);
}

.history-heading { font-size: 1.05rem; font-weight: 700; }

.history-close {
  background: none;
  border: none;
  color: var(--chat-text-muted);
  font-size: 1.75rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.25rem;
}

.history-body { flex: 1 1 auto; overflow-y: auto; padding: 0.5rem; }

.history-empty {
  padding: 1.5rem 1rem;
  color: var(--chat-text-muted);
  text-align: center;
  font-size: 0.95rem;
}

.history-retry {
  display: block;
  margin: 0.75rem auto 0;
  padding: 0.4rem 1rem;
  border: 1px solid var(--chat-border);
  border-radius: 8px;
  background: none;
  color: inherit;
  cursor: pointer;
}

.history-list { list-style: none; margin: 0; padding: 0; }

.history-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 0.75rem;
  border-radius: 8px;
  cursor: pointer;
}

.history-row:hover { background-color: var(--woh-header-lilac); }

.history-row-main { flex: 1 1 auto; min-width: 0; display: flex;
                    flex-direction: column; gap: 2px; }

.history-row-title { font-weight: 600; font-size: 0.95rem; }

.history-row-sub {
  font-size: 0.85rem;
  color: var(--chat-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.history-badge {
  flex: 0 0 auto;
  font-size: 0.7rem;
  font-weight: 600;
  padding: 0.15rem 0.5rem;
  border-radius: 9999px;
  background-color: var(--woh-header-lilac);
  color: var(--woh-purple);
}

/* The banner replaces the composer while an old chat is open, so the page can
   never look like somewhere you can type. */
.history-banner {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.6rem 1rem;
  background-color: var(--woh-header-lilac);
  border-bottom: 1px solid var(--chat-border);
  color: var(--woh-purple);
  font-size: 0.95rem;
}

.history-back-btn {
  padding: 0.35rem 1rem;
  border: 1px solid var(--woh-purple);
  border-radius: 9999px;
  background: none;
  color: var(--woh-purple);
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

.history-back-btn:hover { background-color: rgba(88, 44, 131, 0.1); }

.history-preview { background-color: var(--chat-surface); border-radius: 12px;
                   padding: 1.25rem; width: 520px; max-width: 90vw; }

.history-preview-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.75rem;
}

.history-preview-title { font-size: 1.05rem; font-weight: 700; margin: 0; }

.history-preview-turns {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-height: 45vh;
  overflow-y: auto;
  padding: 0.25rem;
}

.history-preview-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-top: 1rem;
}

.history-action-btn {
  padding: 0.5rem 1.1rem;
  border-radius: 9999px;
  border: 1px solid var(--woh-purple);
  background-color: var(--woh-purple);
  color: #fff;
  font-family: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}

.history-action-btn.secondary { background: none; color: var(--woh-purple); }
.history-action-btn:disabled { opacity: 0.5; cursor: wait; }

/* The preview modal reuses the lightbox shell, but its close button sits
   inside the card rather than floating above a full-bleed image. */
.history-modal .modal-content { max-width: none; max-height: none; }
.history-modal .close-modal {
  position: static;
  color: var(--chat-text-muted);
  font-size: 1.75rem;
}
