Branding

Branding

All Onelo hosted surfaces — Auth, Checkout card, Store, Customer portal, Feedback, Waitlist, and Roadmap — are styled from your Branding settings via CSS custom properties. This page covers both halves: the visual controls in the dashboard, and Custom CSS for anything they don't expose — injected into every surface automatically. No framework, no build step.

Most branding is done with the visual controls in Dashboard → App → Branding — colors, fonts, radius, logo, shadows, and the "Powered by Onelo" toggle. Reach for Custom CSS only when you need something the controls don't expose — the Custom CSS field itself requires a paid plan (on Free it renders locked).

The visual controls

Open Dashboard → App → Branding. Along the top are tabs for each surface — Auth, Checkout card, Store, Customer portal, Feedback, Waitlist and Roadmap — with a live preview beside the controls. Switch the preview between Desktop and Mobile at any time.

One theme, seven previews. Colors, fonts, radius, buttons, inputs and shadows are shared — change them on any tab and every surface follows, which is what keeps your product looking like one product. Only a handful of settings are genuinely per-surface: the logo's show/alignment, the Store's featured border, the Waitlist card width and border, and the card-border toggle. Those appear only on the tabs they apply to.

Logo

ControlDefaultCSS variableWhat it does
Logo(none)Upload your logo image. Used by every surface that shows one.
Logo frameoffDraws a border/background ring around the logo. Off = clean transparent logo.
Logo frame fill(empty)--onelo-logo-bgFill colour of that ring. Empty = border only. Only used when Logo frame is on.
Logo frame thickness4px--onelo-logo-frame-widthHow thick the ring/padding around the logo is (1–16px).

Below those, each surface gets its own show/hide and alignment — so you can centre the logo on the hosted Auth page but tuck it to the left in the compact checkout card, or hide it entirely on one surface without touching the others.

ControlDefaultCSS variableWhat it does
Authshown · centerHosted sign-in / sign-up page.
Checkout cardshown · leftThe card sits in a compact header row, hence left by default.
Storeshown · leftManaged here, not in the Store panel — one source of truth.
Customer portalshown · centerSubscription management page.
Feedbackshown · centerHosted bug-report / feature-request form.
Waitlistshown · centerHosted waitlist form and its iframe embed.
Roadmapshown · leftPublic roadmap page.

Colors

ControlDefaultCSS variableWhat it does
Brand color#f97316--onelo-brandPrice, highlights, and the default button background.
Page background#111111--onelo-page-bgThe area behind the card on hosted pages.
Card background#1a1a1a--onelo-card-bgThe card / panel surface itself.
Text color#ffffff--onelo-textMain text colour, inherited by inputs unless you override them.
Border color#2a2a2a--onelo-borderDefault colour for card, input and button borders.

Buttons

ControlDefaultCSS variableWhat it does
Button background(empty)--onelo-button-bgLeave empty to follow Brand color.
Button text#ffffff--onelo-button-textLabel colour.
Button border width0px0–4px. At 0 the border is removed entirely.
Button border color(empty)--onelo-button-borderEmpty = Border color. The field only appears once width is above 0.
Button radius14px--onelo-button-radius0–24px. Starts from Card radius, then overrides it.

Inputs

ControlDefaultCSS variableWhat it does
Input background(empty)--onelo-input-bgEmpty = an automatic subtle overlay that works on light and dark cards.
Input text(empty)--onelo-input-textEmpty = inherits Text color.
Input border color(empty)--onelo-input-border-colorEmpty = Border color. Set it to make fields differ from the card frame.
Input border width1px--onelo-field-border-width0–4px.
Field radius14px--onelo-field-radius0–24px. Starts from Card radius, then overrides it.
On the checkout card these same values are forwarded into Stripe's hosted card fields, so your inputs and the card-number field match — see Checkout card & Stripe below.

Card

ControlDefaultCSS variableWhat it does
Show card borderonCheckout card and Customer portal only. Waitlist and Store have their own toggles.
Card border width1px--onelo-card-border-width0–4px.
Card radius14px--onelo-radiusRounds cards and panels. Button and Field radius start from this value.
Featured border width2px--onelo-featured-border-widthStore only — the ring around a featured product (0–8px).
Featured border color(empty)--onelo-featured-border-colorStore only. Empty = Brand color.

Typography

ControlDefaultCSS variableWhat it does
Heading fontInter--onelo-heading-font15 web fonts, plus system-ui (uses the device font, loads nothing).
Heading size26px--onelo-heading-size18 → 48px.
Body fontInter--onelo-body-fontSame list as headings — pick the same one for a quieter look.
Body size14px--onelo-body-size12 → 18px.

Shadow

Shadows are off by default. The master Shadow toggle turns the whole system on; from there each element carries its own geometry, which you set by dragging a light source around a 2D pad rather than typing offsets.

ControlDefaultCSS variableWhat it does
ShadowoffMaster switch. Off = no shadow anywhere, whatever the per-element values say.
Shadow color#000000--onelo-shadow-colorShared by every element.
Card shadowon · 0/12px · blur 48 · 15%Per-element: enable, offset X/Y, blur, opacity.
Buttons shadowon · 0/4px · blur 16 · 20%Tighter and stronger than the card — buttons sit closer to the surface.
Inputs shadowon · 0/2px · blur 8 · 10%Subtlest of the three.

Waitlist-only

ControlDefaultCSS variableWhat it does
Card max width360px--onelo-card-max-width240 → 600px. Widen it when your form collects more than an email.
Show card borderonThe Waitlist card has its own border toggle, separate from the Card one.

Footer & Custom CSS

ControlDefaultCSS variableWhat it does
Show "Powered by Onelo"onTurning it off requires a paid plan. On Free the footer always renders.
Custom CSS(empty)The Advanced field the rest of this page is about. Requires a paid plan — on Free it renders locked.

Custom CSS — how it works

Onelo renders each surface on its own URL and sets a base set of --onelo-* CSS variables from your Branding settings. Your Custom CSS is appended on top.

Custom CSS is automatically scoped to the surface it runs on — every rule you write is prefixed with that surface's root so it can never leak into the Onelo dashboard or another surface. You can also scope a rule yourself to a single surface using its root ID (e.g. #onelo-auth).

The dashboard live preview reflects your edits instantly. The desktop preview does not accept pointer input, so hover and focus states (:hover, :focus) don't show there — check them in the mobile preview or on the hosted URL.

CSS Variables

Onelo sets these on each surface from your Branding settings. The canonical way to change color, font, and radius is the visual controls in Branding. In Custom CSS you can read these variables (e.g. box-shadow: var(--onelo-card-shadow)) and re-declare them scoped to a surface root for fine tuning. Some values (--onelo-button-bg, --onelo-input-bg) are pre-resolved on the root, so to change a concrete element reliably, override the property directly with !important (see Cookbook).

Colors

VariableDefaultDescription
--onelo-brand#f97316Brand accent — price, highlights, default button background
--onelo-page-bg#111111Page background, behind the card
--onelo-card-bg#1a1a1aCard / panel background
--onelo-text#ffffffBody text color
--onelo-border#2a2a2aBorders, inputs, dividers
--onelo-shadow-color#000000Shared color for card / button / input shadows

Buttons & inputs

VariableDefaultDescription
--onelo-button-bg(brand)Button background — falls back to --onelo-brand when unset
--onelo-button-text#ffffffText color on buttons
--onelo-button-bordernoneButton border — none unless a border width is set
--onelo-input-bgrgba(255,255,255,0.06)Input fill — auto subtle overlay when unset
--onelo-input-text(inherits --onelo-text)Input text color
--onelo-input-border-color(inherits --onelo-border)Input border — set “Input border color” in Branding to decouple inputs from the card frame

Radius & borders

VariableDefaultDescription
--onelo-radius14pxRadius for cards / panels — when you haven’t set it explicitly it follows the larger of your button and field radius
--onelo-button-radius14pxButton corner radius (overrides master)
--onelo-field-radius14pxInput corner radius (overrides master)
--onelo-field-border-width1pxInput border width
--onelo-card-border-width1pxCard / panel border width
The Store's featured-product border has its own store-only variables — --onelo-featured-border-width and --onelo-featured-border-color — set from the visual controls in Branding → Card.

Typography

Font family and size are chosen from the Heading / Body pickers in Branding (16 built-in fonts). These variables carry the chosen values.

VariableDefaultDescription
--onelo-heading-fontInterHeading font family
--onelo-heading-size26pxHeading size
--onelo-body-fontInterBody font family
--onelo-body-size14pxBase body font size

Shadows & logo

Shadows are off by default — enable them with the master Shadow toggle in Branding. The composite variables resolve to none while disabled.

VariableDefaultDescription
--onelo-card-shadow(computed)Card box-shadow — none unless shadows are enabled
--onelo-button-shadow(computed)Button box-shadow
--onelo-input-shadow(computed)Input box-shadow
--onelo-logo-bg(unset)Logo frame fill (when Logo frame is on)
--onelo-logo-frame-width4pxLogo frame thickness
--onelo-card-max-width360pxWaitlist card max width (Waitlist only)

Selectors

These surfaces expose a root ID — scope a rule to one surface by prefixing it with the ID (e.g. #onelo-store .onelo-button).

SelectorSurfaceWhat it targets
#onelo-authAuthSign-in / sign-up form root
#onelo-storeStorePricing / products page root
#onelo-portalCustomer portalSubscription / billing portal root
#onelo-waitlistWaitlistWaitlist widget root
#onelo-roadmapRoadmapPublic roadmap root

Element hooks you can target (with !important for concrete properties):

SelectorSurfaceWhat it targets
.checkout-cardCheckout cardThe card container (the card has no #onelo-* root id — scope card-only rules to this)
.onelo-buttonAuth / Store / Waitlist / Checkout cardCTA / submit / purchase buttons
.onelo-inputAuth / Waitlist / Checkout cardText input fields — also bridged into the card’s Stripe fields (see “Checkout card & Stripe”)
[data-onelo-feedback-input]FeedbackFeedback message / details inputs
[data-onelo-feedback-submit]FeedbackFeedback submit button
[data-onelo-feedback-chip]FeedbackFeedback type chips
.portal-btnCustomer portalAll portal buttons (base)
.portal-btn-primary / -secondary / -danger / -ghostCustomer portalA specific portal button style
.portal-card / .portal-sectionCustomer portalPortal cards & sections
[data-onelo-product-card]StoreEach store product card
[data-onelo-card-divider]Checkout cardThe left/right column separator (set border-color to recolor it)
Checkout card and Feedback have no root ID — a rule without a surface-specific selector applies to every surface. To isolate them, target their element hooks above.
The "Powered by Onelo" mark (#onelo-footer / [data-onelo-powered-by]) cannot be styled or hidden via Custom CSS — those rules are stripped. Hide it with the plan-gated toggle in Branding → Powered by Onelo instead.
You cannot target a surface's outermost wrapper directly — Onelo prefixes every rule with the surface root, so a selector must match a descendant (a root ID like #onelo-store, the .checkout-card container, or an element hook).

Per-surface & per-element targeting

Because every rule is auto-scoped to the surface it runs on, and each surface exposes a root ID plus element hooks, you can style one element type on one surface and nothing else — and give each surface its own independent settings. Combine a root ID with an element hook: #surface .element.

Shadow on Auth buttons only — inputs untouched

#onelo-auth .onelo-button {
  box-shadow: 0 6px 24px rgba(255, 0, 255, 0.5) !important;
}

Different settings per surface

Each #surface .element block is independent — style Auth and Portal buttons completely differently.

/* Auth buttons — magenta glow */
#onelo-auth .onelo-button {
  box-shadow: 0 6px 24px rgba(255, 0, 255, 0.5) !important;
}

/* Portal primary button — different glow + sharper corners */
#onelo-portal .portal-btn-primary {
  box-shadow: 0 2px 8px rgba(0, 255, 0, 0.4) !important;
  border-radius: 4px !important;
}

/* Store CTA buttons — yet another look */
#onelo-store .onelo-button {
  text-transform: uppercase !important;
  letter-spacing: 0.06em !important;
}
Buttons and inputs apply their background / border / shadow as inline styles, so override those concrete properties with !important. Overriding a --onelo-* variable scoped to a root (e.g. #onelo-auth { --onelo-text: #eee }) does not need it.
Scoping is automatic and airtight — a rule written under one surface's ID can never leak to another surface. A rule with no surface ID (e.g. a bare .onelo-button) applies to that element on every surface that has it.

Checkout card & Stripe

The checkout card is split in two. The left column (logo, product name, price) is rendered by Onelo and is fully stylable. The right column — every payment field (Email, Card number, Sort code…) and the payment-method tabs (Card / Bacs Direct Debit / …) — is rendered by Stripe inside an iframe. Custom CSS cannot reach inside it — a hard browser-security boundary.

How to style the Stripe fields & tabs anyway

Onelo bridges your input CSS into Stripe's appearance. A rule matching .onelo-input (or input / textarea) has its background, color, border, border-radius and box-shadow copied onto the Stripe fields and the unselected payment-method tabs. So this restyles them:

.onelo-input {
  background: #11001a !important;
  border: 2px solid #2a0040 !important;
  color: #ffffff !important;
}
The selected payment-method tab (its border + text) uses your Brand color — change it in Branding → Brand color, not via CSS. Individual tabs and their hover/selected states can't be targeted separately (they live inside Stripe).

The column divider line

The vertical line between the two columns is the left panel's border. Its color comes from Branding → Border color (applied inline). To recolor it from CSS, target the panel by its inline border — this works regardless of layout/build and leaves the lower divider untouched:

.checkout-card [data-onelo-card-divider] {
  border-color: #00ff88 !important;
}
[data-onelo-card-divider] is the supported hook for the card's separator lines — use it instead of matching inline styles, which breaks whenever the card's markup changes.

Cookbook

Recolor buttons across surfaces

Buttons apply their background inline, so override the property with !important. A rule with no surface ID applies everywhere.

.onelo-button {
  background: #7c3aed !important;
  color: #ffffff !important;
}

Different button per surface

Prefix with a root ID to scope to one surface.

#onelo-auth .onelo-button {
  background: #6d28d9 !important;
}

#onelo-store .onelo-button {
  background: linear-gradient(135deg, #7c3aed, #a855f7) !important;
  box-shadow: 0 4px 20px rgba(124, 58, 237, 0.35) !important;
}

Tune colors that read a variable live

Variables like --onelo-text and --onelo-border are read live, so re-declaring them scoped to a root works without !important.

#onelo-waitlist {
  --onelo-text: #e8e8e8;
  --onelo-border: rgba(14, 165, 233, 0.3);
}

Button hover animation

Hover states are not visible in the dashboard preview — test in the hosted URL.
#onelo-auth .onelo-button,
#onelo-waitlist .onelo-button {
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

#onelo-auth .onelo-button:hover,
#onelo-waitlist .onelo-button:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(124, 58, 237, 0.45) !important;
}

Light mode adaptation

Media queries are supported and scoped automatically.

@media (prefers-color-scheme: light) {
  #onelo-auth,
  #onelo-waitlist {
    --onelo-border: rgba(0, 0, 0, 0.12);
    --onelo-text: #111111;
  }
}

Mobile tweaks

@media (max-width: 400px) {
  #onelo-store .onelo-button {
    font-size: 13px;
    padding: 10px;
  }
}

Fonts

Choose your heading and body fonts from the pickers in Branding → Typography — 15 web fonts are built in (Inter, Poppins, Plus Jakarta Sans, Figtree, Manrope, and more) and are loaded for you on every surface, plus system-ui, which uses the device's own font and loads nothing.

You cannot load an external font with @import in Custom CSS — @import is stripped for security. Use the built-in font picker instead.

What you cannot do with CSS

  • Hide or recolor the "Powered by Onelo" markFooter-targeted rules are stripped; hide it via the plan-gated Branding toggle
  • Load external fonts or stylesheets with @import@import is removed during sanitization — use the built-in font picker
  • Change field order (e.g. name before email)HTML structure is controlled by Onelo
  • Add custom fields to the Auth formUse Waitlist for custom data collection
  • Change button labels ("Sign in", "Join Waitlist")Text is managed by Onelo
  • Reach inside the Stripe iframe with CSSPayment fields + method tabs are cross-origin — style them via the .onelo-input bridge instead (see “Checkout card & Stripe”)

Tips

  • Override variables, not concrete properties, where you can — variable overrides cascade naturally and never need !important.
  • Use !important only when overriding a concrete property (background, box-shadow, border) that a widget applies as an inline style — e.g. on .onelo-button.
  • Avoid structural selectors like > div > div — widget HTML may change between releases. Stick to .onelo-button, .onelo-input, the data-onelo-* hooks, or the root IDs.
  • The dashboard preview is a snapshot — :hover and :focus states are not visible there. Test them on the hosted URL.
  • All surfaces share one Custom CSS field — use the root IDs (#onelo-auth, #onelo-store…) to scope rules to specific surfaces.
Branding — Onelo Docs