Styling & CSS Variables — How to theme the waiting room with CSS custom properties.
See also: Template Markup & Structure | Vue State & Methods
Styling#
CSS Architecture#
Styles are split into two layers:
- Theme (
_ch-theme-auto.scss) — Colors, fonts, shadows, effects. Auto-derives a full palette from 6 input variables. This is what you customise.
- Base (
_ch-base.scss) — Layout, sizing, positioning, animations. Rarely needs customisation.
Theme Input Variables#
Override these in a stylesheet loaded after the main bundle. The theme derives all other colours automatically.
:root {
--ch-brand-primary: #424242; /* Title, accent, stock pill */
--ch-brand-secondary: #4b4b4b; /* Buttons, focus rings */
--ch-bg: #FFFFFF; /* Page background */
--ch-text: #1C1917; /* Main text colour */
--ch-surface: #F0F4F8; /* Card / panel backgrounds */
--ch-progress-color: #004f84; /* Progress bar base colour (optional) */
--ch-border-radius: 12px; /* Base radius — all radii scale from this */
}
Add your overrides in a stylesheet after the main styles:
<link rel="stylesheet" href="crowdhandler-styles.css">
<link rel="stylesheet" href="my-overrides.css">
Progressive Enhancement#
The theme uses a two-tier approach:
- Static fallbacks — Pre-computed hex values that work in all browsers.
- Dynamic derivation — In browsers that support
oklch(from ...) (Chrome 119+, Firefox 128+, Safari 16.4+), all derived colours are calculated automatically from your inputs.
Any derived variable can still be individually overridden.
Derived Variables Reference#
All derived variables can be individually overridden. In browsers supporting oklch(from ...) they are calculated automatically from the inputs above; otherwise they use static hex fallbacks.
Typography#
| Variable |
Por defecto |
Description |
--ch-font-primary |
Plus Jakarta Sans |
Body and heading font |
--ch-font-secondary |
JetBrains Mono |
Position number and countdown digits |
Text#
| Variable |
Derived from |
Description |
--ch-text-primary |
--ch-text |
Main body text |
--ch-text-secondary |
--ch-text 80% |
Secondary text |
--ch-text-muted |
--ch-text 70% |
Muted / helper text |
--ch-on-bg |
--ch-bg |
Auto light/dark text on page background |
--ch-on-bg-secondary |
--ch-on-bg 65% |
Secondary text on page background |
--ch-on-surface |
--ch-surface |
Auto light/dark text on card/panel |
--ch-on-surface-secondary |
--ch-on-surface 65% |
Secondary text on card/panel |
--ch-on-surface-muted |
--ch-on-surface 52% |
Muted text on card/panel |
Backgrounds#
| Variable |
Derived from |
Description |
--ch-bg-page |
--ch-bg |
Page background |
--ch-bg-card |
--ch-surface |
Card background |
--ch-bg-inset |
--ch-surface darkened |
Inset panel background |
--ch-bg-input |
--ch-surface |
Input field background |
--ch-bg-surface |
--ch-surface + --ch-bg 50/50 |
Intermediate surface |
Borders#
| Variable |
Derived from |
Description |
--ch-border |
--ch-on-bg 12% |
Default border colour |
--ch-border-focus |
--ch-brand-secondary |
Focus ring colour |
Accent#
| Variable |
Derived from |
Description |
--ch-accent |
--ch-brand-primary |
Accent colour (titles, stock pill) |
--ch-accent-hover |
--ch-accent darkened |
Accent hover state |
--ch-accent-glow |
--ch-brand-primary 25% opacity |
Accent glow effect |
--ch-on-accent |
--ch-accent |
Auto light/dark text on accent |
Status Colours#
| Variable |
Derived from |
Description |
--ch-status-green |
Input |
Green status input (bright) |
--ch-status-amber |
Input |
Amber status input (bright) |
--ch-status-red |
Input |
Red status input (bright) |
--ch-success |
--ch-status-green darkened |
AA-safe green text |
--ch-warning |
--ch-status-amber darkened |
AA-safe amber text |
--ch-danger |
--ch-status-red darkened |
AA-safe red text |
--ch-success-glow |
--ch-status-green 30% opacity |
Green glow |
--ch-warning-glow |
--ch-status-amber 20% opacity |
Amber glow |
--ch-danger-glow |
--ch-status-red 20% opacity |
Red glow |
Buttons#
| Variable |
Derived from |
Description |
--ch-btn-bg |
--ch-brand-secondary |
Primary button background |
--ch-btn-text |
--ch-btn-bg |
Auto light/dark button text |
--ch-btn-hover |
--ch-btn-bg darkened |
Primary button hover |
--ch-btn-disabled-bg |
--ch-btn-bg lightened |
Disabled button background |
--ch-btn-secondary-bg |
transparent |
Secondary button background |
--ch-btn-secondary-text |
--ch-text-secondary |
Secondary button text |
--ch-btn-secondary-border |
--ch-border |
Secondary button border |
--ch-btn-secondary-hover-bg |
--ch-on-bg 4% |
Secondary button hover |
| Variable |
Derived from |
Description |
--ch-progress-bg |
--ch-on-bg 8% |
Track background |
--ch-progress-dark |
--ch-progress-color darkened |
Gradient dark stop |
--ch-progress-light |
--ch-progress-color lightened |
Gradient light stop |
--ch-progress-gradient |
dark + light stops |
Animated fill gradient |
Position Proximity#
| Variable |
Derived from |
Description |
--ch-position-far |
--ch-text-primary |
Position number colour (far) |
--ch-position-mid |
--ch-text-secondary |
Position number colour (mid) |
--ch-position-near |
--ch-brand-primary |
Position number colour (near) |
--ch-position-soon |
--ch-success |
Position number colour (almost there) |
Message Boxes#
| Variable |
Derived from |
Description |
--ch-message-warning-bg |
--ch-warning 8% |
Warning message background |
--ch-message-warning-border |
--ch-warning 20% |
Warning message border |
--ch-message-danger-bg |
--ch-danger 8% |
Danger message background |
--ch-message-danger-border |
--ch-danger 20% |
Danger message border |
Header & Footer
| Variable |
Derived from |
Description |
--ch-header-bg |
--ch-bg |
Header background |
--ch-on-header-bg |
--ch-header-bg |
Auto light/dark header text |
--ch-on-header-bg-secondary |
--ch-on-header-bg 65% |
Secondary header text |
--ch-footer-bg |
--ch-bg |
Footer background |
--ch-on-footer-bg |
--ch-footer-bg |
Auto light/dark footer text |
--ch-on-footer-bg-secondary |
--ch-on-footer-bg 65% |
Secondary footer text |
Card & Countdown#
| Variable |
Derived from |
Description |
--ch-card-radius |
--ch-border-radius * 2 |
Card corner radius |
--ch-card-shadow |
--ch-brand-primary tinted |
Card box shadow |
--ch-countdown-shadow |
--ch-brand-primary tinted |
Countdown unit shadow |
Footer Utilities
| Variable |
Derived from |
Description |
--ch-token-bg |
--ch-on-bg 4% |
Token badge background |
--ch-token-hover-bg |
--ch-on-bg 8% |
Token badge hover |
--ch-poll-bg |
--ch-on-bg 4% |
Poll timer track |
--ch-poll-gradient |
progress dark + colour |
Poll timer fill gradient |
Key CSS Classes Reference#
| Class |
Purpose |
ch-card |
Main card container |
ch-queue-states |
Wrapper for countdown + active queue content |
ch-state-message |
State message container (blocked / room full) |
ch-state-message.ch-state-danger |
Blocked state (red) |
ch-state-message.ch-state-warning |
Room full state (amber) |
ch-message-box |
Message panel above card |
ch-form-section |
Form area with top border separator |
ch-priority-section |
Priority code form (inset background) |
ch-email-section |
Email form (outside card) |
ch-email-submitting |
Spinner container during email submission |
ch-input-group |
Flex row for input + button(s) |
ch-input |
Text/email input field |
ch-btn |
Primary button |
ch-btn-sm |
Small button variant |
ch-btn-secondary |
Secondary button (outlined) |
ch-btn-change |
Change email button spacing |
ch-form-feedback |
Feedback message row |
ch-form-feedback.ch-success |
Success feedback |
ch-form-feedback.ch-error |
Error feedback |
ch-stock-badge |
Stock indicator |
ch-stock-count |
Stock number pill |
ch-stock-badge.ch-stock-low |
Low stock state |
ch-stock-badge.ch-stock-zero |
Sold out state |
ch-progress-container |
Progress bar wrapper (max-width constrained) |
ch-progress-bar |
Track (background bar) |
ch-progress-fill |
Fill bar (animated gradient) |
ch-progress-bar.ch-progress-mid |
Glow at mid progress |
ch-progress-bar.ch-progress-high |
Stronger glow at high progress |
ch-progress-bar.ch-progress-almost |
Pulsing glow near completion |
ch-progress-info |
Estimate and ETA text below bar |
ch-spinner |
Loading spinner |
ch-text-shimmer |
Text shimmer animation |
ch-session-info |
Session info text |
Required CSS Classes#
Your template must include these structural classes:
/* Screen reader only */
.ch-sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Hidden until loaded */
#crowdhandler-template {
display: none;
opacity: 0;
transition: opacity 0.5s ease;
}
#crowdhandler-template.active {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
opacity: 1;
}
Entrance Animations#
Elements use staggered entrance animations via ch-enter y ch-stagger-N classes. Each stagger level adds a 0.1s delay.
<div class="ch-logo ch-enter ch-stagger-1">...</div>
<div class="ch-header-row ch-enter ch-stagger-4">...</div>
<div class="ch-footer ch-enter ch-stagger-5">...</div>
<div class="ch-message-box ch-enter ch-stagger-6">...</div>