/** * computeOrgGradient — deterministic gradient pair for an organisation. * * Maps an org `id` string to one of 8 colour pairs via a simple djb2-style * character-code hash. Same id always returns the same pair; no external * dependencies. * * Palette rationale (P7-followup-gradient-brand): the diverse crewli-starter * SoT palette. Slot 1 is Crewli's brand teal (`#0D9394` → `#075F60`) so the * brand-anchor org renders in true Crewli teal — NOT Tailwind teal-600 * (`#0d9488`), which had drifted in. Remaining slots span hue families * (purple / orange / green / amber / pink / indigo / rose) so multi-org * users see clearly distinct avatars rather than a wall of similar teals. * Each tuple is `[from, to]` for a 135° linear gradient (darker "to" * keeps depth on the logo square). */ /** Exported so tests can assert membership without hard-coding values. */ export const GRADIENT_PALETTE: [string, string][] = [ ['#0D9394', '#075F60'], // Crewli teal (brand anchor) ['#7C3AED', '#4C1D95'], // purple ['#EA580C', '#9A3412'], // orange ['#16A34A', '#14532D'], // green ['#F59E0B', '#92400E'], // amber ['#EC4899', '#9D174D'], // pink ['#4F46E5', '#312E81'], // indigo (added for org-distinguishability) ['#E11D48', '#881337'], // rose (added for org-distinguishability) ] /** * Returns a `[fromHex, toHex]` colour pair deterministically derived * from `id`. Handles empty string (hash stays 0; maps to palette[0]). */ export function computeOrgGradient(id: string): [string, string] { // djb2-style hash: accumulate across char codes let hash = 5381 for (let i = 0; i < id.length; i++) { // Equivalent to hash * 33 ^ charCode, kept 32-bit safe via >>> 0 hash = ((hash << 5) + hash + id.charCodeAt(i)) >>> 0 } const index = hash % GRADIENT_PALETTE.length return GRADIENT_PALETTE[index] }