Skip to main content

Customizing the widget’s look

The widget ships with sensible defaults that work on light backgrounds. You can override any of that from your own site’s CSS — the widget honors a small set of CSS custom properties (variables) plus a set of Shadow DOM parts for cases where the variables aren’t specific enough.

You don’t need to do any of this. The widget looks fine untouched. But if your site has a strong brand you want the widget to inherit, or you’re running a dark theme, here’s how.

How customization works

The widget renders inside a Shadow DOM. That means your page’s global CSS can’t leak into the widget by accident — and, conversely, the widget’s internal styles can’t leak into your page. Two mechanisms cross that boundary intentionally:

  1. CSS custom properties (variables) — set them on your page (or on the <ask-pod-widget> element itself) and the widget reads them from inside the Shadow DOM
  2. CSS Shadow Parts (::part()) — for elements explicitly labeled with a part="" attribute inside the widget, you can target them from outside using the ::part() selector

Variables cover 90% of what customers want (colors, radius, font). Parts cover the rest.

Quick example

Say you’re a church with a warm brown-red brand color, using a serif on your site, and you want the widget to match.

Add this to your site’s global stylesheet:

ask-pod-widget {
    --podsaid-accent: #8b3a1e;
    --podsaid-accent-fg: #fff8f2;
    --podsaid-font: 'EB Garamond', Georgia, serif;
    --podsaid-radius: 4px;
}

That’s it. The widget now uses your brand color for tabs, buttons, and focus states; renders body text in your serif; and uses squared-off corners instead of the default rounded ones.

CSS variables — the full list

Set any of these on the <ask-pod-widget> element (or anywhere they cascade from, like :root) to override the defaults.

Colors

VariableDefaultControls
--podsaid-bgtransparentWidget frame background
--podsaid-fginheritMain text color
--podsaid-accent#E05A2BActive tab underline, primary buttons, focus rings, links
--podsaid-accent-fgcurrentColorText color on accent-colored backgrounds (e.g. Send button)
--podsaid-muted60% of currentColorSecondary text (dates, char counters, footer copy)
--podsaid-surface6% of currentColorSubtle secondary background (stat tiles, controls background)
--podsaid-border15% of currentColorBorders between tabs, around inputs, dividers
--podsaid-error#c00Error text and error state
--podsaid-inputinherits from --podsaid-surfaceInput field background
--podsaid-input-fginherits from --podsaid-fgInput field text

The four “N% of currentColor” defaults use color-mix(in srgb, currentColor N%, transparent) — which means they automatically adapt to whatever text color they cascade under. If your page uses light text on a dark background, the widget’s borders and surfaces adapt without you doing anything.

Layout and sizing

VariableDefaultControls
--podsaid-radius8pxBorder radius on inputs, cards, tiles
--podsaid-pane-height480pxHeight of the main pane (chat/search area). Set to 100% if you want the widget to fill a bounded container

Typography

VariableDefaultControls
--podsaid-fontsystem-ui, sans-serifFont family for all widget text

Shadow Parts — targeting specific elements

When a CSS variable isn’t specific enough (say you want the Send button a different shape from other buttons), the widget exposes these named parts:

PartElement it targets
widgetThe outer widget container
feed-headerThe feed identity strip (avatar + name + info) above the tabs
tabsThe tab container
tabEach individual tab (Ask, Search)
paneThe active pane (chat or search)
search-inputThe search text input
search-submitThe Search button
chat-inputThe chat textarea
chat-sendThe Send button
resultEach search result row
turnEach chat turn (question or answer)
citationEach citation card inside an assistant answer

Target from your global CSS with ::part():

/* Make just the Send button pill-shaped */
ask-pod-widget::part(chat-send) {
    border-radius: 999px;
    padding-inline: 1.25rem;
}

/* Highlight the active tab differently */
ask-pod-widget::part(tab) {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.75rem;
}

/* Give search results a subtle card look */
ask-pod-widget::part(result) {
    background: #fdfbf7;
    border-left: 3px solid var(--podsaid-accent, #E05A2B);
}

One catch: you can’t target descendants of a part with plain descendant selectors. ::part(result) p { ... } won’t work — the selector needs to end at the part boundary. If you need finer control, add another part attribute in a follow-up, or use CSS variables cascaded through the part.

Common recipes

Dark mode

@media (prefers-color-scheme: dark) {
    ask-pod-widget {
        --podsaid-bg: #0f172a;
        --podsaid-fg: #f1f5f9;
        --podsaid-accent: #f97316;
        --podsaid-accent-fg: #0f172a;
        --podsaid-border: rgba(255, 255, 255, 0.15);
        --podsaid-surface: rgba(255, 255, 255, 0.06);
    }
}

Because the widget uses color-mix for --podsaid-muted, --podsaid-border, and --podsaid-surface, you often only need to set --podsaid-fg and --podsaid-accent for a dark theme — the derived colors adapt automatically.

Fill a full-height sidebar

If you’re embedding in a fixed-height sidebar container (e.g. a right-side widget slot), tell the widget to fill it:

.my-sidebar ask-pod-widget {
    --podsaid-pane-height: 100%;
    display: block;
    height: 100%;
}

Match a church’s Google-Fonts pairing

<!-- Load the fonts once at the top of your <head> -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Merriweather:wght@400;700&display=swap" rel="stylesheet">
ask-pod-widget {
    --podsaid-font: 'Merriweather', Georgia, serif;
}

The widget’s Shadow DOM inherits the font because font resources on the page cascade in.

Brand-color the launcher without changing anything else

ask-pod-widget {
    --podsaid-accent: #2c6e49;
    --podsaid-accent-fg: white;
}

Since the Send button, active tab underline, and focus ring all read from --podsaid-accent, one variable change updates all of them consistently.

When customization doesn’t take effect

  • You forgot the widget renders in Shadow DOM. Rules like ask-pod-widget button { ... } don’t work — you can’t reach inside from outside. Use variables or ::part().
  • You set the variable on a parent that isn’t in the widget’s inheritance chain. Safest: set on ask-pod-widget itself, or on :root.
  • The variable name is misspelled. They’re all --podsaid-*, not --pod-said-* or --podsaid_*. Autocomplete in your editor helps.
  • A more-specific selector inside the widget wins. Rare, but the widget’s internal styles sometimes use !important when the layout would otherwise break. If a variable seems ignored, DevTools → Elements → click the shadow root → inspect the specific element to see what rule won.

What’s stable

Variable and part names are considered public API for the widget. Additions come in minor versions; renames or removals only in major versions. See the widget’s stability principles for the policy.

Related

  • WordPress — pastes the snippet; your global CSS reaches it
  • Squarespace — Code Block for the snippet, Custom CSS for the customization
  • Next.js — put your customization CSS in a global stylesheet imported from your root layout
  • Allowed origins — the security allowlist