import * as React from 'react'; import { cn } from '../../shared/utils'; import { ISOTYPE_COLORS } from './patterns'; import { ISOTYPE_TWIST_VARIANTS, type IsotypeTwistVariantId } from './twist-variants'; export interface IsotypeTwistProps extends React.HTMLAttributes { /** Which registered color-pair variant to render. */ variant?: IsotypeTwistVariantId; /** Accessible label. Omit for purely decorative use. */ 'aria-label'?: string; } const VIEW_WIDTH = 800; const VIEW_HEIGHT = 694; /** CSS blend mode used to combine the two shapes — the intersection color is whatever this mode produces, not a fixed value. */ const TWIST_BLEND_MODE: React.CSSProperties['mixBlendMode'] = 'multiply'; /** Back shape of the pair — one fixed hand-derived composition, not data-driven. */ const BACK_SHAPE_PATH = 'M218.149 0L344.167 230.665L470.185 0H681.981L467.008 344.092L687.805 693.902H473.892L344.167 458.948L214.443 693.902H0L221.326 344.092L5.82437 0H218.149Z'; /** Front shape of the pair — overlaps the back shape; dominates the intersection blend. */ const FRONT_SHAPE_PATH = 'M486.064 230.488L570.299 384.535L654.535 230.488H796.107L652.411 460.285L800 693.902H657.012L570.299 536.991L483.586 693.902H340.244L488.187 460.285L344.137 230.488H486.064Z'; /** * Two overlapping angular ribbon shapes — the fifth mark in the Xertica * "isotipos" series. Both shapes render fully opaque; their intersection * blends into a third color via a CSS mix-blend-mode, not transparency. * * @ai-rules * 1. Colors are fixed brand hex values (see `patterns.ts`), not theme tokens — never make them theme-reactive. * 2. The intersection color is a rendering side-effect of `TWIST_BLEND_MODE`, not data — never hardcode a third color per variant. * 3. Add new color pairs via `ISOTYPE_TWIST_VARIANTS` in `twist-variants.ts`; this component never needs to change. * 4. Pair order is `[back, front]` — the front (second) color dominates the intersection blend. * 5. The root `isolate` class scopes the blend to these two shapes — removing it would let the front shape blend against whatever sits behind this component on the page. * 6. The viewBox is not square (800x694) — the root uses `aspect-[800/694]`, not `aspect-square`. */ export function IsotypeTwist({ variant = 'magenta-blue', className, 'aria-label': ariaLabel, ...props }: IsotypeTwistProps) { const [backKey, frontKey] = ISOTYPE_TWIST_VARIANTS[variant]; return (
); }