// Shared editor UI constants + tiny helpers used across the object/plop markers // and overlays, so colors, handle sizes, and the object-local transform stay in // one place instead of drifting between files. export const SELECT_COLOR = '#2f7a3e' // selection stroke/handles // Whether the primary pointer is a fingertip rather than a mouse — the one signal // the touch affordances key off (bigger handles here, the on-screen nudge pad in // the editor), so they can't disagree about what "touch" means. Read once at // load; a device doesn't switch its primary pointer mid-session, and the optional // chain keeps it false (mouse defaults) under test / SSR where matchMedia is absent. export const isCoarsePointer = typeof window !== 'undefined' && !!window.matchMedia?.('(pointer: coarse)').matches // On-screen size of a drag/resize handle. Bigger on touch so a fingertip can // actually grab a resize corner or the rotate knob — 12px is fine for a mouse but // frustrating for a thumb (#104). export const HANDLE_PX = isCoarsePointer ? 22 : 12 export const MIN_RADIUS_CM = 1 // smallest plop radius export const DIMMED_OPACITY = 0.4 // non-focused objects/plops in focus mode /** SVG transform placing content in an object's local frame: its center point * then its clockwise rotation. Plops and overlays render inside this. */ export function objectTransform(o: { xCm: number; yCm: number; rotationDeg: number }): string { return `translate(${o.xCm} ${o.yCm}) rotate(${o.rotationDeg})` }