mezame 0.8.42

An ACP client that bridges a local agent (Kiro CLI, Claude Agent CLI, Gemini CLI, Codex, ...) to a browser UI over WebSockets.
@import 'tailwindcss';
@import 'tw-animate-css';

@custom-variant dark (&:is(.dark *));
@custom-variant touch (&:where(@media (pointer: coarse)));
@custom-variant mouse (&:where(@media (pointer: fine)));

/* mezame design tokens.
 *
 * Warm cream + terracotta light theme. Body text in Manrope; the
 * wordmark and section headings use EB Garamond serif for a single
 * note of editorial personality. The user bubble takes the primary
 * terracotta; the agent bubble takes the secondary container so the
 * two roles read distinctly without either one shouting. Dark-mode
 * follow-up is left for a later pass; the current shell is light
 * only, matching the reference design. */

:root {
  /* Surface ladder, lightest at the top. */
  --background: oklch(0.97 0.012 70);
  --surface-bright: oklch(0.99 0.008 80);
  --surface-container-lowest: oklch(1 0 0);
  --surface-container-low: oklch(0.965 0.014 70);
  --surface-container: oklch(0.95 0.018 70);
  --surface-container-high: oklch(0.93 0.02 70);
  --surface-container-highest: oklch(0.91 0.022 70);

  --foreground: oklch(0.27 0.018 50);
  --on-surface-variant: oklch(0.45 0.018 60);
  --outline: oklch(0.62 0.012 70);
  --outline-variant: oklch(0.85 0.012 70);

  /* Mapped onto Tailwind/shadcn tokens. */
  --card: var(--surface-container-lowest);
  --card-foreground: var(--foreground);
  --popover: var(--surface-container-lowest);
  --popover-foreground: var(--foreground);
  --secondary: var(--surface-container-high);
  --secondary-foreground: var(--foreground);
  --muted: var(--surface-container);
  --muted-foreground: var(--on-surface-variant);
  --accent: var(--surface-container-high);
  --accent-foreground: var(--foreground);
  --border: oklch(0.85 0.012 70);
  --input: var(--surface-container-low);

  /* Terracotta primary. Warm, fairly saturated; carries through to
   * the user bubble and the send button. */
  --primary: oklch(0.62 0.14 45);
  --primary-foreground: oklch(0.99 0 0);
  --primary-container: oklch(0.7 0.13 45);
  --primary-fixed: oklch(0.93 0.05 60);
  --on-primary-fixed: oklch(0.3 0.1 40);

  --destructive: oklch(0.55 0.18 28);
  --destructive-foreground: oklch(0.99 0 0);
  --ring: oklch(0.7 0.13 45);
  --radius: 0.75rem;

  /* Role colours for log entries and status badges. */
  --user: var(--primary);
  --agent: var(--surface-container-high);
  --sys: var(--on-surface-variant);
  --attn-done: oklch(0.7 0.12 145);
  --attn-permission: oklch(0.78 0.12 75);
  --attn-error: var(--destructive);

  /* User message bubble. Same hue as primary so the user role reads as
   * the active speaker; agent bubble below picks up the cool secondary
   * container so it reads as "the other person". */
  --user-bubble: var(--primary);
  --user-bubble-foreground: var(--primary-foreground);
  --agent-bubble: oklch(0.93 0.02 70);
  --agent-bubble-foreground: var(--foreground);

  /* Default width matches `SIDEBAR_DEFAULT_PX` in
   * `useSidebarWidth.ts`. The hook overwrites this on mount with the
   * persisted value, but the default keeps the layout correct on the
   * very first render before any component has mounted. */
  --mz-sidebar-width: 272px;

  /* Reservation gutter for the main column to clear the floating
   * sidebar at desktop widths. Defaults to 0 (mobile drawer mode);
   * the media query below promotes it to "sidebar width plus 18 px
   * of breathing room" on screens wide enough that the sidebar is
   * always visible. */
  --mz-main-left: 0px;

  /* Virtual-keyboard inset, populated by useKeyboardInset() at
   * runtime. 0 when no keyboard is open. */
  --mz-kb-inset: 0px;

  /* iOS safe-area insets, with a 0 fallback. */
  --mz-safe-top: env(safe-area-inset-top, 0px);
  --mz-safe-bottom: env(safe-area-inset-bottom, 0px);
  --mz-safe-left: env(safe-area-inset-left, 0px);
  --mz-safe-right: env(safe-area-inset-right, 0px);

  /* Typography. EB Garamond for the wordmark and section titles;
   * Manrope for everything else. JetBrains Mono kept around for code
   * fences in markdown so output stays legible. */
  /* Typography. JetBrains Mono everywhere; Chelsea Market for the
   * wordmark. The reskin briefly used EB Garamond + Manrope to match
   * the supplied reference, but the project's identity is the
   * mono-throughout look that pre-dates the reskin. Keeping the warm
   * palette but reverting fonts. */
  --font-display: 'Gugi', ui-serif, Georgia, serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  --font-body: var(--font-mono);
}

/* Desktop layout: promote the chat column's left margin to clear the
 * floating sidebar. Tailwind's `md:` breakpoint is 768 px; matching
 * that here keeps the in-app `md:static` overrides on the sidebar
 * itself in step with the layout reservation here. */
@media (min-width: 768px) {
  :root {
    --mz-main-left: calc(var(--mz-sidebar-width) + 40px);
  }
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --font-display: var(--font-display);
  --font-body: var(--font-body);
  --font-mono: var(--font-mono);
}

@layer base {

  html,
  body,
  #root {
    height: 100%;
  }

  body {
    font-family: var(--font-body);
    font-size: 14px;
    line-height: 20px;
    background-color: var(--background);
    color: var(--foreground);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  * {
    border-color: var(--border);
  }
}

/* Tooltip content: shown only for fine pointers. Suppressed on coarse
 * pointers (touch) where a tap leaves the tooltip lingering with no
 * dismiss affordance. */
.tt-fine-only {
  display: none;
}

@media (pointer: fine) {
  .tt-fine-only {
    display: block;
  }
}

/* Tab pulse keyframes. Inline RGB values so nothing in Tailwind's
 * pipeline can flatten them. */
@keyframes mezame-pulse-orange {

  0%,
  100% {
    background-color: rgba(217, 163, 63, 0.25);
  }

  50% {
    background-color: rgba(217, 163, 63, 0.5);
  }
}

/* Traveling-border animation for busy-in-background tabs. The
 * conic gradient rotates around the tab while the inner fill stays
 * constant; the warmer palette wants a softer terracotta glow rather
 * than the previous green chase. */
@property --busy-border-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

@keyframes mezame-border-spin {
  to {
    --busy-border-angle: 360deg;
  }
}

.tab-busy-border {
  border-width: 2px;
  border-color: transparent;
  padding-left: calc(0.625rem - 1px);
  padding-right: calc(0.625rem - 1px);
  background:
    linear-gradient(#ffffff, #ffffff) padding-box,
    conic-gradient(from var(--busy-border-angle),
      transparent 0deg,
      transparent 280deg,
      rgba(194, 101, 42, 0.85) 325deg,
      transparent 360deg) border-box;
  animation: mezame-border-spin 2s linear infinite;
}

.tab-busy-border:hover {
  background:
    linear-gradient(oklch(0.97 0.018 70), oklch(0.97 0.018 70)) padding-box,
    conic-gradient(from var(--busy-border-angle),
      transparent 0deg,
      transparent 280deg,
      rgba(194, 101, 42, 0.9) 325deg,
      transparent 360deg) border-box;
}

@media (prefers-reduced-motion: reduce) {
  .tab-busy-border {
    animation: none;
  }
}

html[data-visibility="hidden"] .tab-busy-border {
  animation: none;
}

@layer utilities {
  .scrollbar-thin::-webkit-scrollbar {
    width: 8px;
    height: 8px;
  }

  .scrollbar-thin::-webkit-scrollbar-track {
    background: transparent;
  }

  .scrollbar-thin::-webkit-scrollbar-thumb {
    background: var(--outline-variant);
    border-radius: 4px;
  }

  .scrollbar-thin::-webkit-scrollbar-thumb:hover {
    background: var(--outline);
  }

  /* Variant used by the floating sidebar and message thread when we
   * want the scroll to be invisible (matching the reference design's
   * "scrollbar-hide" idiom). */
  .scrollbar-hide::-webkit-scrollbar {
    display: none;
  }

  .scrollbar-hide {
    -ms-overflow-style: none;
    scrollbar-width: none;
  }
}