@seatlayer/core 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -11,12 +11,44 @@ interface Point {
11
11
  x: number;
12
12
  y: number;
13
13
  }
14
+ interface CubicPath {
15
+ start: Point;
16
+ control1: Point;
17
+ control2: Point;
18
+ end: Point;
19
+ }
20
+ /** A real closed section boundary. `outline` remains its sampled collision and
21
+ * persistence fallback; this path is the smooth authoring/buyer paint source. */
22
+ type SectionPathSegment = {
23
+ kind: 'line';
24
+ end: Point;
25
+ } | {
26
+ kind: 'arc';
27
+ center: Point;
28
+ radius: number;
29
+ clockwise: boolean;
30
+ end: Point;
31
+ } | {
32
+ kind: 'bezier';
33
+ control1: Point;
34
+ control2: Point;
35
+ end: Point;
36
+ };
37
+ interface SectionOutlinePath {
38
+ version: 1;
39
+ closed: true;
40
+ start: Point;
41
+ segments: SectionPathSegment[];
42
+ }
14
43
  interface Category {
15
44
  key: string;
16
45
  label: string;
17
46
  color: string;
18
47
  /** Base price — used when the category has no explicit tiers. */
19
48
  price?: number;
49
+ /** Durable evidence for semantic/display facts proposed while converting a
50
+ * private reference into sellable inventory. */
51
+ referenceCategorySource?: ReferenceCategorySource;
20
52
  /**
21
53
  * Ticket tiers (Adult / Child / Senior…). When present, a buyer picks a tier
22
54
  * per seat in this category and the tier's price applies; the first tier is the
@@ -25,6 +57,33 @@ interface Category {
25
57
  */
26
58
  tiers?: CategoryTier[];
27
59
  }
60
+ interface ReferenceCategorySource {
61
+ assetId: string;
62
+ /** Original sampled section color. `Category.color` is the approved output
63
+ * color and may differ only with separately recorded evidence. */
64
+ sourceColor: string;
65
+ /** Every exact sampled color normalized into the same original 4-bit/channel
66
+ * segmentation class. Older documents may contain only `sourceColor`. */
67
+ sourceColors?: string[];
68
+ /** Logical sections whose generated inventory uses this category. */
69
+ logicalSectionIds?: string[];
70
+ /** Source-color grouping is deterministic; a semantic regrouping needs its
71
+ * own confirmed assignment evidence. */
72
+ assignmentDerivation?: 'source-color-class' | 'confirmed-logical-sections';
73
+ assignmentEvidence?: 'user-confirmed' | 'authoritative-source';
74
+ assignmentSourceDescription?: string;
75
+ /** Optional legend/commercial swatch stated by the source. This remains
76
+ * immutable provenance when the approved accessible output color differs. */
77
+ sourcePaletteColor?: string;
78
+ sourcePaletteColorEvidence?: 'user-confirmed' | 'authoritative-source';
79
+ sourcePaletteColorSourceDescription?: string;
80
+ labelEvidence: 'user-confirmed' | 'authoritative-source';
81
+ labelSourceDescription: string;
82
+ priceEvidence: 'user-confirmed' | 'authoritative-source';
83
+ priceSourceDescription: string;
84
+ outputColorEvidence?: 'user-confirmed' | 'authoritative-source';
85
+ outputColorSourceDescription?: string;
86
+ }
28
87
  /** One ticket tier within a category: a named price (Adult, Child, Senior…). */
29
88
  interface CategoryTier {
30
89
  id: string;
@@ -111,7 +170,14 @@ interface RowObject {
111
170
  seatCount: number;
112
171
  /** Distance between adjacent seat centers, in chart units. */
113
172
  seatSpacing: number;
173
+ /** Optional exact cubic centreline. Normal code owns these coordinates and
174
+ * distributes seats by arc length; MCP/model inputs never submit them. */
175
+ path?: CubicPath;
114
176
  categoryKey: string;
177
+ /** Deterministic provenance for rows fitted from confirmed reference
178
+ * inventory. It enables revision-safe replacement without touching manually
179
+ * authored rows or accepting client coordinates. */
180
+ referenceInventorySource?: ReferenceInventorySource;
115
181
  /** First seat number (default 1). */
116
182
  seatLabelStart?: number;
117
183
  /** Seat numbering within the row (default ltr, step 1). */
@@ -141,8 +207,59 @@ interface GAAreaObject {
141
207
  label: string;
142
208
  /** Closed polygon, in chart units. */
143
209
  points: Point[];
210
+ /** Explicit aisles/pillars/cutouts excluded from the sellable GA surface. */
211
+ holes?: Point[][];
144
212
  capacity: number;
145
213
  categoryKey: string;
214
+ referenceInventorySource?: ReferenceInventorySource;
215
+ }
216
+ /**
217
+ * Durable evidence link for sellable objects generated from a private reference.
218
+ * The client supplies facts and stable logical-section ids, never coordinates.
219
+ */
220
+ interface ReferenceAccessibilitySource {
221
+ placementDerivation: 'server-synthesized-row-edges';
222
+ groupLogicalSectionIds: string[];
223
+ assignmentEvidence: 'user-confirmed' | 'authoritative-source';
224
+ assignmentSourceDescription: string;
225
+ counts: Array<{
226
+ type: AccessibilityType;
227
+ count: number;
228
+ evidence: 'user-confirmed' | 'authoritative-source';
229
+ sourceDescription: string;
230
+ }>;
231
+ }
232
+ interface ReferenceInventorySource {
233
+ assetId: string;
234
+ logicalSectionId: string;
235
+ evidence: 'user-confirmed' | 'authoritative-source';
236
+ sourceDescription: string;
237
+ /** Distinguishes directly supplied inventory from a user-approved server
238
+ * distribution based only on an aggregate capacity. */
239
+ derivation?: 'explicit-inventory' | 'server-synthesized-from-aggregate';
240
+ /** Evidence for the aggregate figure; synthesized rows remain
241
+ * `user-confirmed` and are never mislabeled as source-extracted. */
242
+ aggregateEvidence?: 'user-confirmed' | 'authoritative-source';
243
+ /** Separate evidence for assigning standing inventory to this logical
244
+ * section. Aggregate evidence alone cannot prove section placement. */
245
+ sectionAssignmentEvidence?: 'user-confirmed' | 'authoritative-source';
246
+ sectionAssignmentSourceDescription?: string;
247
+ /** Aggregate row synthesis may propose numbering, but persistence requires
248
+ * the applying user/agent to confirm that policy explicitly. */
249
+ numberingEvidence?: 'user-confirmed';
250
+ numberingSourceDescription?: string;
251
+ /** Evidence and deterministic placement contract for synthesized accessible
252
+ * units in this logical section. */
253
+ accessibility?: ReferenceAccessibilitySource;
254
+ }
255
+ /** Durable evidence that a visible source-backed section shell intentionally
256
+ * carries no generated sellable inventory in this reference configuration. */
257
+ interface ReferenceInventoryExclusionSource {
258
+ assetId: string;
259
+ logicalSectionId: string;
260
+ reason: string;
261
+ evidence: 'user-confirmed' | 'authoritative-source';
262
+ sourceDescription: string;
146
263
  }
147
264
  /** Non-bookable décor: stage, walls, exits. */
148
265
  interface ShapeObject {
@@ -198,6 +315,7 @@ interface TableObject {
198
315
  categoryKey: string;
199
316
  /** Whole-table booking: buyers get all seats or none (per-event override later). */
200
317
  bookAsWhole?: boolean;
318
+ referenceInventorySource?: ReferenceInventorySource;
201
319
  }
202
320
  /** A booth: one bookable unit rendered as a block (trade shows, VIP boxes). */
203
321
  interface BoothObject {
@@ -209,6 +327,7 @@ interface BoothObject {
209
327
  height: number;
210
328
  rotation: number;
211
329
  categoryKey: string;
330
+ referenceInventorySource?: ReferenceInventorySource;
212
331
  }
213
332
  /**
214
333
  * A named region of the venue (Balcony Left, Floor B…). Sections are outlines
@@ -221,8 +340,40 @@ interface SectionObject {
221
340
  type: 'section';
222
341
  id: string;
223
342
  label: string;
343
+ /**
344
+ * Stable management/inventory identity shared by disconnected visual
345
+ * components of one logical section. When absent, `id` is the logical id.
346
+ * Each component keeps its own `id` and reference provenance so rendering,
347
+ * editing, measured diffs, and source restoration remain exact.
348
+ */
349
+ logicalSectionId?: string;
224
350
  /** Closed polygon, chart units. */
225
351
  outline: Point[];
352
+ /** Optional true line/arc/cubic boundary. `outline` is a deterministic sample
353
+ * of this path and remains authoritative for membership, validation, and
354
+ * clients that predate curved section rendering. */
355
+ outlinePath?: SectionOutlinePath;
356
+ /** Explicit aisle/cutout polygons excluded from rendering, hit-testing, and membership. */
357
+ holes?: Point[][];
358
+ /** Durable opaque link to the private reference component. Unlike generator
359
+ * provenance, this survives manual geometry edits so a measured diff can
360
+ * report drift and server-owned code can restore the source contour. */
361
+ referenceSource?: {
362
+ assetId: string;
363
+ regionId: string;
364
+ };
365
+ /** Evidence-backed reason this source section remains a visible shell without
366
+ * synthesized sellable inventory (press, closed technical zone, etc.). */
367
+ referenceInventoryExclusion?: ReferenceInventoryExclusionSource;
368
+ /** Deterministic generator provenance for editable reference/parametric shells. */
369
+ geometry?: {
370
+ kind: 'rectangle' | 'tapered' | 'bezier' | 'contour';
371
+ sourceRegionId?: string;
372
+ contourMethod?: 'pixel-edge-loops-rdp' | 'shared-edge-vector-fit-v1';
373
+ simplificationTolerancePx?: number;
374
+ vectorFitErrorPx?: number;
375
+ sharedEdgeCount?: number;
376
+ };
226
377
  /** Optional tint override (defaults to a neutral fill / dominant category mix). */
227
378
  color?: string;
228
379
  /** Zone this section belongs to (id into `ChartDoc.zones`). Far-zoom nav + pricing group. */
@@ -306,6 +457,53 @@ interface Floor {
306
457
  focalPoint: Point;
307
458
  backgroundImage?: ChartDoc['backgroundImage'];
308
459
  }
460
+ interface ReferenceCalibration {
461
+ type: 'two-point';
462
+ /** Points in immutable source-image pixels, selected by a human or trusted detector. */
463
+ sourceA: Point;
464
+ sourceB: Point;
465
+ /** Verified real-world distance between the two source points. */
466
+ distance: number;
467
+ unit: 'm' | 'ft' | 'chart-unit';
468
+ /** Derived and stored for deterministic geometry compilers. */
469
+ pixelsPerUnit: number;
470
+ }
471
+ /** Coordinate-free physical scale derived by server code from a confirmed
472
+ * semantic feature. Unlike manual two-point calibration, no source points pass
473
+ * through an MCP client or language model. */
474
+ interface ReferenceDerivedScale {
475
+ method: 'confirmed-focal-axis-v1';
476
+ feature: 'focal-long-axis' | 'focal-short-axis';
477
+ distance: number;
478
+ unit: 'm' | 'ft';
479
+ evidence: 'user-confirmed' | 'authoritative-source';
480
+ sourceDescription: string;
481
+ chartUnitsPerUnit: number;
482
+ }
483
+ interface ChartReferenceImage {
484
+ /** Stable private reference asset. New cloud-authored charts use this. */
485
+ assetId?: string;
486
+ /** Legacy/self-contained source. Optional when assetId is present. */
487
+ url?: string;
488
+ center: Point;
489
+ /** Rendered width in chart units (height follows the cropped image aspect). */
490
+ width: number;
491
+ opacity: number;
492
+ rotation?: number;
493
+ visible?: boolean;
494
+ layer?: 'below' | 'above';
495
+ locked?: boolean;
496
+ /** Normalized source crop; defaults to the full image. */
497
+ crop?: {
498
+ x: number;
499
+ y: number;
500
+ width: number;
501
+ height: number;
502
+ };
503
+ calibration?: ReferenceCalibration;
504
+ /** Server-derived semantic calibration without source-image coordinates. */
505
+ derivedScale?: ReferenceDerivedScale;
506
+ }
309
507
  interface ChartDoc {
310
508
  version: 1;
311
509
  name: string;
@@ -322,14 +520,7 @@ interface ChartDoc {
322
520
  floors?: Floor[];
323
521
  objects: ChartObject[];
324
522
  /** Floor-plan photo the organizer traces over (designer-only aid, also rendered dimly in picker if kept). */
325
- backgroundImage?: {
326
- url: string;
327
- center: Point;
328
- /** Rendered width in chart units (height follows the image aspect). */
329
- width: number;
330
- opacity: number;
331
- locked?: boolean;
332
- };
523
+ backgroundImage?: ChartReferenceImage;
333
524
  /** Brand/venue theming (colors); categories carry their own colors separately. */
334
525
  theme?: ChartTheme;
335
526
  /** Parametric-template provenance: present ⇒ the chart came from a capacity-
@@ -427,6 +618,130 @@ interface RendererOptions extends RendererCallbacks {
427
618
  */
428
619
  marqueeSelect?: boolean;
429
620
  }
621
+ type RenderedLabelHiddenReason = 'below-minimum-size' | 'outside-viewport' | 'dimmed-or-unavailable' | 'clutter-or-fit' | 'renderer-hidden';
622
+ /** Browser-renderer evidence used by visual QA and catalog release gates. */
623
+ interface RenderedBookableLabelEvidence {
624
+ seatId: string;
625
+ label: string;
626
+ kind: 'seat' | 'booth';
627
+ categoryKey: string;
628
+ sectionId?: string;
629
+ zoneId?: string;
630
+ status: SeatStatus;
631
+ selected: boolean;
632
+ visible: boolean;
633
+ renderedFontPx: number;
634
+ fill: string;
635
+ ink: string;
636
+ opacity: number;
637
+ /** Direct Konva shape bounds and the production near-miss rescue combined. */
638
+ pointerTarget: {
639
+ active: boolean;
640
+ directWidthPx: number;
641
+ directHeightPx: number;
642
+ effectiveMinimumPx: number;
643
+ };
644
+ /** Centre of the painted unit, even when its text is intentionally hidden. */
645
+ screenCenter: {
646
+ x: number;
647
+ y: number;
648
+ };
649
+ screenBox?: {
650
+ x: number;
651
+ y: number;
652
+ width: number;
653
+ height: number;
654
+ };
655
+ hiddenReason?: RenderedLabelHiddenReason;
656
+ }
657
+ interface RenderedHierarchyLabelEvidence {
658
+ id: string;
659
+ kind: 'section' | 'zone';
660
+ role: 'name' | 'availability' | 'price';
661
+ label: string;
662
+ visible: boolean;
663
+ renderedFontPx: number;
664
+ opacity: number;
665
+ fill: string;
666
+ ink: string;
667
+ /** Independent geometric containment check for section-owned text. */
668
+ fitsContainer?: boolean;
669
+ screenBox?: {
670
+ x: number;
671
+ y: number;
672
+ width: number;
673
+ height: number;
674
+ };
675
+ }
676
+ interface RenderedFreeTextEvidence {
677
+ objectId: string;
678
+ kind: 'free-text' | 'stage' | 'table' | 'decor' | 'ga-label' | 'ga-capacity';
679
+ text: string;
680
+ visible: boolean;
681
+ renderedFontPx: number;
682
+ ink: string;
683
+ background: string;
684
+ opacity: number;
685
+ screenBox?: {
686
+ x: number;
687
+ y: number;
688
+ width: number;
689
+ height: number;
690
+ };
691
+ hiddenReason?: 'below-minimum-size' | 'outside-viewport' | 'renderer-hidden';
692
+ }
693
+ interface RenderedGAAreaEvidence {
694
+ areaId: string;
695
+ label: string;
696
+ capacity: number;
697
+ categoryKey: string;
698
+ /** Owning logical section when the rendered GA surface is section-contained. */
699
+ sectionId?: string;
700
+ visible: boolean;
701
+ interactive: boolean;
702
+ opacity: number;
703
+ fill: string;
704
+ effectiveBackground: string;
705
+ screenBox?: {
706
+ x: number;
707
+ y: number;
708
+ width: number;
709
+ height: number;
710
+ };
711
+ }
712
+ interface RendererQualityEvidence {
713
+ viewport: {
714
+ width: number;
715
+ height: number;
716
+ };
717
+ canvasBackground: string;
718
+ effectiveScale: number;
719
+ rung: LodRung;
720
+ minimumVisibleLabelPx: number;
721
+ totalLabelledBookableUnits: number;
722
+ visibleLabels: number;
723
+ hiddenLabels: number;
724
+ /** Seats/table-seats/booths plus the full GA capacity. */
725
+ totalBookableUnits: number;
726
+ selectionRingSeatIds: string[];
727
+ selectionRingColor: string;
728
+ focusedSectionId: string | null;
729
+ focusBackdropVisible: boolean;
730
+ categoryFilterKeys: string[] | null;
731
+ /** Exact scene-graph proof for the clean section-first overview contract. */
732
+ overviewStyle: {
733
+ visibleSectionShells: number;
734
+ categoryPaintedSectionShells: number;
735
+ visibleCategoryDetailOutlines: number;
736
+ visibleSectionRowHints: number;
737
+ visibleSectionAvailabilityLabels: number;
738
+ visibleSectionGADetails: number;
739
+ };
740
+ labels: RenderedBookableLabelEvidence[];
741
+ gaAreas: RenderedGAAreaEvidence[];
742
+ hierarchyLabels: RenderedHierarchyLabelEvidence[];
743
+ freeTextLabels: RenderedFreeTextEvidence[];
744
+ }
430
745
  interface ISeatmapRenderer {
431
746
  /** Replace the chart. Resets selection and statuses, zooms to fit.
432
747
  * `opts.floorId` picks which floor to render on a multi-floor chart (Batch 5). */
@@ -492,6 +807,8 @@ interface ISeatmapRenderer {
492
807
  */
493
808
  selectAllSelectable?(): ExpandedSeat[];
494
809
  selectByLabels?(labels: string[]): ExpandedSeat[];
810
+ /** Exact-render QA only: select one server-chosen unit without label ambiguity. */
811
+ setEvidenceSelection?(seatId: string): boolean;
495
812
  /** Selectable seats belonging to a section OR zone id (no selection side-effect). */
496
813
  getSelectableInSection?(sectionId: string): ExpandedSeat[];
497
814
  /** Programmatic deselect of specific seats (e.g. chip × in the cart). */
@@ -502,13 +819,21 @@ interface ISeatmapRenderer {
502
819
  * delta. Purely visual; no state change. `color` overrides the default.
503
820
  */
504
821
  flashSeat(seatId: string, color?: string): void;
822
+ /**
823
+ * Brief organizer attention pulse around a whole section. This is a visual
824
+ * overlay only: it never changes section geometry, hit targets, selection, or
825
+ * the active camera. Useful for grouped realtime operations at venue overview.
826
+ */
827
+ flashSection?(sectionId: string, color?: string): void;
505
828
  zoomToFit(): void;
506
829
  /** Zoom in one step about the viewport center, clamped to the usual zoom bounds. */
507
830
  zoomIn(): void;
508
831
  /** Zoom out one step about the viewport center, clamped to the usual zoom bounds. */
509
832
  zoomOut(): void;
510
- /** Total seat count of the current chart. */
833
+ /** Individually status-managed seats/table-seats/booths; excludes GA capacity. */
511
834
  seatCount(): number;
835
+ /** Seats/table-seats/booths plus the full capacity of rendered GA areas. */
836
+ bookableCount(): number;
512
837
  /**
513
838
  * Maps a chart-space point (or a seat, by its x/y) to container-relative
514
839
  * screen pixels, using the current stage scale/position. Lets host UI anchor
@@ -616,6 +941,9 @@ interface ISeatmapRenderer {
616
941
  getRung?(): LodRung;
617
942
  /** Jump the camera to a rung's zoom band, centred on the chart (glided). */
618
943
  setRung?(rung: LodRung): void;
944
+ /** Read actual browser-rendered label visibility, size, fill, ink and state.
945
+ * Pure diagnostic: it never changes chart or renderer state. */
946
+ getRenderedQualityEvidence(): RendererQualityEvidence;
619
947
  destroy(): void;
620
948
  }
621
949
  /** localStorage key the Designer writes and the Picker reads. */
@@ -656,6 +984,9 @@ declare function expandTable(t: TableObject): ExpandedSeat[];
656
984
  declare function expandBooth(b: BoothObject): ExpandedSeat[];
657
985
  /** Ray-cast point-in-polygon test — odd crossings ⇒ inside. */
658
986
  declare function pointInPolygon(p: Point, poly: Point[]): boolean;
987
+ declare function pointInPolygonWithHoles(p: Point, outer: Point[], holes: Point[][] | undefined): boolean;
988
+ /** Stable interior label anchor that cannot land inside a polygon cutout. */
989
+ declare function polygonLabelPoint(outer: Point[], holes: Point[][] | undefined): Point;
659
990
  /**
660
991
  * Visual centre of any object — used for spatial section membership and for
661
992
  * rotating an object about its centre. Rows: centroid of expanded seats (or
@@ -801,11 +1132,21 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
801
1132
  private circleById;
802
1133
  /** Booth block geometry, keyed by booth id (= the unit's rowId). */
803
1134
  private boothDims;
804
- /** Booth label node so status changes can say HELD/SOLD on the full block. */
1135
+ /** Booth labels live with the booth shape but obey the shared rendered-size LOD. */
805
1136
  private boothLabelById;
1137
+ /** Viewport seat labels are rebuilt after each settled camera change. */
1138
+ private seatLabelById;
1139
+ /** Authored free-text nodes obey the same rendered-size visibility floor. */
1140
+ private freeTextById;
1141
+ /** Stage/rink landmarks retain a readable screen-space caption at overview. */
1142
+ private primaryFocalLabels;
1143
+ /** GA paint and text share price/highlight filter state. */
1144
+ private gaById;
806
1145
  private statusById;
807
1146
  private catColor;
808
1147
  private theme;
1148
+ /** Opaque paint actually visible behind transparent Konva canvases. */
1149
+ private canvasBackground;
809
1150
  /** Effective selection/hover ring color — resolved per chart in setChart(). */
810
1151
  private effSelection;
811
1152
  /** Colorblind-safe mode (Okabe-Ito hues + hollow booked seats). */
@@ -941,6 +1282,9 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
941
1282
  /** Select the selectable seats matching these public labels (category/row/
942
1283
  * section bulk resolves to labels host-side). Returns the newly added seats. */
943
1284
  selectByLabels(labels: string[]): ExpandedSeat[];
1285
+ /** Exact SDK capture helper. MCP never accepts this id; the SDK derives it
1286
+ * from the persisted floor and uses the normal selected paint/ring path. */
1287
+ setEvidenceSelection(seatId: string): boolean;
944
1288
  /** Selectable seats in a section OR zone id — pure read (no selection change). */
945
1289
  getSelectableInSection(sectionId: string): ExpandedSeat[];
946
1290
  /**
@@ -961,6 +1305,12 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
961
1305
  */
962
1306
  private finishMarquee;
963
1307
  flashSeat(seatId: string, color?: string): void;
1308
+ /**
1309
+ * Pulse a section outline without moving the camera or mutating the authored
1310
+ * geometry. The temporary halo is drawn in the non-listening overlay layer,
1311
+ * so the apparent 4% lift never changes hit testing or selection bounds.
1312
+ */
1313
+ flashSection(sectionId: string, color?: string): void;
964
1314
  private onKeyDown;
965
1315
  /** Nearest seat from `fromId` in a cardinal direction (aligned + close wins). */
966
1316
  private nearestSeat;
@@ -973,6 +1323,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
973
1323
  zoomIn(): void;
974
1324
  zoomOut(): void;
975
1325
  seatCount(): number;
1326
+ bookableCount(): number;
976
1327
  worldToScreen(point: Point): {
977
1328
  x: number;
978
1329
  y: number;
@@ -986,6 +1337,10 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
986
1337
  * widget resolves which categories fall inside the buyer's chosen band.
987
1338
  */
988
1339
  setCategoryFilter(keys: string[] | null): void;
1340
+ private gaCategoryDimmed;
1341
+ /** Keep GA paint and its two labels in the same legend/price-filter state. */
1342
+ private applyGAFilterState;
1343
+ private paintGAStateForView;
989
1344
  /** Frame the currently available inventory that survived a buyer price
990
1345
  * filter. Clearing the filter glides back to the full venue. */
991
1346
  focusCategories(keys: string[] | null): void;
@@ -1039,6 +1394,9 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1039
1394
  private renderBoothUnit;
1040
1395
  /** The category's display color — Okabe-Ito hue when colorblind-safe is on. */
1041
1396
  private seatBaseColor;
1397
+ /** Authored free fills retain the chart's validated ink. Renderer-owned
1398
+ * transient fills choose an ink against the paint that is actually visible. */
1399
+ private renderedBookableLabelInk;
1042
1400
  /** Apply fill/stroke/opacity for a seat's current status + selection. */
1043
1401
  private paintSeat;
1044
1402
  /** True when a seat sits in a section/zone currently marked `closed`. */
@@ -1081,7 +1439,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1081
1439
  width: number;
1082
1440
  height: number;
1083
1441
  };
1084
- /** Axis-aligned world bounds of all seats + section outlines (minimap F3 frame). */
1442
+ /** Axis-aligned world bounds of seats, section outlines, and GA polygons (minimap F3 frame). */
1085
1443
  getWorldBounds(): {
1086
1444
  x: number;
1087
1445
  y: number;
@@ -1110,22 +1468,18 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1110
1468
  /**
1111
1469
  * A section renders in three coordinated layers driven by the LOD melt:
1112
1470
  * • a faint outline (the existing near-zoom look, untouched),
1113
- * • a solid category-mix block that fades in at the block rung, and
1114
- * • a name + "N LEFT" sublabel.
1115
- * Membership (which seats live inside the outline) + the mix fill + the live
1116
- * availability count are precomputed here (once), not per frame.
1471
+ * • a neutral solid shell that fades in at the overview rung, and
1472
+ * • one readable, contained section name.
1473
+ * Category, row, seat, and availability detail belongs to section focus/zoom.
1474
+ * Membership and category mix are still precomputed for the detailed state.
1117
1475
  */
1118
1476
  private renderSection;
1119
1477
  private refreshSectionHeat;
1120
- /** Recompute a section's availability-tinted fill + "N LEFT" (cheap; on status change). */
1478
+ /** Recompute a section's neutral overview state and retained detail count. */
1121
1479
  private refreshSectionFill;
1122
1480
  /** True when a section/zone is currently in the `closed` event-state. */
1123
1481
  private isSectionClosed;
1124
- /**
1125
- * The block-fill colour for a section: flat desaturated grey when `closed`,
1126
- * else the availability-darkened category mix; then desaturated toward neutral
1127
- * when another section holds focus (AXS dim treatment).
1128
- */
1482
+ /** Clean overview shells never leak category, price, or live availability paint. */
1129
1483
  private sectionBlockFill;
1130
1484
  /**
1131
1485
  * Zone rung: one giant screen-constant label per zone (+ optional "FROM $n"),
@@ -1143,17 +1497,19 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1143
1497
  * Section/zone labels are scale-compensated to hold a roughly constant screen size.
1144
1498
  */
1145
1499
  private applySectionLod;
1500
+ /** One semantic section gets one overview label, even across split contours. */
1501
+ private dedupeLogicalSectionLabels;
1146
1502
  /**
1147
- * Greedy label de-collision for the zone/section rungs (same approach as the
1148
- * designer's cullRowLabels): price/"N LEFT" sublabels are lowest priority and
1149
- * drop first; name labels keep top-to-bottom, left-to-right; anything whose
1150
- * on-screen box (+4px gap) overlaps an already-kept box hides. Recomputed on
1151
- * every LOD pass so hidden labels reappear as zoom spreads them apart.
1152
- * Culling multiplies the opacity applySectionLod just assigned (never raises).
1503
+ * Keep transitional zone pills from covering section names. Section names
1504
+ * are already proven inside disjoint shells, so they must not cull each other.
1153
1505
  */
1154
1506
  private decollideRungLabels;
1155
1507
  /** Set a centred label's world fontSize (for a target screen px) and re-anchor it. */
1156
1508
  private sizeLabel;
1509
+ /** Fit one centred section name, rotating narrow shells like the target chart. */
1510
+ private fitSectionRungLabels;
1511
+ /** Size one screen-constant zone name/price pill around its shared anchor. */
1512
+ private sizeZonePill;
1157
1513
  /**
1158
1514
  * Map a container-relative screen point back to world coords. Inverts the
1159
1515
  * stage (scale/pos) and, in iso view, the iso affine — so screen-space taps
@@ -1179,6 +1535,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1179
1535
  * the container's computed CSS background (walking up past transparent
1180
1536
  * ancestors). Unknown/unparseable backgrounds keep the dark default.
1181
1537
  */
1538
+ private resolveCanvasBackground;
1182
1539
  private resolveSelectionColor;
1183
1540
  private setSelected;
1184
1541
  /** Rebuild one marker after selected/held/candidate state changes. */
@@ -1190,6 +1547,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1190
1547
  * whether the section already fills the viewport (small container) so the tap
1191
1548
  * must fall through and pick.
1192
1549
  */
1550
+ private sectionBounds;
1193
1551
  private sectionFrameScale;
1194
1552
  /**
1195
1553
  * Resolve a seat tap: honour the 3D deck-drill and the AXS seat-pick gate,
@@ -1252,8 +1610,17 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1252
1610
  private cancelGlide;
1253
1611
  /** Current LOD rung derived from effective zoom — drives the ZONES/SECTIONS/SEATS pill. */
1254
1612
  getRung(): LodRung;
1255
- /** Jump the camera to a rung's zoom band, centred on the chart (glided). */
1613
+ getRenderedQualityEvidence(): RendererQualityEvidence;
1614
+ /** Jump the camera to a rung's zoom band (glided). */
1256
1615
  setRung(rung: LodRung): void;
1616
+ /**
1617
+ * The seat rung must account for labels that auto-fit inside a seat circle.
1618
+ * A short `A-1` remains at the normal 7u target; a table label such as
1619
+ * `T13-10` may fit at 4u and therefore needs a deeper camera target to reach
1620
+ * the same 12 CSS-pixel floor. Measurement happens only on explicit rung
1621
+ * navigation, never during pan/zoom frames.
1622
+ */
1623
+ private seatLabelTargetScale;
1257
1624
  /** Recompute LOD (cache/labels) after any pan/zoom settles. */
1258
1625
  private afterViewChange;
1259
1626
  /** rAF-coalesced `onViewChange` — at most one host callback per animation frame. */
@@ -1275,6 +1642,7 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1275
1642
  * byte-identical.
1276
1643
  */
1277
1644
  forceDraw(): void;
1645
+ private updateFreeTextVisibility;
1278
1646
  private updateLabels;
1279
1647
  private handleResize;
1280
1648
  private startFpsLoop;
@@ -1815,4 +2183,4 @@ declare function formatMoney(amount: number, currency?: string, fractionDigits?:
1815
2183
  /** Bare symbol for input adornments ("€", "$", "₹"). */
1816
2184
  declare function currencySymbol(currency?: string): string;
1817
2185
 
1818
- export { ACCESSIBILITY_TYPES, type AccessibilityMeta, type AccessibilityType, type AvailabilityRule, type BoothObject, CHART_STORAGE_KEY, type Category, type CategoryTier, type ChartDoc, type ChartObject, type ChartTheme, DEFAULT_CURRENCY, type DecorImageObject, type Dict, type ExpandedSeat, type Floor, type GAAreaObject, type HoldConflict, type HoldInfo, type HoldSelectionRequest, type HoldServerItem, type ISeatmapRenderer, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PanoramaResult, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, type RendererCallbacks, type RendererOptions, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatHoverDetails, type SeatOverride, type SeatStatus, SeatmapRenderer, type SectionCategory, type SectionNode, type SectionObject, type SectionSummary, type SelectionLayer, type ShapeObject, type TableObject, type TextObject, UNGROUPED_ID, type ZoneDef, accessibilityMeta, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, floorObjects, floorsOf, formatDate, formatMoney, gaAreasOf, gaUnitLabel, gaUnitLabels, generateSeatPanorama, generateSeatThumb, getLocale, hiddenObjectIds, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
2186
+ export { ACCESSIBILITY_TYPES, type AccessibilityMeta, type AccessibilityType, type AvailabilityRule, type BoothObject, CHART_STORAGE_KEY, type Category, type CategoryTier, type ChartDoc, type ChartObject, type ChartReferenceImage, type ChartTheme, type CubicPath, DEFAULT_CURRENCY, type DecorImageObject, type Dict, type ExpandedSeat, type Floor, type GAAreaObject, type HoldConflict, type HoldInfo, type HoldSelectionRequest, type HoldServerItem, type ISeatmapRenderer, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PanoramaResult, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, type ReferenceAccessibilitySource, type ReferenceCalibration, type ReferenceCategorySource, type ReferenceDerivedScale, type ReferenceInventoryExclusionSource, type ReferenceInventorySource, type RenderedBookableLabelEvidence, type RenderedFreeTextEvidence, type RenderedGAAreaEvidence, type RenderedHierarchyLabelEvidence, type RenderedLabelHiddenReason, type RendererCallbacks, type RendererOptions, type RendererQualityEvidence, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatHoverDetails, type SeatOverride, type SeatStatus, SeatmapRenderer, type SectionCategory, type SectionNode, type SectionObject, type SectionOutlinePath, type SectionPathSegment, type SectionSummary, type SelectionLayer, type ShapeObject, type TableObject, type TextObject, UNGROUPED_ID, type ZoneDef, accessibilityMeta, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, floorObjects, floorsOf, formatDate, formatMoney, gaAreasOf, gaUnitLabel, gaUnitLabels, generateSeatPanorama, generateSeatThumb, getLocale, hiddenObjectIds, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, pointInPolygonWithHoles, polygonLabelPoint, resolveLocale, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };