/** * THE PRACTICE'S MARK, the shared small ak-org-mark, beside its name. * * Spencer, 2026-08-25: *"Also missing the organization as seen in the screenshot."* * * IT IS NOT DECORATION. Any surface that mixes practices into one column - the patient's queue, their * task list, their bills - needs the practice to be the thing that stops someone calling the wrong * front desk. A mark reads before the name does. The queue is the case that makes it plain: a lab * result FROM one practice ORDERED BY another's doctor, two rows apart in one list. * * The tone is DERIVED FROM THE NAME, not stored, so the same practice keeps the same colour on every * row and in every session without anything having to remember it. Six muted tones rather than a hash * across the whole spectrum: the point is telling two practices apart, not giving each a signature. * * LIFTED HERE FROM `HomePage/PatientQueue.tsx` when the patient's task list needed the same mark. It is * shared rather than copied for the reason the tone function makes obvious: a second implementation is * a second map for one value, and the first time they disagreed the same practice would be two colours * on two screens - which is precisely the confusion the badge exists to prevent. */ const BADGE_TONES = [ "bg-sky-800", "bg-amber-800", "bg-teal-800", "bg-violet-800", "bg-rose-800", // Not a slate or a grey: the colour ratchet forbids Tailwind's neutral scales outright, because // our neutrals are the warm ramp in index.css and a cool grey beside them reads as a different // product. It caught this line on the first run. "bg-emerald-800", ] as const; /** * Two letters off a name, for a mark that has to stand in for it. * * Exported under a general name because the person badge wants the same rule: this is formatting * with no meaning attached, unlike the tone map below, which is a claim about identity and is * deliberately NOT shared. */ export const initialsOf = (name: string): string => name .split(/\s+/) .filter((word) => /[a-z]/i.test(word)) .slice(0, 2) .map((word) => word[0]!.toUpperCase()) .join("") || "?"; export const orgTone = (name: string): string => { // A plain sum of code points. Stable across reloads, and nothing here needs it to be unguessable. let total = 0; for (const character of name) total += character.codePointAt(0) ?? 0; return BADGE_TONES[total % BADGE_TONES.length]!; }; export const OrgBadge = ({ name }: { name: string }) => ( );