@seatlayer/core 0.25.0 → 0.27.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.cts CHANGED
@@ -95,7 +95,7 @@ interface CategoryTier {
95
95
  * venues (and seats.io) expose so buyers can filter for exactly what they need
96
96
  * and organizers can mark seats precisely. `wheelchair` is the legacy default.
97
97
  */
98
- type AccessibilityType = 'wheelchair' | 'companion' | 'semi-ambulatory' | 'hearing' | 'sign-language' | 'plus-size' | 'lift-armrest';
98
+ type AccessibilityType = 'wheelchair' | 'companion' | 'semi-ambulatory' | 'hearing' | 'cart' | 'sign-language' | 'plus-size' | 'lift-armrest';
99
99
  interface AccessibilityMeta {
100
100
  key: AccessibilityType;
101
101
  /** Full descriptive label (designer checkbox, picker legend). */
@@ -135,6 +135,13 @@ interface SeatOverride {
135
135
  accessible?: boolean;
136
136
  /** Accessibility accommodations of this seat (empty/absent = none). */
137
137
  accessibility?: AccessibilityType[];
138
+ /**
139
+ * Physical wheelchair provision. Absent keeps legacy seat rendering;
140
+ * `seat-present` is an explicit removable/fixed accessible chair, while
141
+ * `no-seat` is an empty wheelchair bay that remains one sellable inventory
142
+ * unit. This is deliberately distinct from `skip`, which removes inventory.
143
+ */
144
+ wheelchairSpaceType?: 'seat-present' | 'no-seat';
138
145
  /** Commercial selling/view attributes are deliberately not accessibility. */
139
146
  commercial?: SeatCommercialAttributes;
140
147
  /** Seat-specific view photo; falls back to the row photo. */
@@ -218,6 +225,13 @@ interface ChartTheme {
218
225
  interface RowObject {
219
226
  type: 'row';
220
227
  id: string;
228
+ /** Present when this row was materialized by the in-canvas reference scan.
229
+ * A re-scan of the same asset replaces rows carrying this marker and NEVER
230
+ * touches hand-authored rows — the same replace-generated-only invariant as
231
+ * applyReferenceInventory. */
232
+ referenceScan?: {
233
+ assetId: string;
234
+ };
221
235
  /** Row label, e.g. "A". Seat labels are `${label}-${n}`. */
222
236
  label: string;
223
237
  /** Buyer-facing row name. `label` remains the legacy inventory prefix. */
@@ -279,6 +293,48 @@ interface RowObject {
279
293
  rowIndex: number;
280
294
  segmentIndex: number;
281
295
  };
296
+ /**
297
+ * Membership in one buyer-facing segmented row. Physical component rows and
298
+ * their `${rowId}:${slotIndex}` inventory ids remain authoritative; this
299
+ * metadata only supplies logical ordering/presentation and explicit aisle
300
+ * continuity. The descriptor is repeated on every component so selecting any
301
+ * one can resolve the complete logical row without a chart-level side table.
302
+ */
303
+ segmentedRow?: {
304
+ kind: 'segmented-row-v1';
305
+ groupId: string;
306
+ componentIndex: number;
307
+ componentCount: number;
308
+ /** The first component must use `start`; later boundaries are explicit. */
309
+ boundaryBefore: 'start' | 'continuous' | 'break';
310
+ /** Buyer-facing row name; technical component `label` values never change. */
311
+ displayLabel: string;
312
+ displayType?: string;
313
+ labelPresentation?: LabelPresentation;
314
+ viewFromSeatUrl?: string;
315
+ /** Presentation intent for a continuous node-defined centreline. */
316
+ smoothing?: boolean;
317
+ };
318
+ /**
319
+ * Versioned provenance for rows created by the multiple/intertwined block
320
+ * generator. Manual geometry edits remove this marker rather than allowing a
321
+ * later regeneration to overwrite hand-authored work.
322
+ */
323
+ rowBlockGeneration?: {
324
+ kind: 'row-block-v1';
325
+ groupId: string;
326
+ style: 'multiple' | 'intertwined';
327
+ rowIndex: number;
328
+ rowCount: number;
329
+ seatsPerRow: number;
330
+ origin: Point;
331
+ rotation: number;
332
+ rowGap: number;
333
+ seatSpacing: number;
334
+ curve: number;
335
+ /** Stable canonical generator signature shared by every intact member. */
336
+ signature: string;
337
+ };
282
338
  /** First seat number (default 1). Roman/letters read it as a 1-based ordinal
283
339
  * (start 1 → I / A). */
284
340
  seatLabelStart?: number;
@@ -297,13 +353,16 @@ interface RowObject {
297
353
  * - `even` 2,4,6 — even numbers from the first even ≥ start.
298
354
  * - `updown` 1,3,5,…,6,4,2 — odd-up-even-back; REPLACES direction (uses
299
355
  * physical left→right order); start shifts.
356
+ * - `updown-descending` …5,3,1,2,4,6 — odd-back-even-up; the distinct
357
+ * reverse up/down sequence. Also replaces
358
+ * direction and uses physical order.
300
359
  * - `roman` I,II,III — honours direction + step + start (uppercase).
301
360
  * - `letters-upper` A,B,C…Z,AA — honours direction + step + start.
302
361
  * - `letters-lower` a,b,c…z,aa — honours direction + step + start.
303
362
  * Like `step`/`direction` today, the scheme changes the seat's inventory
304
363
  * label (its booking identity), by design.
305
364
  */
306
- scheme?: 'decimal' | 'odd' | 'even' | 'updown' | 'roman' | 'letters-upper' | 'letters-lower';
365
+ scheme?: 'decimal' | 'odd' | 'even' | 'updown' | 'updown-descending' | 'roman' | 'letters-upper' | 'letters-lower';
307
366
  /** Optional prefix prepended to every seat number, e.g. 'R' → 'R1', 'R2'. */
308
367
  prefix?: string;
309
368
  /**
@@ -334,7 +393,10 @@ interface RowObject {
334
393
  interface GAAreaObject {
335
394
  type: 'gaArea';
336
395
  id: string;
396
+ /** Stable technical/inventory label. */
337
397
  label: string;
398
+ /** Buyer-facing area name; technical `label` and GA unit ids stay stable. */
399
+ displayLabel?: string;
338
400
  /** Buyer-facing type word override (seats.io "Displayed type"), ≤24 chars.
339
401
  * Absent = the default type word. Pure presentation. */
340
402
  displayType?: string;
@@ -344,8 +406,34 @@ interface GAAreaObject {
344
406
  holes?: Point[][];
345
407
  capacity: number;
346
408
  categoryKey: string;
409
+ /** Corner-rounding radius in chart units (default 0 = sharp corners). Pure
410
+ * presentation — softens the polygon's corners in every renderer without
411
+ * touching capacity, unit identities, or the stored points. Clamped per
412
+ * corner to half the shorter adjacent edge at draw time. */
413
+ cornerRadius?: number;
414
+ /**
415
+ * Durable inventory provenance for a surface produced by Join Areas.
416
+ *
417
+ * A GA unit is identified by the id and zero-based range of the area that
418
+ * originally authored it, not by the current polygon which happens to own
419
+ * it. Keeping those source ranges means a geometric join never renumbers an
420
+ * already published/booked unit. Ordinary (never-joined) areas omit this
421
+ * field and implicitly own `[0, capacity)` under their own id.
422
+ *
423
+ * The ranges must be non-overlapping, contain positive whole counts, and sum
424
+ * exactly to `capacity`; validation rejects malformed metadata. Capacity
425
+ * growth appends a new range under the surviving area id, while shrinking a
426
+ * joined area is deliberately refused because it would silently destroy
427
+ * stable inventory identities.
428
+ */
429
+ inventorySegments?: GAInventorySegment[];
347
430
  referenceInventorySource?: ReferenceInventorySource;
348
431
  }
432
+ interface GAInventorySegment {
433
+ sourceAreaId: string;
434
+ startIndex: number;
435
+ count: number;
436
+ }
349
437
  /**
350
438
  * Durable evidence link for sellable objects generated from a private reference.
351
439
  * The client supplies facts and stable logical-section ids, never coordinates.
@@ -394,20 +482,46 @@ interface ReferenceInventoryExclusionSource {
394
482
  evidence: 'user-confirmed' | 'authoritative-source';
395
483
  sourceDescription: string;
396
484
  }
485
+ /** Open-path stroke semantics. Optional ShapeObject fields retain the legacy
486
+ * round/round/no-ending rendering when absent. */
487
+ type ShapeLineCap = 'butt' | 'round' | 'square';
488
+ type ShapeLineJoin = 'miter' | 'round' | 'bevel';
489
+ type ShapeLineEnding = 'none' | 'arrow';
397
490
  /** Non-bookable décor: stage, walls, exits. */
398
491
  interface ShapeObject {
399
492
  type: 'shape';
400
493
  id: string;
401
- kind: 'rect' | 'ellipse' | 'polygon';
494
+ /**
495
+ * Closed area shapes (`rect`/`ellipse`/`polygon`) take a `fill`; open path
496
+ * primitives (`line` = two points, `polyline` = n points) are stroke-only and
497
+ * never filled. All kinds honour the optional `stroke`.
498
+ */
499
+ kind: 'rect' | 'ellipse' | 'polygon' | 'line' | 'polyline';
402
500
  label?: string;
403
501
  /** For rect/ellipse: bounding box. For a stage polygon: the base (pre-shape) box, so its kind can be regenerated. */
404
502
  x?: number;
405
503
  y?: number;
406
504
  width?: number;
407
505
  height?: number;
408
- /** For polygon. */
506
+ /** For polygon/line/polyline. */
409
507
  points?: Point[];
410
508
  fill?: string;
509
+ /** Optional outline. `width` is in chart units; both fields are required together. */
510
+ stroke?: {
511
+ color: string;
512
+ width: number;
513
+ };
514
+ /** Open line/polyline only. Absent fields preserve round/round/no-ending legacy rendering. */
515
+ lineCap?: ShapeLineCap;
516
+ /** Controls corners between open-path segments. */
517
+ lineJoin?: ShapeLineJoin;
518
+ /** Independent open-path start/end decorations. Closed outlines never use these fields. */
519
+ startEnding?: ShapeLineEnding;
520
+ endEnding?: ShapeLineEnding;
521
+ /** Rect only — corner rounding radius in chart units, clamped to half the short side at edit time. */
522
+ cornerRadius?: number;
523
+ /** Whole-shape opacity 0.1–1 (default 1). */
524
+ opacity?: number;
411
525
  /** Degrees clockwise about the shape's center (default 0). Applied at render time. */
412
526
  rotation?: number;
413
527
  /**
@@ -420,12 +534,27 @@ interface ShapeObject {
420
534
  /** For a stage: which `StageKind` its polygon was generated from. */
421
535
  stageKind?: string;
422
536
  }
423
- /** Seats arranged around a table; bookable per-seat or as a whole. */
537
+ type RectTableSide = 'top' | 'bottom' | 'left' | 'right';
538
+ /** Exact rectangular-table chair distribution. The four keys are deliberately
539
+ * required: zero means that edge has no chair, while the sum is the authored
540
+ * `seatCount`. Numeric chair identity remains `${table.id}:${index}` in the
541
+ * canonical top, bottom, left, right expansion order. */
542
+ interface RectTableSeatCounts {
543
+ top: number;
544
+ bottom: number;
545
+ left: number;
546
+ right: number;
547
+ }
548
+ /** Seats arranged around a table. Grouped selling is activated only by an
549
+ * event's explicit inventory-model-2 snapshot; model-1 events continue to
550
+ * treat every authored chair as an independent unit. */
424
551
  interface TableObject {
425
552
  type: 'table';
426
553
  id: string;
427
554
  /** e.g. "T1" — seat labels are `${label}-${n}`. */
428
555
  label: string;
556
+ /** Buyer-facing table name; technical chair/group labels stay stable. */
557
+ displayLabel?: string;
429
558
  /** Buyer-facing type word override (seats.io "Displayed type"), ≤24 chars.
430
559
  * Absent = the default "Row"/"Table" word. Pure presentation. */
431
560
  displayType?: string;
@@ -434,7 +563,16 @@ interface TableObject {
434
563
  /** Seats around the perimeter (round) or along the enabled edges (rect). */
435
564
  seatCount: number;
436
565
  /** Rect tables: which edges get seats (default ['top','bottom']). */
437
- sides?: Array<'top' | 'bottom' | 'left' | 'right'>;
566
+ sides?: RectTableSide[];
567
+ /**
568
+ * Rect tables only: exact chairs on every edge. Absent preserves the legacy
569
+ * `seatCount` + `sides` round-robin distribution byte-for-byte. When present,
570
+ * all four values are whole numbers >= 0 and their sum equals `seatCount`.
571
+ */
572
+ seatCountsBySide?: RectTableSeatCounts;
573
+ /** Individual-chair semantic overrides. Grouped whole/variable tables cannot
574
+ * author these because their only sellable identity is the table itself. */
575
+ overrides?: SeatOverride[];
438
576
  rotation: number;
439
577
  /** Round tables. */
440
578
  radius?: number;
@@ -449,15 +587,23 @@ interface TableObject {
449
587
  width?: number;
450
588
  height?: number;
451
589
  categoryKey: string;
452
- /** Whole-table booking: buyers get all seats or none (per-event override later). */
590
+ /** One buyer owns the complete table at exactly `seatCount` guests. */
453
591
  bookAsWhole?: boolean;
592
+ /** One buyer owns the complete table and chooses a bounded guest quantity. */
593
+ variableOccupancy?: boolean;
594
+ /** Required inclusive guest bounds when `variableOccupancy` is true. */
595
+ minOccupancy?: number;
596
+ maxOccupancy?: number;
454
597
  referenceInventorySource?: ReferenceInventorySource;
455
598
  }
456
599
  /** A booth: one bookable unit rendered as a block (trade shows, VIP boxes). */
457
600
  interface BoothObject {
458
601
  type: 'booth';
459
602
  id: string;
603
+ /** Stable technical/inventory label. */
460
604
  label: string;
605
+ /** Buyer-facing booth name; technical `label` stays stable. */
606
+ displayLabel?: string;
461
607
  /** Buyer-facing type word override (seats.io "Displayed type"), ≤24 chars.
462
608
  * Absent = the default type word. Pure presentation. */
463
609
  displayType?: string;
@@ -465,6 +611,16 @@ interface BoothObject {
465
611
  width: number;
466
612
  height: number;
467
613
  rotation: number;
614
+ /**
615
+ * Optional custom outline (closed polygon, absolute chart coordinates) for
616
+ * non-rectangular booths — L-shaped, corner, or island units on expo floors.
617
+ * Absent = the default axis-aligned rectangle described by `width`/`height`/
618
+ * `rotation`. A booth stays exactly ONE atomic sellable unit whatever its
619
+ * outline; `points` is purely geometric. `width`/`height` are retained as the
620
+ * last rectangular size so "Back to rectangle" can restore it. When `points`
621
+ * is present, renderers draw the polygon and ignore `rotation`.
622
+ */
623
+ points?: Point[];
468
624
  categoryKey: string;
469
625
  referenceInventorySource?: ReferenceInventorySource;
470
626
  }
@@ -486,6 +642,13 @@ interface SectionObject {
486
642
  * ("Entrance X"). ≤40 chars; absent = no entrance line. Pure presentation.
487
643
  */
488
644
  entrance?: string;
645
+ /**
646
+ * Organizer-supplied view image inherited by buyer inventory whose owning
647
+ * row/table/booth sits in this logical section. Seat and row photos take
648
+ * precedence; multipart components are kept in sync by the shared section
649
+ * metadata operation.
650
+ */
651
+ viewFromSeatUrl?: string;
489
652
  labelPresentation?: LabelPresentation;
490
653
  /**
491
654
  * Stable management/inventory identity shared by disconnected visual
@@ -532,11 +695,35 @@ interface SectionObject {
532
695
  * Tier height. 0 = floor (default). Higher values lift the section in the
533
696
  * picker's isometric ("3D") view, drawn on extruded side faces. Same field a
534
697
  * future multi-floor mode reuses — authored in 2D, never drawn by the user.
698
+ *
699
+ * This is the coarse, back-compat source for {@link height}/{@link rake}: when
700
+ * those are absent, {@link sectionGeometry} derives real geometry from this
701
+ * tier so legacy charts render pixel-identical.
535
702
  */
536
703
  elevation?: number;
704
+ /**
705
+ * 3D foundations (Phase A, additive — no migration; charts are JSON blobs).
706
+ * Metres the section's **front edge** sits above floor 0 (a balcony/tier floor
707
+ * height). Absent ⇒ derived from the coarse {@link elevation} tier via
708
+ * {@link sectionGeometry}. Deliberately two scalars, not a foundation polygon:
709
+ * front-height + {@link rake} fully determine a rectangular tier's back-height.
710
+ *
711
+ * NOTE: no consumer reads this raw field directly — all callers go through
712
+ * {@link sectionGeometry}. Phase B consumers (iso view lift in
713
+ * `SeatmapRenderer`, per-seat eye-height in the `generatePanorama` 360°
714
+ * generator) are intentionally NOT wired in Phase A. Range 0–120 m.
715
+ */
716
+ height?: number;
717
+ /**
718
+ * Degrees of seating incline within the section (0 = flat; typical stalls
719
+ * 5–15°, steep tiers 25–35°). Absent ⇒ 0. Consumed alongside {@link height}
720
+ * by the future Phase B iso-lift shear and 360° sightline math — never in
721
+ * Phase A. Range 0–45°.
722
+ */
723
+ rake?: number;
537
724
  /** Uniform scale about the outline centroid (1 = as drawn). Scales members too. */
538
725
  scale?: number;
539
- /** 0–1: how strongly member-row curves are bent toward a common arc fitted to the outline. */
726
+ /** 0–100: reviewed strength last used to bend member rows toward a common fitted arc. */
540
727
  smoothing?: number;
541
728
  /** Degrees clockwise about the outline centroid (default 0). Rotates members too. */
542
729
  rotation?: number;
@@ -550,23 +737,49 @@ interface ZoneDef {
550
737
  id: string;
551
738
  label: string;
552
739
  color?: string;
740
+ /**
741
+ * Authored point this zone faces. Optional only for legacy documents: runtime
742
+ * consumers fall back to the active floor/chart focal, while publication of
743
+ * a zone-mode draft requires every used zone to carry an explicit point.
744
+ */
745
+ focalPoint?: Point;
553
746
  }
554
747
  /**
555
748
  * Selection layer — a hit-test/dim filter in the designer, NOT z-order management.
556
749
  * Fixed set of four; derived from object type via `layerOf()` (no per-object field yet).
557
750
  */
558
751
  type SelectionLayer = 'interactive' | 'background' | 'foreground' | 'surroundings';
752
+ /** Shape roles emitted by the curated venue-landmark palette. Keep this list in
753
+ * lockstep with `DECOR_PRESETS`; the selection-layer unit test fails if either
754
+ * vocabulary changes without an explicit routing decision. `reference-focal`
755
+ * is source-backed venue context rather than an authoring-palette preset. */
756
+ declare const SURROUNDINGS_SHAPE_ROLES: readonly ["reference-focal", "bar", "entrance", "exit", "restroom", "screen", "sound", "concession", "coat", "wall"];
559
757
  /** Derive an object's selection layer from its type. */
560
758
  declare function layerOf(obj: ChartObject): SelectionLayer;
561
759
  /** Free-standing text on the chart (aisle names, door labels…). */
562
760
  interface TextObject {
563
761
  type: 'text';
564
762
  id: string;
763
+ /** Persisted provenance for objects created from the venue-icon palette. */
764
+ semanticKind?: 'icon';
765
+ /**
766
+ * Registry key for a vector wayfinding icon (see src/core/icons.ts). Present
767
+ * on modern icon placements; the object then renders as a single-color vector
768
+ * Path instead of `text`. Absent on legacy emoji icons, which keep rendering
769
+ * `text` through the shared glyph path — old charts are never rewritten.
770
+ */
771
+ iconKey?: string;
565
772
  text: string;
566
773
  position: Point;
567
774
  fontSize: number;
775
+ /** Optional CSS family stack for this annotation; absent inherits ChartTheme.fontFamily. */
776
+ fontFamily?: string;
568
777
  rotation: number;
569
778
  color?: string;
779
+ /** Render weight (default false). Maps to Konva fontStyle bold. */
780
+ bold?: boolean;
781
+ /** Render slant (default false). Maps to Konva fontStyle italic. */
782
+ italic?: boolean;
570
783
  }
571
784
  /**
572
785
  * A raster/vector decor graphic drawn IN the chart, beneath the seats and
@@ -590,6 +803,12 @@ interface DecorImageObject {
590
803
  rotation?: number;
591
804
  /** 0–1 (default 1). Multiplied by any chart-theme dimming at render time. */
592
805
  opacity?: number;
806
+ /**
807
+ * Z-layer relative to the interactive seat layer. `background` (default)
808
+ * draws beneath the seats/sections; `foreground` draws above them (a roof
809
+ * canopy, an overlay graphic). Absent = background — no migration needed.
810
+ */
811
+ layer?: 'background' | 'foreground';
593
812
  /** Optional caption for the designer inspector / accessibility (not drawn). */
594
813
  label?: string;
595
814
  }
@@ -603,8 +822,25 @@ type ChartObject = RowObject | GAAreaObject | ShapeObject | TableObject | BoothO
603
822
  interface Floor {
604
823
  id: string;
605
824
  name: string;
825
+ /**
826
+ * Absolute physical deck height in metres above the venue/stage datum.
827
+ * Optional for backwards compatibility; an absent value resolves to ground
828
+ * level (0 m). Section tiers and rakes are separate, section-local metadata.
829
+ * Range 0–120 m.
830
+ */
831
+ baseHeightM?: number;
606
832
  objects: ChartObject[];
607
833
  focalPoint: Point;
834
+ /**
835
+ * Private organizer trace/calibration layer. This is authoring evidence and
836
+ * must never be served to, or rendered by, a buyer surface.
837
+ */
838
+ referenceImage?: ChartReferenceImage;
839
+ /**
840
+ * Buyer-visible aesthetic background. Canonical documents store URL-only
841
+ * images here. Historical `assetId` values are interpreted as a trace layer
842
+ * by the background compatibility helpers.
843
+ */
608
844
  backgroundImage?: ChartDoc['backgroundImage'];
609
845
  }
610
846
  interface ReferenceCalibration {
@@ -618,6 +854,64 @@ interface ReferenceCalibration {
618
854
  /** Derived and stored for deterministic geometry compilers. */
619
855
  pixelsPerUnit: number;
620
856
  }
857
+ /**
858
+ * A single human-placed seat probe: the author clicks one seat on the reference
859
+ * image and the server reads the surrounding seat lattice from it.
860
+ *
861
+ * COORDINATE-POLICY CARVE-OUT (owner decision 2026-07-21). The reference
862
+ * blueprint pipeline runs `coordinatePolicy: 'opaque-region-ids-only'` — the
863
+ * server is the sole source of chart coordinates and MCP clients select opaque
864
+ * `reg_*` ids, never points. This type is a deliberate, narrow exception on the
865
+ * same grounds as `ReferenceCalibration`: the point is placed by a human in the
866
+ * designer canvas, not proposed by a model.
867
+ *
868
+ * Therefore this is DESIGNER-ONLY and is intentionally NOT exposed over MCP.
869
+ * That is an accepted, documented exception to the MCP-parity rule — the
870
+ * server-is-sole-source guarantee for model-driven edits is worth more than
871
+ * parity here. Do not "fix" it by adding a seed point to an MCP tool schema.
872
+ */
873
+ interface ReferenceSeatSeed {
874
+ /** Seed centre in immutable source-image pixels (never chart coordinates). */
875
+ source: Point;
876
+ /** Half-width of the author's sizing ring, in source pixels — the "this is how
877
+ * big one seat is" hint that replaces seats.io's zoom-until-it-matches step. */
878
+ radius: number;
879
+ /** Whether `radius` was fitted from image pixels or set by hand. Detection
880
+ * weights an author-set radius more heavily than one we guessed. */
881
+ origin: 'auto-fit' | 'manual';
882
+ }
883
+ /** One detected row in a scan proposal — a straight seat run in CHART
884
+ * coordinates (the server maps source pixels through referencePixelToChart;
885
+ * clients never see source-pixel geometry back). */
886
+ interface ReferenceScanRowProposal {
887
+ start: Point;
888
+ end: Point;
889
+ seatCount: number;
890
+ }
891
+ /** Detected rows attributed to one compiled section (or unattributed when the
892
+ * lattice extends outside every compiled polygon). */
893
+ interface ReferenceScanSectionProposal {
894
+ /** Id of the compiled SectionObject the rows landed in; null = unattributed. */
895
+ sectionId: string | null;
896
+ name: string;
897
+ rows: ReferenceScanRowProposal[];
898
+ seatCount: number;
899
+ /** 0..1 — how well this section's lattice agreed with the probe's pitch. */
900
+ confidence: number;
901
+ /** Index of the seed (multi-probe) whose pitch produced these rows. */
902
+ seedIndex: number;
903
+ }
904
+ /** Server response for an in-canvas reference scan. A PROPOSAL — nothing is
905
+ * committed until the author applies it in the designer (chartOps + undo). */
906
+ interface ReferenceScanProposal {
907
+ assetId: string;
908
+ /** Measured seat diameter / centre-to-centre pitch, in chart units. */
909
+ seatDiameter: number;
910
+ seatPitch: number;
911
+ totalSeats: number;
912
+ totalRows: number;
913
+ sections: ReferenceScanSectionProposal[];
914
+ }
621
915
  /** Coordinate-free physical scale derived by server code from a confirmed
622
916
  * semantic feature. Unlike manual two-point calibration, no source points pass
623
917
  * through an MCP client or language model. */
@@ -669,7 +963,16 @@ interface ChartDoc {
669
963
  * is kept mirroring floor 0 so single-floor readers never branch. */
670
964
  floors?: Floor[];
671
965
  objects: ChartObject[];
672
- /** Floor-plan photo the organizer traces over (designer-only aid, also rendered dimly in picker if kept). */
966
+ /**
967
+ * Private floor-plan source used for tracing, calibration, scanning and
968
+ * reference-backed generation. Buyer projections always remove this field.
969
+ */
970
+ referenceImage?: ChartReferenceImage;
971
+ /**
972
+ * Buyer-visible aesthetic background. Canonical values are URL-only.
973
+ * Compatibility: a historical value containing `assetId` is trace-only and
974
+ * is never rendered or exposed to buyers.
975
+ */
673
976
  backgroundImage?: ChartReferenceImage;
674
977
  /** Brand/venue theming (colors); categories carry their own colors separately. */
675
978
  theme?: ChartTheme;
@@ -691,6 +994,18 @@ interface ExpandedSeat {
691
994
  x: number;
692
995
  y: number;
693
996
  rowId: string;
997
+ /** Owning logical section and navigation zone, resolved once at expand time. */
998
+ sectionId?: string;
999
+ zoneId?: string;
1000
+ /** Zone focal when authored, otherwise the active floor/chart legacy fallback. */
1001
+ focalPoint?: Point;
1002
+ /** Buyer-facing segmented-row identity. `rowId` stays the physical owner id. */
1003
+ logicalRowId?: string;
1004
+ /**
1005
+ * Seat order inside the logical row. A deliberate missing integer is inserted
1006
+ * at every aisle boundary, so numerical adjacency cannot bridge a gap.
1007
+ */
1008
+ logicalSeatIndex?: number;
694
1009
  categoryKey: string;
695
1010
  /** 'booth' units render as blocks (dimensions looked up via rowId = booth id). */
696
1011
  kind?: 'seat' | 'booth';
@@ -698,13 +1013,24 @@ interface ExpandedSeat {
698
1013
  accessible?: boolean;
699
1014
  /** Specific accessibility accommodations (absent = none) — picker badges/filters these. */
700
1015
  accessibility?: AccessibilityType[];
1016
+ /** Physical wheelchair provision resolved from the seat override. */
1017
+ wheelchairSpaceType?: 'seat-present' | 'no-seat';
701
1018
  commercial?: SeatCommercialAttributes;
702
1019
  /** Organizer-supplied view-from-seat image (inherited from the row). */
703
1020
  viewUrl?: string;
704
1021
  /** Per-seat label size/color override; absent = inherit the row/theme default. */
705
1022
  labelStyle?: LabelStyle;
1023
+ /**
1024
+ * Real-world eye height in metres above the focal/stage datum, resolved at
1025
+ * expand time from the owning section's `{height, rake}` + drawn depth (Phase B2).
1026
+ * Feeds the auto-360° generator's stage-pitch math. Absent ⇒ flat seated eye
1027
+ * height (legacy / seats in no section) — so old charts stay pixel-identical.
1028
+ */
1029
+ eyeHeightM?: number;
706
1030
  }
707
1031
  type SeatStatus = 'free' | 'held' | 'booked' | 'not_for_sale';
1032
+ /** Buyer canvas projection. Perspective is a view-only projected-2.5D lane. */
1033
+ type RendererViewMode = 'flat' | 'isometric' | 'perspective';
708
1034
  interface RendererCallbacks {
709
1035
  onSelect?: (seat: ExpandedSeat) => void;
710
1036
  onDeselect?: (seat: ExpandedSeat) => void;
@@ -779,6 +1105,11 @@ interface RenderedBookableLabelEvidence {
779
1105
  seatId: string;
780
1106
  label: string;
781
1107
  kind: 'seat' | 'booth';
1108
+ /** Painted inventory silhouette. Empty wheelchair bays are deliberately
1109
+ * square, while physical seats retain the ordinary circular marker. */
1110
+ markerShape: 'circle' | 'square' | 'booth';
1111
+ /** Physical wheelchair provision represented by this inventory unit. */
1112
+ wheelchairSpaceType?: 'seat-present' | 'no-seat';
782
1113
  categoryKey: string;
783
1114
  sectionId?: string;
784
1115
  zoneId?: string;
@@ -789,6 +1120,13 @@ interface RenderedBookableLabelEvidence {
789
1120
  fill: string;
790
1121
  ink: string;
791
1122
  opacity: number;
1123
+ /** Buyer-visible accessibility glyph evidence. Filter emphasis uses a
1124
+ * screen-space minimum so wheelchair provision remains recognizable at fit. */
1125
+ accessibilityMarker?: {
1126
+ glyphVisible: boolean;
1127
+ glyphWidthPx: number;
1128
+ emphasizedByFilter: boolean;
1129
+ };
792
1130
  /** Direct Konva shape bounds and the production near-miss rescue combined. */
793
1131
  pointerTarget: {
794
1132
  active: boolean;
@@ -869,6 +1207,15 @@ interface RendererQualityEvidence {
869
1207
  width: number;
870
1208
  height: number;
871
1209
  };
1210
+ /** Runtime projection actually used for the pixels and hit graph below. */
1211
+ projection: RendererViewMode;
1212
+ /** Phase-C proof metadata. Present only in the projected-2.5D lane. */
1213
+ perspective?: {
1214
+ model: 'pinhole-exact-seat-anchors';
1215
+ sectionSurfaceModel: 'tangent-plane';
1216
+ exactSeatAnchorCount: number;
1217
+ depthSorted: true;
1218
+ };
872
1219
  canvasBackground: string;
873
1220
  effectiveScale: number;
874
1221
  rung: LodRung;
@@ -1053,13 +1400,14 @@ interface ISeatmapRenderer {
1053
1400
  */
1054
1401
  setColorblindSafe?(on: boolean): void;
1055
1402
  /**
1056
- * Switch the projection. `'flat'` = normal top-down; `'isometric'` = the "3D"
1057
- * view (affine skew/rotate + elevation lift), hit-testing preserved in screen
1058
- * space. Purely visual the chart is authored flat. Animated unless reduced-motion.
1403
+ * Switch the projection. `'flat'` = normal top-down; `'isometric'` = the
1404
+ * legacy affine preview; `'perspective'` = projected 2.5D with exact pinhole
1405
+ * seat anchors/native hit shapes and bounded per-section tangent surfaces.
1406
+ * Purely visual — the chart is authored flat.
1059
1407
  */
1060
- setViewMode?(mode: 'flat' | 'isometric'): void;
1408
+ setViewMode?(mode: RendererViewMode): void;
1061
1409
  /** Current projection (defaults to 'flat' when unimplemented). */
1062
- getViewMode?(): 'flat' | 'isometric';
1410
+ getViewMode?(): RendererViewMode;
1063
1411
  /** Multi-floor (Batch 5): switch the shown floor; list floors; read the active id. */
1064
1412
  setActiveFloor?(floorId: string): void;
1065
1413
  getFloors?(): {
@@ -1128,6 +1476,8 @@ declare const CHART_STORAGE_KEY = "seatmap.chart";
1128
1476
  */
1129
1477
  /** Base (pre-override) seat centre per index — shared by expandRow + designer edit mode. */
1130
1478
  declare function rowSeatPositions(row: RowObject): Point[];
1479
+ /** Sellable row slots: skipped slots are absent; empty wheelchair bays remain. */
1480
+ declare function rowInventoryCount(row: RowObject): number;
1131
1481
  /**
1132
1482
  * Every seat slot of a row INCLUDING skipped ones (designer seat-edit mode uses
1133
1483
  * this to draw un-skip handles). Overrides (dx/dy/label/categoryKey) are applied
@@ -1143,10 +1493,17 @@ interface RowSeatSlot {
1143
1493
  skipped: boolean;
1144
1494
  accessible: boolean;
1145
1495
  accessibility: AccessibilityType[];
1496
+ wheelchairSpaceType?: SeatOverride['wheelchairSpaceType'];
1146
1497
  commercial?: RowObject['commercial'];
1147
1498
  viewUrl?: string;
1148
1499
  labelStyle?: LabelStyle;
1149
1500
  }
1501
+ /** Every authored table-chair slot, including skipped inventory. This mirrors
1502
+ * row seat slots so Designer, MCP and buyer/event expansion share one semantic
1503
+ * source while retaining the table's stable numeric slot identity. */
1504
+ interface TableSeatSlot extends RowSeatSlot {
1505
+ side?: RectTableSide;
1506
+ }
1150
1507
  /**
1151
1508
  * The seat NUMBER part of a row seat's label (the row prefix is prepended by the
1152
1509
  * caller). Applies the row's numbering scheme, direction, step, start and label
@@ -1163,6 +1520,15 @@ declare function expandRow(row: RowObject): ExpandedSeat[];
1163
1520
  * bottom edges (split evenly, any remainder to the top), 16u outside the edge,
1164
1521
  * the whole set rotated about the table centre.
1165
1522
  */
1523
+ /** Legacy rect tables distribute aggregate capacity round-robin across enabled
1524
+ * sides, then emit chairs in canonical top/bottom/left/right order. */
1525
+ declare function tableSeatCountsBySide(t: TableObject): RectTableSeatCounts;
1526
+ /** Expand every authored table chair, including skipped slots needed by the
1527
+ * Designer to restore inventory. */
1528
+ declare function expandTableSlots(t: TableObject): TableSeatSlot[];
1529
+ /** Sellable individual table chairs. Grouped tables own one atomic inventory
1530
+ * unit elsewhere and therefore retain their full authored chair capacity. */
1531
+ declare function tableInventoryCount(t: TableObject): number;
1166
1532
  declare function expandTable(t: TableObject): ExpandedSeat[];
1167
1533
  /** Expand a booth into its single bookable block unit. */
1168
1534
  declare function expandBooth(b: BoothObject): ExpandedSeat[];
@@ -1178,6 +1544,14 @@ declare function polygonLabelPoint(outer: Point[], holes: Point[][] | undefined)
1178
1544
  * shape: bbox centre; text: its position.
1179
1545
  */
1180
1546
  declare function objectCenter(o: ChartObject): Point;
1547
+ /**
1548
+ * Resolve one bookable object's owning physical section using the canonical
1549
+ * first-match rule. Generated reference inventory may name a logical section,
1550
+ * but that provenance is trusted only when the stored geometry confirms it.
1551
+ * Keeping this primitive in layout lets section inventory, category painting,
1552
+ * and buyer view inheritance share one ownership decision.
1553
+ */
1554
+ declare function owningSectionForObject(objects: ChartObject[], object: ChartObject): SectionObject | undefined;
1181
1555
  /**
1182
1556
  * Normalized floor list (Batch 5): a multi-floor chart's `floors`, or a synthetic
1183
1557
  * single floor wrapping a single-floor chart's `objects`. Every consumer that needs
@@ -1195,8 +1569,15 @@ declare function allObjects(doc: ChartDoc): ChartObject[];
1195
1569
  * only for the 3D overview render — 2D still shows one floor via `floorObjects`.
1196
1570
  */
1197
1571
  declare function stackFloors(doc: ChartDoc, spread?: number): ChartDoc;
1198
- /** Expand every seat-bearing object across all floors (rows, tables, booths). */
1199
- declare function expandChart(doc: ChartDoc): ExpandedSeat[];
1572
+ interface ExpandChartOptions {
1573
+ /** Physical height for a single-floor projection extracted from a multi-floor
1574
+ * document. Full multi-floor documents resolve each floor directly. */
1575
+ floorBaseHeightM?: number;
1576
+ }
1577
+ /** Expand every seat-bearing object across all floors (rows, tables, booths).
1578
+ * Multi-floor ownership is resolved one floor at a time: local coordinates may
1579
+ * overlap between floors and must never assign a seat to another floor's section. */
1580
+ declare function expandChart(doc: ChartDoc, options?: ExpandChartOptions): ExpandedSeat[];
1200
1581
  /** Axis-aligned bounds over every object plus the background image, with padding. */
1201
1582
  declare function chartBounds(doc: ChartDoc): {
1202
1583
  x: number;
@@ -1209,10 +1590,63 @@ declare const MAX_GA_CAPACITY = 100000;
1209
1590
  declare const MAX_EVENT_INVENTORY = 100000;
1210
1591
  /** Stable internal inventory label for one unit of a GA area's capacity. */
1211
1592
  declare function gaUnitLabel(areaId: string, index: number): string;
1593
+ /** Strict, bounded validation for durable Join Areas inventory provenance. */
1594
+ declare function validGAInventorySegments(area: GAAreaObject): boolean;
1595
+ /** Canonical source ranges. Invalid explicit provenance intentionally yields no
1596
+ * labels: chart validation blocks publication instead of inventing identities. */
1597
+ declare function gaInventorySegments(area: GAAreaObject): GAInventorySegment[];
1212
1598
  declare function gaUnitLabels(area: GAAreaObject): string[];
1599
+ /** Append-only capacity semantics for an already joined GA surface. */
1600
+ declare function growJoinedGAInventory(area: GAAreaObject, nextCapacity: number): GAInventorySegment[] | undefined;
1213
1601
  declare function gaAreasOf(doc: ChartDoc): GAAreaObject[];
1214
1602
  declare function isGaUnitLabel(label: string): boolean;
1215
1603
 
1604
+ /**
1605
+ * Real-world scale primitives — the ONE place the app fixes chart-unit ↔ metre ↔
1606
+ * renderer-world scale, and the section 3D-geometry resolver that rides on it.
1607
+ *
1608
+ * Everything that converts between chart units, metres, and renderer "world"
1609
+ * units derives from {@link METRES_PER_CHART_UNIT}. Renderer world units and
1610
+ * chart units are 1:1, so metres → world is exactly {@link CHART_UNITS_PER_METRE}
1611
+ * (the single m→world conversion constant Phase B consumers use).
1612
+ *
1613
+ * This is a leaf module (types only) so both `layout.ts` and `sections.ts` can
1614
+ * import it without the two forming an import cycle.
1615
+ */
1616
+
1617
+ /**
1618
+ * Metres of front-edge height one elevation tier represents. Chosen (not guessed)
1619
+ * so `elevation × TIER_HEIGHT_M` metres, scaled back through
1620
+ * {@link CHART_UNITS_PER_METRE}, equals the legacy `elevation × LIFT_PER_STEP`
1621
+ * world lift exactly — an un-authored chart stays pixel-identical. ≈ 1.329 m/tier.
1622
+ */
1623
+ declare const TIER_HEIGHT_M: number;
1624
+ /**
1625
+ * Resolve a section's real 3D geometry, applying the legacy-elevation fallback so
1626
+ * old charts and new charts share ONE code path. Every consumer (iso lift, 360°
1627
+ * eye-height, author lint, any 2D depth cue) must call this and never read the raw
1628
+ * {@link SectionObject.height}/{@link SectionObject.rake} fields — that is what
1629
+ * keeps un-authored charts rendering identically to today.
1630
+ *
1631
+ * - `height`: authored absolute metres if present, else owning-floor base height
1632
+ * plus `elevation × TIER_HEIGHT_M`.
1633
+ * - `rake`: authored degrees if present, else 0 (flat).
1634
+ *
1635
+ * Malformed values are bounded here as a last defensive barrier. Structural
1636
+ * validation still reports them so drafts can be repaired instead of silently
1637
+ * persisting a renderer-only interpretation.
1638
+ *
1639
+ * Pure — no document mutation, no side effects.
1640
+ */
1641
+ interface SectionGeometryContext {
1642
+ /** Absolute physical height of the owning floor above the venue datum. */
1643
+ floorBaseHeightM?: number;
1644
+ }
1645
+ declare function sectionGeometry(section: Pick<SectionObject, 'elevation' | 'height' | 'rake'>, context?: SectionGeometryContext): {
1646
+ height: number;
1647
+ rake: number;
1648
+ };
1649
+
1216
1650
  /**
1217
1651
  * Section membership + hide/show resolution (Batch 3.3).
1218
1652
  *
@@ -1415,8 +1849,17 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1415
1849
  private seatLayer;
1416
1850
  private overlayLayer;
1417
1851
  private labelGroup;
1852
+ /** Per-elevated-section label containers. Keeping the labels grouped lets the
1853
+ * Phase-B lift move thousands of seat labels with one transform per section
1854
+ * instead of rewriting every label on every tween frame. */
1855
+ private labelLiftGroups;
1856
+ /** Foreground decor images — drawn on the overlay layer, ABOVE the seats. */
1857
+ private fgDecorGroup;
1418
1858
  private seats;
1419
1859
  private seatById;
1860
+ /** One build per chart/floor; section membership queries only inspect seats in
1861
+ * the section bounds instead of rescanning the full 13k venue per section. */
1862
+ private seatIndex;
1420
1863
  /** Multi-floor (Batch 5): the last-set chart + which floor we're rendering. */
1421
1864
  private chartDoc;
1422
1865
  private activeFloorId;
@@ -1432,15 +1875,15 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1432
1875
  private seatLabelById;
1433
1876
  /** Coloured accommodation ring per accessible seat (few per chart). */
1434
1877
  private accessRingById;
1435
- /** Centred accessibility glyph per accessible seat shown once the seat is
1436
- * big enough on-screen (see {@link SEAT_GLYPH_MIN_PX}); the ring is the
1437
- * smaller-zoom fallback. Kept in a map so zoom toggles touch only the handful
1438
- * of accessible seats, never all 13k nodes. */
1878
+ /** Centred glyph per physical wheelchair provision. It keeps a small
1879
+ * screen-space floor at every LOD and grows when the Wheelchair filter is
1880
+ * active. Kept in a map so zoom updates touch only the handful of matching
1881
+ * seats, never all 13k nodes. */
1439
1882
  private accessGlyphById;
1440
- /** Whether the accessibility glyph is legible at the current camera scale. */
1441
- private accessGlyphVisible;
1442
1883
  /** Authored free-text nodes obey the same rendered-size visibility floor. */
1443
1884
  private freeTextById;
1885
+ /** Vector venue-icon Path nodes + authored size; obey the free-text size floor. */
1886
+ private iconNodeById;
1444
1887
  /** Stage/rink landmarks retain a readable screen-space caption at overview. */
1445
1888
  private primaryFocalLabels;
1446
1889
  /** GA paint and text share price/highlight filter state. */
@@ -1454,6 +1897,12 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1454
1897
  private effSelection;
1455
1898
  /** Colorblind-safe mode (Okabe-Ito hues + hollow booked seats). */
1456
1899
  private colorblind;
1900
+ /** Stable per-category-KEY colorblind hue (OV-46) — order-independent. */
1901
+ private cbHueByKey;
1902
+ /** OV-45(a): authored row-letter labels for the buyer/preview map, resolved in
1903
+ * world space (matching seat labels) and honouring each row's labelPresentation
1904
+ * (position/rotation/visibility/style). Painted at the seats LOD rung. */
1905
+ private rowLabelPlan;
1457
1906
  /** Category order from the doc — the stable index into the CB palette. */
1458
1907
  private catOrder;
1459
1908
  private selection;
@@ -1464,6 +1913,8 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1464
1913
  /** One selected seat being inspected before it is committed to the cart. */
1465
1914
  private selectionFocusId;
1466
1915
  private hoverRing;
1916
+ /** Seat currently owning the shared hover ring (null while not hovering). */
1917
+ private hoveredId;
1467
1918
  /** Keyboard-navigation focus ring + the currently focused seat id. */
1468
1919
  private focusRing;
1469
1920
  private focusedId;
@@ -1482,6 +1933,8 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1482
1933
  private sections;
1483
1934
  private zones;
1484
1935
  private seatSection;
1936
+ /** Seats outside every authored section retain the legacy path in one group. */
1937
+ private unsectionedSeatGroup;
1485
1938
  private catPrice;
1486
1939
  /** ISO 4217 currency for on-map "FROM …" prices (undefined ⇒ money default). */
1487
1940
  private currency;
@@ -1496,6 +1949,9 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1496
1949
  private focusedSectionId;
1497
1950
  /** Light backdrop panel drawn behind the focused section (removed on clear). */
1498
1951
  private focusBackdrop;
1952
+ /** Non-listening visual dim outside the focused section. One overlay replaces
1953
+ * descendant opacity mutations across every seat in the venue. */
1954
+ private focusDimOverlay;
1499
1955
  /** Object id → floor id (multi-floor only) — resolves a deck tap in the 3D stack. */
1500
1956
  private objectFloor;
1501
1957
  /** Zone id → colour (drives extruded side faces in iso view). */
@@ -1507,10 +1963,33 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1507
1963
  private isoT;
1508
1964
  private isoTarget;
1509
1965
  private isoRaf;
1966
+ /** Public view target; perspective is a separate non-affine Phase-C lane. */
1967
+ private viewMode;
1968
+ private perspectiveCamera;
1969
+ /** Ground-plane tangent applied once to every renderer layer. */
1970
+ private perspectiveBaseAffine;
1971
+ private perspectiveBaseInverse;
1972
+ /** Exact pinhole anchor expressed in the overlay tangent-layer coordinates. */
1973
+ private perspectiveSeatLocal;
1974
+ /** Exact projected point (before Stage pan/zoom), keyed by seat. */
1975
+ private perspectiveSeatProjected;
1976
+ /** Positive camera depth, used for deterministic far→near paint order. */
1977
+ private perspectiveSeatDepth;
1978
+ /** Exact pinhole size ratio at each seat anchor. */
1979
+ private perspectiveSeatScale;
1980
+ /** Seats whose native Konva nodes currently carry the exact projected pose.
1981
+ * Large sectioned venues apply these lazily as a section enters the live-seat
1982
+ * viewport; the overview rung hides the seat layer completely. */
1983
+ private perspectiveAppliedSeats;
1984
+ private perspectiveBounds;
1510
1985
  /** Chart centre the iso projection pivots about (bounds centre). */
1511
1986
  private isoCentre;
1512
1987
  /** rAF for an in-flight camera glide (focusRegion / setRung); 0 = none. */
1513
1988
  private glideRaf;
1989
+ /** While the camera tween is active, defer polygon label fitting/collision to
1990
+ * the settled frame. Geometry remains smoothly stage-scaled, while expensive
1991
+ * point-in-polygon text work no longer repeats at 120 Hz. */
1992
+ private glideInProgress;
1514
1993
  /** Set in destroy() so an in-flight iso tween bails. */
1515
1994
  private destroyed;
1516
1995
  /** Cached scale the section/zone labels were last sized for (scale-compensation). */
@@ -1537,6 +2016,28 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1537
2016
  private panStarted;
1538
2017
  /** Maximum displacement from gesture start — suppress taps only after a real pan/pinch. */
1539
2018
  private moved;
2019
+ /**
2020
+ * Ghost-click guard. Konva binds `_pointerup` to mouseup, touchend AND
2021
+ * pointerup, so `on('click tap')` is two handlers for one finger tap unless
2022
+ * the browser's synthesized compatibility click is suppressed. Konva only
2023
+ * suppresses it when the touch lands on a LISTENING SHAPE (Stage.js returns
2024
+ * early before its preventDefault() when `!shape || !shape.isListening()`),
2025
+ * so a near-miss rescued by nearestSeatToScreen used to fire `tap` (select)
2026
+ * then `click` (deselect) 1-3ms apart and net to nothing. With
2027
+ * SEAT_TAP_SLOP_PX=14 against a ~12px seat radius, that broken annulus is
2028
+ * ~3.7x the area of the seat itself — i.e. most successful mobile taps.
2029
+ * `touch-action: none` does NOT suppress compatibility mouse events.
2030
+ */
2031
+ private lastTapAt;
2032
+ /**
2033
+ * True when this is the browser's synthesized compatibility click following a
2034
+ * finger tap we already handled. Discriminates on `e.type` deliberately —
2035
+ * `PointerEvent extends MouseEvent`, so an `instanceof MouseEvent` test
2036
+ * matches genuine pointer taps too. One shared timestamp across the layer and
2037
+ * stage handlers: a tap consumed at the layer must also suppress the ghost at
2038
+ * the stage, and only `click` is ever rejected, so bubbling stays intact.
2039
+ */
2040
+ private isGhostClick;
1540
2041
  /**
1541
2042
  * Manage-mode rubber-band marquee (option-gated). `start`/`cur` are WORLD-space
1542
2043
  * points (overlayLayer rides the stage transform); `rect` is the on-canvas
@@ -1551,6 +2052,9 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1551
2052
  /** The chart to render: all floors stacked (3D overview), the active floor, or
1552
2053
  * the whole chart for single-floor charts. */
1553
2054
  private floorView;
2055
+ /** Physical floor height is authored data; the 900-unit stacked overview
2056
+ * spread is presentation-only and must never leak into real 3D geometry. */
2057
+ private floorBaseHeightMFor;
1554
2058
  /** Toggle the 3D all-floors stacked overview (Batch 5). Re-renders; no-op on
1555
2059
  * single-floor charts. The caller re-applies statuses + animates the iso view. */
1556
2060
  setStacked(on: boolean): void;
@@ -1663,9 +2167,9 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1663
2167
  * geometry stays flat, so hit-testing (Konva's own, plus the manual section
1664
2168
  * inverse) keeps landing on the projected seats/sections.
1665
2169
  */
1666
- setViewMode(mode: 'flat' | 'isometric'): void;
2170
+ setViewMode(mode: RendererViewMode): void;
1667
2171
  /** Current projection — reflects the tween target, not the mid-tween isoT. */
1668
- getViewMode(): 'flat' | 'isometric';
2172
+ getViewMode(): RendererViewMode;
1669
2173
  /** Iso angle (rad) + y-squash for the current isoT. */
1670
2174
  private isoParams;
1671
2175
  /** Effective vertical scale = stage scale × iso squash — legibility math uses this. */
@@ -1674,14 +2178,40 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1674
2178
  private isoForward;
1675
2179
  /** Inverse of isoForward (iso-world → world) for screen-space hit-testing. */
1676
2180
  private isoInverse;
2181
+ /** Precompute the Phase-C pinhole camera and every exact seat anchor. */
2182
+ private buildPerspectiveProjection;
2183
+ /** Apply an affine to a Konva container while keeping `pivot` fixed logically. */
2184
+ private setContainerAffine;
2185
+ private resetContainerTransform;
2186
+ /** Exact raked surface height used for the bounded section tangent plane. */
2187
+ private sectionSurfaceHeight;
2188
+ /** Desired perspective-space point for a section surface, before Stage pan/zoom. */
2189
+ private projectedSectionPoint;
2190
+ /** Shared-layer local point which the ground affine paints at `projected`. */
2191
+ private perspectiveLocalPoint;
1677
2192
  /**
1678
2193
  * Local-space offset that, once the layer applies the iso affine, lifts an
1679
- * object straight UP in iso-world by `elevation × LIFT_PER_STEP × isoT`
1680
- * (= inverse-linear of the pure vertical lift). Zero at isoT=0.
2194
+ * object straight UP in iso-world by `liftWorld × isoT` world units
2195
+ * (= inverse-linear of the pure vertical lift). Zero at isoT=0. `liftWorld` is
2196
+ * the section's resolved real height in world units (Phase B1).
1681
2197
  */
1682
2198
  private isoLiftLocal;
1683
- /** Restore the three layers to identity (flat) — byte-for-byte the original. */
2199
+ /** Restore projection layers to identity (flat) — byte-for-byte the original.
2200
+ * `seatLayer` can be skipped when entering perspective from flat: assigning a
2201
+ * top-level transform invalidates all 14k descendant absolute transforms even
2202
+ * while the semantic overview keeps that layer fully transparent. */
1684
2203
  private resetLayerTransforms;
2204
+ /** Restore section-owned containers before applying another projection. */
2205
+ private resetSectionProjection;
2206
+ /** Move native seat/booth hit shapes to or from their exact pinhole anchors. */
2207
+ private applyExactSeatAnchors;
2208
+ /**
2209
+ * Phase C projected 2.5D. Seat/booth anchors are exact pinhole projections;
2210
+ * section top surfaces use one explicitly bounded tangent plane per authored
2211
+ * section. Native Konva shapes move with the anchors, so direct hit testing is
2212
+ * the same graph that paints the buyer-visible unit.
2213
+ */
2214
+ private applyPerspective;
1685
2215
  /**
1686
2216
  * Apply the current isoT to the scene: the base rotate+squash as a decomposed
1687
2217
  * layer transform (so seats/décor/rings project together and Konva's own
@@ -1701,6 +2231,32 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1701
2231
  * tier shifts with one offset in iso view) or the seat layer directly.
1702
2232
  */
1703
2233
  private seatContainer;
2234
+ /** True when a section belongs to the active logical section/zone focus. */
2235
+ private sectionMatchesFocus;
2236
+ /** Visual opacity after the section-focus overlay is composed. */
2237
+ private focusedSeatOpacity;
2238
+ /** Project a section outline through elevation + the active affine view and
2239
+ * then into viewport pixels. The result is conservative (AABB), so a visible
2240
+ * section is never clipped even for rotated or isometric outlines. */
2241
+ private sectionScreenBounds;
2242
+ /** Hide only section groups wholly outside a padded viewport at the live-seat
2243
+ * rung. Overview caching always restores all groups first, so panning a
2244
+ * cached whole-venue bitmap can never reveal missing inventory. */
2245
+ private updateSeatGroupVisibility;
2246
+ /** Seats worth considering for viewport labels. Section culling is a safe
2247
+ * coarse index; the later screen test remains the exact filter. */
2248
+ private visibleSeatCandidates;
2249
+ private seatViewportCulled;
2250
+ /** Local world coordinate at which an elevated seat is actually painted for
2251
+ * the current iso tween. Flat seats and the 2D endpoint are unchanged. */
2252
+ private renderedSeatPoint;
2253
+ /** Overlay labels mirror the seat-layer lift without an O(seats) per-frame
2254
+ * rewrite. The groups are rebuilt with the zoom-dependent label set. */
2255
+ private seatLabelContainer;
2256
+ /** Shared overlay furniture is not parented to section lift groups, so keep
2257
+ * the small transient set aligned explicitly. Selection is capped in buyer
2258
+ * mode, making this constant-sized work during the iso tween. */
2259
+ private syncSeatOverlayPositions;
1704
2260
  private renderSeats;
1705
2261
  /** A booth renders as a click-selectable rounded block (dims from the doc). */
1706
2262
  private renderBoothUnit;
@@ -1711,12 +2267,14 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1711
2267
  */
1712
2268
  private buildAccessGlyph;
1713
2269
  /**
1714
- * Toggle the accessibility glyphs for the current camera scale: shown once the
1715
- * effective on-screen seat radius clears {@link SEAT_GLYPH_MIN_PX}, otherwise
1716
- * hidden so only the ring remains. Iterates the (small) accessible-seat set,
1717
- * never the full node graph, so it is cheap to call on every view change.
2270
+ * Keep physical wheelchair provision readable in screen space at every map
2271
+ * LOD. The active Wheelchair filter promotes it further. Iterates the small
2272
+ * wheelchair-seat set, never the full node graph.
1718
2273
  */
1719
2274
  private updateAccessGlyphs;
2275
+ /** True only for a physical wheelchair provision matching an active buyer filter. */
2276
+ private accessGlyphFilterEmphasized;
2277
+ private accessGlyphShouldShow;
1720
2278
  /**
1721
2279
  * Whether an accessible seat's glyph should show for its current status. It is
1722
2280
  * hidden on seats a buyer cannot take (sold, or another buyer's hold) where the
@@ -1769,6 +2327,11 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1769
2327
  getFocusedSection(): string | null;
1770
2328
  /** Draw (or replace) the light backdrop panel behind the focused section. */
1771
2329
  private drawFocusBackdrop;
2330
+ /** Dim everything outside the active section with one paint-only shape. Group
2331
+ * opacity would make Konva recursively invalidate absolute-opacity caches on
2332
+ * all 14k descendants. The cut-out follows the live elevation offset and is
2333
+ * non-listening, so direct seat hit-testing is unchanged. */
2334
+ private drawFocusDimOverlay;
1772
2335
  /** Repaint every seat + section block to reflect closed/focus state, then redraw. */
1773
2336
  private repaintSectionsAndSeats;
1774
2337
  /** The world-space rectangle currently visible in the viewport (minimap F3). */
@@ -1814,11 +2377,17 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1814
2377
  */
1815
2378
  private renderSection;
1816
2379
  private refreshSectionHeat;
1817
- /** Recompute a section's neutral overview state and retained detail count. */
2380
+ /** Recompute a section's availability shading + retained availability text. */
1818
2381
  private refreshSectionFill;
1819
2382
  /** True when a section/zone is currently in the `closed` event-state. */
1820
2383
  private isSectionClosed;
1821
- /** Clean overview shells never leak category, price, or live availability paint. */
2384
+ /** Resolve the four-bucket overview availability state for a section (OV-69).
2385
+ * `closed` (operator) outranks live availability; the availability buckets
2386
+ * only apply to seated sections (GA-only shells have no seat capacity here). */
2387
+ private sectionAvailabilityState;
2388
+ /** Overview shells stay neutral except for the bounded availability shading
2389
+ * (nearly-gone / sold-out) and the operator `closed` slab — never category
2390
+ * or price paint, which is deferred to section focus/seat detail. */
1822
2391
  private sectionBlockFill;
1823
2392
  /**
1824
2393
  * Zone rung: one giant screen-constant label per zone (+ optional "FROM $n"),
@@ -1982,6 +2551,15 @@ declare class SeatmapRenderer implements ISeatmapRenderer {
1982
2551
  */
1983
2552
  forceDraw(): void;
1984
2553
  private updateFreeTextVisibility;
2554
+ /** OV-45(a): resolve authored row-letter labels for the buyer/preview map, in
2555
+ * world space, matching the Designer's placement contract (start/end/both/none
2556
+ * preset, a free-drag `position` that wins over the preset, rotation, and
2557
+ * labelStyle colour/size fed through the same auto-contrast guard). Segmented
2558
+ * rows keep their own logical-label handling and are resolved by their owner. */
2559
+ private buildRowLabelPlan;
2560
+ /** Row labels never carry status; the buyer just dims them under the same
2561
+ * category/price filters that dim their seats. */
2562
+ private objectFilteredOut;
1985
2563
  private updateLabels;
1986
2564
  private handleResize;
1987
2565
  private startFpsLoop;
@@ -1994,6 +2572,16 @@ interface PickerSeat {
1994
2572
  /** Buyer-facing label (row `displayLabel` applied). Falls back to `label`;
1995
2573
  * never use for booking — `label` is the inventory/booking identity. */
1996
2574
  displayLabel?: string;
2575
+ /** Buyer-facing object type word authored in Designer. Pure presentation. */
2576
+ displayType?: string;
2577
+ /** @deprecated Use `displayType`; retained for source compatibility. */
2578
+ rowType?: string;
2579
+ /** Stable parent chart-object id (row/table/booth), separate from seat id. */
2580
+ objectId?: string;
2581
+ /** Buyer-facing spatial context shared by selection, hold, and hover callbacks. */
2582
+ sectionLabel?: string;
2583
+ rowLabel?: string;
2584
+ seatNumber?: string;
1997
2585
  categoryKey: string;
1998
2586
  /** Price for the chosen tier when the category has tiers, else the base price. */
1999
2587
  price: number;
@@ -2005,6 +2593,29 @@ interface PickerSeat {
2005
2593
  * note) resolved for this seat; absent when the seat carries none. Lets the
2006
2594
  * buyer cart + confirm surface flag limited-view/premium seats. */
2007
2595
  commercial?: SeatCommercialAttributes;
2596
+ /** Accessibility semantics exposed to SDK callbacks and buyer summaries. */
2597
+ accessibility?: AccessibilityType[];
2598
+ /** Explicit physical wheelchair chair/bay distinction. */
2599
+ wheelchairSpaceType?: 'seat-present' | 'no-seat';
2600
+ /** Physical/bookable source kind; booking identity remains `label`. */
2601
+ objectType?: 'seat' | 'booth' | 'table';
2602
+ /** Grouped-table booking contract; absent for normal chair inventory. */
2603
+ bookingMode?: 'whole' | 'variable';
2604
+ /** Guest quantity represented by this one atomic table line. */
2605
+ quantity?: number;
2606
+ capacity?: number;
2607
+ minOccupancy?: number;
2608
+ maxOccupancy?: number;
2609
+ }
2610
+ /** Accessible quantity/confirmation payload for one model-2 table selection. */
2611
+ interface TableSelectionDetails extends PickerSeat {
2612
+ objectType: 'table';
2613
+ bookingMode: 'whole' | 'variable';
2614
+ quantity: number;
2615
+ capacity: number;
2616
+ minOccupancy: number;
2617
+ maxOccupancy: number;
2618
+ physicalSeatIds: string[];
2008
2619
  }
2009
2620
  /**
2010
2621
  * Rich hover payload for seat tooltips — the PickerSeat plus everything a
@@ -2016,13 +2627,20 @@ interface SeatHoverDetails extends PickerSeat {
2016
2627
  categoryColor: string;
2017
2628
  status: SeatStatus;
2018
2629
  currency: string;
2019
- /** Human-readable spatial context for hover and confirmation UI. */
2020
- sectionLabel?: string;
2021
- rowLabel?: string;
2022
- seatNumber?: string;
2023
- /** Buyer-facing type word for the row/table (seats.io "Displayed type"),
2024
- * overriding the default "Row" in tooltip/confirm/cart. Absent = "Row". */
2025
- rowType?: string;
2630
+ }
2631
+ interface PickerGAArea {
2632
+ id: string;
2633
+ /** Stable technical/inventory prefix. */
2634
+ label: string;
2635
+ /** Buyer-facing area name and type; absent fields use UI defaults. */
2636
+ displayLabel?: string;
2637
+ displayType?: string;
2638
+ capacity: number;
2639
+ available: number;
2640
+ categoryKey: string;
2641
+ price: number;
2642
+ currency: string;
2643
+ tiers?: CategoryTier[];
2026
2644
  }
2027
2645
  interface HoldConflict {
2028
2646
  label: string;
@@ -2053,6 +2671,7 @@ interface SectionCategory {
2053
2671
  */
2054
2672
  interface SectionSummary {
2055
2673
  id: string;
2674
+ /** Buyer-facing section name (`displayLabel` when set, else the inventory label). */
2056
2675
  label: string;
2057
2676
  /** Zone label (from ChartDoc.zones); '' when the section has no zone. */
2058
2677
  zoneLabel: string;
@@ -2078,7 +2697,7 @@ interface ResumeHoldResponse extends HoldResponse {
2078
2697
  interface HoldServerItem {
2079
2698
  label: string;
2080
2699
  objectId: string;
2081
- objectType: 'seat' | 'booth' | 'ga';
2700
+ objectType: 'seat' | 'booth' | 'ga' | 'table';
2082
2701
  categoryKey: string;
2083
2702
  tierId: string | null;
2084
2703
  unitPrice: number;
@@ -2088,6 +2707,7 @@ interface HoldServerItem {
2088
2707
  interface HoldSelectionRequest {
2089
2708
  label: string;
2090
2709
  tierId?: string | null;
2710
+ quantity?: number;
2091
2711
  }
2092
2712
  interface BestAvailableResponse extends HoldResponse {
2093
2713
  labels: string[];
@@ -2104,6 +2724,7 @@ interface PickerTransport {
2104
2724
  startsAt?: number | null;
2105
2725
  currency?: string;
2106
2726
  mode?: string;
2727
+ inventoryModelVersion?: 1 | 2;
2107
2728
  };
2108
2729
  }>;
2109
2730
  objects(key: string): Promise<{
@@ -2112,7 +2733,7 @@ interface PickerTransport {
2112
2733
  closed?: string[];
2113
2734
  }>;
2114
2735
  hold(key: string, selections: HoldSelectionRequest[], ttlMs?: number, replaceHoldId?: string): Promise<HoldResponse>;
2115
- bestAvailable(key: string, qty: number, categoryKey?: string): Promise<BestAvailableResponse>;
2736
+ bestAvailable(key: string, qty: number, categoryKey?: string, zoneId?: string): Promise<BestAvailableResponse>;
2116
2737
  release(key: string, labels: string[], holdId: string): Promise<unknown>;
2117
2738
  /** Optional capability-style lookup used to restore an active browser hold. */
2118
2739
  resume?(key: string, holdId: string): Promise<ResumeHoldResponse>;
@@ -2129,6 +2750,8 @@ interface PickerTransport {
2129
2750
  interface PickerCallbacks extends RendererCallbacks {
2130
2751
  /** Selection changed (manual clicks or a server best-available pick). */
2131
2752
  onSelectionChange?: (seats: PickerSeat[]) => void;
2753
+ /** A grouped table was selected and needs buyer confirmation/guest quantity. */
2754
+ onTableSelectionRequest?: (table: TableSelectionDetails) => void;
2132
2755
  /** A hold opened (manual hold or best-available). */
2133
2756
  onHold?: (hold: HoldInfo) => void;
2134
2757
  /** A prior active hold was restored from its opaque hold id. */
@@ -2210,6 +2833,14 @@ declare class PickerController {
2210
2833
  /** id → buyer-facing spatial metadata used by every tooltip/confirm surface. */
2211
2834
  private seatContext;
2212
2835
  private allIds;
2836
+ /** Model-2 tables are one booking unit whose chairs remain renderer geometry. */
2837
+ private groupedTablesByObject;
2838
+ private groupedTablesByLabel;
2839
+ private groupedTableBySeatId;
2840
+ private tableQuantities;
2841
+ /** Variable quantity is a buyer contract, never an inferred default. */
2842
+ private confirmedVariableTables;
2843
+ private groupedSelectionOverhead;
2213
2844
  private ws;
2214
2845
  private reconnectTimer;
2215
2846
  private attempt;
@@ -2237,6 +2868,10 @@ declare class PickerController {
2237
2868
  getRenderer(): ISeatmapRenderer | null;
2238
2869
  seatByLabel(label: string): ExpandedSeat | undefined;
2239
2870
  idForLabel(label: string): string | undefined;
2871
+ private idsForLabel;
2872
+ private idsForLabels;
2873
+ /** Resolve a physical chair id (or table inventory label) to its table unit. */
2874
+ tableSelection(seatIdOrLabel: string): TableSelectionDetails | null;
2240
2875
  /** Fetch chart, build label maps, mount the renderer, seed statuses, go live. */
2241
2876
  render(host: HTMLDivElement): Promise<{
2242
2877
  doc: ChartDoc;
@@ -2255,6 +2890,17 @@ declare class PickerController {
2255
2890
  deselect(ids: string[]): void;
2256
2891
  setMaxSelection(maxSelection: number): void;
2257
2892
  select(ids: string[]): PickerSeat[];
2893
+ /** Confirm/update the guest quantity for a selected variable table. */
2894
+ setTableQuantity(label: string, quantity: number): boolean;
2895
+ /** Atomically replace an active variable-table hold with a new guest count. */
2896
+ replaceTableQuantity(label: string, quantity: number): Promise<HoldInfo | null>;
2897
+ private rendererSelectionCap;
2898
+ private selectionGuestCount;
2899
+ private handleRendererSelect;
2900
+ private handleRendererDeselect;
2901
+ private resetUnheldTableQuantities;
2902
+ private resetTableQuantitiesForLabels;
2903
+ private tableQuantityRequest;
2258
2904
  /**
2259
2905
  * Hold the current selection (or a given label set). The controller does the
2260
2906
  * renderer/hold side (409 → deselect + repaint the taken seats held) and then
@@ -2281,16 +2927,7 @@ declare class PickerController {
2281
2927
  categoryAvailability(): Record<string, number>;
2282
2928
  /** Seat ids belonging to a currently-closed section (excluded from counts). */
2283
2929
  private closedMemberIds;
2284
- getGAAreas(): {
2285
- id: string;
2286
- label: string;
2287
- capacity: number;
2288
- available: number;
2289
- categoryKey: string;
2290
- price: number;
2291
- currency: string;
2292
- tiers?: CategoryTier[];
2293
- }[];
2930
+ getGAAreas(): PickerGAArea[];
2294
2931
  /** Select a quantity from one GA area and hold it atomically. */
2295
2932
  holdGA(areaId: string, qty: number, options?: {
2296
2933
  tierId?: string | null;
@@ -2300,6 +2937,11 @@ declare class PickerController {
2300
2937
  * flag — gates the buyer widget's "★ Best seats" premium quick-pick (chip is
2301
2938
  * present-only, exactly like the accessibility filter chips). */
2302
2939
  hasPremiumSeats(): boolean;
2940
+ /** Zones which still own visible buyer inventory, in authored order. */
2941
+ getBestAvailableZones(): Array<{
2942
+ id: string;
2943
+ label: string;
2944
+ }>;
2303
2945
  /**
2304
2946
  * Client-side premium pre-pass: find the best contiguous block of `qty`
2305
2947
  * PREMIUM-flagged free seats (orphan-avoiding, closest to the focal point)
@@ -2317,6 +2959,7 @@ declare class PickerController {
2317
2959
  */
2318
2960
  bestAvailable(qty: number, categoryKey?: string, opts?: {
2319
2961
  preferPremium?: boolean;
2962
+ zoneId?: string;
2320
2963
  }): Promise<HoldInfo | null>;
2321
2964
  /**
2322
2965
  * Complete a booking. Requires a transport that supports book() (the SDK
@@ -2372,9 +3015,9 @@ declare class PickerController {
2372
3015
  /** Tap-a-deck-to-enter: leave the 3D stack, drop to flat 2D on `floorId`, and
2373
3016
  * tell the host so it can sync its 2D/3D toggle + floor-switcher state. */
2374
3017
  private handleDeckTap;
2375
- /** Switch the map projection (2D flat ⇄ 3D isometric). No-op on a flat renderer. */
2376
- setViewMode(mode: 'flat' | 'isometric'): void;
2377
- getViewMode(): 'flat' | 'isometric';
3018
+ /** Switch the map projection. No-op on a flat-only renderer. */
3019
+ setViewMode(mode: RendererViewMode): void;
3020
+ getViewMode(): RendererViewMode;
2378
3021
  /** Current LOD rung (for the ZONES/SECTIONS/SEATS pill). */
2379
3022
  getRung(): LodRung;
2380
3023
  /** Jump to a rung; ZONES clears any focused summary (back to overview). */
@@ -2421,6 +3064,7 @@ declare class PickerController {
2421
3064
  private sectionSummary;
2422
3065
  destroy(): void;
2423
3066
  private toSeat;
3067
+ private toTableSeat;
2424
3068
  /** Tooltip payload for a hovered seat — see PickerCallbacks.onSeatHover. */
2425
3069
  private describeSeat;
2426
3070
  private priceFor;
@@ -2573,4 +3217,4 @@ declare function formatMoney(amount: number, currency?: string, fractionDigits?:
2573
3217
  /** Bare symbol for input adornments ("€", "$", "₹"). */
2574
3218
  declare function currencySymbol(currency?: string): string;
2575
3219
 
2576
- export { ACCESSIBILITY_RING_COLOR, 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, LABEL_STYLE_MAX_SIZE, LABEL_STYLE_MIN_SIZE, type LabelPresentation, type LabelStyle, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PanoramaResult, type PickerCallbacks, PickerController, type PickerOptions, type PickerSeat, type PickerTransport, type Point, RENDERED_QUALITY_REPORT_VERSION, type ReferenceAccessibilitySource, type ReferenceCalibration, type ReferenceCategorySource, type ReferenceDerivedScale, type ReferenceInventoryExclusionSource, type ReferenceInventorySource, type RenderedBookableLabelEvidence, type RenderedEvidenceState, type RenderedFreeTextEvidence, type RenderedGAAreaEvidence, type RenderedHierarchyLabelEvidence, type RenderedLabelHiddenReason, type RenderedQualityFinding, type RenderedQualityFindingCode, type RenderedQualityReport, type RenderedQualitySample, type RendererCallbacks, type RendererOptions, type RendererQualityEvidence, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, type SeatCommercialAttributes, 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, accessibilityRingColor, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, floorObjects, floorsOf, formatDate, formatMoney, gaAreasOf, gaUnitLabel, gaUnitLabels, generateSeatPanorama, generateSeatThumb, getLocale, hiddenObjectIds, inspectRenderedQualityEvidence, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, pointInPolygon, pointInPolygonWithHoles, polygonLabelPoint, resolveLocale, rowSeatPositions, seatLabelPart, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount };
3220
+ export { ACCESSIBILITY_RING_COLOR, 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 ExpandChartOptions, type ExpandedSeat, type Floor, type GAAreaObject, type GAInventorySegment, type HoldConflict, type HoldInfo, type HoldSelectionRequest, type HoldServerItem, type ISeatmapRenderer, LABEL_STYLE_MAX_SIZE, LABEL_STYLE_MIN_SIZE, type LabelPresentation, type LabelStyle, type Locale, type LodRung, MAX_EVENT_INVENTORY, MAX_GA_CAPACITY, type PanoramaResult, type PickerCallbacks, PickerController, type PickerGAArea, type PickerOptions, type PickerSeat, type PickerTransport, type Point, RENDERED_QUALITY_REPORT_VERSION, type RectTableSeatCounts, type RectTableSide, type ReferenceAccessibilitySource, type ReferenceCalibration, type ReferenceCategorySource, type ReferenceDerivedScale, type ReferenceInventoryExclusionSource, type ReferenceInventorySource, type ReferenceScanProposal, type ReferenceScanRowProposal, type ReferenceScanSectionProposal, type ReferenceSeatSeed, type RenderedBookableLabelEvidence, type RenderedEvidenceState, type RenderedFreeTextEvidence, type RenderedGAAreaEvidence, type RenderedHierarchyLabelEvidence, type RenderedLabelHiddenReason, type RenderedQualityFinding, type RenderedQualityFindingCode, type RenderedQualityReport, type RenderedQualitySample, type RendererCallbacks, type RendererOptions, type RendererQualityEvidence, type RendererViewMode, type RowObject, type RowSeatSlot, SUPPORTED_LOCALES, SURROUNDINGS_SHAPE_ROLES, type SeatCommercialAttributes, type SeatHoverDetails, type SeatOverride, type SeatStatus, SeatmapRenderer, type SectionCategory, type SectionNode, type SectionObject, type SectionOutlinePath, type SectionPathSegment, type SectionSummary, type SelectionLayer, type ShapeLineCap, type ShapeLineEnding, type ShapeLineJoin, type ShapeObject, TIER_HEIGHT_M, type TableObject, type TableSeatSlot, type TableSelectionDetails, type TextObject, UNGROUPED_ID, type ZoneDef, accessibilityMeta, accessibilityRingColor, allObjects, applyHidden, chartBounds, computeSections, createRenderer, currencySymbol, expandBooth, expandChart, expandRow, expandRowSlots, expandTable, expandTableSlots, floorObjects, floorsOf, formatDate, formatMoney, gaAreasOf, gaInventorySegments, gaUnitLabel, gaUnitLabels, generateSeatPanorama, generateSeatThumb, getLocale, growJoinedGAInventory, hiddenObjectIds, inspectRenderedQualityEvidence, isGaUnitLabel, isSectionHidden, layerOf, loadLocale, objectCenter, owningSectionForObject, pointInPolygon, pointInPolygonWithHoles, polygonLabelPoint, resolveLocale, rowInventoryCount, rowSeatPositions, seatLabelPart, sectionGeometry, setLocale, setMoneyLocale, setStringOverrides, stackFloors, t, tCount, tableInventoryCount, tableSeatCountsBySide, validGAInventorySegments };