diff --git a/src/components/overrides/PageTitle.astro b/src/components/overrides/PageTitle.astro
index 360afa0..e970c08 100644
--- a/src/components/overrides/PageTitle.astro
+++ b/src/components/overrides/PageTitle.astro
@@ -14,10 +14,16 @@ const { platforms, wsTopic, scope, status, syntax, arguments: args, aliases, acc
Astro.locals.starlightRoute.entry.data;
---
-
+
{platforms && platforms.length > 0 &&
}
{wsTopic &&
}
{syntax &&
}
{(access || requires || cooldown || (aliases && aliases.length > 0)) && (
)}
+
+
diff --git a/src/components/overrides/Sidebar.astro b/src/components/overrides/Sidebar.astro
new file mode 100644
index 0000000..e950c36
--- /dev/null
+++ b/src/components/overrides/Sidebar.astro
@@ -0,0 +1,116 @@
+---
+import { Icon } from '@astrojs/starlight/components';
+import SidebarSublist from '@astrojs/starlight/components/SidebarSublist.astro';
+import SidebarPersister from '@astrojs/starlight/components/SidebarPersister.astro';
+import MobileMenuFooter from 'virtual:starlight/components/MobileMenuFooter';
+
+const { sidebar } = Astro.locals.starlightRoute;
+const { topics, isPageWithTopic } = Astro.locals.starlightSidebarTopics;
+const current = topics.find((topic) => topic.isCurrent);
+---
+
+
+
+
+
+
diff --git a/src/components/overrides/SiteTitle.astro b/src/components/overrides/SiteTitle.astro
new file mode 100644
index 0000000..d06ba59
--- /dev/null
+++ b/src/components/overrides/SiteTitle.astro
@@ -0,0 +1,22 @@
+---
+const { siteTitleHref } = Astro.locals.starlightRoute;
+---
+
+
+
+
+ Docs
+
+
+
diff --git a/src/content/docs/developers.mdx b/src/content/docs/developers.mdx
new file mode 100644
index 0000000..1125a0f
--- /dev/null
+++ b/src/content/docs/developers.mdx
@@ -0,0 +1,15 @@
+---
+title: Developers
+description: Build StreamElements integrations with the HTTP API, WebSockets, and custom widgets.
+---
+
+import { CardGrid, LinkCard } from '@astrojs/starlight/components';
+
+Choose the tools you need to build on StreamElements.
+
+
+
+
+
+
+
diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx
index b33d13d..ba739a9 100644
--- a/src/content/docs/index.mdx
+++ b/src/content/docs/index.mdx
@@ -1,6 +1,6 @@
---
title: StreamElements Documentation
-description: The official documentation for StreamElements — chatbot, overlays, realtime websockets, and the developer API.
+description: The official documentation for StreamElements — Chatbot, SE.Live, overlays, and developer tools.
# The default
would double the brand ("StreamElements Documentation | StreamElements Docs").
head:
- tag: title
@@ -35,19 +35,19 @@ import { CardGrid, LinkCard } from '@astrojs/starlight/components';
description="Commands, variables, timers, spam filters, and interactive modules for your chat."
/>
+
+
+
+## More from the Help Center
+
+The [SE.Live Help Center](https://support.streamelements.com/hc/en-us/sections/10474402361490-SE-Live) has detailed guides for scenes and sources, Canvas, and streaming formats.
+
+For setup, features, and multistreaming, open the [complete SE.Live guide](https://support.streamelements.com/hc/en-us/articles/18771457842066).
diff --git a/src/content/docs/selive/guides/overlays-and-alerts.mdx b/src/content/docs/selive/guides/overlays-and-alerts.mdx
new file mode 100644
index 0000000..b725b69
--- /dev/null
+++ b/src/content/docs/selive/guides/overlays-and-alerts.mdx
@@ -0,0 +1,22 @@
+---
+title: Add overlays and alerts
+description: Create an overlay and display it in your OBS scene with SE.Live.
+---
+
+## Create your overlay
+
+1. Open [My Overlays](https://streamelements.com/dashboard/overlays) and choose **New overlay**.
+2. Choose a resolution that matches your scene.
+3. In the editor, select **+ → Alerts → AlertBox** to add alerts. Configure the alert types you need, then save.
+
+The [overlay setup guide](/overlays/getting-started) includes screenshots of these steps.
+
+## Add it to OBS
+
+Copy the overlay URL. In OBS, add a **Browser Source** to your scene and paste the URL into its properties. Match the source dimensions to your overlay. Place it above sources that would cover it.
+
+Keep the overlay URL private. See the [SE.Live support guide](https://support.streamelements.com/hc/en-us/articles/18771457842066) for more on overlay setup.
+
+## Customize further
+
+For an overlay with your own HTML, CSS, and JavaScript, follow [Build your first custom widget](/overlays/first-custom-widget).
diff --git a/src/content/docs/selive/index.mdx b/src/content/docs/selive/index.mdx
new file mode 100644
index 0000000..0ff9f9e
--- /dev/null
+++ b/src/content/docs/selive/index.mdx
@@ -0,0 +1,15 @@
+---
+title: SE.Live
+description: Set up SE.Live for OBS Studio, add overlays, and find guides for your stream.
+---
+
+import { CardGrid, LinkCard } from '@astrojs/starlight/components';
+
+SE.Live brings StreamElements chat, activity, and streaming tools into OBS Studio. Start with setup, then choose a guide for the task you want to complete.
+
+
+
+
+
+
+
diff --git a/src/content/docs/selive/troubleshooting.mdx b/src/content/docs/selive/troubleshooting.mdx
new file mode 100644
index 0000000..3fbafee
--- /dev/null
+++ b/src/content/docs/selive/troubleshooting.mdx
@@ -0,0 +1,17 @@
+---
+title: SE.Live troubleshooting
+description: Find troubleshooting steps and contact support for SE.Live.
+---
+
+For installation, login, and streaming issues, start with [SE.Live Troubleshooting in the Help Center](https://support.streamelements.com/hc/en-us/articles/10474479415442).
+
+## Get help with your setup
+
+When asking for help, include:
+
+- Your OBS and SE.Live versions.
+- What you were doing when the problem started.
+- The exact error message, if there is one.
+- Whether the problem happens every time.
+
+Use the [Help Center](https://support.streamelements.com/) to contact support. Remove stream keys and private overlay URLs from screenshots before sharing them.
diff --git a/src/styles/custom.css b/src/styles/custom.css
index 4a8e239..dccd5c1 100644
--- a/src/styles/custom.css
+++ b/src/styles/custom.css
@@ -1,84 +1,106 @@
-/* StreamElements Starlight theme.
- Color tokens mirror the @frontend/ui design system (frontend monorepo,
- packages/ui/src/styles/globals.css, OKLCH). To resync with the app,
- update the --se-* block — everything else derives from it. */
-
-/* Typography: Inter Variable (loaded via customCss entry in astro.config.mjs).
- @frontend/ui intentionally ships no font family (each app sets its own),
- so Inter is a docs-local choice, not a divergence. */
+/* Color values copied from @frontend/ui src/styles/tokens.css.
+ Keep these theme blocks in sync with that file. Starlight uses data-theme
+ instead of .dark; no frontend checkout or Tailwind is required to build. */
:root {
--sl-font: 'Inter Variable', ui-sans-serif, system-ui, sans-serif;
-
- /* Brand + semantic colors (source token noted per line). */
- --se-primary: oklch(0.6426 0.1869 265.73); /* --primary / $uiPrimaryMain #5684FD */
- --se-primary-dark: oklch(0.68 0.16 265.73); /* .dark --primary */
- --se-success: oklch(0.797 0.1683 156.11); /* --success / $uiSuccessMain #46DC8E */
- --se-attention: oklch(0.7272 0.177 54.06); /* --attention / $uiAttentionMain #F98215 */
- --se-destructive: oklch(0.6383 0.2236 17.81); /* --destructive / $uiErrorMain #F53656 */
- --se-purple: oklch(0.6506 0.2049 293.08); /* --chart-5 */
-
- /* Neutral ramp (hue 250, shared across modes in the app). */
+ --se-radius: 0.625rem;
+ --se-radius-sm: 0.375rem;
+ --se-purple: oklch(0.6506 0.2049 293.08);
--se-neutral-0: oklch(1 0 250);
- --se-neutral-50: oklch(0.9861 0 250); /* light --background #f7f7f7 */
+ --se-neutral-50: oklch(0.9861 0 250);
--se-neutral-100: oklch(0.9683 0.0017 250);
- --se-neutral-200: oklch(0.9345 0.0032 250); /* light --border */
+ --se-neutral-200: oklch(0.9345 0.0032 250);
--se-neutral-300: oklch(0.8811 0.0043 250);
- --se-neutral-400: oklch(0.7107 0.0055 250); /* dark --muted-foreground */
+ --se-neutral-400: oklch(0.7107 0.0055 250);
--se-neutral-500: oklch(0.5555 0.0057 250);
--se-neutral-600: oklch(0.4419 0.0052 250);
--se-neutral-700: oklch(0.3715 0.0046 250);
--se-neutral-800: oklch(0.2686 0.0076 250);
--se-neutral-900: oklch(0.2046 0.006 250);
- --se-neutral-950: oklch(0.1684 0.005 250); /* dark --background #131315 */
- --se-card-dark: oklch(0.2146 0.006 250); /* .dark --card #232428 */
- --se-sidebar-dark: oklch(0.19 0.005 250); /* .dark --sidebar */
+ --se-neutral-950: oklch(0.1684 0.005 250);
+}
- /* Radii (--radius: 0.625rem base). */
- --se-radius: 0.625rem;
- --se-radius-sm: 0.375rem;
+:root[data-theme='light'] {
+ --se-background: oklch(0.9861 0 250);
+ --se-foreground: oklch(0 0 0 / 87%);
+ --se-card: oklch(1 0 250);
+ --se-popover: oklch(1 0 250);
+ --se-primary: oklch(0.56 0.1869 265.73);
+ --se-primary-foreground: oklch(1 0 0);
+ --se-muted-foreground: oklch(0 0 0 / 60%);
+ --se-destructive: oklch(0.58 0.2 25);
+ --se-success: oklch(0.797 0.1683 156.11);
+ --se-attention: oklch(0.7272 0.177 54.06);
+ --se-border: var(--se-neutral-200);
+ --se-ring: oklch(0.56 0.1869 265.73);
+ --se-shadow-float: 0 4px 12px rgb(0 0 0 / 0.09), 0 1px 3px rgb(0 0 0 / 0.06);
+ --se-sidebar: oklch(1 0 0);
+ --se-sidebar-accent: oklch(0.9653 0.0019 250);
+ --se-sidebar-border: oklch(0 0 0 / 10%);
}
-/* Starlight ramps derived from the tokens above.
- IMPORTANT: theme ramps MUST be scoped to [data-theme=...] — this stylesheet
- is unlayered and beats Starlight's layered theme styles regardless of
- specificity, so an unscoped :root ramp would poison the other mode.
- Starlight inverts token meaning per mode: `white` = text, `black` = page
- background. */
:root[data-theme='dark'] {
- --sl-color-accent-low: color-mix(in oklch, var(--se-primary) 32%, var(--se-neutral-950));
- --sl-color-accent: var(--se-primary-dark);
- --sl-color-accent-high: color-mix(in oklch, var(--se-primary) 45%, white);
-
- --sl-color-white: var(--se-neutral-100);
- --sl-color-gray-1: var(--se-neutral-200);
- --sl-color-gray-2: var(--se-neutral-300);
- --sl-color-gray-3: var(--se-neutral-400);
- --sl-color-gray-4: var(--se-neutral-600);
- --sl-color-gray-5: var(--se-neutral-800); /* hairlines ≈ .dark --border */
- --sl-color-gray-6: var(--se-card-dark); /* raised surfaces / code blocks */
- --sl-color-gray-7: var(--se-sidebar-dark);
- --sl-color-black: var(--se-neutral-950);
-
- --se-shadow-float: 0 1px 0 rgb(255 255 255 / 0.04) inset, 0 6px 16px rgb(0 0 0 / 0.45); /* .dark --shadow-float */
+ --se-background: oklch(0.1684 0.005 250);
+ --se-foreground: oklch(0.9683 0.0017 250);
+ --se-card: oklch(0.2146 0.006 250);
+ --se-popover: oklch(0.2686 0.0076 250);
+ --se-primary: oklch(0.56 0.1869 265.73);
+ --se-primary-foreground: oklch(1 0 0);
+ --se-muted-foreground: oklch(0.7107 0.0055 250);
+ --se-destructive: oklch(0.68 0.21 17.81);
+ --se-success: oklch(0.797 0.1683 156.11);
+ --se-attention: oklch(0.7272 0.177 54.06);
+ --se-border: oklch(1 0 0 / 8%);
+ --se-ring: oklch(0.56 0.1869 265.73);
+ --se-shadow-float: 0 1px 0 rgb(255 255 255 / 0.04) inset, 0 6px 16px rgb(0 0 0 / 0.45);
+ --se-sidebar: oklch(0.19 0.005 250);
+ --se-sidebar-accent: oklch(1 0 0 / 6%);
+ --se-sidebar-border: var(--se-border);
}
-:root[data-theme='light'] {
- --sl-color-accent-low: color-mix(in oklch, var(--se-primary) 16%, white);
- /* Brand primary darkened for AA text contrast on light surfaces (#5684FD
- alone is ~3.2:1 on white); tints and dark mode keep the exact brand hue. */
- --sl-color-accent: oklch(0.52 0.1869 265.73);
- --sl-color-accent-high: oklch(0.38 0.15 265.73);
- --sl-color-white: var(--se-neutral-900);
+:root[data-theme='light'] {
+ --sl-color-white: var(--se-foreground);
--sl-color-gray-1: var(--se-neutral-800);
--sl-color-gray-2: var(--se-neutral-700);
--sl-color-gray-3: var(--se-neutral-500);
--sl-color-gray-4: var(--se-neutral-400);
- --sl-color-gray-5: var(--se-neutral-200); /* hairlines = light --border */
- --sl-color-gray-6: var(--se-neutral-100); /* inline code bg = light --well */
- --sl-color-gray-7: var(--se-neutral-50); /* subtle bg = light --background */
- --sl-color-black: var(--se-neutral-0); /* page bg = light --card */
-
- --se-shadow-float: 0 4px 12px rgb(0 0 0 / 0.09), 0 1px 3px rgb(0 0 0 / 0.06); /* --shadow-float */
+ --sl-color-gray-5: var(--se-neutral-200);
+ --sl-color-gray-6: var(--se-neutral-100);
+ --sl-color-gray-7: var(--se-background);
+ --sl-color-black: var(--se-card);
+ --sl-color-accent: var(--se-primary);
+ --sl-color-accent-low: color-mix(in srgb, var(--se-primary) 10%, var(--se-sidebar));
+ --sl-color-accent-high: oklch(0.38 0.15 265.73);
+ --sl-color-text-accent: var(--se-primary);
+}
+:root[data-theme='dark'] {
+ --sl-color-white: var(--se-foreground);
+ --sl-color-gray-1: var(--se-neutral-200);
+ --sl-color-gray-2: var(--se-neutral-300);
+ --sl-color-gray-3: var(--se-muted-foreground);
+ --sl-color-gray-4: var(--se-neutral-600);
+ --sl-color-gray-5: var(--se-neutral-800);
+ --sl-color-gray-6: var(--se-card);
+ --sl-color-gray-7: var(--se-sidebar);
+ --sl-color-black: var(--se-background);
+ --sl-color-accent: var(--se-primary);
+ --sl-color-accent-low: color-mix(in srgb, var(--se-primary) 22%, var(--se-sidebar));
+ /* Text tint for readable links; filled controls use the exact UI primary. */
+ --sl-color-accent-high: color-mix(in srgb, var(--se-primary) 55%, white);
+ --sl-color-text-accent: var(--sl-color-accent-high);
+}
+:root[data-theme] {
+ --sl-color-bg: var(--se-background);
+ --sl-color-bg-nav: var(--se-sidebar);
+ --sl-color-bg-sidebar: var(--se-sidebar);
+ --sl-color-hairline-light: var(--se-border);
+ --sl-color-hairline: var(--se-border);
+ --sl-color-text: var(--se-foreground);
+}
+.sl-link-button.primary {
+ background: var(--se-primary);
+ border-color: var(--se-primary);
+ color: var(--se-primary-foreground);
}
/* Inline code may wrap; block code wrapping is handled by Expressive Code
@@ -98,6 +120,9 @@
.card,
.sl-link-card {
border-radius: var(--se-radius);
+ border-color: var(--se-border);
+ background-color: var(--se-card);
+ box-shadow: none;
transition:
border-color 0.2s ease,
transform 0.2s ease,
@@ -110,35 +135,14 @@
box-shadow: var(--se-shadow-float);
}
-/* Topic switcher: neutral icon chips at rest (muted icon on a subtly raised
- surface, like the app sidebar), brand-primary tint only on hover/current —
- color signals state, not category. */
-.starlight-sidebar-topics .starlight-sidebar-topics-icon {
- border: none;
- border-radius: var(--se-radius-sm);
- padding: 0.3rem;
- background-color: var(--sl-color-gray-6);
- color: var(--sl-color-gray-3);
- transition: background-color 0.15s ease, color 0.15s ease;
-}
-.starlight-sidebar-topics svg {
- font-size: 1.05rem;
-}
-.starlight-sidebar-topics
- a:is(.starlight-sidebar-topics-current, :hover, :focus-visible)
- .starlight-sidebar-topics-icon {
- background-color: color-mix(in srgb, var(--se-primary) 15%, transparent);
- color: var(--sl-color-accent);
-}
-
/* StreamElements command syntax blocks keep their signature orange accent bar
(system attention orange). */
.expressive-code pre[data-language='streamelements'] {
border-inline-start: 3px solid var(--se-attention);
}
-/* Keyboard shortcut keys. */
-kbd {
+/* Keyboard shortcuts in docs content; Starlight owns its search shortcut. */
+.sl-markdown kbd {
display: inline-block;
padding: 0.1em 0.45em;
border: 1px solid var(--sl-color-gray-4);
@@ -150,3 +154,142 @@ kbd {
font-size: 0.8em;
line-height: 1.4;
}
+
+@media (prefers-reduced-motion: reduce) {
+ .card, .sl-link-card { transition: none; }
+ .card:hover, .sl-link-card:hover { transform: none; }
+}
+
+/* Semantic callouts and badges share the app palette. */
+:root[data-theme] {
+ --sl-color-blue: var(--se-primary);
+ --sl-color-blue-low: var(--sl-color-accent-low);
+ --sl-color-blue-high: var(--sl-color-text-accent);
+ --sl-color-purple: var(--se-primary);
+ --sl-color-purple-low: var(--sl-color-accent-low);
+ --sl-color-purple-high: var(--sl-color-text-accent);
+ --sl-color-green: var(--se-success);
+ --sl-color-orange: var(--se-attention);
+ --sl-color-red: var(--se-destructive);
+ --sl-color-green-low: color-mix(in srgb, var(--se-success) 12%, var(--se-background));
+ --sl-color-orange-low: color-mix(in srgb, var(--se-attention) 12%, var(--se-background));
+ --sl-color-red-low: color-mix(in srgb, var(--se-destructive) 12%, var(--se-background));
+}
+:root[data-theme='light'] {
+ --sl-color-green-high: color-mix(in srgb, var(--se-success) 40%, black);
+ --sl-color-orange-high: color-mix(in srgb, var(--se-attention) 45%, black);
+ --sl-color-red-high: color-mix(in srgb, var(--se-destructive) 75%, black);
+}
+:root[data-theme='dark'] {
+ --sl-color-green-high: color-mix(in srgb, var(--se-success) 65%, white);
+ --sl-color-orange-high: color-mix(in srgb, var(--se-attention) 65%, white);
+ --sl-color-red-high: color-mix(in srgb, var(--se-destructive) 65%, white);
+}
+.starlight-aside { border-radius: var(--se-radius-sm); }
+
+@media (max-width: 49.999rem) {
+ .site-title { font-size: clamp(1rem, 4.6vw, 1.25rem); }
+}
+@media (max-width: 40rem) {
+ /* Keep reference columns readable; Starlight's table scrolls within the page. */
+ .sl-markdown-content table:has(tr > :nth-child(3)) :is(th, td) {
+ min-width: 9rem;
+ }
+}
+
+/* Article hierarchy: keep headings distinct without dwarfing short sections. */
+:root[data-theme] {
+ --sl-text-h1: 2.25rem;
+ --sl-text-h2: 1.75rem;
+ --sl-text-h3: 1.375rem;
+ --sl-text-h4: 1.125rem;
+}
+@media (max-width: 49.999rem) {
+ :root[data-theme] { --sl-text-h1: 1.875rem; --sl-text-h2: 1.5rem; }
+}
+@media (min-width: 50rem) {
+ .site-title { font-size: 1.5rem; }
+}
+@media (max-width: 40rem) {
+ .sl-markdown-content table:has(tr > :nth-child(3)) :is(th, td):last-child {
+ min-width: 16rem;
+ }
+}
+
+.pagination-links a {
+ background: var(--se-card);
+ border-color: var(--se-border);
+ border-radius: var(--se-radius);
+ box-shadow: none;
+ font-size: 0.875rem;
+}
+.pagination-links .link-title { font-size: 1.125rem; font-weight: 600; }
+.pagination-links a:hover { border-color: var(--se-primary); }
+
+/* Header: quieter branding and consistent controls. */
+.header .site-title {
+ color: var(--se-foreground);
+ font-size: 1.25rem;
+ letter-spacing: -0.025em;
+}
+.header .right-group, .header .social-icons { gap: 0.5rem; }
+.header .social-icons a {
+ display: grid;
+ place-items: center;
+ width: 2.5rem;
+ height: 2.5rem;
+ padding: 0;
+ margin: 0;
+ border-radius: var(--se-radius-sm);
+ color: var(--se-muted-foreground);
+}
+.header .social-icons a:hover {
+ background: var(--se-sidebar-accent);
+ color: var(--se-foreground);
+}
+.header .social-icons::after { height: 1.5rem; border-color: var(--se-border); }
+.header select { min-height: 2.5rem; }
+.header a:focus-visible, .header select:focus-visible {
+ outline: 2px solid var(--se-ring);
+ outline-offset: 2px;
+}
+@media (min-width: 50rem) and (max-width: 63.999rem) {
+ .header .social-icons a { width: 2rem; }
+}
+@media (max-width: 49.999rem) {
+ .header .site-title { font-size: clamp(1rem, 4.6vw, 1.125rem); }
+ :root[data-theme] { --sl-menu-button-size: 2.5rem; }
+ starlight-menu-button button,
+ starlight-menu-button[aria-expanded='true'] button {
+ background: var(--se-sidebar-accent);
+ color: var(--se-foreground);
+ border: 1px solid var(--se-border);
+ border-radius: var(--se-radius-sm);
+ box-shadow: none;
+ }
+}
+.header button[data-open-modal] { border-radius: var(--se-radius-sm); }
+.header button[data-open-modal]:focus-visible { outline: 2px solid var(--se-ring); outline-offset: 2px; }
+@media (min-width: 50rem) {
+ .header button[data-open-modal] { background: var(--se-card); border-color: var(--se-border); }
+}
+@media (max-width: 49.999rem) {
+ .header button[data-open-modal] { width: 2.5rem; justify-content: center; padding: 0; }
+}
+
+/* Use the available content width, not the viewport, to choose card columns.
+ Keep at most two columns and give each card at least 18rem when possible. */
+.card-grid {
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, max(18rem, calc(50% - 0.75rem))), 1fr));
+}
+@media (max-width: 30rem) {
+ .hero .actions {
+ flex-direction: column;
+ align-items: stretch;
+ width: 100%;
+ max-width: 24rem;
+ margin-inline: auto;
+ gap: 0.75rem;
+ }
+ .hero .actions a { justify-content: center; }
+}