import { T as TreatAs } from './kinds-DfnjQK3J.js';

/**
 * The thin identity core: the fields an interaction event carries in
 * `payload.fingerprint`, and the fields the backend hashes into
 * `fingerprint_key` (sorted keys, canonical JSON, SHA-256; slice 19.0).
 *
 * This shape is a cross-repo contract, not a convenience type. The same
 * object is captured in two places, by 7.3's collector on every interactive
 * click and by the design-mode picker (15.4) when an operator selects an
 * element, and the two must produce byte-identical JSON for the same element
 * or match counts (15.9), the observed-element list (D180), and the
 * fingerprint-confidence stats silently read zero. Three rules keep the hash
 * stable, enforced by the golden-vector parity tests:
 *
 * 1. **Flat.** `computeFingerprintKey` sorts only top-level keys, so a nested
 *    object would hash in whatever insertion order the client used. The
 *    semantic ancestor is three flat fields for exactly this reason.
 * 2. **Absent keys are omitted, never `null` or `undefined`.**
 *    `JSON.stringify` drops `undefined` properties but keeps `null` ones, so
 *    the two spellings of "no value" would hash differently. There is one
 *    spelling: the key does not appear.
 * 3. **No raw class string, anywhere.** G5 (PRODUCT_SCOPE §6.2.5.1.1): on a
 *    Tailwind app a class string is a presentational sentence that changes
 *    when a designer touches padding. Classes enter the system only through
 *    the ranked selector generator (15.2), after utility suppression.
 *
 * Changing this field set orphans every stored `fingerprint_key`. It is a
 * migration, not an edit (see ADR 0059).
 */

interface EventFingerprint {
    /** Lowercase tag name. The one field that is always present. */
    tag: string;
    /** Subtree text, whitespace-collapsed, PII-masked, capped. Primary matcher. */
    text?: string;
    /** The icon-only control's signal; masked and capped like text. */
    ariaLabel?: string;
    /** Form controls have no textContent; their placeholder stands in. */
    placeholder?: string;
    /**
     * The element's own id, only when it looks author-written. Generated ids
     * (React useId's `:r3:`, Radix) change per render and would fragment the
     * key, turning one button into a new "element" every session.
     */
    id?: string;
    /** The explicit `role` attribute. No implicit-role table: not worth its bytes. */
    role?: string;
    /**
     * The element's own `data-testid`, `data-test`, or `data-cy`, first one
     * present (ADR 0134). The strongest evidence a page can offer that two
     * elements are the same element: it is written by a developer to be stable
     * and survives a redesign, a copy edit, and a locale switch at once.
     *
     * Read from the element itself, unlike `ancestorAttr`/`ancestorValue`,
     * which report the same attributes found on an ancestor. Absent on most
     * elements, and absence is spelled the way every optional field here is
     * spelled: the key does not appear.
     */
    testId?: string;
    /** 0-based index among same-tag element siblings. The structural tiebreak. */
    siblingIndex: number;
    /** Nearest ancestor carrying a semantic identifier, as three flat fields. */
    ancestorTag?: string;
    /** Which attribute won the ancestor walk (e.g. "data-testid", "id"). */
    ancestorAttr?: string;
    /** That attribute's value, masked and capped like text. */
    ancestorValue?: string;
}
/**
 * How strictly the runtime matcher (15.3) scores candidates. A discrete step,
 * not a float: the mapping from step to score threshold lives in the matcher,
 * so tuning the scoring function never migrates stored targets. 1 is loosest,
 * 5 is strictest. The slider help text is the workflow: loosen when the
 * element is not found, tighten when the wrong element is found.
 */
type Precision = 1 | 2 | 3 | 4 | 5;
/**
 * The full element target: the identity core plus the authoring layer an
 * operator sets in the picker (15.4) and edits in manual adjustment (15.9).
 * Stored on a flow step, so this object outlives any single arcy.js version.
 */
interface TargetFingerprint {
    /**
     * Schema version. Durable data stored in customers' flows needs a
     * discriminant before a v2 exists, or the v2 migration has nothing to
     * dispatch on. Bump only with a migration plan for stored targets.
     */
    v: 1;
    /**
     * The identity core, embedded as-is and never spread flat. Everything that
     * hashes or matches reads `target.core`, structurally the same object shape
     * an event carries, so a field can never be forgotten in translation.
     */
    core: EventFingerprint;
    /**
     * The active selector refinement. Default null (§6.2.5.1: the reference
     * leads with text, not a selector, and that default is preserved). Never
     * hand-authored; 15.2's generator is the only writer, and it writes only
     * when the top-ranked candidate is top-two-tier and matches exactly one
     * element at pick time (D318).
     */
    selector: string | null;
    /**
     * Ranked stable-selector candidates captured at pick time by 15.2, shown
     * read-only in manual adjustment as a diagnostic. Capped so a pathological
     * page cannot bloat a stored target.
     */
    selectorCandidates: string[];
    /**
     * 1-based position among document-ordered candidates that survive the
     * precision threshold: "if multiple matches, select 1st element". Always
     * present. This is the G5 policy reversal (D013): a human pointed at the
     * element and set this, so ties take the ordinal, never refuse-to-guess.
     */
    ordinal: number;
    precision: Precision;
    /**
     * Marks text as changing at runtime ("3 items in cart"), so the matcher
     * down-weights text rather than treating its mismatch as disqualifying.
     */
    dynamicText: boolean;
    /**
     * Where the element sat when it was picked (ADR 0242 §4): `open`, or
     * behind a platform boundary the widget cannot cross at run time, which
     * the drawers warn about from the stored target. Authoring layer, never
     * the core: the core is hashed. Absent reads as open, so a target picked
     * by an older widget is reachable.
     */
    reach?: TargetReach;
    /**
     * The storage key of the element's cropped screenshot (D1803), captured by
     * the picker and uploaded by the dashboard. On the target, not the step,
     * so a trigger condition's target has the same face a step's has.
     * Authoring layer only: never part of the hashed core, never served to the
     * widget (the backend strips it from published content), never read by
     * the matcher.
     */
    screenshotKey?: string;
    /**
     * The operator's answer to "what is this?" for a role-less element (ADR
     * 0255 §4): a kind from the control registry, or `handover`. Applied by
     * the executor only when the resolver itself returns no kind. Authoring
     * layer, never the hashed core.
     */
    treatAs?: TreatAs;
}
type TargetReach = "open" | "closed_shadow" | "cross_origin_iframe";

/** The one masking token. Exported because the matcher (15.3) must treat it
 * as an absent signal rather than a value: every masked email collapses to
 * this same string, so scoring it as text would make any PII match any
 * other PII exactly. */
declare const MASK = "[masked]";

/**
 * Bumped whenever a message shape changes incompatibly. A receiver that reads
 * a number it does not speak refuses and says so, rather than guessing at a
 * payload it half understands (the same posture ADR 0069 took for loading).
 */
declare const DESIGN_MODE_PROTOCOL = 2;
/** Posted once, when the overlay has mounted and the operator can click. */
declare const DESIGN_MODE_READY = "arcy:design-mode:ready";
/** Posted for every pick. The last one wins; there is no confirm (D502). */
declare const DESIGN_MODE_PICK = "arcy:design-mode:pick";
/** Posted when the operator leaves design mode. */
declare const DESIGN_MODE_EXIT = "arcy:design-mode:exit";
/**
 * Posted once per pick, asynchronously, after rasterization finishes
 * (15.7). Never gates `DESIGN_MODE_PICK`'s own delivery (D502): a receiver
 * that has not built `DESIGN_MODE_SCREENSHOT` into its `switch` simply drops
 * it via the same unknown-`type` path every other unrecognized message takes,
 * so this needed no `DESIGN_MODE_PROTOCOL` bump to add.
 */
declare const DESIGN_MODE_SCREENSHOT = "arcy:design-mode:screenshot";
/**
 * Posted instead of a pick when the picker refuses the element (ADR 0255
 * §5): a captcha, or an element inside a frame from another site. Carries
 * the reason and nothing about the element; the dashboard shows the
 * sentence under the picker button. Additive, like the screenshot message:
 * an older receiver drops it through the unknown-type path.
 */
declare const DESIGN_MODE_REFUSED = "arcy:design-mode:refused";
type PickRefusal = "captcha" | "cross_origin_iframe";
declare const PICK_REFUSALS: readonly PickRefusal[];
/**
 * How long the widget may spend rasterizing before it gives up on a
 * screenshot, in milliseconds. Part of the wire contract, not an internal
 * detail of `screenshot.ts`, because the receiver has to wait at least this
 * long before deciding no screenshot is coming (D1476).
 *
 * It lives here so both halves read one number. When they did not, the
 * dashboard closed the picker tab two seconds after the pick while the
 * rasterizer was still working, and every screenshot on a page of ordinary
 * weight was lost: the tab died mid-render and the message was never posted.
 * The gap opened the day the rasterizer changed (ADR 0157). The old one
 * copied a property list onto absolutely positioned boxes and finished in
 * well under a second; the one that replaced it clones the whole document
 * with its computed styles, its pseudo-elements and its web fonts embedded as
 * data URLs, which on a real marketing page takes several. Nobody revisited
 * the two seconds, because nothing in either file mentioned the other.
 *
 * Then 8s turned out to be a floor rather than a ceiling, because the
 * rasterizer spends its `timeout` per resource and one lazy image below the
 * fold always ran it out (D1258). With that fixed and the render scoped to
 * the crop's covering ancestor, a real capture is around 200ms, so this
 * number stopped being something an operator waits on. It is now only the
 * ceiling on the worst case left: a target nothing smaller than the document
 * covers, on a heavy page, which measured 2.6s of real work.
 */
declare const SCREENSHOT_RENDER_BUDGET_MS = 5000;
interface DesignModeReady {
    type: typeof DESIGN_MODE_READY;
    protocol: number;
}
interface DesignModePick {
    type: typeof DESIGN_MODE_PICK;
    protocol: number;
    target: TargetFingerprint;
    /**
     * The path the element was picked on, read at pick time (D504). A target
     * and the page it lives on are stored as two separate fields on a step, and
     * browse mode means the operator can be somewhere else by the time they
     * pick. Without this the step would keep whichever page was chosen in the
     * dropdown, and a target filed under the wrong page reports zero forever.
     */
    route: string;
    /**
     * How many elements on this page matched the target at the moment it was
     * picked (ADR 0132). Scored here, where the live document and the matcher
     * both already are, rather than asked for afterwards over a channel to a tab
     * the pick is about to close.
     *
     * Information for the operator, never a gate: zero and forty are both real
     * answers worth showing, and neither is a reason to refuse a save.
     */
    matchCount: number;
}
type PickReach = TargetReach;
interface DesignModeExit {
    type: typeof DESIGN_MODE_EXIT;
    protocol: number;
}
interface DesignModeScreenshot {
    type: typeof DESIGN_MODE_SCREENSHOT;
    protocol: number;
    /** A `data:image/png;base64,...` artifact of the most recently picked
     * element. Last one wins, same as the pick it decorates: a receiver simply
     * overwrites whatever it is holding. */
    screenshot: string;
}
interface DesignModeRefused {
    type: typeof DESIGN_MODE_REFUSED;
    protocol: number;
    reason: PickRefusal;
}
type DesignModeMessage = DesignModeReady | DesignModePick | DesignModeExit | DesignModeScreenshot | DesignModeRefused;
/**
 * The receiver's only entry point: turns `event.data` into a message it can
 * act on, or null. Says nothing about *who* sent it. The other two checks
 * D501 requires, the source window and the origin, belong to the receiver,
 * because only it knows which window it opened and which environment it is
 * authoring in.
 */
declare function readDesignModeMessage(data: unknown): DesignModeMessage | null;

export { DESIGN_MODE_EXIT, DESIGN_MODE_PICK, DESIGN_MODE_PROTOCOL, DESIGN_MODE_READY, DESIGN_MODE_REFUSED, DESIGN_MODE_SCREENSHOT, type DesignModeExit, type DesignModeMessage, type DesignModePick, type DesignModeReady, type DesignModeRefused, type DesignModeScreenshot, MASK, PICK_REFUSALS, type PickReach, type PickRefusal, SCREENSHOT_RENDER_BUDGET_MS, readDesignModeMessage };
ODE_REFUSED;
    protocol: number;
    reason: PickRefusal;
}
type DesignModeMessage = DesignModeReady | DesignModePick | DesignModeExit | DesignModeScreenshot | DesignModeRefused;
/**
 * The receiver's only entry point: turns `event.data` into a message it can
 * act on, or null. Says nothing about *who* sent it. The other two checks
 * D501 requires, the source window and the origin, belong to the receiver,
 * because only it knows which window it opened and which environment it is
 * authoring in.
 */
declare function readDesignModeMessage(data: unknown): DesignModeMessage | null;

export { DESIGN_MODE_EXIT, DESIGN_MODE_PICK, DESIGN_MODE_PROTOCOL, DESIGN_MODE_READY, DESIGN_MODE_REFUSED, DESIGN_MODE_SCREENSHOT, type DesignModeExit, type DesignModeMessage, type DesignModePick, type DesignModeReady, type DesignModeRefused, type DesignModeScreenshot, MASK, PICK_REFUSALS, type PickReach, type PickRefusal, SCREENSHOT_RENDER_BUDGET_MS, readDesignModeMessage };
