The natural home or environment of an organism — the specific conditions of light, temperature, and surroundings it has adapted to live in.
Every other interface assumes a fixed environment: a bright office, a calibrated monitor, a room that doesn't exist. habitat.css senses the light and color actually around you and lets the page adapt to that habitat instead — paper-toned in low light, camouflaged into the room's own palette, always contrast-safe. Try it above: Off, Eink, Camo — Camo will ask to use your camera, entirely on-device, and you can stop or forget it anytime.
npm install habitat.csspnpm add habitat.cssyarn add habitat.cssbun add habitat.cssimport { HabitatSensor } from "npm:habitat.css";
import "npm:habitat.css/habitat.css" with { type: "css" };<link rel="stylesheet" href="https://unpkg.com/habitat.css/dist/habitat.css">
<script src="https://unpkg.com/habitat.css/dist/habitat.global.js"></script>
<script>const sensor = new Habitat.HabitatSensor();</script>import { HabitatSensor } from "https://esm.sh/habitat.css";<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/habitat.css/dist/habitat.css">
<script src="https://cdn.jsdelivr.net/npm/habitat.css/dist/habitat.global.js"></script>Both modes are driven by the same sensor, and both are built to be contrast-safe by construction, not by accident.
A sepia–saturate–brightness–contrast filter over a warm paper palette that tracks measured room brightness — pale paper in daylight, a darker warm tone as the room dims. No animation, no glow, like an e-reader with a gentle frontlight.
Every fifteen seconds, one tiny camera frame is blurred at capture, quantized into eight dominant colors, and recast as a semantic palette — background, text, accent — that the page wears. The room's most present color becomes the background; its most saturated voice becomes the accent.
Every derived palette is walked until it clears your chosen WCAG target — AA (4.5:1), AAA (7:1), or High (10:1) — before it's ever applied. Camouflage never comes at the cost of reading your own page.
One 64×48 frame exists at a time, blurred as it's drawn, analyzed, then erased. Only a brightness number and a few hex colors ever persist — on-device, nowhere else.
habitat-shadcn.css maps habitat's semantic tokens onto
shadcn/ui's full
theming variable
contract — --background, --primary,
--card, --sidebar, --chart-1
… --radius, and the rest. Load it after
habitat.css and every shadcn/ui component re-themes
automatically under eink and camo modes, no component code changes
— the same lightweight model shadcn's own
Typeset ships with.
<link rel="stylesheet" href="habitat.css">
<link rel="stylesheet" href="habitat-shadcn.css">
This isn't a screenshot — it's live. Toggle Off / Eink / Camo in the
header above and watch these ordinary shadcn-style components
re-theme, styled with nothing but the standard
--primary / --card / --border
token set from habitat-shadcn.css.
Reading ambient brightness and room color every 15 seconds.