@krizaka/ui 3.7.1 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +4 -4
  2. package/dist/{chunk-JZPVUJIX.js → chunk-UB2BI3AW.js} +1 -1
  3. package/dist/{chunk-JZPVUJIX.js.map → chunk-UB2BI3AW.js.map} +1 -1
  4. package/dist/{geometry-CbOU4rtL.d.ts → geometry-B2E8oFhg.d.ts} +1 -1
  5. package/dist/index.d.ts +7 -5
  6. package/dist/index.js +26 -24
  7. package/dist/index.js.map +1 -1
  8. package/dist/map.js +1 -1
  9. package/dist/map.js.map +1 -1
  10. package/dist/mascot-quote.d.ts +1 -1
  11. package/dist/mascot-quote.js.map +1 -1
  12. package/dist/mascot-state.d.ts +1 -1
  13. package/dist/mascot-state.js +1 -1
  14. package/dist/mascots.d.ts +2 -2
  15. package/dist/mascots.js +1 -1
  16. package/dist/native/map.js +1 -1
  17. package/dist/native/map.js.map +1 -1
  18. package/dist/native.d.ts +9 -7
  19. package/dist/native.js +26 -24
  20. package/dist/native.js.map +1 -1
  21. package/dist/status-page.d.ts +1 -1
  22. package/dist/status-page.js.map +1 -1
  23. package/package.json +5 -5
  24. package/registry/examples/landing-page/krizaka.js +1 -1
  25. package/registry/examples/landing-page/krizaka.tsx +1 -1
  26. package/registry/examples/mascots/flock.tsx +1 -1
  27. package/registry/examples/profile-card/match.js +1 -1
  28. package/registry/examples/profile-card/match.tsx +1 -1
  29. package/registry/examples/status-page/building.js +1 -1
  30. package/registry/examples/status-page/building.tsx +1 -1
  31. package/registry/index.json +3 -3
  32. package/registry/landing-page.json +2 -2
  33. package/registry/loader.json +3 -3
  34. package/registry/map.json +1 -1
  35. package/registry/mascots.json +4 -4
  36. package/registry/product-page.json +2 -2
  37. package/registry/profile-card.json +1 -1
  38. package/registry/status-page.json +6 -6
@@ -10,7 +10,7 @@ type StatusPageProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & {
10
10
  };
11
11
  /** A mono line above the title. */
12
12
  eyebrow?: React.ReactNode;
13
- /** The page's `h1` (`Status`, `Yazakia is on its way`). */
13
+ /** The page's `h1` (`Status`, `Yasakia is on its way`). */
14
14
  title: React.ReactNode;
15
15
  /** One sentence under it. */
16
16
  lead?: React.ReactNode;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/status-page/status-page.tsx"],"sourcesContent":["// Server-safe. Where things stand (blocks.css `.kz-tpl-state`, `.kz-tpl-services`): the overall state in words and\n// colour, each service on its line, the incidents under them — or, for something not built yet (`state=\"building\"`),\n// what is coming, its progress and how to hear about it, the bird beside it. A state is always said in words.\nimport { Page, Section } from \"@krizaka/ui/page\";\nimport type { LinkComponent } from \"@krizaka/ui/page-hero\";\nimport { PageHero } from \"@krizaka/ui/page-hero\";\nimport type * as React from \"react\";\n\nexport type ServiceState = \"operational\" | \"degraded\" | \"outage\" | \"building\";\n\nexport type StatusPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\n /** The way back. */\n back?: { href: string; label: string };\n /** A mono line above the title. */\n eyebrow?: React.ReactNode;\n /** The page's `h1` (`Status`, `Yazakia is on its way`). */\n title: React.ReactNode;\n /** One sentence under it. */\n lead?: React.ReactNode;\n /** Beside the hero: a bird (the pigeon that delivers, the duck that builds). */\n aside?: React.ReactNode;\n /** The overall state. */\n state: ServiceState;\n /** The overall state, in words (`All systems operational`). */\n stateLabel: React.ReactNode;\n /** When it was checked (`Checked 2 min ago`). */\n checked?: React.ReactNode;\n /** The services and their states, in words: `{ id, name, state, label }`. */\n services?: readonly { id: string; name: React.ReactNode; state: ServiceState; label: React.ReactNode }[];\n /** The services list's accessible name (`Services`). */\n servicesLabel?: string;\n /** Under the services: the incidents (a ChangelogPage's entries, a list), or for `building` the progress and the way to follow. */\n children?: React.ReactNode;\n /** The app's link component (Next's `Link`). */\n linkAs?: LinkComponent;\n};\n\n/** A status page — or an « under construction » one: the overall state, each service, then incidents or progress. */\nexport function StatusPage({ back, eyebrow, title, lead, aside, state, stateLabel, checked, services, servicesLabel = \"Services\", linkAs, children, ...props }: StatusPageProps) {\n return (\n <div {...props}>\n <PageHero back={back} linkAs={linkAs} eyebrow={eyebrow} title={title} lead={lead} aside={aside} backdrop=\"plain\" />\n <Page className=\"kz-tpl-longform\">\n <div className=\"kz-tpl-state\" data-state={state} role=\"status\">\n <span className=\"kz-tpl-dot\" aria-hidden />\n <strong>{stateLabel}</strong>\n {checked && <span className=\"kz-tpl-count\">{checked}</span>}\n </div>\n {services && services.length > 0 && (\n <ul className=\"kz-tpl-services\" aria-label={servicesLabel}>\n {services.map((s) => (\n <li key={s.id}>\n <span>{s.name}</span>\n <small>\n <span className=\"kz-tpl-dot\" data-state={s.state} aria-hidden />\n {s.label}\n </small>\n </li>\n ))}\n </ul>\n )}\n </Page>\n {children && <Section spacing=\"sm\">{children}</Section>}\n </div>\n );\n}\n"],"mappings":";AAGA,SAAS,MAAM,eAAe;AAE9B,SAAS,gBAAgB;AAoCnB,cAEE,YAFF;AAHC,SAAS,WAAW,EAAE,MAAM,SAAS,OAAO,MAAM,OAAO,OAAO,YAAY,SAAS,UAAU,gBAAgB,YAAY,QAAQ,UAAU,GAAG,MAAM,GAAoB;AAC/K,SACE,qBAAC,SAAK,GAAG,OACP;AAAA,wBAAC,YAAS,MAAY,QAAgB,SAAkB,OAAc,MAAY,OAAc,UAAS,SAAQ;AAAA,IACjH,qBAAC,QAAK,WAAU,mBACd;AAAA,2BAAC,SAAI,WAAU,gBAAe,cAAY,OAAO,MAAK,UACpD;AAAA,4BAAC,UAAK,WAAU,cAAa,eAAW,MAAC;AAAA,QACzC,oBAAC,YAAQ,sBAAW;AAAA,QACnB,WAAW,oBAAC,UAAK,WAAU,gBAAgB,mBAAQ;AAAA,SACtD;AAAA,MACC,YAAY,SAAS,SAAS,KAC7B,oBAAC,QAAG,WAAU,mBAAkB,cAAY,eACzC,mBAAS,IAAI,CAAC,MACb,qBAAC,QACC;AAAA,4BAAC,UAAM,YAAE,MAAK;AAAA,QACd,qBAAC,WACC;AAAA,8BAAC,UAAK,WAAU,cAAa,cAAY,EAAE,OAAO,eAAW,MAAC;AAAA,UAC7D,EAAE;AAAA,WACL;AAAA,WALO,EAAE,EAMX,CACD,GACH;AAAA,OAEJ;AAAA,IACC,YAAY,oBAAC,WAAQ,SAAQ,MAAM,UAAS;AAAA,KAC/C;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/status-page/status-page.tsx"],"sourcesContent":["// Server-safe. Where things stand (blocks.css `.kz-tpl-state`, `.kz-tpl-services`): the overall state in words and\n// colour, each service on its line, the incidents under them — or, for something not built yet (`state=\"building\"`),\n// what is coming, its progress and how to hear about it, the bird beside it. A state is always said in words.\nimport { Page, Section } from \"@krizaka/ui/page\";\nimport type { LinkComponent } from \"@krizaka/ui/page-hero\";\nimport { PageHero } from \"@krizaka/ui/page-hero\";\nimport type * as React from \"react\";\n\nexport type ServiceState = \"operational\" | \"degraded\" | \"outage\" | \"building\";\n\nexport type StatusPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\n /** The way back. */\n back?: { href: string; label: string };\n /** A mono line above the title. */\n eyebrow?: React.ReactNode;\n /** The page's `h1` (`Status`, `Yasakia is on its way`). */\n title: React.ReactNode;\n /** One sentence under it. */\n lead?: React.ReactNode;\n /** Beside the hero: a bird (the pigeon that delivers, the duck that builds). */\n aside?: React.ReactNode;\n /** The overall state. */\n state: ServiceState;\n /** The overall state, in words (`All systems operational`). */\n stateLabel: React.ReactNode;\n /** When it was checked (`Checked 2 min ago`). */\n checked?: React.ReactNode;\n /** The services and their states, in words: `{ id, name, state, label }`. */\n services?: readonly { id: string; name: React.ReactNode; state: ServiceState; label: React.ReactNode }[];\n /** The services list's accessible name (`Services`). */\n servicesLabel?: string;\n /** Under the services: the incidents (a ChangelogPage's entries, a list), or for `building` the progress and the way to follow. */\n children?: React.ReactNode;\n /** The app's link component (Next's `Link`). */\n linkAs?: LinkComponent;\n};\n\n/** A status page — or an « under construction » one: the overall state, each service, then incidents or progress. */\nexport function StatusPage({ back, eyebrow, title, lead, aside, state, stateLabel, checked, services, servicesLabel = \"Services\", linkAs, children, ...props }: StatusPageProps) {\n return (\n <div {...props}>\n <PageHero back={back} linkAs={linkAs} eyebrow={eyebrow} title={title} lead={lead} aside={aside} backdrop=\"plain\" />\n <Page className=\"kz-tpl-longform\">\n <div className=\"kz-tpl-state\" data-state={state} role=\"status\">\n <span className=\"kz-tpl-dot\" aria-hidden />\n <strong>{stateLabel}</strong>\n {checked && <span className=\"kz-tpl-count\">{checked}</span>}\n </div>\n {services && services.length > 0 && (\n <ul className=\"kz-tpl-services\" aria-label={servicesLabel}>\n {services.map((s) => (\n <li key={s.id}>\n <span>{s.name}</span>\n <small>\n <span className=\"kz-tpl-dot\" data-state={s.state} aria-hidden />\n {s.label}\n </small>\n </li>\n ))}\n </ul>\n )}\n </Page>\n {children && <Section spacing=\"sm\">{children}</Section>}\n </div>\n );\n}\n"],"mappings":";AAGA,SAAS,MAAM,eAAe;AAE9B,SAAS,gBAAgB;AAoCnB,cAEE,YAFF;AAHC,SAAS,WAAW,EAAE,MAAM,SAAS,OAAO,MAAM,OAAO,OAAO,YAAY,SAAS,UAAU,gBAAgB,YAAY,QAAQ,UAAU,GAAG,MAAM,GAAoB;AAC/K,SACE,qBAAC,SAAK,GAAG,OACP;AAAA,wBAAC,YAAS,MAAY,QAAgB,SAAkB,OAAc,MAAY,OAAc,UAAS,SAAQ;AAAA,IACjH,qBAAC,QAAK,WAAU,mBACd;AAAA,2BAAC,SAAI,WAAU,gBAAe,cAAY,OAAO,MAAK,UACpD;AAAA,4BAAC,UAAK,WAAU,cAAa,eAAW,MAAC;AAAA,QACzC,oBAAC,YAAQ,sBAAW;AAAA,QACnB,WAAW,oBAAC,UAAK,WAAU,gBAAgB,mBAAQ;AAAA,SACtD;AAAA,MACC,YAAY,SAAS,SAAS,KAC7B,oBAAC,QAAG,WAAU,mBAAkB,cAAY,eACzC,mBAAS,IAAI,CAAC,MACb,qBAAC,QACC;AAAA,4BAAC,UAAM,YAAE,MAAK;AAAA,QACd,qBAAC,WACC;AAAA,8BAAC,UAAK,WAAU,cAAa,cAAY,EAAE,OAAO,eAAW,MAAC;AAAA,UAC7D,EAAE;AAAA,WACL;AAAA,WALO,EAAE,EAMX,CACD,GACH;AAAA,OAEJ;AAAA,IACC,YAAY,oBAAC,WAAQ,SAAQ,MAAM,UAAS;AAAA,KAC/C;AAEJ;","names":[]}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@krizaka/ui",
3
- "version": "3.7.1",
4
- "description": "The Krizaka front-end platform's components: the primitives (button, card, dialog, toast, menu, field, tabs, chip, switch, slider, command palette, theme, countdown…) on the semantic --kz-* tokens, the animated marks (Krizaka, Orazaka, Orochia, Yazakia, Yororis) and the motion signature — web and /native.",
3
+ "version": "3.8.0",
4
+ "description": "The Krizaka front-end platform's components: the primitives (button, card, dialog, toast, menu, field, tabs, chip, switch, slider, command palette, theme, countdown…) on the semantic --kz-* tokens, the animated marks (Krizaka, Orazaka, Orochia, Yasakia, Yororis) and the motion signature — web and /native.",
5
5
  "keywords": [
6
6
  "krizaka",
7
7
  "orazaka",
8
8
  "orochia",
9
- "yazakia",
9
+ "yasakia",
10
10
  "yororis",
11
11
  "react",
12
12
  "logo",
@@ -590,7 +590,7 @@
590
590
  ],
591
591
  "peerDependencies": {
592
592
  "@krizaka/query": ">=0.2.0",
593
- "@krizaka/tailwind": ">=3.7.1",
593
+ "@krizaka/tailwind": ">=3.8.0",
594
594
  "@maplibre/maplibre-react-native": ">=11",
595
595
  "@shopify/flash-list": ">=2",
596
596
  "expo-camera": ">=16",
@@ -2030,7 +2030,7 @@
2030
2030
  "sonner": "^2.0.8",
2031
2031
  "tailwind-variants": "^3.3.1",
2032
2032
  "@krizaka/intl": "^0.2.0",
2033
- "@krizaka/tokens": "^3.7.1"
2033
+ "@krizaka/tokens": "^3.8.0"
2034
2034
  },
2035
2035
  "scripts": {
2036
2036
  "build": "node -e \"const fs=require('node:fs');fs.rmSync('dist',{recursive:true,force:true});for(const f of fs.readdirSync('registry/examples',{recursive:true}))if(/\\.(js|d\\.ts)$/.test(f))fs.rmSync('registry/examples/'+f)\" && tsup && node -e \"require('node:fs').copyFileSync('src/motion.css','dist/motion.css');require('node:fs').copyFileSync('src/blocks.css','dist/blocks.css');require('node:fs').copyFileSync('src/story.css','dist/story.css')\" && node scripts/build-registry.mjs",
@@ -31,7 +31,7 @@ function LandingPageKrizaka() {
31
31
  features: [
32
32
  { id: "orazaka", size: "lg", title: "Orazaka \u2014 the AI that never leaves home", text: "Chat, image, voice and video on your own server, one governed pipeline." },
33
33
  { id: "orochia", title: "Orochia", text: "Creators paid 90 % of what fans spend." },
34
- { id: "yazakia", title: "Yazakia", text: "Meet by talking first \u2014 coming." },
34
+ { id: "yasakia", title: "Yasakia", text: "Meet by talking first \u2014 coming." },
35
35
  { id: "blocks", size: "md", title: "Open building blocks", text: "Users, billing, notifications \u2014 on Maven Central and npm." },
36
36
  { id: "ui", size: "md", title: "One design system", text: "Krizaka UI, web and mobile, documented from its code." }
37
37
  ],
@@ -34,7 +34,7 @@ export default function LandingPageKrizaka() {
34
34
  features={[
35
35
  { id: "orazaka", size: "lg", title: "Orazaka — the AI that never leaves home", text: "Chat, image, voice and video on your own server, one governed pipeline." },
36
36
  { id: "orochia", title: "Orochia", text: "Creators paid 90 % of what fans spend." },
37
- { id: "yazakia", title: "Yazakia", text: "Meet by talking first — coming." },
37
+ { id: "yasakia", title: "Yasakia", text: "Meet by talking first — coming." },
38
38
  { id: "blocks", size: "md", title: "Open building blocks", text: "Users, billing, notifications — on Maven Central and npm." },
39
39
  { id: "ui", size: "md", title: "One design system", text: "Krizaka UI, web and mobile, documented from its code." },
40
40
  ]}
@@ -1,7 +1,7 @@
1
1
  import { Mascot,MASCOT_BIRDS } from "@krizaka/ui/mascots";
2
2
 
3
3
  // The seven birds in the host's brand colours: blue on Krizaka, orange in Orazaka, violet in Orochia, turquoise in
4
- // Yazakia, sage in Yororis.
4
+ // Yasakia, sage in Yororis.
5
5
  export default function MascotFlock() {
6
6
  return (
7
7
  <div className="flex flex-wrap items-end gap-6">
@@ -8,7 +8,7 @@ function ProfileCardMatch() {
8
8
  return /* @__PURE__ */ jsx(
9
9
  ProfileCard,
10
10
  {
11
- brand: "yazakia",
11
+ brand: "yasakia",
12
12
  visual: /* @__PURE__ */ jsx(Avatar, { src: "https://krizaka-assets.b-cdn.net/site/people/ui/camille-256.dc2943029a.webp", alt: "Camille Roy", fallback: "CR", size: "xl" }),
13
13
  visualSize: 88,
14
14
  name: "Camille, 29",
@@ -5,7 +5,7 @@ import { ProfileCard } from "@krizaka/ui/profile-card";
5
5
  export default function ProfileCardMatch() {
6
6
  return (
7
7
  <ProfileCard
8
- brand="yazakia"
8
+ brand="yasakia"
9
9
  visual={<Avatar src="https://krizaka-assets.b-cdn.net/site/people/ui/camille-256.dc2943029a.webp" alt="Camille Roy" fallback="CR" size="xl" />}
10
10
  visualSize={88}
11
11
  name="Camille, 29"
@@ -10,7 +10,7 @@ function StatusPageBuilding() {
10
10
  return /* @__PURE__ */ jsx(
11
11
  StatusPage,
12
12
  {
13
- eyebrow: "Yazakia",
13
+ eyebrow: "Yasakia",
14
14
  title: "On its way",
15
15
  lead: "Meet by talking first. The first build reaches testers this winter.",
16
16
  aside: /* @__PURE__ */ jsx(Mascot, { bird: "duck", mood: "thinking", size: 112 }),
@@ -8,7 +8,7 @@ import { StatusPage } from "@krizaka/ui/status-page";
8
8
  export default function StatusPageBuilding() {
9
9
  return (
10
10
  <StatusPage
11
- eyebrow="Yazakia"
11
+ eyebrow="Yasakia"
12
12
  title="On its way"
13
13
  lead="Meet by talking first. The first build reaches testers this winter."
14
14
  aside={<Mascot bird="duck" mood="thinking" size={112} />}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krizaka/ui",
3
- "version": "3.7.1",
3
+ "version": "3.8.0",
4
4
  "templatePurposes": {
5
5
  "convince": {
6
6
  "title": "Convince",
@@ -388,7 +388,7 @@
388
388
  "platform": "web",
389
389
  "name": "building",
390
390
  "title": "Under construction",
391
- "description": "Yazakia on its way: progress and how to hear about it.",
391
+ "description": "Yasakia on its way: progress and how to hear about it.",
392
392
  "purpose": "recover",
393
393
  "why": "A visitor learns honestly what is coming, how far it is and how to hear about it."
394
394
  },
@@ -1711,7 +1711,7 @@
1711
1711
  "native": 2
1712
1712
  },
1713
1713
  "dependencies": [
1714
- "@krizaka/tokens@^3.7.1",
1714
+ "@krizaka/tokens@^3.8.0",
1715
1715
  "@protomaps/basemaps@5.7.2",
1716
1716
  "tailwind-variants@^3.3.1"
1717
1717
  ],
@@ -131,7 +131,7 @@
131
131
  "why": "A visitor gets the promise in one screen, the product alive, the proofs and one call to act.",
132
132
  "path": "examples/landing-page/krizaka.tsx",
133
133
  "module": "@krizaka/ui/registry/examples/landing-page/krizaka",
134
- "code": "import { Button } from \"@krizaka/ui/button\";\nimport { LandingPage } from \"@krizaka/ui/landing-page\";\nimport { Meter } from \"@krizaka/ui/meter\";\n\n// TEMPLATE — a company's landing (krizaka.com): the promise beside the product alive, a band of proofs, the features\n// as a bento where the main one takes the room, the closing call. On a phone the window follows the words, the bento\n// is one column, the proofs stack.\nexport default function LandingPageKrizaka() {\n return (\n <LandingPage\n eyebrow=\"Software studio · Montréal\"\n title=\"Products that keep what is yours\"\n lead=\"Krizaka builds sovereign AI and a platform where creators are paid — open source, on your servers or ours.\"\n actions={\n <>\n <Button variant=\"primary\" size=\"lg\" shape=\"cut\" shimmer>See the products</Button>\n <Button variant=\"secondary\" size=\"lg\" shape=\"cut\">Read the docs</Button>\n </>\n }\n visualLabel=\"orazaka.local — console\"\n visual={\n <div className=\"grid gap-3 p-5\">\n <p className=\"font-mono text-xs text-fg-secondary\">$ npx orazaka install</p>\n <p className=\"font-mono text-xs text-fg-success\">✓ 1,284 answers this week, none left the server</p>\n <Meter label=\"Credits\" value={3800} max={12000} valueText=\"3,800 of 12,000\" showLabel />\n </div>\n }\n proofs={[\n { value: \"34\", label: \"public repositories\" },\n { value: \"Apache-2.0\", label: \"every line\" },\n { value: \"0\", label: \"telemetry calls\" },\n ]}\n featuresHeading={{ eyebrow: \"What we build\", title: \"Three products, one way of building\" }}\n features={[\n { id: \"orazaka\", size: \"lg\", title: \"Orazaka — the AI that never leaves home\", text: \"Chat, image, voice and video on your own server, one governed pipeline.\" },\n { id: \"orochia\", title: \"Orochia\", text: \"Creators paid 90 % of what fans spend.\" },\n { id: \"yazakia\", title: \"Yazakia\", text: \"Meet by talking first — coming.\" },\n { id: \"blocks\", size: \"md\", title: \"Open building blocks\", text: \"Users, billing, notifications — on Maven Central and npm.\" },\n { id: \"ui\", size: \"md\", title: \"One design system\", text: \"Krizaka UI, web and mobile, documented from its code.\" },\n ]}\n closing={{ title: \"Something to build together?\", body: \"Tell us what you need; a person answers within two days.\", actions: <Button variant=\"primary\" size=\"lg\" shape=\"cut\">Contact us</Button> }}\n />\n );\n}\n"
134
+ "code": "import { Button } from \"@krizaka/ui/button\";\nimport { LandingPage } from \"@krizaka/ui/landing-page\";\nimport { Meter } from \"@krizaka/ui/meter\";\n\n// TEMPLATE — a company's landing (krizaka.com): the promise beside the product alive, a band of proofs, the features\n// as a bento where the main one takes the room, the closing call. On a phone the window follows the words, the bento\n// is one column, the proofs stack.\nexport default function LandingPageKrizaka() {\n return (\n <LandingPage\n eyebrow=\"Software studio · Montréal\"\n title=\"Products that keep what is yours\"\n lead=\"Krizaka builds sovereign AI and a platform where creators are paid — open source, on your servers or ours.\"\n actions={\n <>\n <Button variant=\"primary\" size=\"lg\" shape=\"cut\" shimmer>See the products</Button>\n <Button variant=\"secondary\" size=\"lg\" shape=\"cut\">Read the docs</Button>\n </>\n }\n visualLabel=\"orazaka.local — console\"\n visual={\n <div className=\"grid gap-3 p-5\">\n <p className=\"font-mono text-xs text-fg-secondary\">$ npx orazaka install</p>\n <p className=\"font-mono text-xs text-fg-success\">✓ 1,284 answers this week, none left the server</p>\n <Meter label=\"Credits\" value={3800} max={12000} valueText=\"3,800 of 12,000\" showLabel />\n </div>\n }\n proofs={[\n { value: \"34\", label: \"public repositories\" },\n { value: \"Apache-2.0\", label: \"every line\" },\n { value: \"0\", label: \"telemetry calls\" },\n ]}\n featuresHeading={{ eyebrow: \"What we build\", title: \"Three products, one way of building\" }}\n features={[\n { id: \"orazaka\", size: \"lg\", title: \"Orazaka — the AI that never leaves home\", text: \"Chat, image, voice and video on your own server, one governed pipeline.\" },\n { id: \"orochia\", title: \"Orochia\", text: \"Creators paid 90 % of what fans spend.\" },\n { id: \"yasakia\", title: \"Yasakia\", text: \"Meet by talking first — coming.\" },\n { id: \"blocks\", size: \"md\", title: \"Open building blocks\", text: \"Users, billing, notifications — on Maven Central and npm.\" },\n { id: \"ui\", size: \"md\", title: \"One design system\", text: \"Krizaka UI, web and mobile, documented from its code.\" },\n ]}\n closing={{ title: \"Something to build together?\", body: \"Tell us what you need; a person answers within two days.\", actions: <Button variant=\"primary\" size=\"lg\" shape=\"cut\">Contact us</Button> }}\n />\n );\n}\n"
135
135
  }
136
136
  ]
137
137
  },
@@ -162,7 +162,7 @@
162
162
  ],
163
163
  "demo": {
164
164
  "path": "examples/landing-page/krizaka.tsx",
165
- "content": "import { Button } from \"@krizaka/ui/button\";\nimport { LandingPage } from \"@krizaka/ui/landing-page\";\nimport { Meter } from \"@krizaka/ui/meter\";\n\n// TEMPLATE — a company's landing (krizaka.com): the promise beside the product alive, a band of proofs, the features\n// as a bento where the main one takes the room, the closing call. On a phone the window follows the words, the bento\n// is one column, the proofs stack.\nexport default function LandingPageKrizaka() {\n return (\n <LandingPage\n eyebrow=\"Software studio · Montréal\"\n title=\"Products that keep what is yours\"\n lead=\"Krizaka builds sovereign AI and a platform where creators are paid — open source, on your servers or ours.\"\n actions={\n <>\n <Button variant=\"primary\" size=\"lg\" shape=\"cut\" shimmer>See the products</Button>\n <Button variant=\"secondary\" size=\"lg\" shape=\"cut\">Read the docs</Button>\n </>\n }\n visualLabel=\"orazaka.local — console\"\n visual={\n <div className=\"grid gap-3 p-5\">\n <p className=\"font-mono text-xs text-fg-secondary\">$ npx orazaka install</p>\n <p className=\"font-mono text-xs text-fg-success\">✓ 1,284 answers this week, none left the server</p>\n <Meter label=\"Credits\" value={3800} max={12000} valueText=\"3,800 of 12,000\" showLabel />\n </div>\n }\n proofs={[\n { value: \"34\", label: \"public repositories\" },\n { value: \"Apache-2.0\", label: \"every line\" },\n { value: \"0\", label: \"telemetry calls\" },\n ]}\n featuresHeading={{ eyebrow: \"What we build\", title: \"Three products, one way of building\" }}\n features={[\n { id: \"orazaka\", size: \"lg\", title: \"Orazaka — the AI that never leaves home\", text: \"Chat, image, voice and video on your own server, one governed pipeline.\" },\n { id: \"orochia\", title: \"Orochia\", text: \"Creators paid 90 % of what fans spend.\" },\n { id: \"yazakia\", title: \"Yazakia\", text: \"Meet by talking first — coming.\" },\n { id: \"blocks\", size: \"md\", title: \"Open building blocks\", text: \"Users, billing, notifications — on Maven Central and npm.\" },\n { id: \"ui\", size: \"md\", title: \"One design system\", text: \"Krizaka UI, web and mobile, documented from its code.\" },\n ]}\n closing={{ title: \"Something to build together?\", body: \"Tell us what you need; a person answers within two days.\", actions: <Button variant=\"primary\" size=\"lg\" shape=\"cut\">Contact us</Button> }}\n />\n );\n}\n"
165
+ "content": "import { Button } from \"@krizaka/ui/button\";\nimport { LandingPage } from \"@krizaka/ui/landing-page\";\nimport { Meter } from \"@krizaka/ui/meter\";\n\n// TEMPLATE — a company's landing (krizaka.com): the promise beside the product alive, a band of proofs, the features\n// as a bento where the main one takes the room, the closing call. On a phone the window follows the words, the bento\n// is one column, the proofs stack.\nexport default function LandingPageKrizaka() {\n return (\n <LandingPage\n eyebrow=\"Software studio · Montréal\"\n title=\"Products that keep what is yours\"\n lead=\"Krizaka builds sovereign AI and a platform where creators are paid — open source, on your servers or ours.\"\n actions={\n <>\n <Button variant=\"primary\" size=\"lg\" shape=\"cut\" shimmer>See the products</Button>\n <Button variant=\"secondary\" size=\"lg\" shape=\"cut\">Read the docs</Button>\n </>\n }\n visualLabel=\"orazaka.local — console\"\n visual={\n <div className=\"grid gap-3 p-5\">\n <p className=\"font-mono text-xs text-fg-secondary\">$ npx orazaka install</p>\n <p className=\"font-mono text-xs text-fg-success\">✓ 1,284 answers this week, none left the server</p>\n <Meter label=\"Credits\" value={3800} max={12000} valueText=\"3,800 of 12,000\" showLabel />\n </div>\n }\n proofs={[\n { value: \"34\", label: \"public repositories\" },\n { value: \"Apache-2.0\", label: \"every line\" },\n { value: \"0\", label: \"telemetry calls\" },\n ]}\n featuresHeading={{ eyebrow: \"What we build\", title: \"Three products, one way of building\" }}\n features={[\n { id: \"orazaka\", size: \"lg\", title: \"Orazaka — the AI that never leaves home\", text: \"Chat, image, voice and video on your own server, one governed pipeline.\" },\n { id: \"orochia\", title: \"Orochia\", text: \"Creators paid 90 % of what fans spend.\" },\n { id: \"yasakia\", title: \"Yasakia\", text: \"Meet by talking first — coming.\" },\n { id: \"blocks\", size: \"md\", title: \"Open building blocks\", text: \"Users, billing, notifications — on Maven Central and npm.\" },\n { id: \"ui\", size: \"md\", title: \"One design system\", text: \"Krizaka UI, web and mobile, documented from its code.\" },\n ]}\n closing={{ title: \"Something to build together?\", body: \"Tell us what you need; a person answers within two days.\", actions: <Button variant=\"primary\" size=\"lg\" shape=\"cut\">Contact us</Button> }}\n />\n );\n}\n"
166
166
  },
167
167
  "props": [
168
168
  {
@@ -255,7 +255,7 @@
255
255
  "entry": "@krizaka/ui/native",
256
256
  "import": "import { Loader, LoaderGlyph, useDelayedWait } from \"@krizaka/ui/native\";",
257
257
  "differences": [
258
- "`product` (`orochia`, `orazaka`, `yazakia`, `yororis`, `krizaka`) draws the product's animated `ProductMark`; on the web it is the `mark` slot.",
258
+ "`product` (`orochia`, `orazaka`, `yasakia`, `yororis`, `krizaka`) draws the product's animated `ProductMark`; on the web it is the `mark` slot.",
259
259
  "Announced with the platform's announcement (and a polite live region) instead of `role=\"status\"`.",
260
260
  "No `LoadingRegion`: lists show their own skeleton rows (`List loading`).",
261
261
  "`overlay` and `page` cover their parent with the theme's surface at 90 %; no backdrop blur."
@@ -345,7 +345,7 @@
345
345
  "name": "product",
346
346
  "type": "BrandId",
347
347
  "default": null,
348
- "description": "The product whose animated mark waits in place of the Krizaka glyph (`orochia`, `orazaka`, `yazakia`, `yororis`,\n`krizaka`). Still when the system reduces motion; the ending stays the check or the cross.",
348
+ "description": "The product whose animated mark waits in place of the Krizaka glyph (`orochia`, `orazaka`, `yasakia`, `yororis`,\n`krizaka`). Still when the system reduces motion; the ending stays the check or the cross.",
349
349
  "required": false
350
350
  },
351
351
  {
@@ -436,7 +436,7 @@
436
436
  },
437
437
  {
438
438
  "path": "loader/meta.ts",
439
- "content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Loader\",\n summary:\n \"A wait from start to end: nothing for the first instants, then the Krizaka glyph with its words, a percentage and an ETA, held long enough to read, ending on a check or a cross that is drawn and announced — and `LoadingRegion`, which hands a region over to a skeleton of its shape.\",\n status: \"beta\",\n category: \"feedback\",\n platforms: \"both\",\n whenToUse: [\n \"Any wait whose length you do not control (a fetch, a refresh): the delay keeps fast answers from flashing a spinner.\",\n \"A wait that ends in a result worth saying — “12 invoices loaded”, “Could not publish”.\",\n \"Over a region that stays readable while it refreshes (`variant=\\\"overlay\\\"`), or over the whole screen at start-up (`page`).\",\n \"`LoadingRegion` for a card, a list or a panel: a skeleton of its shape while it loads, words when it lasts.\",\n ],\n whenNotToUse: [\n { when: \"Inside the button that started the action: the button draws the same glyph.\", use: \"button\" },\n { when: \"For a long task with steps or a known size the user follows.\", use: \"progress\" },\n { when: \"A tiny wait glyph with nothing else.\", use: \"spinner\" },\n ],\n bestPractices: [\n \"Say what is loading (“Loading your invoices”), not “Loading…”; say how it ended with `successLabel` / `errorLabel`.\",\n \"Brand it in a product: `mark={<OrochiaLogo animated />}` (web) or `product=\\\"orochia\\\"` (native) — the mark replaces the glyph, never the words.\",\n \"Keep the defaults: 250 ms of delay, 600 ms at least once shown — the two numbers that stop flicker.\",\n \"Give an `eta` when you can estimate it (format durations with `@krizaka/intl`): a known wait feels shorter.\",\n \"With `LoadingRegion`, draw the skeleton the shape of the content: nothing moves when it arrives.\",\n ],\n accessibility: {\n keyboard: [],\n notes: [\n \"`role=\\\"status\\\"` (polite) is present from the first render, so its words are announced when the wait shows and again when it ends.\",\n \"`LoadingRegion` sets `aria-busy` on the region while it waits; the skeleton is hidden from assistive technology and the wait is announced once.\",\n \"Under `prefers-reduced-motion` the glyph rests on a still frame and endings do not animate; the delay, the words and the announcements stay.\",\n ],\n },\n related: [\"spinner\", \"skeleton\", \"progress\", \"button\"],\n web: {\n imports: [\"Loader\", \"LoadingRegion\", \"useDelayedWait\"],\n examples: [\n { name: \"fetch-flow\", title: \"No flash, then a result\", description: \"A fast answer shows nothing; a slow one shows the wait, then “12 invoices loaded” with a check, then nothing.\" },\n { name: \"region-handover\", title: \"Hand-over to a skeleton\", description: \"`LoadingRegion`: a skeleton of the card's shape, words when it lasts, the card fading in.\" },\n { name: \"upload-eta\", title: \"Progress and ETA\", description: \"`value` and `eta`: the trace grows, the percentage and the time left read in tabular figures.\" },\n { name: \"overlay\", title: \"Over a region\", description: \"`variant=\\\"overlay\\\"`: the report stays readable behind frosted glass while it refreshes.\" },\n { name: \"endings\", title: \"Endings\", description: \"`status`: a success and a failure, drawn in their colour and said in words.\" },\n { name: \"minimal\", title: \"Minimal\", description: \"A label, nothing else: the defaults do the rest.\" },\n { name: \"branded\", title: \"The product's mark\", description: \"`mark`: Orochia's animated mark in place of the Krizaka glyph; the ending stays the check.\" },\n ],\n },\n native: {\n imports: [\"Loader\", \"LoaderGlyph\", \"useDelayedWait\"],\n differences: [\n \"`product` (`orochia`, `orazaka`, `yazakia`, `yororis`, `krizaka`) draws the product's animated `ProductMark`; on the web it is the `mark` slot.\",\n \"Announced with the platform's announcement (and a polite live region) instead of `role=\\\"status\\\"`.\",\n \"No `LoadingRegion`: lists show their own skeleton rows (`List loading`).\",\n \"`overlay` and `page` cover their parent with the theme's surface at 90 %; no backdrop blur.\",\n ],\n examples: [\n { name: \"job-wait\", title: \"A job's wait\", description: \"Determinate, with the time left, ending on a check and its words.\" },\n { name: \"block\", title: \"Block\", description: \"The centre of a region whose content is on its way.\" },\n { name: \"branded\", title: \"The product's mark\", description: \"`product`: the animated mark of the app waits for you, still under reduced motion.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
439
+ "content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Loader\",\n summary:\n \"A wait from start to end: nothing for the first instants, then the Krizaka glyph with its words, a percentage and an ETA, held long enough to read, ending on a check or a cross that is drawn and announced — and `LoadingRegion`, which hands a region over to a skeleton of its shape.\",\n status: \"beta\",\n category: \"feedback\",\n platforms: \"both\",\n whenToUse: [\n \"Any wait whose length you do not control (a fetch, a refresh): the delay keeps fast answers from flashing a spinner.\",\n \"A wait that ends in a result worth saying — “12 invoices loaded”, “Could not publish”.\",\n \"Over a region that stays readable while it refreshes (`variant=\\\"overlay\\\"`), or over the whole screen at start-up (`page`).\",\n \"`LoadingRegion` for a card, a list or a panel: a skeleton of its shape while it loads, words when it lasts.\",\n ],\n whenNotToUse: [\n { when: \"Inside the button that started the action: the button draws the same glyph.\", use: \"button\" },\n { when: \"For a long task with steps or a known size the user follows.\", use: \"progress\" },\n { when: \"A tiny wait glyph with nothing else.\", use: \"spinner\" },\n ],\n bestPractices: [\n \"Say what is loading (“Loading your invoices”), not “Loading…”; say how it ended with `successLabel` / `errorLabel`.\",\n \"Brand it in a product: `mark={<OrochiaLogo animated />}` (web) or `product=\\\"orochia\\\"` (native) — the mark replaces the glyph, never the words.\",\n \"Keep the defaults: 250 ms of delay, 600 ms at least once shown — the two numbers that stop flicker.\",\n \"Give an `eta` when you can estimate it (format durations with `@krizaka/intl`): a known wait feels shorter.\",\n \"With `LoadingRegion`, draw the skeleton the shape of the content: nothing moves when it arrives.\",\n ],\n accessibility: {\n keyboard: [],\n notes: [\n \"`role=\\\"status\\\"` (polite) is present from the first render, so its words are announced when the wait shows and again when it ends.\",\n \"`LoadingRegion` sets `aria-busy` on the region while it waits; the skeleton is hidden from assistive technology and the wait is announced once.\",\n \"Under `prefers-reduced-motion` the glyph rests on a still frame and endings do not animate; the delay, the words and the announcements stay.\",\n ],\n },\n related: [\"spinner\", \"skeleton\", \"progress\", \"button\"],\n web: {\n imports: [\"Loader\", \"LoadingRegion\", \"useDelayedWait\"],\n examples: [\n { name: \"fetch-flow\", title: \"No flash, then a result\", description: \"A fast answer shows nothing; a slow one shows the wait, then “12 invoices loaded” with a check, then nothing.\" },\n { name: \"region-handover\", title: \"Hand-over to a skeleton\", description: \"`LoadingRegion`: a skeleton of the card's shape, words when it lasts, the card fading in.\" },\n { name: \"upload-eta\", title: \"Progress and ETA\", description: \"`value` and `eta`: the trace grows, the percentage and the time left read in tabular figures.\" },\n { name: \"overlay\", title: \"Over a region\", description: \"`variant=\\\"overlay\\\"`: the report stays readable behind frosted glass while it refreshes.\" },\n { name: \"endings\", title: \"Endings\", description: \"`status`: a success and a failure, drawn in their colour and said in words.\" },\n { name: \"minimal\", title: \"Minimal\", description: \"A label, nothing else: the defaults do the rest.\" },\n { name: \"branded\", title: \"The product's mark\", description: \"`mark`: Orochia's animated mark in place of the Krizaka glyph; the ending stays the check.\" },\n ],\n },\n native: {\n imports: [\"Loader\", \"LoaderGlyph\", \"useDelayedWait\"],\n differences: [\n \"`product` (`orochia`, `orazaka`, `yasakia`, `yororis`, `krizaka`) draws the product's animated `ProductMark`; on the web it is the `mark` slot.\",\n \"Announced with the platform's announcement (and a polite live region) instead of `role=\\\"status\\\"`.\",\n \"No `LoadingRegion`: lists show their own skeleton rows (`List loading`).\",\n \"`overlay` and `page` cover their parent with the theme's surface at 90 %; no backdrop blur.\",\n ],\n examples: [\n { name: \"job-wait\", title: \"A job's wait\", description: \"Determinate, with the time left, ending on a check and its words.\" },\n { name: \"block\", title: \"Block\", description: \"The centre of a region whose content is on its way.\" },\n { name: \"branded\", title: \"The product's mark\", description: \"`product`: the animated mark of the app waits for you, still under reduced motion.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
440
440
  },
441
441
  {
442
442
  "path": "meta.ts",
package/registry/map.json CHANGED
@@ -930,7 +930,7 @@
930
930
  }
931
931
  ],
932
932
  "dependencies": [
933
- "@krizaka/tokens@^3.7.1",
933
+ "@krizaka/tokens@^3.8.0",
934
934
  "@protomaps/basemaps@5.7.2",
935
935
  "tailwind-variants@^3.3.1"
936
936
  ],
@@ -56,7 +56,7 @@
56
56
  "props": [
57
57
  {
58
58
  "component": "MASCOT_BIRDS",
59
- "description": "The Krizaka flock — the geometry of the mascots, drawn by the web `Mascot` (`./mascot.tsx`) and the native one\n(`../native/mascots.tsx`). Five birds that have carried the Krizaka story since the first site (the sentry falcon,\nthe owl that reads, the developer duck, the flamingo that answers, the carrier pigeon), the lovebird that\nintroduces (2026-10, with Yazakia: \"l'inséparable présente\") and the crane that listens (2026-10, with Yororis:\n\"la grue écoute\"), redrawn on one 120 × 120 grid so that any bird can wear any mood.\n\nColours are roles, never fixed: `brand` (the default) paints a bird in the host's accent (`--kz-accent`,\n`--kz-accent-2`), so the same falcon is blue on krizaka.com, orange in Orazaka and violet in Orochia; `own` gives\neach bird the signature palette it has in the Krizaka story (the brand layer's exception, like the marks). Shades\nand highlights are black and white at a low opacity over the role, so they hold in both themes.",
59
+ "description": "The Krizaka flock — the geometry of the mascots, drawn by the web `Mascot` (`./mascot.tsx`) and the native one\n(`../native/mascots.tsx`). Five birds that have carried the Krizaka story since the first site (the sentry falcon,\nthe owl that reads, the developer duck, the flamingo that answers, the carrier pigeon), the lovebird that\nintroduces (2026-10, with Yasakia: \"l'inséparable présente\") and the crane that listens (2026-10, with Yororis:\n\"la grue écoute\"), redrawn on one 120 × 120 grid so that any bird can wear any mood.\n\nColours are roles, never fixed: `brand` (the default) paints a bird in the host's accent (`--kz-accent`,\n`--kz-accent-2`), so the same falcon is blue on krizaka.com, orange in Orazaka and violet in Orochia; `own` gives\neach bird the signature palette it has in the Krizaka story (the brand layer's exception, like the marks). Shades\nand highlights are black and white at a low opacity over the role, so they hold in both themes.",
60
60
  "props": []
61
61
  },
62
62
  {
@@ -157,7 +157,7 @@
157
157
  "description": "The seven birds in the brand colours of the host.",
158
158
  "path": "examples/mascots/flock.tsx",
159
159
  "module": "@krizaka/ui/registry/examples/mascots/flock",
160
- "code": "import { Mascot,MASCOT_BIRDS } from \"@krizaka/ui/mascots\";\n\n// The seven birds in the host's brand colours: blue on Krizaka, orange in Orazaka, violet in Orochia, turquoise in\n// Yazakia, sage in Yororis.\nexport default function MascotFlock() {\n return (\n <div className=\"flex flex-wrap items-end gap-6\">\n {MASCOT_BIRDS.map((bird) => (\n <figure key={bird} className=\"flex flex-col items-center gap-2\">\n <Mascot bird={bird} mood=\"welcome\" size={88} />\n <figcaption className=\"text-xs text-fg-secondary\">{bird}</figcaption>\n </figure>\n ))}\n </div>\n );\n}\n"
160
+ "code": "import { Mascot,MASCOT_BIRDS } from \"@krizaka/ui/mascots\";\n\n// The seven birds in the host's brand colours: blue on Krizaka, orange in Orazaka, violet in Orochia, turquoise in\n// Yasakia, sage in Yororis.\nexport default function MascotFlock() {\n return (\n <div className=\"flex flex-wrap items-end gap-6\">\n {MASCOT_BIRDS.map((bird) => (\n <figure key={bird} className=\"flex flex-col items-center gap-2\">\n <Mascot bird={bird} mood=\"welcome\" size={88} />\n <figcaption className=\"text-xs text-fg-secondary\">{bird}</figcaption>\n </figure>\n ))}\n </div>\n );\n}\n"
161
161
  },
162
162
  {
163
163
  "name": "own-tone",
@@ -327,7 +327,7 @@
327
327
  "files": [
328
328
  {
329
329
  "path": "mascots/geometry.ts",
330
- "content": "/**\n * The Krizaka flock — the geometry of the mascots, drawn by the web `Mascot` (`./mascot.tsx`) and the native one\n * (`../native/mascots.tsx`). Five birds that have carried the Krizaka story since the first site (the sentry falcon,\n * the owl that reads, the developer duck, the flamingo that answers, the carrier pigeon), the lovebird that\n * introduces (2026-10, with Yazakia: \"l'inséparable présente\") and the crane that listens (2026-10, with Yororis:\n * \"la grue écoute\"), redrawn on one 120 × 120 grid so that any bird can wear any mood.\n *\n * Colours are roles, never fixed: `brand` (the default) paints a bird in the host's accent (`--kz-accent`,\n * `--kz-accent-2`), so the same falcon is blue on krizaka.com, orange in Orazaka and violet in Orochia; `own` gives\n * each bird the signature palette it has in the Krizaka story (the brand layer's exception, like the marks). Shades\n * and highlights are black and white at a low opacity over the role, so they hold in both themes.\n */\n\nexport const MASCOT_BIRDS = [\"falcon\", \"owl\", \"duck\", \"flamingo\", \"pigeon\", \"lovebird\", \"crane\"] as const;\nexport type MascotBird = (typeof MASCOT_BIRDS)[number];\n\nexport const MASCOT_MOODS = [\"welcome\", \"thinking\", \"success\", \"empty\", \"error\"] as const;\nexport type MascotMood = (typeof MASCOT_MOODS)[number];\n\nexport type MascotTone = \"brand\" | \"own\";\n\ntype Point = readonly [number, number];\n\nexport interface BirdGeometry {\n /** The ground shadow: centre x, y and radii. */\n readonly shadow: readonly [number, number, number, number];\n /** Legs and feet, stroked in the beak colour. */\n readonly legs: readonly string[];\n /** Drawn behind the body (tail, parcel strings). */\n readonly back?: readonly string[];\n readonly body: string;\n readonly belly: string;\n /** Left then right wing, and the point each one turns around. */\n readonly wings: readonly [{ readonly d: string; readonly pivot: Point }, { readonly d: string; readonly pivot: Point }];\n /** A neck, stroked in the body colour with this width (the flamingo). */\n readonly neck?: { readonly d: string; readonly width: number };\n /** The head: a circle. */\n readonly head: { readonly cx: number; readonly cy: number; readonly r: number };\n /** Ear tufts, a crest, a visor's frame: filled with the detail colour. */\n readonly details: readonly string[];\n /** A band behind the eyes (the falcon's visor), in the page's surface. */\n readonly visor?: { readonly x: number; readonly y: number; readonly w: number; readonly h: number };\n /** Glasses (the duck): stroked rings around the eyes. */\n readonly glasses?: boolean;\n readonly beak: string;\n /** The eyes: centres, the radius of the white, the radius of the pupil (no white when `white` is 0). */\n readonly eyes: { readonly at: readonly Point[]; readonly white: number; readonly pupil: number };\n /** The parcel the pigeon carries: its three faces. */\n readonly parcel?: readonly [string, string, string];\n}\n\nconst mirror = (d: string) => d.replace(/(-?\\d+(?:\\.\\d+)?) (-?\\d+(?:\\.\\d+)?)/g, (_, x: string, y: string) => `${120 - Number(x)} ${y}`);\n\nconst falconWing = \"M29 58 C17 68 19 88 37 86 C31 76 31 66 29 58 Z\";\nconst pigeonWing = \"M36 58 C20 50 16 80 38 84 C34 74 34 66 36 58 Z\";\n\nexport const BIRDS: Readonly<Record<MascotBird, BirdGeometry>> = {\n falcon: {\n shadow: [60, 110, 26, 3.5],\n legs: [\"M51 94 L48 108 M44 108 L52 108\", \"M69 94 L72 108 M68 108 L76 108\"],\n body: \"M30 62 C30 42 90 42 90 62 C90 88 78 98 60 98 C42 98 30 88 30 62 Z\",\n belly: \"M41 66 C41 55 79 55 79 66 C79 82 71 90 60 90 C49 90 41 82 41 66 Z\",\n wings: [\n { d: falconWing, pivot: [29, 58] },\n { d: mirror(falconWing), pivot: [91, 58] },\n ],\n head: { cx: 60, cy: 38, r: 22 },\n details: [\"M46 20 L52 10 L56 19 Z\", \"M74 20 L68 10 L64 19 Z\"],\n visor: { x: 41, y: 29, w: 38, h: 13 },\n beak: \"M54 45 L66 45 L60 57 Z\",\n eyes: { at: [[50, 35.5], [70, 35.5]], white: 0, pupil: 3.2 },\n },\n owl: {\n shadow: [60, 110, 24, 3.5],\n legs: [\"M53 100 L51 107 M47 107 L55 107\", \"M67 100 L69 107 M65 107 L73 107\"],\n body: \"M28 52 C28 20 92 20 92 52 C92 86 82 102 60 102 C38 102 28 86 28 52 Z\",\n belly: \"M42 66 C42 52 78 52 78 66 C78 86 72 94 60 94 C48 94 42 86 42 66 Z\",\n wings: [\n { d: \"M29 58 C18 68 20 88 36 90 C32 78 32 68 29 58 Z\", pivot: [29, 58] },\n { d: mirror(\"M29 58 C18 68 20 88 36 90 C32 78 32 68 29 58 Z\"), pivot: [91, 58] },\n ],\n head: { cx: 60, cy: 42, r: 0 },\n details: [\"M31 20 L47 31 L31 41 Z\", \"M89 20 L73 31 L89 41 Z\"],\n beak: \"M55 50 L65 50 L60 59 Z\",\n eyes: { at: [[47, 41], [73, 41]], white: 10, pupil: 4 },\n },\n duck: {\n shadow: [60, 110, 30, 3.5],\n legs: [],\n back: [\"M88 80 C100 76 104 66 96 62 C98 70 94 74 88 74 Z\"],\n body: \"M26 80 C26 62 94 62 94 80 C94 100 82 106 60 106 C38 106 26 100 26 80 Z\",\n belly: \"M38 84 C38 72 82 72 82 84 C82 96 74 101 60 101 C46 101 38 96 38 84 Z\",\n wings: [\n { d: \"M27 74 C14 80 18 98 35 96 C31 88 29 80 27 74 Z\", pivot: [27, 74] },\n { d: mirror(\"M27 74 C14 80 18 98 35 96 C31 88 29 80 27 74 Z\"), pivot: [93, 74] },\n ],\n head: { cx: 60, cy: 42, r: 23 },\n details: [\"M57 20 C54 11 63 8 66 14 C62 13 60 16 61 20 Z\"],\n glasses: true,\n beak: \"M43 51 C43 46 55 45 60 45 C65 45 77 46 77 51 C77 56 66 60 60 60 C54 60 43 56 43 51 Z\",\n eyes: { at: [[51, 37], [69, 37]], white: 0, pupil: 2.6 },\n },\n flamingo: {\n shadow: [60, 110, 20, 3],\n legs: [\"M56 86 L55 97 L58 108 M53 108 L62 108\", \"M65 86 L66 108 M62 108 L71 108\"],\n body: \"M38 70 C38 54 88 54 88 70 C88 86 76 90 62 90 C48 90 38 86 38 70 Z\",\n belly: \"M46 72 C46 63 80 63 80 72 C80 82 72 85 63 85 C54 85 46 82 46 72 Z\",\n wings: [\n { d: \"M42 64 C30 68 32 84 47 84 C43 76 43 70 42 64 Z\", pivot: [42, 64] },\n { d: \"M84 64 C96 68 94 84 79 84 C83 76 83 70 84 64 Z\", pivot: [84, 64] },\n ],\n neck: { d: \"M58 60 C58 42 40 34 46 22\", width: 7 },\n head: { cx: 48, cy: 18, r: 11 },\n details: [],\n beak: \"M38 16 C28 18 29 28 24 33 C33 28 38 23 40 20 Z\",\n eyes: { at: [[46, 15]], white: 3.2, pupil: 1.8 },\n },\n pigeon: {\n shadow: [60, 112, 22, 3],\n legs: [\"M52 94 L51 99 M48 99 L54 99\", \"M68 94 L69 99 M66 99 L72 99\"],\n back: [\"M53 98 L52 103\", \"M67 98 L68 103\", \"M30 68 C16 72 14 62 28 56 C17 57 15 49 32 48 Z\"],\n body: \"M34 64 C34 44 86 44 86 64 C86 86 74 96 60 96 C46 96 34 86 34 64 Z\",\n belly: \"M43 68 C43 57 77 57 77 68 C77 82 70 88 60 88 C50 88 43 82 43 68 Z\",\n wings: [\n { d: pigeonWing, pivot: [36, 58] },\n { d: mirror(pigeonWing), pivot: [84, 58] },\n ],\n head: { cx: 60, cy: 36, r: 19 },\n details: [\"M54 18 C56 12 64 12 66 18 C63 16 57 16 54 18 Z\"],\n beak: \"M55 41 L65 41 L60 50 Z\",\n eyes: { at: [[52, 33], [68, 33]], white: 5, pupil: 2.4 },\n parcel: [\"M60 100 L71 105 L60 110 L49 105 Z\", \"M49 105 L60 110 L60 118 L49 113 Z\", \"M71 105 L60 110 L60 118 L71 113 Z\"],\n },\n /**\n * The lovebird — the inseparable that introduces two people. A plump little parrot: a short tail, a round head\n * with its coloured face (the detail colour), the white eye-rings of the species and a short hooked beak.\n */\n lovebird: {\n shadow: [60, 110, 23, 3.5],\n legs: [\"M53 96 L52 106 M48 106 L56 106\", \"M67 96 L68 106 M64 106 L72 106\"],\n back: [\"M74 90 C82 98 88 104 95 103 C91 98 86 91 82 84 Z\"],\n body: \"M32 66 C32 46 88 46 88 66 C88 90 76 100 60 100 C44 100 32 90 32 66 Z\",\n belly: \"M42 70 C42 59 78 59 78 70 C78 85 70 92 60 92 C50 92 42 85 42 70 Z\",\n wings: [\n { d: \"M33 60 C20 68 22 88 40 90 C35 80 34 70 33 60 Z\", pivot: [33, 60] },\n { d: mirror(\"M33 60 C20 68 22 88 40 90 C35 80 34 70 33 60 Z\"), pivot: [87, 60] },\n ],\n head: { cx: 60, cy: 38, r: 21 },\n details: [\"M43 40 C42 28 51 22 60 22 C69 22 78 28 77 40 C76 50 68 55 60 55 C52 55 44 50 43 40 Z\"],\n beak: \"M55 44 C55 40 65 40 65 44 C65 50 62 54 60 55 C58 54 55 50 55 44 Z\",\n eyes: { at: [[51, 36], [69, 36]], white: 4.6, pupil: 2.4 },\n },\n /**\n * The crane — the one that listens: posed, unhurried, drawn in one line. A tall wader seen in profile, standing still\n * on two straight legs, the neck a single stroke up to a small head with its crown (the detail colour) and a long,\n * straight beak; the folded wings low on its back. The flamingo bends and answers; the crane stands and listens.\n */\n crane: {\n shadow: [62, 110, 20, 3],\n legs: [\"M56 87 L55 108 M51 108 L59 108\", \"M67 87 L68 108 M64 108 L73 108\"],\n body: \"M40 66 C38 54 84 54 86 68 C88 82 76 88 62 88 C48 88 40 80 40 66 Z\",\n belly: \"M48 70 C48 62 78 62 79 70 C80 79 72 84 63 84 C54 84 48 79 48 70 Z\",\n wings: [\n { d: \"M44 62 C33 68 35 82 49 83 C45 76 45 69 44 62 Z\", pivot: [44, 62] },\n { d: \"M82 62 C93 67 96 82 80 84 C83 76 83 69 82 62 Z\", pivot: [82, 62] },\n ],\n neck: { d: \"M52 62 C48 47 52 37 48 26\", width: 6 },\n head: { cx: 47, cy: 21, r: 8.5 },\n details: [\"M41 16.5 C42 11 52 11 53 16.5 C50 14.6 44 14.6 41 16.5 Z\"],\n beak: \"M40.5 18.5 L19 22.5 L40.5 25.5 Z\",\n eyes: { at: [[45.5, 19.5]], white: 2.8, pupil: 1.6 },\n },\n};\n\n/** What a mood adds around the bird: a badge, a thought, an empty tray. */\nexport const MOOD_PARTS = {\n /** The badge of `success` and `error`, top right. */\n badge: { cx: 98, cy: 22, r: 11 },\n check: \"M92.5 22.5 L96.8 26.6 L103.6 18.4\",\n bang: { line: \"M98 15.5 L98 23.5\", dot: [98, 28] as Point },\n /** `thinking`: three dots rising to the right of the head. */\n dots: [\n [88, 26, 2.6],\n [96, 19, 3.2],\n [105, 11, 3.8],\n ] as const,\n /** `empty`: an open tray beside the bird. */\n tray: \"M90 96 L110 96 L107 108 L93 108 Z\",\n /** `success`: two sparkles. */\n sparkles: [\"M16 26 L18 31 L23 33 L18 35 L16 40 L14 35 L9 33 L14 31 Z\", \"M104 52 L105.2 55 L108 56 L105.2 57 L104 60 L102.8 57 L100 56 L102.8 55 Z\"],\n} as const;\n\n/** The happy eye of `success`: an arch. */\nexport const archEye = ([x, y]: Point, r: number) => `M${x - r} ${y + r * 0.45} Q${x} ${y - r * 1.15} ${x + r} ${y + r * 0.45}`;\n/** The lowered lid of `empty`: a line across the eye. */\nexport const lidEye = ([x, y]: Point, r: number) => `M${x - r} ${y + 0.4} L${x + r} ${y + 0.4}`;\n/** The heavy lid of `empty` over an eye with a white: its upper half. */\nexport const upperLid = ([x, y]: Point, r: number) => `M${x - r} ${y} A${r} ${r} 0 0 1 ${x + r} ${y} Z`;\n/** The worried brow of `error`, above one eye (`side` -1 left, 1 right). */\nexport const brow = ([x, y]: Point, r: number, side: number) =>\n `M${x - r * 1.1} ${y - r * 1.25 - (side < 0 ? 0 : r * 0.7)} L${x + r * 1.1} ${y - r * 1.5 - (side < 0 ? r * 0.7 : 0)}`;\n\nexport interface MascotPalette {\n /** Top and bottom of the body gradient. */\n readonly from: string;\n readonly to: string;\n /** Wings and details (tufts, crest). */\n readonly wing: string;\n readonly detail: string;\n /** Beak and feet. */\n readonly beak: string;\n /** The pupils (and the falcon's visor lights). */\n readonly eye: string;\n}\n\n/** The signature palettes of the Krizaka story (`tone=\"own\"`), from the first drawings of each bird. */\nexport const OWN_PALETTES: Readonly<Record<MascotBird, MascotPalette>> = {\n falcon: { from: \"#ff9f00\", to: \"#ff2a00\", wing: \"#d84315\", detail: \"#b4320d\", beak: \"#ffb300\", eye: \"#00c8d4\" },\n owl: { from: \"#a78bfa\", to: \"#6d28d9\", wing: \"#7c3aed\", detail: \"#5b21b6\", beak: \"#fbbf24\", eye: \"#1f2937\" },\n duck: { from: \"#f43f5e\", to: \"#be123c\", wing: \"#db2777\", detail: \"#9f1239\", beak: \"#fbbf24\", eye: \"#1f2937\" },\n flamingo: { from: \"#f9a8d4\", to: \"#db2777\", wing: \"#ec4899\", detail: \"#be185d\", beak: \"#fbbf24\", eye: \"#1f2937\" },\n pigeon: { from: \"#22d3ee\", to: \"#6366f1\", wing: \"#a855f7\", detail: \"#4338ca\", beak: \"#f59e0b\", eye: \"#1f2937\" },\n lovebird: { from: \"#6ee7b7\", to: \"#059669\", wing: \"#047857\", detail: \"#fb7185\", beak: \"#f97316\", eye: \"#1f2937\" },\n // The sandhill crane (grue du Canada): sand-grey plumage, its red crown, dark legs and beak.\n crane: { from: \"#ebe3d6\", to: \"#9c8f80\", wing: \"#7d7266\", detail: \"#dc2626\", beak: \"#44403c\", eye: \"#1f2937\" },\n};\n\n/** Fixed light and shade, laid at a low opacity over a role (they read on both themes). */\nexport const LIGHT = \"#ffffff\";\nexport const SHADE = \"#000000\";\n/** The parcel's faces (pigeon). */\nexport const PARCEL = [\"#f59e0b\", \"#d97706\", \"#b45309\"] as const;\n"
330
+ "content": "/**\n * The Krizaka flock — the geometry of the mascots, drawn by the web `Mascot` (`./mascot.tsx`) and the native one\n * (`../native/mascots.tsx`). Five birds that have carried the Krizaka story since the first site (the sentry falcon,\n * the owl that reads, the developer duck, the flamingo that answers, the carrier pigeon), the lovebird that\n * introduces (2026-10, with Yasakia: \"l'inséparable présente\") and the crane that listens (2026-10, with Yororis:\n * \"la grue écoute\"), redrawn on one 120 × 120 grid so that any bird can wear any mood.\n *\n * Colours are roles, never fixed: `brand` (the default) paints a bird in the host's accent (`--kz-accent`,\n * `--kz-accent-2`), so the same falcon is blue on krizaka.com, orange in Orazaka and violet in Orochia; `own` gives\n * each bird the signature palette it has in the Krizaka story (the brand layer's exception, like the marks). Shades\n * and highlights are black and white at a low opacity over the role, so they hold in both themes.\n */\n\nexport const MASCOT_BIRDS = [\"falcon\", \"owl\", \"duck\", \"flamingo\", \"pigeon\", \"lovebird\", \"crane\"] as const;\nexport type MascotBird = (typeof MASCOT_BIRDS)[number];\n\nexport const MASCOT_MOODS = [\"welcome\", \"thinking\", \"success\", \"empty\", \"error\"] as const;\nexport type MascotMood = (typeof MASCOT_MOODS)[number];\n\nexport type MascotTone = \"brand\" | \"own\";\n\ntype Point = readonly [number, number];\n\nexport interface BirdGeometry {\n /** The ground shadow: centre x, y and radii. */\n readonly shadow: readonly [number, number, number, number];\n /** Legs and feet, stroked in the beak colour. */\n readonly legs: readonly string[];\n /** Drawn behind the body (tail, parcel strings). */\n readonly back?: readonly string[];\n readonly body: string;\n readonly belly: string;\n /** Left then right wing, and the point each one turns around. */\n readonly wings: readonly [{ readonly d: string; readonly pivot: Point }, { readonly d: string; readonly pivot: Point }];\n /** A neck, stroked in the body colour with this width (the flamingo). */\n readonly neck?: { readonly d: string; readonly width: number };\n /** The head: a circle. */\n readonly head: { readonly cx: number; readonly cy: number; readonly r: number };\n /** Ear tufts, a crest, a visor's frame: filled with the detail colour. */\n readonly details: readonly string[];\n /** A band behind the eyes (the falcon's visor), in the page's surface. */\n readonly visor?: { readonly x: number; readonly y: number; readonly w: number; readonly h: number };\n /** Glasses (the duck): stroked rings around the eyes. */\n readonly glasses?: boolean;\n readonly beak: string;\n /** The eyes: centres, the radius of the white, the radius of the pupil (no white when `white` is 0). */\n readonly eyes: { readonly at: readonly Point[]; readonly white: number; readonly pupil: number };\n /** The parcel the pigeon carries: its three faces. */\n readonly parcel?: readonly [string, string, string];\n}\n\nconst mirror = (d: string) => d.replace(/(-?\\d+(?:\\.\\d+)?) (-?\\d+(?:\\.\\d+)?)/g, (_, x: string, y: string) => `${120 - Number(x)} ${y}`);\n\nconst falconWing = \"M29 58 C17 68 19 88 37 86 C31 76 31 66 29 58 Z\";\nconst pigeonWing = \"M36 58 C20 50 16 80 38 84 C34 74 34 66 36 58 Z\";\n\nexport const BIRDS: Readonly<Record<MascotBird, BirdGeometry>> = {\n falcon: {\n shadow: [60, 110, 26, 3.5],\n legs: [\"M51 94 L48 108 M44 108 L52 108\", \"M69 94 L72 108 M68 108 L76 108\"],\n body: \"M30 62 C30 42 90 42 90 62 C90 88 78 98 60 98 C42 98 30 88 30 62 Z\",\n belly: \"M41 66 C41 55 79 55 79 66 C79 82 71 90 60 90 C49 90 41 82 41 66 Z\",\n wings: [\n { d: falconWing, pivot: [29, 58] },\n { d: mirror(falconWing), pivot: [91, 58] },\n ],\n head: { cx: 60, cy: 38, r: 22 },\n details: [\"M46 20 L52 10 L56 19 Z\", \"M74 20 L68 10 L64 19 Z\"],\n visor: { x: 41, y: 29, w: 38, h: 13 },\n beak: \"M54 45 L66 45 L60 57 Z\",\n eyes: { at: [[50, 35.5], [70, 35.5]], white: 0, pupil: 3.2 },\n },\n owl: {\n shadow: [60, 110, 24, 3.5],\n legs: [\"M53 100 L51 107 M47 107 L55 107\", \"M67 100 L69 107 M65 107 L73 107\"],\n body: \"M28 52 C28 20 92 20 92 52 C92 86 82 102 60 102 C38 102 28 86 28 52 Z\",\n belly: \"M42 66 C42 52 78 52 78 66 C78 86 72 94 60 94 C48 94 42 86 42 66 Z\",\n wings: [\n { d: \"M29 58 C18 68 20 88 36 90 C32 78 32 68 29 58 Z\", pivot: [29, 58] },\n { d: mirror(\"M29 58 C18 68 20 88 36 90 C32 78 32 68 29 58 Z\"), pivot: [91, 58] },\n ],\n head: { cx: 60, cy: 42, r: 0 },\n details: [\"M31 20 L47 31 L31 41 Z\", \"M89 20 L73 31 L89 41 Z\"],\n beak: \"M55 50 L65 50 L60 59 Z\",\n eyes: { at: [[47, 41], [73, 41]], white: 10, pupil: 4 },\n },\n duck: {\n shadow: [60, 110, 30, 3.5],\n legs: [],\n back: [\"M88 80 C100 76 104 66 96 62 C98 70 94 74 88 74 Z\"],\n body: \"M26 80 C26 62 94 62 94 80 C94 100 82 106 60 106 C38 106 26 100 26 80 Z\",\n belly: \"M38 84 C38 72 82 72 82 84 C82 96 74 101 60 101 C46 101 38 96 38 84 Z\",\n wings: [\n { d: \"M27 74 C14 80 18 98 35 96 C31 88 29 80 27 74 Z\", pivot: [27, 74] },\n { d: mirror(\"M27 74 C14 80 18 98 35 96 C31 88 29 80 27 74 Z\"), pivot: [93, 74] },\n ],\n head: { cx: 60, cy: 42, r: 23 },\n details: [\"M57 20 C54 11 63 8 66 14 C62 13 60 16 61 20 Z\"],\n glasses: true,\n beak: \"M43 51 C43 46 55 45 60 45 C65 45 77 46 77 51 C77 56 66 60 60 60 C54 60 43 56 43 51 Z\",\n eyes: { at: [[51, 37], [69, 37]], white: 0, pupil: 2.6 },\n },\n flamingo: {\n shadow: [60, 110, 20, 3],\n legs: [\"M56 86 L55 97 L58 108 M53 108 L62 108\", \"M65 86 L66 108 M62 108 L71 108\"],\n body: \"M38 70 C38 54 88 54 88 70 C88 86 76 90 62 90 C48 90 38 86 38 70 Z\",\n belly: \"M46 72 C46 63 80 63 80 72 C80 82 72 85 63 85 C54 85 46 82 46 72 Z\",\n wings: [\n { d: \"M42 64 C30 68 32 84 47 84 C43 76 43 70 42 64 Z\", pivot: [42, 64] },\n { d: \"M84 64 C96 68 94 84 79 84 C83 76 83 70 84 64 Z\", pivot: [84, 64] },\n ],\n neck: { d: \"M58 60 C58 42 40 34 46 22\", width: 7 },\n head: { cx: 48, cy: 18, r: 11 },\n details: [],\n beak: \"M38 16 C28 18 29 28 24 33 C33 28 38 23 40 20 Z\",\n eyes: { at: [[46, 15]], white: 3.2, pupil: 1.8 },\n },\n pigeon: {\n shadow: [60, 112, 22, 3],\n legs: [\"M52 94 L51 99 M48 99 L54 99\", \"M68 94 L69 99 M66 99 L72 99\"],\n back: [\"M53 98 L52 103\", \"M67 98 L68 103\", \"M30 68 C16 72 14 62 28 56 C17 57 15 49 32 48 Z\"],\n body: \"M34 64 C34 44 86 44 86 64 C86 86 74 96 60 96 C46 96 34 86 34 64 Z\",\n belly: \"M43 68 C43 57 77 57 77 68 C77 82 70 88 60 88 C50 88 43 82 43 68 Z\",\n wings: [\n { d: pigeonWing, pivot: [36, 58] },\n { d: mirror(pigeonWing), pivot: [84, 58] },\n ],\n head: { cx: 60, cy: 36, r: 19 },\n details: [\"M54 18 C56 12 64 12 66 18 C63 16 57 16 54 18 Z\"],\n beak: \"M55 41 L65 41 L60 50 Z\",\n eyes: { at: [[52, 33], [68, 33]], white: 5, pupil: 2.4 },\n parcel: [\"M60 100 L71 105 L60 110 L49 105 Z\", \"M49 105 L60 110 L60 118 L49 113 Z\", \"M71 105 L60 110 L60 118 L71 113 Z\"],\n },\n /**\n * The lovebird — the inseparable that introduces two people. A plump little parrot: a short tail, a round head\n * with its coloured face (the detail colour), the white eye-rings of the species and a short hooked beak.\n */\n lovebird: {\n shadow: [60, 110, 23, 3.5],\n legs: [\"M53 96 L52 106 M48 106 L56 106\", \"M67 96 L68 106 M64 106 L72 106\"],\n back: [\"M74 90 C82 98 88 104 95 103 C91 98 86 91 82 84 Z\"],\n body: \"M32 66 C32 46 88 46 88 66 C88 90 76 100 60 100 C44 100 32 90 32 66 Z\",\n belly: \"M42 70 C42 59 78 59 78 70 C78 85 70 92 60 92 C50 92 42 85 42 70 Z\",\n wings: [\n { d: \"M33 60 C20 68 22 88 40 90 C35 80 34 70 33 60 Z\", pivot: [33, 60] },\n { d: mirror(\"M33 60 C20 68 22 88 40 90 C35 80 34 70 33 60 Z\"), pivot: [87, 60] },\n ],\n head: { cx: 60, cy: 38, r: 21 },\n details: [\"M43 40 C42 28 51 22 60 22 C69 22 78 28 77 40 C76 50 68 55 60 55 C52 55 44 50 43 40 Z\"],\n beak: \"M55 44 C55 40 65 40 65 44 C65 50 62 54 60 55 C58 54 55 50 55 44 Z\",\n eyes: { at: [[51, 36], [69, 36]], white: 4.6, pupil: 2.4 },\n },\n /**\n * The crane — the one that listens: posed, unhurried, drawn in one line. A tall wader seen in profile, standing still\n * on two straight legs, the neck a single stroke up to a small head with its crown (the detail colour) and a long,\n * straight beak; the folded wings low on its back. The flamingo bends and answers; the crane stands and listens.\n */\n crane: {\n shadow: [62, 110, 20, 3],\n legs: [\"M56 87 L55 108 M51 108 L59 108\", \"M67 87 L68 108 M64 108 L73 108\"],\n body: \"M40 66 C38 54 84 54 86 68 C88 82 76 88 62 88 C48 88 40 80 40 66 Z\",\n belly: \"M48 70 C48 62 78 62 79 70 C80 79 72 84 63 84 C54 84 48 79 48 70 Z\",\n wings: [\n { d: \"M44 62 C33 68 35 82 49 83 C45 76 45 69 44 62 Z\", pivot: [44, 62] },\n { d: \"M82 62 C93 67 96 82 80 84 C83 76 83 69 82 62 Z\", pivot: [82, 62] },\n ],\n neck: { d: \"M52 62 C48 47 52 37 48 26\", width: 6 },\n head: { cx: 47, cy: 21, r: 8.5 },\n details: [\"M41 16.5 C42 11 52 11 53 16.5 C50 14.6 44 14.6 41 16.5 Z\"],\n beak: \"M40.5 18.5 L19 22.5 L40.5 25.5 Z\",\n eyes: { at: [[45.5, 19.5]], white: 2.8, pupil: 1.6 },\n },\n};\n\n/** What a mood adds around the bird: a badge, a thought, an empty tray. */\nexport const MOOD_PARTS = {\n /** The badge of `success` and `error`, top right. */\n badge: { cx: 98, cy: 22, r: 11 },\n check: \"M92.5 22.5 L96.8 26.6 L103.6 18.4\",\n bang: { line: \"M98 15.5 L98 23.5\", dot: [98, 28] as Point },\n /** `thinking`: three dots rising to the right of the head. */\n dots: [\n [88, 26, 2.6],\n [96, 19, 3.2],\n [105, 11, 3.8],\n ] as const,\n /** `empty`: an open tray beside the bird. */\n tray: \"M90 96 L110 96 L107 108 L93 108 Z\",\n /** `success`: two sparkles. */\n sparkles: [\"M16 26 L18 31 L23 33 L18 35 L16 40 L14 35 L9 33 L14 31 Z\", \"M104 52 L105.2 55 L108 56 L105.2 57 L104 60 L102.8 57 L100 56 L102.8 55 Z\"],\n} as const;\n\n/** The happy eye of `success`: an arch. */\nexport const archEye = ([x, y]: Point, r: number) => `M${x - r} ${y + r * 0.45} Q${x} ${y - r * 1.15} ${x + r} ${y + r * 0.45}`;\n/** The lowered lid of `empty`: a line across the eye. */\nexport const lidEye = ([x, y]: Point, r: number) => `M${x - r} ${y + 0.4} L${x + r} ${y + 0.4}`;\n/** The heavy lid of `empty` over an eye with a white: its upper half. */\nexport const upperLid = ([x, y]: Point, r: number) => `M${x - r} ${y} A${r} ${r} 0 0 1 ${x + r} ${y} Z`;\n/** The worried brow of `error`, above one eye (`side` -1 left, 1 right). */\nexport const brow = ([x, y]: Point, r: number, side: number) =>\n `M${x - r * 1.1} ${y - r * 1.25 - (side < 0 ? 0 : r * 0.7)} L${x + r * 1.1} ${y - r * 1.5 - (side < 0 ? r * 0.7 : 0)}`;\n\nexport interface MascotPalette {\n /** Top and bottom of the body gradient. */\n readonly from: string;\n readonly to: string;\n /** Wings and details (tufts, crest). */\n readonly wing: string;\n readonly detail: string;\n /** Beak and feet. */\n readonly beak: string;\n /** The pupils (and the falcon's visor lights). */\n readonly eye: string;\n}\n\n/** The signature palettes of the Krizaka story (`tone=\"own\"`), from the first drawings of each bird. */\nexport const OWN_PALETTES: Readonly<Record<MascotBird, MascotPalette>> = {\n falcon: { from: \"#ff9f00\", to: \"#ff2a00\", wing: \"#d84315\", detail: \"#b4320d\", beak: \"#ffb300\", eye: \"#00c8d4\" },\n owl: { from: \"#a78bfa\", to: \"#6d28d9\", wing: \"#7c3aed\", detail: \"#5b21b6\", beak: \"#fbbf24\", eye: \"#1f2937\" },\n duck: { from: \"#f43f5e\", to: \"#be123c\", wing: \"#db2777\", detail: \"#9f1239\", beak: \"#fbbf24\", eye: \"#1f2937\" },\n flamingo: { from: \"#f9a8d4\", to: \"#db2777\", wing: \"#ec4899\", detail: \"#be185d\", beak: \"#fbbf24\", eye: \"#1f2937\" },\n pigeon: { from: \"#22d3ee\", to: \"#6366f1\", wing: \"#a855f7\", detail: \"#4338ca\", beak: \"#f59e0b\", eye: \"#1f2937\" },\n lovebird: { from: \"#6ee7b7\", to: \"#059669\", wing: \"#047857\", detail: \"#fb7185\", beak: \"#f97316\", eye: \"#1f2937\" },\n // The sandhill crane (grue du Canada): sand-grey plumage, its red crown, dark legs and beak.\n crane: { from: \"#ebe3d6\", to: \"#9c8f80\", wing: \"#7d7266\", detail: \"#dc2626\", beak: \"#44403c\", eye: \"#1f2937\" },\n};\n\n/** Fixed light and shade, laid at a low opacity over a role (they read on both themes). */\nexport const LIGHT = \"#ffffff\";\nexport const SHADE = \"#000000\";\n/** The parcel's faces (pigeon). */\nexport const PARCEL = [\"#f59e0b\", \"#d97706\", \"#b45309\"] as const;\n"
331
331
  },
332
332
  {
333
333
  "path": "mascots/index.ts",
@@ -363,7 +363,7 @@
363
363
  "props": [
364
364
  {
365
365
  "component": "MASCOT_BIRDS",
366
- "description": "The Krizaka flock — the geometry of the mascots, drawn by the web `Mascot` (`./mascot.tsx`) and the native one\n(`../native/mascots.tsx`). Five birds that have carried the Krizaka story since the first site (the sentry falcon,\nthe owl that reads, the developer duck, the flamingo that answers, the carrier pigeon), the lovebird that\nintroduces (2026-10, with Yazakia: \"l'inséparable présente\") and the crane that listens (2026-10, with Yororis:\n\"la grue écoute\"), redrawn on one 120 × 120 grid so that any bird can wear any mood.\n\nColours are roles, never fixed: `brand` (the default) paints a bird in the host's accent (`--kz-accent`,\n`--kz-accent-2`), so the same falcon is blue on krizaka.com, orange in Orazaka and violet in Orochia; `own` gives\neach bird the signature palette it has in the Krizaka story (the brand layer's exception, like the marks). Shades\nand highlights are black and white at a low opacity over the role, so they hold in both themes.",
366
+ "description": "The Krizaka flock — the geometry of the mascots, drawn by the web `Mascot` (`./mascot.tsx`) and the native one\n(`../native/mascots.tsx`). Five birds that have carried the Krizaka story since the first site (the sentry falcon,\nthe owl that reads, the developer duck, the flamingo that answers, the carrier pigeon), the lovebird that\nintroduces (2026-10, with Yasakia: \"l'inséparable présente\") and the crane that listens (2026-10, with Yororis:\n\"la grue écoute\"), redrawn on one 120 × 120 grid so that any bird can wear any mood.\n\nColours are roles, never fixed: `brand` (the default) paints a bird in the host's accent (`--kz-accent`,\n`--kz-accent-2`), so the same falcon is blue on krizaka.com, orange in Orazaka and violet in Orochia; `own` gives\neach bird the signature palette it has in the Krizaka story (the brand layer's exception, like the marks). Shades\nand highlights are black and white at a low opacity over the role, so they hold in both themes.",
367
367
  "props": []
368
368
  },
369
369
  {
@@ -9,7 +9,7 @@
9
9
  "category": "templates",
10
10
  "platforms": "web",
11
11
  "whenToUse": [
12
- "The overview of each product (Orazaka, Orochia, Yazakia).",
12
+ "The overview of each product (Orazaka, Orochia, Yasakia).",
13
13
  "A building block's page that argues its decisions."
14
14
  ],
15
15
  "whenNotToUse": [
@@ -182,7 +182,7 @@
182
182
  },
183
183
  {
184
184
  "path": "product-page/meta.ts",
185
- "content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Product page\",\n summary: \"A product's overview in its brand: split hero with facts and the product alive, the traps it removes as compact argument cards, its decisions with their cost, the promise a bird keeps, the closing call.\",\n status: \"beta\",\n category: \"templates\",\n platforms: \"web\",\n whenToUse: [\"The overview of each product (Orazaka, Orochia, Yazakia).\", \"A building block's page that argues its decisions.\"],\n whenNotToUse: [\n { when: \"For the whole company's home.\", use: \"landing-page\" },\n { when: \"For the steps of how it works.\", use: \"how-it-works-page\" },\n ],\n bestPractices: [\"The traps in one line each; the long version on the page `href` leads to.\", \"Say what every decision costs: a decision without its cost is an advertisement.\", \"Pass `brand`: the page wears the product's colour.\", \"Words and content arrive as props; the motion is the platform's (`[data-reveal]`, still under reduced motion).\"],\n accessibility: {\n keyboard: [],\n notes: [\"One `h1` in the hero; each card an `article` named by its title.\", \"Decisions are an ordered list, each part labelled in words.\"],\n },\n related: [\"argument-card\", \"decision-list\", \"landing-page\"],\n web: {\n imports: [\"ProductPage\"],\n examples: [\n { name: \"orazaka\", title: \"Orazaka\", description: \"The sovereign AI engine's overview, in its orange.\", template: true, purpose: \"convince\", why: \"A visitor understands what a product does, the traps it avoids and the decisions behind it, then acts.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
185
+ "content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Product page\",\n summary: \"A product's overview in its brand: split hero with facts and the product alive, the traps it removes as compact argument cards, its decisions with their cost, the promise a bird keeps, the closing call.\",\n status: \"beta\",\n category: \"templates\",\n platforms: \"web\",\n whenToUse: [\"The overview of each product (Orazaka, Orochia, Yasakia).\", \"A building block's page that argues its decisions.\"],\n whenNotToUse: [\n { when: \"For the whole company's home.\", use: \"landing-page\" },\n { when: \"For the steps of how it works.\", use: \"how-it-works-page\" },\n ],\n bestPractices: [\"The traps in one line each; the long version on the page `href` leads to.\", \"Say what every decision costs: a decision without its cost is an advertisement.\", \"Pass `brand`: the page wears the product's colour.\", \"Words and content arrive as props; the motion is the platform's (`[data-reveal]`, still under reduced motion).\"],\n accessibility: {\n keyboard: [],\n notes: [\"One `h1` in the hero; each card an `article` named by its title.\", \"Decisions are an ordered list, each part labelled in words.\"],\n },\n related: [\"argument-card\", \"decision-list\", \"landing-page\"],\n web: {\n imports: [\"ProductPage\"],\n examples: [\n { name: \"orazaka\", title: \"Orazaka\", description: \"The sovereign AI engine's overview, in its orange.\", template: true, purpose: \"convince\", why: \"A visitor understands what a product does, the traps it avoids and the decisions behind it, then acts.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
186
186
  },
187
187
  {
188
188
  "path": "product-page/product-page.tsx",
@@ -212,7 +212,7 @@
212
212
  "description": "In a dating app's brand: what two people share, never a score alone.",
213
213
  "path": "examples/profile-card/match.tsx",
214
214
  "module": "@krizaka/ui/registry/examples/profile-card/match",
215
- "code": "import { Avatar } from \"@krizaka/ui/avatar\";\nimport { ProfileCard } from \"@krizaka/ui/profile-card\";\n\n// A match in a dating app: what you share, in words — never a score alone.\nexport default function ProfileCardMatch() {\n return (\n <ProfileCard\n brand=\"yazakia\"\n visual={<Avatar src=\"https://krizaka-assets.b-cdn.net/site/people/ui/camille-256.dc2943029a.webp\" alt=\"Camille Roy\" fallback=\"CR\" size=\"xl\" />}\n visualSize={88}\n name=\"Camille, 29\"\n stats={[\n { label: \"Interests in common\", value: 4, max: 6, valueText: \"4 of 6\" },\n { label: \"Answers that match\", value: 7, max: 10, valueText: \"7 of 10\" },\n ]}\n caption=\"You both answered “a slow Sunday market” first.\"\n />\n );\n}\n"
215
+ "code": "import { Avatar } from \"@krizaka/ui/avatar\";\nimport { ProfileCard } from \"@krizaka/ui/profile-card\";\n\n// A match in a dating app: what you share, in words — never a score alone.\nexport default function ProfileCardMatch() {\n return (\n <ProfileCard\n brand=\"yasakia\"\n visual={<Avatar src=\"https://krizaka-assets.b-cdn.net/site/people/ui/camille-256.dc2943029a.webp\" alt=\"Camille Roy\" fallback=\"CR\" size=\"xl\" />}\n visualSize={88}\n name=\"Camille, 29\"\n stats={[\n { label: \"Interests in common\", value: 4, max: 6, valueText: \"4 of 6\" },\n { label: \"Answers that match\", value: 7, max: 10, valueText: \"7 of 10\" },\n ]}\n caption=\"You both answered “a slow Sunday market” first.\"\n />\n );\n}\n"
216
216
  },
217
217
  {
218
218
  "name": "arcade",
@@ -65,7 +65,7 @@
65
65
  "name": "title",
66
66
  "type": "ReactNode",
67
67
  "default": null,
68
- "description": "The page's `h1` (`Status`, `Yazakia is on its way`).",
68
+ "description": "The page's `h1` (`Status`, `Yasakia is on its way`).",
69
69
  "required": true
70
70
  },
71
71
  {
@@ -142,13 +142,13 @@
142
142
  {
143
143
  "name": "building",
144
144
  "title": "Under construction",
145
- "description": "Yazakia on its way: progress and how to hear about it.",
145
+ "description": "Yasakia on its way: progress and how to hear about it.",
146
146
  "template": true,
147
147
  "purpose": "recover",
148
148
  "why": "A visitor learns honestly what is coming, how far it is and how to hear about it.",
149
149
  "path": "examples/status-page/building.tsx",
150
150
  "module": "@krizaka/ui/registry/examples/status-page/building",
151
- "code": "import { Button } from \"@krizaka/ui/button\";\nimport { Mascot } from \"@krizaka/ui/mascots\";\nimport { Progress } from \"@krizaka/ui/progress\";\nimport { StatusPage } from \"@krizaka/ui/status-page\";\n\n// TEMPLATE — « under construction »: what is coming, said honestly — its state in words, its progress, how to hear\n// about it — the duck that builds beside it. Never a fake screen.\nexport default function StatusPageBuilding() {\n return (\n <StatusPage\n eyebrow=\"Yazakia\"\n title=\"On its way\"\n lead=\"Meet by talking first. The first build reaches testers this winter.\"\n aside={<Mascot bird=\"duck\" mood=\"thinking\" size={112} />}\n state=\"building\"\n stateLabel=\"In construction\"\n checked=\"Updated this week\"\n >\n <div className=\"flex max-w-md flex-col gap-4\">\n <Progress value={40} label=\"First build\" showLabel valueText=\"4 of 10 milestones\" />\n <Button variant=\"primary\" shape=\"cut\" className=\"w-fit\">Tell me when it is ready</Button>\n </div>\n </StatusPage>\n );\n}\n"
151
+ "code": "import { Button } from \"@krizaka/ui/button\";\nimport { Mascot } from \"@krizaka/ui/mascots\";\nimport { Progress } from \"@krizaka/ui/progress\";\nimport { StatusPage } from \"@krizaka/ui/status-page\";\n\n// TEMPLATE — « under construction »: what is coming, said honestly — its state in words, its progress, how to hear\n// about it — the duck that builds beside it. Never a fake screen.\nexport default function StatusPageBuilding() {\n return (\n <StatusPage\n eyebrow=\"Yasakia\"\n title=\"On its way\"\n lead=\"Meet by talking first. The first build reaches testers this winter.\"\n aside={<Mascot bird=\"duck\" mood=\"thinking\" size={112} />}\n state=\"building\"\n stateLabel=\"In construction\"\n checked=\"Updated this week\"\n >\n <div className=\"flex max-w-md flex-col gap-4\">\n <Progress value={40} label=\"First build\" showLabel valueText=\"4 of 10 milestones\" />\n <Button variant=\"primary\" shape=\"cut\" className=\"w-fit\">Tell me when it is ready</Button>\n </div>\n </StatusPage>\n );\n}\n"
152
152
  },
153
153
  {
154
154
  "name": "maintenance",
@@ -175,11 +175,11 @@
175
175
  },
176
176
  {
177
177
  "path": "status-page/meta.ts",
178
- "content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Status page\",\n summary: \"Where things stand: the overall state in words and colour, each service on its line, the incidents — or, for what is not built yet, its progress and how to hear about it.\",\n status: \"beta\",\n category: \"templates\",\n platforms: \"web\",\n whenToUse: [\"A service status page.\", \"An « under construction » page that says honestly what is coming.\"],\n whenNotToUse: [\n { when: \"For what changed over time.\", use: \"changelog-page\" },\n { when: \"For a page that does not exist.\", use: \"error-page\" },\n ],\n bestPractices: [\"Always say the state in words; the colour only repeats it.\", \"Under construction: show progress and a way to follow, never a fake screen.\", \"Words and content arrive as props; the motion is the platform's (`[data-reveal]`, still under reduced motion).\"],\n accessibility: {\n keyboard: [],\n notes: [\"The overall state is a `status` region.\", \"Each service says its state in words beside its dot.\"],\n },\n related: [\"changelog-page\", \"progress\", \"error-page\"],\n web: {\n imports: [\"StatusPage\"],\n examples: [\n { name: \"operational\", title: \"Status\", description: \"Three services, one slower than usual.\", template: true, purpose: \"recover\", why: \"A person checks in one look whether the service works and which part is slow.\" },\n { name: \"building\", title: \"Under construction\", description: \"Yazakia on its way: progress and how to hear about it.\", template: true, purpose: \"recover\", why: \"A visitor learns honestly what is coming, how far it is and how to hear about it.\" },\n { name: \"maintenance\", title: \"Planned maintenance\", description: \"What is paused until when, and what still works.\", template: true, purpose: \"recover\", why: \"A person learns what is down, until when, and what they can still do.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
178
+ "content": "import type { ComponentMeta } from \"../meta\";\n\nexport const meta = {\n title: \"Status page\",\n summary: \"Where things stand: the overall state in words and colour, each service on its line, the incidents — or, for what is not built yet, its progress and how to hear about it.\",\n status: \"beta\",\n category: \"templates\",\n platforms: \"web\",\n whenToUse: [\"A service status page.\", \"An « under construction » page that says honestly what is coming.\"],\n whenNotToUse: [\n { when: \"For what changed over time.\", use: \"changelog-page\" },\n { when: \"For a page that does not exist.\", use: \"error-page\" },\n ],\n bestPractices: [\"Always say the state in words; the colour only repeats it.\", \"Under construction: show progress and a way to follow, never a fake screen.\", \"Words and content arrive as props; the motion is the platform's (`[data-reveal]`, still under reduced motion).\"],\n accessibility: {\n keyboard: [],\n notes: [\"The overall state is a `status` region.\", \"Each service says its state in words beside its dot.\"],\n },\n related: [\"changelog-page\", \"progress\", \"error-page\"],\n web: {\n imports: [\"StatusPage\"],\n examples: [\n { name: \"operational\", title: \"Status\", description: \"Three services, one slower than usual.\", template: true, purpose: \"recover\", why: \"A person checks in one look whether the service works and which part is slow.\" },\n { name: \"building\", title: \"Under construction\", description: \"Yasakia on its way: progress and how to hear about it.\", template: true, purpose: \"recover\", why: \"A visitor learns honestly what is coming, how far it is and how to hear about it.\" },\n { name: \"maintenance\", title: \"Planned maintenance\", description: \"What is paused until when, and what still works.\", template: true, purpose: \"recover\", why: \"A person learns what is down, until when, and what they can still do.\" },\n ],\n },\n} satisfies ComponentMeta;\n"
179
179
  },
180
180
  {
181
181
  "path": "status-page/status-page.tsx",
182
- "content": "// Server-safe. Where things stand (blocks.css `.kz-tpl-state`, `.kz-tpl-services`): the overall state in words and\n// colour, each service on its line, the incidents under them — or, for something not built yet (`state=\"building\"`),\n// what is coming, its progress and how to hear about it, the bird beside it. A state is always said in words.\nimport { Page, Section } from \"@krizaka/ui/page\";\nimport type { LinkComponent } from \"@krizaka/ui/page-hero\";\nimport { PageHero } from \"@krizaka/ui/page-hero\";\nimport type * as React from \"react\";\n\nexport type ServiceState = \"operational\" | \"degraded\" | \"outage\" | \"building\";\n\nexport type StatusPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\n /** The way back. */\n back?: { href: string; label: string };\n /** A mono line above the title. */\n eyebrow?: React.ReactNode;\n /** The page's `h1` (`Status`, `Yazakia is on its way`). */\n title: React.ReactNode;\n /** One sentence under it. */\n lead?: React.ReactNode;\n /** Beside the hero: a bird (the pigeon that delivers, the duck that builds). */\n aside?: React.ReactNode;\n /** The overall state. */\n state: ServiceState;\n /** The overall state, in words (`All systems operational`). */\n stateLabel: React.ReactNode;\n /** When it was checked (`Checked 2 min ago`). */\n checked?: React.ReactNode;\n /** The services and their states, in words: `{ id, name, state, label }`. */\n services?: readonly { id: string; name: React.ReactNode; state: ServiceState; label: React.ReactNode }[];\n /** The services list's accessible name (`Services`). */\n servicesLabel?: string;\n /** Under the services: the incidents (a ChangelogPage's entries, a list), or for `building` the progress and the way to follow. */\n children?: React.ReactNode;\n /** The app's link component (Next's `Link`). */\n linkAs?: LinkComponent;\n};\n\n/** A status page — or an « under construction » one: the overall state, each service, then incidents or progress. */\nexport function StatusPage({ back, eyebrow, title, lead, aside, state, stateLabel, checked, services, servicesLabel = \"Services\", linkAs, children, ...props }: StatusPageProps) {\n return (\n <div {...props}>\n <PageHero back={back} linkAs={linkAs} eyebrow={eyebrow} title={title} lead={lead} aside={aside} backdrop=\"plain\" />\n <Page className=\"kz-tpl-longform\">\n <div className=\"kz-tpl-state\" data-state={state} role=\"status\">\n <span className=\"kz-tpl-dot\" aria-hidden />\n <strong>{stateLabel}</strong>\n {checked && <span className=\"kz-tpl-count\">{checked}</span>}\n </div>\n {services && services.length > 0 && (\n <ul className=\"kz-tpl-services\" aria-label={servicesLabel}>\n {services.map((s) => (\n <li key={s.id}>\n <span>{s.name}</span>\n <small>\n <span className=\"kz-tpl-dot\" data-state={s.state} aria-hidden />\n {s.label}\n </small>\n </li>\n ))}\n </ul>\n )}\n </Page>\n {children && <Section spacing=\"sm\">{children}</Section>}\n </div>\n );\n}\n"
182
+ "content": "// Server-safe. Where things stand (blocks.css `.kz-tpl-state`, `.kz-tpl-services`): the overall state in words and\n// colour, each service on its line, the incidents under them — or, for something not built yet (`state=\"building\"`),\n// what is coming, its progress and how to hear about it, the bird beside it. A state is always said in words.\nimport { Page, Section } from \"@krizaka/ui/page\";\nimport type { LinkComponent } from \"@krizaka/ui/page-hero\";\nimport { PageHero } from \"@krizaka/ui/page-hero\";\nimport type * as React from \"react\";\n\nexport type ServiceState = \"operational\" | \"degraded\" | \"outage\" | \"building\";\n\nexport type StatusPageProps = Omit<React.HTMLAttributes<HTMLElement>, \"title\"> & {\n /** The way back. */\n back?: { href: string; label: string };\n /** A mono line above the title. */\n eyebrow?: React.ReactNode;\n /** The page's `h1` (`Status`, `Yasakia is on its way`). */\n title: React.ReactNode;\n /** One sentence under it. */\n lead?: React.ReactNode;\n /** Beside the hero: a bird (the pigeon that delivers, the duck that builds). */\n aside?: React.ReactNode;\n /** The overall state. */\n state: ServiceState;\n /** The overall state, in words (`All systems operational`). */\n stateLabel: React.ReactNode;\n /** When it was checked (`Checked 2 min ago`). */\n checked?: React.ReactNode;\n /** The services and their states, in words: `{ id, name, state, label }`. */\n services?: readonly { id: string; name: React.ReactNode; state: ServiceState; label: React.ReactNode }[];\n /** The services list's accessible name (`Services`). */\n servicesLabel?: string;\n /** Under the services: the incidents (a ChangelogPage's entries, a list), or for `building` the progress and the way to follow. */\n children?: React.ReactNode;\n /** The app's link component (Next's `Link`). */\n linkAs?: LinkComponent;\n};\n\n/** A status page — or an « under construction » one: the overall state, each service, then incidents or progress. */\nexport function StatusPage({ back, eyebrow, title, lead, aside, state, stateLabel, checked, services, servicesLabel = \"Services\", linkAs, children, ...props }: StatusPageProps) {\n return (\n <div {...props}>\n <PageHero back={back} linkAs={linkAs} eyebrow={eyebrow} title={title} lead={lead} aside={aside} backdrop=\"plain\" />\n <Page className=\"kz-tpl-longform\">\n <div className=\"kz-tpl-state\" data-state={state} role=\"status\">\n <span className=\"kz-tpl-dot\" aria-hidden />\n <strong>{stateLabel}</strong>\n {checked && <span className=\"kz-tpl-count\">{checked}</span>}\n </div>\n {services && services.length > 0 && (\n <ul className=\"kz-tpl-services\" aria-label={servicesLabel}>\n {services.map((s) => (\n <li key={s.id}>\n <span>{s.name}</span>\n <small>\n <span className=\"kz-tpl-dot\" data-state={s.state} aria-hidden />\n {s.label}\n </small>\n </li>\n ))}\n </ul>\n )}\n </Page>\n {children && <Section spacing=\"sm\">{children}</Section>}\n </div>\n );\n}\n"
183
183
  }
184
184
  ],
185
185
  "dependencies": [],
@@ -214,7 +214,7 @@
214
214
  "name": "title",
215
215
  "type": "ReactNode",
216
216
  "default": null,
217
- "description": "The page's `h1` (`Status`, `Yazakia is on its way`).",
217
+ "description": "The page's `h1` (`Status`, `Yasakia is on its way`).",
218
218
  "required": true
219
219
  },
220
220
  {