{"version":3,"sources":["../src/index.ts","../src/internal/math.ts","../src/config/palettes.ts","../src/config/defaults.ts","../src/config/merge.ts","../src/geometry/clip-path.ts","../src/geometry/rng.ts","../src/geometry/edges.ts","../src/geometry/noise-tile.ts","../src/geometry/pool.ts","../src/geometry/mark-space.ts","../src/geometry/snap.ts","../src/internal/dom.ts","../src/targeting/text-search.ts","../src/targeting/include-exclude.ts","../src/targeting/normalize.ts","../src/targeting/line-rects.ts","../src/targeting/velocity.ts","../src/targeting/anchor.ts","../src/targeting/observers.ts","../src/render/renderer.ts","../src/render/tier-select.ts","../src/render/blend.ts","../src/render/tier-b-css.ts","../src/render/tier-a-svg.ts","../src/render/tier-c-highlight-api.ts","../src/render/animation.ts","../src/render/mark-handle.ts","../src/render/highlight.ts"],"sourcesContent":["/** `@highlighters/core` - the framework-agnostic public API. The DOM-free subset is available from the SSR-safe `@highlighters/core/path` entry. */\n\nexport { highlight, highlightAll, highlightSelection, group } from \"./render/highlight.js\";\n\nexport { resolveOptions, mergeOptions } from \"./config/merge.js\";\nexport { DEFAULT_OPTIONS } from \"./config/defaults.js\";\nexport { PALETTES, getPalette, resolveSwatch, defaultSwatch } from \"./config/palettes.js\";\n\nexport { buildMarkGeometry } from \"./geometry/mark-space.js\";\nexport { buildClipPath } from \"./geometry/clip-path.js\";\nexport { buildEdge } from \"./geometry/edges.js\";\nexport { buildNoiseTile, buildNoiseTileDataUrl } from \"./geometry/noise-tile.js\";\nexport { buildPoolGradient } from \"./geometry/pool.js\";\nexport { hashJitter, hashU32, mulberry } from \"./geometry/rng.js\";\nexport { snapRangeToBounds } from \"./geometry/snap.js\";\n\nexport { toRanges } from \"./targeting/normalize.js\";\nexport { rangesToLineRects, computeAnchor } from \"./targeting/line-rects.js\";\nexport { collectPageRanges } from \"./targeting/include-exclude.js\";\nexport { findTextRanges } from \"./targeting/text-search.js\";\nexport { findSelectionAnchor } from \"./targeting/anchor.js\";\nexport { createReflowObserver, createMutationWatcher } from \"./targeting/observers.js\";\n\nexport { detectEnvironment, selectTier } from \"./render/tier-select.js\";\nexport { createSvgRenderer } from \"./render/tier-a-svg.js\";\nexport { createCssRenderer } from \"./render/tier-b-css.js\";\nexport { createHighlightApiRenderer } from \"./render/tier-c-highlight-api.js\";\n\nexport type {\n  ColorValue,\n  MarkType,\n  ShapeType,\n  TipType,\n  EdgeCap,\n  BlendMode,\n  SnapMode,\n  RendererTierPreference,\n  RendererTier,\n  AnimationDirection,\n  AnimationTrigger,\n  EasingValue,\n  GradientStop,\n  GradientConfig,\n  PaletteName,\n  PaletteSwatch,\n  Palette,\n  TipOptions,\n  InkOptions,\n  SpeedDynamicsOptions,\n  EdgeOptions,\n  PaperOptions,\n  GlowOptions,\n  AnimationOptions,\n  HighlightOptions,\n  ResolvedTip,\n  ResolvedInk,\n  ResolvedSpeedDynamics,\n  ResolvedEdge,\n  ResolvedPaper,\n  ResolvedGlow,\n  ResolvedAnimation,\n  ResolvedOptions,\n  LineSpeedProfile,\n  Box,\n  LineRect,\n  Anchor,\n  EdgeVertex,\n  PoolGradient,\n  NoiseTile,\n  MaskOffset,\n  MarkGeometry,\n  PageTarget,\n  TextTarget,\n  Target,\n  MarkHandle,\n  GroupHandle,\n  RenderEnvironment,\n  Renderer,\n  RenderContext,\n  ReflowCallback,\n  MutationCallback,\n  Disconnect,\n} from \"./types.js\";\n","export function clamp(value: number, lo: number, hi: number): number {\n  return value < lo ? lo : value > hi ? hi : value;\n}\n","/** Curated palette families, each tuned so any pair of its swatches reads coherently for color-coding. Pure data. */\n\nimport type {\n  ColorValue,\n  Palette,\n  PaletteName,\n  PaletteSwatch,\n} from \"../types.js\";\n\n/** Each `swatches` map is ordered; that order is the color-coding cycle. */\nexport const PALETTES: Record<PaletteName, Palette> = {\n  fluorescent: {\n    name: \"fluorescent\",\n    swatches: {\n      yellow: \"#fff14d\",\n      green: \"#9bff5a\",\n      orange: \"#ffb24d\",\n      pink: \"#ff6fae\",\n      blue: \"#5ad7ff\",\n      purple: \"#c08bff\",\n    },\n  },\n  mild: {\n    name: \"mild\",\n    swatches: {\n      yellow: \"#f5e6a8\",\n      green: \"#bfe0b2\",\n      blue: \"#aacfe0\",\n      pink: \"#eec2cf\",\n      orange: \"#f0cdb0\",\n      purple: \"#cdc1e0\",\n    },\n  },\n  vintage: {\n    name: \"vintage\",\n    swatches: {\n      mustard: \"#e3c567\",\n      olive: \"#bcc06a\",\n      rust: \"#d99873\",\n      rose: \"#d39ba0\",\n      teal: \"#7fb3a8\",\n      plum: \"#a98bb0\",\n    },\n  },\n  neutral: {\n    name: \"neutral\",\n    swatches: {\n      sand: \"#e7dcc4\",\n      stone: \"#d8d2c4\",\n      clay: \"#dcc3b0\",\n      sage: \"#cdd6c2\",\n      slate: \"#c4ccd2\",\n      taupe: \"#d3c8c2\",\n    },\n  },\n  calm: {\n    name: \"calm\",\n    swatches: {\n      sky: \"#bcd6ec\",\n      mint: \"#bfe4d6\",\n      lavender: \"#cfcae8\",\n      blush: \"#ecd2da\",\n      seafoam: \"#c6e3df\",\n      periwinkle: \"#c2cce8\",\n    },\n  },\n};\n\n/** Default swatch per family: the least-text-obscuring hue. */\nconst DEFAULT_SWATCH_NAMES: Record<PaletteName, string> = {\n  fluorescent: \"yellow\",\n  mild: \"yellow\",\n  vintage: \"mustard\",\n  neutral: \"sand\",\n  calm: \"sky\",\n};\n\n/** Return a palette family by name. Throws on an unknown family. */\nexport function getPalette(name: PaletteName): Palette {\n  const palette = PALETTES[name];\n  if (!palette) {\n    throw new Error(`@highlighters: unknown palette \"${name}\"`);\n  }\n  return palette;\n}\n\n/** Resolve a `{ palette, swatch }` reference to a {@link ColorValue}. Throws on an unknown swatch. */\nexport function resolveSwatch(ref: PaletteSwatch): ColorValue {\n  const palette = getPalette(ref.palette);\n  const color = palette.swatches[ref.swatch];\n  if (color === undefined) {\n    throw new Error(\n      `@highlighters: unknown swatch \"${ref.swatch}\" in palette \"${ref.palette}\"`,\n    );\n  }\n  return color;\n}\n\n/** The default color for a family. */\nexport function defaultSwatch(name: PaletteName): ColorValue {\n  return resolveSwatch({ palette: name, swatch: DEFAULT_SWATCH_NAMES[name] });\n}\n","/** The fully-resolved baseline at the bottom of the merge chain. Deep-frozen so it can be shared as the merge floor without mutation. */\n\nimport type { ResolvedOptions } from \"../types.js\";\nimport { defaultSwatch } from \"./palettes.js\";\n\nexport const DEFAULT_OPTIONS: ResolvedOptions = Object.freeze({\n  markType: \"highlight\",\n  color: defaultSwatch(\"mild\"),\n  gradient: null,\n  opacity: 0.55,\n  blendMode: \"multiply\",\n  vivid: false,\n  tip: Object.freeze({\n    type: \"chisel\",\n    width: 16,\n    thickness: 4,\n    angle: 35,\n    overshoot: 2,\n    overshootJitter: 1,\n    angleJitter: 0,\n  }),\n  ink: Object.freeze({\n    flow: 0.45,\n    viscosity: 0.5,\n    feathering: 0.2,\n    streakiness: 0.25,\n    dryout: 0.1,\n    startEndBuildup: 0.1,\n    flowFade: 0.5,\n  }),\n  // Speed-aware deposit is Beta and off by default; thresholds are px/ms.\n  speed: Object.freeze({\n    enabled: false,\n    sensitivity: 1,\n    slowSpeed: 2.5,\n    fastSpeed: 10.5,\n    minDeposit: 0.4,\n    smoothing: 1,\n    resolution: 24,\n    dryoutBoost: 1,\n    streakBoost: 0.08,\n    featherReduce: 1,\n    poolBoost: 1,\n  }),\n  edge: Object.freeze({\n    waviness: 1,\n    frequency: 22, // px segment length of the wave grid\n    roughness: 0.2,\n    cap: \"round\",\n    radius: 5,\n  }),\n  paper: Object.freeze({\n    absorbency: 0.3,\n  }),\n  glow: Object.freeze({\n    enabled: false,\n    intensity: 0.5,\n    spread: 4,\n    // Empty resolves to a brightened form of the ink color at render time.\n    color: \"\",\n  }),\n  snap: \"word\",\n  fadeOnClear: true,\n  renderer: \"auto\",\n  animation: Object.freeze({\n    draw: true,\n    duration: 420,\n    easing: \"ease-out\",\n    direction: \"left-to-right\",\n    stagger: 90,\n    trigger: \"immediate\",\n    threshold: 0.2,\n    rootMargin: \"0px\",\n    repeat: false,\n  }),\n  semantic: false,\n  contrastBackground: null,\n  // Null signals each mark must derive its seed from a stable target identity.\n  seed: null,\n}) as ResolvedOptions;\n","/** Option merging and resolution. SSR-safe (no DOM access). */\n\nimport type {\n  BlendMode,\n  ColorValue,\n  HighlightOptions,\n  PaletteSwatch,\n  ResolvedAnimation,\n  ResolvedEdge,\n  ResolvedGlow,\n  ResolvedInk,\n  ResolvedOptions,\n  ResolvedPaper,\n  ResolvedSpeedDynamics,\n  ResolvedTip,\n} from \"../types.js\";\nimport { clamp } from \"../internal/math.js\";\nimport { DEFAULT_OPTIONS } from \"./defaults.js\";\nimport { defaultSwatch, resolveSwatch } from \"./palettes.js\";\n\n/** A finite number, else `fallback`. Guards against NaN/Infinity leaking into geometry/CSS. */\nfunction finiteOr(value: number | undefined, fallback: number): number {\n  return typeof value === \"number\" && Number.isFinite(value) ? value : fallback;\n}\n\n/** A finite, strictly-positive number, else `fallback`. */\nfunction positiveOr(value: number | undefined, fallback: number): number {\n  return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\n/** The namespaced option groups that are merged field-wise rather than replaced. */\nconst GROUP_KEYS = [\"tip\", \"ink\", \"speed\", \"edge\", \"paper\", \"glow\", \"animation\"] as const;\n\ntype GroupKey = (typeof GROUP_KEYS)[number];\n\n/** Shallow-merge a single namespaced group, with `override` winning per field. */\nfunction mergeGroup(\n  base: Record<string, unknown> | undefined,\n  override: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n  if (base === undefined) return override;\n  if (override === undefined) return base;\n  return { ...base, ...override };\n}\n\n/** Deep-merge two partials: scalars take `override`, namespaced groups merge field-wise, `shape`/`markType` collapse onto `markType`. Pure. */\nexport function mergeOptions(\n  base: HighlightOptions,\n  override: HighlightOptions,\n): HighlightOptions {\n  const result: HighlightOptions = { ...base, ...override };\n\n  for (const key of GROUP_KEYS) {\n    const merged = mergeGroup(\n      base[key] as Record<string, unknown> | undefined,\n      override[key] as Record<string, unknown> | undefined,\n    );\n    if (merged === undefined) {\n      delete result[key];\n    } else {\n      (result as Record<GroupKey, unknown>)[key] = merged;\n    }\n  }\n\n  const markType =\n    override.markType ?? override.shape ?? base.markType ?? base.shape;\n  if (markType !== undefined) {\n    result.markType = markType;\n    delete result.shape;\n  }\n\n  return result;\n}\n\n/** Resolve the `color`/`palette` inputs to a concrete {@link ColorValue}. */\nfunction resolveColor(\n  color: ColorValue | PaletteSwatch | undefined,\n  palette: HighlightOptions[\"palette\"],\n  fallback: ColorValue,\n): ColorValue {\n  // Empty/whitespace string is treated as unset so it can't emit an empty colour token into the gradient.\n  if (typeof color === \"string\" && color.trim() !== \"\") {\n    return color;\n  }\n  if (color && typeof color === \"object\") {\n    return resolveSwatch(color);\n  }\n  if (palette) {\n    return defaultSwatch(palette);\n  }\n  return fallback;\n}\n\n/** Resolve a partial {@link HighlightOptions} into a fully-defaulted {@link ResolvedOptions}. Pure. */\nexport function resolveOptions(input: HighlightOptions = {}): ResolvedOptions {\n  const d = DEFAULT_OPTIONS;\n\n  const merged = mergeOptions({}, input);\n\n  const tip: ResolvedTip = {\n    type: merged.tip?.type ?? d.tip.type,\n    width: finiteOr(merged.tip?.width, d.tip.width),\n    thickness: finiteOr(merged.tip?.thickness, d.tip.thickness),\n    angle: finiteOr(merged.tip?.angle, d.tip.angle),\n    overshoot: finiteOr(merged.tip?.overshoot, d.tip.overshoot),\n    overshootJitter: finiteOr(merged.tip?.overshootJitter, d.tip.overshootJitter),\n    angleJitter: finiteOr(merged.tip?.angleJitter, d.tip.angleJitter),\n  };\n\n  const ink: ResolvedInk = {\n    flow: finiteOr(merged.ink?.flow, d.ink.flow),\n    viscosity: finiteOr(merged.ink?.viscosity, d.ink.viscosity),\n    feathering: finiteOr(merged.ink?.feathering, d.ink.feathering),\n    streakiness: finiteOr(merged.ink?.streakiness, d.ink.streakiness),\n    dryout: finiteOr(merged.ink?.dryout, d.ink.dryout),\n    startEndBuildup: finiteOr(merged.ink?.startEndBuildup, d.ink.startEndBuildup),\n    flowFade: finiteOr(merged.ink?.flowFade, d.ink.flowFade),\n  };\n\n  const sd = d.speed;\n  // Order thresholds so fastSpeed >= slowSpeed; an inverted pair collapses the velocity normalizer's denominator.\n  const rawSlow = Math.max(0, finiteOr(merged.speed?.slowSpeed, sd.slowSpeed));\n  const rawFast = Math.max(0, finiteOr(merged.speed?.fastSpeed, sd.fastSpeed));\n  const speed: ResolvedSpeedDynamics = {\n    enabled: merged.speed?.enabled ?? sd.enabled,\n    sensitivity: clamp(finiteOr(merged.speed?.sensitivity, sd.sensitivity), 0, 1),\n    slowSpeed: Math.min(rawSlow, rawFast),\n    fastSpeed: Math.max(rawSlow, rawFast),\n    minDeposit: clamp(finiteOr(merged.speed?.minDeposit, sd.minDeposit), 0, 1),\n    smoothing: clamp(finiteOr(merged.speed?.smoothing, sd.smoothing), 0, 1),\n    resolution: Math.max(4, Math.min(24, Math.round(finiteOr(merged.speed?.resolution, sd.resolution)))),\n    dryoutBoost: clamp(finiteOr(merged.speed?.dryoutBoost, sd.dryoutBoost), 0, 1),\n    streakBoost: clamp(finiteOr(merged.speed?.streakBoost, sd.streakBoost), 0, 1),\n    featherReduce: clamp(finiteOr(merged.speed?.featherReduce, sd.featherReduce), 0, 1),\n    poolBoost: clamp(finiteOr(merged.speed?.poolBoost, sd.poolBoost), 0, 1),\n  };\n\n  const edge: ResolvedEdge = {\n    waviness: finiteOr(merged.edge?.waviness, d.edge.waviness),\n    frequency: finiteOr(merged.edge?.frequency, d.edge.frequency),\n    roughness: finiteOr(merged.edge?.roughness, d.edge.roughness),\n    cap: merged.edge?.cap ?? d.edge.cap,\n    radius: finiteOr(merged.edge?.radius, d.edge.radius),\n  };\n\n  const paper: ResolvedPaper = {\n    absorbency: finiteOr(merged.paper?.absorbency, d.paper.absorbency),\n  };\n\n  // A `palette` with no `color` draws that palette's default swatch; detect from raw input, not merged.\n  const color =\n    input.color === undefined && input.palette !== undefined\n      ? defaultSwatch(input.palette)\n      : resolveColor(merged.color, merged.palette, d.color);\n\n  const glow: ResolvedGlow = {\n    enabled: merged.glow?.enabled ?? d.glow.enabled,\n    intensity: finiteOr(merged.glow?.intensity, d.glow.intensity),\n    spread: finiteOr(merged.glow?.spread, d.glow.spread),\n    color: merged.glow?.color ?? (d.glow.color || color),\n  };\n\n  const animation: ResolvedAnimation = {\n    draw: merged.animation?.draw ?? d.animation.draw,\n    duration: positiveOr(merged.animation?.duration, d.animation.duration),\n    easing: merged.animation?.easing ?? d.animation.easing,\n    direction: merged.animation?.direction ?? d.animation.direction,\n    stagger: finiteOr(merged.animation?.stagger, d.animation.stagger),\n    trigger: merged.animation?.trigger ?? d.animation.trigger,\n    threshold: finiteOr(merged.animation?.threshold, d.animation.threshold),\n    rootMargin: merged.animation?.rootMargin ?? d.animation.rootMargin,\n    repeat: merged.animation?.repeat ?? d.animation.repeat,\n  };\n\n  const blendMode: BlendMode = merged.blendMode ?? d.blendMode;\n\n  return {\n    markType: merged.markType ?? merged.shape ?? d.markType,\n    color,\n    gradient: merged.gradient ?? d.gradient,\n    opacity: Math.max(0, Math.min(1, finiteOr(merged.opacity, d.opacity))),\n    blendMode,\n    vivid: merged.vivid ?? d.vivid,\n    tip,\n    ink,\n    speed,\n    edge,\n    paper,\n    glow,\n    snap: merged.snap ?? d.snap,\n    fadeOnClear: merged.fadeOnClear ?? d.fadeOnClear,\n    renderer: merged.renderer ?? d.renderer,\n    animation,\n    semantic: merged.semantic ?? d.semantic,\n    contrastBackground: merged.contrastBackground ?? d.contrastBackground,\n    seed: merged.seed ?? d.seed,\n  };\n}\n","import type { Box, EdgeCap, EdgeVertex, ResolvedTip } from \"../types.js\";\n\n/**\n * Build the `clip-path: path(...)` value for one band, in absolute-px local coordinates.\n *\n * The shape is the chisel parallelogram, edges threaded through the wave vertices and\n * joined by rounded `Q`-arc corners. Slant is an absolute-px x-shift (not a percentage)\n * so radius and slant keep their true size at any width. Every coordinate is a pure\n * function of the inputs, so growing the mark only appends commands and the covered prefix\n * stays byte-identical.\n */\n\nexport interface ClipPathOptions {\n  /** The band's local box. Only `width`/`height` are used (origin is `0,0`). */\n  box: Box;\n  tip: ResolvedTip;\n  /** Top-edge wave vertices (ascending x), threaded left → right. */\n  topEdge: EdgeVertex[];\n  /** Bottom-edge wave vertices (ascending x), threaded right → left. */\n  bottomEdge: EdgeVertex[];\n  cap: EdgeCap;\n  /** Corner radius in absolute px (clamped against short marks). */\n  radius: number;\n  /** Advancing-front truncation width in local px (the draw-on); the emitted prefix stays byte-identical as it grows. Defaults to `box.width`. */\n  front?: number;\n}\n\nfunction fx(value: number): string {\n  return value.toFixed(1);\n}\n\nfunction fy(value: number): string {\n  return value.toFixed(2);\n}\n\n/** The chisel slant in absolute px: how far the top edge leads the bottom. Capped at half the width so it can't invert the parallelogram. */\nexport function chiselSlant(tip: ResolvedTip, width: number, height: number): number {\n  if (tip.type !== \"chisel\") return 0;\n  const norm = Math.min(Math.abs(tip.angle), 90) / 90;\n  return Math.min(norm * height * 0.9, width * 0.5);\n}\n\n/** Resolve slant and corner radius for a tip type and box. Radius is clamped so the four arcs always fit. */\nfunction resolveSlantAndRadius(\n  tip: ResolvedTip,\n  cap: EdgeCap,\n  width: number,\n  height: number,\n  radius: number,\n): { slant: number; r: number } {\n  const slant = chiselSlant(tip, width, height);\n\n  const usableWidth = Math.max(0, width - slant);\n  const maxByWidth = usableWidth / 2;\n  const maxByHeight = height / 2;\n  const radiusCeil = Math.max(0, Math.min(maxByWidth, maxByHeight));\n\n  let r: number;\n  if (cap === \"flat\" || cap === \"square\") {\n    r = 0;\n  } else if (tip.type === \"bullet\") {\n    r = radiusCeil;\n  } else if (tip.type === \"fine\") {\n    r = Math.min(radius, radiusCeil, height * 0.25);\n  } else {\n    r = Math.min(Math.max(0, radius), radiusCeil);\n  }\n  return { slant, r };\n}\n\n/** The smallest visible front (local px): the touchdown width where the leading cap's arcs just meet (`slant + 2·radius`). Below it the parallelogram inverts. */\nexport function minVisibleFront(\n  tip: ResolvedTip,\n  cap: EdgeCap,\n  width: number,\n  height: number,\n  radius: number,\n): number {\n  const { slant, r } = resolveSlantAndRadius(tip, cap, width, height, radius);\n  return slant + 2 * r;\n}\n\ninterface Pt {\n  x: number;\n  y: number;\n}\n\n/** Collect wave vertices strictly inside the corner-arc inset so a wave point can't kink a corner arc. `reverse` consumes right to left (the bottom edge). */\nfunction collectVertices(\n  vertices: EdgeVertex[],\n  reverse: boolean,\n  minX: number,\n  maxX: number,\n): Pt[] {\n  const out: Pt[] = [];\n  const n = vertices.length;\n  for (let k = 0; k < n; k++) {\n    const v = reverse ? vertices[n - 1 - k] : vertices[k];\n    if (v.x <= minX || v.x >= maxX) continue;\n    out.push({ x: v.x, y: v.y });\n  }\n  return out;\n}\n\n/** Emit a smooth edge through the wave vertices as quadratic Béziers (midpoint smoothing) so corners round instead of kinking. No vertices yields a straight `L`. */\nfunction smoothEdge(sx: number, sy: number, verts: Pt[], ex: number, ey: number): string {\n  if (verts.length === 0) return `L ${fx(ex)} ${fy(ey)} `;\n  const pts: Pt[] = [{ x: sx, y: sy }, ...verts, { x: ex, y: ey }];\n  let out = \"\";\n  for (let i = 1; i < pts.length - 2; i++) {\n    const mx = (pts[i].x + pts[i + 1].x) / 2;\n    const my = (pts[i].y + pts[i + 1].y) / 2;\n    out += `Q ${fx(pts[i].x)} ${fy(pts[i].y)} ${fx(mx)} ${fy(my)} `;\n  }\n  const c = pts[pts.length - 2];\n  out += `Q ${fx(c.x)} ${fy(c.y)} ${fx(ex)} ${fy(ey)} `;\n  return out;\n}\n\n/** Build the bare `path(...)` clip-path value, walking the parallelogram clockwise with a `Q` arc at each corner. */\nexport function buildClipPath(opts: ClipPathOptions): string {\n  const { box, tip, topEdge, bottomEdge, cap, radius } = opts;\n  const ow = box.width;\n  const oh = box.height;\n\n  // Resolve slant/radius from the FULL box, never the current front, so the leading cap shape is identical from first frame to last.\n  const { slant: sl, r: R } = resolveSlantAndRadius(tip, cap, ow, oh, radius);\n\n  // `front <= 0` is the empty state. Clamp into [minFront, ow] so the band starts at a tip-shaped touchdown and never inverts.\n  const reqFront = opts.front ?? ow;\n  if (reqFront <= 0) return 'path(\"M 0 0 Z\")';\n  const minFront = sl + 2 * R;\n  const F = Math.max(minFront, Math.min(reqFront, ow));\n\n  // Only the leading (right) cap rides the front `F`; the left cap is fixed.\n  const topStartX = sl + R;\n  const topEndX = F - R;\n  const bottomStartX = F - sl - R;\n  const bottomEndX = R;\n\n  const topVerts = collectVertices(topEdge, false, topStartX, topEndX);\n  const bottomVerts = collectVertices(bottomEdge, true, bottomEndX, bottomStartX);\n\n  return (\n    `path(\"M ${fx(topStartX)} 0 ` +\n    smoothEdge(topStartX, 0, topVerts, topEndX, 0) +\n    `Q ${fx(F)} 0 ${fx(F)} ${fy(R)} ` +\n    `L ${fx(F - sl)} ${fy(oh - R)} ` +\n    `Q ${fx(F - sl)} ${fy(oh)} ${fx(bottomStartX)} ${fy(oh)} ` +\n    smoothEdge(bottomStartX, oh, bottomVerts, bottomEndX, oh) +\n    `Q 0 ${fy(oh)} 0 ${fy(oh - R)} ` +\n    `L ${fx(sl)} ${fy(R)} ` +\n    `Q ${fx(sl)} 0 ${fx(topStartX)} 0 Z\")`\n  );\n}\n","/** Deterministic randomness primitives: no platform PRNG or wall-clock, so identical seeds yield byte-identical geometry on server and client. */\n\n/** Canonical jitter primitive: a value in `[-1, 1]` from a `sin()`-based hash. Draw decorrelated values by offsetting the seed. */\nexport function hashJitter(seed: number): number {\n  const x = Math.sin(seed * 9301 + 49297) * 233280;\n  return (x - Math.floor(x)) * 2 - 1;\n}\n\n/** Mulberry-style integer hash to u32. Avalanches the bits hard, for deriving one stable seed from another without low-bit correlation. */\nexport function hashU32(seed: number): number {\n  let z = (seed | 0) + 0x6d2b79f5;\n  z = Math.imul(z ^ (z >>> 15), z | 1);\n  z ^= z + Math.imul(z ^ (z >>> 7), z | 61);\n  return (z ^ (z >>> 14)) >>> 0;\n}\n\n/** Deterministic mulberry32 PRNG in `[0, 1)`, for cases needing many sequential draws rather than offset {@link hashJitter} lookups. */\nexport function mulberry(seed: number): () => number {\n  let a = seed | 0;\n  return function next(): number {\n    a |= 0;\n    a = (a + 0x6d2b79f5) | 0;\n    let t = Math.imul(a ^ (a >>> 15), a | 1);\n    t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n  };\n}\n","import type { EdgeVertex } from \"../types.js\";\nimport { hashJitter } from \"./rng.js\";\n\n/**\n * Wavy-edge vertices on a fixed spatial grid.\n *\n * Vertices live at `x = gridIndex * segmentLength` on a global px grid, jitter\n * seeded by that grid index, so wavelength and per-x phase are width-independent\n * and growing the extent only appends vertices, never shifting the existing ones.\n * (Interpolating by current width and seeding by loop index would make the wobble swim during a drag.)\n */\n\n/** Per-role seed offsets so independent jitter draws never move in lockstep. */\nconst BASE_WAVE_OFFSET = 17;\nconst ROUGHNESS_OFFSET = 911;\n\nexport interface EdgeBuildOptions {\n  /** One endpoint in absolute px (lower or higher x; either order). */\n  startX: number;\n  /** The other endpoint in absolute px. May be less than `startX` (reversed edge). */\n  endX: number;\n  /** The edge's baseline y in absolute px; vertices jitter around this. */\n  baseY: number;\n  /** Wave wavelength: the px spacing between adjacent grid vertices. */\n  segmentLength: number;\n  /** Peak wave displacement from `baseY`, in absolute px. */\n  amplitude: number;\n  /** High-frequency micro-jitter on the base wave, `0`-`1` (up to ~30% of `amplitude`) so the edge reads frayed rather than sinusoidal. */\n  roughness: number;\n  /** Base seed for this edge (e.g. line seed + a top/bottom offset). */\n  seed: number;\n}\n\n/**\n * Generate wave vertices on the fixed global grid for one edge, ascending in `x`.\n * @returns Vertices ascending in `x`; empty for a sub-`segmentLength` span (caller draws straight).\n */\nexport function buildEdge(opts: EdgeBuildOptions): EdgeVertex[] {\n  const { startX, endX, baseY, segmentLength, amplitude, roughness, seed } = opts;\n\n  if (!(segmentLength > 0)) return [];\n\n  const lo = Math.min(startX, endX);\n  const hi = Math.max(startX, endX);\n\n  // Half-px epsilon keeps the extreme grid points clear of the corner arcs.\n  const firstIdx = Math.ceil((lo + 0.5) / segmentLength);\n  const lastIdx = Math.floor((hi - 0.5) / segmentLength);\n\n  const vertices: EdgeVertex[] = [];\n  const roughAmp = amplitude * 0.3 * roughness;\n  for (let i = firstIdx; i <= lastIdx; i++) {\n    const x = i * segmentLength;\n    let y = baseY + hashJitter(seed + i * BASE_WAVE_OFFSET) * amplitude;\n    if (roughAmp !== 0) {\n      y += hashJitter(seed + i * BASE_WAVE_OFFSET + ROUGHNESS_OFFSET) * roughAmp;\n    }\n    vertices.push({ x, y, gridIndex: i });\n  }\n  return vertices;\n}\n","import { clamp } from \"../internal/math.js\";\nimport type { NoiseTile } from \"../types.js\";\nimport { hashU32 } from \"./rng.js\";\n\n/**\n * The fixed-pixel noise tile that gives the mark its hand-inked grain.\n *\n * Two `feTurbulence` layers (striation lanes + pressure patches) baked once into a\n * constant-pixel, seamlessly-stitched tile and repeated, never scaled, so grain density\n * is invariant to mark size. Pure string-built SVG `data:` URL: no DOM access (SSR-safe).\n */\n\nconst DEFAULT_TILE_WIDTH = 256;\nconst DEFAULT_TILE_HEIGHT = 64;\n\n// Low x + moderate y yields chunky horizontal lanes that read as bands rather than hair-thin noise.\nconst STRIATION_FREQUENCY = \"0.04 0.34\";\nconst PATCH_FREQUENCY = \"0.012\";\n\n// Base mask-alpha floors/slopes; the builder lowers the floor as the knobs rise. Baseline stays high enough that the tip caps don't sit on a low-alpha hole.\nconst STRIATION_ALPHA_MIN = 0.82;\nconst STRIATION_ALPHA_SLOPE = 0.16;\nconst PATCH_ALPHA_MIN = 0.86;\nconst PATCH_ALPHA_SLOPE = 0.14;\n\nconst STRIATION_OCTAVES = 1;\nconst PATCH_OCTAVES = 2;\n\nexport interface NoiseTileOptions {\n  /** Fixed tile width in px (default {@link DEFAULT_TILE_WIDTH}). */\n  width?: number;\n  /** Fixed tile height in px (default {@link DEFAULT_TILE_HEIGHT}). */\n  height?: number;\n  /** Master seed; mixed into both layers' `feTurbulence` seeds deterministically. */\n  seed: number;\n  /** Striation density, `0`-`1`. Raises the streak layer's alpha contrast. Clamped internally. */\n  streakiness: number;\n  /** Pressure-patch density, `0`-`1`. Raises the soft pressure-blob contribution. Clamped internally. */\n  feathering: number;\n  /** Probabilistic alpha gaps, `0`-`1`: a discrete threshold cuts low-coverage regions to transparent. Defaults to `0`. */\n  dryout?: number;\n}\n\n/** Round to 3 decimals so the emitted SVG string is byte-stable. */\nfunction fmt(value: number): string {\n  return String(Math.round(value * 1000) / 1000);\n}\n\n/** Clamp then snap a density knob to its 0.02 bucket; sub-bucket alpha deltas are below perceptual threshold. */\nfunction quantizeKnob(value: number): number {\n  return Math.round(clamp(value, 0, 1) * 50) / 50;\n}\n\n// ASCII-only base64; avoids `btoa` (a DOM global absent in some SSR runtimes) while encoding identically everywhere.\nconst B64_ALPHABET =\n  \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\nfunction toBase64Ascii(input: string): string {\n  let out = \"\";\n  const len = input.length;\n  for (let i = 0; i < len; i += 3) {\n    const b0 = input.charCodeAt(i) & 0xff;\n    const b1 = i + 1 < len ? input.charCodeAt(i + 1) & 0xff : 0;\n    const b2 = i + 2 < len ? input.charCodeAt(i + 2) & 0xff : 0;\n    const triple = (b0 << 16) | (b1 << 8) | b2;\n    out += B64_ALPHABET[(triple >> 18) & 0x3f];\n    out += B64_ALPHABET[(triple >> 12) & 0x3f];\n    out += i + 1 < len ? B64_ALPHABET[(triple >> 6) & 0x3f] : \"=\";\n    out += i + 2 < len ? B64_ALPHABET[triple & 0x3f] : \"=\";\n  }\n  return out;\n}\n\n/** Build the SVG source for the dual-`feTurbulence` tile; arithmetic `feComposite` multiplies the two layers so dark streak and dark patch reinforce. */\nfunction buildNoiseTileSvg(opts: Required<NoiseTileOptions>): string {\n  const { width, height, seed, streakiness, feathering, dryout } = opts;\n\n  // Decorrelate the two layers' seeds; `% 256` keeps them in feTurbulence's documented range.\n  const striationSeed = hashU32(seed * 2 + 3) % 256;\n  const patchSeed = hashU32(seed * 2 + 7) % 256;\n\n  // Floor bottoms out at ~0.22 at streakiness 1 so dark lanes go deep without punching a hole under the tip caps.\n  const striationSlope = STRIATION_ALPHA_SLOPE * (0.5 + 6 * streakiness);\n  const striationMin = STRIATION_ALPHA_MIN - 0.6 * streakiness;\n\n  // Dryout steepens the patch layer and lowers its floor so more area falls below the cut threshold.\n  const patchSlope = PATCH_ALPHA_SLOPE * (0.5 + feathering) + 0.6 * dryout;\n  const patchMin = PATCH_ALPHA_MIN - 0.62 * dryout;\n\n  const dryoutCut = dryoutTransfer(dryout);\n\n  return (\n    `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\">` +\n    `<defs>` +\n    `<filter id=\"g\" x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" color-interpolation-filters=\"sRGB\">` +\n    `<feTurbulence type=\"fractalNoise\" baseFrequency=\"${STRIATION_FREQUENCY}\" numOctaves=\"${STRIATION_OCTAVES}\" stitchTiles=\"stitch\" seed=\"${striationSeed}\" result=\"s\"/>` +\n    `<feColorMatrix in=\"s\" values=\"0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 ${fmt(striationSlope)} ${fmt(striationMin)}\" result=\"sa\"/>` +\n    `<feTurbulence type=\"fractalNoise\" baseFrequency=\"${PATCH_FREQUENCY}\" numOctaves=\"${PATCH_OCTAVES}\" stitchTiles=\"stitch\" seed=\"${patchSeed}\" result=\"p\"/>` +\n    `<feColorMatrix in=\"p\" values=\"0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 ${fmt(patchSlope)} ${fmt(patchMin)}\" result=\"pa\"/>` +\n    `<feComposite in=\"sa\" in2=\"pa\" operator=\"arithmetic\" k1=\"1\" k2=\"0\" k3=\"0\" k4=\"0\" result=\"ink\"/>` +\n    `<feComponentTransfer in=\"ink\">` +\n    `<feFuncA type=\"discrete\" tableValues=\"${dryoutCut}\"/>` +\n    `</feComponentTransfer>` +\n    `</filter>` +\n    `</defs>` +\n    `<rect width=\"${width}\" height=\"${height}\" fill=\"black\" filter=\"url(#g)\"/>` +\n    `</svg>`\n  );\n}\n\n/** Build the `tableValues` for the dryout alpha threshold: `\"1\"` at `dryout = 0`, leading entries flipping to `0` (transparent) up to ~45% of the range. */\nfunction dryoutTransfer(dryout: number): string {\n  if (dryout <= 0) return \"1\";\n  const segments = 16;\n  const cut = Math.round(dryout * 0.45 * segments);\n  const values: string[] = [];\n  for (let i = 0; i < segments; i++) values.push(i < cut ? \"0\" : \"1\");\n  return values.join(\" \");\n}\n\n/** Build a bare `data:image/svg+xml;base64,…` URL for the noise tile. Deterministic from `seed` and the density knobs (quantized to 0.02 buckets). Memoised, so a knob drag rebuilds at most one tile per bucket. */\nconst tileCache = new Map<string, string>();\n\nexport function buildNoiseTileDataUrl(opts: NoiseTileOptions): string {\n  // Quantize before both the key and the SVG, so cache identity and emitted tile always agree.\n  const resolved: Required<NoiseTileOptions> = {\n    width: opts.width ?? DEFAULT_TILE_WIDTH,\n    height: opts.height ?? DEFAULT_TILE_HEIGHT,\n    seed: opts.seed,\n    streakiness: quantizeKnob(opts.streakiness),\n    feathering: quantizeKnob(opts.feathering),\n    dryout: quantizeKnob(opts.dryout ?? 0),\n  };\n  const key = `${resolved.width}x${resolved.height}|${resolved.seed}|${resolved.streakiness}|${resolved.feathering}|${resolved.dryout}`;\n  const hit = tileCache.get(key);\n  if (hit !== undefined) {\n    // Re-promote so the oldest-half eviction approximates LRU; a drag can't evict its own hot tiles.\n    tileCache.delete(key);\n    tileCache.set(key, hit);\n    return hit;\n  }\n  const url = `data:image/svg+xml;base64,${toBase64Ascii(buildNoiseTileSvg(resolved))}`;\n  // Evict the oldest half rather than clearing all, so a continuous drag keeps its hot working set.\n  if (tileCache.size > 512) {\n    const half = Math.floor(tileCache.size / 2);\n    const iter = tileCache.keys();\n    for (let i = 0; i < half; i++) tileCache.delete(iter.next().value!);\n  }\n  tileCache.set(key, url);\n  return url;\n}\n\n/** Wrap {@link buildNoiseTileDataUrl} plus the fixed px dimensions (the renderer's `mask-size`, repeated never scaled) into a {@link NoiseTile}. */\nexport function buildNoiseTile(opts: NoiseTileOptions): NoiseTile {\n  const width = opts.width ?? DEFAULT_TILE_WIDTH;\n  const height = opts.height ?? DEFAULT_TILE_HEIGHT;\n  return {\n    dataUrl: buildNoiseTileDataUrl({ ...opts, width, height }),\n    width,\n    height,\n  };\n}\n","import { clamp } from \"../internal/math.js\";\nimport type { ColorValue, GradientStop, PoolGradient } from \"../types.js\";\n\n/**\n * The absolute-px end-pool gradient: end darkening is a fixed px width, not a stroke percentage.\n * The `min`/`max` clamps stop the two pools overrunning each other on a short mark, so long and\n * short marks share the same pool width. `startEndBuildup` scales pool darkness bidirectionally\n * (positive darker ends, negative lighter ends). The renderer turns the {@link PoolGradient} into CSS.\n */\n\nconst DEFAULT_ANGLE = 85;\n\nconst START_INSET_PX = 2;\nconst CORE_PX = 10;\nconst START_CORE_PCT = 40;\nconst END_CORE_PCT = 60;\nconst END_INSET_PX = 2;\n\nexport interface PoolOptions {\n  /** The band length in px (stroke direction). Drives the px↔% clamps. */\n  lengthPx: number;\n  /** Bidirectional end deposit, `-1`-`1`: positive darker ends, negative lighter ends. */\n  startEndBuildup: number;\n  color: ColorValue;\n  /** Base ink alpha at the flat core, `0`-`1`. */\n  opacity: number;\n  /** Gradient angle in degrees; defaults to `85`. */\n  angle?: number;\n  /** Directional dry-out, `0`-`1`: scales every stop's alpha down toward the end. Defaults to `0`. */\n  flowFade?: number;\n  /** Reverse the dry-out direction for a right-to-left live selection. No effect when `flowFade` is `0`. */\n  flowReversed?: boolean;\n  /** Live-speed only. Number of interior core stops (>=2). Absent yields the 4-stop gradient. */\n  coreStopCount?: number;\n  /** Live-speed only. Deposit multiplier in `[minDeposit, 1]` at core fraction `f`: `1` where slow, lower where fast. */\n  depositAt?: (fraction: number) => number;\n  /** Live-speed only. Extra end-pool build-up from deceleration, added to {@link startEndBuildup} for the end stops. */\n  decelBuildup?: number;\n}\n\nfunction roundAlpha(value: number): number {\n  return Math.round(clamp(value, 0, 1) * 1000) / 1000;\n}\n\n/** Build the absolute-px end-pool gradient. `startEndBuildup` lifts/drops the end stops, then `flowFade` tilts the whole ramp toward the drying end. */\nexport function buildPoolGradient(opts: PoolOptions): PoolGradient {\n  const buildup = clamp(opts.startEndBuildup, -1, 1);\n  const base = clamp(opts.opacity, 0, 1);\n  const fade = clamp(opts.flowFade ?? 0, 0, 1);\n\n  // 0.7 pool-contrast gain: +1 makes the ends 1.7x the core alpha, -1 drops them to 0.3x.\n  const endBase = base * (1 + 0.7 * buildup);\n  const coreBase = base;\n  const dryAt = (offset: number): number =>\n    1 - fade * (opts.flowReversed ? 1 - offset : offset);\n\n  const color: ColorValue = opts.color;\n\n  const meta = {\n    angle: opts.angle ?? DEFAULT_ANGLE,\n    startInsetPx: START_INSET_PX,\n    startCorePx: CORE_PX,\n    startCorePct: START_CORE_PCT,\n    endCorePx: CORE_PX,\n    endCorePct: END_CORE_PCT,\n    endInsetPx: END_INSET_PX,\n  };\n\n  // 4-stop gradient whenever no live speed profile is present, so static geometry stays byte-identical.\n  if (opts.coreStopCount == null && opts.depositAt == null && opts.decelBuildup == null) {\n    return {\n      ...meta,\n      stops: [\n        { offset: 0, color, opacity: roundAlpha(endBase * dryAt(0)) },\n        { offset: 0.4, color, opacity: roundAlpha(coreBase * dryAt(0.4)) },\n        { offset: 0.6, color, opacity: roundAlpha(coreBase * dryAt(0.6)) },\n        { offset: 1, color, opacity: roundAlpha(endBase * dryAt(1)) },\n      ],\n    };\n  }\n\n  // Live speed path: N core stops carrying the per-x deposit profile.\n  const n = Math.max(2, Math.round(opts.coreStopCount ?? 12));\n  const deposit = opts.depositAt ?? ((): number => 1);\n  const endBuildup = clamp(buildup + (opts.decelBuildup ?? 0), -1, 1);\n  const endAlphaBase = base * (1 + 0.7 * endBuildup);\n\n  // Core stops sit between the two px-clamped pool insets, positions resolved to px so the renderer needs no nested calc/min/max.\n  const len = Math.max(1, opts.lengthPx);\n  const startCorePos = Math.min(CORE_PX, (START_CORE_PCT / 100) * len);\n  const endCorePos = Math.max(len - CORE_PX, (END_CORE_PCT / 100) * len);\n  const span = Math.max(0, endCorePos - startCorePos);\n\n  const stops: GradientStop[] = [];\n  const coreStopsPositionsPx: number[] = [];\n\n  // The renderer normalizes per-stop alpha to the brightest stop, so a uniformly-fast line would\n  // normalize back to full. Tracking peak alpha with and without the speed factor lets `layerScale`\n  // carry the absolute dimming into layer opacity, leaving the stops to express only relative shape.\n  const leadBaked = endAlphaBase * dryAt(0) * deposit(0);\n  const trailBaked = endAlphaBase * dryAt(1) * deposit(1);\n  let maxBaked = Math.max(leadBaked, trailBaked);\n  let maxBare = Math.max(endBase * dryAt(0), endBase * dryAt(1));\n\n  stops.push({ offset: 0, color, opacity: roundAlpha(leadBaked) });\n  for (let i = 0; i < n; i++) {\n    const f = n === 1 ? 0.5 : i / (n - 1);\n    const baked = coreBase * dryAt(f) * deposit(f);\n    const bare = coreBase * dryAt(f);\n    if (baked > maxBaked) maxBaked = baked;\n    if (bare > maxBare) maxBare = bare;\n    stops.push({ offset: f, color, opacity: roundAlpha(baked) });\n    coreStopsPositionsPx.push(startCorePos + f * span);\n  }\n  stops.push({ offset: 1, color, opacity: roundAlpha(trailBaked) });\n\n  const layerScale = maxBare > 0 ? clamp(maxBaked / maxBare, 0, 1) : 1;\n\n  return {\n    ...meta,\n    stops,\n    coreStopCount: n,\n    coreStopsPositionsPx,\n    layerScale,\n  };\n}\n","import type {\n  Box,\n  EdgeVertex,\n  LineRect,\n  LineSpeedProfile,\n  MarkGeometry,\n  MaskOffset,\n  NoiseTile,\n  ResolvedOptions,\n} from \"../types.js\";\nimport { clamp } from \"../internal/math.js\";\nimport { buildClipPath, chiselSlant, minVisibleFront } from \"./clip-path.js\";\nimport { buildEdge } from \"./edges.js\";\nimport { buildNoiseTile } from \"./noise-tile.js\";\nimport { buildPoolGradient } from \"./pool.js\";\nimport { hashJitter } from \"./rng.js\";\n\n/**\n * From one line rect + resolved options + seed, produce the complete absolute-px\n * {@link MarkGeometry} for a single visual line. Everything is anchored to absolute px\n * and seeded by the stable line seed, so identical inputs yield byte-identical output\n * and growing the mark only appends grid vertices. No DOM access (SSR-safe).\n */\n\n/** Vertical padding above/below the text so the wavy edge stays clear of glyphs. */\nconst VERT_PAD = 2;\n\n/** Decorrelating seed offsets, one per derived role. */\nconst SEED_LEFT_OVER = 0;\nconst SEED_RIGHT_OVER = 11;\nconst SEED_TOP_EDGE = 200;\nconst SEED_BOTTOM_EDGE = 300;\nconst SEED_ANGLE = 400;\n\nconst MASK_X_MULT = 37;\nconst MASK_Y_MULT = 13;\n// Fixed width-invariant noise tile, wide enough that the mask-repeat seam clears any normal band.\n// WebKit draws a hairline at mask tile edges; a smaller tile lands that seam inside the band.\nconst NOISE_TILE_W = 1024;\nconst NOISE_TILE_H = 64;\nconst MASK_OFFSET_X = 96;\nconst MASK_OFFSET_Y = 16;\n\n/** A non-negative modulo (JS `%` keeps the sign of the dividend). */\nfunction mod(n: number, m: number): number {\n  return ((n % m) + m) % m;\n}\n\n/** Resolve the band's vertical offset and height (px) for the mark type. Every mark is one band primitive at a different position/height. */\nfunction resolveBand(\n  markType: ResolvedOptions[\"markType\"],\n  lineHeight: number,\n): { offsetY: number; height: number } {\n  const thin = Math.max(2, lineHeight * 0.12);\n  switch (markType) {\n    case \"underline\":\n      return { offsetY: lineHeight - thin, height: thin };\n    case \"overline\":\n      return { offsetY: 0, height: thin };\n    case \"strike-through\":\n      return { offsetY: (lineHeight - thin) / 2, height: thin };\n    default:\n      return { offsetY: 0, height: lineHeight };\n  }\n}\n\n/**\n * Build the full geometry for one visual line.\n *\n * @param seed - The stable seed every value derives from.\n * @param flowReversed - Pour the dry-out gradient from the right (backward live selection).\n * @param speedProfile - Live-only per-line swipe-speed read; absent leaves byte-identical geometry.\n */\nexport function buildMarkGeometry(\n  lineRect: LineRect,\n  options: ResolvedOptions,\n  seed: number,\n  flowReversed = false,\n  speedProfile?: LineSpeedProfile,\n): MarkGeometry {\n  const { edge, ink, tip, paper, speed } = options;\n\n  // How far each end runs past (or short of) the text edge, jittered per end and seeded by the width-independent line seed so growing a mark never shifts its start.\n  const endOver = (s: number): number =>\n    tip.overshoot + hashJitter(s) * tip.overshootJitter;\n  const leftExt = endOver(seed + SEED_LEFT_OVER);\n  const rightExt = endOver(seed + SEED_RIGHT_OVER);\n\n  // Per-line slant jitter drives both the clip-path and the slant/minFront fields, so painted shape and draw-on front agree.\n  const slantTip =\n    tip.angleJitter > 0\n      ? { ...tip, angle: tip.angle + hashJitter(seed + SEED_ANGLE) * tip.angleJitter }\n      : tip;\n\n  const band = resolveBand(options.markType, lineRect.height);\n  const boxX = lineRect.left - leftExt;\n  const boxY = lineRect.top - VERT_PAD + band.offsetY;\n  // Positive-width clamp so an aggressive negative overshoot can't invert the box.\n  const boxWidth = Math.max(1, lineRect.width + leftExt + rightExt);\n  const boxHeight = band.height + VERT_PAD * 2;\n  const box: Box = { x: boxX, y: boxY, width: boxWidth, height: boxHeight };\n\n  // Amplitude grows with paper absorbency (wetter, fuzzier edge); wavelength is the width-independent px frequency.\n  const amplitude = edge.waviness * (1 + paper.absorbency * 0.5);\n  const segmentLength = edge.frequency;\n\n  // Absolute-x grid so growing the extent appends fresh vertices; shifted to local box coords below.\n  const absStartX = box.x;\n  const absEndX = box.x + box.width;\n\n  const topAbs = buildEdge({\n    startX: absStartX,\n    endX: absEndX,\n    baseY: 0,\n    segmentLength,\n    amplitude,\n    roughness: edge.roughness,\n    seed: seed + SEED_TOP_EDGE,\n  });\n  const bottomAbs = buildEdge({\n    startX: absStartX,\n    endX: absEndX,\n    baseY: box.height,\n    segmentLength,\n    amplitude,\n    roughness: edge.roughness,\n    seed: seed + SEED_BOTTOM_EDGE,\n  });\n\n  // Grid index preserved so prefix-stability tests can compare per-index vertices.\n  const toLocal = (v: EdgeVertex): EdgeVertex => ({\n    x: v.x - box.x,\n    y: v.y,\n    gridIndex: v.gridIndex,\n  });\n  const topEdge: EdgeVertex[] = topAbs.map(toLocal);\n  const bottomEdge: EdgeVertex[] = bottomAbs.map(toLocal);\n\n  // Clip-path parameterized by an advancing front; the entrance grows the front so the band gains grid nodes rather than stretching.\n  const clipAtFront = (front: number): string =>\n    buildClipPath({\n      box,\n      tip: slantTip,\n      topEdge,\n      bottomEdge,\n      cap: edge.cap,\n      radius: edge.radius,\n      front,\n    });\n  const clipPath = clipAtFront(box.width);\n\n  // Per-line noise tile (never scaled). With a live profile a faster mean swipe lays a drier, streakier line; without one the three values reduce to the base expressions.\n  const sp = speedProfile;\n  const m = sp ? sp.meanNorm : 0;\n  const sens = speed.sensitivity;\n  const baseDryout = ink.dryout + ink.viscosity * 0.2;\n  const baseStreak = ink.streakiness;\n  const baseFeather = ink.feathering + paper.absorbency * 0.25;\n  const noiseTile: NoiseTile = buildNoiseTile({\n    width: NOISE_TILE_W,\n    height: NOISE_TILE_H,\n    seed,\n    streakiness: sp\n      ? clamp(baseStreak + speed.streakBoost * sens * m * Math.max(0, 1 - baseStreak), 0, 1)\n      : baseStreak,\n    feathering: sp ? Math.max(0, baseFeather * (1 - speed.featherReduce * sens * m)) : baseFeather,\n    dryout: sp\n      ? clamp(baseDryout + speed.dryoutBoost * sens * m * Math.max(0, 1 - baseDryout), 0, 1)\n      : baseDryout,\n  });\n  // Offsets capped to the headroom so the wrap stays past the band's right/bottom edge.\n  const maskOffset: MaskOffset = {\n    x: -mod(seed * MASK_X_MULT, MASK_OFFSET_X),\n    y: -mod(seed * MASK_Y_MULT, MASK_OFFSET_Y),\n  };\n\n  const pool = buildPoolGradient({\n    lengthPx: box.width,\n    startEndBuildup: ink.startEndBuildup,\n    color: options.color,\n    opacity: options.opacity,\n    angle: options.gradient?.angle ?? undefined,\n    flowFade: ink.flowFade,\n    flowReversed,\n    // Live speed path: per-x deposit across N stops + extra end pooling from deceleration. Omitted without a profile.\n    ...(sp\n      ? {\n          coreStopCount: speed.resolution,\n          depositAt: sp.depositAt,\n          decelBuildup: speed.poolBoost * sens * sp.decel,\n        }\n      : {}),\n  });\n\n  return {\n    box,\n    seed,\n    clipPath,\n    clipAtFront,\n    slant: chiselSlant(slantTip, box.width, box.height),\n    minFront: Math.min(minVisibleFront(slantTip, edge.cap, box.width, box.height, edge.radius), box.width),\n    topEdge,\n    bottomEdge,\n    noiseTile,\n    maskOffset,\n    pool,\n  };\n}\n","import type { SnapMode } from \"../types.js\";\n\n/**\n * Snap a range's start/end to the nearest text boundary. Read-only DOM access: returns a\n * cloned, adjusted `Range`, never mutating the document or input, and import-safe off-DOM.\n *\n *  - `none`  - range unchanged (same reference).\n *  - `word`  - trims whitespace, then expands each end to the enclosing word boundary.\n *  - `glyph` - trims surrounding whitespace only.\n *  - `line`  - trims like `glyph`; per-visual-line clamping happens downstream.\n */\n\nconst WHITESPACE = /\\s/;\nconst WORD_CHAR = /[\\p{L}\\p{N}_-]/u;\n\nfunction isText(node: Node | null): node is Text {\n  return node != null && node.nodeType === 3 /* TEXT_NODE */;\n}\n\n/** Snap `range` to `mode`. Read-only; returns a (possibly cloned) range. */\nexport function snapRangeToBounds(range: Range, mode: SnapMode): Range {\n  if (mode === \"none\") return range;\n\n  // Non-DOM / detached environment: hand the range back rather than throwing.\n  if (typeof range.cloneRange !== \"function\") return range;\n\n  const out = range.cloneRange();\n\n  if (isText(out.startContainer)) {\n    const text = out.startContainer.data;\n    let i = out.startOffset;\n    while (i < text.length && WHITESPACE.test(text.charAt(i))) i++;\n    if (i !== out.startOffset) out.setStart(out.startContainer, i);\n  }\n\n  if (isText(out.endContainer)) {\n    const text = out.endContainer.data;\n    let j = out.endOffset;\n    while (j > 0 && WHITESPACE.test(text.charAt(j - 1))) j--;\n    if (j !== out.endOffset) out.setEnd(out.endContainer, j);\n  }\n\n  // `word` grows each end out to the enclosing word boundary.\n  if (mode === \"word\") {\n    if (isText(out.startContainer)) {\n      const text = out.startContainer.data;\n      let i = out.startOffset;\n      while (i > 0 && WORD_CHAR.test(text.charAt(i - 1))) i--;\n      if (i !== out.startOffset) out.setStart(out.startContainer, i);\n    }\n    if (isText(out.endContainer)) {\n      const text = out.endContainer.data;\n      let j = out.endOffset;\n      while (j < text.length && WORD_CHAR.test(text.charAt(j))) j++;\n      if (j !== out.endOffset) out.setEnd(out.endContainer, j);\n    }\n  }\n\n  // A trim crossing both boundaries (e.g. an all-whitespace range) can invert start/end; collapse to a valid paint-nothing range.\n  if (out.collapsed && !range.collapsed) {\n    out.collapse(true);\n  }\n\n  return out;\n}\n","/**\n * Internal SSR-environment predicates and `NodeFilter` sentinels.\n *\n * Each predicate is a distinct capability question, kept separate because each call\n * site reads a different set of globals. Touches no DOM global at module load (SSR-safe).\n */\n\n/** `document` + `Range` present - guards the targeting collectors that build `Range`s. */\nexport function hasDomWithRange(): boolean {\n  return typeof document !== \"undefined\" && typeof Range !== \"undefined\";\n}\n\n/** `document` + `window` present - guards the render entry points. */\nexport function hasDom(): boolean {\n  return typeof document !== \"undefined\" && typeof window !== \"undefined\";\n}\n\n/** `window` present - guards the observer layer. */\nexport function hasWindow(): boolean {\n  return typeof window !== \"undefined\";\n}\n\n/** `window.matchMedia` present - guards tier selection's preference reads. */\nexport function hasMediaQueries(): boolean {\n  return (\n    typeof document !== \"undefined\" &&\n    typeof window !== \"undefined\" &&\n    typeof window.matchMedia === \"function\"\n  );\n}\n\n// NodeFilter sentinels as literals: the global NodeFilter doesn't exist outside a DOM.\nexport const SHOW_TEXT = 0x4;\nexport const FILTER_ACCEPT = 1;\nexport const FILTER_REJECT = 2;\n\n/** Tag names whose text content never renders as visible page content. */\nconst NON_RENDERED_TAGS = new Set([\n  \"SCRIPT\",\n  \"STYLE\",\n  \"TEMPLATE\",\n  \"NOSCRIPT\",\n  \"HEAD\",\n  \"TITLE\",\n]);\n\n/** Whether `node` sits inside a non-rendered subtree (walks ancestors). */\nexport function isInNonRenderedSubtree(node: Node): boolean {\n  let el = node.parentElement;\n  while (el) {\n    if (NON_RENDERED_TAGS.has(el.tagName)) return true;\n    el = el.parentElement;\n  }\n  return false;\n}\n","/**\n * Text-query targeting: a `Range` per match of a string/`RegExp` under a root, including matches that\n * span inline element boundaries (e.g. `foo<em>bar</em>baz`). The walk concatenates text nodes into\n * one flat string, recording each character's source node + offset, then maps matches back onto the nodes.\n */\n\nimport {\n  FILTER_ACCEPT,\n  FILTER_REJECT,\n  hasDomWithRange,\n  isInNonRenderedSubtree,\n  SHOW_TEXT,\n} from \"../internal/dom.js\";\n\n/** A single character's provenance: the owning text node and its in-node index. */\ninterface CharSlot {\n  node: Text;\n  offset: number;\n}\n\n/** Flat string of all text under `root`, plus a parallel index mapping each character to its source node + in-node offset. */\nfunction collectText(root: Node): { text: string; slots: CharSlot[] } {\n  const slots: CharSlot[] = [];\n  let text = \"\";\n\n  // Skip non-rendered subtrees so a query never matches CSS/JS source or straddles into adjacent visible text.\n  const walker = document.createTreeWalker(root, SHOW_TEXT, {\n    acceptNode: (n) => (isInNonRenderedSubtree(n) ? FILTER_REJECT : FILTER_ACCEPT),\n  });\n  let node = walker.nextNode() as Text | null;\n  while (node) {\n    const value = node.data;\n    for (let i = 0; i < value.length; i++) {\n      slots.push({ node, offset: i });\n    }\n    text += value;\n    node = walker.nextNode() as Text | null;\n  }\n\n  return { text, slots };\n}\n\n/** Range covering the half-open span `[start, end)` of the flat text. */\nfunction rangeForSpan(slots: CharSlot[], start: number, end: number): Range {\n  const range = document.createRange();\n  const startSlot = slots[start];\n  const endSlot = slots[end - 1];\n  range.setStart(startSlot.node, startSlot.offset);\n  range.setEnd(endSlot.node, endSlot.offset + 1);\n  return range;\n}\n\n/**\n * Find every match of `query` within `root`, one `Range` per match.\n * - `string`: literal, case-sensitive, non-overlapping.\n * - `RegExp`: scanned globally on a copy; case follows the `i` flag; zero-width matches skipped.\n * Never throws.\n */\nexport function findTextRanges(\n  root: Element | Document,\n  query: string | RegExp,\n): Range[] {\n  if (!hasDomWithRange() || !root) return [];\n\n  const { text, slots } = collectText(root);\n  if (text.length === 0) return [];\n\n  const ranges: Range[] = [];\n\n  if (typeof query === \"string\") {\n    if (query.length === 0) return [];\n    let from = 0;\n    for (;;) {\n      const index = text.indexOf(query, from);\n      if (index === -1) break;\n      ranges.push(rangeForSpan(slots, index, index + query.length));\n      from = index + query.length; // advance past this match\n    }\n    return ranges;\n  }\n\n  // Strip the sticky `y` flag first: under `y`, `exec` only matches at `lastIndex`, so adding `g` can't\n  // override it and the scan would stop at the first gap, silently under-matching.\n  const base = query.flags.replace(\"y\", \"\");\n  const flags = base.includes(\"g\") ? base : base + \"g\";\n  const re = new RegExp(query.source, flags);\n  let match: RegExpExecArray | null;\n  while ((match = re.exec(text)) !== null) {\n    const matched = match[0];\n    if (matched.length === 0) {\n      // Zero-width match: nudge lastIndex to avoid an infinite loop.\n      re.lastIndex += 1;\n      continue;\n    }\n    ranges.push(rangeForSpan(slots, match.index, match.index + matched.length));\n  }\n\n  return ranges;\n}\n","/** Whole-page targeting with include/exclude selectors. Exclusion always wins: a node is dropped the moment any ancestor matches an exclude selector. */\n\nimport type { PageTarget } from \"../types.js\";\nimport {\n  FILTER_ACCEPT,\n  FILTER_REJECT,\n  hasDomWithRange,\n  isInNonRenderedSubtree,\n  SHOW_TEXT,\n} from \"../internal/dom.js\";\n\nconst EXCLUDE_ATTR = \"data-highlight-exclude\";\n\nfunction elementOf(node: Node): Element | null {\n  return node.nodeType === 1 ? (node as Element) : node.parentElement;\n}\n\n/** True if `node` is inside any subtree matching an exclude selector or marked `data-highlight-exclude`. */\nexport function isExcluded(node: Node, excludeSelectors: string[]): boolean {\n  const el = elementOf(node);\n  if (!el) return false;\n\n  if (el.closest(`[${EXCLUDE_ATTR}]`)) return true;\n\n  for (const selector of excludeSelectors) {\n    if (!selector) continue;\n    try {\n      if (el.closest(selector)) return true;\n    } catch {\n      // An invalid selector excludes nothing rather than throwing.\n    }\n  }\n  return false;\n}\n\n/**\n * Reshape live-selection ranges so every `[data-highlight-exclude]` subtree is carved out, while the\n * runs between excluded elements stay whole (so their geometry is unchanged). The selection marker\n * paints by range rectangles, which span `user-select: none` text too, so a select-all would\n * otherwise band over opted-out regions. This only reshapes what gets painted; the document's own\n * selection is left alone, so single-range browsers keep working.\n */\nexport function excludeMarkedSubtrees(ranges: Range[]): Range[] {\n  if (!hasDomWithRange()) return ranges;\n  const out: Range[] = [];\n  for (const range of ranges) {\n    if (range.collapsed) continue;\n    const root = elementOf(range.commonAncestorContainer);\n    // The whole range sits inside an opted-out subtree: paint none of it.\n    if (root?.closest(`[${EXCLUDE_ATTR}]`)) continue;\n    // The opted-out elements this range crosses, outermost-only, in document order.\n    const all = root ? Array.from(root.querySelectorAll(`[${EXCLUDE_ATTR}]`)) : [];\n    const hits = all.filter(\n      (el) => range.intersectsNode(el) && !el.parentElement?.closest(`[${EXCLUDE_ATTR}]`),\n    );\n    if (hits.length === 0) {\n      out.push(range); // nothing opted out here: keep the range whole\n      continue;\n    }\n    // Keep each gap (before, between, after the excluded elements) as one contiguous range.\n    const cursor = range.cloneRange();\n    for (const el of hits) {\n      const gap = cursor.cloneRange();\n      gap.setEndBefore(el);\n      if (!gap.collapsed) out.push(gap);\n      cursor.setStartAfter(el);\n    }\n    if (!cursor.collapsed) out.push(cursor);\n  }\n  return out;\n}\n\n/** With no include selectors the whole root is in scope (returns `true` for every node). */\nfunction isIncluded(node: Node, includeSelectors: string[]): boolean {\n  if (includeSelectors.length === 0) return true;\n  const el = elementOf(node);\n  if (!el) return false;\n  for (const selector of includeSelectors) {\n    if (!selector) continue;\n    try {\n      if (el.closest(selector)) return true;\n    } catch {\n      // Ignore invalid include selectors.\n    }\n  }\n  return false;\n}\n\n/** Collect every textual `Range` under `target.root` (default `document.body`), honouring include/exclude. Each accepted text node becomes one `Range` over its non-whitespace span. Never throws. */\nexport function collectPageRanges(target: PageTarget): Range[] {\n  if (!hasDomWithRange()) return [];\n\n  const root = target.root ?? document.body;\n  if (!root) return [];\n\n  const include = target.include ?? [];\n  const exclude = target.exclude ?? [];\n\n  const walker = document.createTreeWalker(root, SHOW_TEXT, {\n    acceptNode(node) {\n      const text = node as Text;\n      if (text.data.trim().length === 0) return FILTER_REJECT;\n      // Never paint text that doesn't render (<script>/<style>/<head>/…).\n      if (isInNonRenderedSubtree(text)) return FILTER_REJECT;\n      if (isExcluded(text, exclude)) return FILTER_REJECT;\n      if (!isIncluded(text, include)) return FILTER_REJECT;\n      return FILTER_ACCEPT;\n    },\n  });\n\n  const ranges: Range[] = [];\n  let node = walker.nextNode() as Text | null;\n  while (node) {\n    const data = node.data;\n    // Trim to the first/last non-whitespace char so the mark hugs visible glyphs.\n    const start = data.length - data.replace(/^\\s+/, \"\").length;\n    const end = data.replace(/\\s+$/, \"\").length;\n    if (end > start) {\n      const range = document.createRange();\n      range.setStart(node, start);\n      range.setEnd(node, end);\n      ranges.push(range);\n    }\n    node = walker.nextNode() as Text | null;\n  }\n\n  return ranges;\n}\n","/** The normalization front door: every {@link Target} variant collapses to a flat array of DOM `Range`s. Never throws; yields `[]` on no match or no DOM. */\n\nimport type { Target, TextTarget } from \"../types.js\";\nimport { findTextRanges } from \"./text-search.js\";\nimport { collectPageRanges } from \"./include-exclude.js\";\nimport { hasDomWithRange } from \"../internal/dom.js\";\n\n/** Avoids `instanceof` across realms/SSR. */\nfunction isRange(value: unknown): value is Range {\n  return typeof Range !== \"undefined\" && value instanceof Range;\n}\n\nfunction isSelection(value: unknown): value is Selection {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    typeof (value as Selection).getRangeAt === \"function\" &&\n    typeof (value as Selection).rangeCount === \"number\"\n  );\n}\n\nfunction isElement(value: unknown): value is Element {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    (value as Node).nodeType === 1 &&\n    typeof (value as Element).querySelectorAll === \"function\"\n  );\n}\n\nfunction isTextTarget(value: unknown): value is TextTarget {\n  if (typeof value !== \"object\" || value === null) return false;\n  const text = (value as TextTarget).text;\n  return typeof text === \"string\" || text instanceof RegExp;\n}\n\n/** Whitespace is left intact here; boundary trimming/snapping is the snap stage's job. */\nfunction rangeForElement(el: Element): Range {\n  const range = document.createRange();\n  range.selectNodeContents(el);\n  return range;\n}\n\n/**\n * Normalize any {@link Target} to a flat array of DOM `Range`s. Dispatch order is significant:\n * specific shapes (`Range`, `Selection`, `Element`, {@link TextTarget}) are matched before the\n * catch-all page-target object, and `string` is a CSS selector. Never throws.\n */\nexport function toRanges(target: Target): Range[] {\n  if (!hasDomWithRange() || target == null) return [];\n\n  if (isRange(target)) {\n    return target.collapsed ? [] : [target];\n  }\n\n  if (isSelection(target)) {\n    const out: Range[] = [];\n    for (let i = 0; i < target.rangeCount; i++) {\n      const range = target.getRangeAt(i);\n      if (!range.collapsed) out.push(range);\n    }\n    return out;\n  }\n\n  if (isElement(target)) {\n    return [rangeForElement(target)];\n  }\n\n  if (typeof target === \"string\") {\n    if (target.length === 0) return [];\n    let elements: NodeListOf<Element>;\n    try {\n      elements = document.querySelectorAll(target);\n    } catch {\n      // Invalid selector matches nothing rather than throwing.\n      return [];\n    }\n    const out: Range[] = [];\n    elements.forEach((el) => out.push(rangeForElement(el)));\n    return out;\n  }\n\n  if (isTextTarget(target)) {\n    const root = target.root ?? document.body;\n    if (!root) return [];\n    return findTextRanges(root, target.text);\n  }\n\n  // Catch-all page-target object form, reached only after every more-specific shape returned.\n  return collectPageRanges(target);\n}\n","/**\n * Range to per-visual-line rectangles: the read-only layout stage. Collect client rects per text node,\n * coalesce into one rect per visual line, and stamp each line with a layout-stable seed for the\n * geometry layer's jitter. Per-text-node collection avoids the full-width bbox rects `getClientRects()`\n * emits at block boundaries; the merge folds same-line fragments but won't merge across large\n * horizontal gaps (so `justify-between` rows don't fuse into one ghost band).\n */\n\nimport type { Anchor, LineRect } from \"../types.js\";\nimport {\n  FILTER_ACCEPT,\n  FILTER_REJECT,\n  SHOW_TEXT,\n  hasDomWithRange,\n  isInNonRenderedSubtree,\n} from \"../internal/dom.js\";\n\nfunction rectArray(list: DOMRectList): DOMRect[] {\n  const out: DOMRect[] = [];\n  for (let i = 0; i < list.length; i++) out.push(list[i]);\n  return out;\n}\n\n/** Reject text whose parent is `visibility: hidden` (layout spacers still emit client rects). */\nfunction isHiddenText(node: Node): boolean {\n  if (typeof getComputedStyle === \"undefined\") return false;\n  const parent = node.parentElement;\n  if (!parent) return false;\n  try {\n    return getComputedStyle(parent).visibility === \"hidden\";\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Client rects for a range, collected per text node. `Range.getClientRects()` across block boundaries\n * emits spurious full-width bbox rects, so a multi-text-node range uses a sub-range clamped to each\n * text node (tight to glyphs); a single-text-node range keeps its own rects.\n *\n * When `scope` is set, only text nodes under that element are walked — the reading-surface boundary\n * for live selection, so page chrome outside `article`/`main` is never measured.\n */\nfunction collectRangeRects(range: Range, scope?: Element): DOMRect[] {\n  const common = scope ?? range.commonAncestorContainer;\n  // A text-node common ancestor (or no TreeWalker) is a single text run.\n  if (!scope && common.nodeType === 3) {\n    return rectArray(range.getClientRects());\n  }\n  if (typeof document.createTreeWalker !== \"function\") {\n    return rectArray(range.getClientRects());\n  }\n\n  const walker = document.createTreeWalker(common, SHOW_TEXT, {\n    acceptNode(node: Node) {\n      if (isInNonRenderedSubtree(node)) return FILTER_REJECT;\n      if (isHiddenText(node)) return FILTER_REJECT;\n      // intersectsNode is near-universal; fall back to \"accept\" if a host lacks it.\n      const hit =\n        typeof range.intersectsNode === \"function\"\n          ? range.intersectsNode(node)\n          : true;\n      return hit ? FILTER_ACCEPT : FILTER_REJECT;\n    },\n  } as NodeFilter);\n\n  const texts: Text[] = [];\n  for (let n = walker.nextNode(); n; n = walker.nextNode()) texts.push(n as Text);\n\n  // 0 or 1 text node: the range's own rects are already artifact-free.\n  if (texts.length <= 1) return rectArray(range.getClientRects());\n\n  // 2+ text nodes: one sub-range per text node, clamped to the parent range's endpoints.\n  const out: DOMRect[] = [];\n  for (const text of texts) {\n    const start = text === range.startContainer ? range.startOffset : 0;\n    const end = text === range.endContainer ? range.endOffset : text.length;\n    if (end <= start) continue;\n    const sub = document.createRange();\n    sub.setStart(text, start);\n    sub.setEnd(text, end);\n    for (const r of rectArray(sub.getClientRects())) out.push(r);\n  }\n  return out;\n}\n\n/** Drop rects taller than this multiple of the median line height (bbox artifacts). */\nconst BBOX_REJECT_RATIO = 3.0;\n/** Two rects share a line when their vertical centres differ by < this × median height. */\nconst MERGE_TOLERANCE = 0.5;\n/** Don't merge same-line rects separated by a horizontal gap > this × median height. */\nconst MERGE_MAX_GAP_RATIO = 1.5;\n/** Horizontal slop (px) around the anchor column when filtering stray rects. */\nconst COLUMN_SLOP = 24;\n/** Seed quantization: anchor-relative top × this, rounded (≈0.14 px buckets). */\nconst SEED_SCALE = 7;\n\n/** A mutable line accumulator in absolute viewport px. */\ninterface LineBox {\n  top: number;\n  bottom: number;\n  left: number;\n  right: number;\n}\n\n/** `DOMRect`-shaped object from edges, without relying on the constructor (jsdom). */\nfunction toDomRect(box: LineBox): DOMRect {\n  const { top, bottom, left, right } = box;\n  const width = right - left;\n  const height = bottom - top;\n  return {\n    x: left,\n    y: top,\n    width,\n    height,\n    top,\n    right,\n    bottom,\n    left,\n    toJSON() {\n      return { x: left, y: top, width, height, top, right, bottom, left };\n    },\n  } as DOMRect;\n}\n\nfunction median(values: number[]): number {\n  if (values.length === 0) return 0;\n  const sorted = [...values].sort((a, b) => a - b);\n  return sorted[Math.floor(sorted.length / 2)] ?? 0;\n}\n\n/** Coalesce raw `getClientRects()` output into one rect per visual line, dropping bbox artifacts and merging rects sharing a vertical centre. Pure; input never mutated. */\nexport function mergeRectsByLine(rects: DOMRect[]): DOMRect[] {\n  if (rects.length === 0) return [];\n\n  const heights = rects.map((r) => r.height);\n  const med = median(heights);\n  const tol = med * MERGE_TOLERANCE;\n  const maxH = med * BBOX_REJECT_RATIO;\n  const maxGap = med * MERGE_MAX_GAP_RATIO;\n\n  const lines: LineBox[] = [];\n  for (const r of rects) {\n    // Reject paragraph-spanning bbox artifacts (only when there's a median to compare against).\n    if (med > 0 && r.height > maxH) continue;\n\n    const cy = (r.top + r.bottom) / 2;\n    let merged = false;\n    for (const line of lines) {\n      if (Math.abs(cy - (line.top + line.bottom) / 2) >= tol) continue;\n      // Only merge when horizontally adjacent; wide gaps mean separate columns.\n      const gap = Math.max(r.left - line.right, line.left - r.right);\n      if (gap > maxGap) continue;\n      if (r.top < line.top) line.top = r.top;\n      if (r.bottom > line.bottom) line.bottom = r.bottom;\n      if (r.left < line.left) line.left = r.left;\n      if (r.right > line.right) line.right = r.right;\n      merged = true;\n      break;\n    }\n    if (!merged) {\n      lines.push({ top: r.top, bottom: r.bottom, left: r.left, right: r.right });\n    }\n  }\n\n  // Top-to-bottom order so isFirst/isLast and stagger read correctly.\n  lines.sort((a, b) => a.top - b.top || a.left - b.left);\n  return lines.map(toDomRect);\n}\n\n/** The top-left-most point of the targeted content's bounding box; the horizontal column-filter origin. `{0, 0}` with nothing to measure. */\nexport function computeAnchor(ranges: Range[]): Anchor {\n  let top = Infinity;\n  let left = Infinity;\n\n  if (hasDomWithRange()) {\n    for (const range of ranges) {\n      // Same per-text-node collection the line stage uses, so both stages agree on the content edge.\n      for (const r of collectRangeRects(range)) {\n        // Must use the same sub-pixel test `rangesToLineRects` uses, else the anchor latches onto a\n        // caret rect the line stage discards and shifts the column filter off the painted lines.\n        if (r.width < 1 || r.height < 1) continue;\n        if (r.top < top) top = r.top;\n        if (r.left < left) left = r.left;\n      }\n    }\n  }\n\n  if (!Number.isFinite(top)) top = 0;\n  if (!Number.isFinite(left)) left = 0;\n  return { top, left };\n}\n\nexport interface RangesToLineRectsOptions {\n  /** Only measure text under this element (live-selection reading surface). */\n  scope?: Element;\n  /** Anchor element bounds for column filtering; when set, both edges come from the host rect. */\n  columnBounds?: { left: number; right: number };\n}\n\n/** Collect per-text-node rects, merge into visual lines, drop rects outside the anchor column, and emit one {@link LineRect} per line with its stable seed. Read-only. */\nexport function rangesToLineRects(\n  ranges: Range[],\n  anchor: Anchor,\n  originTop = 0,\n  options?: RangesToLineRectsOptions,\n): LineRect[] {\n  if (!hasDomWithRange() || ranges.length === 0) return [];\n\n  const raw: DOMRect[] = [];\n  for (const range of ranges) {\n    for (const r of collectRangeRects(range, options?.scope)) {\n      if (r.width < 1 || r.height < 1) continue;\n      raw.push(r);\n    }\n  }\n  if (raw.length === 0) return [];\n\n  // Anchor-column filter: drop rects horizontally outside the content column. Live selection passes\n  // the overlay host's viewport bounds; static marks use selection min-left and widest rect right.\n  let maxRight = -Infinity;\n  for (const r of raw) if (r.right > maxRight) maxRight = r.right;\n  const bounds = options?.columnBounds;\n  const minLeft = (bounds?.left ?? anchor.left) - COLUMN_SLOP;\n  const maxRightBound = (bounds?.right ?? maxRight) + COLUMN_SLOP;\n  const columnRects = raw.filter(\n    (r) => r.right >= minLeft && r.left <= maxRightBound,\n  );\n\n  const lines = mergeRectsByLine(columnRects.length > 0 ? columnRects : raw);\n  if (lines.length === 0) return [];\n\n  return lines.map((rect, index) => ({\n    left: rect.left,\n    top: rect.top,\n    width: rect.width,\n    height: rect.height,\n    // Seed off `originTop` (container's document origin), not the selection's min-top: min-top moves\n    // when an upward drag adds a line above, re-rolling every seed and re-randomizing painted shapes.\n    seed: Math.round((rect.top - originTop) * SEED_SCALE),\n    isFirst: index === 0,\n    isLast: index === lines.length - 1,\n  }));\n}\n","/**\n * Live selection swipe-velocity tracking for speed-aware ink deposit.\n *\n * A spatial velocity field: focus-caret `{x, y, v}` samples in the same container-local px space the\n * line geometry uses. A live drag never reflows between sampling and painting, so a line looks up the\n * swipe speed by spatial position (no brittle per-glyph character-offset mapping). Used only by\n * `highlightSelection` during an active fine-pointer drag. Output is a {@link LineSpeedProfile} per\n * line, or `undefined` when a line has no samples.\n */\n\nimport { clamp } from \"../internal/math.js\";\nimport type { LineSpeedProfile, ResolvedSpeedDynamics } from \"../types.js\";\n\n/** One focus-caret reading in container-local px, with its smoothed speed (px/ms). */\ninterface Sample {\n  x: number;\n  y: number;\n  v: number;\n}\n\n/** Hard cap on retained samples; on overflow we drop the oldest half. */\nconst MAX_SAMPLES = 500;\n/** Two samples within this px in both axes are treated as co-located (last-pass dedup). */\nconst DEDUP_PX = 2;\n/** Only the most-recent few samples are scanned for a co-located duplicate. */\nconst DEDUP_LOOKBACK = 8;\n/** Floor on the inter-sample interval so a coalesced/instant event can't divide by ~0. */\nconst DT_FLOOR_MS = 1;\n\n/** A node+offset caret position in container-local px, or `null` if unmeasurable. */\nfunction caretLocal(\n  node: Node,\n  offset: number,\n  originLeft: number,\n  originTop: number,\n): { x: number; y: number } | null {\n  try {\n    const range = document.createRange();\n    range.setStart(node, offset);\n    range.collapse(true);\n    let rect: DOMRect | undefined = range.getClientRects()[0] ?? range.getBoundingClientRect();\n    // A collapsed caret can measure 0x0; fall back to the single char ending at the offset, whose right edge sits at the caret.\n    if (!rect || (rect.width === 0 && rect.height === 0)) {\n      const len = node.nodeType === 3 ? (node as Text).length : node.childNodes.length;\n      const start = Math.max(0, Math.min(offset, len) - 1);\n      const end = Math.min(len, start + 1);\n      if (end > start) {\n        range.setStart(node, start);\n        range.setEnd(node, end);\n        rect = range.getClientRects()[0] ?? range.getBoundingClientRect();\n      }\n    }\n    // Still empty: unmeasurable, skip rather than plant a bogus (0,0) sample that corrupts the velocity.\n    if (!rect || (rect.width === 0 && rect.height === 0)) return null;\n    // Right edge tracks the focus side; vertical centre lands inside the y-band.\n    return { x: rect.right - originLeft, y: (rect.top + rect.bottom) / 2 - originTop };\n  } catch {\n    // Detached node, cross-origin, or no Range support: no sample.\n    return null;\n  }\n}\n\n/** Accumulates the drag's spatial velocity field and serves per-line speed profiles. {@link reset} clears it between gestures. */\nexport class SelectionVelocityTracker {\n  private samples: Sample[] = [];\n  private prevX = 0;\n  private prevY = 0;\n  private prevT = 0;\n  private hasPrev = false;\n  private ema = 0;\n\n  reset(): void {\n    this.samples = [];\n    this.hasPrev = false;\n    this.ema = 0;\n  }\n\n  hasData(): boolean {\n    return this.samples.length > 0;\n  }\n\n  /** Record one focus-caret reading. `now` is a monotonic ms timestamp; `smoothing` is the EMA weight on the newest sample. No-op if unmeasurable. */\n  recordSample(\n    selection: Selection,\n    originLeft: number,\n    originTop: number,\n    now: number,\n    smoothing: number,\n  ): void {\n    const { focusNode, focusOffset } = selection;\n    if (!focusNode) return;\n\n    const pos = caretLocal(focusNode, focusOffset, originLeft, originTop);\n    if (!pos) return;\n\n    if (!this.hasPrev) {\n      // First reading seeds position/time only: a fake 0-speed sample would read \"wet\" at the band start and pin peak deposit, defeating a fast swipe's dimming.\n      this.prevX = pos.x;\n      this.prevY = pos.y;\n      this.prevT = now;\n      this.hasPrev = true;\n      return;\n    }\n\n    const dt = Math.max(DT_FLOOR_MS, now - this.prevT);\n    const dist = Math.hypot(pos.x - this.prevX, pos.y - this.prevY);\n    const instant = dist / dt;\n    const a = clamp(smoothing, 0, 1);\n    this.ema = this.hasData() ? (1 - a) * this.ema + a * instant : instant;\n    this.prevX = pos.x;\n    this.prevY = pos.y;\n    this.prevT = now;\n    this.push({ x: pos.x, y: pos.y, v: this.ema });\n  }\n\n  /** Append a sample, collapsing a co-located recent one. */\n  private push(sample: Sample): void {\n    const from = Math.max(0, this.samples.length - DEDUP_LOOKBACK);\n    for (let i = this.samples.length - 1; i >= from; i--) {\n      const o = this.samples[i];\n      if (Math.abs(o.x - sample.x) <= DEDUP_PX && Math.abs(o.y - sample.y) <= DEDUP_PX) {\n        this.samples[i] = sample;\n        return;\n      }\n    }\n    this.samples.push(sample);\n    if (this.samples.length > MAX_SAMPLES) {\n      this.samples = this.samples.slice(this.samples.length - Math.floor(MAX_SAMPLES / 2));\n    }\n  }\n\n  /** Build the {@link LineSpeedProfile} for a line box (container-local px), or `undefined` when no sample fell on this line. */\n  profileForLine(\n    line: { top: number; height: number; left: number; width: number },\n    sd: ResolvedSpeedDynamics,\n  ): LineSpeedProfile | undefined {\n    const top = line.top;\n    const bottom = line.top + line.height;\n    const band: Sample[] = [];\n    for (const s of this.samples) {\n      if (s.y >= top && s.y < bottom) band.push(s);\n    }\n    if (band.length === 0) return undefined;\n\n    // Deceleration uses temporal (insertion) order so it stays correct for backward drags; must be read before the x-sort below.\n    const vTemporalStart = band[0].v;\n    const vTemporalEnd = band[band.length - 1].v;\n\n    band.sort((p, q) => p.x - q.x);\n\n    const left = line.left;\n    const width = Math.max(1, line.width);\n    const denom = Math.max(1e-3, sd.fastSpeed - sd.slowSpeed);\n    const norm = (v: number): number => clamp((v - sd.slowSpeed) / denom, 0, 1);\n    // 1 (wet) at/below slowSpeed to minDeposit (dry) at/above fastSpeed, scaled by sensitivity (0 = no effect).\n    const deposit = (v: number): number => 1 - sd.sensitivity * norm(v) * (1 - sd.minDeposit);\n\n    // `band` is sorted by x; binary-search the bracketing pair to keep this O(log n) on the repaint path.\n    const vAtX = (absX: number): number => {\n      const first = band[0];\n      const last = band[band.length - 1];\n      if (absX <= first.x) return first.v;\n      if (absX >= last.x) return last.v;\n      let lo = 0;\n      let hi = band.length - 1;\n      while (hi - lo > 1) {\n        const mid = (lo + hi) >> 1;\n        if (band[mid].x <= absX) lo = mid;\n        else hi = mid;\n      }\n      const a = band[lo];\n      const b = band[hi];\n      const t = (absX - a.x) / Math.max(1e-6, b.x - a.x);\n      return a.v + t * (b.v - a.v);\n    };\n\n    let sum = 0;\n    for (const s of band) sum += s.v;\n    const meanNorm = norm(sum / band.length);\n\n    const decel = clamp((vTemporalStart - vTemporalEnd) / Math.max(1e-3, vTemporalStart), 0, 1);\n\n    return {\n      depositAt: (f: number): number => deposit(vAtX(left + clamp(f, 0, 1) * width)),\n      meanNorm,\n      decel,\n    };\n  }\n}\n","import { hasWindow } from \"../internal/dom.js\";\n\n/**\n * The element live selection marks should attach to: the nearest positioned ancestor of the\n * selection, or the reading surface (`article`, then `main`) when the walk reaches `body` (Cmd+A).\n * Overlays are children of this node with anchor-relative coordinates, so they scroll natively and\n * stay aligned when the viewport reflows — mounting on `document.body` drifts from centered columns.\n */\nexport function findSelectionAnchor(node: Node): HTMLElement {\n  if (!hasWindow() || typeof getComputedStyle === \"undefined\") {\n    return (document.body ?? document.documentElement) as HTMLElement;\n  }\n  let el: Element | null = node instanceof Element ? node : node.parentElement;\n  while (el && el !== document.body && el !== document.documentElement) {\n    const position = getComputedStyle(el).position;\n    if (position && position !== \"static\") return el as HTMLElement;\n    el = el.parentElement;\n  }\n  const contentRoot =\n    document.querySelector<HTMLElement>(\"article\") ??\n    document.querySelector<HTMLElement>(\"main\");\n  return contentRoot ?? (document.body as HTMLElement);\n}\n","/**\n * Reflow and dynamic-DOM observation. `createReflowObserver` funnels every event that can move a mark\n * (resize, web-font load) into a single rAF-batched callback. `createMutationWatcher` is the scoped,\n * debounced `MutationObserver` for page/declarative modes. Both return a leak-free, idempotent `Disconnect`.\n */\n\nimport type {\n  Disconnect,\n  MutationCallback,\n  ReflowCallback,\n} from \"../types.js\";\nimport { hasWindow } from \"../internal/dom.js\";\n\nconst MUTATION_DEBOUNCE_MS = 50;\n\n/** Nearest ancestor whose `position` is not `static` (what overlays position against). `null` if none before the root or off-DOM. */\nfunction nearestPositionedContainer(el: Element): Element | null {\n  if (!hasWindow() || typeof getComputedStyle === \"undefined\") return null;\n  let current: Element | null = el.parentElement;\n  while (current && current !== document.documentElement) {\n    let position: string;\n    try {\n      position = getComputedStyle(current).position;\n    } catch {\n      position = \"static\";\n    }\n    if (position && position !== \"static\") return current;\n    current = current.parentElement;\n  }\n  return null;\n}\n\n/** Wire reflow observation for `targets` (and their positioned containers), window resize, and web-font load into one rAF-batched `callback`. Leak-free `Disconnect`; inert off-DOM. */\nexport function createReflowObserver(\n  targets: Element[],\n  callback: ReflowCallback,\n): Disconnect {\n  if (!hasWindow()) return () => {};\n\n  let disposed = false;\n  let rafId: number | undefined;\n\n  const schedule = () => {\n    if (disposed || rafId !== undefined) return;\n    rafId = requestAnimationFrame(() => {\n      rafId = undefined;\n      if (!disposed) callback();\n    });\n  };\n\n  // Observe each target's positioned container too: a container resize moves overlays without resizing the target. De-duped.\n  let resizeObserver: ResizeObserver | undefined;\n  if (typeof ResizeObserver !== \"undefined\") {\n    resizeObserver = new ResizeObserver(schedule);\n    const observed = new Set<Element>();\n    for (const target of targets) {\n      if (!observed.has(target)) {\n        observed.add(target);\n        resizeObserver.observe(target);\n      }\n      const container = nearestPositionedContainer(target);\n      if (container && !observed.has(container)) {\n        observed.add(container);\n        resizeObserver.observe(container);\n      }\n    }\n  }\n\n  window.addEventListener(\"resize\", schedule);\n\n  // visualViewport.resize (mobile URL bar, pinch-zoom) shifts layout without a window resize.\n  const vv = window.visualViewport;\n  if (vv) vv.addEventListener(\"resize\", schedule);\n\n  // Late web-font load shifts text metrics; reflow once fonts are ready.\n  const fonts = (document as Document & { fonts?: FontFaceSet }).fonts;\n  if (fonts && typeof fonts.ready?.then === \"function\") {\n    fonts.ready.then(() => {\n      if (!disposed) schedule();\n    });\n  }\n\n  return () => {\n    if (disposed) return;\n    disposed = true;\n    resizeObserver?.disconnect();\n    window.removeEventListener(\"resize\", schedule);\n    if (vv) vv.removeEventListener(\"resize\", schedule);\n    if (rafId !== undefined) {\n      cancelAnimationFrame(rafId);\n      rafId = undefined;\n    }\n  };\n}\n\n/** Scoped, debounced `MutationObserver` on `root`: a mutation burst flushes one `callback` once the DOM is quiet for {@link MUTATION_DEBOUNCE_MS}. Leak-free `Disconnect`; inert off-DOM. */\nexport function createMutationWatcher(\n  root: Element | Document,\n  callback: MutationCallback,\n): Disconnect {\n  if (typeof MutationObserver === \"undefined\") return () => {};\n\n  let disposed = false;\n  let timer: ReturnType<typeof setTimeout> | undefined;\n  let pending: MutationRecord[] = [];\n\n  const flush = () => {\n    timer = undefined;\n    if (disposed) return;\n    const records = pending;\n    pending = [];\n    if (records.length > 0) callback(records);\n  };\n\n  const observer = new MutationObserver((records) => {\n    if (disposed) return;\n    for (const record of records) pending.push(record);\n    if (timer !== undefined) clearTimeout(timer);\n    timer = setTimeout(flush, MUTATION_DEBOUNCE_MS);\n  });\n\n  observer.observe(root, {\n    childList: true,\n    subtree: true,\n    characterData: true,\n  });\n\n  return () => {\n    if (disposed) return;\n    disposed = true;\n    observer.disconnect();\n    if (timer !== undefined) {\n      clearTimeout(timer);\n      timer = undefined;\n    }\n    pending = [];\n  };\n}\n","/**\n * Renderer contract re-exports plus the overlay-host helpers every tier shares.\n *\n * The overlay container, by construction:\n *  - absolutely positioned, out of layout flow, so a mark can't cause layout shift;\n *  - `aria-hidden` + `pointer-events: none`, so it's invisible to AT and never intercepts input;\n *  - `isolation: isolate`, so `mix-blend-mode: multiply` composites against the intended backdrop\n *    rather than leaking into ancestor stacking contexts;\n *  - `mix-blend-mode: multiply` by default (the subtractive-ink optic); individual nodes may override it.\n *\n * Nodes are pooled by stable identity (the per-line seed), not array index, so a surviving line keeps\n * its exact node and never flickers when the line set changes. {@link teardownContainer} leaves the DOM as it was.\n */\n\nimport type { BlendMode, Box, RenderContext } from \"../types.js\";\n\nexport type { Renderer, RenderContext } from \"../types.js\";\n\n/** Marks an overlay host this module created, so teardown is unambiguous. */\nconst OVERLAY_FLAG = \"data-highlighters-overlay\";\n\n/**\n * Per-element cache of the last inline value written per style property, so the helpers skip no-op writes.\n * Re-assigning `mask-image`/`filter` even to the same value can force a mask re-decode or filter\n * re-rasterize that flickers an in-flight draw-on. Keyed by the applied string, not the computed value.\n */\nconst appliedStyles = new WeakMap<HTMLElement, Record<string, string>>();\n\n/** Write via `apply` only if `value` differs from the last value cached for `key`. */\nfunction applyOnce(el: HTMLElement, key: string, value: string, apply: () => void): void {\n  let cache = appliedStyles.get(el);\n  if (!cache) {\n    cache = {};\n    appliedStyles.set(el, cache);\n  }\n  if (cache[key] === value) return;\n  cache[key] = value;\n  apply();\n}\n\n/** Set a style property in both camelCase and `-webkit-` prefixed forms. Idempotent (avoids mask re-decode on reflow). */\nexport function setVendorPrefixed(\n  el: HTMLElement,\n  prop: \"clipPath\" | \"maskImage\" | \"maskRepeat\" | \"maskPosition\" | \"maskSize\",\n  value: string,\n): void {\n  applyOnce(el, prop, value, () => {\n    const s = el.style as CSSStyleDeclaration & Record<string, string>;\n    s[prop] = value;\n    const webkitProp = `webkit${prop.charAt(0).toUpperCase()}${prop.slice(1)}`;\n    s[webkitProp] = value;\n  });\n}\n\n/** Set a plain inline style property idempotently; use for repaint-prone properties (`filter`, `background-image`). */\nexport function setStyleOnce(el: HTMLElement, prop: string, value: string): void {\n  applyOnce(el, prop, value, () => {\n    (el.style as CSSStyleDeclaration & Record<string, string>)[prop] = value;\n  });\n}\n\n/** The element behind a mark's first range, for backdrop-aware ink choices. Falls back to the overlay host. */\nexport function backdropElement(context: RenderContext): Element | null {\n  const node = context.ranges[0]?.commonAncestorContainer;\n  const el = node instanceof Element ? node : (node?.parentElement ?? null);\n  return el ?? context.container.parentElement;\n}\n\n/** Place an element as an absolutely-positioned px box from a {@link Box}. */\nexport function applyBoxPosition(el: HTMLElement, box: Box): void {\n  const s = el.style;\n  s.position = \"absolute\";\n  s.left = `${box.x}px`;\n  s.top = `${box.y}px`;\n  s.width = `${box.width}px`;\n  s.height = `${box.height}px`;\n}\n\n/**\n * Create (or return the existing) absolutely-positioned, isolated, `aria-hidden`, non-interactive\n * overlay host appended to `host`. Idempotent per host. A static host is promoted to\n * `position: relative`, anchoring the overlay without layout shift.\n * @param host - MUST be attached to a document for the overlay to paint.\n */\nexport function createOverlayContainer(host: HTMLElement): HTMLElement {\n  const existing = host.querySelector<HTMLElement>(`:scope > [${OVERLAY_FLAG}]`);\n  if (existing) return existing;\n\n  const doc = host.ownerDocument;\n  const container = doc.createElement(\"div\");\n  container.setAttribute(OVERLAY_FLAG, \"\");\n  styleOverlayLayer(container, \"multiply\");\n\n  // Promote only a static host to `relative`, anchoring the overlay without disturbing its layout.\n  const view = doc.defaultView;\n  if (view) {\n    const position = view.getComputedStyle(host).position;\n    if (position === \"static\") host.style.position = \"relative\";\n  }\n\n  host.appendChild(container);\n  return container;\n}\n\n/** Style an element as a positioned, isolated, non-interactive overlay layer with `blend` compositing. */\nfunction styleOverlayLayer(el: HTMLElement, blend: BlendMode): void {\n  el.setAttribute(\"aria-hidden\", \"true\");\n  const s = el.style;\n  s.position = \"absolute\";\n  s.top = \"0\";\n  s.left = \"0\";\n  s.width = \"100%\";\n  s.height = \"100%\";\n  s.pointerEvents = \"none\";\n  // Isolate so the blend composites against this overlay's own backdrop, not an ancestor stacking context.\n  s.isolation = \"isolate\";\n  s.mixBlendMode = blend;\n  s.overflow = \"visible\";\n  s.userSelect = \"none\";\n}\n\n/**\n * An extra overlay layer on `host` with a non-default blend, for a mark whose ink can't use the shared\n * multiply container - a near-white ink on a dark backdrop, or any ink under `vivid`, needs its own blend\n * to stay visible. Fills the host identically to the shared container (so host-relative line boxes line\n * up), but is uncached and unflagged, so it never disturbs sibling marks. Its lifetime is owned by\n * {@link resolveBlendTarget}.\n */\nfunction createBlendLayer(host: Element, blend: BlendMode): HTMLElement {\n  const layer = host.ownerDocument.createElement(\"div\");\n  styleOverlayLayer(layer, blend);\n  host.appendChild(layer);\n  return layer;\n}\n\n/**\n * Pick where this frame's mark nodes mount, reconciling the renderer's private escape layer in place.\n *\n * Most marks paint into the shared `multiply` container (`layerBlend` null). A mark that must escape it\n * gets its own isolated layer whose blend is baked in at creation, so this owns that layer across\n * re-renders: it keeps the cached one while the blend still matches, rebuilds it when the blend changes\n * (e.g. `vivid` flipped `\"screen\"` -> `true`), and removes it once no escape is needed (`vivid` off).\n * Pass the cached layer in as `current` and store the returned `layer` back, so the renderer holds a\n * single source of truth for its lifetime.\n */\nexport function resolveBlendTarget(\n  host: Element | null,\n  container: HTMLElement,\n  current: HTMLElement | null,\n  layerBlend: BlendMode | null,\n): { target: HTMLElement; layer: HTMLElement | null } {\n  if (!layerBlend || !host) {\n    current?.remove();\n    return { target: container, layer: null };\n  }\n  if (current && current.style.mixBlendMode === layerBlend) {\n    return { target: current, layer: current };\n  }\n  current?.remove();\n  const layer = createBlendLayer(host, layerBlend);\n  return { target: layer, layer };\n}\n\n/**\n * Tear down a mark's overlay container after its renderer unmounted. The container is shared by every\n * mark on the same host, so this only strips it once no marks remain: removing one mark never tears\n * down its neighbours. Safe to call more than once or on a never-attached container.\n */\nexport function teardownContainer(container: HTMLElement): void {\n  if (!container.firstChild) container.remove();\n}\n\n/** A node pool keyed by stable line identity (the per-line seed), so a surviving line keeps its exact node across a reflow that changes the line set. */\nexport class NodePool<T extends Node> {\n  private readonly nodes = new Map<number, T>();\n\n  get size(): number {\n    return this.nodes.size;\n  }\n\n  get(key: number): T | undefined {\n    return this.nodes.get(key);\n  }\n\n  set(key: number, node: T): void {\n    this.nodes.set(key, node);\n  }\n\n  has(key: number): boolean {\n    return this.nodes.has(key);\n  }\n\n  /** Reconcile after reflow: dispose every pooled node whose key is not in `keep`. Survivors keep their identity. */\n  retain(keep: Set<number>, dispose: (node: T) => void): void {\n    for (const [key, node] of this.nodes) {\n      if (!keep.has(key)) {\n        dispose(node);\n        this.nodes.delete(key);\n      }\n    }\n  }\n\n  /** Dispose every pooled node, on unmount, so no residue is left. */\n  clear(dispose: (node: T) => void): void {\n    for (const node of this.nodes.values()) dispose(node);\n    this.nodes.clear();\n  }\n}\n","/**\n * Capability detection and renderer-tier selection.\n *\n * Three tiers sit behind one API; degrade is fidelity-only, a lower tier never moves or recolours a\n * mark, only simplifies edge organicness and texture.\n *\n *  - {@link detectEnvironment}: runtime support + accessibility/data preferences. Touches no DOM at import.\n *  - {@link selectTier}: pick a concrete tier from a request, the environment, and the live mark count.\n */\n\nimport type {\n  RenderEnvironment,\n  RendererTier,\n  RendererTierPreference,\n} from \"../types.js\";\nimport { hasMediaQueries } from \"../internal/dom.js\";\n\n/** Mark count above which Tier A auto-degrades to Tier B under `auto`, so the CSS band protects the frame rate. */\nexport const DEFAULT_DEGRADE_THRESHOLD = 50;\n\n/** Tier order from highest fidelity to the universal floor. */\nconst TIER_ORDER: readonly RendererTier[] = [\"svg\", \"css\", \"highlight-api\"];\n\n/** Conservative environment for import time and off-browser: nothing assumed. */\nconst SSR_ENVIRONMENT: RenderEnvironment = {\n  supportsSvgFilters: false,\n  supportsCssBlend: false,\n  supportsHighlightApi: false,\n  prefersReducedMotion: false,\n  prefersReducedData: false,\n  coarsePointer: false,\n  degradeThreshold: DEFAULT_DEGRADE_THRESHOLD,\n};\n\n/** Safe `CSS.supports(decl, value)` that never throws on old engines. */\nfunction cssSupports(declaration: string, value: string): boolean {\n  if (typeof CSS === \"undefined\" || typeof CSS.supports !== \"function\") {\n    return false;\n  }\n  try {\n    return CSS.supports(declaration, value);\n  } catch {\n    return false;\n  }\n}\n\n/** Safe `matchMedia(query).matches`, `false` when the query is unparseable. */\nfunction mediaMatches(query: string): boolean {\n  try {\n    return window.matchMedia(query).matches;\n  } catch {\n    return false;\n  }\n}\n\n/** Tier A needs `clip-path`, `mask-image`, and SVG filters; test the props directly with `SVGFETurbulenceElement` as the filter signal. */\nfunction detectSvgFilters(): boolean {\n  const clip =\n    cssSupports(\"clip-path\", \"path('M0 0')\") ||\n    cssSupports(\"clip-path\", \"inset(0)\") ||\n    cssSupports(\"-webkit-clip-path\", \"inset(0)\");\n  const mask =\n    cssSupports(\"mask-image\", \"none\") ||\n    cssSupports(\"-webkit-mask-image\", \"none\");\n  const filters = typeof SVGFETurbulenceElement !== \"undefined\";\n  return clip && mask && filters;\n}\n\n/** Tier B needs `mix-blend-mode` and `box-decoration-break` (the CSS band). */\nfunction detectCssBlend(): boolean {\n  const blend = cssSupports(\"mix-blend-mode\", \"multiply\");\n  const clone =\n    cssSupports(\"box-decoration-break\", \"clone\") ||\n    cssSupports(\"-webkit-box-decoration-break\", \"clone\");\n  return blend && clone;\n}\n\n/** Tier C needs the CSS Custom Highlight API (`CSS.highlights` + `Highlight`). */\nfunction detectHighlightApi(): boolean {\n  return (\n    typeof CSS !== \"undefined\" &&\n    \"highlights\" in CSS &&\n    typeof Highlight !== \"undefined\"\n  );\n}\n\n/** Feature-detect the tiers and read motion/data/pointer preferences into a {@link RenderEnvironment}. SSR-safe; DOM-pure. */\nexport function detectEnvironment(): RenderEnvironment {\n  if (!hasMediaQueries()) return SSR_ENVIRONMENT;\n\n  return {\n    supportsSvgFilters: detectSvgFilters(),\n    supportsCssBlend: detectCssBlend(),\n    supportsHighlightApi: detectHighlightApi(),\n    prefersReducedMotion: mediaMatches(\"(prefers-reduced-motion: reduce)\"),\n    prefersReducedData: mediaMatches(\"(prefers-reduced-data: reduce)\"),\n    coarsePointer:\n      mediaMatches(\"(pointer: coarse)\") || mediaMatches(\"(hover: none)\"),\n    degradeThreshold: DEFAULT_DEGRADE_THRESHOLD,\n  };\n}\n\n/** Whether `env` reports support for a given concrete tier. */\nfunction tierSupported(tier: RendererTier, env: RenderEnvironment): boolean {\n  switch (tier) {\n    case \"svg\":\n      return env.supportsSvgFilters;\n    case \"css\":\n      return env.supportsCssBlend;\n    case \"highlight-api\":\n      return env.supportsHighlightApi;\n  }\n}\n\n/** First supported tier at or below `start`, else any supported tier, else `css` (the floor), so the selector always yields a concrete tier. */\nfunction firstSupportedFrom(\n  start: RendererTier,\n  env: RenderEnvironment,\n): RendererTier {\n  const startIndex = TIER_ORDER.indexOf(start);\n  for (let i = startIndex; i < TIER_ORDER.length; i++) {\n    const tier = TIER_ORDER[i]!;\n    if (tierSupported(tier, env)) return tier;\n  }\n  // Any supported tier above `start`.\n  for (const tier of TIER_ORDER) {\n    if (tierSupported(tier, env)) return tier;\n  }\n  return \"css\";\n}\n\n/**\n * Select the concrete renderer tier for a mark.\n *\n * - Pinned (`!== \"auto\"`): honour the request when supported, else step down to the nearest supported.\n * - `\"auto\"`: degrade precedence - reduced-motion/reduced-data and a mark count above the threshold\n *   both step SVG down to the CSS band; an unsupported tier falls through to the next supported. Tier B\n *   is the floor of auto-degrade; Tier C is chosen only when highest supported or explicitly pinned.\n *\n * Pure given its inputs; all capability reads happen in {@link detectEnvironment}.\n * @param markCount - Number of simultaneously visible marks (for the threshold).\n */\nexport function selectTier(\n  requested: RendererTierPreference,\n  env: RenderEnvironment,\n  markCount: number,\n): RendererTier {\n  if (requested !== \"auto\") {\n    return tierSupported(requested, env)\n      ? requested\n      : firstSupportedFrom(requested, env);\n  }\n\n  // Start from the highest supported tier, then apply degrade rules.\n  let tier = firstSupportedFrom(\"svg\", env);\n\n  if (tier === \"svg\") {\n    const degradeForPreference =\n      env.prefersReducedMotion || env.prefersReducedData;\n    const degradeForCount = markCount > env.degradeThreshold;\n    if (degradeForPreference || degradeForCount) {\n      tier = firstSupportedFrom(\"css\", env);\n    }\n  }\n\n  return tier;\n}\n","/**\n * Luminance-aware ink compositing.\n *\n * The overlay composites with `mix-blend-mode: multiply` by default - the subtractive-ink optic that\n * lets text show through and overlaps darken. But multiply is `backdrop x ink`, so a near-white ink\n * (every channel ~1) barely darkens anything: it's invisible on a light page, and on a dark page\n * multiply drives every colour to black. {@link effectiveInk} keeps such an ink visible:\n *\n *  - on a DARK backdrop, composite `normal` so the white ink paints a bright translucent wash;\n *  - on a LIGHT backdrop (light-on-light), keep `multiply` but darken the ink to a soft off-white so\n *    it still darkens the page into a faint, visible mark instead of vanishing.\n *\n * Near-white is judged by the per-channel MINIMUM, not luminance: highlighter yellow (`#ffff00`) has\n * high luminance but a zero blue channel, so multiply still tints it - only an all-channels-high\n * colour vanishes. Any explicit non-multiply blend the caller chose is always respected.\n */\n\nimport type { BlendMode, ColorValue } from \"../types.js\";\n\n// ~0.85 of 255: below this the ink still darkens enough under multiply to read.\nconst NEAR_WHITE_MIN = 217;\n// The off-white a near-white ink falls back to on a light backdrop, so multiply leaves a visible wash.\nconst OFF_WHITE = \"#d6d6d6\";\n\n/**\n * How to paint an ink. `layer` is the blend for a private overlay layer the mark needs to escape the\n * shared multiply container (a near-white ink on a dark backdrop, or any ink under `vivid`; see\n * {@link effectiveInk}), or `null` to use the shared multiply container as-is. `color` is the ink,\n * possibly substituted to an off-white.\n */\nexport interface InkPlan {\n  layer: BlendMode | null;\n  color: ColorValue;\n}\n\n/** Parse `#rgb(a)`, `#rrggbb(aa)`, or `rgb()/rgba()` to `[r, g, b, a]` (0-255, a 0-1). Null for other notations. */\nfunction parseRgba(color: string): [number, number, number, number] | null {\n  const c = color.trim();\n  if (c[0] === \"#\") {\n    const h = c.slice(1);\n    const short = h.length === 3 || h.length === 4;\n    if (!short && h.length !== 6 && h.length !== 8) return null;\n    const step = short ? 1 : 2;\n    const at = (i: number) => parseInt(short ? h[i].repeat(2) : h.slice(i, i + 2), 16);\n    const hasAlpha = h.length === 4 || h.length === 8;\n    const out: [number, number, number, number] = [at(0), at(step), at(2 * step), hasAlpha ? at(3 * step) / 255 : 1];\n    return out.some(Number.isNaN) ? null : out;\n  }\n  const m = /^rgba?\\(([^)]+)\\)/i.exec(c);\n  if (!m) return null;\n  const p = m[1].split(/[\\s,/]+/).filter(Boolean).map(Number);\n  return p.length >= 3 && p.slice(0, 3).every(Number.isFinite)\n    ? [p[0], p[1], p[2], p[3] ?? 1]\n    : null;\n}\n\n/** Smallest RGB channel (0-255) of a colour, or null if it can't be parsed without a browser. Pure; exported for tests. */\nexport function colorMinChannel(color: ColorValue): number | null {\n  const c = parseRgba(color);\n  return c ? Math.min(c[0], c[1], c[2]) : null;\n}\n\n// Exotic notations (named colours, hsl/oklch, currentColor) need the browser to normalise via one\n// reused throwaway canvas. An unparseable value leaves the \"#000\" sentinel, which reads as a dark ink\n// and safely keeps multiply. The common hex/rgb inks never reach here (colorMinChannel parses them).\nlet probe: CanvasRenderingContext2D | null | undefined;\n\nfunction minChannel(color: ColorValue, doc: Document): number | null {\n  const direct = colorMinChannel(color);\n  if (direct !== null) return direct;\n  try {\n    if (probe === undefined) probe = doc.createElement(\"canvas\").getContext(\"2d\");\n    if (probe) {\n      probe.fillStyle = \"#000\";\n      probe.fillStyle = color;\n      return colorMinChannel(probe.fillStyle as string);\n    }\n  } catch {\n    // Drop a context that errored (e.g. a torn-down document) so the next call retries with a live one.\n    probe = undefined;\n  }\n  return null;\n}\n\n/** Walk up from `el` to the first mostly-opaque background; light when its luminance >= 0.5. Unknown reads as light (default page canvas is white). */\nfunction backdropIsLight(el: Element | null, doc: Document): boolean {\n  const view = doc.defaultView;\n  if (!view) return true;\n  for (let node = el; node; node = node.parentElement) {\n    // Skip near-transparent layers (e.g. a faint scrim) so the real surface below decides the verdict.\n    const c = parseRgba(view.getComputedStyle(node).backgroundColor);\n    if (c && c[3] > 0.5) return (0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2]) / 255 >= 0.5;\n  }\n  return true;\n}\n\n/**\n * How to paint an ink so a near-white one stays visible. On a light backdrop it stays in the shared\n * multiply container but darkens to a soft off-white (`layer: null`); on a dark backdrop it needs its\n * own `normal`-blend layer to escape multiply (`layer: \"normal\"`). Every other colour, and any\n * explicit non-multiply blend, is left to the shared container untouched (`layer: null`).\n *\n * When `vivid` is set, any ink escapes onto a private layer (no near-white gate): `true` paints a\n * translucent `normal` wash, `\"screen\"` a `screen` band. It wins over `blendMode` and uses no probe.\n */\nexport function effectiveInk(\n  blendMode: BlendMode,\n  color: ColorValue,\n  backdrop: Element | null,\n  doc: Document,\n  vivid: boolean | \"screen\" = false,\n): InkPlan {\n  if (vivid) return { layer: vivid === \"screen\" ? \"screen\" : \"normal\", color };\n  if (blendMode !== \"multiply\") return { layer: null, color };\n  const min = minChannel(color, doc);\n  if (min === null || min < NEAR_WHITE_MIN) return { layer: null, color };\n  return backdropIsLight(backdrop, doc)\n    ? { layer: null, color: OFF_WHITE }\n    : { layer: \"normal\", color };\n}\n","/**\n * Tier B renderer: a CSS `linear-gradient` band. The lightweight tier.\n *\n * A per-line wrapper `<div>` holds a band `<div>` at `inset: 0` painted with the absolute-px end-pool\n * gradient and composited with `mix-blend-mode: multiply`. Edges are straight (no wave, no texture),\n * but colour, opacity, blend, and band position match Tier A, so degrading here changes fidelity not\n * identity. The wrapper carries only the box position (no clip), structurally identical to Tier A.\n *\n * Nodes are pooled by stable line identity; `unmount()` leaves the DOM pristine.\n */\n\nimport type { Renderer, RenderContext, MarkGeometry, PoolGradient, ColorValue } from \"../types.js\";\nimport { NodePool, applyBoxPosition, backdropElement, resolveBlendTarget } from \"./renderer.js\";\nimport { effectiveInk } from \"./blend.js\";\n\n/**\n * Convert a {@link PoolGradient} into a CSS `linear-gradient(...)` with absolute-px stop positions\n * and `min`/`max` clamps so a short mark can't over-pool. Each stop's alpha is folded into its colour\n * via `color-mix(... transparent)`, normalized to the brightest stop, so the gradient carries relative\n * pooling + dry-out while the band's layer opacity supplies the base. Without normalization the\n * per-stop alpha never renders and the band is flat.\n */\nexport function poolGradientToCss(pool: PoolGradient, colorOverride?: ColorValue): string {\n  const stops = pool.stops;\n  let maxAlpha = 0;\n  for (const s of stops) maxAlpha = Math.max(maxAlpha, s.opacity ?? 1);\n\n  // Relative per-stop alpha (1 at the brightest stop) folded into the colour, so layer opacity stays the absolute base.\n  const fill = (i: number): string => {\n    const stop = stops[i] ?? stops[0];\n    const rel = maxAlpha > 0 ? (stop?.opacity ?? 1) / maxAlpha : 1;\n    const color = colorOverride ?? stop?.color ?? \"transparent\";\n    return `color-mix(in srgb, ${color} ${Math.round(rel * 100)}%, transparent)`;\n  };\n\n  // Live-speed path: N core stops at pre-computed px positions between the two pool ends; no nested calc/min/max, so it parses everywhere.\n  const positions = pool.coreStopsPositionsPx;\n  if (positions) {\n    const parts: string[] = [\n      `linear-gradient(${pool.angle}deg`,\n      `${fill(0)} ${pool.startInsetPx}px`,\n    ];\n    for (let i = 0; i < positions.length; i++) {\n      parts.push(`${fill(i + 1)} ${round2(positions[i])}px`);\n    }\n    parts.push(`${fill(stops.length - 1)} calc(100% - ${pool.endInsetPx}px))`);\n    return parts.join(\", \");\n  }\n\n  // 4-stop gradient: absolute-px insets with min()/max() clamps keep the cap-pool width constant.\n  const startCore = `min(${pool.startCorePx}px, ${pool.startCorePct}%)`;\n  const endCore = `max(calc(100% - ${pool.endCorePx}px), ${pool.endCorePct}%)`;\n\n  return [\n    `linear-gradient(${pool.angle}deg`,\n    `${fill(0)} ${pool.startInsetPx}px`,\n    `${fill(1)} ${startCore}`,\n    `${fill(2)} ${endCore}`,\n    `${fill(3)} calc(100% - ${pool.endInsetPx}px))`,\n  ].join(\", \");\n}\n\n/** Round a px position to 2 decimals for a compact, stable gradient string. */\nfunction round2(value: number): number {\n  return Math.round(value * 100) / 100;\n}\n\n/** Create a Tier B renderer (`tier: \"css\"`). */\nexport function createCssRenderer(): Renderer {\n  // Per line: a positioned wrapper (the draw-on wipe surface) holding a band node.\n  const wrapperPool = new NodePool<HTMLElement>();\n  const bandPool = new NodePool<HTMLElement>();\n  let container: HTMLElement | null = null;\n  // A private `normal`-blend layer for a near-white ink on a dark backdrop, so it escapes the shared\n  // multiply container without flipping its blend (which would knock sibling marks out of multiply).\n  let blendLayer: HTMLElement | null = null;\n\n  function styleBand(\n    el: HTMLElement,\n    line: MarkGeometry,\n    context: RenderContext,\n    inkColor: ColorValue | undefined,\n  ): void {\n    const { options } = context;\n    const s = el.style;\n    s.position = \"absolute\";\n    s.left = \"0\";\n    s.top = \"0\";\n    s.width = \"100%\";\n    s.height = \"100%\";\n    s.pointerEvents = \"none\";\n    s.mixBlendMode = options.blendMode;\n    // layerScale (live-speed path only, else 1) carries the band's absolute deposit so a uniformly-fast swipe dims here rather than normalizing to full.\n    s.opacity = String(options.opacity * (line.pool.layerScale ?? 1));\n    s.backgroundImage = poolGradientToCss(line.pool, inkColor);\n    s.backgroundRepeat = \"no-repeat\";\n    (s as CSSStyleDeclaration & { boxDecorationBreak?: string }).boxDecorationBreak = \"clone\";\n    s.borderRadius = `${options.edge.radius}px`;\n  }\n\n  /** Reconcile the pool against the incoming line set, mounting/keeping nodes. */\n  function render(context: RenderContext): void {\n    container = context.container;\n    const doc = container.ownerDocument;\n    // Near-white ink on a dark backdrop, or any ink under vivid, escapes onto its own blend layer; everything else uses the shared container.\n    const plan = effectiveInk(context.options.blendMode, context.options.color, backdropElement(context), doc, context.options.vivid);\n    const { target, layer } = resolveBlendTarget(container.parentElement, container, blendLayer, plan.layer);\n    blendLayer = layer;\n    const inkColor = plan.color === context.options.color ? undefined : plan.color;\n    const keep = new Set<number>();\n\n    for (const line of context.lines) {\n      keep.add(line.seed);\n      // The wrapper carries only the box position (no clip) so the draw-on wipes it open without scaling; its clip-path is left untouched across reflow.\n      let wrapper = wrapperPool.get(line.seed);\n      if (!wrapper) {\n        wrapper = doc.createElement(\"div\");\n        wrapper.setAttribute(\"aria-hidden\", \"true\");\n        wrapper.style.pointerEvents = \"none\";\n        wrapperPool.set(line.seed, wrapper);\n      }\n      if (wrapper.parentElement !== target) target.appendChild(wrapper);\n      applyBoxPosition(wrapper, line.box);\n\n      let band = bandPool.get(line.seed);\n      if (!band) {\n        band = doc.createElement(\"div\");\n        band.setAttribute(\"aria-hidden\", \"true\");\n        wrapper.appendChild(band);\n        bandPool.set(line.seed, band);\n      }\n      styleBand(band, line, context, inkColor);\n    }\n\n    // Release vanished lines (the wrapper takes its band child with it); survivors keep their identical subtree.\n    wrapperPool.retain(keep, (el) => el.remove());\n    bandPool.retain(keep, () => {});\n  }\n\n  return {\n    tier: \"css\",\n    mount: render,\n    update: render,\n    bandFor: (seed: number): HTMLElement | null => wrapperPool.get(seed) ?? null,\n    unmount(): void {\n      wrapperPool.clear((el) => el.remove());\n      bandPool.clear(() => {});\n      blendLayer?.remove();\n      blendLayer = null;\n      container = null;\n    },\n  };\n}\n","/**\n * Tier A renderer: the realistic SVG-filter band. The default tier.\n *\n * Each visual line gets a positioned wrapper `<div>`; inside it at `inset: 0` sit the ink node\n * (pool gradient, clipped to the tip geometry via `clip-path`, textured by the offset-sampled noise\n * tile via `mask-image`, run through a shared SVG filter) and an optional glow node. The wrapper\n * carries no geometry clip-path, only the box position, so the draw-on can wipe it open with\n * `clip-path: inset(...)` instead of a `scaleX()` that would stretch the texture/wave.\n *\n * One shared `<svg>`/`<defs>` filter block is reused by every mark. Filters are referenced, never\n * animated: computed once per geometry and reused until reflow, so scrolling never re-filters.\n *\n * An optional additive fluorescence layer is a second node in `screen` blend over the multiply ink,\n * so an enabled mark reads brighter than its background rather than as a darker tint.\n *\n * Nodes are pooled by stable line identity; `unmount()` leaves the DOM pristine.\n */\n\nimport type { Renderer, RenderContext, MarkGeometry, ResolvedOptions, ColorValue } from \"../types.js\";\nimport { NodePool, applyBoxPosition, setVendorPrefixed, setStyleOnce, backdropElement, resolveBlendTarget } from \"./renderer.js\";\nimport { poolGradientToCss } from \"./tier-b-css.js\";\nimport { effectiveInk } from \"./blend.js\";\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\n/** Id of the document-level shared `<svg>` holding the filter defs. */\nconst SHARED_SVG_ID = \"highlighters-shared-defs\";\n\n/**\n * Lazily create (or return) the zero-size, off-screen, `aria-hidden` shared `<svg>`/`<defs>` block\n * every Tier A mark references. Filters are interned by id (see {@link edgeFilterId}): marks whose\n * params quantize to the same bucket share one filter, keeping the defs small.\n */\nfunction getSharedDefs(doc: Document): SVGDefsElement {\n  const existing = doc.getElementById(SHARED_SVG_ID);\n  if (existing) {\n    const defs = existing.querySelector(\"defs\");\n    if (defs) return defs as SVGDefsElement;\n  }\n\n  const svg = doc.createElementNS(SVG_NS, \"svg\");\n  svg.setAttribute(\"id\", SHARED_SVG_ID);\n  svg.setAttribute(\"aria-hidden\", \"true\");\n  svg.setAttribute(\"width\", \"0\");\n  svg.setAttribute(\"height\", \"0\");\n  const s = svg.style;\n  s.position = \"absolute\";\n  s.width = \"0\";\n  s.height = \"0\";\n  s.overflow = \"hidden\";\n  s.pointerEvents = \"none\";\n\n  const defs = doc.createElementNS(SVG_NS, \"defs\");\n  svg.appendChild(defs);\n  (doc.body ?? doc.documentElement).appendChild(svg);\n  return defs;\n}\n\n/** Quantize a 0-1 knob into one of `steps` buckets so filters can be interned. */\nfunction quantize(value: number, steps: number): number {\n  return Math.round(clamp01(value) * steps) / steps;\n}\n\n/** Edge-filter parameters, all absolute px: `scale` the displacement fray, `morph` the bleed dilation, `blur` the feather. */\ninterface EdgeFilterParams {\n  scale: number;\n  morph: number;\n  blur: number;\n}\n\n/**\n * Resolve + quantize the per-mark edge-filter params, driving both the filter's id and its\n * primitives. Returns `null` when nothing perturbs the edge, so the mark skips the filter.\n * Feathering drives blur and dilation, flow softens, viscosity sharpens; waviness/roughness/absorbency raise the fray.\n */\nfunction resolveEdgeFilter(options: ResolvedOptions): EdgeFilterParams | null {\n  const { edge, ink, paper } = options;\n\n  const softness =\n    ink.feathering * 1.0 + ink.flow * 0.4 - ink.viscosity * 0.35 + paper.absorbency * 0.4;\n  const blur = quantize(Math.max(0, softness), 8) * 4; // 0 .. 4px stdDeviation\n  // Thin (low-flow) ink dilates less so it stays skinny.\n  const spread = ink.feathering * 0.8 + paper.absorbency * 0.5 + ink.flow * 0.25 - 0.15;\n  const morph = quantize(Math.max(0, spread), 6) * 1.8; // 0 .. 1.8px dilate radius\n\n  const frayRaw = edge.waviness * 0.8 + edge.roughness * 4 + paper.absorbency * 2;\n  const scale = Math.min(8, Math.round(frayRaw * 2) / 2);\n\n  if (blur <= 0 && morph <= 0 && scale <= 0) return null;\n  return { scale, morph, blur };\n}\n\n/** A stable, collision-free id encoding the (quantized) edge-filter params. */\nfunction edgeFilterId(p: EdgeFilterParams): string {\n  const key = `${p.scale}-${p.morph}-${p.blur}`.replace(/\\./g, \"p\");\n  return `highlighters-edge-${key}`;\n}\n\n/** Return the edge filter id for `params`, interning it into the shared defs on first use. */\nfunction ensureEdgeFilter(defs: SVGDefsElement, params: EdgeFilterParams): string {\n  const id = edgeFilterId(params);\n  const doc = defs.ownerDocument;\n  if (!doc.getElementById(id)) {\n    defs.appendChild(buildEdgeFilter(doc, id, params));\n  }\n  return id;\n}\n\n/** Build one edge filter: turbulence, displacement (fray), optional morphology (bleed), optional blur (feather). Scale is absolute px, resolution-independent. */\nfunction buildEdgeFilter(\n  doc: Document,\n  id: string,\n  params: EdgeFilterParams,\n): SVGFilterElement {\n  const filter = doc.createElementNS(SVG_NS, \"filter\");\n  filter.setAttribute(\"id\", id);\n  // Generous region so the displaced/dilated edge isn't clipped by the filter box.\n  filter.setAttribute(\"x\", \"-20%\");\n  filter.setAttribute(\"y\", \"-20%\");\n  filter.setAttribute(\"width\", \"140%\");\n  filter.setAttribute(\"height\", \"140%\");\n  filter.setAttribute(\"filterUnits\", \"objectBoundingBox\");\n\n  const turb = doc.createElementNS(SVG_NS, \"feTurbulence\");\n  turb.setAttribute(\"type\", \"fractalNoise\");\n  turb.setAttribute(\"baseFrequency\", \"0.012 0.04\");\n  turb.setAttribute(\"numOctaves\", \"2\");\n  turb.setAttribute(\"seed\", \"7\");\n  // Seamless tiling so displaced edges never reveal a turbulence seam.\n  turb.setAttribute(\"stitchTiles\", \"stitch\");\n  turb.setAttribute(\"result\", \"noise\");\n  filter.appendChild(turb);\n\n  const disp = doc.createElementNS(SVG_NS, \"feDisplacementMap\");\n  disp.setAttribute(\"in\", \"SourceGraphic\");\n  disp.setAttribute(\"in2\", \"noise\");\n  disp.setAttribute(\"scale\", String(params.scale));\n  disp.setAttribute(\"xChannelSelector\", \"R\");\n  disp.setAttribute(\"yChannelSelector\", \"G\");\n  disp.setAttribute(\"result\", \"displaced\");\n  filter.appendChild(disp);\n\n  let last = \"displaced\";\n  if (params.morph > 0) {\n    const morph = doc.createElementNS(SVG_NS, \"feMorphology\");\n    morph.setAttribute(\"in\", last);\n    morph.setAttribute(\"operator\", \"dilate\");\n    morph.setAttribute(\"radius\", String(params.morph));\n    morph.setAttribute(\"result\", \"bled\");\n    filter.appendChild(morph);\n    last = \"bled\";\n  }\n  if (params.blur > 0) {\n    const blur = doc.createElementNS(SVG_NS, \"feGaussianBlur\");\n    blur.setAttribute(\"in\", last);\n    blur.setAttribute(\"stdDeviation\", String(params.blur));\n    filter.appendChild(blur);\n  }\n\n  return filter;\n}\n\n/** Create a Tier A renderer (`tier: \"svg\"`). */\nexport function createSvgRenderer(): Renderer {\n  // Per line: a positioned wrapper (the draw-on wipe surface, no geometry clip) holding an ink node and an optional glow node, all pooled by identity.\n  const wrapperPool = new NodePool<HTMLElement>();\n  const inkPool = new NodePool<HTMLElement>();\n  const glowPool = new NodePool<HTMLElement>();\n  let container: HTMLElement | null = null;\n  // A private `normal`-blend layer for a near-white ink on a dark backdrop, so it escapes the shared\n  // multiply container without flipping its blend (which would knock sibling marks out of multiply).\n  let blendLayer: HTMLElement | null = null;\n\n  /** Place a child node at `inset: 0` of its wrapper (fills the line box). */\n  function fillWrapper(el: HTMLElement): void {\n    const s = el.style;\n    s.position = \"absolute\";\n    s.left = \"0\";\n    s.top = \"0\";\n    s.width = \"100%\";\n    s.height = \"100%\";\n  }\n\n  function styleInk(\n    el: HTMLElement,\n    line: MarkGeometry,\n    context: RenderContext,\n    filterValue: string,\n    inkColor: ColorValue | undefined,\n  ): void {\n    const { options } = context;\n    const { ink } = options;\n    const s = el.style;\n    fillWrapper(el);\n    s.pointerEvents = \"none\";\n    s.mixBlendMode = options.blendMode;\n\n    // flow adds opacity, viscosity subtracts; 0.805 is the baked former ink.saturation gain.\n    const flowGain = 1 + 0.35 * (clamp01(ink.flow) - clamp01(ink.viscosity));\n    // layerScale (live-speed path only, else 1) carries the band's absolute deposit so a uniformly-fast swipe dims the layer instead of normalizing to full.\n    const effectiveAlpha = clamp01(\n      options.opacity * 0.805 * flowGain * (line.pool.layerScale ?? 1),\n    );\n    s.opacity = String(round3(effectiveAlpha));\n\n    setStyleOnce(el, \"backgroundImage\", poolGradientToCss(line.pool, inkColor));\n    s.backgroundRepeat = \"no-repeat\";\n    setVendorPrefixed(el, \"clipPath\", line.clipPath);\n    // Offset-sampled, fixed-px, repeated noise tile as a mask so the gradient shows through the grain. Sampled by offsetting the window, never rescaling it.\n    setVendorPrefixed(el, \"maskImage\", `url(\"${line.noiseTile.dataUrl}\")`);\n    setVendorPrefixed(el, \"maskRepeat\", \"repeat\");\n    setVendorPrefixed(el, \"maskPosition\", `${line.maskOffset.x}px ${line.maskOffset.y}px`);\n    setVendorPrefixed(el, \"maskSize\", `${line.noiseTile.width}px ${line.noiseTile.height}px`);\n\n    // The filter is invariant across a mark's lines, so it's interned once in render() and the URL passed in, no per-line recompute on the hot reflow path.\n    setStyleOnce(el, \"filter\", filterValue);\n  }\n\n  function styleGlow(el: HTMLElement, line: MarkGeometry, context: RenderContext): void {\n    const { glow } = context.options;\n    const s = el.style;\n    fillWrapper(el);\n    s.pointerEvents = \"none\";\n    // Additive emission over the multiply ink: screen blend + bloom so the mark reads brighter than its background. 0.82 is the baked saturation contribution.\n    s.mixBlendMode = \"screen\";\n    s.opacity = String(round3(clamp01(glow.intensity * 0.82)));\n    s.backgroundColor = glow.color;\n    setVendorPrefixed(el, \"clipPath\", line.clipPath);\n    setStyleOnce(el, \"filter\", `blur(${glow.spread}px)`);\n  }\n\n  function ensureInk(doc: Document, wrapper: HTMLElement, seed: number): HTMLElement {\n    let ink = inkPool.get(seed);\n    if (!ink) {\n      ink = doc.createElement(\"div\");\n      ink.setAttribute(\"aria-hidden\", \"true\");\n      wrapper.appendChild(ink);\n      inkPool.set(seed, ink);\n    }\n    return ink;\n  }\n\n  function render(context: RenderContext): void {\n    container = context.container;\n    const doc = container.ownerDocument;\n    // Near-white ink on a dark backdrop, or any ink under vivid, escapes onto its own blend layer; everything else uses the shared container.\n    const plan = effectiveInk(context.options.blendMode, context.options.color, backdropElement(context), doc, context.options.vivid);\n    const { target, layer } = resolveBlendTarget(container.parentElement, container, blendLayer, plan.layer);\n    blendLayer = layer;\n    const inkColor = plan.color === context.options.color ? undefined : plan.color;\n    // Intern the edge filter once: it depends only on doc + options, so it's invariant across a mark's lines.\n    const defs = getSharedDefs(doc);\n    const filterParams = resolveEdgeFilter(context.options);\n    const filterValue = filterParams ? `url(#${ensureEdgeFilter(defs, filterParams)})` : \"\";\n\n    const glowEnabled = context.options.glow.enabled;\n    const keep = new Set<number>();\n\n    for (const line of context.lines) {\n      keep.add(line.seed);\n\n      // The wrapper carries only the box position, never a geometry clip; its clip-path is left untouched here so an in-flight/primed reveal survives reflow.\n      let wrapper = wrapperPool.get(line.seed);\n      if (!wrapper) {\n        wrapper = doc.createElement(\"div\");\n        wrapper.setAttribute(\"aria-hidden\", \"true\");\n        wrapper.style.pointerEvents = \"none\";\n        wrapperPool.set(line.seed, wrapper);\n      }\n      if (wrapper.parentElement !== target) target.appendChild(wrapper);\n      applyBoxPosition(wrapper, line.box);\n\n      const ink = ensureInk(doc, wrapper, line.seed);\n\n      if (glowEnabled) {\n        let glow = glowPool.get(line.seed);\n        if (!glow) {\n          glow = doc.createElement(\"div\");\n          glow.setAttribute(\"aria-hidden\", \"true\");\n          // Glow sits beneath the ink in DOM order so the ink's clip wins visually.\n          wrapper.insertBefore(glow, ink);\n          glowPool.set(line.seed, glow);\n        }\n        styleGlow(glow, line, context);\n      }\n\n      styleInk(ink, line, context, filterValue, inkColor);\n    }\n\n    // A vanished line's wrapper (with its ink/glow children) is removed as a unit; survivors keep their exact subtree.\n    wrapperPool.retain(keep, (el) => el.remove());\n    inkPool.retain(keep, () => {});\n    // Drop all glow nodes if glow is now off.\n    const glowKeep = glowEnabled ? keep : new Set<number>();\n    glowPool.retain(glowKeep, (el) => el.remove());\n  }\n\n  return {\n    tier: \"svg\",\n    mount: render,\n    update: render,\n    bandFor: (seed: number): HTMLElement | null => wrapperPool.get(seed) ?? null,\n    unmount(): void {\n      // Removing each wrapper detaches its ink/glow children; clear the child pools\n      // without re-removing (their nodes leave with the wrapper).\n      wrapperPool.clear((el) => el.remove());\n      inkPool.clear(() => {});\n      glowPool.clear(() => {});\n      blendLayer?.remove();\n      blendLayer = null;\n      container = null;\n    },\n  };\n}\n\nfunction clamp01(v: number): number {\n  return v < 0 ? 0 : v > 1 ? 1 : v;\n}\n\n/** Round to 3 decimals so inline-style writes stay stable/compact. */\nfunction round3(v: number): number {\n  return Math.round(v * 1000) / 1000;\n}\n","/**\n * Tier C renderer: the CSS Custom Highlight API (`::highlight()`). The maximally-safe tier.\n *\n * Registers the mark's `Range`s with `CSS.highlights` and paints them via a generated `::highlight()`\n * rule: zero overlay DOM, native multiline, find-in-page/selection unaffected, text nodes untouched.\n * The trade-off is fidelity (flat colour only), but colour and coverage still match the other tiers.\n *\n * Each instance owns one named `Highlight` registration and one CSS rule in a shared `<style>`.\n * `unmount()` deregisters and removes its rule, leaving the document pristine.\n */\n\nimport type { Renderer, RenderContext } from \"../types.js\";\n\n/** Monotonic id source so concurrent marks never collide on a highlight name. */\nlet highlightSeq = 0;\n\nconst STYLE_ID = \"highlighters-highlight-api-styles\";\n\n/** Lazily create (or return) the single shared `<style>` for all `::highlight()` rules. */\nfunction getSharedStyle(doc: Document): HTMLStyleElement {\n  const existing = doc.getElementById(STYLE_ID);\n  if (existing instanceof HTMLStyleElement) return existing;\n\n  const style = doc.createElement(\"style\");\n  style.id = STYLE_ID;\n  (doc.head ?? doc.documentElement).appendChild(style);\n  return style;\n}\n\n/** Whether the Custom Highlight API is usable here; guarded for SSR/old engines. */\nfunction highlightApiAvailable(): boolean {\n  return (\n    typeof CSS !== \"undefined\" &&\n    \"highlights\" in CSS &&\n    typeof Highlight !== \"undefined\"\n  );\n}\n\n/** Create a Tier C renderer (`tier: \"highlight-api\"`): one shared-stylesheet rule keyed by a unique highlight name, plus a `Highlight` over the ranges. */\nexport function createHighlightApiRenderer(): Renderer {\n  const name = `highlighters-${++highlightSeq}`;\n  let highlight: Highlight | null = null;\n  let styleEl: HTMLStyleElement | null = null;\n  let ruleText = \"\";\n\n  function ruleFor(context: RenderContext): string {\n    const { options } = context;\n    // `::highlight()` exposes no opacity/blend, so fold opacity into the fill via `color-mix`; blend mode is dropped.\n    const alpha = Math.max(0, Math.min(1, options.opacity));\n    // `options.color` lands in raw stylesheet rule text, so guard against CSS injection: `CSS.supports`\n    // accepts only a bare colour and rejects anything crafted to close `color-mix()` and inject rules.\n    const raw = String(options.color);\n    const color =\n      typeof CSS !== \"undefined\" && CSS.supports?.(\"color\", raw) ? raw : \"transparent\";\n    const fill = `color-mix(in srgb, ${color} ${Math.round(alpha * 100)}%, transparent)`;\n    const decls = [`background-color: ${fill}`, `color: inherit`];\n    return `::highlight(${name}) { ${decls.join(\"; \")}; }`;\n  }\n\n  function register(ranges: Range[]): void {\n    if (!highlightApiAvailable()) return;\n\n    if (!highlight) {\n      highlight = new Highlight();\n      CSS.highlights.set(name, highlight);\n    } else {\n      highlight.clear();\n    }\n    for (const range of ranges) highlight.add(range);\n  }\n\n  function writeRule(context: RenderContext): void {\n    const doc =\n      context.container.ownerDocument ??\n      (typeof document !== \"undefined\" ? document : null);\n    if (!doc) return;\n    styleEl ??= getSharedStyle(doc);\n    ruleText = ruleFor(context);\n    rewriteOwnRule();\n  }\n\n  /** Replace this renderer's rule in the shared sheet without disturbing others. */\n  function rewriteOwnRule(): void {\n    if (!styleEl) return;\n    // Strip only this renderer's rule (others stay byte-intact), then append the fresh one. `name` is regex-escaped.\n    const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n    const ownRule = new RegExp(`\\\\s*::highlight\\\\(${escaped}\\\\)\\\\s*\\\\{[^}]*\\\\}`, \"g\");\n    const base = (styleEl.textContent ?? \"\").replace(ownRule, \"\").trim();\n    styleEl.textContent = base ? `${base}\\n${ruleText}` : ruleText;\n  }\n\n  return {\n    tier: \"highlight-api\",\n\n    mount(context: RenderContext): void {\n      register(context.ranges);\n      writeRule(context);\n    },\n\n    update(context: RenderContext): void {\n      register(context.ranges);\n      writeRule(context);\n    },\n\n    // No overlay DOM (paints via ::highlight()), so there's no wrapper to draw on.\n    bandFor: (): HTMLElement | null => null,\n\n    unmount(): void {\n      if (highlightApiAvailable() && CSS.highlights.has(name)) {\n        CSS.highlights.delete(name);\n      }\n      highlight = null;\n      if (styleEl) {\n        ruleText = \"\";\n        rewriteOwnRule();\n        // Drop the node entirely once the sheet is empty, so we leave no trace.\n        if (!styleEl.textContent || styleEl.textContent.trim() === \"\") {\n          styleEl.remove();\n        }\n        styleEl = null;\n      }\n    },\n  };\n}\n","/**\n * Entrance animation: the draw-on swipe.\n *\n * The mark draws itself on by growing its own geometry: each frame the line's `clip-path`\n * is rebuilt truncated to an advancing front (`clipAtFront`), so the leading edge is always\n * the mark's own tip cap and the drawn prefix is byte-identical frame to frame.\n *\n * The draw clip lives on the per-line wrapper, never its ink/glow children: the renderer\n * owns the children's full clip and rewrites it on every reflow, the draw owns the wrapper's\n * clip, and the two never touch the same property on one element. Load-bearing: a reflow\n * mid-draw re-runs `update()`, resetting the children's clip, but the wrapper's front clip is\n * left intact so the band keeps drawing instead of flashing to full and restarting.\n *\n * The band finds its wrapper by stable seed (`bandFor`), never by index: several marks share\n * one container, so an index lookup would alias onto a sibling mark's band.\n *\n * Reflow never re-animates; only first appearance or an explicit re-show does. The\n * {@link Disconnect} cancels the rAF + observer and restores each line's full clip so a\n * cancelled mid-draw never strands a truncated mark.\n */\n\nimport type {\n  Disconnect,\n  MarkGeometry,\n  ResolvedAnimation,\n  RenderEnvironment,\n} from \"../types.js\";\n\n/** Guarded read of `prefers-reduced-motion`; `false` outside a DOM. */\nexport function prefersReducedMotion(): boolean {\n  if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n    return false;\n  }\n  try {\n    return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n  } catch {\n    return false;\n  }\n}\n\ntype Easer = (t: number) => number;\n\nconst NAMED_EASINGS: Record<string, [number, number, number, number]> = {\n  ease: [0.25, 0.1, 0.25, 1],\n  \"ease-in\": [0.42, 0, 1, 1],\n  \"ease-out\": [0, 0, 0.58, 1],\n  \"ease-in-out\": [0.42, 0, 0.58, 1],\n};\n\n/** A cubic-bezier easing sampler (Newton-Raphson invert of X, then Y). */\nfunction cubicBezierEaser(p1x: number, p1y: number, p2x: number, p2y: number): Easer {\n  const cx = 3 * p1x;\n  const bx = 3 * (p2x - p1x) - cx;\n  const ax = 1 - cx - bx;\n  const cy = 3 * p1y;\n  const by = 3 * (p2y - p1y) - cy;\n  const ay = 1 - cy - by;\n  const sampleX = (t: number) => ((ax * t + bx) * t + cx) * t;\n  const sampleY = (t: number) => ((ay * t + by) * t + cy) * t;\n  const slopeX = (t: number) => (3 * ax * t + 2 * bx) * t + cx;\n  return (x: number): number => {\n    if (x <= 0) return 0;\n    if (x >= 1) return 1;\n    let t = x;\n    for (let i = 0; i < 6; i++) {\n      const err = sampleX(t) - x;\n      if (Math.abs(err) < 1e-4) break;\n      const d = slopeX(t);\n      if (Math.abs(d) < 1e-6) break;\n      t -= err / d;\n    }\n    return sampleY(t);\n  };\n}\n\n/** Resolve a CSS easing string to a JS progress sampler (rAF needs a sampler). */\nfunction parseEasing(easing: ResolvedAnimation[\"easing\"]): Easer {\n  if (easing === \"linear\") return (t) => t;\n  const named = NAMED_EASINGS[easing];\n  if (named) return cubicBezierEaser(...named);\n  const m = /cubic-bezier\\(([^)]+)\\)/.exec(easing);\n  if (m) {\n    const n = m[1].split(\",\").map((s) => Number(s.trim()));\n    if (n.length === 4 && n.every(Number.isFinite)) {\n      return cubicBezierEaser(n[0], n[1], n[2], n[3]);\n    }\n  }\n  return cubicBezierEaser(...NAMED_EASINGS[\"ease-out\"]);\n}\n\n/** Set `clip-path` plus the `-webkit-` alias for older Safari. */\nfunction setClip(el: HTMLElement, path: string): void {\n  el.style.clipPath = path;\n  el.style.setProperty(\"-webkit-clip-path\", path);\n}\n\n/** Onset fade-in (ms): a tiny fixed wall-clock time to soften the touchdown, draw-speed-independent. */\nconst FADE_IN_MS = 50;\n\nfunction fadeOpacity(elapsedMs: number, fadeMs: number): string {\n  if (elapsedMs >= fadeMs) return \"\";\n  return (Math.max(0, elapsedMs) / fadeMs).toFixed(3);\n}\n\n/** Resolve a line's stable seed to its wrapper. Keyed by seed not index: shared containers make sibling marks' wrappers alias. `null` for no-overlay tiers or an unmounted line. */\ntype BandFor = (seed: number) => HTMLElement | null;\n\ninterface DrawItem {\n  node: HTMLElement;\n  full: string;\n  build: (front: number) => string;\n  width: number;\n  minFront: number;\n  startMs: number;\n}\n\nfunction drawItems(bandFor: BandFor, lines: MarkGeometry[], stagger: number): DrawItem[] {\n  const items: DrawItem[] = [];\n  lines.forEach((line, i) => {\n    const node = bandFor(line.seed);\n    if (!node) return;\n    items.push({\n      node,\n      full: line.clipPath,\n      build: line.clipAtFront,\n      width: line.box.width,\n      minFront: line.minFront,\n      startMs: i * stagger,\n    });\n  });\n  return items;\n}\n\n/** Restore every wrapper to its full (settled) clip and opacity. */\nfunction showFull(items: DrawItem[]): void {\n  for (const it of items) {\n    setClip(it.node, it.full);\n    it.node.style.opacity = \"\";\n  }\n}\n\n/**\n * A {@link Disconnect} for the draw-on, plus `retarget`: re-point an in-flight draw-on at\n * freshly-built geometry without restarting its clock (e.g. a late web-font load correcting\n * a line height mid-entrance). Once settled, `retarget` only re-shows the full clip.\n */\nexport type DrawOnHandle = Disconnect & {\n  retarget: (lines: MarkGeometry[]) => void;\n  /** Replay the draw-on from the start (an explicit re-show). Reduced motion / draw off just re-shows full. */\n  replay: () => void;\n};\n\nfunction asHandle(\n  disconnect: Disconnect,\n  retarget: DrawOnHandle[\"retarget\"],\n  replay: DrawOnHandle[\"replay\"],\n): DrawOnHandle {\n  return Object.assign(disconnect, { retarget, replay });\n}\n\n/**\n * Run the draw-on across the wrappers in `container`, or show them instantly when motion is\n * reduced, drawing is disabled, or no `requestAnimationFrame` exists. `stagger` offsets each\n * line so a wrapped mark reads as one continuous pen travel.\n * @returns A {@link DrawOnHandle} cancelling the rAF/observer and restoring full clips.\n */\nexport function applyDrawOn(\n  container: HTMLElement,\n  bandFor: BandFor,\n  lines: MarkGeometry[],\n  animation: ResolvedAnimation,\n  env: RenderEnvironment,\n): DrawOnHandle {\n  if (lines.length === 0) return asHandle(() => {}, () => {}, () => {});\n\n  let items = drawItems(bandFor, lines, animation.stagger);\n  if (items.length === 0) return asHandle(() => {}, () => {}, () => {});\n\n  // Reduced motion / draw off / no rAF: instant full mark, no animation.\n  if (\n    env.prefersReducedMotion ||\n    !animation.draw ||\n    typeof requestAnimationFrame === \"undefined\"\n  ) {\n    showFull(items);\n    return asHandle(\n      () => {},\n      (next) => showFull(drawItems(bandFor, next, animation.stagger)),\n      () => showFull(items),\n    );\n  }\n\n  const ease = parseEasing(animation.easing);\n  const duration = Math.max(1, animation.duration);\n  // Capped at half the draw so a very short draw still softens.\n  const fadeMs = Math.min(FADE_IN_MS, duration * 0.5);\n  let raf = 0;\n  let startTime = 0;\n  let observer: IntersectionObserver | null = null;\n  let played = false;\n\n  /** Park a line closed (front 0 → an empty clip), hiding it until its turn. */\n  function primeClosed(it: DrawItem): void {\n    setClip(it.node, it.build(0));\n  }\n\n  function frame(now: number): void {\n    if (startTime === 0) startTime = now;\n    let done = true;\n    for (const it of items) {\n      const elapsed = now - startTime - it.startMs;\n      const t = elapsed / duration;\n      if (t >= 1) {\n        setClip(it.node, it.full);\n        it.node.style.opacity = \"\";\n        continue;\n      }\n      done = false;\n      // Map progress onto [minFront -> width] so the band touches down at its tip and drags.\n      // Front 0 (t <= 0) stays the empty clip, hiding a staggered line until its turn. Mapping\n      // from 0 instead would clamp every sub-tip front up to minFront, popping then freezing.\n      const p = t <= 0 ? 0 : ease(t);\n      const front = p <= 0 ? 0 : it.minFront + p * (it.width - it.minFront);\n      setClip(it.node, it.build(front));\n      it.node.style.opacity = fadeOpacity(elapsed, fadeMs);\n    }\n    raf = done ? 0 : requestAnimationFrame(frame);\n  }\n\n  function play(): void {\n    startTime = 0;\n    for (const it of items) primeClosed(it);\n    raf = requestAnimationFrame(frame);\n  }\n\n  function stop(): void {\n    if (raf) cancelAnimationFrame(raf);\n    raf = 0;\n  }\n\n  if (animation.trigger === \"in-view\" && typeof IntersectionObserver !== \"undefined\") {\n    // Park closed so the marks are hidden until they enter view.\n    for (const it of items) primeClosed(it);\n    observer = new IntersectionObserver(\n      (entries) => {\n        const visible = entries.some((e) => e.isIntersecting);\n        if (!visible) return;\n        if (played && !animation.repeat) return;\n        if (animation.repeat) stop();\n        played = true;\n        play();\n        if (!animation.repeat) {\n          observer?.disconnect();\n          observer = null;\n        }\n      },\n      { threshold: animation.threshold, rootMargin: animation.rootMargin },\n    );\n    observer.observe(container);\n  } else {\n    played = true;\n    play();\n  }\n\n  function retarget(next: MarkGeometry[]): void {\n    items = drawItems(bandFor, next, animation.stagger);\n    if (raf !== 0) return; // mid-draw: the frame loop keeps drawing the corrected geometry\n    // Settled: re-show the corrected full clip. Armed-but-not-played: keep it parked closed so a\n    // reflow before the mark enters view can't flash it fully-drawn then restart on play.\n    if (played) showFull(items);\n    else for (const it of items) primeClosed(it);\n  }\n\n  function replay(): void {\n    stop();\n    played = true;\n    play();\n  }\n\n  return asHandle(\n    () => {\n      stop();\n      observer?.disconnect();\n      observer = null;\n      // Never strand a cancelled mid-draw as a truncated mark.\n      showFull(items);\n    },\n    retarget,\n    replay,\n  );\n}\n","/**\n * The mark handle: the object every targeting call returns.\n *\n * A handle owns a single mounted mark (renderer, overlay container, reflow observer, extra cleanup).\n * `update(opts)` re-resolves options through the merge chain and re-renders without re-seeding stable\n * geometry; `remove()` tears everything down, leaving the DOM byte-for-byte as before. Given a\n * `rebuild` callback, `update`/reflow both flow through it, so one place turns ranges + options into\n * a {@link RenderContext}.\n */\n\nimport type {\n  Disconnect,\n  HighlightOptions,\n  MarkHandle,\n  RenderContext,\n  Renderer,\n  RendererTier,\n  ResolvedOptions,\n} from \"../types.js\";\nimport { mergeOptions, resolveOptions } from \"../config/merge.js\";\nimport { teardownContainer } from \"./renderer.js\";\n\nexport interface MarkHandleInit {\n  /** The originating ranges (needed for re-render and Tier C painting). */\n  ranges: Range[];\n  options: ResolvedOptions;\n  renderer: Renderer;\n  container: HTMLElement;\n  reflow: Disconnect;\n  /** Extra teardown to run on `remove()` (animation, mutation watcher, …). */\n  cleanup?: Disconnect[];\n  /** Replay the draw-on entrance on an explicit `show()`. No-op if none. */\n  replay?: () => void;\n  /** Re-point the draw-on at freshly-built geometry on `update()`; without it a reshape leaves the old shape's clip cropping the new one. Never re-animates. */\n  retarget?: (lines: RenderContext[\"lines\"]) => void;\n  /** The user-facing options that produced {@link options}; `update()` accumulates overrides on top. */\n  userOptions?: HighlightOptions;\n  /** Recompute the {@link RenderContext} for the current layout and options from a fresh read phase. */\n  rebuild: (options: ResolvedOptions) => RenderContext;\n}\n\n/** Build a {@link MarkHandle} over a mounted renderer. */\nexport function createMarkHandle(init: MarkHandleInit): MarkHandle {\n  const { renderer, container, reflow, rebuild, replay, retarget } = init;\n  const cleanups = init.cleanup ? [...init.cleanup] : [];\n  // Accumulated across `update()` calls so the merge chain stays correct.\n  let userOptions: HighlightOptions = init.userOptions ? { ...init.userOptions } : {};\n  let resolved = init.options;\n  let showing = true;\n  let removed = false;\n\n  /** Re-derive geometry and hand it to the renderer (the single render path). */\n  function rerender(): void {\n    if (removed) return;\n    const ctx = rebuild(resolved);\n    renderer.update(ctx);\n    // Keep the wrapper clip in step with the new geometry; a reshape would otherwise leave the old\n    // shape's clip cropping the new one. Settled shows the new full clip, mid-draw picks it up. Never re-animates.\n    retarget?.(ctx.lines);\n    container.style.visibility = showing ? \"\" : \"hidden\";\n  }\n\n  return {\n    get tier(): RendererTier {\n      return renderer.tier;\n    },\n\n    show(): void {\n      if (removed) return;\n      showing = true;\n      container.style.visibility = \"\";\n      // An explicit re-show replays the entrance; the initial mount animates directly, so this only fires on a later show().\n      replay?.();\n    },\n\n    hide(): void {\n      if (removed) return;\n      showing = false;\n      // Hide without tearing down geometry/observers: nodes stay pooled so a later show() is instant.\n      container.style.visibility = \"hidden\";\n    },\n\n    isShowing(): boolean {\n      return showing && !removed;\n    },\n\n    update(opts: Partial<HighlightOptions>): void {\n      if (removed) return;\n      // Re-resolve through the full merge chain so overrides compose correctly across successive updates.\n      userOptions = mergeOptions(userOptions, opts as HighlightOptions);\n      resolved = resolveOptions(userOptions);\n      rerender();\n    },\n\n    remove(): void {\n      if (removed) return;\n      removed = true;\n      showing = false;\n      // Order matters: stop incoming work (reflow + cleanups), then unmount the renderer, then strip the container.\n      reflow();\n      for (const dispose of cleanups) {\n        try {\n          dispose();\n        } catch {\n          // A cleanup throwing must not strand the rest of teardown.\n        }\n      }\n      cleanups.length = 0;\n      renderer.unmount();\n      teardownContainer(container);\n    },\n  };\n}\n","/**\n * The public entry points.\n *\n * One pipeline, many front doors: every targeting input normalizes to DOM `Range`s, then\n * per-visual-line rectangles, then absolute-px {@link MarkGeometry} per line, then the selected\n * renderer tier. The returned handle owns the reflow observer and (for page/selection modes) the\n * mutation watcher or selection listener, tearing them all down on `remove()`.\n *\n * SSR-safe: outside a DOM the entry points return an inert no-op handle.\n */\n\nimport type {\n  GroupHandle,\n  HighlightOptions,\n  LineRect,\n  LineSpeedProfile,\n  MarkGeometry,\n  MarkHandle,\n  RenderContext,\n  Renderer,\n  ResolvedOptions,\n  SnapMode,\n  Target,\n} from \"../types.js\";\nimport { mergeOptions, resolveOptions } from \"../config/merge.js\";\nimport { buildMarkGeometry } from \"../geometry/mark-space.js\";\nimport { hashU32 } from \"../geometry/rng.js\";\nimport { snapRangeToBounds } from \"../geometry/snap.js\";\nimport { toRanges } from \"../targeting/normalize.js\";\nimport { collectPageRanges, excludeMarkedSubtrees } from \"../targeting/include-exclude.js\";\nimport { computeAnchor, rangesToLineRects } from \"../targeting/line-rects.js\";\nimport { SelectionVelocityTracker } from \"../targeting/velocity.js\";\nimport { findSelectionAnchor } from \"../targeting/anchor.js\";\nimport { createMutationWatcher, createReflowObserver } from \"../targeting/observers.js\";\nimport { createOverlayContainer, teardownContainer } from \"./renderer.js\";\nimport { detectEnvironment, selectTier } from \"./tier-select.js\";\nimport { createSvgRenderer } from \"./tier-a-svg.js\";\nimport { createCssRenderer } from \"./tier-b-css.js\";\nimport { createHighlightApiRenderer } from \"./tier-c-highlight-api.js\";\nimport { applyDrawOn } from \"./animation.js\";\nimport { createMarkHandle } from \"./mark-handle.js\";\nimport { hasDom } from \"../internal/dom.js\";\n\n/** An inert no-op handle for non-DOM environments so callers needn't branch. */\nfunction inertHandle(): MarkHandle {\n  return {\n    show() {},\n    hide() {},\n    update() {},\n    remove() {},\n    isShowing() {\n      return false;\n    },\n    tier: \"css\",\n  };\n}\n\nfunction rendererForTier(tier: ReturnType<typeof selectTier>): Renderer {\n  switch (tier) {\n    case \"svg\":\n      return createSvgRenderer();\n    case \"highlight-api\":\n      return createHighlightApiRenderer();\n    case \"css\":\n    default:\n      return createCssRenderer();\n  }\n}\n\n/** Default snap mode by target shape: elements/page yield line, text/selection yield word. */\nfunction defaultSnap(target: Target): SnapMode {\n  if (typeof target === \"string\" || target instanceof Element) return \"line\";\n  if (typeof Range !== \"undefined\" && target instanceof Range) return \"word\";\n  if (typeof Selection !== \"undefined\" && target instanceof Selection) return \"word\";\n  if (typeof target === \"object\" && target !== null && \"text\" in target) return \"word\";\n  return \"line\";\n}\n\n/** Apply the configured snap mode to a list of ranges. */\nfunction snapRanges(ranges: Range[], mode: SnapMode): Range[] {\n  if (mode === \"none\") return ranges;\n  return ranges.map((r) => snapRangeToBounds(r, mode));\n}\n\n/** Elements whose layout shifts should trigger a mark reflow (the range's text nodes and ancestors). */\nfunction elementsFromRanges(ranges: Range[]): Element[] {\n  const seen = new Set<Element>();\n  const add = (node: Node | null) => {\n    if (!node) return;\n    const el = node instanceof Element ? node : node.parentElement;\n    if (el) seen.add(el);\n  };\n  for (const range of ranges) {\n    add(range.startContainer);\n    add(range.endContainer);\n    add(range.commonAncestorContainer);\n  }\n  return [...seen];\n}\n\n/** Reflow targets for a mounted mark: the overlay host plus every highlighted element. */\nfunction reflowTargetsFor(host: HTMLElement, ranges: Range[]): Element[] {\n  return [...new Set<Element>([host, ...elementsFromRanges(ranges)])];\n}\n\n/** The host an overlay attaches to - the document body, where line boxes are anchored. */\nfunction hostFor(ranges: Range[]): HTMLElement | null {\n  for (const range of ranges) {\n    const node = range.commonAncestorContainer;\n    const el = node instanceof Element ? node : node.parentElement;\n    if (el) {\n      // Body, so absolute-px line boxes (document coordinates) line up regardless of the target's box.\n      return el.ownerDocument.body ?? el.ownerDocument.documentElement;\n    }\n  }\n  return null;\n}\n\n/** The forced-layout phase: measure ranges into container-local {@link LineRect}s (raw seeds intact). */\nfunction measureLines(\n  ranges: Range[],\n  container: HTMLElement,\n  cachedOrigin?: DOMRect,\n  anchorHost?: HTMLElement,\n): LineRect[] {\n  if (ranges.length === 0) return [];\n  // `getClientRects()` is viewport-relative; subtracting the container's rect ties a line's seed\n  // and position to its document position alone, stable under scroll and either drag direction.\n  // A caller mid-frame can pass `cachedOrigin` so several builds share one layout read.\n  const origin = cachedOrigin ?? container.getBoundingClientRect();\n  const hostRect = anchorHost?.getBoundingClientRect();\n  const lineRects = rangesToLineRects(\n    ranges,\n    computeAnchor(ranges),\n    origin.top,\n    anchorHost && hostRect\n      ? { scope: anchorHost, columnBounds: { left: hostRect.left, right: hostRect.right } }\n      : undefined,\n  );\n  return lineRects.map((rect) => ({\n    ...rect,\n    left: rect.left - origin.left,\n    top: rect.top - origin.top,\n  }));\n}\n\n/** The pure phase: container-local line rects to per-line {@link MarkGeometry}. No DOM reads. */\nfunction linesToGeometry(\n  locals: LineRect[],\n  options: ResolvedOptions,\n  flowReversed = false,\n  profileFor?: (local: LineRect) => LineSpeedProfile | undefined,\n): MarkGeometry[] {\n  return locals.map((local) => {\n    // An explicit `options.seed` must still yield a distinct per-line seed, else every line's\n    // pooled wrapper keys to one value and collapses onto a single node, aliasing the draw-on.\n    const seed = options.seed == null ? local.seed : hashU32(options.seed + local.seed);\n    return buildMarkGeometry(local, options, seed, flowReversed, profileFor?.(local));\n  });\n}\n\n/** Is the live selection dragged backward (focus before anchor)? Then ink pours from the right edge. Collapsed/detached read as forward. */\nfunction isSelectionBackward(selection: Selection): boolean {\n  const { anchorNode, focusNode } = selection;\n  if (selection.isCollapsed || !anchorNode || !focusNode) return false;\n  if (anchorNode === focusNode) return selection.focusOffset < selection.anchorOffset;\n  const relation = anchorNode.compareDocumentPosition(focusNode);\n  return (relation & Node.DOCUMENT_POSITION_PRECEDING) !== 0;\n}\n\n/**\n * Mount a renderer at the selected tier, wire a reflow observer, and return the\n * mark handle. Shared by all public entry points.\n *\n * @param hostOverride - Optional explicit overlay host (else derived from ranges).\n */\nfunction mountMark(\n  ranges: Range[],\n  userOptions: HighlightOptions,\n  resolved: ResolvedOptions,\n  extraCleanup: (() => void)[] = [],\n  hostOverride?: HTMLElement | null,\n  rangeSource?: () => Range[],\n): MarkHandle {\n  const host = hostOverride ?? hostFor(ranges);\n  if (!host) return inertHandle();\n\n  const container = createOverlayContainer(host);\n  const env = detectEnvironment();\n\n  // Static mark never changes; a watched page mark (`rangeSource` set) re-collects each update()\n  // so added nodes are painted and removed ones drop out.\n  let activeRanges = ranges;\n\n  // Measured container-local line rects, keyed by the snap they were built with. Local rects are\n  // scroll-invariant, so the reflow observer + range re-collection + a snap change form the complete\n  // invalidation set; an ink-only update() rebuilds geometry with zero forced layout reads.\n  let cached: { snap: SnapMode; lines: LineRect[] } | null = null;\n\n  const buildContext = (opts: ResolvedOptions): RenderContext => {\n    if (cached === null || cached.snap !== opts.snap) {\n      cached = { snap: opts.snap, lines: measureLines(snapRanges(activeRanges, opts.snap), container) };\n    }\n    const lines = linesToGeometry(cached.lines, opts);\n    return { container, options: opts, lines, ranges: activeRanges };\n  };\n\n  const initialContext = buildContext(resolved);\n  const tier = selectTier(resolved.renderer, env, initialContext.lines.length);\n  const renderer = rendererForTier(tier);\n  renderer.mount(initialContext);\n\n  // Entrance animation, one-shot on mount. The draw-on finds each line's wrapper by stable seed,\n  // never by index, so marks sharing a container don't animate each other's bands.\n  const animDisconnect = applyDrawOn(\n    container,\n    (seed) => renderer.bandFor(seed),\n    initialContext.lines,\n    resolved.animation,\n    env,\n  );\n\n  // Re-derive geometry and update the renderer without re-animating. An in-flight draw-on is\n  // retargeted onto the corrected geometry so it finishes the right shape instead of snapping.\n  const reflow = createReflowObserver(reflowTargetsFor(host, activeRanges), () => {\n    cached = null;\n    const ctx = buildContext(resolved);\n    renderer.update(ctx);\n    animDisconnect.retarget(ctx.lines);\n  });\n\n  return createMarkHandle({\n    ranges,\n    options: resolved,\n    userOptions,\n    renderer,\n    container,\n    reflow,\n    cleanup: [animDisconnect, ...extraCleanup],\n    replay: () => animDisconnect.replay(),\n    retarget: (lines) => animDisconnect.retarget(lines),\n    rebuild: (opts) => {\n      // Mutate `resolved` in place so the reflow closure above picks up the new values next build.\n      Object.assign(resolved, opts);\n      // A watched page mark re-collects here so a watcher-fired update() paints added and drops\n      // removed nodes. Reflow calls buildContext directly, so a resize never re-scans the DOM.\n      if (rangeSource) {\n        activeRanges = rangeSource();\n        cached = null;\n      }\n      return buildContext(resolved);\n    },\n  });\n}\n\n/**\n * Highlight a target: the primary entry point.\n *\n * @param target - Any {@link Target}: element, selector, `Range`, `Selection`, text query, or page target.\n * @param host - Optional positioned element to mount the overlay inside, scoping it to a transformed,\n *   scrolling, or stacked container. Promoted to `position: relative` if static. Defaults to the body.\n * @returns A {@link MarkHandle}; inert outside a DOM.\n */\nexport function highlight(\n  target: Target,\n  options?: HighlightOptions,\n  host?: HTMLElement | null,\n): MarkHandle {\n  if (!hasDom()) return inertHandle();\n\n  const userOptions: HighlightOptions = {\n    snap: defaultSnap(target),\n    ...options,\n  };\n  const resolved = resolveOptions(userOptions);\n  const ranges = toRanges(target);\n  if (ranges.length === 0) return inertHandle();\n\n  return mountMark(ranges, userOptions, resolved, [], host ?? undefined);\n}\n\n/**\n * Highlight whole-page / declarative-attribute content.\n *\n * Collects `data-highlight` elements and/or a page target (default root `document.body`), honouring\n * exclusions, and attaches a debounced `MutationObserver` so added nodes get marked and removed nodes\n * drop their marks without a full rescan. Returns one handle covering all matches.\n * @returns A {@link MarkHandle}; inert outside a DOM.\n */\nexport function highlightAll(options?: HighlightOptions): MarkHandle {\n  if (!hasDom()) return inertHandle();\n\n  const root = document.body ?? document.documentElement;\n  const userOptions: HighlightOptions = { snap: \"line\", ...options };\n  const resolved = resolveOptions(userOptions);\n\n  const collect = (): Range[] => {\n    const pageRanges = collectPageRanges({ root });\n    // Explicit data-highlight elements augment the page scan; the targeting layer drops excluded subtrees.\n    const declaredRanges: Range[] = [];\n    for (const el of root.querySelectorAll(\"[data-highlight]\")) {\n      declaredRanges.push(...toRanges(el));\n    }\n    return [...pageRanges, ...declaredRanges];\n  };\n\n  const ranges = collect();\n  if (ranges.length === 0) {\n    // Still wire the watcher so a later DOM change can produce a mark.\n    const host = root instanceof HTMLElement ? root : document.body;\n    if (!host) return inertHandle();\n    const handle = mountMark([], userOptions, resolved, [], host, collect);\n    return wrapWithWatcher(handle, root);\n  }\n\n  const handle = mountMark(ranges, userOptions, resolved, [], undefined, collect);\n  return wrapWithWatcher(handle, root);\n}\n\n/** Attach a debounced mutation watcher that re-renders on subtree changes; its disconnect folds into `remove()`. */\nfunction wrapWithWatcher(\n  handle: MarkHandle,\n  root: Element | Document,\n): MarkHandle {\n  const watcher = createMutationWatcher(root, () => {\n    handle.update({});\n  });\n\n  const baseRemove = handle.remove.bind(handle);\n  return {\n    get tier() {\n      return handle.tier;\n    },\n    show: handle.show.bind(handle),\n    hide: handle.hide.bind(handle),\n    isShowing: handle.isShowing.bind(handle),\n    update: handle.update.bind(handle),\n    remove(): void {\n      watcher();\n      baseRemove();\n    },\n  };\n}\n\n/**\n * Highlight the user's live selection in real time.\n *\n * Drives `selectionchange`-derived ranges into the same pipeline. On coarse pointers it defers to\n * native selection UI rather than painting an overlay. `remove()` detaches the listener.\n *\n * Subtrees marked `data-highlight-exclude` are carved out before painting, so a select-all never\n * bands over opted-out regions (read-only content, code blocks, and the like).\n * @returns A {@link MarkHandle}; inert outside a DOM.\n */\nexport function highlightSelection(options?: HighlightOptions): MarkHandle {\n  if (!hasDom()) return inertHandle();\n\n  const env = detectEnvironment();\n  // On touch devices native selection is the better UX: no overlay.\n  if (env.coarsePointer) return inertHandle();\n\n  // Accumulated across update() calls so options compose additively; re-spreading the\n  // construction-time options each update would revert prior ones.\n  let userOptions: HighlightOptions = { snap: \"word\", ...options };\n  let resolved = resolveOptions(userOptions);\n  // Anchor follows the selection (article/main/positioned ancestor), not a fixed body mount.\n  let currentHost: HTMLElement | null = null;\n  let container: HTMLElement | null = null;\n  let reflowDisconnect: () => void = () => {};\n  let renderer: Renderer | null = null;\n  let currentRanges: Range[] = [];\n\n  const ensureAnchor = (anchor: HTMLElement): boolean => {\n    if (anchor === currentHost && container) return false;\n    if (!container) {\n      container = createOverlayContainer(anchor);\n      currentHost = anchor;\n      return true;\n    }\n    if (anchor !== currentHost) {\n      // createOverlayContainer only promotes at creation, so re-parenting to a new host needs its\n      // own static->relative check before moving the overlay in.\n      const view = anchor.ownerDocument.defaultView;\n      if (view && view.getComputedStyle(anchor).position === \"static\") {\n        anchor.style.position = \"relative\";\n      }\n      anchor.appendChild(container);\n      currentHost = anchor;\n      return true;\n    }\n    return false;\n  };\n\n  const armReflow = (anchor: HTMLElement, ranges: Range[]): void => {\n    reflowDisconnect();\n    reflowDisconnect = createReflowObserver(reflowTargetsFor(anchor, ranges), () => {\n      if (currentRanges.length === 0) return;\n      // Observer already coalesces to rAF — paint now, not one frame later.\n      if (rafId) {\n        cancelAnimationFrame(rafId);\n        rafId = 0;\n      }\n      renderSelection();\n    });\n  };\n\n  // Speed-aware ink, live-drag only. The tracker samples focus-caret velocity during a primary\n  // fine-pointer drag and serves a per-line deposit profile. Skipped under reduced motion; gated on\n  // `speed.enabled` and `dragging` so programmatic/keyboard/instant selections build no field.\n  const tracker = env.prefersReducedMotion ? null : new SelectionVelocityTracker();\n  let dragging = false;\n  const onPointerDown = (e: PointerEvent): void => {\n    // Primary-button, fine-pointer only.\n    if (e.button !== 0 || (e.pointerType !== \"mouse\" && e.pointerType !== \"pen\")) return;\n    dragging = true;\n    tracker?.reset();\n  };\n  const endDrag = (): void => {\n    // Paint any frame still pending while the drag is \"live\" so the settled mark keeps the last\n    // sampled speed look, matching the pre-coalescing behaviour where the final event rendered sync.\n    flushRender();\n    dragging = false;\n  };\n  if (tracker) {\n    document.addEventListener(\"pointerdown\", onPointerDown, true);\n    document.addEventListener(\"pointerup\", endDrag, true);\n    document.addEventListener(\"pointercancel\", endDrag, true);\n    // A pointer released outside the window fires no pointerup, so blur clears the flag too,\n    // else it sticks true and a later non-drag selection paints with speed.\n    window.addEventListener(\"blur\", endDrag);\n  }\n\n  const rebuild = (\n    ranges: Range[],\n    flowReversed: boolean,\n    origin?: DOMRect,\n  ): RenderContext => {\n    const snapped = snapRanges(ranges, resolved.snap);\n    // Speed profile only while a drag actively feeds the tracker; gating on `dragging` stops a\n    // post-release selection from reusing a finished gesture's stale samples. The look persists\n    // after release because nothing repaints until the next gesture.\n    const speedOn = tracker !== null && resolved.speed.enabled && dragging;\n    const profileFor = speedOn\n      ? (local: LineRect): LineSpeedProfile | undefined =>\n          tracker!.profileForLine(\n            { top: local.top, height: local.height, left: local.left, width: local.width },\n            resolved.speed,\n          )\n      : undefined;\n    const lines = linesToGeometry(\n      measureLines(snapped, container!, origin, currentHost ?? undefined),\n      resolved,\n      flowReversed,\n      profileFor,\n    );\n    return { container: container!, options: resolved, lines, ranges };\n  };\n\n  // Clear-fade: when the selection empties, fade the overlay out then drop the bands; re-selecting cancels it.\n  const CLEAR_FADE_MS = 200;\n  let clearTimer: ReturnType<typeof setTimeout> | null = null;\n  const cancelClearFade = (): void => {\n    if (clearTimer !== null) {\n      clearTimeout(clearTimer);\n      clearTimer = null;\n    }\n    // Transition off first so resetting opacity is instant, not a fade back.\n    if (container) {\n      container.style.transition = \"\";\n      container.style.opacity = \"\";\n    }\n  };\n\n  // Sample the focus-caret velocity on EVERY selectionchange (cheap; the field's fidelity depends\n  // on per-event sampling), but coalesce the expensive geometry+paint into one rAF per frame. Each\n  // frame still reads the latest selection, so intermediate states that would be overwritten anyway\n  // are skipped rather than drawn.\n  const sample = (): void => {\n    if (!tracker || !dragging || !resolved.speed.enabled) return;\n    // sample() runs on selectionchange, before the rAF render's ensureAnchor creates the container.\n    if (!container) return;\n    const selection = document.getSelection();\n    if (!selection || selection.isCollapsed) return;\n    // Same container-local px space measureLines projects into, so the lookup is exact during the drag.\n    const origin = container.getBoundingClientRect();\n    tracker.recordSample(\n      selection,\n      origin.left,\n      origin.top,\n      performance.now(),\n      resolved.speed.smoothing,\n    );\n  };\n\n  const renderSelection = (): void => {\n    const selection = document.getSelection();\n    const ranges: Range[] = [];\n    // A backward drag (focus before anchor) pours its ink from the right edge.\n    let flowReversed = false;\n    if (selection && !selection.isCollapsed) {\n      flowReversed = isSelectionBackward(selection);\n      for (let i = 0; i < selection.rangeCount; i++) {\n        ranges.push(selection.getRangeAt(i).cloneRange());\n      }\n    }\n    // Carve out any data-highlight-exclude subtree before painting: range geometry covers\n    // user-select:none text too, so a select-all would otherwise band over opted-out regions.\n    const painted = excludeMarkedSubtrees(ranges);\n\n    // Selection just emptied: fade out, then drop the bands when the fade lands (instant clear if disabled/reduced-motion).\n    const cleared = painted.length === 0 && currentRanges.length > 0;\n    currentRanges = painted;\n    if (cleared && resolved.fadeOnClear && renderer && !env.prefersReducedMotion) {\n      container!.style.transition = `opacity ${CLEAR_FADE_MS}ms ease-out`;\n      container!.style.opacity = \"0\";\n      clearTimer = setTimeout(() => {\n        clearTimer = null;\n        // remove() may have nulled the container after this timer was queued (clearTimeout no-ops once enqueued).\n        if (!container) return;\n        renderer?.update(rebuild([], false));\n        container.style.transition = \"\";\n        container.style.opacity = \"\";\n      }, CLEAR_FADE_MS);\n      return;\n    }\n    cancelClearFade();\n\n    if (painted.length > 0) {\n      const anchor = findSelectionAnchor(painted[0].commonAncestorContainer);\n      if (ensureAnchor(anchor)) armReflow(anchor, painted);\n    }\n\n    if (!container) return;\n\n    // One layout read per frame, shared by every line's build.\n    const origin = container.getBoundingClientRect();\n    const context = rebuild(painted, flowReversed, origin);\n    if (!renderer) {\n      const tier = selectTier(resolved.renderer, env, context.lines.length);\n      renderer = rendererForTier(tier);\n      renderer.mount(context);\n    } else {\n      renderer.update(context);\n    }\n  };\n\n  let rafId = 0;\n  const scheduleRender = (): void => {\n    if (rafId) return;\n    rafId = requestAnimationFrame(() => {\n      rafId = 0;\n      renderSelection();\n    });\n  };\n  // Flush a pending coalesced frame synchronously (e.g. on drag-settle), so the final selection is\n  // painted now rather than a frame later, while `dragging` is still true and the speed look holds.\n  const flushRender = (): void => {\n    if (!rafId) return;\n    cancelAnimationFrame(rafId);\n    rafId = 0;\n    renderSelection();\n  };\n\n  const onSelectionChange = (): void => {\n    sample();\n    scheduleRender();\n  };\n  document.addEventListener(\"selectionchange\", onSelectionChange);\n  renderSelection();\n\n  let showing = true;\n  let removed = false;\n  return {\n    get tier() {\n      return renderer?.tier ?? \"css\";\n    },\n    show(): void {\n      if (removed) return;\n      showing = true;\n      if (container) container.style.visibility = \"\";\n    },\n    hide(): void {\n      if (removed) return;\n      showing = false;\n      if (container) container.style.visibility = \"hidden\";\n    },\n    isShowing(): boolean {\n      return showing && !removed && currentRanges.length > 0;\n    },\n    update(opts: Partial<HighlightOptions>): void {\n      if (removed) return;\n      userOptions = mergeOptions(userOptions, opts as HighlightOptions);\n      resolved = resolveOptions(userOptions);\n      // An option change renders synchronously; drop any pending coalesced frame (same selection).\n      if (rafId) {\n        cancelAnimationFrame(rafId);\n        rafId = 0;\n      }\n      renderSelection();\n    },\n    remove(): void {\n      if (removed) return;\n      removed = true;\n      showing = false;\n      if (rafId) cancelAnimationFrame(rafId);\n      if (clearTimer !== null) clearTimeout(clearTimer);\n      reflowDisconnect();\n      document.removeEventListener(\"selectionchange\", onSelectionChange);\n      if (tracker) {\n        document.removeEventListener(\"pointerdown\", onPointerDown, true);\n        document.removeEventListener(\"pointerup\", endDrag, true);\n        document.removeEventListener(\"pointercancel\", endDrag, true);\n        window.removeEventListener(\"blur\", endDrag);\n        tracker.reset();\n      }\n      renderer?.unmount();\n      renderer = null;\n      if (container) {\n        teardownContainer(container);\n        container = null;\n        currentHost = null;\n      }\n    },\n  };\n}\n\n/**\n * Bundle handles into a {@link GroupHandle} for sequential show/hide choreography. `show()`\n * reveals members in array order so their draw-on staggers like a pen down the page.\n * @param handles - The member handles, in choreography order.\n */\nexport function group(handles: MarkHandle[]): GroupHandle {\n  const marks = [...handles];\n  return {\n    get marks(): MarkHandle[] {\n      return marks;\n    },\n    show(): void {\n      for (const handle of marks) handle.show();\n    },\n    hide(): void {\n      for (const handle of marks) handle.hide();\n    },\n    remove(): void {\n      for (const handle of marks) handle.remove();\n    },\n  };\n}\n"],"mappings":"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","names":["node","defs","highlight","handle"]}