@dataimago/hub-chrome 0.2.0-alpha.7 → 0.2.0-alpha.8

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.
package/dist/index.cjs CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ CopulaFooter: () => CopulaFooter,
33
34
  GitHubNavButton: () => GitHubNavButton,
34
35
  MinimalFooter: () => MinimalFooter,
35
36
  PhilosophyFooter: () => PhilosophyFooter,
@@ -85,6 +86,7 @@ function PlatformNav({
85
86
  brandMark = "dataimago_ai_OVERLAP",
86
87
  navbarMark,
87
88
  aiMonogram,
89
+ dataimago = "shown",
88
90
  brandLabel = "dataimago.ai home",
89
91
  links = DEFAULT_LINKS,
90
92
  cta = DEFAULT_CTA,
@@ -102,7 +104,7 @@ function PlatformNav({
102
104
  "aria-label": navLabel,
103
105
  children: [
104
106
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 sm:gap-3", children: [
105
- aiMonogram && (aiHref ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_link.default, { href: aiHref, "aria-label": aiLabel, className: AI_BUTTON_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.NavbarLogo, { name: "ai-monogram", "aria-hidden": true, className: "[&_svg]:h-6 [&_svg]:w-auto" }) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: AI_BUTTON_CLASS, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.NavbarLogo, { name: "ai-monogram", "aria-hidden": true, className: "[&_svg]:h-6 [&_svg]:w-auto" }) })),
107
+ aiMonogram && dataimago === "shown" && (aiHref ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_link.default, { href: aiHref, "aria-label": aiLabel, className: AI_BUTTON_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.NavbarLogo, { name: "ai-monogram", "aria-hidden": true, className: "[&_svg]:h-6 [&_svg]:w-auto" }) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: AI_BUTTON_CLASS, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ui.NavbarLogo, { name: "ai-monogram", "aria-hidden": true, className: "[&_svg]:h-6 [&_svg]:w-auto" }) })),
106
108
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
107
109
  import_link.default,
108
110
  {
@@ -401,8 +403,66 @@ function MinimalFooter({
401
403
  );
402
404
  }
403
405
 
404
- // src/PhilosophyFooter.tsx
406
+ // src/CopulaFooter.tsx
407
+ var import_link4 = __toESM(require("next/link"), 1);
408
+ var import_ui4 = require("@dataimago/ui");
405
409
  var import_jsx_runtime6 = require("react/jsx-runtime");
410
+ function FooterLink({ href, children, ...props }) {
411
+ return href.startsWith("/") ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_link4.default, { href, ...props, children }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { href, ...props, children });
412
+ }
413
+ function CopulaFooter({
414
+ property,
415
+ propertyLabel,
416
+ propertyHref = "/",
417
+ dataimago = "shown",
418
+ brandHref = "https://dataimago.ai",
419
+ links = [],
420
+ linksLabel = "Legal",
421
+ copyright
422
+ }) {
423
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
424
+ "footer",
425
+ {
426
+ className: "border-t border-stone-800 bg-stone-900 text-stone-400",
427
+ "data-bs-theme": "dark",
428
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-auto flex max-w-6xl flex-wrap items-center justify-between gap-x-6 gap-y-3 px-6 py-4", children: [
429
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
430
+ import_ui4.CopulaLockup,
431
+ {
432
+ property,
433
+ propertyLabel,
434
+ propertyHref,
435
+ dataimago,
436
+ brandHref,
437
+ linkClassName: "text-stone-200 transition hover:text-stone-50",
438
+ badgeClassName: "text-stone-200",
439
+ renderLink: FooterLink
440
+ }
441
+ ),
442
+ links.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("nav", { "aria-label": linksLabel, className: "flex flex-wrap items-center gap-x-5 gap-y-2 text-sm", children: links.map(
443
+ ({ href, label, external }) => !href ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-stone-400", children: label }, label) : external ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
444
+ "a",
445
+ {
446
+ href,
447
+ className: "text-stone-400 transition hover:text-stone-200",
448
+ target: "_blank",
449
+ rel: "noreferrer",
450
+ children: [
451
+ label,
452
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NewTabIndicator, {})
453
+ ]
454
+ },
455
+ label
456
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_link4.default, { href, className: "text-stone-400 transition hover:text-stone-200", children: label }, label)
457
+ ) }) : null,
458
+ copyright ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "w-full text-xs text-stone-400", children: copyright }) : null
459
+ ] })
460
+ }
461
+ );
462
+ }
463
+
464
+ // src/PhilosophyFooter.tsx
465
+ var import_jsx_runtime7 = require("react/jsx-runtime");
406
466
  var DEFAULT_PAIRS = [
407
467
  {
408
468
  eyebrow: "our belief",
@@ -431,17 +491,17 @@ function PhilosophyFooter({
431
491
  density = "default"
432
492
  }) {
433
493
  const compact = density === "compact";
434
- const pullQuote = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
494
+ const pullQuote = /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
435
495
  "blockquote",
436
496
  {
437
497
  className: `border-l-2 border-copper-500 pl-6 font-display italic text-paper-100 ${compact ? "" : "mt-16 max-w-prose-wide"}`,
438
498
  children: [
439
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-base leading-relaxed", children: quote.text }),
440
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("footer", { className: "mt-4 text-sm not-italic text-stone-400", children: [
499
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-base leading-relaxed", children: quote.text }),
500
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("footer", { className: "mt-4 text-sm not-italic text-stone-400", children: [
441
501
  "\u2014 ",
442
502
  quote.attribution,
443
503
  ", ",
444
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("cite", { children: quote.work }),
504
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("cite", { children: quote.work }),
445
505
  " (",
446
506
  quote.year,
447
507
  ")"
@@ -449,41 +509,41 @@ function PhilosophyFooter({
449
509
  ]
450
510
  }
451
511
  );
452
- const closing = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
512
+ const closing = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
453
513
  "p",
454
514
  {
455
515
  className: `text-stone-400 ${compact ? "text-base leading-relaxed" : "mt-8 max-w-prose-wide text-sm"}`,
456
516
  children: closingStatement
457
517
  }
458
518
  );
459
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
519
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
460
520
  "section",
461
521
  {
462
522
  "aria-labelledby": "philosophy-heading",
463
523
  className: `border-t border-stone-200 bg-stone-900 text-paper-100 ${compact ? "flex flex-col justify-center py-14 sm:py-16 lg:min-h-[50vh]" : "py-20 sm:py-28"}`,
464
524
  "data-bs-theme": "dark",
465
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-auto w-full max-w-6xl px-6", children: [
466
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `grid lg:grid-cols-3 ${compact ? "gap-8" : "gap-12"}`, children: pairs.map((pair, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
467
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "font-mono text-xs uppercase tracking-wider text-accent-300", children: pair.eyebrow }),
468
- i === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
525
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mx-auto w-full max-w-6xl px-6", children: [
526
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `grid lg:grid-cols-3 ${compact ? "gap-8" : "gap-12"}`, children: pairs.map((pair, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
527
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "font-mono text-xs uppercase tracking-wider text-accent-300", children: pair.eyebrow }),
528
+ i === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
469
529
  "h3",
470
530
  {
471
531
  id: "philosophy-heading",
472
532
  className: "mt-2 font-display text-xl text-paper-100",
473
533
  children: pair.body
474
534
  }
475
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mt-2 font-display text-xl text-paper-100", children: pair.body })
535
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mt-2 font-display text-xl text-paper-100", children: pair.body })
476
536
  ] }, i)) }),
477
537
  compact ? (
478
538
  // Critique / answer, side by side — Baudrillard's warning and
479
539
  // dataimago's structural answer. Filling the width is what pulls the
480
540
  // section down to ~half height (the default stacks these in one column,
481
541
  // leaving the right half empty).
482
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mt-10 grid gap-x-12 gap-y-8 lg:grid-cols-2", children: [
542
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mt-10 grid gap-x-12 gap-y-8 lg:grid-cols-2", children: [
483
543
  pullQuote,
484
544
  closing
485
545
  ] })
486
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
546
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
487
547
  pullQuote,
488
548
  closing
489
549
  ] })
@@ -493,6 +553,7 @@ function PhilosophyFooter({
493
553
  }
494
554
  // Annotate the CommonJS export names for ESM import in node:
495
555
  0 && (module.exports = {
556
+ CopulaFooter,
496
557
  GitHubNavButton,
497
558
  MinimalFooter,
498
559
  PhilosophyFooter,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/PlatformNav.tsx","../src/NewTabIndicator.tsx","../src/GitHubNavButton.tsx","../src/SiteFooter.tsx","../src/MinimalFooter.tsx","../src/PhilosophyFooter.tsx"],"sourcesContent":["/**\n * @dataimago/hub-chrome — public surface barrel.\n *\n * All three chrome components are named exports. The original apps/hub\n * versions were default exports; the package exposes them as named exports\n * for tree-shaking and to keep the import surface symmetric with\n * @dataimago/ui and @dataimago/interview.\n */\nexport { PlatformNav } from './PlatformNav';\nexport { GitHubNavButton } from './GitHubNavButton';\nexport { SiteFooter } from './SiteFooter';\nexport { MinimalFooter } from './MinimalFooter';\nexport { PhilosophyFooter } from './PhilosophyFooter';\n\nexport type {\n NavLink,\n FooterColumn,\n EditorialPair,\n PullQuote,\n BrandMark,\n NavbarMark,\n AiMonogram,\n PlatformNavProps,\n GitHubNavButtonProps,\n SiteFooterProps,\n MinimalFooterProps,\n PhilosophyFooterProps,\n} from './types';\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo, NavbarLogo } from '@dataimago/ui';\nimport type { PlatformNavProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * Platform navigation — sticky header with the property's brand mark + nav cluster.\n *\n * The property mark is rendered by height (so any aspect fits the nav). By default\n * it's the static `@dataimago/brand` wordmark via `<Logo>` (font-free, IoU-locked,\n * `currentColor`). When `navbarMark` is set it becomes the ANIMATED `<NavbarLogo>`\n * (the a/i assemble toggle for L2 marks, lift+wash for L1) — falling back to the\n * static `<Logo brandMark>` otherwise, so pre-navbar consumers are unaffected.\n *\n * `aiMonogram` adds the dataimago `ai-monogram` icon button to the LEFT of the\n * property mark (a 48px touch target; lift+washes to the brand-mark red on hover).\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11); `navbarMark`/`aiMonogram` added in iteration-4 (the navbar logo\n * system). All props default to the Level-1 hub configuration.\n */\n\nconst DEFAULT_LINKS = [\n { href: '/ecosystem', label: 'Ecosystem' },\n { href: '/philosophy', label: 'Philosophy' },\n];\n\nconst DEFAULT_CTA = { href: '/onboard', label: 'Begin' };\n\n/** Height-based sizing for the property mark (the navbar norm — ~30% larger letters). */\nconst MARK_CLASS = '[&_svg]:h-7 [&_svg]:w-auto sm:[&_svg]:h-8';\n\n/** The optional ai-monogram icon button — a 48px touch target (ready-to-hand floor). */\nconst AI_BUTTON_CLASS =\n 'inline-flex min-h-[48px] min-w-[48px] items-center justify-center rounded-xl ' +\n 'border border-stone-200 bg-stone-50 text-stone-900 transition hover:bg-stone-100';\n\nexport function PlatformNav({\n brandMark = 'dataimago_ai_OVERLAP',\n navbarMark,\n aiMonogram,\n brandLabel = 'dataimago.ai home',\n links = DEFAULT_LINKS,\n cta = DEFAULT_CTA,\n rightSlot,\n navLabel = 'Primary',\n homeHref = '/',\n}: PlatformNavProps) {\n const propertyMark = navbarMark ? (\n <NavbarLogo name={navbarMark} aria-hidden className={MARK_CLASS} />\n ) : (\n <Logo name={brandMark} variant=\"PATH\" aria-hidden className={MARK_CLASS} />\n );\n\n const aiHref = typeof aiMonogram === 'object' ? aiMonogram.href : undefined;\n const aiLabel =\n typeof aiMonogram === 'object' ? (aiMonogram.label ?? 'dataimago') : 'dataimago';\n\n return (\n <header className=\"sticky top-0 z-40 border-b border-stone-200 bg-stone-100/95 backdrop-blur-sm\">\n <nav\n className=\"mx-auto flex max-w-7xl items-center justify-between px-6 py-4\"\n aria-label={navLabel}\n >\n <div className=\"flex items-center gap-2 sm:gap-3\">\n {aiMonogram &&\n (aiHref ? (\n <Link href={aiHref} aria-label={aiLabel} className={AI_BUTTON_CLASS}>\n <NavbarLogo name=\"ai-monogram\" aria-hidden className=\"[&_svg]:h-6 [&_svg]:w-auto\" />\n </Link>\n ) : (\n <span className={AI_BUTTON_CLASS} aria-hidden>\n <NavbarLogo name=\"ai-monogram\" aria-hidden className=\"[&_svg]:h-6 [&_svg]:w-auto\" />\n </span>\n ))}\n <Link\n href={homeHref}\n className=\"inline-flex min-h-[48px] items-center text-stone-900 transition hover:opacity-80\"\n aria-label={brandLabel}\n >\n {propertyMark}\n </Link>\n </div>\n\n <div className=\"flex items-center gap-2 sm:gap-6\">\n {links.map(({ href, label, external }) =>\n external ? (\n <a\n key={href}\n href={href}\n className=\"btn-ghost hidden sm:inline-flex\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={href} href={href} className=\"btn-ghost hidden sm:inline-flex\">\n {label}\n </Link>\n )\n )}\n {cta && (\n <Link href={cta.href} className=\"btn-primary\">\n {cta.label}\n </Link>\n )}\n {rightSlot}\n </div>\n </nav>\n </header>\n );\n}\n","/**\n * Disclosure for links that open in a new tab (WCAG 3.2.5), shared by every\n * `target=\"_blank\"` link in this package so sighted and screen-reader users get\n * the same warning.\n *\n * - Sighted: a small \"arrow out of a box\" glyph after the link content.\n * - Screen reader: the visually hidden text \"(opens in a new tab)\", appended to\n * the link's accessible name. For a link that sets `aria-label` (which\n * replaces its content in the name), append `NEW_TAB_SUFFIX` to the label\n * instead and pass `hideText` so the name is not announced twice.\n */\nexport const NEW_TAB_SUFFIX = ' (opens in a new tab)';\n\nexport function NewTabIndicator({ hideText = false }: { hideText?: boolean }) {\n return (\n <>\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n viewBox=\"0 0 24 24\"\n width=\"0.85em\"\n height=\"0.85em\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"ml-1 inline-block shrink-0 align-baseline\"\n >\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n {hideText ? null : <span className=\"sr-only\">{NEW_TAB_SUFFIX}</span>}\n </>\n );\n}\n","import type { GitHubNavButtonProps } from './types';\nimport { NEW_TAB_SUFFIX, NewTabIndicator } from './NewTabIndicator';\n\n/**\n * The unified GitHub account control for the nav's right slot — the canonical\n * login affordance + login-state indicator shared across every L1/L2 dataimago\n * app (rendered into `PlatformNav`'s `rightSlot`).\n *\n * Fully presentational and **stateless** — it reads no auth itself; the consumer\n * feeds it. Uses a native `<details>` disclosure for the signed-in menu, so it\n * needs no client JS and works whether rendered on the server (a server parent\n * injecting the avatar) or the client.\n *\n * - `mode=\"auth\"` (default): the login-state indicator.\n * - `status=\"unauthed\"` → a GET link to `signInHref` (start OAuth) showing the\n * GitHub mark + a login glyph.\n * - `status=\"authed\"` → the GitHub mark + the user's avatar, opening a menu\n * (profile link + a POST sign-out form to `signOutAction`).\n * - `mode=\"link\"`: a plain GitHub→`orgHref` link (L1, which has no auth).\n *\n * Icons are inlined (the GitHub mark + a lucide-style \"log-in\" glyph) to keep the\n * shared package free of an icon-library peer dependency.\n */\n\n// The 48px touch-target floor (the ready-to-hand dignity gate); colours resolve\n// from the consuming app's dataimago palette. The global `*:focus-visible` rule\n// supplies the focus ring.\nconst SHELL =\n 'inline-flex min-h-[48px] items-center gap-2 rounded-xl border border-stone-200 ' +\n 'bg-stone-50 px-3 text-stone-900 transition hover:bg-stone-100';\n\nconst MENU_ITEM =\n 'flex min-h-[48px] w-full items-center rounded px-2 text-left text-sm ' +\n 'text-stone-900 transition hover:bg-stone-100';\n\nfunction GithubMark() {\n return (\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" className=\"h-5 w-5 shrink-0\" fill=\"currentColor\">\n <path d=\"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23a11.5 11.5 0 0 1 3.003-.404c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.014 2.898-.014 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" />\n </svg>\n );\n}\n\nfunction LoginGlyph() {\n // lucide \"log-in\" (ISC), inlined.\n return (\n <svg\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n className=\"h-5 w-5 shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\" />\n <polyline points=\"10 17 15 12 10 7\" />\n <line x1=\"15\" x2=\"3\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\nexport function GitHubNavButton({\n mode = 'auth',\n status = 'unauthed',\n login,\n avatarUrl,\n signInHref,\n profileHref,\n signOutAction,\n orgHref,\n defaultOpen,\n}: GitHubNavButtonProps) {\n // L1 mode: a plain GitHub→org link (no auth).\n if (mode === 'link') {\n return (\n <a\n href={orgHref}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={SHELL}\n aria-label={`dataimago on GitHub${NEW_TAB_SUFFIX}`}\n >\n <GithubMark />\n <NewTabIndicator hideText />\n </a>\n );\n }\n\n // Signed out: a GET link that starts the OAuth flow.\n if (status !== 'authed') {\n return (\n <a href={signInHref} className={SHELL} aria-label=\"Sign in with GitHub\">\n <GithubMark />\n <LoginGlyph />\n </a>\n );\n }\n\n // Signed in: the GitHub mark + the user's avatar, with a native-disclosure menu.\n return (\n <details className=\"relative\" open={defaultOpen}>\n <summary\n className={`${SHELL} cursor-pointer list-none [&::-webkit-details-marker]:hidden`}\n aria-label={`GitHub account — signed in as ${login ?? 'your account'}`}\n >\n <GithubMark />\n {avatarUrl ? (\n <img\n src={avatarUrl}\n alt=\"\"\n className=\"h-7 w-7 rounded-full border border-stone-200\"\n width={28}\n height={28}\n />\n ) : (\n <span className=\"text-sm font-medium\">@{login}</span>\n )}\n </summary>\n <div className=\"absolute right-0 z-50 mt-2 w-60 rounded-lg border border-stone-200 bg-stone-50 p-2 shadow-lg\">\n <p className=\"px-2 py-1 text-sm text-stone-700\">\n Signed in as <span className=\"font-medium text-stone-900\">@{login}</span>\n </p>\n {profileHref && (\n <a href={profileHref} target=\"_blank\" rel=\"noreferrer\" className={MENU_ITEM}>\n View your GitHub profile\n <NewTabIndicator />\n </a>\n )}\n {signOutAction && (\n <form method=\"POST\" action={signOutAction}>\n <button type=\"submit\" className={MENU_ITEM}>\n Sign out\n </button>\n </form>\n )}\n </div>\n </details>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo } from '@dataimago/ui';\nimport type { SiteFooterProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * Site footer — the Level-1 hub footer: dark surface, dataimago wordmark + a\n * trimmed nav column grid.\n *\n * The wordmark is the `dataimago` brand mark via `<Logo>` (font-free, in a light\n * `currentColor` on the dark surface) — no backplate, no hardcoded \".ai\" span.\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11). The defaults drop the former \"Legacy\" column + the critical-theory\n * closing statement (the philosophical-basis editorial lives on the PhilosophyFooter,\n * which is Level-1-only). Level-2 verticals use `MinimalFooter` instead.\n */\n\nconst DEFAULT_TAGLINE = 'A living AI-native application ecosystem.';\n\nconst DEFAULT_COLUMNS = [\n {\n heading: 'Platform',\n links: [\n { href: '/onboard', label: 'Begin a project' },\n { href: '/ecosystem', label: 'Ecosystem' },\n { href: '/philosophy', label: 'Philosophy' },\n ],\n },\n {\n heading: 'Framework',\n links: [\n {\n href: 'https://github.com/dataimago/dataimago-design',\n label: 'dataimago-design',\n external: true,\n },\n {\n href: 'https://github.com/dataimago/dataimago',\n label: 'dataimago',\n external: true,\n },\n {\n href: 'https://github.com/dataimago/dataimago-ai',\n label: 'dataimago-ai',\n external: true,\n },\n ],\n },\n];\n\nexport function SiteFooter({\n tagline = DEFAULT_TAGLINE,\n columns = DEFAULT_COLUMNS,\n closingStatement,\n}: SiteFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto max-w-6xl px-6 py-12\">\n <div className=\"grid gap-8 md:grid-cols-4\">\n <div>\n <Link\n href=\"/\"\n className=\"inline-flex items-center text-stone-100 transition hover:opacity-80\"\n aria-label=\"dataimago\"\n >\n <Logo\n name=\"dataimago\"\n variant=\"PATH\"\n aria-hidden\n className=\"[&_svg]:h-7 [&_svg]:w-auto\"\n />\n </Link>\n <p className=\"mt-3 text-xs text-stone-400\">{tagline}</p>\n </div>\n\n {columns.map((col) => (\n <div key={col.heading}>\n <h4 className=\"font-mono text-xs uppercase tracking-wider text-accent-300\">\n {col.heading}\n </h4>\n <ul className=\"mt-3 space-y-2 text-sm\">\n {col.links.map(({ href, label, external }) => (\n <li key={label}>\n {!href ? (\n label\n ) : external ? (\n <a\n href={href}\n className=\"hover:text-paper-100\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link href={href} className=\"hover:text-paper-100\">\n {label}\n </Link>\n )}\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n\n {closingStatement ? (\n <div className=\"mt-12 border-t border-stone-800 pt-6 text-xs text-stone-400\">\n <p>{closingStatement}</p>\n </div>\n ) : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo } from '@dataimago/ui';\nimport type { MinimalFooterProps } from './types';\nimport { NEW_TAB_SUFFIX, NewTabIndicator } from './NewTabIndicator';\n\n/**\n * MinimalFooter — the Level-2 vertical footer.\n *\n * A Level-2 vertical (dissertation.ai, future rpkg.ai / sgpc.ai) is \"an embodiment\n * of dataimago\": the footer shows the parent `dataimago` wordmark linking UP to\n * dataimago.ai, the embodiment line, a compact links row, and a copyright line.\n * No nav columns, no philosophy — those belong to the Level-1 hub (SiteFooter +\n * PhilosophyFooter). See dataimago-design wiki/patterns/hub-hero-anatomy.\n */\n\nconst DEFAULT_BRAND_HREF = 'https://dataimago.ai';\nconst DEFAULT_EMBODIMENT = 'An embodiment of dataimago';\n\nexport function MinimalFooter({\n brandHref = DEFAULT_BRAND_HREF,\n embodimentLabel = DEFAULT_EMBODIMENT,\n links = [],\n copyright,\n}: MinimalFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto flex max-w-6xl flex-col items-center gap-4 px-6 py-10 text-center\">\n <a\n href={brandHref}\n className=\"inline-flex flex-col items-center gap-2 text-stone-100 transition hover:opacity-80\"\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label={`${embodimentLabel} — visit dataimago.ai${NEW_TAB_SUFFIX}`}\n >\n <Logo\n name=\"dataimago\"\n variant=\"PATH\"\n aria-hidden\n className=\"[&_svg]:h-7 [&_svg]:w-auto\"\n />\n <span className=\"text-sm text-stone-400\">\n {embodimentLabel}\n <NewTabIndicator hideText />\n </span>\n </a>\n\n {links.length > 0 ? (\n <nav\n className=\"flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm\"\n aria-label=\"Footer\"\n >\n {links.map(({ href, label, external }) =>\n !href ? (\n <span key={label} className=\"text-stone-400\">\n {label}\n </span>\n ) : external ? (\n <a\n key={label}\n href={href}\n className=\"text-stone-300 hover:text-paper-100\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={label} href={href} className=\"text-stone-300 hover:text-paper-100\">\n {label}\n </Link>\n )\n )}\n </nav>\n ) : null}\n\n {copyright ? <p className=\"text-xs text-stone-400\">{copyright}</p> : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport type { PhilosophyFooterProps } from './types';\n\n/**\n * Philosophy footer — the platform's moral weight, rendered as a dark\n * editorial section with three belief/mission/vision pairs and a pull-quote.\n *\n * Iteration-1 visual identity (Phase B.3, 2026-05-06):\n * Dark-surface chrome with text-accent-500 eyebrows, font-display body, and\n * the Baudrillard blockquote with border-copper-500 (preserved-decorative-\n * copper per iteration-1 §5.2 governance).\n *\n * Iteration-2 role-shift (2026-05-07): eyebrows were meant to resolve to\n * sky-blue accent-300 (#3498DB) on this dark surface via mode-aware mapping —\n * 5.41:1 on stone-900. The static Tailwind class `text-accent-500` binds the\n * absolute color instead (~2.56:1). 2026-09-05: eyebrows match SiteFooter\n * (`text-accent-300` + `data-bs-theme=\"dark\"`). The border-copper-500\n * blockquote frame survives untouched. \"Two warmths\" coexist: cool sky-blue\n * on editorial eyebrows, warm copper on the philosophical-quote frame.\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11). The `pairs`, `quote`, and `closingStatement` props allow\n * per-vertical adaptation; all props default to the Level-1 hub content.\n */\n\nconst DEFAULT_PAIRS = [\n {\n eyebrow: 'our belief',\n body: 'AI can enable virtuous cycles of improvement in the world.',\n },\n {\n eyebrow: 'our mission',\n body: 'The emancipation of humanity through ai super-alignment.',\n },\n {\n eyebrow: 'our vision',\n body: 'Super-alignment embeds ai in culture, not culture in ai.',\n },\n];\n\nconst DEFAULT_QUOTE = {\n text: `If men create intelligent machines, or fantasize about them, it is either because they secretly despair of their own intelligence or because they are in danger of succumbing to the weight of a monstrous and useless intelligence which they seek to exorcize by transferring it to machines, where they can play with it and make fun of it. By entrusting this burdensome intelligence to machines we are released from any responsibility to knowledge.`,\n attribution: 'Jean Baudrillard',\n work: 'Xerox and Infinity',\n year: 1988,\n};\n\nconst DEFAULT_CLOSING =\n 'dataimago is the structural answer to this critique. Every architectural choice — R as source of truth, editorial authority with the domain expert, the non-destructive retrofit principle, the ecosystem-as-commons — refuses to release the scholar from responsibility to their own knowledge. The AI serves the culture; the culture governs the AI.';\n\nexport function PhilosophyFooter({\n pairs = DEFAULT_PAIRS,\n quote = DEFAULT_QUOTE,\n closingStatement = DEFAULT_CLOSING,\n density = 'default',\n}: PhilosophyFooterProps) {\n const compact = density === 'compact';\n\n // Pull-quote — border-copper-500 PRESERVED: decorative-emphasis blockquote\n // frame per iteration-1 §5.2 preserved-decorative-copper governance.\n const pullQuote = (\n <blockquote\n className={`border-l-2 border-copper-500 pl-6 font-display italic text-paper-100 ${\n compact ? '' : 'mt-16 max-w-prose-wide'\n }`}\n >\n <p className=\"text-base leading-relaxed\">{quote.text}</p>\n <footer className=\"mt-4 text-sm not-italic text-stone-400\">\n — {quote.attribution}, <cite>{quote.work}</cite> ({quote.year})\n </footer>\n </blockquote>\n );\n\n const closing = (\n <p\n className={`text-stone-400 ${\n compact ? 'text-base leading-relaxed' : 'mt-8 max-w-prose-wide text-sm'\n }`}\n >\n {closingStatement}\n </p>\n );\n\n return (\n <section\n aria-labelledby=\"philosophy-heading\"\n className={`border-t border-stone-200 bg-stone-900 text-paper-100 ${\n compact\n ? 'flex flex-col justify-center py-14 sm:py-16 lg:min-h-[50vh]'\n : 'py-20 sm:py-28'\n }`}\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto w-full max-w-6xl px-6\">\n <div className={`grid lg:grid-cols-3 ${compact ? 'gap-8' : 'gap-12'}`}>\n {pairs.map((pair, i) => (\n <div key={i}>\n <p className=\"font-mono text-xs uppercase tracking-wider text-accent-300\">\n {pair.eyebrow}\n </p>\n {i === 0 ? (\n <h3\n id=\"philosophy-heading\"\n className=\"mt-2 font-display text-xl text-paper-100\"\n >\n {pair.body}\n </h3>\n ) : (\n <p className=\"mt-2 font-display text-xl text-paper-100\">\n {pair.body}\n </p>\n )}\n </div>\n ))}\n </div>\n\n {compact ? (\n // Critique / answer, side by side — Baudrillard's warning and\n // dataimago's structural answer. Filling the width is what pulls the\n // section down to ~half height (the default stacks these in one column,\n // leaving the right half empty).\n <div className=\"mt-10 grid gap-x-12 gap-y-8 lg:grid-cols-2\">\n {pullQuote}\n {closing}\n </div>\n ) : (\n <>\n {pullQuote}\n {closing}\n </>\n )}\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime","Link","import_jsx_runtime","import_link","import_ui","import_jsx_runtime","Link","import_link","import_ui","import_jsx_runtime","Link","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/PlatformNav.tsx","../src/NewTabIndicator.tsx","../src/GitHubNavButton.tsx","../src/SiteFooter.tsx","../src/MinimalFooter.tsx","../src/CopulaFooter.tsx","../src/PhilosophyFooter.tsx"],"sourcesContent":["/**\n * @dataimago/hub-chrome — public surface barrel.\n *\n * All three chrome components are named exports. The original apps/hub\n * versions were default exports; the package exposes them as named exports\n * for tree-shaking and to keep the import surface symmetric with\n * @dataimago/ui and @dataimago/interview.\n */\nexport { PlatformNav } from './PlatformNav';\nexport { GitHubNavButton } from './GitHubNavButton';\nexport { SiteFooter } from './SiteFooter';\nexport { MinimalFooter } from './MinimalFooter';\nexport { CopulaFooter } from './CopulaFooter';\nexport { PhilosophyFooter } from './PhilosophyFooter';\n\nexport type {\n NavLink,\n FooterColumn,\n EditorialPair,\n PullQuote,\n BrandMark,\n NavbarMark,\n AiMonogram,\n DataimagoVisibility,\n PlatformNavProps,\n GitHubNavButtonProps,\n SiteFooterProps,\n MinimalFooterProps,\n CopulaFooterProps,\n PhilosophyFooterProps,\n} from './types';\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo, NavbarLogo } from '@dataimago/ui';\nimport type { PlatformNavProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * Platform navigation — sticky header with the property's brand mark + nav cluster.\n *\n * The property mark is rendered by height (so any aspect fits the nav). By default\n * it's the static `@dataimago/brand` wordmark via `<Logo>` (font-free, IoU-locked,\n * `currentColor`). When `navbarMark` is set it becomes the ANIMATED `<NavbarLogo>`\n * (the a/i assemble toggle for L2 marks, lift+wash for L1) — falling back to the\n * static `<Logo brandMark>` otherwise, so pre-navbar consumers are unaffected.\n *\n * `aiMonogram` adds the dataimago `ai-monogram` icon button to the LEFT of the\n * property mark (a 48px touch target; lift+washes to the brand-mark red on hover).\n * `dataimago=\"hidden\"` drops it, for apps that keep dataimago out of view while\n * it is in stealth (the maintainer, 2026-11-03).\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11); `navbarMark`/`aiMonogram` added in iteration-4 (the navbar logo\n * system). All props default to the Level-1 hub configuration.\n */\n\nconst DEFAULT_LINKS = [\n { href: '/ecosystem', label: 'Ecosystem' },\n { href: '/philosophy', label: 'Philosophy' },\n];\n\nconst DEFAULT_CTA = { href: '/onboard', label: 'Begin' };\n\n/** Height-based sizing for the property mark (the navbar norm — ~30% larger letters). */\nconst MARK_CLASS = '[&_svg]:h-7 [&_svg]:w-auto sm:[&_svg]:h-8';\n\n/** The optional ai-monogram icon button — a 48px touch target (ready-to-hand floor). */\nconst AI_BUTTON_CLASS =\n 'inline-flex min-h-[48px] min-w-[48px] items-center justify-center rounded-xl ' +\n 'border border-stone-200 bg-stone-50 text-stone-900 transition hover:bg-stone-100';\n\nexport function PlatformNav({\n brandMark = 'dataimago_ai_OVERLAP',\n navbarMark,\n aiMonogram,\n dataimago = 'shown',\n brandLabel = 'dataimago.ai home',\n links = DEFAULT_LINKS,\n cta = DEFAULT_CTA,\n rightSlot,\n navLabel = 'Primary',\n homeHref = '/',\n}: PlatformNavProps) {\n const propertyMark = navbarMark ? (\n <NavbarLogo name={navbarMark} aria-hidden className={MARK_CLASS} />\n ) : (\n <Logo name={brandMark} variant=\"PATH\" aria-hidden className={MARK_CLASS} />\n );\n\n const aiHref = typeof aiMonogram === 'object' ? aiMonogram.href : undefined;\n const aiLabel =\n typeof aiMonogram === 'object' ? (aiMonogram.label ?? 'dataimago') : 'dataimago';\n\n return (\n <header className=\"sticky top-0 z-40 border-b border-stone-200 bg-stone-100/95 backdrop-blur-sm\">\n <nav\n className=\"mx-auto flex max-w-7xl items-center justify-between px-6 py-4\"\n aria-label={navLabel}\n >\n <div className=\"flex items-center gap-2 sm:gap-3\">\n {aiMonogram && dataimago === 'shown' &&\n (aiHref ? (\n <Link href={aiHref} aria-label={aiLabel} className={AI_BUTTON_CLASS}>\n <NavbarLogo name=\"ai-monogram\" aria-hidden className=\"[&_svg]:h-6 [&_svg]:w-auto\" />\n </Link>\n ) : (\n <span className={AI_BUTTON_CLASS} aria-hidden>\n <NavbarLogo name=\"ai-monogram\" aria-hidden className=\"[&_svg]:h-6 [&_svg]:w-auto\" />\n </span>\n ))}\n <Link\n href={homeHref}\n className=\"inline-flex min-h-[48px] items-center text-stone-900 transition hover:opacity-80\"\n aria-label={brandLabel}\n >\n {propertyMark}\n </Link>\n </div>\n\n <div className=\"flex items-center gap-2 sm:gap-6\">\n {links.map(({ href, label, external }) =>\n external ? (\n <a\n key={href}\n href={href}\n className=\"btn-ghost hidden sm:inline-flex\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={href} href={href} className=\"btn-ghost hidden sm:inline-flex\">\n {label}\n </Link>\n )\n )}\n {cta && (\n <Link href={cta.href} className=\"btn-primary\">\n {cta.label}\n </Link>\n )}\n {rightSlot}\n </div>\n </nav>\n </header>\n );\n}\n","/**\n * Disclosure for links that open in a new tab (WCAG 3.2.5), shared by every\n * `target=\"_blank\"` link in this package so sighted and screen-reader users get\n * the same warning.\n *\n * - Sighted: a small \"arrow out of a box\" glyph after the link content.\n * - Screen reader: the visually hidden text \"(opens in a new tab)\", appended to\n * the link's accessible name. For a link that sets `aria-label` (which\n * replaces its content in the name), append `NEW_TAB_SUFFIX` to the label\n * instead and pass `hideText` so the name is not announced twice.\n */\nexport const NEW_TAB_SUFFIX = ' (opens in a new tab)';\n\nexport function NewTabIndicator({ hideText = false }: { hideText?: boolean }) {\n return (\n <>\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n viewBox=\"0 0 24 24\"\n width=\"0.85em\"\n height=\"0.85em\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"ml-1 inline-block shrink-0 align-baseline\"\n >\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n {hideText ? null : <span className=\"sr-only\">{NEW_TAB_SUFFIX}</span>}\n </>\n );\n}\n","import type { GitHubNavButtonProps } from './types';\nimport { NEW_TAB_SUFFIX, NewTabIndicator } from './NewTabIndicator';\n\n/**\n * The unified GitHub account control for the nav's right slot — the canonical\n * login affordance + login-state indicator shared across every L1/L2 dataimago\n * app (rendered into `PlatformNav`'s `rightSlot`).\n *\n * Fully presentational and **stateless** — it reads no auth itself; the consumer\n * feeds it. Uses a native `<details>` disclosure for the signed-in menu, so it\n * needs no client JS and works whether rendered on the server (a server parent\n * injecting the avatar) or the client.\n *\n * - `mode=\"auth\"` (default): the login-state indicator.\n * - `status=\"unauthed\"` → a GET link to `signInHref` (start OAuth) showing the\n * GitHub mark + a login glyph.\n * - `status=\"authed\"` → the GitHub mark + the user's avatar, opening a menu\n * (profile link + a POST sign-out form to `signOutAction`).\n * - `mode=\"link\"`: a plain GitHub→`orgHref` link (L1, which has no auth).\n *\n * Icons are inlined (the GitHub mark + a lucide-style \"log-in\" glyph) to keep the\n * shared package free of an icon-library peer dependency.\n */\n\n// The 48px touch-target floor (the ready-to-hand dignity gate); colours resolve\n// from the consuming app's dataimago palette. The global `*:focus-visible` rule\n// supplies the focus ring.\nconst SHELL =\n 'inline-flex min-h-[48px] items-center gap-2 rounded-xl border border-stone-200 ' +\n 'bg-stone-50 px-3 text-stone-900 transition hover:bg-stone-100';\n\nconst MENU_ITEM =\n 'flex min-h-[48px] w-full items-center rounded px-2 text-left text-sm ' +\n 'text-stone-900 transition hover:bg-stone-100';\n\nfunction GithubMark() {\n return (\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" className=\"h-5 w-5 shrink-0\" fill=\"currentColor\">\n <path d=\"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23a11.5 11.5 0 0 1 3.003-.404c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.014 2.898-.014 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" />\n </svg>\n );\n}\n\nfunction LoginGlyph() {\n // lucide \"log-in\" (ISC), inlined.\n return (\n <svg\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n className=\"h-5 w-5 shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\" />\n <polyline points=\"10 17 15 12 10 7\" />\n <line x1=\"15\" x2=\"3\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\nexport function GitHubNavButton({\n mode = 'auth',\n status = 'unauthed',\n login,\n avatarUrl,\n signInHref,\n profileHref,\n signOutAction,\n orgHref,\n defaultOpen,\n}: GitHubNavButtonProps) {\n // L1 mode: a plain GitHub→org link (no auth).\n if (mode === 'link') {\n return (\n <a\n href={orgHref}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={SHELL}\n aria-label={`dataimago on GitHub${NEW_TAB_SUFFIX}`}\n >\n <GithubMark />\n <NewTabIndicator hideText />\n </a>\n );\n }\n\n // Signed out: a GET link that starts the OAuth flow.\n if (status !== 'authed') {\n return (\n <a href={signInHref} className={SHELL} aria-label=\"Sign in with GitHub\">\n <GithubMark />\n <LoginGlyph />\n </a>\n );\n }\n\n // Signed in: the GitHub mark + the user's avatar, with a native-disclosure menu.\n return (\n <details className=\"relative\" open={defaultOpen}>\n <summary\n className={`${SHELL} cursor-pointer list-none [&::-webkit-details-marker]:hidden`}\n aria-label={`GitHub account — signed in as ${login ?? 'your account'}`}\n >\n <GithubMark />\n {avatarUrl ? (\n <img\n src={avatarUrl}\n alt=\"\"\n className=\"h-7 w-7 rounded-full border border-stone-200\"\n width={28}\n height={28}\n />\n ) : (\n <span className=\"text-sm font-medium\">@{login}</span>\n )}\n </summary>\n <div className=\"absolute right-0 z-50 mt-2 w-60 rounded-lg border border-stone-200 bg-stone-50 p-2 shadow-lg\">\n <p className=\"px-2 py-1 text-sm text-stone-700\">\n Signed in as <span className=\"font-medium text-stone-900\">@{login}</span>\n </p>\n {profileHref && (\n <a href={profileHref} target=\"_blank\" rel=\"noreferrer\" className={MENU_ITEM}>\n View your GitHub profile\n <NewTabIndicator />\n </a>\n )}\n {signOutAction && (\n <form method=\"POST\" action={signOutAction}>\n <button type=\"submit\" className={MENU_ITEM}>\n Sign out\n </button>\n </form>\n )}\n </div>\n </details>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo } from '@dataimago/ui';\nimport type { SiteFooterProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * Site footer — the Level-1 hub footer: dark surface, dataimago wordmark + a\n * trimmed nav column grid.\n *\n * The wordmark is the `dataimago` brand mark via `<Logo>` (font-free, in a light\n * `currentColor` on the dark surface) — no backplate, no hardcoded \".ai\" span.\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11). The defaults drop the former \"Legacy\" column + the critical-theory\n * closing statement (the philosophical-basis editorial lives on the PhilosophyFooter,\n * which is Level-1-only). Level-2 verticals use `MinimalFooter` instead.\n */\n\nconst DEFAULT_TAGLINE = 'A living AI-native application ecosystem.';\n\nconst DEFAULT_COLUMNS = [\n {\n heading: 'Platform',\n links: [\n { href: '/onboard', label: 'Begin a project' },\n { href: '/ecosystem', label: 'Ecosystem' },\n { href: '/philosophy', label: 'Philosophy' },\n ],\n },\n {\n heading: 'Framework',\n links: [\n {\n href: 'https://github.com/dataimago/dataimago-design',\n label: 'dataimago-design',\n external: true,\n },\n {\n href: 'https://github.com/dataimago/dataimago',\n label: 'dataimago',\n external: true,\n },\n {\n href: 'https://github.com/dataimago/dataimago-ai',\n label: 'dataimago-ai',\n external: true,\n },\n ],\n },\n];\n\nexport function SiteFooter({\n tagline = DEFAULT_TAGLINE,\n columns = DEFAULT_COLUMNS,\n closingStatement,\n}: SiteFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto max-w-6xl px-6 py-12\">\n <div className=\"grid gap-8 md:grid-cols-4\">\n <div>\n <Link\n href=\"/\"\n className=\"inline-flex items-center text-stone-100 transition hover:opacity-80\"\n aria-label=\"dataimago\"\n >\n <Logo\n name=\"dataimago\"\n variant=\"PATH\"\n aria-hidden\n className=\"[&_svg]:h-7 [&_svg]:w-auto\"\n />\n </Link>\n <p className=\"mt-3 text-xs text-stone-400\">{tagline}</p>\n </div>\n\n {columns.map((col) => (\n <div key={col.heading}>\n <h4 className=\"font-mono text-xs uppercase tracking-wider text-accent-300\">\n {col.heading}\n </h4>\n <ul className=\"mt-3 space-y-2 text-sm\">\n {col.links.map(({ href, label, external }) => (\n <li key={label}>\n {!href ? (\n label\n ) : external ? (\n <a\n href={href}\n className=\"hover:text-paper-100\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link href={href} className=\"hover:text-paper-100\">\n {label}\n </Link>\n )}\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n\n {closingStatement ? (\n <div className=\"mt-12 border-t border-stone-800 pt-6 text-xs text-stone-400\">\n <p>{closingStatement}</p>\n </div>\n ) : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo } from '@dataimago/ui';\nimport type { MinimalFooterProps } from './types';\nimport { NEW_TAB_SUFFIX, NewTabIndicator } from './NewTabIndicator';\n\n/**\n * MinimalFooter — the Level-2 vertical footer.\n *\n * A Level-2 vertical (dissertation.ai, future rpkg.ai / sgpc.ai) is \"an embodiment\n * of dataimago\": the footer shows the parent `dataimago` wordmark linking UP to\n * dataimago.ai, the embodiment line, a compact links row, and a copyright line.\n * No nav columns, no philosophy — those belong to the Level-1 hub (SiteFooter +\n * PhilosophyFooter). See dataimago-design wiki/patterns/hub-hero-anatomy.\n */\n\nconst DEFAULT_BRAND_HREF = 'https://dataimago.ai';\nconst DEFAULT_EMBODIMENT = 'An embodiment of dataimago';\n\nexport function MinimalFooter({\n brandHref = DEFAULT_BRAND_HREF,\n embodimentLabel = DEFAULT_EMBODIMENT,\n links = [],\n copyright,\n}: MinimalFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto flex max-w-6xl flex-col items-center gap-4 px-6 py-10 text-center\">\n <a\n href={brandHref}\n className=\"inline-flex flex-col items-center gap-2 text-stone-100 transition hover:opacity-80\"\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label={`${embodimentLabel} — visit dataimago.ai${NEW_TAB_SUFFIX}`}\n >\n <Logo\n name=\"dataimago\"\n variant=\"PATH\"\n aria-hidden\n className=\"[&_svg]:h-7 [&_svg]:w-auto\"\n />\n <span className=\"text-sm text-stone-400\">\n {embodimentLabel}\n <NewTabIndicator hideText />\n </span>\n </a>\n\n {links.length > 0 ? (\n <nav\n className=\"flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm\"\n aria-label=\"Footer\"\n >\n {links.map(({ href, label, external }) =>\n !href ? (\n <span key={label} className=\"text-stone-400\">\n {label}\n </span>\n ) : external ? (\n <a\n key={label}\n href={href}\n className=\"text-stone-300 hover:text-paper-100\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={label} href={href} className=\"text-stone-300 hover:text-paper-100\">\n {label}\n </Link>\n )\n )}\n </nav>\n ) : null}\n\n {copyright ? <p className=\"text-xs text-stone-400\">{copyright}</p> : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { CopulaLockup, type CopulaLinkProps } from '@dataimago/ui';\nimport type { CopulaFooterProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * CopulaFooter — the slim dark footer every dataimago hub shares.\n *\n * LEFT: the copula lockup from @dataimago/ui, \"<property> is dataimago\": the\n * property wordmark (→ `propertyHref`), the `is_badge` disc, and the dataimago\n * wordmark (→ `brandHref`). The two wordmarks share one hover treatment. The\n * disc is a mark, not a link: at 16×16 it is below the WCAG 2.5.8 24×24\n * pointer-target floor, so it is read aloud as \"is\" and /philosophy stays in the\n * nav (wi-20260928-at-footer-badge-target-size). `dataimago=\"hidden\"` draws the\n * property mark alone, for apps that keep dataimago out of view while it is in\n * stealth (the maintainer, 2026-11-03).\n * RIGHT: a compact links row (e.g. Privacy · Terms). An optional copyright line\n * takes its own row below.\n *\n * Generalised from dissertation-ai's footer (dataimago/dissertation-ai#254); see\n * dataimago-design wiki/connections/is-copula-coupling.md.\n */\n\n// Internal hrefs go through next/link; anything else is a plain link.\nfunction FooterLink({ href, children, ...props }: CopulaLinkProps) {\n return href.startsWith('/') ? (\n <Link href={href} {...props}>\n {children}\n </Link>\n ) : (\n <a href={href} {...props}>\n {children}\n </a>\n );\n}\n\nexport function CopulaFooter({\n property,\n propertyLabel,\n propertyHref = '/',\n dataimago = 'shown',\n brandHref = 'https://dataimago.ai',\n links = [],\n linksLabel = 'Legal',\n copyright,\n}: CopulaFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto flex max-w-6xl flex-wrap items-center justify-between gap-x-6 gap-y-3 px-6 py-4\">\n <CopulaLockup\n property={property}\n propertyLabel={propertyLabel}\n propertyHref={propertyHref}\n dataimago={dataimago}\n brandHref={brandHref}\n linkClassName=\"text-stone-200 transition hover:text-stone-50\"\n badgeClassName=\"text-stone-200\"\n renderLink={FooterLink}\n />\n\n {links.length > 0 ? (\n <nav aria-label={linksLabel} className=\"flex flex-wrap items-center gap-x-5 gap-y-2 text-sm\">\n {links.map(({ href, label, external }) =>\n !href ? (\n <span key={label} className=\"text-stone-400\">\n {label}\n </span>\n ) : external ? (\n <a\n key={label}\n href={href}\n className=\"text-stone-400 transition hover:text-stone-200\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={label} href={href} className=\"text-stone-400 transition hover:text-stone-200\">\n {label}\n </Link>\n )\n )}\n </nav>\n ) : null}\n\n {copyright ? <p className=\"w-full text-xs text-stone-400\">{copyright}</p> : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport type { PhilosophyFooterProps } from './types';\n\n/**\n * Philosophy footer — the platform's moral weight, rendered as a dark\n * editorial section with three belief/mission/vision pairs and a pull-quote.\n *\n * Iteration-1 visual identity (Phase B.3, 2026-05-06):\n * Dark-surface chrome with text-accent-500 eyebrows, font-display body, and\n * the Baudrillard blockquote with border-copper-500 (preserved-decorative-\n * copper per iteration-1 §5.2 governance).\n *\n * Iteration-2 role-shift (2026-05-07): eyebrows were meant to resolve to\n * sky-blue accent-300 (#3498DB) on this dark surface via mode-aware mapping —\n * 5.41:1 on stone-900. The static Tailwind class `text-accent-500` binds the\n * absolute color instead (~2.56:1). 2026-09-05: eyebrows match SiteFooter\n * (`text-accent-300` + `data-bs-theme=\"dark\"`). The border-copper-500\n * blockquote frame survives untouched. \"Two warmths\" coexist: cool sky-blue\n * on editorial eyebrows, warm copper on the philosophical-quote frame.\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11). The `pairs`, `quote`, and `closingStatement` props allow\n * per-vertical adaptation; all props default to the Level-1 hub content.\n */\n\nconst DEFAULT_PAIRS = [\n {\n eyebrow: 'our belief',\n body: 'AI can enable virtuous cycles of improvement in the world.',\n },\n {\n eyebrow: 'our mission',\n body: 'The emancipation of humanity through ai super-alignment.',\n },\n {\n eyebrow: 'our vision',\n body: 'Super-alignment embeds ai in culture, not culture in ai.',\n },\n];\n\nconst DEFAULT_QUOTE = {\n text: `If men create intelligent machines, or fantasize about them, it is either because they secretly despair of their own intelligence or because they are in danger of succumbing to the weight of a monstrous and useless intelligence which they seek to exorcize by transferring it to machines, where they can play with it and make fun of it. By entrusting this burdensome intelligence to machines we are released from any responsibility to knowledge.`,\n attribution: 'Jean Baudrillard',\n work: 'Xerox and Infinity',\n year: 1988,\n};\n\nconst DEFAULT_CLOSING =\n 'dataimago is the structural answer to this critique. Every architectural choice — R as source of truth, editorial authority with the domain expert, the non-destructive retrofit principle, the ecosystem-as-commons — refuses to release the scholar from responsibility to their own knowledge. The AI serves the culture; the culture governs the AI.';\n\nexport function PhilosophyFooter({\n pairs = DEFAULT_PAIRS,\n quote = DEFAULT_QUOTE,\n closingStatement = DEFAULT_CLOSING,\n density = 'default',\n}: PhilosophyFooterProps) {\n const compact = density === 'compact';\n\n // Pull-quote — border-copper-500 PRESERVED: decorative-emphasis blockquote\n // frame per iteration-1 §5.2 preserved-decorative-copper governance.\n const pullQuote = (\n <blockquote\n className={`border-l-2 border-copper-500 pl-6 font-display italic text-paper-100 ${\n compact ? '' : 'mt-16 max-w-prose-wide'\n }`}\n >\n <p className=\"text-base leading-relaxed\">{quote.text}</p>\n <footer className=\"mt-4 text-sm not-italic text-stone-400\">\n — {quote.attribution}, <cite>{quote.work}</cite> ({quote.year})\n </footer>\n </blockquote>\n );\n\n const closing = (\n <p\n className={`text-stone-400 ${\n compact ? 'text-base leading-relaxed' : 'mt-8 max-w-prose-wide text-sm'\n }`}\n >\n {closingStatement}\n </p>\n );\n\n return (\n <section\n aria-labelledby=\"philosophy-heading\"\n className={`border-t border-stone-200 bg-stone-900 text-paper-100 ${\n compact\n ? 'flex flex-col justify-center py-14 sm:py-16 lg:min-h-[50vh]'\n : 'py-20 sm:py-28'\n }`}\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto w-full max-w-6xl px-6\">\n <div className={`grid lg:grid-cols-3 ${compact ? 'gap-8' : 'gap-12'}`}>\n {pairs.map((pair, i) => (\n <div key={i}>\n <p className=\"font-mono text-xs uppercase tracking-wider text-accent-300\">\n {pair.eyebrow}\n </p>\n {i === 0 ? (\n <h3\n id=\"philosophy-heading\"\n className=\"mt-2 font-display text-xl text-paper-100\"\n >\n {pair.body}\n </h3>\n ) : (\n <p className=\"mt-2 font-display text-xl text-paper-100\">\n {pair.body}\n </p>\n )}\n </div>\n ))}\n </div>\n\n {compact ? (\n // Critique / answer, side by side — Baudrillard's warning and\n // dataimago's structural answer. Filling the width is what pulls the\n // section down to ~half height (the default stacks these in one column,\n // leaving the right half empty).\n <div className=\"mt-10 grid gap-x-12 gap-y-8 lg:grid-cols-2\">\n {pullQuote}\n {closing}\n </div>\n ) : (\n <>\n {pullQuote}\n {closing}\n </>\n )}\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime","Link","import_jsx_runtime","import_link","import_ui","import_jsx_runtime","Link","import_link","import_ui","import_jsx_runtime","Link","import_link","import_ui","import_jsx_runtime","Link","import_jsx_runtime"]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { LogoProps, NavbarLogoProps } from '@dataimago/ui';
3
+ import { LogoProps, CopulaLockupProps, NavbarLogoProps } from '@dataimago/ui';
4
4
 
5
5
  /**
6
6
  * @dataimago/hub-chrome — configuration type surface.
@@ -24,6 +24,12 @@ type AiMonogram = boolean | {
24
24
  href: string;
25
25
  label?: string;
26
26
  };
27
+ /**
28
+ * Whether an app shows dataimago in its chrome. `'hidden'` is for apps that keep
29
+ * dataimago out of view while it is in stealth (the maintainer, 2026-11-03: the
30
+ * SGPc apps hide it, every other app shows it). Defaults to `'shown'`.
31
+ */
32
+ type DataimagoVisibility = 'shown' | 'hidden';
27
33
  /** A single navigation link or plain-text label (when href is omitted). */
28
34
  interface NavLink {
29
35
  /** Omit to render as a non-interactive text label (e.g. legacy items). */
@@ -68,6 +74,11 @@ interface PlatformNavProps {
68
74
  * mark (the dataimago "ai" signature). Omit/false to hide.
69
75
  */
70
76
  aiMonogram?: AiMonogram;
77
+ /**
78
+ * `'hidden'` drops the `aiMonogram` button (the dataimago "ai" signature and
79
+ * its link), whatever `aiMonogram` says. Defaults to `'shown'`.
80
+ */
81
+ dataimago?: DataimagoVisibility;
71
82
  /**
72
83
  * Accessible name for the logo/home link.
73
84
  * Defaults to "dataimago.ai home".
@@ -167,6 +178,32 @@ interface MinimalFooterProps {
167
178
  /** Optional copyright / fine-print line. */
168
179
  copyright?: string;
169
180
  }
181
+ /**
182
+ * CopulaFooter — the slim dark footer every dataimago hub shares: the copula
183
+ * lockup "<property> is dataimago" from @dataimago/ui, a compact links row, and
184
+ * an optional copyright line.
185
+ */
186
+ interface CopulaFooterProps {
187
+ /** The property's wordmark id, e.g. `dissertation_ai` or `dataimago_ai`. */
188
+ property: CopulaLockupProps['property'];
189
+ /** Accessible name of the property link, e.g. `dissertation-ai`. */
190
+ propertyLabel: string;
191
+ /** Where the property wordmark links. Defaults to `/`. */
192
+ propertyHref?: string;
193
+ /**
194
+ * `'shown'` (default): "<property> is dataimago". `'hidden'`: the property mark
195
+ * alone, with no badge, no dataimago wordmark and no link to dataimago.
196
+ */
197
+ dataimago?: DataimagoVisibility;
198
+ /** Where the dataimago wordmark links. Defaults to https://dataimago.ai. */
199
+ brandHref?: string;
200
+ /** The links row at the right (e.g. Privacy, Terms). Defaults to none. */
201
+ links?: NavLink[];
202
+ /** Accessible label for the links row's `<nav>`. Defaults to "Legal". */
203
+ linksLabel?: string;
204
+ /** Optional copyright / fine-print line, on its own row. */
205
+ copyright?: string;
206
+ }
170
207
  interface PhilosophyFooterProps {
171
208
  /**
172
209
  * The three editorial pairs (belief / mission / vision or equivalent).
@@ -196,7 +233,7 @@ interface PhilosophyFooterProps {
196
233
  density?: 'default' | 'compact';
197
234
  }
198
235
 
199
- declare function PlatformNav({ brandMark, navbarMark, aiMonogram, brandLabel, links, cta, rightSlot, navLabel, homeHref, }: PlatformNavProps): react_jsx_runtime.JSX.Element;
236
+ declare function PlatformNav({ brandMark, navbarMark, aiMonogram, dataimago, brandLabel, links, cta, rightSlot, navLabel, homeHref, }: PlatformNavProps): react_jsx_runtime.JSX.Element;
200
237
 
201
238
  declare function GitHubNavButton({ mode, status, login, avatarUrl, signInHref, profileHref, signOutAction, orgHref, defaultOpen, }: GitHubNavButtonProps): react_jsx_runtime.JSX.Element;
202
239
 
@@ -204,6 +241,8 @@ declare function SiteFooter({ tagline, columns, closingStatement, }: SiteFooterP
204
241
 
205
242
  declare function MinimalFooter({ brandHref, embodimentLabel, links, copyright, }: MinimalFooterProps): react_jsx_runtime.JSX.Element;
206
243
 
244
+ declare function CopulaFooter({ property, propertyLabel, propertyHref, dataimago, brandHref, links, linksLabel, copyright, }: CopulaFooterProps): react_jsx_runtime.JSX.Element;
245
+
207
246
  declare function PhilosophyFooter({ pairs, quote, closingStatement, density, }: PhilosophyFooterProps): react_jsx_runtime.JSX.Element;
208
247
 
209
- export { type AiMonogram, type BrandMark, type EditorialPair, type FooterColumn, GitHubNavButton, type GitHubNavButtonProps, MinimalFooter, type MinimalFooterProps, type NavLink, type NavbarMark, PhilosophyFooter, type PhilosophyFooterProps, PlatformNav, type PlatformNavProps, type PullQuote, SiteFooter, type SiteFooterProps };
248
+ export { type AiMonogram, type BrandMark, CopulaFooter, type CopulaFooterProps, type DataimagoVisibility, type EditorialPair, type FooterColumn, GitHubNavButton, type GitHubNavButtonProps, MinimalFooter, type MinimalFooterProps, type NavLink, type NavbarMark, PhilosophyFooter, type PhilosophyFooterProps, PlatformNav, type PlatformNavProps, type PullQuote, SiteFooter, type SiteFooterProps };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { LogoProps, NavbarLogoProps } from '@dataimago/ui';
3
+ import { LogoProps, CopulaLockupProps, NavbarLogoProps } from '@dataimago/ui';
4
4
 
5
5
  /**
6
6
  * @dataimago/hub-chrome — configuration type surface.
@@ -24,6 +24,12 @@ type AiMonogram = boolean | {
24
24
  href: string;
25
25
  label?: string;
26
26
  };
27
+ /**
28
+ * Whether an app shows dataimago in its chrome. `'hidden'` is for apps that keep
29
+ * dataimago out of view while it is in stealth (the maintainer, 2026-11-03: the
30
+ * SGPc apps hide it, every other app shows it). Defaults to `'shown'`.
31
+ */
32
+ type DataimagoVisibility = 'shown' | 'hidden';
27
33
  /** A single navigation link or plain-text label (when href is omitted). */
28
34
  interface NavLink {
29
35
  /** Omit to render as a non-interactive text label (e.g. legacy items). */
@@ -68,6 +74,11 @@ interface PlatformNavProps {
68
74
  * mark (the dataimago "ai" signature). Omit/false to hide.
69
75
  */
70
76
  aiMonogram?: AiMonogram;
77
+ /**
78
+ * `'hidden'` drops the `aiMonogram` button (the dataimago "ai" signature and
79
+ * its link), whatever `aiMonogram` says. Defaults to `'shown'`.
80
+ */
81
+ dataimago?: DataimagoVisibility;
71
82
  /**
72
83
  * Accessible name for the logo/home link.
73
84
  * Defaults to "dataimago.ai home".
@@ -167,6 +178,32 @@ interface MinimalFooterProps {
167
178
  /** Optional copyright / fine-print line. */
168
179
  copyright?: string;
169
180
  }
181
+ /**
182
+ * CopulaFooter — the slim dark footer every dataimago hub shares: the copula
183
+ * lockup "<property> is dataimago" from @dataimago/ui, a compact links row, and
184
+ * an optional copyright line.
185
+ */
186
+ interface CopulaFooterProps {
187
+ /** The property's wordmark id, e.g. `dissertation_ai` or `dataimago_ai`. */
188
+ property: CopulaLockupProps['property'];
189
+ /** Accessible name of the property link, e.g. `dissertation-ai`. */
190
+ propertyLabel: string;
191
+ /** Where the property wordmark links. Defaults to `/`. */
192
+ propertyHref?: string;
193
+ /**
194
+ * `'shown'` (default): "<property> is dataimago". `'hidden'`: the property mark
195
+ * alone, with no badge, no dataimago wordmark and no link to dataimago.
196
+ */
197
+ dataimago?: DataimagoVisibility;
198
+ /** Where the dataimago wordmark links. Defaults to https://dataimago.ai. */
199
+ brandHref?: string;
200
+ /** The links row at the right (e.g. Privacy, Terms). Defaults to none. */
201
+ links?: NavLink[];
202
+ /** Accessible label for the links row's `<nav>`. Defaults to "Legal". */
203
+ linksLabel?: string;
204
+ /** Optional copyright / fine-print line, on its own row. */
205
+ copyright?: string;
206
+ }
170
207
  interface PhilosophyFooterProps {
171
208
  /**
172
209
  * The three editorial pairs (belief / mission / vision or equivalent).
@@ -196,7 +233,7 @@ interface PhilosophyFooterProps {
196
233
  density?: 'default' | 'compact';
197
234
  }
198
235
 
199
- declare function PlatformNav({ brandMark, navbarMark, aiMonogram, brandLabel, links, cta, rightSlot, navLabel, homeHref, }: PlatformNavProps): react_jsx_runtime.JSX.Element;
236
+ declare function PlatformNav({ brandMark, navbarMark, aiMonogram, dataimago, brandLabel, links, cta, rightSlot, navLabel, homeHref, }: PlatformNavProps): react_jsx_runtime.JSX.Element;
200
237
 
201
238
  declare function GitHubNavButton({ mode, status, login, avatarUrl, signInHref, profileHref, signOutAction, orgHref, defaultOpen, }: GitHubNavButtonProps): react_jsx_runtime.JSX.Element;
202
239
 
@@ -204,6 +241,8 @@ declare function SiteFooter({ tagline, columns, closingStatement, }: SiteFooterP
204
241
 
205
242
  declare function MinimalFooter({ brandHref, embodimentLabel, links, copyright, }: MinimalFooterProps): react_jsx_runtime.JSX.Element;
206
243
 
244
+ declare function CopulaFooter({ property, propertyLabel, propertyHref, dataimago, brandHref, links, linksLabel, copyright, }: CopulaFooterProps): react_jsx_runtime.JSX.Element;
245
+
207
246
  declare function PhilosophyFooter({ pairs, quote, closingStatement, density, }: PhilosophyFooterProps): react_jsx_runtime.JSX.Element;
208
247
 
209
- export { type AiMonogram, type BrandMark, type EditorialPair, type FooterColumn, GitHubNavButton, type GitHubNavButtonProps, MinimalFooter, type MinimalFooterProps, type NavLink, type NavbarMark, PhilosophyFooter, type PhilosophyFooterProps, PlatformNav, type PlatformNavProps, type PullQuote, SiteFooter, type SiteFooterProps };
248
+ export { type AiMonogram, type BrandMark, CopulaFooter, type CopulaFooterProps, type DataimagoVisibility, type EditorialPair, type FooterColumn, GitHubNavButton, type GitHubNavButtonProps, MinimalFooter, type MinimalFooterProps, type NavLink, type NavbarMark, PhilosophyFooter, type PhilosophyFooterProps, PlatformNav, type PlatformNavProps, type PullQuote, SiteFooter, type SiteFooterProps };
package/dist/index.js CHANGED
@@ -45,6 +45,7 @@ function PlatformNav({
45
45
  brandMark = "dataimago_ai_OVERLAP",
46
46
  navbarMark,
47
47
  aiMonogram,
48
+ dataimago = "shown",
48
49
  brandLabel = "dataimago.ai home",
49
50
  links = DEFAULT_LINKS,
50
51
  cta = DEFAULT_CTA,
@@ -62,7 +63,7 @@ function PlatformNav({
62
63
  "aria-label": navLabel,
63
64
  children: [
64
65
  /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 sm:gap-3", children: [
65
- aiMonogram && (aiHref ? /* @__PURE__ */ jsx2(Link, { href: aiHref, "aria-label": aiLabel, className: AI_BUTTON_CLASS, children: /* @__PURE__ */ jsx2(NavbarLogo, { name: "ai-monogram", "aria-hidden": true, className: "[&_svg]:h-6 [&_svg]:w-auto" }) }) : /* @__PURE__ */ jsx2("span", { className: AI_BUTTON_CLASS, "aria-hidden": true, children: /* @__PURE__ */ jsx2(NavbarLogo, { name: "ai-monogram", "aria-hidden": true, className: "[&_svg]:h-6 [&_svg]:w-auto" }) })),
66
+ aiMonogram && dataimago === "shown" && (aiHref ? /* @__PURE__ */ jsx2(Link, { href: aiHref, "aria-label": aiLabel, className: AI_BUTTON_CLASS, children: /* @__PURE__ */ jsx2(NavbarLogo, { name: "ai-monogram", "aria-hidden": true, className: "[&_svg]:h-6 [&_svg]:w-auto" }) }) : /* @__PURE__ */ jsx2("span", { className: AI_BUTTON_CLASS, "aria-hidden": true, children: /* @__PURE__ */ jsx2(NavbarLogo, { name: "ai-monogram", "aria-hidden": true, className: "[&_svg]:h-6 [&_svg]:w-auto" }) })),
66
67
  /* @__PURE__ */ jsx2(
67
68
  Link,
68
69
  {
@@ -361,8 +362,66 @@ function MinimalFooter({
361
362
  );
362
363
  }
363
364
 
365
+ // src/CopulaFooter.tsx
366
+ import Link4 from "next/link";
367
+ import { CopulaLockup } from "@dataimago/ui";
368
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
369
+ function FooterLink({ href, children, ...props }) {
370
+ return href.startsWith("/") ? /* @__PURE__ */ jsx6(Link4, { href, ...props, children }) : /* @__PURE__ */ jsx6("a", { href, ...props, children });
371
+ }
372
+ function CopulaFooter({
373
+ property,
374
+ propertyLabel,
375
+ propertyHref = "/",
376
+ dataimago = "shown",
377
+ brandHref = "https://dataimago.ai",
378
+ links = [],
379
+ linksLabel = "Legal",
380
+ copyright
381
+ }) {
382
+ return /* @__PURE__ */ jsx6(
383
+ "footer",
384
+ {
385
+ className: "border-t border-stone-800 bg-stone-900 text-stone-400",
386
+ "data-bs-theme": "dark",
387
+ children: /* @__PURE__ */ jsxs6("div", { className: "mx-auto flex max-w-6xl flex-wrap items-center justify-between gap-x-6 gap-y-3 px-6 py-4", children: [
388
+ /* @__PURE__ */ jsx6(
389
+ CopulaLockup,
390
+ {
391
+ property,
392
+ propertyLabel,
393
+ propertyHref,
394
+ dataimago,
395
+ brandHref,
396
+ linkClassName: "text-stone-200 transition hover:text-stone-50",
397
+ badgeClassName: "text-stone-200",
398
+ renderLink: FooterLink
399
+ }
400
+ ),
401
+ links.length > 0 ? /* @__PURE__ */ jsx6("nav", { "aria-label": linksLabel, className: "flex flex-wrap items-center gap-x-5 gap-y-2 text-sm", children: links.map(
402
+ ({ href, label, external }) => !href ? /* @__PURE__ */ jsx6("span", { className: "text-stone-400", children: label }, label) : external ? /* @__PURE__ */ jsxs6(
403
+ "a",
404
+ {
405
+ href,
406
+ className: "text-stone-400 transition hover:text-stone-200",
407
+ target: "_blank",
408
+ rel: "noreferrer",
409
+ children: [
410
+ label,
411
+ /* @__PURE__ */ jsx6(NewTabIndicator, {})
412
+ ]
413
+ },
414
+ label
415
+ ) : /* @__PURE__ */ jsx6(Link4, { href, className: "text-stone-400 transition hover:text-stone-200", children: label }, label)
416
+ ) }) : null,
417
+ copyright ? /* @__PURE__ */ jsx6("p", { className: "w-full text-xs text-stone-400", children: copyright }) : null
418
+ ] })
419
+ }
420
+ );
421
+ }
422
+
364
423
  // src/PhilosophyFooter.tsx
365
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
424
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
366
425
  var DEFAULT_PAIRS = [
367
426
  {
368
427
  eyebrow: "our belief",
@@ -391,17 +450,17 @@ function PhilosophyFooter({
391
450
  density = "default"
392
451
  }) {
393
452
  const compact = density === "compact";
394
- const pullQuote = /* @__PURE__ */ jsxs6(
453
+ const pullQuote = /* @__PURE__ */ jsxs7(
395
454
  "blockquote",
396
455
  {
397
456
  className: `border-l-2 border-copper-500 pl-6 font-display italic text-paper-100 ${compact ? "" : "mt-16 max-w-prose-wide"}`,
398
457
  children: [
399
- /* @__PURE__ */ jsx6("p", { className: "text-base leading-relaxed", children: quote.text }),
400
- /* @__PURE__ */ jsxs6("footer", { className: "mt-4 text-sm not-italic text-stone-400", children: [
458
+ /* @__PURE__ */ jsx7("p", { className: "text-base leading-relaxed", children: quote.text }),
459
+ /* @__PURE__ */ jsxs7("footer", { className: "mt-4 text-sm not-italic text-stone-400", children: [
401
460
  "\u2014 ",
402
461
  quote.attribution,
403
462
  ", ",
404
- /* @__PURE__ */ jsx6("cite", { children: quote.work }),
463
+ /* @__PURE__ */ jsx7("cite", { children: quote.work }),
405
464
  " (",
406
465
  quote.year,
407
466
  ")"
@@ -409,41 +468,41 @@ function PhilosophyFooter({
409
468
  ]
410
469
  }
411
470
  );
412
- const closing = /* @__PURE__ */ jsx6(
471
+ const closing = /* @__PURE__ */ jsx7(
413
472
  "p",
414
473
  {
415
474
  className: `text-stone-400 ${compact ? "text-base leading-relaxed" : "mt-8 max-w-prose-wide text-sm"}`,
416
475
  children: closingStatement
417
476
  }
418
477
  );
419
- return /* @__PURE__ */ jsx6(
478
+ return /* @__PURE__ */ jsx7(
420
479
  "section",
421
480
  {
422
481
  "aria-labelledby": "philosophy-heading",
423
482
  className: `border-t border-stone-200 bg-stone-900 text-paper-100 ${compact ? "flex flex-col justify-center py-14 sm:py-16 lg:min-h-[50vh]" : "py-20 sm:py-28"}`,
424
483
  "data-bs-theme": "dark",
425
- children: /* @__PURE__ */ jsxs6("div", { className: "mx-auto w-full max-w-6xl px-6", children: [
426
- /* @__PURE__ */ jsx6("div", { className: `grid lg:grid-cols-3 ${compact ? "gap-8" : "gap-12"}`, children: pairs.map((pair, i) => /* @__PURE__ */ jsxs6("div", { children: [
427
- /* @__PURE__ */ jsx6("p", { className: "font-mono text-xs uppercase tracking-wider text-accent-300", children: pair.eyebrow }),
428
- i === 0 ? /* @__PURE__ */ jsx6(
484
+ children: /* @__PURE__ */ jsxs7("div", { className: "mx-auto w-full max-w-6xl px-6", children: [
485
+ /* @__PURE__ */ jsx7("div", { className: `grid lg:grid-cols-3 ${compact ? "gap-8" : "gap-12"}`, children: pairs.map((pair, i) => /* @__PURE__ */ jsxs7("div", { children: [
486
+ /* @__PURE__ */ jsx7("p", { className: "font-mono text-xs uppercase tracking-wider text-accent-300", children: pair.eyebrow }),
487
+ i === 0 ? /* @__PURE__ */ jsx7(
429
488
  "h3",
430
489
  {
431
490
  id: "philosophy-heading",
432
491
  className: "mt-2 font-display text-xl text-paper-100",
433
492
  children: pair.body
434
493
  }
435
- ) : /* @__PURE__ */ jsx6("p", { className: "mt-2 font-display text-xl text-paper-100", children: pair.body })
494
+ ) : /* @__PURE__ */ jsx7("p", { className: "mt-2 font-display text-xl text-paper-100", children: pair.body })
436
495
  ] }, i)) }),
437
496
  compact ? (
438
497
  // Critique / answer, side by side — Baudrillard's warning and
439
498
  // dataimago's structural answer. Filling the width is what pulls the
440
499
  // section down to ~half height (the default stacks these in one column,
441
500
  // leaving the right half empty).
442
- /* @__PURE__ */ jsxs6("div", { className: "mt-10 grid gap-x-12 gap-y-8 lg:grid-cols-2", children: [
501
+ /* @__PURE__ */ jsxs7("div", { className: "mt-10 grid gap-x-12 gap-y-8 lg:grid-cols-2", children: [
443
502
  pullQuote,
444
503
  closing
445
504
  ] })
446
- ) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
505
+ ) : /* @__PURE__ */ jsxs7(Fragment2, { children: [
447
506
  pullQuote,
448
507
  closing
449
508
  ] })
@@ -452,6 +511,7 @@ function PhilosophyFooter({
452
511
  );
453
512
  }
454
513
  export {
514
+ CopulaFooter,
455
515
  GitHubNavButton,
456
516
  MinimalFooter,
457
517
  PhilosophyFooter,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/PlatformNav.tsx","../src/NewTabIndicator.tsx","../src/GitHubNavButton.tsx","../src/SiteFooter.tsx","../src/MinimalFooter.tsx","../src/PhilosophyFooter.tsx"],"sourcesContent":["'use client';\n\nimport Link from 'next/link';\nimport { Logo, NavbarLogo } from '@dataimago/ui';\nimport type { PlatformNavProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * Platform navigation — sticky header with the property's brand mark + nav cluster.\n *\n * The property mark is rendered by height (so any aspect fits the nav). By default\n * it's the static `@dataimago/brand` wordmark via `<Logo>` (font-free, IoU-locked,\n * `currentColor`). When `navbarMark` is set it becomes the ANIMATED `<NavbarLogo>`\n * (the a/i assemble toggle for L2 marks, lift+wash for L1) — falling back to the\n * static `<Logo brandMark>` otherwise, so pre-navbar consumers are unaffected.\n *\n * `aiMonogram` adds the dataimago `ai-monogram` icon button to the LEFT of the\n * property mark (a 48px touch target; lift+washes to the brand-mark red on hover).\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11); `navbarMark`/`aiMonogram` added in iteration-4 (the navbar logo\n * system). All props default to the Level-1 hub configuration.\n */\n\nconst DEFAULT_LINKS = [\n { href: '/ecosystem', label: 'Ecosystem' },\n { href: '/philosophy', label: 'Philosophy' },\n];\n\nconst DEFAULT_CTA = { href: '/onboard', label: 'Begin' };\n\n/** Height-based sizing for the property mark (the navbar norm — ~30% larger letters). */\nconst MARK_CLASS = '[&_svg]:h-7 [&_svg]:w-auto sm:[&_svg]:h-8';\n\n/** The optional ai-monogram icon button — a 48px touch target (ready-to-hand floor). */\nconst AI_BUTTON_CLASS =\n 'inline-flex min-h-[48px] min-w-[48px] items-center justify-center rounded-xl ' +\n 'border border-stone-200 bg-stone-50 text-stone-900 transition hover:bg-stone-100';\n\nexport function PlatformNav({\n brandMark = 'dataimago_ai_OVERLAP',\n navbarMark,\n aiMonogram,\n brandLabel = 'dataimago.ai home',\n links = DEFAULT_LINKS,\n cta = DEFAULT_CTA,\n rightSlot,\n navLabel = 'Primary',\n homeHref = '/',\n}: PlatformNavProps) {\n const propertyMark = navbarMark ? (\n <NavbarLogo name={navbarMark} aria-hidden className={MARK_CLASS} />\n ) : (\n <Logo name={brandMark} variant=\"PATH\" aria-hidden className={MARK_CLASS} />\n );\n\n const aiHref = typeof aiMonogram === 'object' ? aiMonogram.href : undefined;\n const aiLabel =\n typeof aiMonogram === 'object' ? (aiMonogram.label ?? 'dataimago') : 'dataimago';\n\n return (\n <header className=\"sticky top-0 z-40 border-b border-stone-200 bg-stone-100/95 backdrop-blur-sm\">\n <nav\n className=\"mx-auto flex max-w-7xl items-center justify-between px-6 py-4\"\n aria-label={navLabel}\n >\n <div className=\"flex items-center gap-2 sm:gap-3\">\n {aiMonogram &&\n (aiHref ? (\n <Link href={aiHref} aria-label={aiLabel} className={AI_BUTTON_CLASS}>\n <NavbarLogo name=\"ai-monogram\" aria-hidden className=\"[&_svg]:h-6 [&_svg]:w-auto\" />\n </Link>\n ) : (\n <span className={AI_BUTTON_CLASS} aria-hidden>\n <NavbarLogo name=\"ai-monogram\" aria-hidden className=\"[&_svg]:h-6 [&_svg]:w-auto\" />\n </span>\n ))}\n <Link\n href={homeHref}\n className=\"inline-flex min-h-[48px] items-center text-stone-900 transition hover:opacity-80\"\n aria-label={brandLabel}\n >\n {propertyMark}\n </Link>\n </div>\n\n <div className=\"flex items-center gap-2 sm:gap-6\">\n {links.map(({ href, label, external }) =>\n external ? (\n <a\n key={href}\n href={href}\n className=\"btn-ghost hidden sm:inline-flex\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={href} href={href} className=\"btn-ghost hidden sm:inline-flex\">\n {label}\n </Link>\n )\n )}\n {cta && (\n <Link href={cta.href} className=\"btn-primary\">\n {cta.label}\n </Link>\n )}\n {rightSlot}\n </div>\n </nav>\n </header>\n );\n}\n","/**\n * Disclosure for links that open in a new tab (WCAG 3.2.5), shared by every\n * `target=\"_blank\"` link in this package so sighted and screen-reader users get\n * the same warning.\n *\n * - Sighted: a small \"arrow out of a box\" glyph after the link content.\n * - Screen reader: the visually hidden text \"(opens in a new tab)\", appended to\n * the link's accessible name. For a link that sets `aria-label` (which\n * replaces its content in the name), append `NEW_TAB_SUFFIX` to the label\n * instead and pass `hideText` so the name is not announced twice.\n */\nexport const NEW_TAB_SUFFIX = ' (opens in a new tab)';\n\nexport function NewTabIndicator({ hideText = false }: { hideText?: boolean }) {\n return (\n <>\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n viewBox=\"0 0 24 24\"\n width=\"0.85em\"\n height=\"0.85em\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"ml-1 inline-block shrink-0 align-baseline\"\n >\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n {hideText ? null : <span className=\"sr-only\">{NEW_TAB_SUFFIX}</span>}\n </>\n );\n}\n","import type { GitHubNavButtonProps } from './types';\nimport { NEW_TAB_SUFFIX, NewTabIndicator } from './NewTabIndicator';\n\n/**\n * The unified GitHub account control for the nav's right slot — the canonical\n * login affordance + login-state indicator shared across every L1/L2 dataimago\n * app (rendered into `PlatformNav`'s `rightSlot`).\n *\n * Fully presentational and **stateless** — it reads no auth itself; the consumer\n * feeds it. Uses a native `<details>` disclosure for the signed-in menu, so it\n * needs no client JS and works whether rendered on the server (a server parent\n * injecting the avatar) or the client.\n *\n * - `mode=\"auth\"` (default): the login-state indicator.\n * - `status=\"unauthed\"` → a GET link to `signInHref` (start OAuth) showing the\n * GitHub mark + a login glyph.\n * - `status=\"authed\"` → the GitHub mark + the user's avatar, opening a menu\n * (profile link + a POST sign-out form to `signOutAction`).\n * - `mode=\"link\"`: a plain GitHub→`orgHref` link (L1, which has no auth).\n *\n * Icons are inlined (the GitHub mark + a lucide-style \"log-in\" glyph) to keep the\n * shared package free of an icon-library peer dependency.\n */\n\n// The 48px touch-target floor (the ready-to-hand dignity gate); colours resolve\n// from the consuming app's dataimago palette. The global `*:focus-visible` rule\n// supplies the focus ring.\nconst SHELL =\n 'inline-flex min-h-[48px] items-center gap-2 rounded-xl border border-stone-200 ' +\n 'bg-stone-50 px-3 text-stone-900 transition hover:bg-stone-100';\n\nconst MENU_ITEM =\n 'flex min-h-[48px] w-full items-center rounded px-2 text-left text-sm ' +\n 'text-stone-900 transition hover:bg-stone-100';\n\nfunction GithubMark() {\n return (\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" className=\"h-5 w-5 shrink-0\" fill=\"currentColor\">\n <path d=\"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23a11.5 11.5 0 0 1 3.003-.404c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.014 2.898-.014 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" />\n </svg>\n );\n}\n\nfunction LoginGlyph() {\n // lucide \"log-in\" (ISC), inlined.\n return (\n <svg\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n className=\"h-5 w-5 shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\" />\n <polyline points=\"10 17 15 12 10 7\" />\n <line x1=\"15\" x2=\"3\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\nexport function GitHubNavButton({\n mode = 'auth',\n status = 'unauthed',\n login,\n avatarUrl,\n signInHref,\n profileHref,\n signOutAction,\n orgHref,\n defaultOpen,\n}: GitHubNavButtonProps) {\n // L1 mode: a plain GitHub→org link (no auth).\n if (mode === 'link') {\n return (\n <a\n href={orgHref}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={SHELL}\n aria-label={`dataimago on GitHub${NEW_TAB_SUFFIX}`}\n >\n <GithubMark />\n <NewTabIndicator hideText />\n </a>\n );\n }\n\n // Signed out: a GET link that starts the OAuth flow.\n if (status !== 'authed') {\n return (\n <a href={signInHref} className={SHELL} aria-label=\"Sign in with GitHub\">\n <GithubMark />\n <LoginGlyph />\n </a>\n );\n }\n\n // Signed in: the GitHub mark + the user's avatar, with a native-disclosure menu.\n return (\n <details className=\"relative\" open={defaultOpen}>\n <summary\n className={`${SHELL} cursor-pointer list-none [&::-webkit-details-marker]:hidden`}\n aria-label={`GitHub account — signed in as ${login ?? 'your account'}`}\n >\n <GithubMark />\n {avatarUrl ? (\n <img\n src={avatarUrl}\n alt=\"\"\n className=\"h-7 w-7 rounded-full border border-stone-200\"\n width={28}\n height={28}\n />\n ) : (\n <span className=\"text-sm font-medium\">@{login}</span>\n )}\n </summary>\n <div className=\"absolute right-0 z-50 mt-2 w-60 rounded-lg border border-stone-200 bg-stone-50 p-2 shadow-lg\">\n <p className=\"px-2 py-1 text-sm text-stone-700\">\n Signed in as <span className=\"font-medium text-stone-900\">@{login}</span>\n </p>\n {profileHref && (\n <a href={profileHref} target=\"_blank\" rel=\"noreferrer\" className={MENU_ITEM}>\n View your GitHub profile\n <NewTabIndicator />\n </a>\n )}\n {signOutAction && (\n <form method=\"POST\" action={signOutAction}>\n <button type=\"submit\" className={MENU_ITEM}>\n Sign out\n </button>\n </form>\n )}\n </div>\n </details>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo } from '@dataimago/ui';\nimport type { SiteFooterProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * Site footer — the Level-1 hub footer: dark surface, dataimago wordmark + a\n * trimmed nav column grid.\n *\n * The wordmark is the `dataimago` brand mark via `<Logo>` (font-free, in a light\n * `currentColor` on the dark surface) — no backplate, no hardcoded \".ai\" span.\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11). The defaults drop the former \"Legacy\" column + the critical-theory\n * closing statement (the philosophical-basis editorial lives on the PhilosophyFooter,\n * which is Level-1-only). Level-2 verticals use `MinimalFooter` instead.\n */\n\nconst DEFAULT_TAGLINE = 'A living AI-native application ecosystem.';\n\nconst DEFAULT_COLUMNS = [\n {\n heading: 'Platform',\n links: [\n { href: '/onboard', label: 'Begin a project' },\n { href: '/ecosystem', label: 'Ecosystem' },\n { href: '/philosophy', label: 'Philosophy' },\n ],\n },\n {\n heading: 'Framework',\n links: [\n {\n href: 'https://github.com/dataimago/dataimago-design',\n label: 'dataimago-design',\n external: true,\n },\n {\n href: 'https://github.com/dataimago/dataimago',\n label: 'dataimago',\n external: true,\n },\n {\n href: 'https://github.com/dataimago/dataimago-ai',\n label: 'dataimago-ai',\n external: true,\n },\n ],\n },\n];\n\nexport function SiteFooter({\n tagline = DEFAULT_TAGLINE,\n columns = DEFAULT_COLUMNS,\n closingStatement,\n}: SiteFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto max-w-6xl px-6 py-12\">\n <div className=\"grid gap-8 md:grid-cols-4\">\n <div>\n <Link\n href=\"/\"\n className=\"inline-flex items-center text-stone-100 transition hover:opacity-80\"\n aria-label=\"dataimago\"\n >\n <Logo\n name=\"dataimago\"\n variant=\"PATH\"\n aria-hidden\n className=\"[&_svg]:h-7 [&_svg]:w-auto\"\n />\n </Link>\n <p className=\"mt-3 text-xs text-stone-400\">{tagline}</p>\n </div>\n\n {columns.map((col) => (\n <div key={col.heading}>\n <h4 className=\"font-mono text-xs uppercase tracking-wider text-accent-300\">\n {col.heading}\n </h4>\n <ul className=\"mt-3 space-y-2 text-sm\">\n {col.links.map(({ href, label, external }) => (\n <li key={label}>\n {!href ? (\n label\n ) : external ? (\n <a\n href={href}\n className=\"hover:text-paper-100\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link href={href} className=\"hover:text-paper-100\">\n {label}\n </Link>\n )}\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n\n {closingStatement ? (\n <div className=\"mt-12 border-t border-stone-800 pt-6 text-xs text-stone-400\">\n <p>{closingStatement}</p>\n </div>\n ) : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo } from '@dataimago/ui';\nimport type { MinimalFooterProps } from './types';\nimport { NEW_TAB_SUFFIX, NewTabIndicator } from './NewTabIndicator';\n\n/**\n * MinimalFooter — the Level-2 vertical footer.\n *\n * A Level-2 vertical (dissertation.ai, future rpkg.ai / sgpc.ai) is \"an embodiment\n * of dataimago\": the footer shows the parent `dataimago` wordmark linking UP to\n * dataimago.ai, the embodiment line, a compact links row, and a copyright line.\n * No nav columns, no philosophy — those belong to the Level-1 hub (SiteFooter +\n * PhilosophyFooter). See dataimago-design wiki/patterns/hub-hero-anatomy.\n */\n\nconst DEFAULT_BRAND_HREF = 'https://dataimago.ai';\nconst DEFAULT_EMBODIMENT = 'An embodiment of dataimago';\n\nexport function MinimalFooter({\n brandHref = DEFAULT_BRAND_HREF,\n embodimentLabel = DEFAULT_EMBODIMENT,\n links = [],\n copyright,\n}: MinimalFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto flex max-w-6xl flex-col items-center gap-4 px-6 py-10 text-center\">\n <a\n href={brandHref}\n className=\"inline-flex flex-col items-center gap-2 text-stone-100 transition hover:opacity-80\"\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label={`${embodimentLabel} — visit dataimago.ai${NEW_TAB_SUFFIX}`}\n >\n <Logo\n name=\"dataimago\"\n variant=\"PATH\"\n aria-hidden\n className=\"[&_svg]:h-7 [&_svg]:w-auto\"\n />\n <span className=\"text-sm text-stone-400\">\n {embodimentLabel}\n <NewTabIndicator hideText />\n </span>\n </a>\n\n {links.length > 0 ? (\n <nav\n className=\"flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm\"\n aria-label=\"Footer\"\n >\n {links.map(({ href, label, external }) =>\n !href ? (\n <span key={label} className=\"text-stone-400\">\n {label}\n </span>\n ) : external ? (\n <a\n key={label}\n href={href}\n className=\"text-stone-300 hover:text-paper-100\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={label} href={href} className=\"text-stone-300 hover:text-paper-100\">\n {label}\n </Link>\n )\n )}\n </nav>\n ) : null}\n\n {copyright ? <p className=\"text-xs text-stone-400\">{copyright}</p> : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport type { PhilosophyFooterProps } from './types';\n\n/**\n * Philosophy footer — the platform's moral weight, rendered as a dark\n * editorial section with three belief/mission/vision pairs and a pull-quote.\n *\n * Iteration-1 visual identity (Phase B.3, 2026-05-06):\n * Dark-surface chrome with text-accent-500 eyebrows, font-display body, and\n * the Baudrillard blockquote with border-copper-500 (preserved-decorative-\n * copper per iteration-1 §5.2 governance).\n *\n * Iteration-2 role-shift (2026-05-07): eyebrows were meant to resolve to\n * sky-blue accent-300 (#3498DB) on this dark surface via mode-aware mapping —\n * 5.41:1 on stone-900. The static Tailwind class `text-accent-500` binds the\n * absolute color instead (~2.56:1). 2026-09-05: eyebrows match SiteFooter\n * (`text-accent-300` + `data-bs-theme=\"dark\"`). The border-copper-500\n * blockquote frame survives untouched. \"Two warmths\" coexist: cool sky-blue\n * on editorial eyebrows, warm copper on the philosophical-quote frame.\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11). The `pairs`, `quote`, and `closingStatement` props allow\n * per-vertical adaptation; all props default to the Level-1 hub content.\n */\n\nconst DEFAULT_PAIRS = [\n {\n eyebrow: 'our belief',\n body: 'AI can enable virtuous cycles of improvement in the world.',\n },\n {\n eyebrow: 'our mission',\n body: 'The emancipation of humanity through ai super-alignment.',\n },\n {\n eyebrow: 'our vision',\n body: 'Super-alignment embeds ai in culture, not culture in ai.',\n },\n];\n\nconst DEFAULT_QUOTE = {\n text: `If men create intelligent machines, or fantasize about them, it is either because they secretly despair of their own intelligence or because they are in danger of succumbing to the weight of a monstrous and useless intelligence which they seek to exorcize by transferring it to machines, where they can play with it and make fun of it. By entrusting this burdensome intelligence to machines we are released from any responsibility to knowledge.`,\n attribution: 'Jean Baudrillard',\n work: 'Xerox and Infinity',\n year: 1988,\n};\n\nconst DEFAULT_CLOSING =\n 'dataimago is the structural answer to this critique. Every architectural choice — R as source of truth, editorial authority with the domain expert, the non-destructive retrofit principle, the ecosystem-as-commons — refuses to release the scholar from responsibility to their own knowledge. The AI serves the culture; the culture governs the AI.';\n\nexport function PhilosophyFooter({\n pairs = DEFAULT_PAIRS,\n quote = DEFAULT_QUOTE,\n closingStatement = DEFAULT_CLOSING,\n density = 'default',\n}: PhilosophyFooterProps) {\n const compact = density === 'compact';\n\n // Pull-quote — border-copper-500 PRESERVED: decorative-emphasis blockquote\n // frame per iteration-1 §5.2 preserved-decorative-copper governance.\n const pullQuote = (\n <blockquote\n className={`border-l-2 border-copper-500 pl-6 font-display italic text-paper-100 ${\n compact ? '' : 'mt-16 max-w-prose-wide'\n }`}\n >\n <p className=\"text-base leading-relaxed\">{quote.text}</p>\n <footer className=\"mt-4 text-sm not-italic text-stone-400\">\n — {quote.attribution}, <cite>{quote.work}</cite> ({quote.year})\n </footer>\n </blockquote>\n );\n\n const closing = (\n <p\n className={`text-stone-400 ${\n compact ? 'text-base leading-relaxed' : 'mt-8 max-w-prose-wide text-sm'\n }`}\n >\n {closingStatement}\n </p>\n );\n\n return (\n <section\n aria-labelledby=\"philosophy-heading\"\n className={`border-t border-stone-200 bg-stone-900 text-paper-100 ${\n compact\n ? 'flex flex-col justify-center py-14 sm:py-16 lg:min-h-[50vh]'\n : 'py-20 sm:py-28'\n }`}\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto w-full max-w-6xl px-6\">\n <div className={`grid lg:grid-cols-3 ${compact ? 'gap-8' : 'gap-12'}`}>\n {pairs.map((pair, i) => (\n <div key={i}>\n <p className=\"font-mono text-xs uppercase tracking-wider text-accent-300\">\n {pair.eyebrow}\n </p>\n {i === 0 ? (\n <h3\n id=\"philosophy-heading\"\n className=\"mt-2 font-display text-xl text-paper-100\"\n >\n {pair.body}\n </h3>\n ) : (\n <p className=\"mt-2 font-display text-xl text-paper-100\">\n {pair.body}\n </p>\n )}\n </div>\n ))}\n </div>\n\n {compact ? (\n // Critique / answer, side by side — Baudrillard's warning and\n // dataimago's structural answer. Filling the width is what pulls the\n // section down to ~half height (the default stacks these in one column,\n // leaving the right half empty).\n <div className=\"mt-10 grid gap-x-12 gap-y-8 lg:grid-cols-2\">\n {pullQuote}\n {closing}\n </div>\n ) : (\n <>\n {pullQuote}\n {closing}\n </>\n )}\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","Link","Logo","jsx","jsxs","Link","Logo","Link","Logo","jsx","jsxs","Logo","Link","Fragment","jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/PlatformNav.tsx","../src/NewTabIndicator.tsx","../src/GitHubNavButton.tsx","../src/SiteFooter.tsx","../src/MinimalFooter.tsx","../src/CopulaFooter.tsx","../src/PhilosophyFooter.tsx"],"sourcesContent":["'use client';\n\nimport Link from 'next/link';\nimport { Logo, NavbarLogo } from '@dataimago/ui';\nimport type { PlatformNavProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * Platform navigation — sticky header with the property's brand mark + nav cluster.\n *\n * The property mark is rendered by height (so any aspect fits the nav). By default\n * it's the static `@dataimago/brand` wordmark via `<Logo>` (font-free, IoU-locked,\n * `currentColor`). When `navbarMark` is set it becomes the ANIMATED `<NavbarLogo>`\n * (the a/i assemble toggle for L2 marks, lift+wash for L1) — falling back to the\n * static `<Logo brandMark>` otherwise, so pre-navbar consumers are unaffected.\n *\n * `aiMonogram` adds the dataimago `ai-monogram` icon button to the LEFT of the\n * property mark (a 48px touch target; lift+washes to the brand-mark red on hover).\n * `dataimago=\"hidden\"` drops it, for apps that keep dataimago out of view while\n * it is in stealth (the maintainer, 2026-11-03).\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11); `navbarMark`/`aiMonogram` added in iteration-4 (the navbar logo\n * system). All props default to the Level-1 hub configuration.\n */\n\nconst DEFAULT_LINKS = [\n { href: '/ecosystem', label: 'Ecosystem' },\n { href: '/philosophy', label: 'Philosophy' },\n];\n\nconst DEFAULT_CTA = { href: '/onboard', label: 'Begin' };\n\n/** Height-based sizing for the property mark (the navbar norm — ~30% larger letters). */\nconst MARK_CLASS = '[&_svg]:h-7 [&_svg]:w-auto sm:[&_svg]:h-8';\n\n/** The optional ai-monogram icon button — a 48px touch target (ready-to-hand floor). */\nconst AI_BUTTON_CLASS =\n 'inline-flex min-h-[48px] min-w-[48px] items-center justify-center rounded-xl ' +\n 'border border-stone-200 bg-stone-50 text-stone-900 transition hover:bg-stone-100';\n\nexport function PlatformNav({\n brandMark = 'dataimago_ai_OVERLAP',\n navbarMark,\n aiMonogram,\n dataimago = 'shown',\n brandLabel = 'dataimago.ai home',\n links = DEFAULT_LINKS,\n cta = DEFAULT_CTA,\n rightSlot,\n navLabel = 'Primary',\n homeHref = '/',\n}: PlatformNavProps) {\n const propertyMark = navbarMark ? (\n <NavbarLogo name={navbarMark} aria-hidden className={MARK_CLASS} />\n ) : (\n <Logo name={brandMark} variant=\"PATH\" aria-hidden className={MARK_CLASS} />\n );\n\n const aiHref = typeof aiMonogram === 'object' ? aiMonogram.href : undefined;\n const aiLabel =\n typeof aiMonogram === 'object' ? (aiMonogram.label ?? 'dataimago') : 'dataimago';\n\n return (\n <header className=\"sticky top-0 z-40 border-b border-stone-200 bg-stone-100/95 backdrop-blur-sm\">\n <nav\n className=\"mx-auto flex max-w-7xl items-center justify-between px-6 py-4\"\n aria-label={navLabel}\n >\n <div className=\"flex items-center gap-2 sm:gap-3\">\n {aiMonogram && dataimago === 'shown' &&\n (aiHref ? (\n <Link href={aiHref} aria-label={aiLabel} className={AI_BUTTON_CLASS}>\n <NavbarLogo name=\"ai-monogram\" aria-hidden className=\"[&_svg]:h-6 [&_svg]:w-auto\" />\n </Link>\n ) : (\n <span className={AI_BUTTON_CLASS} aria-hidden>\n <NavbarLogo name=\"ai-monogram\" aria-hidden className=\"[&_svg]:h-6 [&_svg]:w-auto\" />\n </span>\n ))}\n <Link\n href={homeHref}\n className=\"inline-flex min-h-[48px] items-center text-stone-900 transition hover:opacity-80\"\n aria-label={brandLabel}\n >\n {propertyMark}\n </Link>\n </div>\n\n <div className=\"flex items-center gap-2 sm:gap-6\">\n {links.map(({ href, label, external }) =>\n external ? (\n <a\n key={href}\n href={href}\n className=\"btn-ghost hidden sm:inline-flex\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={href} href={href} className=\"btn-ghost hidden sm:inline-flex\">\n {label}\n </Link>\n )\n )}\n {cta && (\n <Link href={cta.href} className=\"btn-primary\">\n {cta.label}\n </Link>\n )}\n {rightSlot}\n </div>\n </nav>\n </header>\n );\n}\n","/**\n * Disclosure for links that open in a new tab (WCAG 3.2.5), shared by every\n * `target=\"_blank\"` link in this package so sighted and screen-reader users get\n * the same warning.\n *\n * - Sighted: a small \"arrow out of a box\" glyph after the link content.\n * - Screen reader: the visually hidden text \"(opens in a new tab)\", appended to\n * the link's accessible name. For a link that sets `aria-label` (which\n * replaces its content in the name), append `NEW_TAB_SUFFIX` to the label\n * instead and pass `hideText` so the name is not announced twice.\n */\nexport const NEW_TAB_SUFFIX = ' (opens in a new tab)';\n\nexport function NewTabIndicator({ hideText = false }: { hideText?: boolean }) {\n return (\n <>\n <svg\n aria-hidden=\"true\"\n focusable=\"false\"\n viewBox=\"0 0 24 24\"\n width=\"0.85em\"\n height=\"0.85em\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"ml-1 inline-block shrink-0 align-baseline\"\n >\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n {hideText ? null : <span className=\"sr-only\">{NEW_TAB_SUFFIX}</span>}\n </>\n );\n}\n","import type { GitHubNavButtonProps } from './types';\nimport { NEW_TAB_SUFFIX, NewTabIndicator } from './NewTabIndicator';\n\n/**\n * The unified GitHub account control for the nav's right slot — the canonical\n * login affordance + login-state indicator shared across every L1/L2 dataimago\n * app (rendered into `PlatformNav`'s `rightSlot`).\n *\n * Fully presentational and **stateless** — it reads no auth itself; the consumer\n * feeds it. Uses a native `<details>` disclosure for the signed-in menu, so it\n * needs no client JS and works whether rendered on the server (a server parent\n * injecting the avatar) or the client.\n *\n * - `mode=\"auth\"` (default): the login-state indicator.\n * - `status=\"unauthed\"` → a GET link to `signInHref` (start OAuth) showing the\n * GitHub mark + a login glyph.\n * - `status=\"authed\"` → the GitHub mark + the user's avatar, opening a menu\n * (profile link + a POST sign-out form to `signOutAction`).\n * - `mode=\"link\"`: a plain GitHub→`orgHref` link (L1, which has no auth).\n *\n * Icons are inlined (the GitHub mark + a lucide-style \"log-in\" glyph) to keep the\n * shared package free of an icon-library peer dependency.\n */\n\n// The 48px touch-target floor (the ready-to-hand dignity gate); colours resolve\n// from the consuming app's dataimago palette. The global `*:focus-visible` rule\n// supplies the focus ring.\nconst SHELL =\n 'inline-flex min-h-[48px] items-center gap-2 rounded-xl border border-stone-200 ' +\n 'bg-stone-50 px-3 text-stone-900 transition hover:bg-stone-100';\n\nconst MENU_ITEM =\n 'flex min-h-[48px] w-full items-center rounded px-2 text-left text-sm ' +\n 'text-stone-900 transition hover:bg-stone-100';\n\nfunction GithubMark() {\n return (\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" className=\"h-5 w-5 shrink-0\" fill=\"currentColor\">\n <path d=\"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23a11.5 11.5 0 0 1 3.003-.404c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.014 2.898-.014 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" />\n </svg>\n );\n}\n\nfunction LoginGlyph() {\n // lucide \"log-in\" (ISC), inlined.\n return (\n <svg\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n className=\"h-5 w-5 shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\" />\n <polyline points=\"10 17 15 12 10 7\" />\n <line x1=\"15\" x2=\"3\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\nexport function GitHubNavButton({\n mode = 'auth',\n status = 'unauthed',\n login,\n avatarUrl,\n signInHref,\n profileHref,\n signOutAction,\n orgHref,\n defaultOpen,\n}: GitHubNavButtonProps) {\n // L1 mode: a plain GitHub→org link (no auth).\n if (mode === 'link') {\n return (\n <a\n href={orgHref}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={SHELL}\n aria-label={`dataimago on GitHub${NEW_TAB_SUFFIX}`}\n >\n <GithubMark />\n <NewTabIndicator hideText />\n </a>\n );\n }\n\n // Signed out: a GET link that starts the OAuth flow.\n if (status !== 'authed') {\n return (\n <a href={signInHref} className={SHELL} aria-label=\"Sign in with GitHub\">\n <GithubMark />\n <LoginGlyph />\n </a>\n );\n }\n\n // Signed in: the GitHub mark + the user's avatar, with a native-disclosure menu.\n return (\n <details className=\"relative\" open={defaultOpen}>\n <summary\n className={`${SHELL} cursor-pointer list-none [&::-webkit-details-marker]:hidden`}\n aria-label={`GitHub account — signed in as ${login ?? 'your account'}`}\n >\n <GithubMark />\n {avatarUrl ? (\n <img\n src={avatarUrl}\n alt=\"\"\n className=\"h-7 w-7 rounded-full border border-stone-200\"\n width={28}\n height={28}\n />\n ) : (\n <span className=\"text-sm font-medium\">@{login}</span>\n )}\n </summary>\n <div className=\"absolute right-0 z-50 mt-2 w-60 rounded-lg border border-stone-200 bg-stone-50 p-2 shadow-lg\">\n <p className=\"px-2 py-1 text-sm text-stone-700\">\n Signed in as <span className=\"font-medium text-stone-900\">@{login}</span>\n </p>\n {profileHref && (\n <a href={profileHref} target=\"_blank\" rel=\"noreferrer\" className={MENU_ITEM}>\n View your GitHub profile\n <NewTabIndicator />\n </a>\n )}\n {signOutAction && (\n <form method=\"POST\" action={signOutAction}>\n <button type=\"submit\" className={MENU_ITEM}>\n Sign out\n </button>\n </form>\n )}\n </div>\n </details>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo } from '@dataimago/ui';\nimport type { SiteFooterProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * Site footer — the Level-1 hub footer: dark surface, dataimago wordmark + a\n * trimmed nav column grid.\n *\n * The wordmark is the `dataimago` brand mark via `<Logo>` (font-free, in a light\n * `currentColor` on the dark surface) — no backplate, no hardcoded \".ai\" span.\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11). The defaults drop the former \"Legacy\" column + the critical-theory\n * closing statement (the philosophical-basis editorial lives on the PhilosophyFooter,\n * which is Level-1-only). Level-2 verticals use `MinimalFooter` instead.\n */\n\nconst DEFAULT_TAGLINE = 'A living AI-native application ecosystem.';\n\nconst DEFAULT_COLUMNS = [\n {\n heading: 'Platform',\n links: [\n { href: '/onboard', label: 'Begin a project' },\n { href: '/ecosystem', label: 'Ecosystem' },\n { href: '/philosophy', label: 'Philosophy' },\n ],\n },\n {\n heading: 'Framework',\n links: [\n {\n href: 'https://github.com/dataimago/dataimago-design',\n label: 'dataimago-design',\n external: true,\n },\n {\n href: 'https://github.com/dataimago/dataimago',\n label: 'dataimago',\n external: true,\n },\n {\n href: 'https://github.com/dataimago/dataimago-ai',\n label: 'dataimago-ai',\n external: true,\n },\n ],\n },\n];\n\nexport function SiteFooter({\n tagline = DEFAULT_TAGLINE,\n columns = DEFAULT_COLUMNS,\n closingStatement,\n}: SiteFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto max-w-6xl px-6 py-12\">\n <div className=\"grid gap-8 md:grid-cols-4\">\n <div>\n <Link\n href=\"/\"\n className=\"inline-flex items-center text-stone-100 transition hover:opacity-80\"\n aria-label=\"dataimago\"\n >\n <Logo\n name=\"dataimago\"\n variant=\"PATH\"\n aria-hidden\n className=\"[&_svg]:h-7 [&_svg]:w-auto\"\n />\n </Link>\n <p className=\"mt-3 text-xs text-stone-400\">{tagline}</p>\n </div>\n\n {columns.map((col) => (\n <div key={col.heading}>\n <h4 className=\"font-mono text-xs uppercase tracking-wider text-accent-300\">\n {col.heading}\n </h4>\n <ul className=\"mt-3 space-y-2 text-sm\">\n {col.links.map(({ href, label, external }) => (\n <li key={label}>\n {!href ? (\n label\n ) : external ? (\n <a\n href={href}\n className=\"hover:text-paper-100\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link href={href} className=\"hover:text-paper-100\">\n {label}\n </Link>\n )}\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n\n {closingStatement ? (\n <div className=\"mt-12 border-t border-stone-800 pt-6 text-xs text-stone-400\">\n <p>{closingStatement}</p>\n </div>\n ) : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Logo } from '@dataimago/ui';\nimport type { MinimalFooterProps } from './types';\nimport { NEW_TAB_SUFFIX, NewTabIndicator } from './NewTabIndicator';\n\n/**\n * MinimalFooter — the Level-2 vertical footer.\n *\n * A Level-2 vertical (dissertation.ai, future rpkg.ai / sgpc.ai) is \"an embodiment\n * of dataimago\": the footer shows the parent `dataimago` wordmark linking UP to\n * dataimago.ai, the embodiment line, a compact links row, and a copyright line.\n * No nav columns, no philosophy — those belong to the Level-1 hub (SiteFooter +\n * PhilosophyFooter). See dataimago-design wiki/patterns/hub-hero-anatomy.\n */\n\nconst DEFAULT_BRAND_HREF = 'https://dataimago.ai';\nconst DEFAULT_EMBODIMENT = 'An embodiment of dataimago';\n\nexport function MinimalFooter({\n brandHref = DEFAULT_BRAND_HREF,\n embodimentLabel = DEFAULT_EMBODIMENT,\n links = [],\n copyright,\n}: MinimalFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto flex max-w-6xl flex-col items-center gap-4 px-6 py-10 text-center\">\n <a\n href={brandHref}\n className=\"inline-flex flex-col items-center gap-2 text-stone-100 transition hover:opacity-80\"\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label={`${embodimentLabel} — visit dataimago.ai${NEW_TAB_SUFFIX}`}\n >\n <Logo\n name=\"dataimago\"\n variant=\"PATH\"\n aria-hidden\n className=\"[&_svg]:h-7 [&_svg]:w-auto\"\n />\n <span className=\"text-sm text-stone-400\">\n {embodimentLabel}\n <NewTabIndicator hideText />\n </span>\n </a>\n\n {links.length > 0 ? (\n <nav\n className=\"flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm\"\n aria-label=\"Footer\"\n >\n {links.map(({ href, label, external }) =>\n !href ? (\n <span key={label} className=\"text-stone-400\">\n {label}\n </span>\n ) : external ? (\n <a\n key={label}\n href={href}\n className=\"text-stone-300 hover:text-paper-100\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={label} href={href} className=\"text-stone-300 hover:text-paper-100\">\n {label}\n </Link>\n )\n )}\n </nav>\n ) : null}\n\n {copyright ? <p className=\"text-xs text-stone-400\">{copyright}</p> : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { CopulaLockup, type CopulaLinkProps } from '@dataimago/ui';\nimport type { CopulaFooterProps } from './types';\nimport { NewTabIndicator } from './NewTabIndicator';\n\n/**\n * CopulaFooter — the slim dark footer every dataimago hub shares.\n *\n * LEFT: the copula lockup from @dataimago/ui, \"<property> is dataimago\": the\n * property wordmark (→ `propertyHref`), the `is_badge` disc, and the dataimago\n * wordmark (→ `brandHref`). The two wordmarks share one hover treatment. The\n * disc is a mark, not a link: at 16×16 it is below the WCAG 2.5.8 24×24\n * pointer-target floor, so it is read aloud as \"is\" and /philosophy stays in the\n * nav (wi-20260928-at-footer-badge-target-size). `dataimago=\"hidden\"` draws the\n * property mark alone, for apps that keep dataimago out of view while it is in\n * stealth (the maintainer, 2026-11-03).\n * RIGHT: a compact links row (e.g. Privacy · Terms). An optional copyright line\n * takes its own row below.\n *\n * Generalised from dissertation-ai's footer (dataimago/dissertation-ai#254); see\n * dataimago-design wiki/connections/is-copula-coupling.md.\n */\n\n// Internal hrefs go through next/link; anything else is a plain link.\nfunction FooterLink({ href, children, ...props }: CopulaLinkProps) {\n return href.startsWith('/') ? (\n <Link href={href} {...props}>\n {children}\n </Link>\n ) : (\n <a href={href} {...props}>\n {children}\n </a>\n );\n}\n\nexport function CopulaFooter({\n property,\n propertyLabel,\n propertyHref = '/',\n dataimago = 'shown',\n brandHref = 'https://dataimago.ai',\n links = [],\n linksLabel = 'Legal',\n copyright,\n}: CopulaFooterProps) {\n return (\n <footer\n className=\"border-t border-stone-800 bg-stone-900 text-stone-400\"\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto flex max-w-6xl flex-wrap items-center justify-between gap-x-6 gap-y-3 px-6 py-4\">\n <CopulaLockup\n property={property}\n propertyLabel={propertyLabel}\n propertyHref={propertyHref}\n dataimago={dataimago}\n brandHref={brandHref}\n linkClassName=\"text-stone-200 transition hover:text-stone-50\"\n badgeClassName=\"text-stone-200\"\n renderLink={FooterLink}\n />\n\n {links.length > 0 ? (\n <nav aria-label={linksLabel} className=\"flex flex-wrap items-center gap-x-5 gap-y-2 text-sm\">\n {links.map(({ href, label, external }) =>\n !href ? (\n <span key={label} className=\"text-stone-400\">\n {label}\n </span>\n ) : external ? (\n <a\n key={label}\n href={href}\n className=\"text-stone-400 transition hover:text-stone-200\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n {label}\n <NewTabIndicator />\n </a>\n ) : (\n <Link key={label} href={href} className=\"text-stone-400 transition hover:text-stone-200\">\n {label}\n </Link>\n )\n )}\n </nav>\n ) : null}\n\n {copyright ? <p className=\"w-full text-xs text-stone-400\">{copyright}</p> : null}\n </div>\n </footer>\n );\n}\n","'use client';\n\nimport type { PhilosophyFooterProps } from './types';\n\n/**\n * Philosophy footer — the platform's moral weight, rendered as a dark\n * editorial section with three belief/mission/vision pairs and a pull-quote.\n *\n * Iteration-1 visual identity (Phase B.3, 2026-05-06):\n * Dark-surface chrome with text-accent-500 eyebrows, font-display body, and\n * the Baudrillard blockquote with border-copper-500 (preserved-decorative-\n * copper per iteration-1 §5.2 governance).\n *\n * Iteration-2 role-shift (2026-05-07): eyebrows were meant to resolve to\n * sky-blue accent-300 (#3498DB) on this dark surface via mode-aware mapping —\n * 5.41:1 on stone-900. The static Tailwind class `text-accent-500` binds the\n * absolute color instead (~2.56:1). 2026-09-05: eyebrows match SiteFooter\n * (`text-accent-300` + `data-bs-theme=\"dark\"`). The border-copper-500\n * blockquote frame survives untouched. \"Two warmths\" coexist: cool sky-blue\n * on editorial eyebrows, warm copper on the philosophical-quote frame.\n *\n * Extracted from apps/hub into @dataimago/hub-chrome during iteration-3-B.2\n * (2026-05-11). The `pairs`, `quote`, and `closingStatement` props allow\n * per-vertical adaptation; all props default to the Level-1 hub content.\n */\n\nconst DEFAULT_PAIRS = [\n {\n eyebrow: 'our belief',\n body: 'AI can enable virtuous cycles of improvement in the world.',\n },\n {\n eyebrow: 'our mission',\n body: 'The emancipation of humanity through ai super-alignment.',\n },\n {\n eyebrow: 'our vision',\n body: 'Super-alignment embeds ai in culture, not culture in ai.',\n },\n];\n\nconst DEFAULT_QUOTE = {\n text: `If men create intelligent machines, or fantasize about them, it is either because they secretly despair of their own intelligence or because they are in danger of succumbing to the weight of a monstrous and useless intelligence which they seek to exorcize by transferring it to machines, where they can play with it and make fun of it. By entrusting this burdensome intelligence to machines we are released from any responsibility to knowledge.`,\n attribution: 'Jean Baudrillard',\n work: 'Xerox and Infinity',\n year: 1988,\n};\n\nconst DEFAULT_CLOSING =\n 'dataimago is the structural answer to this critique. Every architectural choice — R as source of truth, editorial authority with the domain expert, the non-destructive retrofit principle, the ecosystem-as-commons — refuses to release the scholar from responsibility to their own knowledge. The AI serves the culture; the culture governs the AI.';\n\nexport function PhilosophyFooter({\n pairs = DEFAULT_PAIRS,\n quote = DEFAULT_QUOTE,\n closingStatement = DEFAULT_CLOSING,\n density = 'default',\n}: PhilosophyFooterProps) {\n const compact = density === 'compact';\n\n // Pull-quote — border-copper-500 PRESERVED: decorative-emphasis blockquote\n // frame per iteration-1 §5.2 preserved-decorative-copper governance.\n const pullQuote = (\n <blockquote\n className={`border-l-2 border-copper-500 pl-6 font-display italic text-paper-100 ${\n compact ? '' : 'mt-16 max-w-prose-wide'\n }`}\n >\n <p className=\"text-base leading-relaxed\">{quote.text}</p>\n <footer className=\"mt-4 text-sm not-italic text-stone-400\">\n — {quote.attribution}, <cite>{quote.work}</cite> ({quote.year})\n </footer>\n </blockquote>\n );\n\n const closing = (\n <p\n className={`text-stone-400 ${\n compact ? 'text-base leading-relaxed' : 'mt-8 max-w-prose-wide text-sm'\n }`}\n >\n {closingStatement}\n </p>\n );\n\n return (\n <section\n aria-labelledby=\"philosophy-heading\"\n className={`border-t border-stone-200 bg-stone-900 text-paper-100 ${\n compact\n ? 'flex flex-col justify-center py-14 sm:py-16 lg:min-h-[50vh]'\n : 'py-20 sm:py-28'\n }`}\n data-bs-theme=\"dark\"\n >\n <div className=\"mx-auto w-full max-w-6xl px-6\">\n <div className={`grid lg:grid-cols-3 ${compact ? 'gap-8' : 'gap-12'}`}>\n {pairs.map((pair, i) => (\n <div key={i}>\n <p className=\"font-mono text-xs uppercase tracking-wider text-accent-300\">\n {pair.eyebrow}\n </p>\n {i === 0 ? (\n <h3\n id=\"philosophy-heading\"\n className=\"mt-2 font-display text-xl text-paper-100\"\n >\n {pair.body}\n </h3>\n ) : (\n <p className=\"mt-2 font-display text-xl text-paper-100\">\n {pair.body}\n </p>\n )}\n </div>\n ))}\n </div>\n\n {compact ? (\n // Critique / answer, side by side — Baudrillard's warning and\n // dataimago's structural answer. Filling the width is what pulls the\n // section down to ~half height (the default stacks these in one column,\n // leaving the right half empty).\n <div className=\"mt-10 grid gap-x-12 gap-y-8 lg:grid-cols-2\">\n {pullQuote}\n {closing}\n </div>\n ) : (\n <>\n {pullQuote}\n {closing}\n </>\n )}\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","Link","Logo","jsx","jsxs","Link","Logo","Link","Logo","jsx","jsxs","Logo","Link","Link","jsx","jsxs","Link","Fragment","jsx","jsxs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dataimago/hub-chrome",
3
- "version": "0.2.0-alpha.7",
3
+ "version": "0.2.0-alpha.8",
4
4
  "description": "Configurable hub chrome components — PlatformNav, SiteFooter, PhilosophyFooter — with dataimago house defaults and props for per-vertical adaptation. Extracted from dataimago-ai/apps/hub during iteration-3-B.2 (2026-05-11). Consumed by both the Level-1 dataimago.ai hub and Level-2 verticals (dissertation.ai, future sgpc.ai / rpkg.ai).",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -36,15 +36,15 @@
36
36
  "README.md"
37
37
  ],
38
38
  "peerDependencies": {
39
- "@dataimago/brand": ">=0.1.0-alpha.6",
40
- "@dataimago/ui": ">=0.1.0-alpha.10",
39
+ "@dataimago/brand": ">=0.1.0-alpha.8",
40
+ "@dataimago/ui": ">=0.1.0-alpha.35",
41
41
  "next": ">=14",
42
42
  "react": "^18.2.0",
43
43
  "react-dom": "^18.2.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@dataimago/brand": "^0.1.0-alpha.6",
47
- "@dataimago/ui": "^0.1.0-alpha.10",
46
+ "@dataimago/brand": "^0.1.0-alpha.8",
47
+ "@dataimago/ui": "^0.1.0-alpha.35",
48
48
  "@types/react": "^18.2.43",
49
49
  "@types/react-dom": "^18.2.17",
50
50
  "lucide-react": "^0.344.0",