diff --git a/portal/docs/BRAND_IDENTITY_SANKOFA_NEXUS.md b/portal/docs/BRAND_IDENTITY_SANKOFA_NEXUS.md new file mode 100644 index 0000000..1e789d0 --- /dev/null +++ b/portal/docs/BRAND_IDENTITY_SANKOFA_NEXUS.md @@ -0,0 +1,46 @@ +# Sankofa Nexus — Visual Identity Rationale + +**Version:** 1.0 · **Scope:** Sankofa, Phoenix, PanTel public marks and web shell + +## Symbolism + +### Sankofa master mark + +The geometric Sankofa bird faces backward while the body advances — *return, retrieve, preserve, move forward*. The protective circular ring denotes sovereign jurisdiction and institutional continuity. Tail geometry resolves into network paths (data streams, orbital lines) rather than decorative plumage. + +An optional eight-point grid references Hospitaller order geometry (precision, protection, service) without religious iconography — used at ≤8% opacity as structural scaffolding only. + +### Phoenix sub-mark + +Derived from the Sankofa bird ascending: horizontal wing strata imply cloud compute layers; a central core reads as continuity / rebirth / uptime. Meaning: restoration, resilience, sovereign cloud. + +### PanTel sub-mark + +Derived from the Sankofa central node with signal arcs and orbital paths — telecommunications, secure connectivity, propagation across distributed infrastructure. + +## Tone + +Institutional, sovereign, resilient, precise, civilizational — not startup SaaS, not DeFi meme aesthetics, not cartoon mascots. + +## Palette + +| Token | Hex | Use | +|-------|-----|-----| +| Obsidian | `#111111` | Primary surfaces | +| Deep Midnight | `#0D1B2A` | Depth, headers, panels | +| Sovereign Gold | `#D4A64A` | Primary accent, marks | +| Bronze | `#8B6A3E` | Secondary accent, borders | +| Signal Copper | `#C56B2C` | CTAs, signal / network emphasis | +| Cloud Ivory | `#F5F1E8` | Primary text on dark | + +Gradients are used sparingly — prefer flat gold/copper on obsidian. + +## Typography + +**IBM Plex Sans** — institutional sans with engineering clarity (IBM-grade durability). Fallback: system-ui. + +## Implementation + +- SVG React components: `src/components/brand/logos/` +- Tokens: `src/lib/brand/tokens.ts`, CSS vars in `globals.css`, Tailwind `sovereign.*` +- Brand reference page: `/brand` diff --git a/portal/pnpm-workspace.yaml b/portal/pnpm-workspace.yaml deleted file mode 100644 index 5d7e631..0000000 --- a/portal/pnpm-workspace.yaml +++ /dev/null @@ -1,2 +0,0 @@ -allowBuilds: - unrs-resolver: set this to true or false diff --git a/portal/postcss.config.js b/portal/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/portal/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/portal/src/app/ClientRootLayout.tsx b/portal/src/app/ClientRootLayout.tsx index df9fb95..53acedc 100644 --- a/portal/src/app/ClientRootLayout.tsx +++ b/portal/src/app/ClientRootLayout.tsx @@ -1,18 +1,23 @@ 'use client'; -import { Inter } from 'next/font/google'; +import { IBM_Plex_Sans } from 'next/font/google'; import { AppShell } from '@/components/layout/AppShell'; import { Providers } from './providers'; -import './globals.css'; -const inter = Inter({ subsets: ['latin'] }); +const ibmPlexSans = IBM_Plex_Sans({ + subsets: ['latin'], + weight: ['400', '500', '600', '700'], + variable: '--font-ibm-plex', +}); export function ClientRootLayout({ children }: { children: React.ReactNode }) { return ( - + {children} diff --git a/portal/src/app/apple-icon.tsx b/portal/src/app/apple-icon.tsx index ea3ff56..6ed63ad 100644 --- a/portal/src/app/apple-icon.tsx +++ b/portal/src/app/apple-icon.tsx @@ -13,14 +13,32 @@ export default function AppleIcon() { display: 'flex', alignItems: 'center', justifyContent: 'center', - background: 'linear-gradient(135deg, #f97316 0%, #fbbf24 100%)', + background: '#0D1B2A', borderRadius: 36, - color: '#0a0a0a', - fontSize: 96, - fontWeight: 700, }} > - S +
+
+
), { ...size } diff --git a/portal/src/app/brand/page.tsx b/portal/src/app/brand/page.tsx new file mode 100644 index 0000000..1357b30 --- /dev/null +++ b/portal/src/app/brand/page.tsx @@ -0,0 +1,140 @@ +import type { Metadata } from 'next'; + +import { + BrandLockup, + EightPointGrid, + InstitutionalPanel, + PanTelMark, + PhoenixMark, + SankofaMark, +} from '@/components/brand'; +import { CorporateFooter } from '@/components/corporate/CorporateFooter'; +import { CorporateHeader } from '@/components/corporate/CorporateHeader'; +import { brandColors } from '@/lib/brand/tokens'; + +export const metadata: Metadata = { + title: 'Visual Identity — Sankofa Nexus', + description: + 'Sovereign institutional brand system for Sankofa, Phoenix, and PanTel — geometric marks, palette, and typography.', +}; + +const swatches = [ + { name: 'Obsidian', token: 'obsidian', hex: brandColors.obsidian }, + { name: 'Deep Midnight', token: 'midnight', hex: brandColors.midnight }, + { name: 'Sovereign Gold', token: 'gold', hex: brandColors.sovereignGold }, + { name: 'Bronze', token: 'bronze', hex: brandColors.bronze }, + { name: 'Signal Copper', token: 'copper', hex: brandColors.signalCopper }, + { name: 'Cloud Ivory', token: 'ivory', hex: brandColors.cloudIvory }, +]; + +export default function BrandPage() { + return ( +
+ + +
+ + +
+

+ Internal reference +

+

+ Sankofa Nexus visual identity +

+

+ Geometric Sankofa symbolism inside a sovereign protection ring — extended to Phoenix (cloud + resilience) and PanTel (secure connectivity). Institutional tone: durable, precise, + civilizational. +

+ +
+

Master marks

+
+ {[ + { Mark: SankofaMark, label: 'Sankofa', sub: 'Sovereign technology · trust · continuity' }, + { Mark: PhoenixMark, label: 'Phoenix', sub: 'Cloud · recovery · uptime' }, + { Mark: PanTelMark, label: 'PanTel', sub: 'Telecom · signal · connectivity' }, + ].map(({ Mark, label, sub }) => ( + +
+ + + +
+
+ ))} +
+
+ +
+

Lockup

+ +
+ + + +
+
+
+ +
+

Color palette

+
+ {swatches.map((s) => ( +
+
+
+

{s.name}

+

{s.hex}

+
+
+ ))} +
+
+ +
+

Typography

+ +

Primary — IBM Plex Sans

+

Sovereign technology infrastructure

+

+ Institutional sans-serif for governments, orders, and critical systems operators. +

+

+ ABCDEFGHIJKLMNOPQRSTUVWXYZ · abcdefghijklmnopqrstuvwxyz · 0123456789 +

+
+
+ +
+

Symbolism

+
+ +

+ The geometric bird glances backward while the body advances. The protection ring denotes + sovereign jurisdiction. Tail paths resolve into network continuity — not decorative + plumage. +

+
+ +

+ Hospitaller-inspired geometry at low opacity — precision, protection, service — without + overt religious iconography. +

+
+
+

+ Full rationale: docs/BRAND_IDENTITY_SANKOFA_NEXUS.md +

+
+
+
+ + +
+ ); +} diff --git a/portal/src/app/globals.css b/portal/src/app/globals.css index e9ef0bc..fbe6aca 100644 --- a/portal/src/app/globals.css +++ b/portal/src/app/globals.css @@ -2,14 +2,21 @@ @tailwind components; @tailwind utilities; -/* Portal is dark-first; avoid prefers-color-scheme body rules that fight Tailwind and - leave bare tags as low-contrast browser default blue on black. */ +:root { + --sovereign-obsidian: #111111; + --sovereign-midnight: #0d1b2a; + --sovereign-gold: #d4a64a; + --sovereign-bronze: #8b6a3e; + --sovereign-copper: #c56b2c; + --sovereign-ivory: #f5f1e8; +} + @layer base { body { - @apply bg-gray-950 text-gray-100; + @apply bg-sovereign-obsidian text-sovereign-ivory; } a { - @apply text-orange-300 underline-offset-2 transition-colors hover:text-orange-200; + @apply text-sovereign-gold underline-offset-2 transition-colors hover:text-sovereign-ivory; } } @@ -18,4 +25,3 @@ text-wrap: balance; } } - diff --git a/portal/src/app/icon.tsx b/portal/src/app/icon.tsx index 4f8c9c6..b17de54 100644 --- a/portal/src/app/icon.tsx +++ b/portal/src/app/icon.tsx @@ -3,6 +3,7 @@ import { ImageResponse } from 'next/og'; export const size = { width: 32, height: 32 }; export const contentType = 'image/png'; +/** Favicon — simplified Sankofa sovereign ring mark */ export default function Icon() { return new ImageResponse( ( @@ -13,14 +14,33 @@ export default function Icon() { display: 'flex', alignItems: 'center', justifyContent: 'center', - background: 'linear-gradient(135deg, #f97316 0%, #fbbf24 100%)', - borderRadius: 8, - color: '#0a0a0a', - fontSize: 20, - fontWeight: 700, + background: '#0D1B2A', + borderRadius: 6, }} > - S +
+
+
), { ...size } diff --git a/portal/src/app/layout.tsx b/portal/src/app/layout.tsx index 085f219..58b6c13 100644 --- a/portal/src/app/layout.tsx +++ b/portal/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from 'next'; import { ClientRootLayout } from './ClientRootLayout'; +import './globals.css'; export const metadata: Metadata = { metadataBase: new URL('https://sankofa.nexus'), diff --git a/portal/src/components/brand/BrandLockup.tsx b/portal/src/components/brand/BrandLockup.tsx new file mode 100644 index 0000000..d0cad1a --- /dev/null +++ b/portal/src/components/brand/BrandLockup.tsx @@ -0,0 +1,48 @@ +import { cn } from '@/lib/utils'; + +import { SankofaMark } from './logos/SankofaMark'; + +type BrandLockupProps = { + size?: 'sm' | 'md' | 'lg'; + showWordmark?: boolean; + subtitle?: string; + className?: string; +}; + +const sizes = { + sm: { mark: 28, title: 'text-base', sub: 'text-[10px]' }, + md: { mark: 36, title: 'text-lg', sub: 'text-xs' }, + lg: { mark: 48, title: 'text-xl', sub: 'text-sm' }, +}; + +/** Logo mark + institutional wordmark lockup */ +export function BrandLockup({ + size = 'md', + showWordmark = true, + subtitle, + className, +}: BrandLockupProps) { + const s = sizes[size]; + + return ( +
+ + {showWordmark && ( +
+ + Sankofa + + {subtitle ? ( + + {subtitle} + + ) : ( + + Nexus + + )} +
+ )} +
+ ); +} diff --git a/portal/src/components/brand/DashboardCard.tsx b/portal/src/components/brand/DashboardCard.tsx new file mode 100644 index 0000000..f4ce84e --- /dev/null +++ b/portal/src/components/brand/DashboardCard.tsx @@ -0,0 +1,56 @@ +import type { ReactNode } from 'react'; + +import { cn } from '@/lib/utils'; + +type DashboardCardProps = { + title: string; + value?: string | number; + description?: string; + icon?: ReactNode; + footer?: ReactNode; + className?: string; + accent?: 'gold' | 'copper' | 'bronze'; +}; + +const accentBorder = { + gold: 'border-sovereign-gold/30 hover:border-sovereign-gold/50', + copper: 'border-sovereign-copper/30 hover:border-sovereign-copper/50', + bronze: 'border-sovereign-bronze/30 hover:border-sovereign-bronze/50', +}; + +/** Explorer / console metric card with institutional styling */ +export function DashboardCard({ + title, + value, + description, + icon, + footer, + className, + accent = 'gold', +}: DashboardCardProps) { + return ( +
+
+
+

{title}

+ {value !== undefined && ( +

{value}

+ )} +
+ {icon && ( +
+ {icon} +
+ )} +
+ {description &&

{description}

} + {footer &&
{footer}
} +
+ ); +} diff --git a/portal/src/components/brand/EcosystemTrinitySection.tsx b/portal/src/components/brand/EcosystemTrinitySection.tsx new file mode 100644 index 0000000..4eef275 --- /dev/null +++ b/portal/src/components/brand/EcosystemTrinitySection.tsx @@ -0,0 +1,36 @@ +import { EightPointGrid } from './EightPointGrid'; +import { NetworkMeshDiagram } from './NetworkMeshDiagram'; +import { ProductCard } from './ProductCard'; + +/** Homepage ecosystem trinity — Sankofa · Phoenix · PanTel */ +export function EcosystemTrinitySection() { + return ( +
+ +
+ +
+ +
+
+

+ Sovereign product ecosystem +

+

+ One institution. Three pillars. +

+

+ Sankofa governs trust and continuity. Phoenix delivers sovereign cloud. PanTel carries secure + telecommunications — unified under Hospitaller-grade institutional standards. +

+
+ +
+ + + +
+
+
+ ); +} diff --git a/portal/src/components/brand/EightPointGrid.tsx b/portal/src/components/brand/EightPointGrid.tsx new file mode 100644 index 0000000..6f5a4bb --- /dev/null +++ b/portal/src/components/brand/EightPointGrid.tsx @@ -0,0 +1,37 @@ +import { cn } from '@/lib/utils'; + +type EightPointGridProps = { + className?: string; + opacity?: number; +}; + +/** Subtle Hospitaller-inspired eight-point structural grid (decorative) */ +export function EightPointGrid({ className, opacity = 0.08 }: EightPointGridProps) { + return ( + + + + {[0, 45, 90, 135].map((deg) => ( + + ))} + + ); +} diff --git a/portal/src/components/brand/InstitutionalPanel.tsx b/portal/src/components/brand/InstitutionalPanel.tsx new file mode 100644 index 0000000..599108e --- /dev/null +++ b/portal/src/components/brand/InstitutionalPanel.tsx @@ -0,0 +1,48 @@ +import type { ReactNode } from 'react'; + +import { cn } from '@/lib/utils'; + +type InstitutionalPanelProps = { + title?: string; + eyebrow?: string; + children: ReactNode; + className?: string; + variant?: 'default' | 'elevated' | 'inset'; +}; + +/** Institutional content panel with sovereign border treatment */ +export function InstitutionalPanel({ + title, + eyebrow, + children, + className, + variant = 'default', +}: InstitutionalPanelProps) { + return ( +
+
+ {(eyebrow || title) && ( +
+ {eyebrow && ( +

+ {eyebrow} +

+ )} + {title &&

{title}

} +
+ )} +
{children}
+
+ ); +} diff --git a/portal/src/components/brand/NetworkMeshDiagram.tsx b/portal/src/components/brand/NetworkMeshDiagram.tsx new file mode 100644 index 0000000..6488ded --- /dev/null +++ b/portal/src/components/brand/NetworkMeshDiagram.tsx @@ -0,0 +1,88 @@ +import { cn } from '@/lib/utils'; + +type NetworkMeshDiagramProps = { + className?: string; + variant?: 'full' | 'compact' | 'hero'; +}; + +/** Protected node mesh — sovereign network topology visual */ +export function NetworkMeshDiagram({ className, variant = 'full' }: NetworkMeshDiagramProps) { + const viewBox = variant === 'compact' ? '0 0 200 80' : '0 0 400 240'; + + return ( + + + + + + + + {variant !== 'compact' && ( + + )} + + {/* Protection ring */} + + + {/* Hub node */} + + + {/* Satellite nodes + links */} + {(variant === 'compact' + ? [ + [30, 20], + [170, 20], + [30, 60], + [170, 60], + ] + : [ + [80, 60], + [320, 60], + [60, 180], + [340, 180], + [200, 30], + [200, 210], + ] + ).map(([x, y]) => ( + + + + + ))} + + {variant === 'hero' && ( + + + + + )} + + ); +} diff --git a/portal/src/components/brand/ProductCard.tsx b/portal/src/components/brand/ProductCard.tsx new file mode 100644 index 0000000..a6b6d7f --- /dev/null +++ b/portal/src/components/brand/ProductCard.tsx @@ -0,0 +1,67 @@ +import { ArrowRight } from 'lucide-react'; +import Link from 'next/link'; +import type { ReactNode } from 'react'; + +import { divisionMeta, type BrandDivision } from '@/lib/brand/tokens'; +import { cn } from '@/lib/utils'; + +import { PanTelMark, PhoenixMark, SankofaMark } from './logos'; +import { NetworkMeshDiagram } from './NetworkMeshDiagram'; + +type ProductCardProps = { + division: BrandDivision; + className?: string; + children?: ReactNode; +}; + +const marks = { + sankofa: SankofaMark, + phoenix: PhoenixMark, + pantel: PanTelMark, +}; + +const markColors = { + sankofa: 'text-sovereign-gold', + phoenix: 'text-sovereign-gold', + pantel: 'text-sovereign-copper', +}; + +/** Trinity pillar card — Sankofa / Phoenix / PanTel */ +export function ProductCard({ division, className, children }: ProductCardProps) { + const meta = divisionMeta[division]; + const Mark = marks[division]; + + return ( +
+
+ +
+ +
+
+
+

+ {meta.tagline} +

+

{meta.name}

+

{meta.description}

+ {children} + + Explore {meta.name} + + +
+
+ ); +} diff --git a/portal/src/components/brand/index.ts b/portal/src/components/brand/index.ts new file mode 100644 index 0000000..ff364b1 --- /dev/null +++ b/portal/src/components/brand/index.ts @@ -0,0 +1,8 @@ +export { BrandLockup } from './BrandLockup'; +export { InstitutionalPanel } from './InstitutionalPanel'; +export { DashboardCard } from './DashboardCard'; +export { ProductCard } from './ProductCard'; +export { NetworkMeshDiagram } from './NetworkMeshDiagram'; +export { EightPointGrid } from './EightPointGrid'; +export { EcosystemTrinitySection } from './EcosystemTrinitySection'; +export * from './logos'; diff --git a/portal/src/components/brand/logos/PanTelMark.tsx b/portal/src/components/brand/logos/PanTelMark.tsx new file mode 100644 index 0000000..580f938 --- /dev/null +++ b/portal/src/components/brand/logos/PanTelMark.tsx @@ -0,0 +1,80 @@ +import { cn } from '@/lib/utils'; + +type MarkProps = { + size?: number; + className?: string; + title?: string; +}; + +/** + * PanTel sub-mark — central node with signal arcs and orbital network paths. + */ +export function PanTelMark({ size = 48, className, title = 'PanTel' }: MarkProps) { + return ( + + {/* Orbital paths */} + + + + {/* Signal arcs — propagation */} + + + + + + + {/* Central node — derived Sankofa body geometry */} + + + + {/* Distributed access nodes */} + {[ + [12, 20], + [52, 20], + [10, 44], + [54, 44], + ].map(([x, y]) => ( + + ))} + + {/* Topology links */} + + + + + + + + ); +} diff --git a/portal/src/components/brand/logos/PhoenixMark.tsx b/portal/src/components/brand/logos/PhoenixMark.tsx new file mode 100644 index 0000000..f5151f4 --- /dev/null +++ b/portal/src/components/brand/logos/PhoenixMark.tsx @@ -0,0 +1,61 @@ +import { cn } from '@/lib/utils'; + +type MarkProps = { + size?: number; + className?: string; + title?: string; +}; + +/** + * Phoenix sub-mark — ascending bird; wing strata as cloud compute layers; + * central core as continuity / rebirth. + */ +export function PhoenixMark({ size = 48, className, title = 'Phoenix' }: MarkProps) { + return ( + + {/* Cloud strata — horizontal compute layers */} + + + + + + + {/* Rising bird silhouette */} + + + {/* Wing layers — cloud strata */} + + + + + + + {/* Sun / fire core — uptime continuity */} + + + + {/* Ascent vector */} + + + ); +} diff --git a/portal/src/components/brand/logos/SankofaMark.tsx b/portal/src/components/brand/logos/SankofaMark.tsx new file mode 100644 index 0000000..ccd37be --- /dev/null +++ b/portal/src/components/brand/logos/SankofaMark.tsx @@ -0,0 +1,93 @@ +import { cn } from '@/lib/utils'; + +type MarkProps = { + size?: number; + className?: string; + title?: string; + /** Show subtle eight-point Hospitaller-inspired grid */ + showGrid?: boolean; +}; + +/** + * Master Sankofa mark — geometric bird (backward glance, forward motion) + * inside a sovereign protection ring. Tail resolves to network path streams. + */ +export function SankofaMark({ + size = 48, + className, + title = 'Sankofa', + showGrid = true, +}: MarkProps) { + return ( + + {showGrid && ( + + {[0, 45, 90, 135].map((deg) => ( + + ))} + + + )} + + {/* Sovereign protection ring */} + + + + {/* Forward body — angular chevron advancing right */} + + + {/* Neck + head looking backward (left) */} + + + + {/* Leading wing — forward motion */} + + + {/* Tail / data streams — network paths trailing backward */} + + + + + + + ); +} diff --git a/portal/src/components/brand/logos/index.ts b/portal/src/components/brand/logos/index.ts new file mode 100644 index 0000000..a3ca31f --- /dev/null +++ b/portal/src/components/brand/logos/index.ts @@ -0,0 +1,3 @@ +export { SankofaMark } from './SankofaMark'; +export { PhoenixMark } from './PhoenixMark'; +export { PanTelMark } from './PanTelMark'; diff --git a/portal/src/components/corporate/CorporateFooter.tsx b/portal/src/components/corporate/CorporateFooter.tsx index 27e9e07..792f339 100644 --- a/portal/src/components/corporate/CorporateFooter.tsx +++ b/portal/src/components/corporate/CorporateFooter.tsx @@ -1,5 +1,6 @@ import Link from 'next/link'; +import { BrandLockup } from '@/components/brand'; import { ECOSYSTEM_SIGN_IN_PATH } from '@/lib/corporate-site-data'; function isExternalHref(href: string) { @@ -8,12 +9,12 @@ function isExternalHref(href: string) { const footerColumns = [ { - title: 'Products', + title: 'Ecosystem', links: [ - { label: 'Phoenix Cloud', href: 'https://phoenix.sankofa.nexus' }, - { label: 'Complete Credential', href: 'https://cc.sankofa.nexus' }, - { label: 'Sankofa Studio', href: 'https://studio.sankofa.nexus/studio/' }, - { label: 'Client Portal', href: 'https://portal.sankofa.nexus' }, + { label: 'Sankofa — Sovereign Technology', href: 'https://sankofa.nexus' }, + { label: 'Phoenix — Cloud Services', href: 'https://phoenix.sankofa.nexus' }, + { label: 'PanTel — Telecommunications', href: 'https://portal.sankofa.nexus' }, + { label: 'Visual identity', href: '/brand' }, ], }, { @@ -47,12 +48,12 @@ const footerColumns = [ export function CorporateFooter() { return ( -