/* css/remi.css — Remi AI Concierge
 *
 * All Remi UI lives here, scoped with the .remi- prefix.
 * Uses existing tokens from css/tokens.css — no new colors, no new fonts.
 *
 * Layout states (added incrementally across Phases 4-8):
 *   .remi--docked   : fixed bottom-right (360x480), site-wide  [Phase 4]
 *   .remi--pill     : minimized collapsed pill (240x56)        [Phase 5]
 *   .remi--hero     : homepage hero right panel (480x560)      [Phase 7]
 *   .remi--mobile-inline : mobile inline card below hero      [Phase 8]
 *   .remi--mobile-bar    : mobile fixed bottom bar             [Phase 8]
 *   .remi--mobile-drawer : mobile full-screen drawer           [Phase 8]
 *
 * Structural contract: #remi-root always contains a single .remi element.
 * The layout state class (docked, pill, hero, etc.) lives on #remi-root,
 * not on .remi — so JS can swap states with a single classList change.
 */

#remi-root {
  position: fixed;
  z-index: 45; /* below the navbar (z-index 50) */
  pointer-events: none; /* children re-enable */
}

#remi-root .remi {
  pointer-events: auto;
  font-family: var(--font-family);
  color: var(--color-text);
  background: var(--color-surface-solid);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  height: 100%;
}

/* ===== HEADER ===== */
.remi-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface-solid);
  flex-shrink: 0;
}

.remi-avatar {
  width: 24px;
  height: 24px;
  border-radius: 25%;
  flex-shrink: 0;
  animation: remi-pulse 2.4s ease-in-out infinite;
}

.remi-avatar img {
  display: block;
  width: 100%;
  height: 100%;
}

@keyframes remi-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--color-brand-a30); }
  50%      { box-shadow: 0 0 0 6px var(--color-brand-a4); }
}

.remi-title {
  flex: 1;
  line-height: 1.2;
  min-width: 0;
}

.remi-title-name {
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--color-text);
}

.remi-title-subtitle {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.remi-header-actions {
  display: flex;
  gap: var(--space-1);
}

.remi-icon-btn {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  border: 0;
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--duration-fast) var(--ease-default), color var(--duration-fast) var(--ease-default);
}

.remi-icon-btn:hover {
  background: var(--color-brand-a8);
  color: var(--color-text);
}

/* ===== MESSAGES AREA ===== */
.remi-messages {
  flex: 1;
  overflow-y: auto;
  /* Explicit overflow-x: hidden — without it, the CSS spec treats a
   * block with `overflow-y: auto` and `overflow-x: visible` as
   * `overflow: auto auto`, which lets a long unbreakable string (e.g.
   * an email address a user types into the chat) scroll the messages
   * container horizontally and, on iOS Safari specifically, can
   * propagate width up to the drawer. */
  overflow-x: hidden;
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--color-bg);
  min-height: 0;
  min-width: 0;
}

.remi-msg {
  display: flex;
  gap: var(--space-2);
  max-width: 85%;
  /* Prevent the flex-column parent (.remi-messages) from shrinking bubbles
   * when the container is full. Without this, any bubble with `overflow:
   * hidden` or similar would collapse below its natural size. */
  flex-shrink: 0;
  /* Allow the bubble to shrink below its min-content width so a long
   * unbreakable token (email, URL) can never push it wider than
   * max-width: 85%. WebKit's flex min-sizing otherwise honors the
   * intrinsic min-content of the child, which defeats max-width. */
  min-width: 0;
}

.remi-msg--user {
  align-self: flex-end;
  flex-direction: row-reverse;
}

.remi-msg--ai {
  align-self: flex-start;
}

.remi-msg-avatar {
  width: 16px;
  height: 16px;
  border-radius: var(--radius-full);
  background: var(--color-brand);
  flex-shrink: 0;
  margin-top: 4px;
}

.remi-msg-body {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-lg);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  /* Break long unbreakable tokens (emails, URLs) anywhere rather than
   * overflowing their container. `overflow-wrap: break-word` only
   * breaks as a last resort and still allows a single long word to
   * push the bubble's min-content width larger than its container;
   * `word-break: break-word` is the belt-and-suspenders version that
   * WebKit honors at the min-content sizing step. */
  word-wrap: break-word;
  overflow-wrap: anywhere;
  word-break: break-word;
  min-width: 0;
  max-width: 100%;
}

.remi-msg--user .remi-msg-body {
  background: var(--color-brand);
  color: #fff;
  border-bottom-right-radius: var(--radius-sm);
}

.remi-msg--ai .remi-msg-body {
  background: var(--color-surface-solid);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-bottom-left-radius: var(--radius-sm);
}

/* ===== RENDERED MARKDOWN INSIDE MESSAGES ===== */
.remi-msg-body strong {
  font-weight: 600;
  color: inherit;
}

.remi-msg-body em {
  font-style: italic;
}

.remi-msg-body code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--color-brand-a8);
  padding: 0 4px;
  border-radius: var(--radius-sm);
  color: inherit;
}

.remi-msg-body ul.remi-md-ul,
.remi-msg-body ol.remi-md-ol {
  margin: var(--space-2) 0;
  padding-left: var(--space-5);
  list-style-position: outside;
}

.remi-msg-body ul.remi-md-ul {
  list-style-type: disc;
}

.remi-msg-body ol.remi-md-ol {
  list-style-type: decimal;
}

.remi-msg-body li {
  margin: 2px 0;
  line-height: var(--leading-normal);
}

.remi-msg-body li::marker {
  color: var(--color-brand);
}

/* Streaming cursor (used in Phase 5) */
.remi-cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  background: var(--color-brand);
  vertical-align: text-bottom;
  animation: remi-cursor-blink 1s step-end infinite;
  margin-left: 1px;
}

@keyframes remi-cursor-blink {
  0%, 50%    { opacity: 1; }
  51%, 100%  { opacity: 0; }
}

/* ===== SUGGESTED PROMPT CHIPS ===== */
.remi-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0 var(--space-4) var(--space-3);
  flex-shrink: 0;
}

.remi-chip {
  background: var(--color-surface-solid);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  color: var(--color-text);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-default), transform var(--duration-fast) var(--ease-default);
  font-family: inherit;
  text-align: left;
  line-height: 1.3;
}

.remi-chip:hover {
  border-color: var(--color-brand);
  transform: scale(1.02);
}

/* ===== COMPOSER ===== */
.remi-composer {
  border-top: 1px solid var(--color-border);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-solid);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex-shrink: 0;
  /* Allow the composer to shrink below its content's min-content so
   * the textarea's WebKit-intrinsic width (derived from its default
   * `cols` attribute) can never push it wider than the drawer. */
  min-width: 0;
  max-width: 100%;
}

.remi-composer-row {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  /* Same reason as .remi-composer — the flex row needs to be free to
   * shrink below its children's min-content. */
  min-width: 0;
  max-width: 100%;
}

.remi-composer-input {
  flex: 1;
  /* WebKit gives a <textarea> an intrinsic min-content width derived
   * from its default `cols` attribute (20). In a flex row with
   * `flex: 1`, the default `min-width: auto` resolves to that
   * min-content, so the textarea refuses to shrink below ~200px even
   * when the parent row is narrower. Explicit `min-width: 0` lets
   * flex shrink the textarea down to zero width as designed. */
  min-width: 0;
  resize: none;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: var(--leading-normal);
  outline: none;
  max-height: 100px;
  min-height: 20px;
  padding: 0;
}

.remi-composer-input::placeholder {
  color: var(--color-text-muted);
}

.remi-send-btn {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  background: var(--color-brand);
  color: #fff;
  border: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background var(--duration-fast) var(--ease-default), opacity var(--duration-fast) var(--ease-default);
  padding: 0;
}

.remi-send-btn:hover:not(:disabled) {
  background: var(--color-brand-dark);
}

.remi-send-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ===== STATE: DOCKED ===== */
#remi-root.remi--docked {
  bottom: 24px;
  right: 24px;
  width: 360px;
  height: 480px;
}

/* When the homepage hero hosts both the restored .hero-mockup AND the
 * docked Remi chat, reserve the bottom-right corner for Remi so the
 * dashboard panel's right edge doesn't disappear behind the chat card.
 *
 * Also widens the mockup container and bumps the two panels' width
 * overrides so both the chat panel and the dashboard panel feel weightier
 * than the default 55%/70% that sections.css sets — the default was tuned
 * for a 1024px container before the right-hand gutter was carved out. The
 * right panel grows the most because it's the one that was getting crushed.
 *
 * Constraint: right panel's right edge must stop before Remi's left edge
 * at x = viewport_w - 24 - 360 = 1056 on a 1440 viewport. With the numbers
 * below the right panel ends around x≈988, giving ~68px of breathing room.
 *
 * Applies only at viewports wide enough to render Remi at its full 360x480
 * docked size (the mobile breakpoint lives in a different layout where the
 * mockup and Remi don't coexist on screen). */
@media (min-width: 1024px) {
  section.hero > .hero-mockup {
    max-width: 1160px;
    padding-right: calc(var(--space-8) + 280px);
  }
  section.hero > .hero-mockup .mockup-panel--left {
    width: 62%;
  }
  section.hero > .hero-mockup .mockup-panel--right {
    width: 78%;
  }
}

/* ===== STATE: PILL (minimized) ===== */
#remi-root.remi--pill {
  bottom: 24px;
  right: 24px;
  width: 240px;
  height: 56px;
}

#remi-root.remi--pill .remi {
  cursor: pointer;
}

#remi-root.remi--pill .remi-messages,
#remi-root.remi--pill .remi-chips,
#remi-root.remi--pill .remi-composer {
  display: none;
}

#remi-root.remi--pill .remi-header {
  height: 100%;
  border-bottom: 0;
  padding: var(--space-3) var(--space-4);
}

#remi-root.remi--pill .remi-title-subtitle {
  display: none;
}

#remi-root.remi--pill .remi-title-name::after {
  content: ' · online';
  color: var(--color-text-muted);
  font-weight: 400;
}

/* ===== STATE: HERO (homepage, before scroll-dock) =====
 * The actual top/left/width/height values are set by js/remi.js via
 * inline styles, based on the hero slot's getBoundingClientRect() at
 * load time. CSS here only sets the initial visibility and clears any
 * conflicting position shorthand from .remi--docked.
 *
 * The same element transitions to docked via inline style updates on
 * scroll — no separate DOM tree, no class swap, no flicker. */
#remi-root.remi--hero {
  /* width/height/top/left are all set via inline style by the morph script */
  bottom: auto;
  right: auto;
}

/* A small anti-flicker: while the morph script hasn't yet measured the
 * hero slot (first paint), keep the element visually hidden so it doesn't
 * flash in the default docked position. The JS removes this class on the
 * first animation frame. */
#remi-root.remi--hero.remi--measuring {
  opacity: 0;
  pointer-events: none;
}

/* ===== CONFIRMATION CARD ===== */
.remi-confirm {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface-solid);
  margin: var(--space-2) 0;
  overflow: hidden;
  font-size: var(--text-sm);
  box-shadow: var(--shadow-md);
  /* CRITICAL: In a flex-column parent (.remi-messages), `overflow: hidden`
   * on the child collapses `min-height: auto` to `min-height: 0`. Combined
   * with the default `flex-shrink: 1`, the card gets squashed to whatever
   * vertical space is left over by the other messages — title/body/actions
   * then clip invisibly via the card's own overflow. `flex-shrink: 0` keeps
   * the natural content height so parent overflow-y: auto scrolls instead. */
  flex-shrink: 0;
}

.remi-confirm--error {
  border-color: #C0453A;
}

.remi-confirm--success {
  border-color: var(--color-sage);
}

.remi-confirm-title {
  padding: var(--space-3) var(--space-4);
  font-weight: 600;
  color: var(--color-text);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border-bottom: 1px solid var(--color-border);
}

.remi-confirm-icon {
  font-size: 16px;
  line-height: 1;
  flex-shrink: 0;
}

.remi-confirm-body {
  padding: var(--space-3) var(--space-4);
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-1) var(--space-3);
}

.remi-confirm-label {
  font-size: var(--text-tag);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  padding-top: 2px;
  white-space: nowrap;
}

.remi-confirm-value {
  font-size: var(--text-sm);
  color: var(--color-text);
  word-break: break-word;
}

.remi-confirm-actions {
  padding: var(--space-3) var(--space-4);
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
  border-top: 1px solid var(--color-border);
  background: var(--color-bg);
}

.remi-confirm-btn {
  border: 1px solid var(--color-border);
  background: var(--color-surface-solid);
  color: var(--color-text);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: 500;
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-default);
}

.remi-confirm-btn:hover:not(:disabled) {
  border-color: var(--color-brand);
}

.remi-confirm-btn--primary {
  background: var(--color-brand);
  color: #fff;
  border-color: var(--color-brand);
}

.remi-confirm-btn--primary:hover:not(:disabled) {
  background: var(--color-brand-dark);
  border-color: var(--color-brand-dark);
}

.remi-confirm-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.remi-confirm-error-msg {
  padding: var(--space-2) var(--space-4);
  color: #C0453A;
  font-size: var(--text-xs);
  border-top: 1px solid var(--color-border);
  background: rgba(192, 69, 58, 0.06);
  line-height: var(--leading-normal);
}

.remi-confirm--collapsed .remi-confirm-body {
  display: none;
}

.remi-confirm--collapsed .remi-confirm-actions {
  display: none;
}

.remi-confirm--collapsed .remi-confirm-title {
  border-bottom: 0;
  opacity: 0.7;
}

/* Inline calendly open button (shown after book_a_demo success) */
.remi-confirm-calendly-link {
  display: inline-block;
  padding: var(--space-2) var(--space-4);
  background: var(--color-brand);
  color: #fff;
  text-decoration: none;
  border-radius: var(--radius-md);
  font-size: var(--text-xs);
  font-weight: 500;
  margin: var(--space-2) var(--space-4) var(--space-3);
}

.remi-confirm-calendly-link:hover {
  background: var(--color-brand-dark);
}

/* ===== MOBILE BREAKPOINT (< 768px) ===== */
@media (max-width: 767px) {
  /* Suppress desktop states entirely — mobile JS will add mobile classes
     and clear any inline styles left over from setupHeroMorph. */
  #remi-root.remi--hero,
  #remi-root.remi--docked,
  #remi-root.remi--pill,
  #remi-root.remi--hero-docked {
    position: static;
    width: auto;
    height: auto;
    top: auto;
    left: auto;
    right: auto;
    bottom: auto;
  }

  /* --- Mobile inline card is disabled on phones — we go straight to the
         fixed bottom bar so the hero/content stays uncluttered. The inline
         mode class is still supported below in case setupMobileStates sets
         it, but it collapses to a 0-height no-op. --- */
  #remi-root.remi--mobile-inline {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: calc(56px + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    border-top: 1px solid var(--color-border);
    background: var(--color-surface-solid);
    z-index: 45;
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04);
  }

  #remi-root.remi--mobile-inline .remi {
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
    flex-direction: row;
    align-items: center;
    padding: 0;
    height: 56px;
  }

  #remi-root.remi--mobile-inline .remi-messages,
  #remi-root.remi--mobile-inline .remi-chips,
  #remi-root.remi--mobile-inline .remi-composer,
  #remi-root.remi--mobile-inline .remi-header-actions {
    display: none;
  }

  #remi-root.remi--mobile-inline .remi-header {
    border-bottom: 0;
    padding: 0 var(--space-4);
    flex: 1;
    height: 56px;
    background: transparent;
  }

  #remi-root.remi--mobile-inline .remi-title-subtitle {
    display: none;
  }

  #remi-root.remi--mobile-inline .remi-title-name::after {
    content: ' — tap to chat';
    color: var(--color-text-muted);
    font-weight: 400;
  }

  #remi-root.remi--mobile-inline::after {
    content: '▲';
    color: var(--color-text-muted);
    position: absolute;
    right: var(--space-5);
    top: 28px;
    transform: translateY(-50%);
    font-size: 10px;
    pointer-events: none;
  }

  /* --- Mobile bottom bar (fixed, appears after scroll-past on homepage,
         or on page load for non-homepage pages) --- */
  #remi-root.remi--mobile-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: calc(56px + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    border-top: 1px solid var(--color-border);
    background: var(--color-surface-solid);
    z-index: 45;
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04);
  }

  #remi-root.remi--mobile-bar .remi {
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
    flex-direction: row;
    align-items: center;
    padding: 0;
    height: 56px;
  }

  /* Hide every part of the chat except the header row in bottom-bar mode */
  #remi-root.remi--mobile-bar .remi-messages,
  #remi-root.remi--mobile-bar .remi-chips,
  #remi-root.remi--mobile-bar .remi-composer,
  #remi-root.remi--mobile-bar .remi-header-actions {
    display: none;
  }

  #remi-root.remi--mobile-bar .remi-header {
    border-bottom: 0;
    padding: 0 var(--space-4);
    flex: 1;
    height: 56px;
    background: transparent;
  }

  #remi-root.remi--mobile-bar .remi-title-subtitle {
    display: none;
  }

  #remi-root.remi--mobile-bar .remi-title-name::after {
    content: ' — tap to chat';
    color: var(--color-text-muted);
    font-weight: 400;
  }

  #remi-root.remi--mobile-bar::after {
    content: '▲';
    color: var(--color-text-muted);
    position: absolute;
    right: var(--space-5);
    top: 28px;
    transform: translateY(-50%);
    font-size: 10px;
    pointer-events: none;
  }

  /* --- Mobile full-screen drawer ---
     Uses top/bottom for box sizing (no explicit height) so the drawer
     always matches the visible viewport, including when mobile Chrome's
     URL bar is showing. Belt-and-suspenders: 100dvh fallback. The flex
     column inside needs min-height: 0 so the messages area can shrink
     and keep the composer pinned to the bottom. */
  #remi-root.remi--mobile-drawer {
    position: fixed;
    left: 0;
    right: 0;
    top: 40px;
    bottom: 0;
    width: 100%;
    /* The JS installDrawerViewportTracking overrides left/width/top/height
     * inline from visualViewport on every resize/scroll (see js/remi.js).
     * These CSS values are the fallback for `window.visualViewport`
     * being unavailable. */
    max-width: 100vw;
    max-height: calc(100dvh - 40px);
    /* Belt-and-suspenders: clip any child that somehow escapes the
     * flex min-width: 0 guards below. On iOS Safari, a position: fixed
     * element's containing block is the layout viewport, which can in
     * rare cases be wider than the visual viewport — clipping here
     * guarantees the drawer never appears to scroll horizontally. */
    overflow: hidden;
    z-index: 55;
    animation: remi-drawer-in 240ms var(--ease-default);
    display: flex;
    flex-direction: column;
  }

  #remi-root.remi--mobile-drawer .remi {
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    border-bottom: 0;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }

  #remi-root.remi--mobile-drawer .remi-messages {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  #remi-root.remi--mobile-drawer .remi-chips,
  #remi-root.remi--mobile-drawer .remi-composer {
    flex-shrink: 0;
  }

  /* Drag-handle affordance at the very top of the drawer header */
  #remi-root.remi--mobile-drawer .remi-header {
    padding-top: var(--space-5);
    position: relative;
  }

  #remi-root.remi--mobile-drawer .remi-header::before {
    content: '';
    display: block;
    position: absolute;
    top: 8px;
    left: 50%;
    transform: translateX(-50%);
    width: 36px;
    height: 4px;
    border-radius: 2px;
    background: var(--color-border);
  }

  /* The drawer is pinned to the visualViewport via JS (see
     installDrawerViewportTracking in js/remi.js). That means when the
     soft keyboard opens, the drawer's bottom edge already equals the
     top of the keyboard — so the composer doesn't need the
     --remi-kb-inset padding hack. Keep safe-area-inset-bottom only. */
  #remi-root.remi--mobile-drawer .remi-composer {
    padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  }

  @keyframes remi-drawer-in {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
  }
}

@media (max-width: 767px) and (prefers-reduced-motion: reduce) {
  #remi-root.remi--mobile-drawer {
    animation: none;
  }
}

/* ===== REDUCED MOTION ===== */
@media (prefers-reduced-motion: reduce) {
  .remi-avatar,
  .remi-msg-avatar {
    animation: none;
  }
  .remi-cursor {
    animation: none;
    opacity: 1;
  }
  .remi-chip {
    transition: none;
  }
  .remi-chip:hover {
    transform: none;
  }
}
