diff --git a/src/components/Canvas/LineObject.tsx b/src/components/Canvas/LineObject.tsx
index e39bb987..50f3b9f2 100644
--- a/src/components/Canvas/LineObject.tsx
+++ b/src/components/Canvas/LineObject.tsx
@@ -14,6 +14,56 @@ import { selectionHandlers, type KonvaObjectProps } from "./konvaObjectProps";
const HANDLE_VISIBLE_SIZE = 7;
const HANDLE_HIT_SIZE = 14;
+/**
+ * Selection outline for a line — two parallel selection-coloured strokes
+ * offset perpendicular to the body. Drawing alongside (not on top) keeps
+ * the body's difference-blend intact for reverse (^LRY) lines and matches
+ * the Illustrator-style stroke selection affordance. Returns null for
+ * zero-length lines (degenerate input).
+ *
+ * Offset breakdown for a 1 px visual gap between body and selection edges:
+ * bodyStrokeWidth / 2 — half of the body (centre → body edge)
+ * 0.5 — half of the 1 px selection stroke
+ * (centre → selection's body-side edge)
+ * 1 — actual gap requested between the two adjacent
+ * edges
+ */
+function LineSelectionOutline({
+ x1, y1, x2, y2,
+ bodyStrokeWidth,
+ color,
+}: {
+ x1: number; y1: number; x2: number; y2: number;
+ bodyStrokeWidth: number;
+ color: string;
+}) {
+ const dx = x2 - x1;
+ const dy = y2 - y1;
+ const len = Math.hypot(dx, dy);
+ if (len === 0) return null;
+ const off = bodyStrokeWidth / 2 + 1.5;
+ const px = (-dy / len) * off;
+ const py = (dx / len) * off;
+ return (
+ <>
+
+
+ >
+ );
+}
+
type LineLabelObject = Extract;
type Props = Omit & { obj: LineLabelObject };
@@ -217,12 +267,13 @@ export function LineObject({
globalCompositeOperation={isReverse ? "difference" : "source-over"}
/>
{isSelected && (
-
)}
{/* Wide transparent hit area — handles click-to-select and whole-line drag.