/* ========================================
   SEROCHAT APP CHROME
   Shared by dashboard, conversations, sources,
   settings, customise. Includes the global
   reset/typography, sidebar, mobile toggle,
   overlay, and theme switch button.
======================================== */

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

/* The UA's [hidden] { display: none } rule loses to any author `display`
   on the same element (class or inline), which has produced a family of
   hidden-but-still-rendered bugs (empty chips, ghost composers). Enforce
   the attribute's contract globally. The one deliberate exception is
   .account-dropdown, which keeps display while [hidden] so its
   opacity/transform fade can animate. */
[hidden]:not(.account-dropdown) { display: none !important; }

/* .skip-link lives in tokens.css so every layout (marketing, app, auth)
   gets it without needing to load app.css. Don't redeclare it here. */

:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
  border-radius: inherit;
}
.btn-primary:focus-visible,
.auth-submit:focus-visible,
.sidebar-link:focus-visible,
.panel-close:focus-visible,
.btn-secondary:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Entrance cascade — page-header + first row of cards rise on load. Defined
   here so every view gets the identical animation; used to be duplicated
   inline on five pages (with one outlier missing it entirely, which made
   headers appear to land at different heights). */
@keyframes rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
.rise    { animation: rise 0.45s ease forwards; opacity: 0; }
.rise-d1 { animation-delay: 0.04s; }

@media (prefers-reduced-motion: reduce) {
  .rise { animation: none; opacity: 1; transform: none; }
}

body {
  font-family: var(--font-sans);
  background: var(--gradient-paper);
  color: var(--ink-soft);
  font-size: 15px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
}

h1, h2, h3, h4 {
  font-family: var(--font-serif);
  color: var(--ink);
  font-weight: 400;
  letter-spacing: -0.025em;
  line-height: 1.15;
}

.page-header h1,
.greeting h1,
.bill-header h1,
.manage-header h1 {
  font-size: var(--text-3xl);
  font-weight: 500;
  letter-spacing: -0.03em;
}

a { text-decoration: none; color: inherit; }
button { font-family: inherit; cursor: pointer; }

.app { display: flex; min-height: 100vh; }

/* .main is a flex child. Without min-width: 0 it refuses to shrink below
   its intrinsic min-content size, which on narrow phones causes the whole
   page to overflow horizontally (the symptom: cards spill past the right
   edge on /training and /sources). Single defensive rule here so every
   page's inline .main block inherits it. Transition tracks the sidebar
   collapse toggle — every page's inline margin-left reads --sidebar-w, so
   this one rule keeps all of them in sync without touching each view. */
.main { min-width: 0; transition: margin-left 200ms var(--ease-out-soft); }

/* ========================================
   SIDEBAR
======================================== */
.sidebar {
  width: var(--sidebar-w);
  background: var(--white);
  border-right: 1px solid var(--border);
  padding: 24px 16px;
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 50;
  transition: transform 0.3s ease;
}

.sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 32px;
}

.sidebar-logo {
  display: flex;
  align-items: center;
  padding: 4px 12px;
  min-width: 0;
}

.sidebar-logo svg { height: 40px; width: auto; color: var(--ink); flex-shrink: 0; }

/* Compact wordless mark shown only once the rail is collapsed — the full
   logo's "Serochat" text is baked into one SVG (not a separate element), so
   collapsing needs its own icon-only asset rather than clipping the full one. */
.sidebar-logo-mark { display: none; }
.sidebar-logo-mark svg { height: 40px; width: 40px; flex-shrink: 0; }

.sidebar-collapse-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border: none;
  background: none;
  border-radius: 8px;
  color: var(--ink-muted);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.sidebar-collapse-btn:hover { background: var(--paper); color: var(--ink); }
.sidebar-collapse-btn svg { width: 16px; height: 16px; }
/* Chevrons point the direction the action collapses toward, mirroring
   the "panel toggle" affordance of Notion/Linear/VS Code. */
.sidebar-collapse-btn .icon-expand { display: none; }
html.sidebar-collapsed .sidebar-collapse-btn .icon-collapse { display: none; }
html.sidebar-collapsed .sidebar-collapse-btn .icon-expand { display: block; }

/* Icon mark is solid brand green; in dark mode swap to the lighter --green
   token so it stays legible on the dark sidebar (mirrors the marketing nav). */
[data-theme="dark"] .sidebar-logo svg path[fill="#0F6E56"] { fill: var(--green); }

.sidebar-nav { display: flex; flex-direction: column; gap: 2px; flex: 1; }

.sidebar-section-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow);
  color: var(--ink-muted);
  padding: 20px 12px 8px;
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 12px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  transition: all 0.15s ease;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
  position: relative;
}

.sidebar-link:hover { background: var(--paper); color: var(--ink); }

.sidebar-link.active {
  background: var(--green); /* brand green — matches the .sidebar-logo SVG fill */
  color: var(--on-green);
  font-weight: 600;
}

/* Dark mode: the logo remaps its #0F6E56 fill to --green (#2CC494) — see the
   .sidebar-logo svg remap above — so the active pill follows suit to stay in
   step with the logo. Text stays correct via --on-green (dark = near-black). */
[data-theme="dark"] .sidebar-link.active { background: var(--green); }

.sidebar-link svg { width: 18px; height: 18px; flex-shrink: 0; opacity: 0.8; }
.sidebar-link.active svg { opacity: 1; }
.sidebar-link:hover svg { opacity: 0.95; }

/* ========================================
   SIDEBAR COLLAPSE (icon-only rail)
   Desktop only — on the mobile drawer the sidebar is already an overlay,
   so shrinking it to icons would just make it harder to use. Every rule
   here is gated behind the same breakpoint the drawer switches at.
======================================== */
@media (min-width: 769px) {
  html.sidebar-collapsed { --sidebar-w: var(--sidebar-w-collapsed); }
  html.sidebar-collapsed .sidebar { padding-left: 10px; padding-right: 10px; }

  html.sidebar-collapsed .sidebar-header { flex-direction: column; gap: 10px; }
  html.sidebar-collapsed .sidebar-logo { display: none; }
  html.sidebar-collapsed .sidebar-logo-mark { display: flex; justify-content: center; }

  html.sidebar-collapsed .sidebar-link { justify-content: center; padding: 10px; gap: 0; }
  html.sidebar-collapsed .sidebar-link-label { display: none; }

  /* Section labels become a plain divider — text stays in the DOM (screen
     readers still get "Account" / "System" before their links) but is
     visually clipped rather than removed, so collapsed sections still read
     as grouped instead of one long list of icons. */
  html.sidebar-collapsed .sidebar-section-label {
    position: relative;
    height: 1px;
    margin: 14px 10px;
    padding: 0;
    overflow: hidden;
    color: transparent;
  }
  html.sidebar-collapsed .sidebar-section-label::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--border-soft);
  }

  /* Rail tooltips — label pops out to the right of the icon on hover/focus.
     Reuses --tooltip-bg (the app's one tooltip surface token) but its own
     layout, since the sidebar's icons sit flush against the left edge
     rather than centered above inline text. */
  html.sidebar-collapsed [data-tip] { position: relative; }
  html.sidebar-collapsed [data-tip]::after {
    content: attr(data-tip);
    position: absolute;
    left: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%) translateX(-4px);
    background: var(--tooltip-bg);
    color: rgba(255,255,255,0.92);
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.4;
    white-space: nowrap;
    padding: 6px 10px;
    border-radius: 8px;
    pointer-events: none;
    opacity: 0;
    z-index: 70;
    transition: opacity 140ms var(--ease-out-soft), transform 140ms var(--ease-out-soft);
  }
  @media (hover: hover) and (pointer: fine) {
    html.sidebar-collapsed [data-tip]:hover::after,
    html.sidebar-collapsed [data-tip]:focus-visible::after {
      opacity: 1;
      transform: translateY(-50%) translateX(0);
      transition-delay: var(--dur-tooltip-delay);
    }
  }

  /* The chatbot switcher and account trigger keep their popovers at full
     width even though the trigger itself shrinks to an icon — a 76px-wide
     dropdown would be unusable. */
  html.sidebar-collapsed .chatbot-switcher-trigger,
  html.sidebar-collapsed .account-trigger { justify-content: center; padding: 8px; gap: 0; }
  html.sidebar-collapsed .chatbot-switcher-name,
  html.sidebar-collapsed .chatbot-switcher-chevron,
  html.sidebar-collapsed .account-trigger-text,
  html.sidebar-collapsed .account-chevron { display: none; }
  html.sidebar-collapsed .chatbot-switcher-dropdown,
  html.sidebar-collapsed .account-dropdown { left: 0; right: auto; width: 240px; }
}


.sidebar-avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--green-light);
  color: var(--green-dark);
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px;
  font-weight: 600;
}

[data-theme="dark"] .sidebar-avatar {
  background: #143830;
  color: var(--green-on-ink);
}


/* ========================================
   THEME TOGGLE
======================================== */
.theme-toggle {
  width: 36px; height: 36px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-soft);
  cursor: pointer;
  transition: all 0.15s ease;
  flex-shrink: 0;
}

.theme-toggle:hover {
  border-color: var(--ink-muted);
  color: var(--ink);
}

.theme-toggle svg { width: 16px; height: 16px; }
.theme-icon-dark { display: none; }
[data-theme="dark"] .theme-icon-light { display: none; }
[data-theme="dark"] .theme-icon-dark { display: inline-block; }

/* ========================================
   ACCOUNT MENU (sidebar bottom)
======================================== */
.account-menu {
  position: relative;
}
.sidebar-account {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}

.account-trigger {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  background: transparent;
  border-radius: 12px;
  color: var(--ink);
  font-family: inherit;
  cursor: pointer;
  text-align: left;
  transition: background 180ms var(--ease);
}
.account-trigger:hover,
.account-trigger[aria-expanded="true"] { background: var(--paper); }
.account-trigger:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.account-trigger .sidebar-avatar {
  width: 32px;
  height: 32px;
  font-size: 12px;
  font-weight: 600;
  flex-shrink: 0;
}

.account-trigger-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.15;
  text-align: left;
  flex: 1;
  min-width: 0;
}
.account-trigger-name {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.account-trigger-role { font-size: 11.5px; color: var(--ink-muted); margin-top: 1px; }

.account-chevron {
  width: 14px;
  height: 14px;
  color: var(--ink-muted);
  flex-shrink: 0;
  transition: transform 180ms var(--ease);
}
.account-trigger[aria-expanded="true"] .account-chevron { transform: rotate(180deg); }

.account-dropdown {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  right: 0;
  min-width: 100%;
  background: var(--white);
  border: 1px solid var(--border-soft);
  border-radius: 14px;
  box-shadow: 0 12px 36px rgba(26,43,60,0.10), 0 2px 8px rgba(26,43,60,0.04);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.account-dropdown[hidden] { display: none; }

.account-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 12px;
  border: none;
  background: none;
  border-radius: 8px;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.account-item:hover { background: var(--paper); }
.account-item svg { width: 16px; height: 16px; color: var(--ink-muted); flex-shrink: 0; }
.account-item:hover svg { color: var(--ink); }

.account-item--danger { color: var(--red, #DC2626); }
.account-item--danger svg { color: var(--red, #DC2626); }
.account-item--danger:hover { background: rgba(220,38,38,0.08); }

.theme-label-dark { display: none; }
[data-theme="dark"] .theme-label-light { display: none; }
[data-theme="dark"] .theme-label-dark { display: inline; }

[data-theme="dark"] .account-trigger { background: var(--white); }
[data-theme="dark"] .account-dropdown { background: var(--white); }

@media (max-width: 768px) {
  .account-menu { top: 12px; right: 12px; }
  .account-trigger-text { display: none; }
  .account-trigger { padding: 4px; }
  .account-chevron { display: none; }
  /* The drawer already has its own open/close affordance (the hamburger);
     the icon-rail collapse toggle has no meaning on a mobile overlay. */
  .sidebar-collapse-btn { display: none; }
}

/* ========================================
   MOBILE TOGGLE + OVERLAY
======================================== */
.mobile-toggle {
  display: none;
  position: fixed;
  top: 14px; left: 14px;
  z-index: 60;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: var(--white);
  border: 1px solid var(--border);
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-card);
  transition: transform 0.2s ease, opacity 0.2s ease;
}

/* Tucked away while the user scrolls down through content — the floating
   button otherwise sits on top of whatever scrolls under it. Scrolling up
   (or focusing it with the keyboard) brings it back. */
.mobile-toggle.tucked {
  transform: translateY(-72px);
  opacity: 0;
}
.mobile-toggle.tucked:focus-visible {
  transform: none;
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .mobile-toggle { transition: none; }
}

.mobile-toggle svg { width: 18px; height: 18px; color: var(--ink-soft); }

[data-theme="dark"] .mobile-toggle {
  background: var(--white);
  box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}

.sidebar-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.22);
  z-index: 40;
}

[data-theme="dark"] .sidebar-overlay { background: rgba(0,0,0,0.5); }

@media (max-width: 768px) {
  .sidebar { transform: translateX(-100%); }
  .sidebar.open { transform: translateX(0); }
  .sidebar-overlay.visible { display: block; }
  .mobile-toggle { display: flex; }

  /* Prevent iOS Safari auto-zoom when focusing inputs — 16px is the
     threshold. Per-page inputs that explicitly need to look denser can
     still override this locally. */
  input[type="text"], input[type="email"], input[type="password"],
  input[type="number"], input[type="search"], input[type="url"],
  input[type="tel"], input[type="date"], textarea, select { font-size: 16px; }

  /* Primary touch targets: make navigation and chrome finger-friendly. */
  .sidebar-link, .theme-toggle, .mobile-toggle,
  .pill, .cycle-btn, .panel-close, .pi-kebab,
  .btn-primary, .btn-secondary, .auth-submit, .nav a { min-height: 44px; }
  .theme-toggle, .mobile-toggle, .panel-close, .pi-kebab { min-width: 44px; }
}

/* Narrow-phone polish (≤640px). Cap sidebar width so it doesn't fully
   cover the page, and pull the hamburger in slightly. */
@media (max-width: 640px) {
  .sidebar { width: min(86vw, 320px); }
  .mobile-toggle { top: 12px; left: 12px; }
}

html { -webkit-text-size-adjust: 100%; }

/* ========================================
   GLOBAL POLISH (Wispr-flavoured)
   Flat cards on hairline borders, flat green CTAs,
   warmer focus rings, smoother motion.
   Loaded after page-specific inline styles
   in source order — but pages embed their
   <style> AFTER this file via <head>, so we
   bump specificity & use !important on the
   additive bits we need to win.
======================================== */

.card {
  box-shadow: none !important;
}

/* Primary CTAs — flat brand green, hairline border, no glow.
   (De-templated: the previous 135deg gradient fill read as generated
   SaaS chrome; flat fill + hairline is the editorial button grammar.) */
.btn-primary,
.bill-cta,
.success-cta,
.cancel-cta,
.hero-cta,
button.btn.primary,
.auth-submit {
  background: var(--green) !important;
  color: var(--on-green) !important;
  border: 1px solid var(--green-darker) !important;
  transition: background 180ms var(--ease), border-color 180ms var(--ease) !important;
}
.btn-primary:hover,
.bill-cta:hover,
.success-cta:hover,
.cancel-cta:hover,
.hero-cta:hover,
button.btn.primary:hover,
.auth-submit:hover {
  background: var(--green-darker) !important;
}

/* Secondary buttons — gentle hover */
.btn-secondary {
  transition: border-color 180ms var(--ease), background 180ms var(--ease) !important;
}

/* Inputs — warmer focus ring */
input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--green) !important;
  box-shadow: var(--ring-input) !important;
}
[data-theme="dark"] input:focus,
[data-theme="dark"] textarea:focus,
[data-theme="dark"] select:focus {
  box-shadow: 0 0 0 3px rgba(44,196,148,0.22) !important;
}

/* Filter chips / pill toggles — hover state */
.bill-cycle button { transition: background 180ms var(--ease), color 180ms var(--ease); }

/* Greeting / page-header containers — no card chrome but get a touch more breathing room */
.greeting { margin-bottom: var(--space-6); }
.page-header { margin-bottom: var(--space-7); }

/* Status pills consistent radius */
.bill-plan-badge { letter-spacing: 0.01em; }

/* ============================================
   Token-driven utilities (added in polish pass)
   ============================================ */

/* Tertiary / ghost button — for non-primary in-app CTAs that need to sit
   alongside the gradient primary (e.g., "+ New article" next to "+ Upload").
   Uses the warm paper border, ink-soft text, no background. Promotes a
   single primary CTA per surface. */
.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 8px 14px;
  border: 1px solid var(--border);
  background: var(--white);
  color: var(--ink-soft);
  font-size: var(--text-base);
  font-weight: 500;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: border-color 180ms var(--ease), background 180ms var(--ease), color 180ms var(--ease);
}
.btn-ghost:hover { border-color: var(--border-strong); color: var(--ink); background: var(--row-hover); }
.btn-ghost:focus-visible { outline: none; box-shadow: var(--ring); }

/* Plum-accented surfaces — used for informational / "what's new" / upsell
   cues so brand-green stays reserved for primary actions and "good" states. */
.surface-info { background: var(--plum-light); color: var(--plum-dark); }

/* Visually-hidden helper — for screen-reader-only labels (used by Agent
   work that adds explicit labels to icon-only buttons). */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ========================================
   APP-CHROME MICRO-INTERACTIONS
   Specific to authed pages (sidebar, account
   dropdown, app modals). Site-wide primitives
   like [data-reveal] and .sc-toast
   live in tokens.css so marketing pages also
   pick them up.
======================================== */

/* Account-dropdown smooth open (overrides the bare hidden toggle). */
.account-dropdown {
  transform-origin: bottom center;
  transition: opacity 140ms var(--ease-out-soft),
              transform 140ms var(--ease-out-soft);
}
.account-dropdown[hidden] {
  display: flex;
  opacity: 0;
  transform: translateY(4px) scale(0.97);
  pointer-events: none;
}
.account-dropdown:not([hidden]) {
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* Mobile sidebar overlay — fade rather than display-flip. */
@media (max-width: 768px) {
  .sidebar-overlay {
    display: block;
    opacity: 0;
    pointer-events: none;
    transition: opacity 240ms var(--ease-out-soft);
  }
  .sidebar-overlay.visible {
    opacity: 1;
    pointer-events: auto;
  }
}

/* Sidebar drawer — premium settling curve. Width transition is for the
   desktop collapse toggle; harmless on mobile since width is fixed there. */
.sidebar {
  transition: transform var(--dur-drawer-in) var(--ease-out-soft),
              width 200ms var(--ease-out-soft),
              padding 200ms var(--ease-out-soft);
}

/* Tooltips — universal hover delay so brushing the cursor doesn't fire.
   Suppresses on touch devices where :hover lingers. Components opting
   into tooltips (.has-tip / .tip class) inherit this delay. */
@media (hover: hover) and (pointer: fine) {
  .has-tip .tip { transition-delay: 0ms 0ms; }
  .has-tip:hover .tip,
  .has-tip:focus-within .tip {
    transition-delay: var(--dur-tooltip-delay);
  }
}
@media (hover: none) {
  .has-tip .tip { display: none !important; }
}
