@mj-biz-apps/sales-ng 6.7.1 → 6.8.1

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.
Files changed (38) hide show
  1. package/dist/lib/form-panels/deal-form.panels.d.ts +54 -4
  2. package/dist/lib/form-panels/deal-form.panels.d.ts.map +1 -1
  3. package/dist/lib/form-panels/deal-form.panels.js +111 -31
  4. package/dist/lib/form-panels/deal-form.panels.js.map +1 -1
  5. package/dist/lib/form-panels/deal-line-editor.component.d.ts.map +1 -1
  6. package/dist/lib/form-panels/deal-line-editor.component.js +56 -5
  7. package/dist/lib/form-panels/deal-line-editor.component.js.map +1 -1
  8. package/dist/lib/generated/Entities/mjBizAppsSalesPipeline/mjbizappssalespipeline.form.component.js +31 -29
  9. package/dist/lib/generated/Entities/mjBizAppsSalesPipeline/mjbizappssalespipeline.form.component.js.map +1 -1
  10. package/dist/lib/pages/dashboard-dates.d.ts +12 -20
  11. package/dist/lib/pages/dashboard-dates.d.ts.map +1 -1
  12. package/dist/lib/pages/dashboard-dates.js +39 -5
  13. package/dist/lib/pages/dashboard-dates.js.map +1 -1
  14. package/dist/lib/pages/dashboard-inspect.d.ts +12 -2
  15. package/dist/lib/pages/dashboard-inspect.d.ts.map +1 -1
  16. package/dist/lib/pages/dashboard-inspect.js +16 -4
  17. package/dist/lib/pages/dashboard-inspect.js.map +1 -1
  18. package/dist/lib/pages/dashboard-period.d.ts +6 -1
  19. package/dist/lib/pages/dashboard-period.d.ts.map +1 -1
  20. package/dist/lib/pages/dashboard-period.js +8 -3
  21. package/dist/lib/pages/dashboard-period.js.map +1 -1
  22. package/dist/lib/sections/sales-section.component.d.ts +6 -0
  23. package/dist/lib/sections/sales-section.component.d.ts.map +1 -1
  24. package/dist/lib/sections/sales-section.component.js +32 -14
  25. package/dist/lib/sections/sales-section.component.js.map +1 -1
  26. package/dist/lib/workspace/deal-workspace.component.d.ts +39 -3
  27. package/dist/lib/workspace/deal-workspace.component.d.ts.map +1 -1
  28. package/dist/lib/workspace/deal-workspace.component.js +99 -19
  29. package/dist/lib/workspace/deal-workspace.component.js.map +1 -1
  30. package/dist/lib/workspace/deal-workspace.dates.d.ts +19 -27
  31. package/dist/lib/workspace/deal-workspace.dates.d.ts.map +1 -1
  32. package/dist/lib/workspace/deal-workspace.dates.js +29 -24
  33. package/dist/lib/workspace/deal-workspace.dates.js.map +1 -1
  34. package/dist/lib/workspace/deal-workspace.service.d.ts +18 -1
  35. package/dist/lib/workspace/deal-workspace.service.d.ts.map +1 -1
  36. package/dist/lib/workspace/deal-workspace.service.js +16 -2
  37. package/dist/lib/workspace/deal-workspace.service.js.map +1 -1
  38. package/package.json +4 -3
@@ -195,6 +195,48 @@ interface DealFieldSpec {
195
195
  currency?: boolean;
196
196
  }
197
197
  export declare class MJSDealOverviewPanel extends BaseFormPanel<DealEntity> {
198
+ /**
199
+ * HAS THE BUSINESS ZONE BEEN LOADED? (bc-aidp-next-golive#168)
200
+ *
201
+ * A SIGNAL, for the reason the Pipeline panel's `statuses` is one: the host is OnPush and nothing
202
+ * marks this panel dirty when `Config()` resolves, so the four getters below would paint their
203
+ * first values from the unconfigured engine and keep them. Read inside {@link daysFromToday},
204
+ * which every one of them goes through, so the template's read of any countdown registers the
205
+ * dependency and re-runs once the zone lands. `inject(ChangeDetectorRef)` would also do it and
206
+ * would cost `new MJSDealOverviewPanel()` in a unit test.
207
+ *
208
+ * `?.()` because the suites construct panels with `Object.create(prototype)`, which runs no field
209
+ * initialisers — an absent signal means "not marked", never a throw out of a template binding.
210
+ */
211
+ private readonly businessZoneLoaded;
212
+ /**
213
+ * THE ZONE IS LOADED BEFORE THIS PANEL IS ASKED WHAT DAY IT IS (bc-aidp-next-golive#168).
214
+ *
215
+ * `BusinessTimeZoneEngine` FAILS OPEN TO UTC when it has not been configured — that is its
216
+ * documented contract, and it is silently the exact defect #168 exists to fix, so an unconfigured
217
+ * read is not a neutral default but the old close clock wearing the new code. `@RegisterForStartup()`
218
+ * means MJ's boot sequence configures it, but `sales-ng` is a lazily-loaded chunk that a deal form
219
+ * can mount before or without that sequence having run here, and the two other `Today()` call sites
220
+ * in this app (`deal-workspace.service.ts`, `sales-section.component.ts`) already refuse to rely on
221
+ * it. This one was left relying on it.
222
+ *
223
+ * `Config(false)` is idempotent and a no-op once loaded, so mounting the panel costs nothing after
224
+ * the first time, and the engine resolves to UTC rather than throwing when no configuration row
225
+ * exists — a host that has not set a zone behaves exactly as it did before.
226
+ *
227
+ * BaseFormPanel declares no lifecycle hook, so there is nothing to chain to.
228
+ */
229
+ ngOnInit(): Promise<void>;
230
+ /**
231
+ * {@link daysFrom}, read through the load signal above.
232
+ *
233
+ * Every today-relative getter on this panel goes through here rather than calling `daysFrom`
234
+ * directly, so there is ONE place that both marks the zone dependency and can be pointed at when
235
+ * asking "what configured the engine for this figure?" — a second call site that skipped it would
236
+ * paint a UTC countdown next to a business-day one on the same tile, which is the disagreement
237
+ * #168 was filed about in the first place.
238
+ */
239
+ private daysFromToday;
198
240
  G(field: string): string;
199
241
  get Money(): string;
200
242
  get Weighted(): string;
@@ -654,10 +696,18 @@ export declare class MJSDealClosePanel extends MJSDealFieldPanel {
654
696
  * The audited way back through the lock (bc-aidp-next-golive#205).
655
697
  *
656
698
  * Mirrors {@link ConfirmClose}, including the part that is easy to drop: a reopen can return
657
- * `Success: true` WITH issues, and those are the ones that matter most. S-US8's reopen asks the
658
- * order to come back while it sits at `Voided`, which orders treats as terminal — the deal reopens
659
- * regardless, because an order-side refusal must never block a stage change, so this list is the
660
- * only thing standing between the rep and a live deal pointing at a dead order.
699
+ * `Success: true` WITH issues, and those are the ones that matter most. The deal reopens
700
+ * regardless of what the order does, because an order-side refusal must never block a stage
701
+ * change — so this list is the only thing standing between the rep and a live deal pointing at a
702
+ * dead order.
703
+ *
704
+ * THIS USED TO SAY the reopen "asks the order to come back while it sits at `Voided`, which orders
705
+ * treats as terminal". It does not: `TRANSITIONS.Voided` is `['Draft', 'Quoted']`, so
706
+ * `IsTerminal('Voided')` is FALSE and `Confirmed` is the terminal status. Recorded once in
707
+ * `docs/DECISIONS.md` D-OS4; KI-27 is the lifecycle collapse that caused it, not the transition
708
+ * fact itself. The cases that genuinely leave an order behind are a BOOKED order, which the reopen
709
+ * refuses outright, and — until golive#205 — a restored stage that declared nothing, which asked
710
+ * the order for nothing and said nothing either.
661
711
  *
662
712
  * IT DOES SAVE FIRST, which this comment used to say it must not. The old reasoning was that "a
663
713
  * locked deal has almost nothing editable, and the close lock would refuse the save anyway". Both
@@ -1 +1 @@
1
- {"version":3,"file":"deal-form.panels.d.ts","sourceRoot":"","sources":["../../../src/lib/form-panels/deal-form.panels.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deal-form.panels.d.ts","sourceRoot":"","sources":["../../../src/lib/form-panels/deal-form.panels.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,7 @@ import { CommonModule } from '@angular/common';
22
22
  import { FormsModule } from '@angular/forms';
23
23
  import { CompositeKey, Metadata, RunView, EntitySaveOptions } from '@memberjunction/core';
24
24
  import { RegisterClassEx } from '@memberjunction/global';
25
+ import { BusinessTimeZoneEngine, FromCalendarDay, ToCalendarDay } from '@mj-biz-apps/common-entities';
25
26
  import { BaseFormPanel, BaseFormsModule, ExplorerEntityDataGridComponent } from '@memberjunction/ng-base-forms';
26
27
  import { EntityViewerModule, } from '@memberjunction/ng-entity-viewer';
27
28
  import { IsDealFieldEditableWhileLocked, LoadDealStatusOptions, } from '@mj-biz-apps/sales-entities';
@@ -1048,7 +1049,7 @@ async function LoadLossReasons() {
1048
1049
  *
1049
1050
  * TWO LAYERS OF SUCCESS. `Success` on the envelope means the operation RAN; whether the deal reopened
1050
1051
  * is `Output.Success`. And a SUCCESSFUL reopen still carries issues worth showing: S-US8 reopens behind
1051
- * an order orders treats as terminal, and that list is the only thing between the rep and a live deal
1052
+ * an order the deal cannot be worked from, and that list is the only thing between the rep and a live deal
1052
1053
  * pointing at a dead order.
1053
1054
  */
1054
1055
  /**
@@ -1229,18 +1230,41 @@ function moneyExact(n) {
1229
1230
  style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2,
1230
1231
  });
1231
1232
  }
1233
+ /**
1234
+ * Whole days from TODAY to a stored day. Negative is in the past.
1235
+ *
1236
+ * ── TWO READS, AND ONLY ONE OF THEM HAS A ZONE (bc-aidp-next-golive#168) ────────────────────────
1237
+ *
1238
+ * The STORED side is a `DATE` column — a calendar day with no time and no zone, handed back as UTC
1239
+ * midnight — so `ToCalendarDay` reads it from UTC parts and takes a string as written. That half was
1240
+ * always right and has not moved.
1241
+ *
1242
+ * TODAY is the half that was wrong. It read `now.getUTC*()`, so the countdown rolled over at UTC
1243
+ * midnight: from 19:00 Central every close clock, every "overdue" verdict and the next-step warning
1244
+ * jumped a day early. A deal closing tomorrow read "today" all evening, and after #168 fixed the
1245
+ * product picker the same screen carried two different ideas of what day it was.
1246
+ *
1247
+ * SYNCHRONOUS, like the getters that call it — so IT DOES NOT CONFIGURE THE ENGINE, and must never be
1248
+ * reached before something else has. `MJSDealOverviewPanel.ngOnInit` is that something else, and
1249
+ * {@link MJSDealOverviewPanel.daysFromToday} is the only way in; call this directly from a new panel
1250
+ * and you get UTC.
1251
+ *
1252
+ * The reasoning this replaces said `@RegisterForStartup()` made the boot sequence enough, and that the
1253
+ * UTC fallback made the worst case harmless. Both halves were wrong together: `sales-ng` is a lazily
1254
+ * loaded chunk, and the UTC fallback IS the defect #168 fixes — falling open to it here restores the
1255
+ * old close clock silently, with one logged warning nobody reads. Failing open is still the right
1256
+ * contract (a date default that throws out of a template binding is worse), which is exactly why the
1257
+ * `Config()` has to be arranged for rather than assumed.
1258
+ *
1259
+ * Both sides are converted through `FromCalendarDay`, i.e. UTC midnight, so the subtraction is whole
1260
+ * days with no DST remainder to round away. `Math.round` is kept as a belt on that brace.
1261
+ */
1232
1262
  function daysFrom(d) {
1233
- if (!d)
1234
- return null;
1235
- const iso = d instanceof Date
1236
- ? `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`
1237
- : String(d).slice(0, 10);
1238
- const t = Date.parse(`${iso}T00:00:00Z`);
1239
- if (!Number.isFinite(t))
1263
+ const day = ToCalendarDay(d);
1264
+ if (day === null)
1240
1265
  return null;
1241
- const now = new Date();
1242
- const today = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
1243
- return Math.round((t - today) / 86_400_000);
1266
+ const today = BusinessTimeZoneEngine.Instance.Today();
1267
+ return Math.round((FromCalendarDay(day).getTime() - FromCalendarDay(today).getTime()) / 86_400_000);
1244
1268
  }
1245
1269
  /**
1246
1270
  * Whole days from one date to another, both read as UTC days.
@@ -1567,6 +1591,54 @@ const FIELD_STYLES = `
1567
1591
  `;
1568
1592
  /* ── Overview ─────────────────────────────────────────────────────────────── */
1569
1593
  let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
1594
+ /**
1595
+ * HAS THE BUSINESS ZONE BEEN LOADED? (bc-aidp-next-golive#168)
1596
+ *
1597
+ * A SIGNAL, for the reason the Pipeline panel's `statuses` is one: the host is OnPush and nothing
1598
+ * marks this panel dirty when `Config()` resolves, so the four getters below would paint their
1599
+ * first values from the unconfigured engine and keep them. Read inside {@link daysFromToday},
1600
+ * which every one of them goes through, so the template's read of any countdown registers the
1601
+ * dependency and re-runs once the zone lands. `inject(ChangeDetectorRef)` would also do it and
1602
+ * would cost `new MJSDealOverviewPanel()` in a unit test.
1603
+ *
1604
+ * `?.()` because the suites construct panels with `Object.create(prototype)`, which runs no field
1605
+ * initialisers — an absent signal means "not marked", never a throw out of a template binding.
1606
+ */
1607
+ businessZoneLoaded = signal(false, ...(ngDevMode ? [{ debugName: "businessZoneLoaded" }] : []));
1608
+ /**
1609
+ * THE ZONE IS LOADED BEFORE THIS PANEL IS ASKED WHAT DAY IT IS (bc-aidp-next-golive#168).
1610
+ *
1611
+ * `BusinessTimeZoneEngine` FAILS OPEN TO UTC when it has not been configured — that is its
1612
+ * documented contract, and it is silently the exact defect #168 exists to fix, so an unconfigured
1613
+ * read is not a neutral default but the old close clock wearing the new code. `@RegisterForStartup()`
1614
+ * means MJ's boot sequence configures it, but `sales-ng` is a lazily-loaded chunk that a deal form
1615
+ * can mount before or without that sequence having run here, and the two other `Today()` call sites
1616
+ * in this app (`deal-workspace.service.ts`, `sales-section.component.ts`) already refuse to rely on
1617
+ * it. This one was left relying on it.
1618
+ *
1619
+ * `Config(false)` is idempotent and a no-op once loaded, so mounting the panel costs nothing after
1620
+ * the first time, and the engine resolves to UTC rather than throwing when no configuration row
1621
+ * exists — a host that has not set a zone behaves exactly as it did before.
1622
+ *
1623
+ * BaseFormPanel declares no lifecycle hook, so there is nothing to chain to.
1624
+ */
1625
+ async ngOnInit() {
1626
+ await BusinessTimeZoneEngine.Instance.Config(false);
1627
+ this.businessZoneLoaded.set(true);
1628
+ }
1629
+ /**
1630
+ * {@link daysFrom}, read through the load signal above.
1631
+ *
1632
+ * Every today-relative getter on this panel goes through here rather than calling `daysFrom`
1633
+ * directly, so there is ONE place that both marks the zone dependency and can be pointed at when
1634
+ * asking "what configured the engine for this figure?" — a second call site that skipped it would
1635
+ * paint a UTC countdown next to a business-day one on the same tile, which is the disagreement
1636
+ * #168 was filed about in the first place.
1637
+ */
1638
+ daysFromToday(d) {
1639
+ this.businessZoneLoaded?.();
1640
+ return daysFrom(d);
1641
+ }
1570
1642
  G(field) {
1571
1643
  const v = this.Record?.Get?.(field);
1572
1644
  return v == null || v === '' ? '' : String(v);
@@ -1603,7 +1675,7 @@ let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
1603
1675
  * a claim about a caller that no longer exists, and the next reader has no way to tell.
1604
1676
  */
1605
1677
  get DaysToCloseLabel() {
1606
- const n = daysFrom(this.Record?.ExpectedCloseDate);
1678
+ const n = this.daysFromToday(this.Record?.ExpectedCloseDate);
1607
1679
  if (n === null)
1608
1680
  return '—';
1609
1681
  if (n < 0)
@@ -1633,7 +1705,7 @@ let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
1633
1705
  return String(this.Record?.Get?.('ForecastCategoryType') ?? '') || '—';
1634
1706
  }
1635
1707
  get CloseClock() {
1636
- const n = daysFrom(this.Record?.ExpectedCloseDate);
1708
+ const n = this.daysFromToday(this.Record?.ExpectedCloseDate);
1637
1709
  // A closed deal shows WHEN it closed. Counting days against an expected date it already met
1638
1710
  // (or missed) is advice on a decision nobody can take any more.
1639
1711
  if (this.IsClosed) {
@@ -1762,7 +1834,7 @@ let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
1762
1834
  // Nothing is overdue on a deal that is finished.
1763
1835
  if (this.IsClosed)
1764
1836
  return false;
1765
- const n = daysFrom(this.Record?.NextStepDate);
1837
+ const n = this.daysFromToday(this.Record?.NextStepDate);
1766
1838
  return n !== null && n < 0;
1767
1839
  }
1768
1840
  get Health() {
@@ -1779,7 +1851,7 @@ let MJSDealOverviewPanel = class MJSDealOverviewPanel extends BaseFormPanel {
1779
1851
  // that is finished -- re-date it, assign it, give it a next step -- and none of it applies.
1780
1852
  if (this.IsClosed)
1781
1853
  return out;
1782
- const days = daysFrom(this.Record.ExpectedCloseDate);
1854
+ const days = this.daysFromToday(this.Record.ExpectedCloseDate);
1783
1855
  if (days !== null && days < 0 && !this.Record.ActualCloseDate) {
1784
1856
  out.push('The expected close date has passed. Update the date or close the deal.');
1785
1857
  }
@@ -1990,7 +2062,7 @@ export { MJSDealOverviewPanel };
1990
2062
  </mj-collapsible-panel>
1991
2063
  `, styles: ["\n .mjs-ov { display: flex; flex-direction: column; gap: var(--mj-space-4); padding: var(--mj-space-3) var(--mj-space-4) var(--mj-space-5); }\n .mjs-ov-health { display: flex; flex-direction: column; gap: var(--mj-space-2); }\n .mjs-ov-alert {\n display: flex; align-items: center; gap: var(--mj-space-2);\n padding: var(--mj-space-2) var(--mj-space-3);\n background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text);\n border-radius: var(--mj-radius-md); font-size: var(--mj-text-sm); font-weight: 600;\n }\n .mjs-ov-ok {\n display: flex; align-items: center; gap: var(--mj-space-2);\n padding: var(--mj-space-2) var(--mj-space-3);\n background: var(--mj-status-success-bg); color: var(--mj-status-success-text);\n border-radius: var(--mj-radius-md); font-size: var(--mj-text-sm); font-weight: 600;\n }\n .mjs-ov-strip {\n display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: var(--mj-space-3);\n }\n @media (max-width: 900px) { .mjs-ov-strip { grid-template-columns: 1fr 1fr; } }\n .mjs-ov-kpi {\n background: var(--mj-bg-page); border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md); padding: var(--mj-space-3) var(--mj-space-4);\n }\n .mjs-ov-kpi .l {\n font-size: var(--mj-text-xs); text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700;\n }\n .mjs-ov-kpi .v { font-size: 1.35rem; font-weight: 800; letter-spacing: -.02em; margin-top: 4px; line-height: 1.2; }\n .mjs-ov-kpi .s { color: var(--mj-text-muted); font-size: var(--mj-text-sm); margin-top: 2px; }\n .mjs-ov-kpi[data-tone='warning'] .v { color: var(--mj-status-warning-text); }\n .mjs-ov-kpi[data-tone='success'] .v { color: var(--mj-status-success-text); }\n .mjs-ov-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--mj-space-3); }\n @media (max-width: 800px) { .mjs-ov-grid { grid-template-columns: 1fr; } }\n .mjs-ov-card {\n background: var(--mj-bg-page); border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md); padding: var(--mj-space-3) var(--mj-space-4);\n }\n .mjs-ov-card--wide { grid-column: 1 / -1; }\n .mjs-ov-card header {\n display: flex; align-items: center; gap: 8px;\n font-weight: 700; margin-bottom: var(--mj-space-3); color: var(--mj-text-primary);\n }\n .mjs-ov-card header i { color: var(--mj-brand-primary); width: 1.1rem; text-align: center; }\n .mjs-ov-facts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--mj-space-3); }\n .mjs-ov-facts .l {\n font-size: var(--mj-text-xs); text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700;\n }\n .mjs-ov-facts .v { font-weight: 650; margin-top: 2px; }\n /* The loss reason carries free-text notes under it, so it takes the full row rather than\n squeezing a sentence into a half-width cell. */\n .mjs-ov-fact--span { grid-column: 1 / -1; }\n .mjs-ov-fact--span .s {\n margin-top: 2px; font-weight: 450; color: var(--mj-text-muted);\n white-space: pre-wrap; overflow-wrap: anywhere;\n }\n .mjs-ov-link {\n border: 0; padding: 0; background: transparent; color: var(--mj-text-link);\n cursor: pointer; font: inherit; font-weight: 650; text-align: left;\n }\n .mjs-ov-link:hover { text-decoration: underline; }\n .mjs-ov-next { margin: 0; font-size: 1.05rem; font-weight: 650; }\n .mjs-ov-empty, .muted { color: var(--mj-text-muted); margin: 0; }\n "] }]
1992
2064
  }], null, null); })();
1993
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealOverviewPanel, { className: "MJSDealOverviewPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 933 }); })();
2065
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealOverviewPanel, { className: "MJSDealOverviewPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 958 }); })();
1994
2066
  /* ── Field sections ───────────────────────────────────────────────────────── */
1995
2067
  let MJSDealPipelinePanel = class MJSDealPipelinePanel extends MJSDealFieldPanel {
1996
2068
  /** Every active status, loaded once. Filtered for display; see SelectableStatuses. */
@@ -2569,7 +2641,7 @@ export { MJSDealPipelinePanel };
2569
2641
  </mj-collapsible-panel>
2570
2642
  `, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n"] }]
2571
2643
  }], null, null); })();
2572
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealPipelinePanel, { className: "MJSDealPipelinePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1337 }); })();
2644
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealPipelinePanel, { className: "MJSDealPipelinePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1410 }); })();
2573
2645
  const PIPELINE_FIELDS = [
2574
2646
  // Name and DealNumber are deliberately NOT here. The hero directly above this panel already
2575
2647
  // renders Name as an editable field in edit mode, and shows DealNumber beneath the title once
@@ -2644,7 +2716,7 @@ export { MJSDealPartyPanel };
2644
2716
  </mj-collapsible-panel>
2645
2717
  `, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n"] }]
2646
2718
  }], null, null); })();
2647
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealPartyPanel, { className: "MJSDealPartyPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1782 }); })();
2719
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealPartyPanel, { className: "MJSDealPartyPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1855 }); })();
2648
2720
  /**
2649
2721
  * The Commercial section's fields, at module scope for the reason `PARTY_FIELDS` is: `Object.create`
2650
2722
  * -- how these panels are built in tests, because they inject nothing -- does NOT run property
@@ -2721,7 +2793,7 @@ export { MJSDealCommercialPanel };
2721
2793
  </mj-collapsible-panel>
2722
2794
  `, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n"] }]
2723
2795
  }], null, null); })();
2724
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealCommercialPanel, { className: "MJSDealCommercialPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1875 }); })();
2796
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealCommercialPanel, { className: "MJSDealCommercialPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1948 }); })();
2725
2797
  let MJSDealLinesPanel = class MJSDealLinesPanel extends BaseFormPanel {
2726
2798
  /**
2727
2799
  * Whether the deal's persisted status locks it.
@@ -3000,7 +3072,7 @@ export { MJSDealLinesPanel };
3000
3072
  type: ViewChild,
3001
3073
  args: [ExplorerEntityDataGridComponent]
3002
3074
  }] }); })();
3003
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealLinesPanel, { className: "MJSDealLinesPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 1995 }); })();
3075
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealLinesPanel, { className: "MJSDealLinesPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2068 }); })();
3004
3076
  let MJSDealMotionPanel = class MJSDealMotionPanel extends MJSDealFieldPanel {
3005
3077
  /**
3006
3078
  * ── THE TWO ORDER/CONTRACT CHANGES HERE (bc-aidp-next-golive#226) ───────────────────────────
@@ -3069,7 +3141,7 @@ export { MJSDealMotionPanel };
3069
3141
  </mj-collapsible-panel>
3070
3142
  `, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n"] }]
3071
3143
  }], null, null); })();
3072
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealMotionPanel, { className: "MJSDealMotionPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2181 }); })();
3144
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealMotionPanel, { className: "MJSDealMotionPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2254 }); })();
3073
3145
  let MJSDealClosePanel = class MJSDealClosePanel extends MJSDealFieldPanel {
3074
3146
  PanelOpen = false;
3075
3147
  ReopenPanelOpen = false;
@@ -3336,10 +3408,18 @@ let MJSDealClosePanel = class MJSDealClosePanel extends MJSDealFieldPanel {
3336
3408
  * The audited way back through the lock (bc-aidp-next-golive#205).
3337
3409
  *
3338
3410
  * Mirrors {@link ConfirmClose}, including the part that is easy to drop: a reopen can return
3339
- * `Success: true` WITH issues, and those are the ones that matter most. S-US8's reopen asks the
3340
- * order to come back while it sits at `Voided`, which orders treats as terminal — the deal reopens
3341
- * regardless, because an order-side refusal must never block a stage change, so this list is the
3342
- * only thing standing between the rep and a live deal pointing at a dead order.
3411
+ * `Success: true` WITH issues, and those are the ones that matter most. The deal reopens
3412
+ * regardless of what the order does, because an order-side refusal must never block a stage
3413
+ * change — so this list is the only thing standing between the rep and a live deal pointing at a
3414
+ * dead order.
3415
+ *
3416
+ * THIS USED TO SAY the reopen "asks the order to come back while it sits at `Voided`, which orders
3417
+ * treats as terminal". It does not: `TRANSITIONS.Voided` is `['Draft', 'Quoted']`, so
3418
+ * `IsTerminal('Voided')` is FALSE and `Confirmed` is the terminal status. Recorded once in
3419
+ * `docs/DECISIONS.md` D-OS4; KI-27 is the lifecycle collapse that caused it, not the transition
3420
+ * fact itself. The cases that genuinely leave an order behind are a BOOKED order, which the reopen
3421
+ * refuses outright, and — until golive#205 — a restored stage that declared nothing, which asked
3422
+ * the order for nothing and said nothing either.
3343
3423
  *
3344
3424
  * IT DOES SAVE FIRST, which this comment used to say it must not. The old reasoning was that "a
3345
3425
  * locked deal has almost nothing editable, and the close lock would refuse the save anyway". Both
@@ -3591,7 +3671,7 @@ export { MJSDealClosePanel };
3591
3671
  </mj-collapsible-panel>
3592
3672
  `, styles: ["\n .mjs-fields {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--mj-space-4) var(--mj-space-5);\n padding: var(--mj-space-4) var(--mj-space-5);\n }\n @media (max-width: 720px) { .mjs-fields { grid-template-columns: 1fr; } }\n .mjs-field { min-width: 0; }\n .mjs-field--span { grid-column: 1 / -1; }\n /* The Status control's hints. Previously dw-field__hint, which is defined only in the deal\n WORKSPACE's stylesheet under emulated encapsulation, so the rule could never match markup in\n this component and both hints rendered as unstyled body text. FIELD_STYLES is a template\n literal, so no backticks in here. */\n .mjs-field__hint { display: block; margin-top: var(--mj-space-1); color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-reopen { display: flex; flex-direction: column; gap: var(--mj-space-2); margin-top: var(--mj-space-2); }\n .mjs-reopen__field { display: flex; flex-direction: column; gap: var(--mj-space-1); font-size: 0.82rem; }\n .mjs-reopen__field textarea { width: 100%; font: inherit; }\n .mjs-reopen__row { display: flex; gap: var(--mj-space-2); }\n .mjs-reopen__confirm {\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary);\n color: var(--mj-text-on-brand); border-radius: var(--mj-radius-sm);\n padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__confirm:disabled { opacity: 0.55; cursor: not-allowed; }\n .mjs-reopen__cancel {\n border: 1px solid var(--mj-border-default); background: transparent; color: var(--mj-text-default);\n border-radius: var(--mj-radius-sm); padding: var(--mj-space-1) var(--mj-space-3); cursor: pointer; font: inherit;\n }\n .mjs-reopen__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-reopen__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-reopen__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n .mjs-field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjs-field .mj-forms-field-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .06em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjs-field .mj-forms-field--editing:hover { margin: 0; padding: 0; }\n /* The NATIVE selects this file draws itself, brought into line with the shared control\n (bc-aidp-next-golive#259 item 2: \"Status drop-down list does not seem to be styled consistently\n with rest of the app (shorter font)\").\n\n IT IS A NATIVE SELECT ON PURPOSE. mj-form-field renders a foreign key as an unfiltered dropdown\n off the related entity, which offered Won and Lost and bypassed the audited close -- golive#205,\n and the comment at the Status control says so. Opting out of the component meant opting out of\n its CSS too, and nothing put that back: a bare select inherits the browser's own font, about a\n point smaller than everything around it, which is exactly what was reported.\n\n So this restates .mj-forms-field-input's typography and underline rather than swapping the\n control back. The values are copied from that rule deliberately -- there is no shared token for\n \"a form control\" to reference, and inventing one here would be this app's guess at a platform\n decision.\n\n NO appearance: none. The shared control is a div that draws its own chevron; a native select\n stripped of its appearance would lose the arrow and have nothing to replace it, which is a worse\n inconsistency than the one being fixed.\n\n Scoped to this file's own classes because encapsulation is None on every panel that uses these\n styles, so an unscoped bare-element rule would reach the whole application. All three selects the\n deal form owns -- Status, and the loss reason on the pipeline and close panels -- sit inside one\n of these two. */\n .mjs-field select, .mjs-reopen__field select {\n font-size: 14px; font-family: inherit; color: var(--mj-text-primary);\n background: transparent; border: none;\n border-bottom: 1.5px solid var(--mj-border-default);\n padding: 4px 0; width: 100%; cursor: pointer; outline: none;\n transition: border-color var(--mj-transition-base) ease,\n background var(--mj-transition-base) ease;\n }\n .mjs-field select:focus, .mjs-reopen__field select:focus {\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n border-radius: 4px 4px 0 0; padding: 4px 6px;\n }\n /* Matches .mj-forms-field--readonly, which is how the shared control shows a field it will not\n let you change -- the Status select is disabled whenever the deal is locked. */\n .mjs-field select:disabled, .mjs-reopen__field select:disabled {\n opacity: 0.7; cursor: not-allowed;\n }\n /* A money field the panel drew itself. It carries .mj-forms-field-value too, so the size, colour\n and row height are the shared control's rather than a second opinion about them; this adds only\n what money specifically wants -- figures of equal width, so a column of amounts lines up. */\n .mjs-field__money { font-variant-numeric: tabular-nums; }\n", "\n .mjs-close-action {\n padding: var(--mj-space-4) var(--mj-space-5);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex; flex-direction: column; gap: var(--mj-space-3);\n }\n .mjs-close-action__start {\n align-self: flex-start; cursor: pointer;\n padding: 6px 14px; border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-card);\n font-weight: 600;\n }\n .mjs-close-action__start:hover { background: var(--mj-bg-surface-hover); }\n .mjs-close-action__hint { color: var(--mj-text-muted); font-size: 0.78rem; }\n .mjs-close-action__form { display: flex; flex-direction: column; gap: var(--mj-space-3); max-width: 520px; }\n .mjs-close-action__row { display: flex; gap: var(--mj-space-4); align-items: center; }\n .mjs-close-action__field { display: flex; flex-direction: column; gap: 4px; }\n .mjs-close-action__field > span { font-size: 0.78rem; color: var(--mj-text-muted); }\n .mjs-close-action__confirm {\n cursor: pointer; padding: 6px 14px; border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-brand-primary); background: var(--mj-brand-primary); color: var(--mj-text-on-brand);\n font-weight: 600;\n }\n .mjs-close-action__confirm:disabled { opacity: 0.5; cursor: not-allowed; }\n .mjs-close-action__cancel {\n cursor: pointer; padding: 6px 14px; border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-border-default); background: transparent;\n }\n .mjs-close-action__msg { font-size: 0.82rem; color: var(--mj-status-success); }\n .mjs-close-action__msg.is-error { color: var(--mj-status-warning); font-weight: 500; }\n .mjs-close-action__issue { font-size: 0.78rem; color: var(--mj-status-warning); }\n"] }]
3593
3673
  }], null, null); })();
3594
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealClosePanel, { className: "MJSDealClosePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2367 }); })();
3674
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealClosePanel, { className: "MJSDealClosePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2440 }); })();
3595
3675
  /* ── Related, renamed ─────────────────────────────────────────────────────── */
3596
3676
  let MJSDealTeamGridPanel = class MJSDealTeamGridPanel extends BaseFormPanel {
3597
3677
  Entity = MJS_ENTITIES.DealTeamMember;
@@ -3641,7 +3721,7 @@ export { MJSDealTeamGridPanel };
3641
3721
  </mj-collapsible-panel>
3642
3722
  `, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }"] }]
3643
3723
  }], null, null); })();
3644
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealTeamGridPanel, { className: "MJSDealTeamGridPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2770 }); })();
3724
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealTeamGridPanel, { className: "MJSDealTeamGridPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2851 }); })();
3645
3725
  let MJSDealBuyingTeamPanel = class MJSDealBuyingTeamPanel extends BaseFormPanel {
3646
3726
  Entity = MJS_ENTITIES.DealContactRole;
3647
3727
  OnDataLoad(event) {
@@ -3690,7 +3770,7 @@ export { MJSDealBuyingTeamPanel };
3690
3770
  </mj-collapsible-panel>
3691
3771
  `, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }"] }]
3692
3772
  }], null, null); })();
3693
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealBuyingTeamPanel, { className: "MJSDealBuyingTeamPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2809 }); })();
3773
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealBuyingTeamPanel, { className: "MJSDealBuyingTeamPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2890 }); })();
3694
3774
  let MJSDealActivityPanel = class MJSDealActivityPanel extends BaseFormPanel {
3695
3775
  cdr = inject(ChangeDetectorRef);
3696
3776
  ActivityEntity = null;
@@ -3791,7 +3871,7 @@ export { MJSDealActivityPanel };
3791
3871
  </mj-collapsible-panel>
3792
3872
  `, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }", "\n .mjs-deal-activity { display: flex; flex-direction: column; gap: var(--mj-space-3); padding: var(--mj-space-3) var(--mj-space-4) var(--mj-space-5); min-height: 0; }\n .mjs-deal-activity__viewer {\n min-height: 420px; height: 480px;\n display: flex; flex-direction: column;\n border: 1px solid var(--mj-border-default); border-radius: var(--mj-radius-md); overflow: hidden;\n }\n .mjs-deal-activity__viewer mj-entity-viewer {\n display: flex; flex-direction: column; flex: 1 1 auto; height: 100%; width: 100%;\n }\n "] }]
3793
3873
  }], null, null); })();
3794
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealActivityPanel, { className: "MJSDealActivityPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2863 }); })();
3874
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealActivityPanel, { className: "MJSDealActivityPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2944 }); })();
3795
3875
  let MJSDealHistoryPanel = class MJSDealHistoryPanel extends BaseFormPanel {
3796
3876
  Entity = MJS_ENTITIES.DealStageEvent;
3797
3877
  OnDataLoad(event) {
@@ -3842,7 +3922,7 @@ export { MJSDealHistoryPanel };
3842
3922
  </mj-collapsible-panel>
3843
3923
  `, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }"] }]
3844
3924
  }], null, null); })();
3845
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealHistoryPanel, { className: "MJSDealHistoryPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 2966 }); })();
3925
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealHistoryPanel, { className: "MJSDealHistoryPanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 3047 }); })();
3846
3926
  let MJSDealSchedulePanel = class MJSDealSchedulePanel extends BaseFormPanel {
3847
3927
  Entity = MJS_ENTITIES.DealPaymentSchedule;
3848
3928
  OnDataLoad(event) {
@@ -3891,5 +3971,5 @@ export { MJSDealSchedulePanel };
3891
3971
  </mj-collapsible-panel>
3892
3972
  `, styles: [".mjs-deal-empty { margin: 0; padding: var(--mj-space-4) var(--mj-space-5); color: var(--mj-text-muted); }"] }]
3893
3973
  }], null, null); })();
3894
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealSchedulePanel, { className: "MJSDealSchedulePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 3005 }); })();
3974
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJSDealSchedulePanel, { className: "MJSDealSchedulePanel", filePath: "lib/form-panels/deal-form.panels.ts", lineNumber: 3086 }); })();
3895
3975
  //# sourceMappingURL=deal-form.panels.js.map