/* Kashikoi component styles (design section 11.3).
 *
 * Each component defines all of its states once and is reused; nothing is styled
 * ad hoc per view (UX-4). Content first: the transcript is the interface and the
 * chrome recedes (UX-1).
 */

/* --------------------------------------------------------------- reset & base */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The `hidden` attribute is the app's toggle for the notice and error blocks
 * (and stream.js drives it via the property). It is only a UA-stylesheet
 * `display: none`, so any component rule that sets `display` silently defeats
 * it -- which is how a completed message came to show an error box. */
[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  height: 100%;
}

body {
  font-family: var(--font);
  font-size: var(--text-base);
  line-height: var(--leading-prose);
  color: var(--text);
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
  /* The page body must never scroll horizontally (UX-14). */
  overflow-x: hidden;
}

h1, h2, h3, h4, h5, h6 {
  line-height: var(--leading-tight);
  margin: 0;
  font-weight: 600;
}

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

/* The focus ring is always visible and never removed (UX-15). */
:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-sm);
}

button {
  font: inherit;
  color: inherit;
}

/* Alpine sets x-cloak and removes it once it has booted. Without this rule every
 * x-show element is visible for the moment before that happens. */
[x-cloak] {
  display: none !important;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: var(--space-2);
  top: -100px;
  z-index: 100;
  padding: var(--space-2) var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  transition: top var(--transition);
}

.skip-link:focus {
  top: var(--space-2);
}

/* --------------------------------------------------------------------- layout */

.app {
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  height: 100dvh;
}

.app__main {
  display: flex;
  flex-direction: column;
  min-width: 0; /* lets children with wide content scroll rather than stretch */
  height: 100dvh;
}

/* -------------------------------------------------------------------- sidebar */

.sidebar {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-3);
  background: var(--bg-subtle);
  border-right: 1px solid var(--border);
  height: 100dvh;
  overflow: hidden;
}

.sidebar__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.sidebar__brand {
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  text-decoration: none;
}

.sidebar__list {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin: 0 calc(var(--space-2) * -1);
  padding: 0 var(--space-2);
  list-style: none;
}

.sidebar__foot {
  border-top: 1px solid var(--border);
  padding-top: var(--space-3);
}

.sidebar__empty {
  color: var(--text-muted);
  font-size: var(--text-sm);
  padding: var(--space-3) var(--space-2);
}

.conversation-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border-radius: var(--radius-sm);
  transition: background var(--transition);
}

.conversation-item:hover,
.conversation-item:focus-within {
  background: var(--surface);
}

.conversation-item[aria-current="page"] {
  background: var(--surface);
  box-shadow: inset 2px 0 0 var(--accent);
}

.conversation-item__link {
  flex: 1;
  min-width: 0;
  display: block;
  padding: var(--space-2);
  color: var(--text);
  text-decoration: none;
  min-height: var(--touch-target);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.conversation-item__title {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-sm);
}

.conversation-item__time {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.conversation-item__actions {
  display: flex;
  gap: var(--space-1);
  padding-right: var(--space-1);
  opacity: 0;
  transition: opacity var(--transition);
}

.conversation-item:hover .conversation-item__actions,
.conversation-item:focus-within .conversation-item__actions {
  opacity: 1;
}

/* -------------------------------------------------------------------- buttons */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--touch-target);
  padding: 0 var(--space-4);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}

.button:hover:not(:disabled) {
  border-color: var(--text-muted);
}

.button:active:not(:disabled) {
  background: var(--bg-subtle);
}

.button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.button--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
  font-weight: 500;
}

.button--primary:hover:not(:disabled) {
  filter: brightness(1.08);
}

.button--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text-muted);
}

.button--ghost:hover:not(:disabled) {
  background: var(--bg-subtle);
  color: var(--text);
  border-color: transparent;
}

.button--danger {
  color: var(--danger);
  border-color: var(--border);
}

.button--danger:hover:not(:disabled) {
  border-color: var(--danger);
}

.button--icon {
  min-width: var(--touch-target);
  padding: 0;
}

.button--small {
  min-height: 32px;
  padding: 0 var(--space-3);
  font-size: var(--text-xs);
}

/* --------------------------------------------------------------------- header */

.topbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  min-height: 52px;
}

.topbar__title {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.topbar__meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
  white-space: nowrap;
}

.drawer-toggle {
  display: none;
}

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

.transcript {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  .transcript {
    scroll-behavior: auto;
  }
}

.transcript__inner {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--space-5) var(--space-4) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.message {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.message__meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.message__actions {
  display: flex;
  gap: var(--space-1);
  opacity: 0;
  transition: opacity var(--transition);
}

.message:hover .message__actions,
.message:focus-within .message__actions {
  opacity: 1;
}

/* The user's turn is distinguished by a subtle surface fill and the alignment of
 * its metadata, not by a saturated colour (design section 11.3). */
.message--user .message__body {
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  /* User messages are plain text with newlines preserved, never interpreted as
   * markdown or HTML (FR-39). */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.message--assistant .message__body {
  min-width: 0;
}

.message__notice {
  font-size: var(--text-xs);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.message__error {
  border: 1px solid var(--danger);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  color: var(--danger);
  font-size: var(--text-sm);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}

/* The three states of UX-19, distinguished visually as well as by the live
 * region of UX-17. */
.status-dot {
  width: 7px;
  height: 7px;
  border-radius: var(--radius-pill);
  background: var(--text-muted);
  flex: none;
}

.status-dot--thinking {
  animation: pulse 1.4s ease-in-out infinite;
}

.status-dot--streaming {
  background: var(--accent);
  animation: pulse 1s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 0.25; }
  50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .status-dot--thinking,
  .status-dot--streaming {
    animation: none;
    opacity: 1;
  }
}

/* --------------------------------------------------------------- markdown body */

.markdown-body > *:first-child { margin-top: 0; }
.markdown-body > *:last-child { margin-bottom: 0; }

.markdown-body p,
.markdown-body ul,
.markdown-body ol,
.markdown-body blockquote,
.markdown-body pre,
.markdown-body table {
  margin: 0 0 var(--space-4);
}

.markdown-body h1 { font-size: var(--text-xl); margin: var(--space-5) 0 var(--space-3); }
.markdown-body h2 { font-size: var(--text-lg); margin: var(--space-5) 0 var(--space-3); }
.markdown-body h3 { font-size: var(--text-md); margin: var(--space-4) 0 var(--space-2); }
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 { font-size: var(--text-base); margin: var(--space-4) 0 var(--space-2); }

.markdown-body ul,
.markdown-body ol {
  padding-left: var(--space-5);
}

.markdown-body li + li {
  margin-top: var(--space-1);
}

.markdown-body blockquote {
  border-left: 2px solid var(--border);
  padding-left: var(--space-4);
  color: var(--text-muted);
}

.markdown-body hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: var(--space-5) 0;
}

.markdown-body code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--code-bg);
  border-radius: 4px;
  padding: 0.15em 0.35em;
}

/* Long unbroken strings must not widen the page (UX-14). */
.markdown-body p,
.markdown-body li,
.markdown-body h1,
.markdown-body h2,
.markdown-body h3 {
  overflow-wrap: anywhere;
}

/* Wide tables scroll within their own container, not the page. */
.markdown-body .table-scroll {
  overflow-x: auto;
  margin: 0 0 var(--space-4);
}

.markdown-body table {
  border-collapse: collapse;
  font-size: var(--text-sm);
  margin: 0;
}

.markdown-body th,
.markdown-body td {
  border: 1px solid var(--border);
  padding: var(--space-2) var(--space-3);
  text-align: left;
}

.markdown-body th {
  background: var(--bg-subtle);
  font-weight: 600;
}

/* ------------------------------------------------------------------ code block */

.code-block {
  position: relative;
  margin: 0 0 var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--code-bg);
  overflow: hidden;
}

.code-block__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-1) var(--space-1) var(--space-3);
  border-bottom: 1px solid var(--border);
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-family: var(--font-mono);
}

.code-block pre {
  margin: 0;
  padding: var(--space-3);
  overflow-x: auto; /* wide code scrolls in its own container (UX-14) */
}

.code-block code {
  background: none;
  padding: 0;
  font-size: var(--text-sm);
  line-height: 1.55;
  white-space: pre;
}

/* ------------------------------------------------------------------- composer */

.composer {
  border-top: 1px solid var(--border);
  background: var(--bg);
  padding: var(--space-3) var(--space-4)
    calc(var(--space-3) + env(safe-area-inset-bottom));
}

.composer__inner {
  max-width: var(--measure);
  margin: 0 auto;
}

.composer__box {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  padding: var(--space-2);
  transition: border-color var(--transition);
}

.composer__box:focus-within {
  border-color: var(--accent);
}

.composer__input {
  flex: 1;
  border: 0;
  background: none;
  resize: none;
  color: var(--text);
  /* 16px so iOS does not zoom the viewport on focus (UX-16). */
  font: inherit;
  font-size: 16px;
  line-height: 1.5;
  padding: var(--space-2);
  max-height: 40dvh;
  overflow-y: auto;
}

.composer__input:focus {
  outline: none;
}

.composer__hint {
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-muted);
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
}

.composer__controls {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* ------------------------------------------------------------- jump to latest */

.jump-latest {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: var(--space-3);
  z-index: 5;
  box-shadow: var(--shadow-overlay);
  border-radius: var(--radius-pill);
}

.transcript-wrap {
  position: relative;
  flex: 1;
  display: flex;
  min-height: 0;
}

/* ---------------------------------------------------------------- empty state */

.empty-state {
  margin: auto;
  max-width: 44ch;
  text-align: center;
  padding: var(--space-6) var(--space-4);
  color: var(--text-muted);
}

.empty-state h1 {
  font-size: var(--text-lg);
  color: var(--text);
  margin-bottom: var(--space-2);
}

/* ---------------------------------------------------------------------- forms */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.field label {
  font-size: var(--text-sm);
  font-weight: 500;
}

.field input,
.field select {
  min-height: var(--touch-target);
  font-size: 16px;
  padding: 0 var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
}

.field__error,
.form__error {
  color: var(--danger);
  font-size: var(--text-sm);
}

.field__help {
  color: var(--text-muted);
  font-size: var(--text-xs);
}

/* --------------------------------------------------------------- auth screens */

.auth {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: var(--space-4);
}

.auth__card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
}

.auth__title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-1);
}

.auth__subtitle {
  color: var(--text-muted);
  font-size: var(--text-sm);
  margin: 0 0 var(--space-5);
}

/* ---------------------------------------------------------- htmx indicators */

/* htmx normally injects these as an inline <style> element, which the CSP blocks
 * (see base.html). Same rules, loaded from a stylesheet on our own origin. */
.htmx-indicator {
  opacity: 0;
  transition: opacity var(--transition);
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  opacity: 1;
}

/* -------------------------------------------------------------------- toasts */

.toast-region {
  position: fixed;
  bottom: var(--space-4);
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  pointer-events: none;
}

.toast {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-overlay);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
  pointer-events: auto;
}

.toast--error {
  border-color: var(--danger);
  color: var(--danger);
}

/* ------------------------------------------------------------------ settings */

.settings-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.settings-bar select,
.settings-bar input[type="number"] {
  min-height: 32px;
  font-size: var(--text-xs);
  padding: 0 var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
}

/* ------------------------------------------------------------------ responsive */

/* Tablet: collapsible sidebar, otherwise the desktop layout (UX-12). */
@media (max-width: 1023px) {
  :root {
    --sidebar-width: 240px;
  }
}

/* Mobile: the sidebar becomes an off-canvas drawer (UX-11). */
@media (max-width: 767px) {
  .app {
    grid-template-columns: 1fr;
  }

  .drawer-toggle {
    display: inline-flex;
  }

  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: min(86vw, 320px);
    z-index: 30;
    transform: translateX(-100%);
    transition: transform var(--transition);
    box-shadow: var(--shadow-overlay);
    padding-top: calc(var(--space-3) + env(safe-area-inset-top));
  }

  .sidebar[data-open="true"] {
    transform: translateX(0);
  }

  .scrim {
    position: fixed;
    inset: 0;
    z-index: 20;
    background: rgb(0 0 0 / 40%);
    border: 0;
  }

  .transcript__inner {
    padding-left: var(--space-3);
    padding-right: var(--space-3);
  }

  .composer {
    padding-left: var(--space-3);
    padding-right: var(--space-3);
  }

  /* Actions are always visible on touch: there is no hover to reveal them. */
  .message__actions,
  .conversation-item__actions {
    opacity: 1;
  }
}
