{"_id":"@333eco/brand","name":"@333eco/brand","dist-tags":{"latest":"1.3.0"},"versions":{"1.3.0":{"name":"@333eco/brand","version":"1.3.0","description":"The canonical brand layer for the institution — design tokens, themes, motion, and the B-Emblem. A READ-ONLY MIRROR; institution repos vendor this layer, they do not install it.","license":"Apache-2.0","author":{"name":"Thon Ly"},"homepage":"https://brand.333.eco","repository":{"type":"git","url":"git+https://github.com/333eco/brand.333.eco.git"},"bugs":{"url":"https://github.com/333eco/brand.333.eco/issues"},"keywords":["design-tokens","design-system","css","tailwind","theme","dark-mode"],"type":"module","exports":{"./css/*":"./css/*","./emblem/*":"./emblem/*","./data/*":"./data/*","./tokens.json":"./dist/tokens.json","./Brand.swift":"./dist/Brand.swift","./Brand.kt":"./dist/Brand.kt","./brand.lock":"./brand.lock","./package.json":"./package.json"},"scripts":{"check":"node scripts/check-brand.mjs","check:publish":"node scripts/check-publish.mjs","generate":"node scripts/generate.mjs"},"publishConfig":{"access":"public"},"_id":"@333eco/brand@1.3.0","gitHead":"1410b0df3f555d28fc5fbe2d59c6a846927f2abb","_nodeVersion":"22.12.0","_npmVersion":"11.0.0","dist":{"integrity":"sha512-vbmCoakUgv1kfQQ2yOAAWRym7I9k92w0Pd18+bLus2fTpE19BDXyp/oGvMrltGA91hkWve2Dw8sJdP+xSNpvTw==","shasum":"90ae9ca15ec4fc95c7e4a73a7c68ed72d19d789a","tarball":"https://registry.npmjs.org/@333eco/brand/-/brand-1.3.0.tgz","fileCount":20,"unpackedSize":122775,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGQte9EKn1XvutZsjwR37vKXFwmPrR74I+n/GaTC2MyTAiBhUK5MwGzGOQg929Shu9QvhKzVNvDSsXu8gBV/XhCOpw=="}]},"_npmUser":{"name":"thonly","email":"thonly@heartbank.ceo"},"directories":{},"maintainers":[{"name":"thonly","email":"thonly@heartbank.ceo"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/brand_1.3.0_1788281894077_0.0011600765046042572"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-01T16:58:13.873Z","1.3.0":"2026-09-01T16:58:14.213Z","modified":"2026-09-01T16:58:14.477Z"},"maintainers":[{"name":"thonly","email":"thonly@heartbank.ceo"}],"description":"The canonical brand layer for the institution — design tokens, themes, motion, and the B-Emblem. A READ-ONLY MIRROR; institution repos vendor this layer, they do not install it.","homepage":"https://brand.333.eco","keywords":["design-tokens","design-system","css","tailwind","theme","dark-mode"],"repository":{"type":"git","url":"git+https://github.com/333eco/brand.333.eco.git"},"author":{"name":"Thon Ly"},"bugs":{"url":"https://github.com/333eco/brand.333.eco/issues"},"license":"Apache-2.0","readme":"# brand.333.eco\n\nThe canonical brand layer for the institution: design tokens, the B-Emblem™, and\nthe heartbeat. Vendored into every site that renders them, behind a hash guard.\n\nPublished as guidelines at **<https://brand.333.eco>** — a page that is *drawn by\nthe tokens it documents*, so it cannot drift from them.\n\n## ⚠️ On npm as `@333eco/brand` — a READ-ONLY MIRROR\n\nThe package exists so that people outside the institution can take what the\nNOTICE invites them to take. **It is not how institution repos get this layer.**\n\n> **Institution repos VENDOR this layer. They do not `npm install` it.**\n> `npm run brand:sync -- --from <path to brand.333.eco>`, guarded by\n> `brand.lock`. A dependency range is drift with a number on it, and four\n> consumers were once found three minor versions behind while every guard\n> reported green — see the note further down. Do not add `@333eco/brand` to any\n> repository in this estate.\n\nFor everyone else: `npm i @333eco/brand`, then import what you need —\n`@333eco/brand/css/tokens.css`, `@333eco/brand/tokens.json`,\n`@333eco/brand/Brand.swift`. The mirror is published from the same commit that\nbumps the version, gated by `scripts/check-publish.mjs`, so it cannot lag behind\nthe repository.\n\n## Why this exists\n\nThis layer lived in four repositories at once — `seysays`, `sayyourname`,\n`playsey` and `333.eco` — as copies, and had already begun to fork. Two of the\ncopies were improved on the same day in opposite directions: one refined the\nplacement rule's comment, the other rewrote the rule itself and documented why.\nNeither was broken. The next edit that landed in one repo only was the one that\nwould bite.\n\nIt was deliberately **not** extracted earlier, and that was correct: *a design\nsystem published before it has been used once is a guess.* It has now been used\nfour times.\n\n## Why it is on 333.eco\n\nThe brand serves four GitHub orgs and a dozen domains. Hosting it under any one\nbody's TLD would make that body the landlord of the others' identity. `333.eco`\nis the domain that **names no single body** — the same argument that placed\nB-Registry℠ there.\n\n## Layout\n\n```\ncss/\n  tokens.css          Tier A @theme + Tier B -d-/-l- palette pairs + derived accents\n  theme-3block.css    dark-default cascade with the :not() guard   ─┐ pick\n  theme-2state.css    light-default + .dark stamp                  ─┘ exactly one\n  motion.css          @keyframes heartbeat + .beating + the scoped reduce guard\n  metta.css           the Metta Light session descent (OPT-IN)\n  reduce-global.css   the estate-wide reduced-motion sweep (OPT-IN)\nemblem/\n  emblem.svg          reference copy + the home of the rotation warning\n  emblem.ts           Lit template function\n  emblem.path.txt     the path `d` string, alone, for generators\ndata/\n  gems.json           gem semantics (MEDIUM). NO hex — those live in tokens.css\n  auras.json          aura-ramp semantics (RATE). NO hex — same rule\n  tlds.json           the six-TLD rainbow (DOMAIN). No hex ANYWHERE — see below\n  brand.json          version, wordmark, mark rules, the accent rule, site map\ndist/                 GENERATED, committed: tokens.json · Brand.swift · Brand.kt\nscripts/\n  generate.mjs        css/ + data/ -> dist/\n  check-brand.mjs     the drift guard; copied verbatim into every consumer\nsite/                 the guidelines page -> brand.333.eco (an installable PWA)\nbrand.lock            every package file -> sha256, plus a version\n```\n\nThe page is also **the mark's colour playground**: every mark on it reads\n`--emblem`, and a visitor can point that at any gem or leave it rotating.\nDiamond is in the picker but **not** in the rotation: a cool near-white blinks\nout on the light ground, and a rotation that disappears for a sixth of its cycle\nin one theme is a bug that only shows up in one theme.\n\n⚠️ **The rotation is driven from JS, and this paragraph used to say otherwise.**\nIt was built first as pure CSS — an `@property`-registered custom property\ninterpolated by `@keyframes` — and that version was wrong on screen in a way\n`getComputedStyle` could not see: the hero mark tracked it while the header mark\npainted its pre-animation colour. Chrome does not re-rasterise an element for an\nanimated custom property it *inherits*. The code changed and this file did not,\nso it claimed a property the page does not have — the rotation does **not**\nsurvive with scripting off. Recorded here because the same technique is the\nobvious way to build the Metta Light, and it will fail the same way.\n\n⚠️ **Rendering the MARK in gem colours is not the thing the gem rule forbids.**\nThe rule is that a gem must not become a SITE ACCENT. Hearts in gem colours is\nratified doctrine — Tonsay's stream is *\"7 rainbow hearts: the 6 GEM colours +\nDIAMOND\"*. This page's own accent stays a site value and does not move.\n\n**No value is typed twice.** `css/tokens.css` is canonical; the JSON holds only\nwhat a stylesheet cannot say; `dist/` is generated from both.\n\n## Consuming it\n\nThere is nothing to install and nothing to fetch at build time.\n\n```bash\n# take the current layer (deliberate, reviewable, never CI)\nnpm run brand:sync -- --from ../../333.eco/brand.333.eco\n\n# verify — no network, no credentials, no sibling checkout\nnpm run check:brand\n```\n\nA consumer holds three files from this repo:\n\n| File | Differs per repo? |\n|---|---|\n| the vendored `css/` and `emblem/` files | no — byte-identical |\n| `brand.lock` | **no** — byte-identical, so a lagging repo shows an older version in a diff |\n| `check-brand.mjs` | no — byte-identical |\n| `brand.uses` | **yes** — the one file that must differ |\n\n`brand.uses` declares what this repo took and where it lives:\n\n```json\n{ \"dir\": \"partials\", \"files\": [\"tokens.css\", \"theme-3block.css\", \"motion.css\", \"reduce-global.css\"] }\n```\n\n### Concatenation order\n\nNot arbitrary. Custom-property substitution is lazy, so a value declared early\nmay reference one a later file sets — that is how `--accent`, set per site,\nreaches the derived family.\n\n```\ntokens.css\n  + theme-3block.css   or   theme-2state.css\n  + motion.css\n  + reduce-global.css  (opt-in)\n  + brand.css          (per site — the accent and the two values that cannot derive)\n  + site.css           (per site)\n```\n\n### ⚠️ Never `@import` a sibling of these files\n\nThe partial-based sites inject their stylesheets as **raw text** and concatenate\nthem. A relative `@import` resolves against `src/`, where `partials/` is\nunreachable, and ships a dead render-blocking at-rule — quietly destroying the\none-request-renders-complete property the inlining exists to buy.\n\n`@import \"tailwindcss\"` at the top of `tokens.css` is a different thing and is\nfine: a bare specifier the Tailwind plugin resolves. Verified to reach `dist`.\n\n## The rules that are easy to break\n\n- **A site's accent is DERIVED**, never picked: take the gem whose media type\n  *is* that product's medium. Two values cannot derive — `--accent-ink`, and\n  `--accent-soft` on a light ground. Measure and pin them per site.\n- **THERE ARE THREE PALETTES AND THEY ARE NOT ONE SYSTEM.** A gem means a\n  **medium** (7, `gems.json`); an aura stop means a **rate** (7, `auras.json`);\n  a rainbow hue means a **domain** (6, `tlds.json`). The hues rhyme because a\n  colour wheel is small. The two sevens are *different sets* — the aura ramp\n  carries indigo and ends at violet, the gems carry no indigo and end at\n  diamond.\n- **The six-TLD rainbow has NO pinned values, anywhere.** The corpus fixes six\n  colour *words*; no file fixes a hex. Do not add six tokens to tidy that up —\n  none of the four consumers is a `heartbank.{TLD}`, so they would ship dead\n  into all four behind the lock. Pin them when the first one needs them, and\n  measure contrast then.\n- **The Metta Light chain lives on `.metta`, never on `:root`.** Custom\n  properties inherit their *computed* value, so a chain on `:root` resolves once\n  against root's `--t` and every descendant inherits the finished colour — the\n  ramp dies silently. The element that sets `--t` must carry the class.\n- **Never register `--metta` with `@property`.** It buys a type and the ability\n  to transition it, and transitioning it puts the file straight back inside the\n  Chrome inherited-animated-custom-property bug it was written to route around.\n  Move `--t` on the app's clock instead.\n- **Pink is absent by construction.** Reserved for B-Dating. Not an oversight —\n  and the aura ramp is where the reservation was actually being broken: four\n  shipped Phase-1 surfaces were rendering the `indigo` bucket in pink.\n- **Two aura hexes collide with other tokens** — `--color-aura-red` with\n  `--danger`, `--color-aura-violet` with `--color-violet-sey`. Coincidence, not\n  kinship. Never alias them into each other.\n- **`.beating` goes on CHROME**, never beside a person's name.\n- **The 45° rotation is baked into the path coordinates.** Never a `transform`.\n- **The two theme files are peers.** Converting a site between them is a\n  regression, not a tidy-up. So is dropping `reduce-global.css` into seysays.\n\n## Tripwires\n\nThese fail **silently** — no error at any layer. Check them after touching the\nCSS or the build:\n\n```bash\n# @theme tokens are tree-shaken unless the AUTHOR'S own CSS references them.\n# A token referenced only from runtime JS vanishes and the element renders bare.\ngrep -o -- '--color-ruby' site/dist/assets/*.css       # must be > 0\ngrep -o -- '--color-aura-indigo' site/dist/assets/*.css   # must be > 0\ngrep -o -- '--beat-duration' site/dist/assets/*.css   # must be > 0\n\n# The six-TLD marks are painted with CSS KEYWORDS, not tokens, because nothing\n# is pinned. If this ever returns > 0, someone invented six values — check that\n# it was a decision and not a tidy-up.\ngrep -o -- '--color-tld' css/tokens.css               # must be 0\n\n# The Metta ramp dies silently if the chain is hoisted to :root — it resolves\n# once and descendants inherit a frozen colour. The chain must be class-scoped.\ngrep -c '^\\.metta {' css/metta.css                     # must be 1\ngrep -c '^@property' css/metta.css                     # must be 0 (prose mentions it)\n\n# The custom domain unmaps if this is missing, with a green build.\ntest -f site/dist/CNAME\n\n# A service worker that ships an unstamped placeholder caches under the literal\n# string \"__BUILD_ID__\" forever. The build throws instead — but check anyway.\ngrep -c '__BUILD_ID__\\|__ASSET_LIST__' site/dist/sw.js   # must be 0\n```\n\n### Two that bit this page already\n\n**Transforms do not apply to non-replaced inline elements.** `.beating` on a\nbare `<span>` wrapper animates nothing, silently. The header mark and the motion\ndemo were both built that way and both sat still. The class goes on the `<svg>`.\n\n**XML comments cannot contain a double hyphen.** Writing a CSS custom property\nname the ordinary way inside `icon.svg` makes the file unparseable and the whole\nicon set fails to build. Name tokens in prose there, never in their real syntax.\n\n## Maintaining\n\n```bash\nnode scripts/generate.mjs            # rewrite dist/\nnode scripts/generate.mjs --check    # prove dist/ is current (CI)\nnode scripts/check-brand.mjs         # prove brand.lock matches css/ + emblem/\nnode scripts/check-brand.mjs --write # rewrite brand.lock after a change\ncd site && npm run dev               # the guidelines page, localhost:57890\n```\n\n**Bump `version` in `data/brand.json`** with any change to `css/` or `emblem/`,\nthen run both `--write` steps and commit `brand.lock` and `dist/` in the same\ncommit as the change. The version is how \"which sites are on which brand\" is\nanswerable by grep.\n\n## Honest limits\n\n- **The fluid type scale does not port to native.** `clamp(min, Nvw, max)` has\n  no equivalent; `dist/` emits `min`/`max` and says so. Do not hard-code the max\n  and call it done — use the platform's own accessibility scale.\n- **`color-mix(in oklab, …)` is reproduced in `generate.mjs`**, not delegated.\n  The values were checked against four independently hand-measured pins in the\n  estate and land within a few percent — the differences are exactly the\n  contrast corrections those pins exist to make.\n- **`dist/Brand.swift` and `dist/Brand.kt` have no consumer yet.** They were\n  written ahead of the first native app, against the rule this package was\n  extracted under. They are therefore the least-proven thing here.\n\n## Licence\n\n**Apache-2.0** for the code — see [`LICENSE`](./LICENSE).\n\n⚠️ **The marks are not licensed by it, and that is why this licence and not a\nmore permissive one.** This repository ships an actual mark, not just the code\nthat renders it: the B-Emblem™ is a design mark under filing, and\n`emblem/emblem.svg` is its canonical copy. Apache-2.0 §6 grants no trademark\nrights, which is exactly the posture wanted — **take the architecture, leave the\nmark.** [`NOTICE`](./NOTICE) lists what is reserved and, more usefully, what you\nare positively invited to do with the rest.\n\nThe design patterns themselves are commons, published as CC0 defensive prior art\nin *Brand Identity as Architecture* (DOI\n[10.5281/zenodo.21947287](https://doi.org/10.5281/zenodo.21947287)), whose §12\nnames this repository as its reference implementation. The paper is the\nspecification; this is the instantiation.\n","readmeFilename":"README.md","_rev":"1-5dbdfa775d7867314348354f4b7b832b"}