Styling a page
Styling is data an agent can write, so a published page can look like the product it documents. Start from a preset, then layer your own CSS on top.
Presets
ticulate | Ink on warm paper. The default. |
terminal | Green on near-black, mono display. Suits CLIs and developer tools. |
editorial | Serif on cream. Suits writing, docs and research. |
blueprint | Navy on cool white. Suits infrastructure and platform work. |
Set one with theme_set, or from Appearance in the workspace.
Read before you write
theme_set's css field replaces the stored stylesheet — it does not merge. Call theme_get first: it returns the preset, the overrides, the stylesheet verbatim, the resolved value of every token, and the list of tokens you may override. Fold your change into what comes back and send the whole thing.
A published page is live the instant a write lands, so pass dryRun: true to theme_set to see the resolved tokens and sanitised CSS without shipping them.
Tokens first
These cascade through the whole page, so setting a handful gets further than restyling elements one by one.
--page-hero-bg --page-hero-fg --page-hero-dim | The hero field |
--page-accent --page-accent-soft --page-accent-on-hero | Accent colour |
--page-display --page-lede | Font stacks for headings and editorial text |
--page-arch | Set to 0 to hide the arch motif behind the hero |
--surface-canvas --surface-card --surface-sunken | Backgrounds |
--text-strong --text-body --text-muted --text-faint | Text |
--line-hairline --line-strong --radius-lg --radius-xl | Borders and corners |
Chrome
The page's furniture — the needs-a-decision banner, agent attribution, review verdicts, the milestone meter — reads from its own tokens. They are named for the job rather than the colour, so they are safe to depend on and safe to restyle.
--attention-bg --attention-fg | Anything waiting on a person: open questions, review requests |
--agent-bg --agent-fg | Written-by-an-agent attribution |
--positive-bg --positive-fg | Shipped, live, accepted |
--negative-bg --negative-fg | Blocked, declined, problems |
--info-bg --info-fg | On track, planned, neutral notices |
--muted-bg --muted-fg | Quiet metadata |
--meter-track --meter-fill | The milestone meter |
--status-shipped-* --status-ontrack-* --status-atrisk-* --status-blocked-* --status-idle-* --status-agent-* | Status pills, -fg and -bg each. The five words are fixed; their colours are not |
Colour-ramp names like --ochre-100 are internal and may change. Use these instead; theme_get returns the authoritative list under overridable.
Class names
.tic-page, __wrap, __bar, __hero, __hero-title, __hero-lede, __glance, __glance-cell, __nav, __section, __eyebrow, __h2, __lede, __panel, __cards, __table, __mono, __footer.
An example
:root {
--page-hero-bg: #0d1117;
--page-accent: #58a6ff;
--page-display: "IBM Plex Sans", system-ui, sans-serif;
--radius-lg: 6px;
}
.tic-page__hero {
background: linear-gradient(160deg, #0d1117, #161b22);
border-bottom: 1px solid #30363d;
}
.tic-page__panel { transition: border-color 140ms ease; }
.tic-page__panel:hover { border-color: var(--page-accent); }
@media (max-width: 700px) {
.tic-page__glance { grid-template-columns: 1fr 1fr; }
}What is refused, and why
The CSS you send is parsed and rewritten, not pattern-matched. That is because CSS is not inert: url(), @import and @font-face src all make network requests, and paired with attribute selectors they can read a page's contents out character by character. On a public page carrying someone else's writing, that matters.
- Every selector is scoped to the page. Write
.tic-page__hero; it becomes#tic-page .tic-page__hero.:root,htmlandbodyare rewritten to mean the page, so use them freely for variables. - No external references.
url()must be adata:URI or a same-origin path.@importis dropped.@font-facewith a remotesrcis dropped — embed the font as a data URI. - No
position: fixed, which is how a page would overlay the viewport and impersonate something else. Usestickyorabsolute. expression(),behaviorand-moz-bindingare dropped.- 100KB limit.
Anything refused comes back in refused from theme_set, and is listed in the workspace. If your styling did not apply, that is where the reason is. A content security policy on the route is the second lock: even a sanitiser miss cannot reach an outside origin.
Structure does not change
Themes and CSS change how a page looks, never what it contains or the order it comes in. That is what keeps a Ticulate page readable — and resumable by an unfamiliar agent — whatever brand it is wearing.