Every control, live
What Eink and Camo mean is on the home page — this is the control panel. Switch modes and contrast in the toolbar above and watch everything below, down to this page's own text selection and scrollbars, respond immediately. Camo reads your camera, on-device only; Eink falls back to the system clock for brightness until you grant it.
Accessibility contrast
The Contrast picker in the toolbar sets the ratios
the palette engine must satisfy; changing it re-derives the camo
palette in place and tunes eink's filter and ink. It defaults to
AAA, or to High if your system asks for
prefers-contrast: more.
| Level | Body text | Accents | Character |
|---|---|---|---|
| AA | 4.5:1 | 3:1 | Closest camouflage |
| AAA | 7:1 | 3:1 | Comfortable reading (default) |
| High | 10:1 | 4.5:1 | Maximum legibility |
The best interface light is the light already in the room.
Light or dark, on demand
Scheme in the toolbar can force every mode toward
a light or dark identity, regardless of what the room or the
system's own prefers-color-scheme would otherwise
pick — Eink's paper jumps straight to its bright or dim endpoint,
and Camo's derived palette keeps its background in that half of
the range. It works the same way without any JavaScript at all:
set data-habitat-scheme="dark" on
<html>, or just add a .dark or
.habitat-dark class if your app already toggles one.
Using the system
Import the stylesheet and let the sensor drive the variables:
<link rel="stylesheet" href="habitat.css">
import { HabitatSensor } from "habitat.css";
import { initHabitatBanner } from "habitat.css";
const sensor = new HabitatSensor();
const consent = initHabitatBanner(sensor);
consent.request(); // shows the banner, then starts sensing
Style your components only with
--habitat-bg, --habitat-surface,
--habitat-text, --habitat-text-muted,
--habitat-accent and --habitat-border,
and every mode — present and future — works for free. Even
text selection and scrollbars wear the habitat
palette.