Skip to content

Theming

The widget renders into an open shadow root, with :host { all: initial }. Your stylesheet cannot reach inside it, and nothing inside it can leak out onto your page. The one channel between the two is a set of CSS custom properties set on the host element.

Most of the time you do not need to use it: the SDK samples your page first.

What is sampled

On takeover, the SDK reads the computed style of your first non-choice field, your form and your submit button:

TokenSampled fromFallback
--nam-fontthe field's font-family, else the form'ssystem-ui, -apple-system, "Segoe UI", sans-serif
--nam-font-sizethe same source's font-size16px
--nam-fgthe field or form color, if opaque#1f2937
--nam-bgthe nearest opaque background-color walking up from the form#ffffff
--nam-borderthe field's border-top-color#d1d5db
--nam-radiusthe field's border-top-left-radius8px
--nam-accentthe submit button's background-color#2563eb
--nam-accent-fgthe submit button's color#ffffff

Four more are derived from that pair rather than sampled, so a dark host page gets dark surfaces instead of pale grey ones:

TokenHowFallback
--nam-mutedforeground blended toward background until it clears 4.5:1 against the background#6b7280
--nam-bubbleforeground blended into background until text on it clears 4.5:1#f3f4f6
--nam-dark / --nam-on-darkthe sampled pair, inverted — a sheet cover is the page turned over#1f2937 / #ffffff
--nam-accent-softaccent blended toward background, else --nam-bubble#eff4ff

A bad pair is left alone

If the sampled foreground and background do not themselves reach 4.5:1, nothing is derived and the known-good defaults are kept. A blend of an unreadable pair is only unreadable twice.

Overriding it

data-nam-theme takes a JSON object of custom properties, merged over the sampled set:

html
<form
  data-nam-landing-page="kestrel"
  data-nam-key="lp_live_xxxxxxxx"
  data-nam-theme='{"--nam-accent":"#e8862b","--nam-display-font":"Fraunces, serif","--nam-image-position":"center 30%"}'
>

Only string values whose keys look like --a-custom-property survive parsing. Malformed JSON, an array, or an empty result all yield null and the sampled theme is used unchanged — silently, which is why a theme that "did not apply" is almost always a quoting problem.

Escape inner single quotes

The JSON needs double quotes, so the attribute has to use single ones. A single quote inside the JSON — a font name like 'DM Sans' — truncates the attribute there, and the browser scatters the remainder as bare attributes. Write it as &#39;.

Tokens you can only set here

These are never sampled. They exist for the cases the page has to decide.

TokenDefaultWhat it controls
--nam-image-positioncenterThe object-position of every picture the SDK draws — answer tiles, option cards, sheet covers. Takes any CSS object-position, e.g. center 20%.
--nam-thread-maxmin(60vh, 520px)The inline thread's maximum height before it scrolls. Ignored in panel layout, which is already full height.
--nam-display-fontvar(--nam-font)Headings on question units, cards and sheets. Set it to give the experience your display face.
--nam-surfacevar(--nam-bg)The background behind stage blocks.
--nam-gap12pxThe global spacing rhythm.
--nam-inka 55% mix of --nam-borderEvery hairline border.
--nam-lifta soft teal-neutral drop shadowBubble and card elevation.

About the crop

Every image is object-fit: cover into a wide box — roughly 2.9:1 for an answer tile and 4.4:1 for an option card — so it keeps the middle band of whatever it is given. Portrait photography with faces high in the frame renders as headless torsos.

--nam-image-position moves that crop, but it moves it for every picture on the page at once. It works well for a photography library shot consistently; where the art varies — a full-length shot beside a close-up — cut the art to the shape instead. There is no per-image control, and the host stylesheet cannot supply one.

Class names inside the shadow root

The rendered markup uses nam-* classes and a set of data-nam-* hooks, listed in the attribute reference. They are stable enough to write an end-to-end test against and are not a supported styling channel: your CSS cannot reach them, and they are free to change with the bundle.

Proprietary. All rights reserved.