/* HALCYON — a warm-paper editorial theme for CopilotChat. * * The point of this demo is to show how far a single stylesheet can take * CopilotChat away from the default look without touching components or * slots. Every selector is namespaced under `.chat-css-demo-scope` so this * theme cannot leak into the rest of the showcase. * * Two layers do the work: * 1. v2 token overrides on `[data-copilotkit]` recolor every Tailwind * utility (cpk:bg-muted, cpk:text-foreground, cpk:border, …) the * runtime relies on — see @copilotkit/react-core/v2/styles.css. * 2. Targeted class rules on `.copilotKitChat`, `.copilotKitMessage*`, * and `.copilotKitInput` add the editorial details: parchment grain, * corner brackets, serif voice, mono dispatch, ember accents. * * Class-name reference: * https://docs.copilotkit.ai/custom-look-and-feel/customize-built-in-ui-components */ /* @region[google-fonts] */ @import url("https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=Instrument+Serif:ital@0;1&family=Inter+Tight:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap"); /* @endregion[google-fonts] */ /* @region[design-tokens] */ /* HALCYON palette — a private library at golden hour. The whole theme is * one warm parchment hue, one warm ink, and a deep copper ember used * sparingly so it actually reads as a signal. */ .chat-css-demo-scope { --halcyon-paper: #f4efe6; --halcyon-paper-soft: #ece6d9; --halcyon-paper-elevated: #fbf8f2; --halcyon-card: #ffffff; --halcyon-rule: #d6cfbe; --halcyon-rule-strong: #aea48a; --halcyon-ink: #1a1714; --halcyon-ink-soft: #3d362e; --halcyon-ink-mute: #7a7468; --halcyon-ember: #c44a1f; --halcyon-ember-bright: #e45f2b; --halcyon-ember-soft: #f3d7c5; --halcyon-champagne: #98794a; --halcyon-display: "Instrument Serif", ui-serif, "Iowan Old Style", Georgia, serif; --halcyon-serif: "Fraunces", "Source Serif Pro", ui-serif, Georgia, "Times New Roman", serif; --halcyon-sans: "Inter Tight", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; --halcyon-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace; --halcyon-shadow-soft: 0 1px 0 rgba(26, 23, 20, 0.04), 0 12px 32px -18px rgba(26, 23, 20, 0.18); --halcyon-shadow-ember: 0 1px 0 rgba(196, 74, 31, 0.18), 0 14px 36px -16px rgba(196, 74, 31, 0.42); } /* @endregion[design-tokens] */ /* @region[v2-token-overrides] */ /* CopilotKit v2 reads these on the [data-copilotkit] root inside the chat. * Re-pointing them under our scope retints every Tailwind utility the * runtime renders (user message bubble, prose, borders, focus rings, …) * without us having to touch any individual class. */ .chat-css-demo-scope [data-copilotkit] { --background: var(--halcyon-paper); --foreground: var(--halcyon-ink); --card: var(--halcyon-card); --card-foreground: var(--halcyon-ink); --popover: var(--halcyon-paper-elevated); --popover-foreground: var(--halcyon-ink); --primary: var(--halcyon-ember); --primary-foreground: var(--halcyon-paper-elevated); --secondary: var(--halcyon-paper-soft); --secondary-foreground: var(--halcyon-ink); --muted: var(--halcyon-paper-soft); --muted-foreground: var(--halcyon-ink-mute); --accent: var(--halcyon-ember-soft); --accent-foreground: var(--halcyon-ember); --destructive: #b3361b; --destructive-foreground: var(--halcyon-paper-elevated); --border: var(--halcyon-rule); --input: var(--halcyon-rule); --ring: var(--halcyon-ember); --radius: 0px; } /* @endregion[v2-token-overrides] */ /* @region[chat-shell] */ /* The chat surface — warm parchment with a single ambient ember glow, * a barely-perceptible paper grain via inline SVG noise, and architectural * corner brackets. Sharp 90° corners are deliberate; the default look is * rounded, so squaring everything off is the fastest visual signal that * "this is a different brand". */ .chat-css-demo-scope .copilotKitChat { font-family: var(--halcyon-sans); color: var(--halcyon-ink); background-color: var(--halcyon-paper); background-image: radial-gradient( 900px 460px at 0% -10%, rgba(228, 95, 43, 0.14), transparent 62% ), radial-gradient( 720px 380px at 100% 110%, rgba(152, 121, 74, 0.08), transparent 65% ), url("data:image/svg+xml;utf8,"); border: 1px solid var(--halcyon-rule); border-radius: 0; box-shadow: var(--halcyon-shadow-soft); position: relative; overflow: hidden; } /* The masthead label — a small mono bar pinned to the top of the surface, * playing against the editorial serif voice. Lives on ::before so it * tracks the chat root and shows in every state (welcome, mid-thread, * empty after clear). */ .chat-css-demo-scope .copilotKitChat::before { content: "CopilotChat · Customized with CSS"; position: absolute; top: 18px; left: 0; right: 0; text-align: center; font-family: var(--halcyon-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.04em; color: var(--halcyon-ink-mute); white-space: nowrap; pointer-events: none; z-index: 3; } /* @endregion[chat-shell] */ /* @region[welcome] */ /* The welcome screen — the page-one impression. The default heading is * sans-serif and tidy; we replace it with a large italic display serif * that wraps the question like a magazine cover line. */ .chat-css-demo-scope [data-testid="copilot-welcome-screen"] { padding-top: 4rem; } .chat-css-demo-scope [data-testid="copilot-welcome-screen"] h1 { font-family: var(--halcyon-display); font-size: clamp(2.4rem, 5vw, 4rem); font-weight: 400; font-style: italic; color: var(--halcyon-ink); letter-spacing: -0.02em; line-height: 1.05; text-align: center; margin: 0 auto 0.6rem; max-width: 22ch; position: relative; } /* A small mono eyebrow above the heading. */ .chat-css-demo-scope [data-testid="copilot-welcome-screen"] h1::before { content: "CopilotKit"; display: block; font-family: var(--halcyon-mono); font-size: 11px; font-style: normal; font-weight: 500; letter-spacing: 0.06em; color: var(--halcyon-ember); margin-bottom: 1.2rem; } /* A short rule under the heading as a visual settle point. */ .chat-css-demo-scope [data-testid="copilot-welcome-screen"] h1::after { content: ""; display: block; width: 36px; height: 1px; background: var(--halcyon-rule-strong); margin: 1.4rem auto 0; } /* @endregion[welcome] */ /* @region[messages-container] */ .chat-css-demo-scope .copilotKitMessages { font-family: var(--halcyon-sans); background: transparent; color: var(--halcyon-ink); padding: 5rem 0 2rem; line-height: 1.6; } /* @endregion[messages-container] */ /* @region[user-message] */ /* User message — a "transmission" in JetBrains Mono on a paper card. The * outer wrapper is the right-aligning flex column; we leave it transparent * and style the inner bubble (which uses cpk:bg-muted, hence we also * target the substring class as a stable hook). */ .chat-css-demo-scope .copilotKitMessage.copilotKitUserMessage { background: transparent; padding: 0; border: none; box-shadow: none; } .chat-css-demo-scope .copilotKitMessage.copilotKitUserMessage > [class*="bg-muted"] { font-family: var(--halcyon-mono); font-size: 0.875rem; font-weight: 400; color: var(--halcyon-ink); background: var(--halcyon-paper-elevated); border: 1px solid var(--halcyon-rule); border-left: 2px solid var(--halcyon-ember); border-radius: 0; padding: 12px 16px 12px 18px; letter-spacing: -0.005em; line-height: 1.55; box-shadow: 0 1px 0 rgba(26, 23, 20, 0.03); position: relative; } /* A mono "→" marker before the user's text to read like a CLI prompt. */ .chat-css-demo-scope .copilotKitMessage.copilotKitUserMessage > [class*="bg-muted"]::before { content: "→"; display: inline-block; margin-right: 10px; color: var(--halcyon-ember); font-weight: 500; } /* @endregion[user-message] */ /* @region[assistant-message] */ /* Assistant message — editorial Fraunces serif, no bubble, just generous * paragraphs offset by a thin ember rule on the left. Reads like the * voice of a publication, not a chatbot. */ .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage { background: transparent; color: var(--halcyon-ink); font-family: var(--halcyon-serif); font-size: 1.0625rem; font-weight: 400; padding: 4px 0 4px 22px; border: none; border-radius: 0; margin-right: auto; margin-bottom: 1.25rem; max-width: 78ch; position: relative; } /* The editorial left rule. */ .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage::before { content: ""; position: absolute; top: 0.45em; bottom: 0.45em; left: 0; width: 1px; background: var(--halcyon-ember); } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose, .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose p { font-family: var(--halcyon-serif); font-size: inherit; color: inherit; line-height: 1.7; font-feature-settings: "ss01", "ss02", "ss03", "kern"; margin: 0 0 0.85em; } /* Headings inside assistant content swap to the display serif so a long * answer reads like a structured article. */ .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose :is(h1, h2, h3, h4) { font-family: var(--halcyon-display); font-style: italic; font-weight: 400; letter-spacing: -0.015em; color: var(--halcyon-ink); margin: 1em 0 0.4em; line-height: 1.15; } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose h1 { font-size: 2rem; } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose h2 { font-size: 1.55rem; } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose h3 { font-size: 1.25rem; } /* Lists — looser, with serif numerals. */ .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose :is(ul, ol) { margin: 0.5em 0 1em; padding-left: 1.4em; } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose li { margin: 0.25em 0; } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose ol > li::marker { color: var(--halcyon-ember); font-feature-settings: "tnum"; font-weight: 500; } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose ul > li::marker { color: var(--halcyon-ember); } /* Blockquote — pull-quote treatment in italic display serif. */ .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose blockquote { border-left: 0; margin: 1.2em 0; padding: 0 0 0 1em; font-family: var(--halcyon-display); font-style: italic; font-size: 1.25em; color: var(--halcyon-ink-soft); position: relative; } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose blockquote::before { content: "“"; position: absolute; left: -0.05em; top: -0.4em; font-size: 2.4em; color: var(--halcyon-ember); line-height: 1; } /* Inline code — small ember chip on a tinted card. */ .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose code { font-family: var(--halcyon-mono); font-size: 0.86em; font-weight: 500; color: var(--halcyon-ember); background: var(--halcyon-ember-soft); border: 1px solid color-mix(in srgb, var(--halcyon-ember) 22%, transparent); border-radius: 0; padding: 1px 6px; } /* Code block — dark ink card flipped against the parchment. The contrast * is deliberate; it reads like a code excerpt set in a printed book. */ .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose pre, .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage div[data-streamdown="code-block"] > pre { background: var(--halcyon-ink) !important; color: #e8e2d5; border: 1px solid var(--halcyon-ink); border-radius: 0; padding: 14px 16px; margin: 1em 0; font-family: var(--halcyon-mono); font-size: 0.86em; line-height: 1.55; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), var(--halcyon-shadow-soft); } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose pre code { background: transparent; color: inherit; border: none; padding: 0; } /* Anchor links — ember underline in classic editorial style. */ .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose a { color: var(--halcyon-ember); text-decoration-line: underline; text-decoration-color: color-mix( in srgb, var(--halcyon-ember) 35%, transparent ); text-decoration-thickness: 1px; text-underline-offset: 3px; transition: text-decoration-color 160ms ease; } .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose a:hover { text-decoration-color: var(--halcyon-ember); } /* Horizontal rule — short, centered, ornament-like. */ .chat-css-demo-scope .copilotKitMessage.copilotKitAssistantMessage .prose hr { border: none; height: 1px; background: var(--halcyon-rule); width: 64px; margin: 1.6em auto; } /* @endregion[assistant-message] */ /* @region[input-composer] */ /* Composer — a sharp paper card with an ember focus rule. The default * pill is rounded; squaring it off is again the visual cue that this is * a different brand. The wrapper around .copilotKitInput uses a fixed * white background in v2, so we override it directly. */ .chat-css-demo-scope .copilotKitInput { font-family: var(--halcyon-sans) !important; background: var(--halcyon-card) !important; border: 1px solid var(--halcyon-rule); border-radius: 0 !important; padding: 14px 16px; min-height: 56px; box-shadow: 0 1px 0 rgba(26, 23, 20, 0.03), 0 8px 24px -16px rgba(26, 23, 20, 0.18); transition: border-color 200ms ease, box-shadow 200ms ease, transform 120ms ease; } .chat-css-demo-scope .copilotKitInput:focus-within { border-color: var(--halcyon-ember); box-shadow: 0 0 0 3px rgba(196, 74, 31, 0.12), 0 1px 0 rgba(196, 74, 31, 0.18), 0 14px 36px -16px rgba(196, 74, 31, 0.22); transform: translateY(-1px); } .chat-css-demo-scope .copilotKitInput textarea { font-family: var(--halcyon-sans) !important; font-size: 1rem; font-weight: 400; color: var(--halcyon-ink); line-height: 1.55; letter-spacing: -0.005em; } .chat-css-demo-scope .copilotKitInput textarea::placeholder { color: var(--halcyon-ink-mute); font-style: italic; opacity: 1; } /* @endregion[input-composer] */ /* @region[input-buttons] */ /* The send button — a square ember chit, not the default circular pill. * v2 ships this as `