in inTouch Docs
Get your key
Embed

Theme reference

159 fields. Every one of them optional, every one purely visual. This page is generated from the schema the validator itself uses, so it cannot promise a field that does not exist.

Rules

Set only some colours?

Then set colorScheme too. Otherwise a visitor in dark mode sees your colours mixed with inTouch's dark layer. The validator warns about this, but the warning reaches you, not them.

Values derived for you

A few colours are computed unless you set them, because getting them wrong is invisible until it is embarrassing:

Contrast

The validator computes contrast ratios per colour mode against the values that actually take effect — your sub-theme over your top level over the inTouch default — and warns below 4.5:1. It never refuses. Accessibility is your call; the number is our job.

Colours colors

Any CSS colour notation, including color-mix() and transparency.

FieldTypeDefaultWhat it changes
colors.bgcolor#E9E9EB / #0A0A0A darkMessage area — the lowest surface
colors.railcolor#ECEDEF / #131313 darkNarrow icon rail on the outside
colors.panelcolor#FFFFFF / #181818 darkChat list (sidebar)
colors.panelHeadercolor#F1F2F4 / #222222 darkHeaders, menus, dialogs
colors.hovercolor#F4F5F6 / #292929 darkSurface under the pointer
colors.activecolor#E4E6E9 / #333333 darkSelected row
colors.fieldcolor#FFFFFF / #2B2B2B darkForm fields in dialogs
colors.searchFieldcolor#EEEFF1 / #222222 darkSearch pill in the sidebar
colors.composerFieldcolor#FFFFFF / #262626 darkComposer pill below the chat
colors.chipBgcolor#FFFFFF / #292929 darkFilter chips
colors.chipBordercolorrgba(0,0,0,0.13) / transparent darkFilter chip border
colors.bordercolorrgba(0,0,0,0.11) / rgba(255,255,255,0.11) darkAll visible borders
colors.dividercolorrgba(0,0,0,0.075) / rgba(255,255,255,0.07) darkDividers in the chat list
colors.scrimcolorrgba(0,0,0,0.35) / rgba(0,0,0,0.45) darkScrim behind media timestamps
colors.modalScrimcolorrgba(0,0,0,0.5)Scrim behind dialogs
colors.shadowColorcolorrgba(0,0,0,0.13) / rgba(0,0,0,0.6) darkColour of every shadow
colors.scrollThumbcolorrgba(0,0,0,0.20) / rgba(255,255,255,0.16) darkScrollbar
colors.scrollThumbHovercolorrgba(0,0,0,0.34) / rgba(255,255,255,0.30) darkScrollbar under the pointer
colors.fgcolor#0A0A0A / #FFFFFF darkPrimary text colour
colors.mutedFgcolor#5E6368 / #A2A2A2 darkSecondary text (previews, subtitles)
colors.faintFgcolor#8A8E93 / #838383 darkFaintest text (times, hints)
colors.titleFgcolor#0084ffTitle above the chat list
colors.iconFgcolor#3F4347 / #D2D2D2 darkInterface icons
colors.accentcolor#0084ffBrand colour: links, active elements, badges
colors.accentSoftcolorrgba(0,132,255,0.13) / rgba(0,132,255,0.20) darkAccent as a surface (active chip)
colors.onAccentcolor#FFFFFFText and icons ON the accent surface
colors.destructivecolor#DC2626 / #EF4444 darkDelete, urgent, recording
colors.onlinecolor#22c55eConnection dot when connected
colors.bubbleIncolor#FFFFFF / #202020 darkIncoming bubble
colors.bubbleInFgcolorvar(--fg)Text in the incoming bubble
colors.bubbleOutcolor#0084ffOutgoing bubble
colors.bubbleOutFgcolor#FFFFFFText in the outgoing bubble
colors.bubbleOutAuthorcolorrgba(255,255,255,0.85)Sender name in the outgoing bubble
colors.bubbleOutMetacolorrgba(255,255,255,0.75)Time and ticks in the outgoing bubble
colors.bubbleOutMutedcolorrgba(255,255,255,0.8)Secondary text in the outgoing bubble
colors.bubbleOutIconcolorrgba(255,255,255,0.9)Menu chevron in the outgoing bubble
colors.checkReadcolor#9fd4ffTicks once read
colors.quoteBgcolorrgba(0,0,0,0.055) / rgba(255,255,255,0.08) darkQuote surface in incoming bubbles
colors.quoteBgOutcolorrgba(255,255,255,0.16) / rgba(0,0,0,0.20) darkQuote surface in outgoing bubbles
colors.quoteBarIncolorvar(--accent)Coloured bar on the quote (incoming)
colors.quoteBarOutcolorrgba(255,255,255,0.85)Coloured bar on the quote (outgoing)
colors.onAccentFillcolorrgba(255,255,255,0.28)Poll bar in the outgoing bubble
colors.onAccentSurfacecolorrgba(255,255,255,0.16)Button surface in the outgoing bubble
colors.onAccentBordercolorrgba(255,255,255,0.24)Button border in the outgoing bubble
colors.qrBackgroundcolor#FFFFFFSurface behind the QR code. It must stay light — a dark one makes the code unscannable.

Attachment menu colours actionColors

The coloured icons in the attachment menu.

FieldTypeDefaultWhat it changes
actionColors.urgentcolor#e0483cUrgent
actionColors.pollcolor#8b5cf6Poll
actionColors.eventcolor#f0932bEvent
actionColors.imagecolor#0084ffImages
actionColors.contactcolor#14b8a6Contact
actionColors.locationcolor#22c55eLocation
actionColors.gifcolor#ec4899GIF
actionColors.stickercolor#eab308Sticker

Message area background background

FieldTypeDefaultWhat it changes
background.patternstring(inTouch-Doodles)Pattern as a CSS url(); "none" removes it
background.patternOpacitynumber0.06 / 0.05 darkOpacity of the pattern
background.imagestringnoneImage behind the messages (https: and data: only)
background.imageFitcover · contain · auto—How the image is scaled
background.imagePositionstringcenterPosition of the image
background.overlaycolortransparentColour wash over the image — for legibility

Typography typography

FieldTypeDefaultWhat it changes
typography.fontFamilystring'Inter', -apple-system, …Font family for the whole interface
typography.fontImportUrlstring—Stylesheet of a web font. Only fonts.googleapis.com, fonts.gstatic.com and fonts.bunny.net — any other address would report the IP of every visitor to a third party.
typography.baselength15pxBase size: input fields, buttons
typography.bodylength14pxBody text, chat preview, search field
typography.messagelength14.5pxMessage text and menu rows
typography.namelength16pxChat name in the list and the header
typography.titlelength23pxTitle above the chat list
typography.avatarInitialslength17pxInitials in the avatar
typography.chiplength13.5pxFilter chips
typography.captionlength13pxLabels and secondary text
typography.quotelength13.2pxQuotes and poll labels
typography.authorlength12.8pxSender name in groups
typography.labellength12.5pxSubtitles in headers
typography.daySeparatorlength12.2pxDate separators
typography.smalllength12pxTime in the chat list, counters
typography.metalength11pxTime in the bubble, badges
typography.emojilength22pxEmoji picker
typography.modalTitlelength19pxDialog titles
typography.herolength30pxHeading in the empty state
typography.pairTitlelength28pxHeading on the linking screen
typography.lineHeightnumber1.4Line height in general
typography.lineHeightMessagenumber1.35Line height inside message bubbles
typography.weightLightnumber300Light weight (empty state)
typography.weightRegularnumber400Regular weight
typography.weightMediumnumber500Chat names, buttons
typography.weightSemiboldnumber600Sender names, badges
typography.weightBoldnumber700Title above the chat list

Radii radius

A number means pixels. 0 gives a squared-off interface, 999px a fully rounded one.

FieldTypeDefaultWhat it changes
radius.bubblelength9pxMessage bubble
radius.bubbleTaillength0pxCorner at the tail. 0 = pointed, as today
radius.quotelength5pxQuote block
radius.medialength6pxImages and videos inside bubbles
radius.cardlength8pxDate separators, small buttons, thumbnails
radius.menuItemlength8pxRows in the attachment menu
radius.popoverItemlength7pxRows in the popover menu
radius.listItemlength9pxRows in pick lists (forwarding)
radius.controllength10pxButtons, form fields, popovers
radius.panellength12pxAttachment menu, reaction chips
radius.modallength14pxDialogs
radius.qrlength14pxSurface around the QR code
radius.pairCardlength18pxCard on the linking screen
radius.composerlength24pxComposer pill and recording bar
radius.replyBarlength16pxReply preview above the composer
radius.pilllength999pxChips, badges, search field
radius.avatarlength50%Avatars. 50% round, 12px rounded, 0 square
radius.buttonlength50%Round control buttons

Sizes and spacing space

FieldTypeDefaultWhat it changes
space.railWidthlength64pxWidth of the icon rail
space.railHeightMobilelength56pxHeight of the rail on narrow screens
space.sidebarWidthstringclamp(360px, 34%, 560px)Width of the chat list; clamp() recommended
space.sidebarWidthMediumstringclamp(320px, 40%, 440px)Width at medium window widths
space.headerHeightlength60pxHeight of the conversation header
space.rowHeightlength72pxRow height in the chat list
space.avatarSizelength49pxAvatar in the chat list
space.avatarSizeSmalllength40pxAvatar in headers and lists
space.avatarSizeRaillength34pxAvatar in the icon rail
space.buttonSizelength40pxRound buttons in the composer
space.buttonSizeSmalllength38pxButtons in headers
space.buttonSizeRaillength44pxButtons in the icon rail
space.iconSizelength24pxIcon size, normal
space.iconSizeSmalllength18pxIcon size, small
space.iconSizeXSmalllength15pxIcon size, extra small
space.iconSizeLargelength26pxIcon size, large
space.bubbleMaxWidthstring65%Maximum bubble width
space.bubbleMaxWidthMobilestring82%Maximum bubble width on narrow screens
space.bubblePaddingXlength9pxBubble padding, horizontal
space.bubblePaddingYlength6pxBubble padding, vertical
space.messageGaplength2pxGap within one sender group
space.messageGroupGaplength12pxGap between sender groups
space.messagesPaddingXstring6%Side padding of the message area
space.gutterlength16pxGeneral side padding

Borders border

FieldTypeDefaultWhat it changes
border.widthlength1pxWidth of every border. 0 removes them

Shadows shadow

A full CSS shadow value, or "none".

FieldTypeDefaultWhat it changes
shadow.bubblestring0 1px 1px var(--shadow)Message bubble
shadow.chipstring0 1px 2px var(--shadow)Reaction chip
shadow.composerstring0 1px 3px var(--shadow)Composer pill
shadow.fabstring0 3px 12px var(--shadow)Scroll-to-bottom button
shadow.hintstring0 4px 14px var(--shadow)Urgent hint
shadow.emojistring0 6px 24px var(--shadow)Emoji picker
shadow.popoverstring0 8px 30px var(--shadow)Popover menu
shadow.menustring0 10px 34px var(--shadow)Attachment menu
shadow.pairCardstring0 10px 40px var(--shadow)Card while linking
shadow.modalstring0 16px 50px var(--shadow)Dialogs

Motion motion

prefers-reduced-motion is always honoured and cannot be switched off.

FieldTypeDefaultWhat it changes
motion.faststring.12sShort transitions (hover)
motion.mediumstring.16sMedium transitions

Layout layout

Moves things around. None of these removes a feature — hidden controls move into a menu automatically.

FieldTypeDefaultWhat it changes
layout.modesplit · conversation—"conversation" shows a single chat instead of list and chat side by side. The list stays reachable through a button in the header — an embedded chat never loses access to the visitor's other conversations
layout.railvisible · hidden—Icon rail. With "hidden", theme switching, sign-out and profile move into the sidebar menu
layout.railPositionleft · right—Side the icon rail sits on
layout.sidebarPositionleft · right—Side the chat list sits on
layout.messageAlignsides · left—"left" puts your own messages on the left too (forum look)
layout.bubbleTailson · off—Tail on the first bubble of a group
layout.avatarsInListon · off—Avatars in the chat list
layout.densitycomfortable · compact · spacious—Sets row height, gaps and padding as a block. Individual "space" values win

Linking notice badge

The notice on the linking screen that names the real domain. Styleable, but NOT removable — without it any site could present inTouch as its own and collect real account links behind a familiar facade.

FieldTypeDefaultWhat it changes
badge.positioncard · top—Placement inside the linking card: below the text (default) or above it. The notice always stays inside the card — it is protected against being moved out of view.
badge.toneauto · light · dark—Lightness of the notice
badge.colorcolorvar(--faint-fg)Text colour of the notice
badge.backgroundcolortransparentSurface behind the notice

Text strings

Overrides individual labels. Keys are the interface i18n names, e.g. "sidebar.title" or "composer.placeholder". Unknown keys are ignored.

An object of your own keys. Values are plain strings.

Icons icons

Replaces individual icons with your own SVG. Only path, circle, rect, line, polyline, polygon, g and defs are allowed — script, foreignObject, image and external references are stripped.

An object of your own keys. Values are SVG markup.

Light or dark colorScheme

Which colour layer applies. "auto" follows the visitor, "host" follows the embedding page (web component only). IMPORTANT: if you set only SOME colours, pin "light" or "dark" here — otherwise your colours mix with inTouch's other layer.

Value: auto · light · dark · host — default auto.

Light mode only light

The same groups as above, but only while light is shown. Top-level values apply to both layers and are overridden here.

Takes the same groups as above and applies them only in that colour mode.

Dark mode only dark

The counterpart to "light". Lets you ship a design that works in both layers instead of switching one off.

Takes the same groups as above and applies them only in that colour mode.

Custom CSS customCss

The last resort for anything no field covers. At most 64 KB, no @import (it would allow arbitrary third-party requests). Rules targeting the linking notice are stripped. Unversioned: a later change to class names can break your CSS.

A string of CSS.

inTouch API · https://api.in-touch.cc · keep your key private.
# intouch api
base    https://api.in-touch.cc
auth    X-API-Key: itk_<64 hex>   one key per user, no expiry, no scopes
docs    https://docs.in-touch.cc
format  every response is JSON and carries "success"

# embed-theme
159 fields, all optional, all purely visual.
Generated from the same schema the validator uses.

# rules
- Everything optional; omitted = inTouch default.
- Unknown fields are ignored, never an error.
- Additive only: a published name never changes meaning.
- Colours: any CSS notation incl. color-mix(). Lengths: number = px, or string with unit.
- Light/dark: top-level applies to both; "light"/"dark" override per mode;
  "colorScheme" pins one ("auto" | "light" | "dark" | "host").
- Setting only some colours without colorScheme mixes with the visitor's dark mode.

# derived
colors.bubbleOutFg -> timestamp, ticks, sender name, quote bar, button surfaces
                      inside outgoing bubbles follow it (default white).
colors.accent      -> colors.onAccent becomes black or white by luminance.

# contrast
Contrast is computed per colour mode against the effective value
(sub-theme > top level > inTouch default) and warned below 4.5:1. Never refused.

# fields

## colors - Colours
Any CSS colour notation, including color-mix() and transparency.
  colors.bg: color default=#E9E9EB dark=#0A0A0A - Message area — the lowest surface
  colors.rail: color default=#ECEDEF dark=#131313 - Narrow icon rail on the outside
  colors.panel: color default=#FFFFFF dark=#181818 - Chat list (sidebar)
  colors.panelHeader: color default=#F1F2F4 dark=#222222 - Headers, menus, dialogs
  colors.hover: color default=#F4F5F6 dark=#292929 - Surface under the pointer
  colors.active: color default=#E4E6E9 dark=#333333 - Selected row
  colors.field: color default=#FFFFFF dark=#2B2B2B - Form fields in dialogs
  colors.searchField: color default=#EEEFF1 dark=#222222 - Search pill in the sidebar
  colors.composerField: color default=#FFFFFF dark=#262626 - Composer pill below the chat
  colors.chipBg: color default=#FFFFFF dark=#292929 - Filter chips
  colors.chipBorder: color default=rgba(0,0,0,0.13) dark=transparent - Filter chip border
  colors.border: color default=rgba(0,0,0,0.11) dark=rgba(255,255,255,0.11) - All visible borders
  colors.divider: color default=rgba(0,0,0,0.075) dark=rgba(255,255,255,0.07) - Dividers in the chat list
  colors.scrim: color default=rgba(0,0,0,0.35) dark=rgba(0,0,0,0.45) - Scrim behind media timestamps
  colors.modalScrim: color default=rgba(0,0,0,0.5) - Scrim behind dialogs
  colors.shadowColor: color default=rgba(0,0,0,0.13) dark=rgba(0,0,0,0.6) - Colour of every shadow
  colors.scrollThumb: color default=rgba(0,0,0,0.20) dark=rgba(255,255,255,0.16) - Scrollbar
  colors.scrollThumbHover: color default=rgba(0,0,0,0.34) dark=rgba(255,255,255,0.30) - Scrollbar under the pointer
  colors.fg: color default=#0A0A0A dark=#FFFFFF - Primary text colour
  colors.mutedFg: color default=#5E6368 dark=#A2A2A2 - Secondary text (previews, subtitles)
  colors.faintFg: color default=#8A8E93 dark=#838383 - Faintest text (times, hints)
  colors.titleFg: color default=#0084ff - Title above the chat list
  colors.iconFg: color default=#3F4347 dark=#D2D2D2 - Interface icons
  colors.accent: color default=#0084ff - Brand colour: links, active elements, badges
  colors.accentSoft: color default=rgba(0,132,255,0.13) dark=rgba(0,132,255,0.20) - Accent as a surface (active chip)
  colors.onAccent: color default=#FFFFFF - Text and icons ON the accent surface
  colors.destructive: color default=#DC2626 dark=#EF4444 - Delete, urgent, recording
  colors.online: color default=#22c55e - Connection dot when connected
  colors.bubbleIn: color default=#FFFFFF dark=#202020 - Incoming bubble
  colors.bubbleInFg: color default=var(--fg) - Text in the incoming bubble
  colors.bubbleOut: color default=#0084ff - Outgoing bubble
  colors.bubbleOutFg: color default=#FFFFFF - Text in the outgoing bubble
  colors.bubbleOutAuthor: color default=rgba(255,255,255,0.85) - Sender name in the outgoing bubble
  colors.bubbleOutMeta: color default=rgba(255,255,255,0.75) - Time and ticks in the outgoing bubble
  colors.bubbleOutMuted: color default=rgba(255,255,255,0.8) - Secondary text in the outgoing bubble
  colors.bubbleOutIcon: color default=rgba(255,255,255,0.9) - Menu chevron in the outgoing bubble
  colors.checkRead: color default=#9fd4ff - Ticks once read
  colors.quoteBg: color default=rgba(0,0,0,0.055) dark=rgba(255,255,255,0.08) - Quote surface in incoming bubbles
  colors.quoteBgOut: color default=rgba(255,255,255,0.16) dark=rgba(0,0,0,0.20) - Quote surface in outgoing bubbles
  colors.quoteBarIn: color default=var(--accent) - Coloured bar on the quote (incoming)
  colors.quoteBarOut: color default=rgba(255,255,255,0.85) - Coloured bar on the quote (outgoing)
  colors.onAccentFill: color default=rgba(255,255,255,0.28) - Poll bar in the outgoing bubble
  colors.onAccentSurface: color default=rgba(255,255,255,0.16) - Button surface in the outgoing bubble
  colors.onAccentBorder: color default=rgba(255,255,255,0.24) - Button border in the outgoing bubble
  colors.qrBackground: color default=#FFFFFF - Surface behind the QR code. It must stay light — a dark one makes the code unscannable.

## actionColors - Attachment menu colours
The coloured icons in the attachment menu.
  actionColors.urgent: color default=#e0483c - Urgent
  actionColors.poll: color default=#8b5cf6 - Poll
  actionColors.event: color default=#f0932b - Event
  actionColors.image: color default=#0084ff - Images
  actionColors.contact: color default=#14b8a6 - Contact
  actionColors.location: color default=#22c55e - Location
  actionColors.gif: color default=#ec4899 - GIF
  actionColors.sticker: color default=#eab308 - Sticker

## background - Message area background
  background.pattern: string default=(inTouch-Doodles) - Pattern as a CSS url(); "none" removes it
  background.patternOpacity: number default=0.06 dark=0.05 - Opacity of the pattern
  background.image: string default=none - Image behind the messages (https: and data: only)
  background.imageFit: enum(cover|contain|auto) - How the image is scaled
  background.imagePosition: string default=center - Position of the image
  background.overlay: color default=transparent - Colour wash over the image — for legibility

## typography - Typography
  typography.fontFamily: string default='Inter', -apple-system, … - Font family for the whole interface
  typography.fontImportUrl: string - Stylesheet of a web font. Only fonts.googleapis.com, fonts.gstatic.com and fonts.bunny.net — any other address would report the IP of every visitor to a third party.
  typography.base: length default=15px - Base size: input fields, buttons
  typography.body: length default=14px - Body text, chat preview, search field
  typography.message: length default=14.5px - Message text and menu rows
  typography.name: length default=16px - Chat name in the list and the header
  typography.title: length default=23px - Title above the chat list
  typography.avatarInitials: length default=17px - Initials in the avatar
  typography.chip: length default=13.5px - Filter chips
  typography.caption: length default=13px - Labels and secondary text
  typography.quote: length default=13.2px - Quotes and poll labels
  typography.author: length default=12.8px - Sender name in groups
  typography.label: length default=12.5px - Subtitles in headers
  typography.daySeparator: length default=12.2px - Date separators
  typography.small: length default=12px - Time in the chat list, counters
  typography.meta: length default=11px - Time in the bubble, badges
  typography.emoji: length default=22px - Emoji picker
  typography.modalTitle: length default=19px - Dialog titles
  typography.hero: length default=30px - Heading in the empty state
  typography.pairTitle: length default=28px - Heading on the linking screen
  typography.lineHeight: number default=1.4 - Line height in general
  typography.lineHeightMessage: number default=1.35 - Line height inside message bubbles
  typography.weightLight: number default=300 - Light weight (empty state)
  typography.weightRegular: number default=400 - Regular weight
  typography.weightMedium: number default=500 - Chat names, buttons
  typography.weightSemibold: number default=600 - Sender names, badges
  typography.weightBold: number default=700 - Title above the chat list

## radius - Radii
A number means pixels. 0 gives a squared-off interface, 999px a fully rounded one.
  radius.bubble: length default=9px - Message bubble
  radius.bubbleTail: length default=0px - Corner at the tail. 0 = pointed, as today
  radius.quote: length default=5px - Quote block
  radius.media: length default=6px - Images and videos inside bubbles
  radius.card: length default=8px - Date separators, small buttons, thumbnails
  radius.menuItem: length default=8px - Rows in the attachment menu
  radius.popoverItem: length default=7px - Rows in the popover menu
  radius.listItem: length default=9px - Rows in pick lists (forwarding)
  radius.control: length default=10px - Buttons, form fields, popovers
  radius.panel: length default=12px - Attachment menu, reaction chips
  radius.modal: length default=14px - Dialogs
  radius.qr: length default=14px - Surface around the QR code
  radius.pairCard: length default=18px - Card on the linking screen
  radius.composer: length default=24px - Composer pill and recording bar
  radius.replyBar: length default=16px - Reply preview above the composer
  radius.pill: length default=999px - Chips, badges, search field
  radius.avatar: length default=50% - Avatars. 50% round, 12px rounded, 0 square
  radius.button: length default=50% - Round control buttons

## space - Sizes and spacing
  space.railWidth: length default=64px - Width of the icon rail
  space.railHeightMobile: length default=56px - Height of the rail on narrow screens
  space.sidebarWidth: string default=clamp(360px, 34%, 560px) - Width of the chat list; clamp() recommended
  space.sidebarWidthMedium: string default=clamp(320px, 40%, 440px) - Width at medium window widths
  space.headerHeight: length default=60px - Height of the conversation header
  space.rowHeight: length default=72px - Row height in the chat list
  space.avatarSize: length default=49px - Avatar in the chat list
  space.avatarSizeSmall: length default=40px - Avatar in headers and lists
  space.avatarSizeRail: length default=34px - Avatar in the icon rail
  space.buttonSize: length default=40px - Round buttons in the composer
  space.buttonSizeSmall: length default=38px - Buttons in headers
  space.buttonSizeRail: length default=44px - Buttons in the icon rail
  space.iconSize: length default=24px - Icon size, normal
  space.iconSizeSmall: length default=18px - Icon size, small
  space.iconSizeXSmall: length default=15px - Icon size, extra small
  space.iconSizeLarge: length default=26px - Icon size, large
  space.bubbleMaxWidth: string default=65% - Maximum bubble width
  space.bubbleMaxWidthMobile: string default=82% - Maximum bubble width on narrow screens
  space.bubblePaddingX: length default=9px - Bubble padding, horizontal
  space.bubblePaddingY: length default=6px - Bubble padding, vertical
  space.messageGap: length default=2px - Gap within one sender group
  space.messageGroupGap: length default=12px - Gap between sender groups
  space.messagesPaddingX: string default=6% - Side padding of the message area
  space.gutter: length default=16px - General side padding

## border - Borders
  border.width: length default=1px - Width of every border. 0 removes them

## shadow - Shadows
A full CSS shadow value, or "none".
  shadow.bubble: string default=0 1px 1px var(--shadow) - Message bubble
  shadow.chip: string default=0 1px 2px var(--shadow) - Reaction chip
  shadow.composer: string default=0 1px 3px var(--shadow) - Composer pill
  shadow.fab: string default=0 3px 12px var(--shadow) - Scroll-to-bottom button
  shadow.hint: string default=0 4px 14px var(--shadow) - Urgent hint
  shadow.emoji: string default=0 6px 24px var(--shadow) - Emoji picker
  shadow.popover: string default=0 8px 30px var(--shadow) - Popover menu
  shadow.menu: string default=0 10px 34px var(--shadow) - Attachment menu
  shadow.pairCard: string default=0 10px 40px var(--shadow) - Card while linking
  shadow.modal: string default=0 16px 50px var(--shadow) - Dialogs

## motion - Motion
prefers-reduced-motion is always honoured and cannot be switched off.
  motion.fast: string default=.12s - Short transitions (hover)
  motion.medium: string default=.16s - Medium transitions

## layout - Layout
Moves things around. None of these removes a feature — hidden controls move into a menu automatically.
  layout.mode: enum(split|conversation) - "conversation" shows a single chat instead of list and chat side by side. The list stays reachable through a button in the header — an embedded chat never loses access to the visitor's other conversations
  layout.rail: enum(visible|hidden) - Icon rail. With "hidden", theme switching, sign-out and profile move into the sidebar menu
  layout.railPosition: enum(left|right) - Side the icon rail sits on
  layout.sidebarPosition: enum(left|right) - Side the chat list sits on
  layout.messageAlign: enum(sides|left) - "left" puts your own messages on the left too (forum look)
  layout.bubbleTails: enum(on|off) - Tail on the first bubble of a group
  layout.avatarsInList: enum(on|off) - Avatars in the chat list
  layout.density: enum(comfortable|compact|spacious) - Sets row height, gaps and padding as a block. Individual "space" values win

## badge - Linking notice
The notice on the linking screen that names the real domain. Styleable, but NOT removable — without it any site could present inTouch as its own and collect real account links behind a familiar facade.
  badge.position: enum(card|top) - Placement inside the linking card: below the text (default) or above it. The notice always stays inside the card — it is protected against being moved out of view.
  badge.tone: enum(auto|light|dark) - Lightness of the notice
  badge.color: color default=var(--faint-fg) - Text colour of the notice
  badge.background: color default=transparent - Surface behind the notice

## strings - Text
Overrides individual labels. Keys are the interface i18n names, e.g. "sidebar.title" or "composer.placeholder". Unknown keys are ignored.
  free-form object; values are strings

## icons - Icons
Replaces individual icons with your own SVG. Only path, circle, rect, line, polyline, polygon, g and defs are allowed — script, foreignObject, image and external references are stripped.
  free-form object; values are SVG markup

## colorScheme - Light or dark
Which colour layer applies. "auto" follows the visitor, "host" follows the embedding page (web component only). IMPORTANT: if you set only SOME colours, pin "light" or "dark" here — otherwise your colours mix with inTouch's other layer.
  value: auto | light | dark | host (default auto)

## light - Light mode only
The same groups as above, but only while light is shown. Top-level values apply to both layers and are overridden here.
  same groups as above, applied only in that colour mode

## dark - Dark mode only
The counterpart to "light". Lets you ship a design that works in both layers instead of switching one off.
  same groups as above, applied only in that colour mode

## customCss - Custom CSS
The last resort for anything no field covers. At most 64 KB, no @import (it would allow arbitrary third-party requests). Rules targeting the linking notice are stripped. Unversioned: a later change to class names can break your CSS.
  a string of CSS

# pages
/                  overview, capability list
/quickstart        get a key, first request
/authentication    key format, rotation, failure modes
/conventions       envelope, status codes, limits, dates
/recipes           recipes capability
/vocabulary        vocabulary capability
/roadmap           capability anatomy, what is planned
every page is also plain text: append .txt  (e.g. https://docs.in-touch.cc/vocabulary.txt)
all pages at once: /llms.txt (index) and /llms-full.txt (everything)

# for agents
- Use only the endpoints listed here; do not invent paths, fields or values.
- Check "success" in the body, not just the HTTP status.
- Error strings are German and developer-facing; branch on the status code.
- Batches are accepted partially: read "rejected" and "errors[].index".
- Dates are UTC. Calendar days are YYYY-MM-DD, timestamps are ISO 8601.
- The API key is a credential: never log it, never pass it to a third party.
- Ask the user before writing content into their app for the first time.