import type { ClipboardEvent } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { createPortal } from 'react-dom' /* The panel's styles ride WITH the panel. Imported from `main.tsx` they were in the entry CSS of every production build; here they are part of this module, so when the dev-only gate in `App.tsx` drops the module the stylesheet goes with it. */ import '../lab.css' import { BLENDS, addEntry, addNote, forgetShares, hoverInfo, chooseVariant, chosenKeys, undoTo, clearGrain, dropVariantSet, loadLab, noteLine, pick, removeEntry, putShot, removeNote, setActive, setPicking, sayVariant, showVariant, shotUrl, toCss, variantCss, toggleNote, updateActive, labOn, useGrainLab, watchDisk, watchPush, openThreadOn, resolveThread, sayOnThread, showThread, type Target, type Thread, type VariantSet, addPending, describe, dropPending, clearIdlePending, markComposer, noteTrail, scrubTo, snapOf, trailCss, dropThread, } from '@/lib/lab' /** * LiGMA — the annotation + grain overlay — `?grain` on the URL, nothing otherwise. * * Two jobs. Grain is dialled live and copied out as CSS. Notes are written * against a selector and saved to `.lab/state.json`, where whoever is editing * the source reads them — so "click a thing, say what is wrong with it" ends * up as a durable instruction rather than a sentence typed into a chat and * lost. * * The three modes are the thing to understand before changing anything here. * They used to be two independent controls — a `picking` toggle and a * `preview` button side by side, looking like the same kind of switch while * meaning different things — and the panel could end up in a state it did not * describe. They are one exclusive control now, each named for what a click * on the page does in it: * * pick a click selects the element under the cursor * browse the page behaves normally, panel stays up * preview the panel folds away too, leaving only a way back * * Pick mode listens in the capture phase so a click lands here before a link * navigates; without that the page would be gone before the element could be * inspected. * * The rules go into a live `