/* Vendored from repos/WijnCode/wijnui/tokens/wijnui.css @ f5725ba — do not edit here;
   change WijnUI and copy it again. */
/* WijnUI — design tokens.
 *
 * The single source of truth. Everything else in this repo (the JSON mirror, the
 * Tailwind theme, the gallery) is generated from or written against these values.
 *
 * Prefix is --wui-. Apps may alias them to their own names — jules-pwa uses
 * --coder-, meals / homeos / feed use --bg-background / --text-primary /
 * --border-base, monie --color-, the DR cockpit --vh- — but the values live here.
 *
 * 2026-09-27: rebased on the language Max's everyday apps actually ship —
 *   repos/jules-pwa/src/theme/tokens.ts   (hue 35, cream accent)
 *   repos/feed/frontend/src/index.css     (hue 28, amber accent)
 *   repos/meals/public/style.css          (rose)
 *   repos/homeos/style.css                (navy)
 * Four apps, one structure: a warm hue-tinted ground, pure-white headings, one
 * accent per product, the same three pastel signals, outlined pills everywhere
 * and a filled pill only for the primary action. The older green-on-charcoal
 * ground that monie and the DR cockpit were extracted from is kept below as
 * their product block, not as the default.
 */

:root {
  color-scheme: dark;

  /* ── Type ──────────────────────────────────────────────────────────────
     ONE typeface, always Plus Jakarta Sans (Max, 2026-09-27). It carries labels,
     body, and figures alike, in every product.

     This is a hard rule, learned the expensive way: setting values in a mono
     face beside the UI face reads as two interfaces sharing one card, and it
     is worst on short values, where "ok" in mono next to SMB MOUNTS
     looks like a rendering fault rather than a choice.

     Values get their column alignment from TABULAR FIGURES, not from a second
     family — set font-variant-numeric on body so it applies wherever numbers
     appear. Hierarchy between a headline figure and a dense one comes from size
     and weight, which is all it ever needed. */
  --wui-font-ui: "Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif;

  /* ── Ground ────────────────────────────────────────────────────────────
     Warm over cool: every neutral is a near-black tinted by ONE hue, so the
     page reads as leather and stone rather than slate. The hue is a product
     slot (jules 35, feed 28); saturation stays low so every product reads as a
     tinted near-black, never "colourful by accident". No cool greys. */
  --wui-hue: 35;
  --wui-bg: hsl(var(--wui-hue) 11% 12%);
  --wui-surface: hsl(var(--wui-hue) 12% 16%);
  --wui-surface-high: hsl(var(--wui-hue) 12% 19%);
  --wui-surface-highest: hsl(var(--wui-hue) 13% 22%);
  /* Borders whisper: 1px, a warm line from the same hue — not white at low
     alpha, which goes grey on a warm ground. */
  --wui-rule: hsl(var(--wui-hue) 12% 26%);

  /* ── Text ──────────────────────────────────────────────────────────────
     Three steps. Headings and values are pure white; secondary and muted
     text tint warm with the hue. */
  --wui-on-bg: #FFFFFF;
  --wui-on-surface: hsl(var(--wui-hue) 8% 70%);
  /* 60%, not jules-pwa's 52%: at 52 muted text was 4.10:1 on a card and
     3.66:1 on a raised card — every section label and hint failed AA.
     gallery.spec measures every text colour on every surface it sits on. */
  --wui-on-faint: hsl(var(--wui-hue) 13% 60%);

  /* ── Colour roles — the important part ─────────────────────────────────
     These are ROLES, not a palette. Breaking them is what makes an interface
     read as noisy.

       brand        UI state ONLY: active, selected, focused. Never domain data.
       ok/warn/crit domain signal. Money moved, lab health, a session failed.
                    Never used for UI chrome.
       agent        the machine's own surfaces — its reasoning, its log, its
                    suggestions. Exactly ONE violet in a product.

     Keeping brand and signal apart is why an active nav pill never reads as an
     alarm, and why a healthy reading never reads as "selected". */
  --wui-brand: #D4C8B8;
  --wui-brand-dim: #E2D8C9;
  --wui-on-brand: #2A2520;
  --wui-nav-indicator: rgb(212 200 184 / .16);
  /* The primary action is the one solid fill on a screen, and it is a deeper
     tone of the brand rather than the brand itself — a cream slab reads as a
     hole in a dark page. Everything else is an outlined pill. */
  --wui-brand-fill: #5C5346;
  --wui-on-brand-fill: #F0EDE8;
  /* The brand ROLE is fixed — UI state only, never domain data. Its VALUE, and
     the hue of the ground, are per product. They are declared in this file
     rather than overridden in an app, because a hue that exists only in an
     app's config is a fork. Set with data-wui-product on the root element;
     the registry is below. */

  /* The same three signals in all four source apps — muted pastels, so a
     reading never shouts over the content around it. */
  --wui-ok: #81C995;
  --wui-ok-bg: rgba(129, 201, 149, .12);
  --wui-ok-border: rgba(129, 201, 149, .28);
  --wui-warn: #FDD663;
  --wui-warn-bg: rgba(253, 214, 99, .12);
  --wui-warn-border: rgba(253, 214, 99, .28);
  --wui-crit: #F2B8B5;
  --wui-crit-bg: rgba(242, 184, 181, .12);
  --wui-crit-border: rgba(242, 184, 181, .28);

  /* The tertiary violet homeos and meals already carry. */
  --wui-agent: #D7AEFB;
  --wui-agent-tint: rgb(215 174 251 / .12);

  /* ── Radius ────────────────────────────────────────────────────────────
     Scales with the SIZE of the surface, which is the rule people get wrong.
     Same steps as the Tailwind override homeos and meals share (lg 12, xl 16,
     3xl 28).
     large   hero-sized surfaces only: a full-width banner, a dialog, a sheet
     medium  cards and panels — the default, and the most-used token
     small   dense inner elements
     full    buttons, inputs, chips, badges, nav indicators, rails, avatars */
  --wui-radius-large: 28px;
  --wui-radius-medium: 16px;
  --wui-radius-small: 12px;
  --wui-radius-full: 9999px;
  /* The phone bottom-nav highlight. A full pill by default (feed, meals); a product may
     take the card radius instead — the DR cockpit does (Max, 2026-09-28: "should be less
     rounded"). The wide-screen tab indicator is a pill either way. */
  --wui-nav-radius: var(--wui-radius-full);

  /* ── Size ──────────────────────────────────────────────────────────────
     jules-pwa's scale (src/theme/tokens.ts), the default since 2026-09-27
     because Max likes how it reads on a phone. Everything derives from base
     16px; 12px is for timestamps and chip labels, never for reading text. */
  --wui-text-xs: 12px;
  --wui-text-sm: 14px;
  --wui-text-base: 16px;
  --wui-text-lg: 18px;
  --wui-text-xl: 22px;
  --wui-text-xxl: 28px;
  /* Hit areas: anything a finger lands on gets at least --wui-touch; rows
     people navigate by get a roomier 48; a tappable chip 40. */
  --wui-touch: 44px;
  --wui-touch-row: 48px;
  --wui-touch-chip: 40px;

  /* ── Motion ────────────────────────────────────────────────────────────
     Subtle is premium: 200ms for colour and border, a 0.97 press on buttons. */
  --wui-ease: cubic-bezier(.2, 0, 0, 1);
  --wui-dur: .2s;

  /* ── Safe areas ────────────────────────────────────────────────────────
     Installed PWAs run under the status bar and over the home indicator. Held
     as variables so browser tests can simulate a device inset by overriding
     them; env() at the call site cannot be faked. */
  --wui-safe-top: env(safe-area-inset-top, 0px);
  --wui-safe-bottom: env(safe-area-inset-bottom, 0px);
  --wui-safe-left: env(safe-area-inset-left, 0px);
  --wui-safe-right: env(safe-area-inset-right, 0px);
}

/* ── Light theme ─────────────────────────────────────────────────────────────
   Dark is the default; light is a warm companion, not a cold afterthought.
   Every source app ships both. Set data-wui-theme="light" on the root. */
:root[data-wui-theme="light"] {
  color-scheme: light;
  --wui-bg: hsl(var(--wui-hue) 26% 97%);
  --wui-surface: hsl(var(--wui-hue) 26% 93%);
  --wui-surface-high: hsl(var(--wui-hue) 24% 89%);
  --wui-surface-highest: hsl(var(--wui-hue) 22% 85%);
  --wui-rule: hsl(var(--wui-hue) 18% 81%);
  --wui-on-bg: #1D1F20;
  --wui-on-surface: #4A4740;
  --wui-on-faint: #655D53;
  --wui-brand: #5C5346;
  --wui-brand-dim: #4A4238;
  --wui-on-brand: #FFFFFF;
  --wui-nav-indicator: rgb(92 83 70 / .12);
  --wui-brand-fill: #5C5346;
  --wui-on-brand-fill: #FFFFFF;
  /* Signals are read as TEXT (a readout value, a badge), so they clear 4.5:1 on every light
     surface: #2D8A4E and #9A7208 measured 3.23:1 and 3.28:1. Found by the jules-pwa rollout. */
  --wui-ok: #1F6B3B;
  --wui-ok-bg: rgba(31, 107, 59, .10);
  --wui-ok-border: rgba(31, 107, 59, .30);
  --wui-warn: #785904;
  --wui-warn-bg: rgba(212, 160, 23, .14);
  --wui-warn-border: rgba(120, 89, 4, .34);
  --wui-crit: #B3261E;
  --wui-crit-bg: rgba(179, 38, 30, .08);
  --wui-crit-border: rgba(179, 38, 30, .28);
  --wui-agent: #6E4C99;
  --wui-agent-tint: rgb(110 76 153 / .10);
}


/* ── Product registry ──────────────────────────────────────────────────────
   See the note on --wui-brand. Add a product by adding a block, never by
   redefining the token inside the product.

     jules-pwa           hue 35, cream #D4C8B8     the default above
     feed                hue 28, amber
     meals               rose, on its own rose-tinted ground
     homeos              navy, on its own blue ground
     DR cockpit          #4ADE80 on AMOLED black (2026-09-28)
     aigw                hue 38, spend-amber #F5B84B
     monie               #4ADE80 on the older neutral charcoal
     filmis              #0A84FF on the same charcoal
     kosing              blue on AMOLED black
     greenhouse          hue 150, the default cream brand on a green ground
     bass-buddy          violet #B69CFF on AMOLED black, and no separate agent colour
     trippy              sky blue #60A5FA, on its own navy ground (2026-10-01)
     fitness             Garmin orange #FFAB7A on hue 22 (2026-10-03) */

/* aigw — AI Gateway spend and routes. Its brand stays spend-amber so it is never
   mistaken for another app; the ground is tinted from the same hue. The brand is UI
   state only, so its money figures are white. */
:root[data-wui-product="aigw"] {
  --wui-hue: 38;
  --wui-brand: #F5B84B;
  --wui-brand-dim: #F8C970;
  --wui-on-brand: #3D2A00;
  --wui-nav-indicator: rgb(245 184 75 / .16);
  --wui-brand-fill: hsl(38 52% 34%);
  --wui-on-brand-fill: #FFF6E6;
}

/* heritage (Wijnbladh Heritage, heritage.wijnbladh.xyz) — the family archive, 2026-10-03.
   The brand is the olive of the vine leaf in the family's arms; the ground is the house's warm
   near-black tinted toward that olive, replacing the navy it shipped with (Max chose this over
   registering the navy as shipped). Olive sits near the ok green, so in this product ok is
   always paired with a word or an icon, never colour alone, and the brand stays UI state. */
:root[data-wui-product="heritage"] {
  --wui-hue: 75;
  --wui-brand: #A8BF7A;
  --wui-brand-dim: #BDCF96;
  --wui-on-brand: #1E2610;
  --wui-nav-indicator: rgb(168 191 122 / .16);
  --wui-brand-fill: hsl(80 32% 30%);
  --wui-on-brand-fill: #F1F4EA;
}
:root[data-wui-product="heritage"][data-wui-theme="light"] {
  --wui-brand: #4F6A26;
  --wui-brand-dim: #3F5520;
  --wui-on-brand: #FFFFFF;
  --wui-nav-indicator: rgb(79 106 38 / .12);
  --wui-brand-fill: #4F6A26;
  --wui-on-brand-fill: #FFFFFF;
}

/* fitness (garmin-fitness-app, fitness.wijnbladh.xyz) — Garmin + Withings health for one
   person, 2026-10-03. It shipped as a vivid orange (#E65100) on neutral black; the orange is
   kept as its identity and lightened for UI state on the house's warm ground, tinted toward it.
   Sports carry their own chart hues as domain data (running, hiking …), so the brand never
   colours a metric — and orange sits next to warn, so a warning is always paired with a word. */
:root[data-wui-product="fitness"] {
  --wui-hue: 22;
  --wui-brand: #FFAB7A;
  --wui-brand-dim: #FFC09A;
  --wui-on-brand: #3A1602;
  --wui-nav-indicator: rgb(255 171 122 / .16);
  --wui-brand-fill: hsl(21 85% 38%);
  --wui-on-brand-fill: #FFF4EC;
}
:root[data-wui-product="fitness"][data-wui-theme="light"] {
  --wui-brand: #B8460B;
  --wui-brand-dim: #9A3A08;
  --wui-on-brand: #FFFFFF;
  --wui-nav-indicator: rgb(184 70 11 / .12);
  --wui-brand-fill: #B8460B;
  --wui-on-brand-fill: #FFFFFF;
}

:root[data-wui-product="feed"] {
  --wui-hue: 28;
  --wui-bg: hsl(var(--wui-hue) 11% 11%);
  --wui-surface: hsl(var(--wui-hue) 11% 14%);
  --wui-surface-high: hsl(var(--wui-hue) 11% 18%);
  --wui-surface-highest: hsl(var(--wui-hue) 11% 21%);
  --wui-rule: hsl(var(--wui-hue) 11% 24%);
  --wui-brand: hsl(28 48% 74%);
  --wui-brand-dim: hsl(28 48% 80%);
  --wui-nav-indicator: hsl(28 48% 74% / .16);
  --wui-brand-fill: hsl(28 40% 36%);
  --wui-on-brand-fill: #FDFBF8;
}

/* meals and homeos ship hand-picked hex rather than hue formulas; these are
   their values verbatim, so the registry describes what is actually on screen. */
:root[data-wui-product="meals"] {
  --wui-hue: 333;
  --wui-bg: #1A1316;
  --wui-surface: #251A1F;
  --wui-surface-high: #31232A;
  --wui-surface-highest: #3B2B33;
  --wui-rule: #48333D;
  --wui-on-surface: #DCC5CE;
  --wui-on-faint: #B3949F;
  --wui-brand: #F5A3C7;
  --wui-brand-dim: #F8BCD6;
  --wui-on-brand: #4A0E2A;
  --wui-nav-indicator: rgb(245 163 199 / .16);
  --wui-brand-fill: #A3245C;
  --wui-on-brand-fill: #FFF0F6;
}
:root[data-wui-product="meals"][data-wui-theme="light"] {
  --wui-bg: #FDF6F8;
  --wui-surface: #FBECF1;
  --wui-surface-high: #F5DDE6;
  --wui-surface-highest: #F0D2DE;
  --wui-rule: #ECC9D6;
  --wui-on-bg: #1F1418;
  --wui-on-surface: #4D3540;
  --wui-on-faint: #7D5566;
  --wui-brand: #A3245C;
  --wui-brand-dim: #8A1E4E;
  --wui-on-brand: #FFFFFF;
  --wui-nav-indicator: rgb(163 36 92 / .12);
  --wui-brand-fill: #A3245C;
  --wui-on-brand-fill: #FFFFFF;
}

:root[data-wui-product="homeos"] {
  --wui-hue: 220;
  --wui-bg: #111827;
  --wui-surface: #1E2433;
  --wui-surface-high: #283040;
  --wui-surface-highest: #313A4C;
  --wui-rule: #334155;
  --wui-on-surface: #B0BDD0;
  --wui-on-faint: #8FA0B6;
  --wui-brand: #A8C7FA;
  --wui-brand-dim: #C2D7FB;
  --wui-on-brand: #0A2A5C;
  --wui-nav-indicator: rgb(168 199 250 / .16);
  --wui-brand-fill: #2E5FAD;
  --wui-on-brand-fill: #E8F0FE;
}
:root[data-wui-product="homeos"][data-wui-theme="light"] {
  --wui-bg: #F5F8FD;
  --wui-surface: #EAF0F8;
  --wui-surface-high: #DCE5F2;
  --wui-surface-highest: #D0DBEC;
  --wui-rule: #C8D5E6;
  --wui-on-bg: #111827;
  --wui-on-surface: #374151;
  --wui-on-faint: #586780;
  --wui-brand: #1E4A8E;
  --wui-brand-dim: #173B72;
  --wui-on-brand: #FFFFFF;
  --wui-nav-indicator: rgb(30 74 142 / .12);
  --wui-brand-fill: #1E4A8E;
  --wui-on-brand-fill: #FFFFFF;
}

/* trippy — the travel planner, registered as shipped (2026-10-01): sky blue on a navy
   ground that predates this registry, kept as its identity the way homeos keeps navy.
   Dark only; it ships no light theme. Its blue sits close to kosing's #5B9BFF, but
   the two never share a screen and the navy ground keeps them apart. */
:root[data-wui-product="trippy"] {
  --wui-hue: 235;
  --wui-bg: #12131F;
  --wui-surface: #1A1B2E;
  --wui-surface-high: #1F2035;
  --wui-surface-highest: #24253A;
  --wui-rule: #3A3C52;
  --wui-on-surface: #C8CDD8;
  --wui-on-faint: #8B90A0;
  --wui-brand: #60A5FA;
  --wui-brand-dim: #93C5FD;
  --wui-on-brand: #0C1B2E;
  --wui-nav-indicator: rgb(96 165 250 / .16);
  --wui-brand-fill: #3B82F6;
  --wui-on-brand-fill: #EFF6FF;
}

/* greenhouse — the balcony PWA, homeos's sibling: it shares that app's stylesheet and
   card module and re-skins them, so it needs a slot of its own rather than homeos's navy.
   It ships the ground ONLY. The brand stays the default cream, deliberately: the plants
   are the domain here, and a healthy pot is drawn in --wui-ok green. A green brand would
   put UI state and domain signal in one colour — a selected tab reading as a healthy
   reading — which is the rule this file says was learned the expensive way. Green is the
   GROUND, cream is the state, and the two never collide.

   Hand-picked hex rather than the hue formula, as meals and homeos are: a hue-150 ground
   at the default 11-13% saturation reads as neutral charcoal, and the whole point of the
   slot is that this app looks like a greenhouse. Saturation sits at meals' level instead.
   Measured on this ground, dark: white headings 12.4-17.9, --wui-on-surface 6.1-8.8,
   --wui-on-faint 4.9 on bg and surface (3.8 on surface-highest, which carries chips
   rather than body text), cream brand 7.6-10.8, and the signals 6.3-12.7. */
:root[data-wui-product="greenhouse"] {
  --wui-hue: 150;
  --wui-bg: #121916;
  --wui-surface: #1A231F;
  --wui-surface-high: #222D28;
  --wui-surface-highest: #2A3730;
  --wui-rule: #35453D;
  --wui-on-surface: #ACB9B3;
  --wui-on-faint: #759585;
}
:root[data-wui-product="greenhouse"][data-wui-theme="light"] {
  --wui-bg: #F5F9F7;
  --wui-surface: #E9F2ED;
  --wui-surface-high: #DCEAE3;
  --wui-surface-highest: #D0E1D9;
  --wui-rule: #C6D7CF;
  --wui-on-surface: #40483F;
  --wui-on-faint: #5C6B5F;
}

/* DR cockpit (homelab-dr, monitor.wijnbladh.xyz) — AMOLED black with green, Max 2026-09-28.
   It has NO appearance picker or theme choice (Max: "def don't need accent picker here", "or
   theme stuff"), so this block is its one and only look.
   The kosing construction: a #000 ground (unlit OLED pixels) with near-black cards separated by
   TONE, not borders. Brand is a vivid #4ADE80 for UI state only; the ok signal stays the softer
   #81C995. On a status board those two greens sit side by side, so an ok reading is ALWAYS paired
   with a word or an icon, never colour alone. */
:root[data-wui-product="cockpit"] {
  --wui-bg: #000000;
  --wui-surface: #121214;
  --wui-surface-high: #1C1C1F;
  --wui-surface-highest: #27272B;
  --wui-rule: rgba(255, 255, 255, .08);
  --wui-on-bg: #F2F2F4;
  --wui-on-surface: #A6A6AE;
  --wui-on-faint: #7A7A83;
  --wui-brand: #4ADE80;
  --wui-brand-dim: #6EE7A0;
  --wui-on-brand: #000000;
  --wui-nav-indicator: rgb(74 222 128 / .16);
  --wui-brand-fill: #4ADE80;
  --wui-on-brand-fill: #000000;
  --wui-shadow: none;
  /* Phone bottom-nav highlight uses the card radius, not a pill (Max, 2026-09-28). */
  --wui-nav-radius: var(--wui-radius-medium);
}

/* The ground monie was extracted from, and filmis was registered against. Kept
   so their registry entries stay true. The DR cockpit has its own block
   above (AMOLED black with green, 2026-09-28). */
:root[data-wui-product="monie"],
:root[data-wui-product="filmis"] {
  --wui-bg: #121417;
  --wui-surface: #1A1D21;
  --wui-surface-high: #22262B;
  --wui-surface-highest: #2B3036;
  --wui-rule: rgba(255, 255, 255, .07);
  --wui-on-bg: #E7EAED;
  --wui-on-surface: #B6BCC3;
  --wui-on-faint: #5A626B;
  --wui-brand: #4ADE80;
  --wui-brand-dim: #34D399;
  --wui-on-brand: #121417;
  --wui-nav-indicator: rgb(74 222 128 / .16);
  --wui-brand-fill: var(--wui-brand);
  --wui-on-brand-fill: var(--wui-bg);
  --wui-ok: #34D399;
  --wui-ok-bg: rgba(52, 211, 153, .12);
  --wui-ok-border: rgba(52, 211, 153, .28);
  --wui-warn: #FBBF24;
  --wui-warn-bg: rgba(251, 191, 36, .12);
  --wui-warn-border: rgba(251, 191, 36, .28);
  --wui-crit: #FB7185;
  --wui-crit-bg: rgba(251, 113, 133, .12);
  --wui-crit-border: rgba(251, 113, 133, .28);
  --wui-agent: #C4B5FD;
  --wui-agent-tint: rgb(196 181 253 / .12);
}
:root[data-wui-product="filmis"] {
  /* The hue of its #121417 ground, so filmis's own Light and Black tint from it
     (recorded by the filmis appearance rollout, 2026-09-28). */
  --wui-hue: 216;
  --wui-brand: #0A84FF;
  --wui-brand-dim: #0066CC;
  --wui-on-brand: #FFFFFF;
  --wui-nav-indicator: rgb(10 132 255 / .16);
}

/* kosing — personal finance, read on a phone by one person. The first CONSUMER product in the family:
   Max asked (2026-09-26) that it not read as a telemetry cockpit. So beyond the brand slot it declares
   a softer ground (navy slate, not charcoal), a geometric-humanist typeface (Plus Jakarta Sans, still ONE typeface with
   tabular figures), and calmer signals (mint for money in, amber kept for real alerts). Roles are
   unchanged: brand = UI state, ok/warn/crit = domain signal, agent = the machine's suggestions. */
:root[data-wui-product="kosing"] {
  /* 2026-09-27: AMOLED black with a blue accent (Max). Pure #000 ground, near-black cards separated by tone,
     no borders; one blue for UI state (#5B9BFF — softer than filmis' #0A84FF, so each product keeps its own);
     muted signals kept apart from the brand — green in, orange-red for a rise. */
  --wui-bg: #000000;
  --wui-surface: #121214;
  --wui-surface-high: #1C1C1F;
  --wui-surface-highest: #27272B;
  --wui-rule: rgba(255, 255, 255, .08);
  --wui-on-bg: #F2F2F4;
  --wui-on-surface: #A6A6AE;
  --wui-on-faint: #6E6E76;
  --wui-brand: #5B9BFF;
  --wui-brand-dim: #3F80EA;
  --wui-nav-indicator: rgb(91 155 255 / .14);
  --wui-ok: #6FD39A;
  --wui-ok-bg: rgba(111, 211, 154, .12);
  --wui-ok-border: rgba(111, 211, 154, .26);
  --wui-warn: #F2915F;
  --wui-warn-bg: rgba(242, 145, 95, .13);
  --wui-warn-border: rgba(242, 145, 95, .28);
  --wui-crit: #F28B82;
  --wui-crit-bg: rgba(242, 139, 130, .12);
  --wui-crit-border: rgba(242, 139, 130, .26);
  --wui-shadow: none;
  /* Its primary stays a solid pill of its own blue; without these it inherits the default
     brown fill, which on a blue product reads as a different app. */
  --wui-on-brand: #000000;
  --wui-brand-fill: #5B9BFF;
  --wui-on-brand-fill: #000000;
}

/* bass-buddy — music library and DJ set builder. Registered as shipped, like monie and
   filmis: its violet predates the agent role, and Max chose (2026-09-27) to keep it as
   the brand. That puts the product's one violet on UI state, so there is NO separate
   agent colour — the co-pilot's surfaces take the brand, and --wui-agent is pinned to
   it rather than left as a second, near-identical violet (which would break "exactly
   one violet" worse than sharing does). The ground is its own (AMOLED black, below); the
   typeface and the three signals are the default. The fill is a deep tone of the violet, as the default's
   is of the cream, because a pale violet slab reads as a hole in a dark page. */
:root[data-wui-product="bass-buddy"] {
  /* 2026-09-27: AMOLED black with the violet accent (Max) — kosing's structure in purple.
     Pure #000 ground, near-black surfaces separated by tone, one quiet solid rule. Neutral,
     not hue-tinted: on true black a warm tint reads as brown, not stone. Measured, dark:
     on-surface 7.5-10.2, on-faint 4.6-6.2, violet 6.8-9.2 on every surface. */
  --wui-bg: #000000;
  --wui-surface: #111113;
  --wui-surface-high: #1A1A1E;
  --wui-surface-highest: #242428;
  --wui-rule: #2C2C32;
  --wui-on-bg: #FFFFFF;
  --wui-on-surface: #B4B4BD;
  --wui-on-faint: #8B8B95;
  --wui-brand: #B69CFF;
  --wui-brand-dim: #CBB6FF;
  --wui-on-brand: #1B1130;
  --wui-nav-indicator: rgb(182 156 255 / .16);
  --wui-brand-fill: hsl(256 42% 40%);
  --wui-on-brand-fill: #F3EEFF;
  --wui-agent: var(--wui-brand);
  --wui-agent-tint: rgb(182 156 255 / .12);
}
:root[data-wui-product="bass-buddy"][data-wui-theme="light"] {
  /* The AMOLED ground above comes later than the default light block, so it would win in
     light too — restate the warm light companion's ground and text. */
  --wui-bg: hsl(var(--wui-hue) 26% 97%);
  --wui-surface: hsl(var(--wui-hue) 26% 93%);
  --wui-surface-high: hsl(var(--wui-hue) 24% 89%);
  --wui-surface-highest: hsl(var(--wui-hue) 22% 85%);
  --wui-rule: hsl(var(--wui-hue) 18% 81%);
  --wui-on-bg: #1D1F20;
  --wui-on-surface: #4A4740;
  --wui-on-faint: #655D53;
  --wui-brand: #6A4BC4;
  --wui-brand-dim: #573AA8;
  --wui-on-brand: #FFFFFF;
  --wui-nav-indicator: rgb(106 75 196 / .12);
  --wui-brand-fill: #6A4BC4;
  --wui-on-brand-fill: #FFFFFF;
  --wui-agent-tint: rgb(106 75 196 / .10);
}


/* ── Products whose own look is already AMOLED ────────────────────────────────
   kosing, the DR cockpit and bass-buddy register a #000 ground with their own
   near-black, neutral cards. The generic Black theme below would otherwise
   re-tint those cards with the default warm hue, so choosing "Black" would
   CHANGE a product that is already black. These restate each product's own
   ground under Black; one attribute more specific, so they beat the generic
   rule. A reader-picked accent (data-wui-accent) still re-tints the cards —
   that block comes later at the same specificity. Found by the bass-buddy
   rollout, 2026-09-28. */
:root[data-wui-product="kosing"][data-wui-theme="black"],
:root[data-wui-product="cockpit"][data-wui-theme="black"] {
  --wui-bg: #000000;
  --wui-surface: #121214;
  --wui-surface-high: #1C1C1F;
  --wui-surface-highest: #27272B;
  --wui-rule: rgba(255, 255, 255, .08);
}
:root[data-wui-product="bass-buddy"][data-wui-theme="black"] {
  --wui-bg: #000000;
  --wui-surface: #111113;
  --wui-surface-high: #1A1A1E;
  --wui-surface-highest: #242428;
  --wui-rule: #2C2C32;
}

/* ═══════════════════════════════════════════════════════════════════════════
   APPEARANCE — the reader's own choice, a core feature of every WijnUI app
   (from feed, 2026-09-27). Two settings, both on the root element, both
   applied by tokens/wijnui.appearance.js before first paint:

     data-wui-theme    dark (default) · light · black
     data-wui-accent   one of the accents below, or absent for the product's own

   These blocks sit AFTER the product registry on purpose: a product declares
   its look, and the reader's choice overrides it. Same specificity, later
   wins; the [theme] × [accent] combinations carry one more attribute, so they
   win over a product's own light block.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Black (AMOLED) ──────────────────────────────────────────────────────────
   Not "dark, but darker": the ground is #000 exactly, because on an OLED panel
   that is an unlit pixel — the battery saving and the look both come from the
   zero. The surfaces above it are NOT black: a card has to be findable, and on
   a true-black page only a lifted surface or a border can say where one ends.
   6% and 11% are the smallest steps that read as edges on a phone at night,
   and the rule is lifted well above dark's, because a hairline that works on
   12% disappears on 0%. Brand and signals are the dark theme's. */
:root[data-wui-theme="black"] {
  color-scheme: dark;
  --wui-bg: #000000;
  --wui-surface: hsl(var(--wui-hue) 10% 6%);
  --wui-surface-high: hsl(var(--wui-hue) 10% 11%);
  --wui-surface-highest: hsl(var(--wui-hue) 10% 15%);
  --wui-rule: hsl(var(--wui-hue) 10% 22%);
}

/* ── Accent ─────────────────────────────────────────────────────────────────
   One hue re-tints the whole app: the brand, the primary fill, the nav
   indicator, AND a faint wash across the ground and its borders, so Sky reads
   as cool slate and Clay as warm taupe. Text stays neutral. Signals never move
   with it: an accent is UI state, and ok/warn/crit are domain signal.

   Pick one with data-wui-accent; the list lives in wijnui.appearance.js. */
:root[data-wui-accent] {
  --wui-bg: hsl(var(--wui-hue) 11% 11%);
  --wui-surface: hsl(var(--wui-hue) 11% 15%);
  --wui-surface-high: hsl(var(--wui-hue) 11% 18%);
  --wui-surface-highest: hsl(var(--wui-hue) 12% 22%);
  --wui-rule: hsl(var(--wui-hue) 11% 25%);
  --wui-on-bg: #FFFFFF;
  --wui-on-surface: hsl(var(--wui-hue) 8% 70%);
  --wui-on-faint: hsl(var(--wui-hue) 12% 62%);   /* 58% fell to 4.2:1 on a raised card for indigo */
  --wui-brand: hsl(var(--wui-hue) 48% 74%);
  --wui-brand-dim: hsl(var(--wui-hue) 48% 80%);
  --wui-on-brand: hsl(var(--wui-hue) 30% 14%);
  --wui-nav-indicator: hsl(var(--wui-hue) 48% 74% / .16);
  /* 34%, not feed's 36%: at 36 the label fell to 4.44:1 on teal. 34 keeps
     every accent's label at 4.88:1 or better (gallery.spec measures it). */
  --wui-brand-fill: hsl(var(--wui-hue) 40% 34%);
  --wui-on-brand-fill: #FDFBF8;
}
:root[data-wui-accent][data-wui-theme="black"] {
  --wui-bg: #000000;
  --wui-surface: hsl(var(--wui-hue) 10% 6%);
  --wui-surface-high: hsl(var(--wui-hue) 10% 11%);
  --wui-surface-highest: hsl(var(--wui-hue) 10% 15%);
  --wui-rule: hsl(var(--wui-hue) 10% 22%);
}
:root[data-wui-accent][data-wui-theme="light"] {
  --wui-bg: hsl(var(--wui-hue) 26% 97%);
  --wui-surface: hsl(var(--wui-hue) 26% 93%);
  --wui-surface-high: hsl(var(--wui-hue) 24% 89%);
  --wui-surface-highest: hsl(var(--wui-hue) 22% 85%);
  --wui-rule: hsl(var(--wui-hue) 18% 81%);
  --wui-on-bg: #1D1F20;
  --wui-on-surface: #4A4740;
  --wui-on-faint: #655D53;
  /* The brand is TEXT here (active tab, chip, link), so it must clear 4.5:1 on every light
     surface: at 32% teal was 3.99:1 on a raised card; 28% clears 4.9:1 for all eight. The
     fill stays at 32% — white on it is 4.94:1 or better. */
  --wui-brand: hsl(var(--wui-hue) 52% 28%);
  --wui-brand-dim: hsl(var(--wui-hue) 52% 22%);
  --wui-on-brand: #FFFFFF;
  --wui-nav-indicator: hsl(var(--wui-hue) 52% 28% / .12);
  /* 32%, not 34%: at 34 white on teal was 4.47:1; at 32 every accent clears 4.9:1. */
  --wui-brand-fill: hsl(var(--wui-hue) 52% 32%);
  --wui-on-brand-fill: #FFFFFF;
}

/* The accents — feed's eight. There is no "neutral" accent: going back to the
   product's own colour is the picker's Default, which removes the attribute. */
:root[data-wui-accent="clay"]    { --wui-hue: 28; }
:root[data-wui-accent="amber"]   { --wui-hue: 42; }
:root[data-wui-accent="rose"]    { --wui-hue: 350; }
:root[data-wui-accent="violet"]  { --wui-hue: 270; }
:root[data-wui-accent="indigo"]  { --wui-hue: 232; }
:root[data-wui-accent="sky"]     { --wui-hue: 205; }
:root[data-wui-accent="teal"]    { --wui-hue: 178; }
:root[data-wui-accent="emerald"] { --wui-hue: 152; }
