@mj-biz-apps/contracts-ng 0.2.0 → 0.3.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/lib/form-panels/contract-form.panels.d.ts +77 -0
- package/dist/lib/form-panels/contract-form.panels.d.ts.map +1 -0
- package/dist/lib/form-panels/contract-form.panels.js +955 -0
- package/dist/lib/form-panels/contract-form.panels.js.map +1 -0
- package/dist/lib/form-panels/contract-form.policy.d.ts +5 -0
- package/dist/lib/form-panels/contract-form.policy.d.ts.map +1 -0
- package/dist/lib/form-panels/contract-form.policy.js +33 -0
- package/dist/lib/form-panels/contract-form.policy.js.map +1 -0
- package/dist/lib/form-panels/contract.panels.d.ts +7 -1
- package/dist/lib/form-panels/contract.panels.d.ts.map +1 -1
- package/dist/lib/form-panels/contract.panels.js +395 -236
- package/dist/lib/form-panels/contract.panels.js.map +1 -1
- package/dist/lib/form-panels/organization.panels.d.ts +4 -13
- package/dist/lib/form-panels/organization.panels.d.ts.map +1 -1
- package/dist/lib/form-panels/organization.panels.js +54 -62
- package/dist/lib/form-panels/organization.panels.js.map +1 -1
- package/dist/lib/form-panels/person.panels.d.ts +14 -0
- package/dist/lib/form-panels/person.panels.d.ts.map +1 -0
- package/dist/lib/form-panels/person.panels.js +108 -0
- package/dist/lib/form-panels/person.panels.js.map +1 -0
- package/dist/lib/form-panels/supersede.panel.d.ts +11 -2
- package/dist/lib/form-panels/supersede.panel.d.ts.map +1 -1
- package/dist/lib/form-panels/supersede.panel.js +44 -13
- package/dist/lib/form-panels/supersede.panel.js.map +1 -1
- package/dist/lib/pages/contracts-dashboard.page.d.ts +37 -17
- package/dist/lib/pages/contracts-dashboard.page.d.ts.map +1 -1
- package/dist/lib/pages/contracts-dashboard.page.js +365 -63
- package/dist/lib/pages/contracts-dashboard.page.js.map +1 -1
- package/dist/lib/sections/section-shell.component.js +2 -2
- package/dist/public-api.d.ts +3 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +15 -4
- package/dist/public-api.js.map +1 -1
- package/package.json +2 -3
- package/dist/lib/form-panels/record-files.panel.d.ts +0 -151
- package/dist/lib/form-panels/record-files.panel.d.ts.map +0 -1
- package/dist/lib/form-panels/record-files.panel.js +0 -1046
- package/dist/lib/form-panels/record-files.panel.js.map +0 -1
|
@@ -14,7 +14,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
14
14
|
*
|
|
15
15
|
* 1. **The panels were not `<mj-collapsible-panel>`s.** They were hand-rolled `<div class="card">`s, so
|
|
16
16
|
* they had none of MJ's panel chrome — hence text with no card behind it, cards touching each other,
|
|
17
|
-
* and content overflowing. The
|
|
17
|
+
* and content overflowing. The panels that looked right were the ones built on
|
|
18
18
|
* the real component.
|
|
19
19
|
* 2a. **`contributionKey` MUST EQUAL the panel's own `SectionKey`, and must DIFFER from
|
|
20
20
|
* `replacesSectionKey`.** This is the rule that took longest to find, because breaking it fails
|
|
@@ -42,75 +42,196 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
42
42
|
import { ChangeDetectorRef, Component, ViewEncapsulation, inject } from '@angular/core';
|
|
43
43
|
import { CommonModule } from '@angular/common';
|
|
44
44
|
import { FormsModule } from '@angular/forms';
|
|
45
|
+
import { CompositeKey } from '@memberjunction/core';
|
|
46
|
+
import { UserInfoEngine } from '@memberjunction/core-entities';
|
|
45
47
|
import { RegisterClassEx } from '@memberjunction/global';
|
|
46
48
|
import { BaseFormPanel, BaseFormsModule } from '@memberjunction/ng-base-forms';
|
|
47
49
|
import { HierarchyTreeComponent } from '@memberjunction/ng-hierarchy-tree';
|
|
48
|
-
import {
|
|
49
|
-
import { MJC_ENTITIES } from '../data/entity-names';
|
|
50
|
+
import { MJC_ENTITIES, MJC_FOREIGN_ENTITIES } from '../data/entity-names';
|
|
50
51
|
import * as i0 from "@angular/core";
|
|
51
|
-
import * as i1 from "@
|
|
52
|
-
import * as i2 from "@angular/
|
|
53
|
-
import * as i3 from "@
|
|
54
|
-
function
|
|
55
|
-
i0.ɵɵ
|
|
52
|
+
import * as i1 from "@memberjunction/ng-base-forms";
|
|
53
|
+
import * as i2 from "@angular/common";
|
|
54
|
+
import * as i3 from "@angular/forms";
|
|
55
|
+
function MJCContractHeroPanel_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
+
i0.ɵɵelement(0, "span", 4);
|
|
57
|
+
} if (rf & 2) {
|
|
58
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
59
|
+
i0.ɵɵproperty("title", ctx_r0.State);
|
|
60
|
+
i0.ɵɵattribute("data-tone", ctx_r0.StatusTone);
|
|
61
|
+
} }
|
|
62
|
+
function MJCContractHeroPanel_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
63
|
+
i0.ɵɵelementStart(0, "div", 8);
|
|
64
|
+
i0.ɵɵtext(1);
|
|
65
|
+
i0.ɵɵelementEnd();
|
|
66
|
+
} if (rf & 2) {
|
|
67
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
68
|
+
i0.ɵɵadvance();
|
|
69
|
+
i0.ɵɵtextInterpolate(ctx_r0.Record.ContractNumber);
|
|
70
|
+
} }
|
|
71
|
+
function MJCContractHeroPanel_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
72
|
+
i0.ɵɵelementStart(0, "span", 12);
|
|
56
73
|
i0.ɵɵtext(1);
|
|
57
|
-
i0.ɵɵ
|
|
74
|
+
i0.ɵɵelementEnd();
|
|
58
75
|
} if (rf & 2) {
|
|
59
76
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
60
77
|
i0.ɵɵadvance();
|
|
61
78
|
i0.ɵɵtextInterpolate(ctx_r0.TypeName);
|
|
62
79
|
} }
|
|
63
|
-
function
|
|
64
|
-
i0.ɵɵ
|
|
65
|
-
i0.ɵɵ
|
|
80
|
+
function MJCContractHeroPanel_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
81
|
+
i0.ɵɵelementStart(0, "span", 13);
|
|
82
|
+
i0.ɵɵelement(1, "i", 16);
|
|
66
83
|
i0.ɵɵtext(2, " Agreement modified ");
|
|
67
|
-
i0.ɵɵ
|
|
84
|
+
i0.ɵɵelementEnd();
|
|
68
85
|
} }
|
|
69
|
-
function
|
|
70
|
-
i0.ɵɵ
|
|
71
|
-
i0.ɵɵ
|
|
86
|
+
function MJCContractHeroPanel_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
87
|
+
i0.ɵɵelementStart(0, "span", 14);
|
|
88
|
+
i0.ɵɵelement(1, "i", 17);
|
|
72
89
|
i0.ɵɵtext(2, " Awaiting document ");
|
|
73
|
-
i0.ɵɵ
|
|
90
|
+
i0.ɵɵelementEnd();
|
|
74
91
|
} }
|
|
75
|
-
function
|
|
76
|
-
i0.ɵɵ
|
|
77
|
-
i0.ɵɵ
|
|
78
|
-
i0.ɵɵ
|
|
79
|
-
i0.ɵɵtext(
|
|
80
|
-
i0.ɵɵ
|
|
92
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
93
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
94
|
+
i0.ɵɵelementStart(0, "button", 26);
|
|
95
|
+
i0.ɵɵlistener("click", function MJCContractHeroPanel_Conditional_21_Conditional_9_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OpenCustomer($event)); });
|
|
96
|
+
i0.ɵɵtext(1);
|
|
97
|
+
i0.ɵɵelementEnd();
|
|
81
98
|
} if (rf & 2) {
|
|
82
|
-
const ctx_r0 = i0.ɵɵnextContext();
|
|
83
|
-
i0.ɵɵadvance(
|
|
84
|
-
i0.ɵɵtextInterpolate(ctx_r0.
|
|
99
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
100
|
+
i0.ɵɵadvance();
|
|
101
|
+
i0.ɵɵtextInterpolate(ctx_r0.CustomerName);
|
|
85
102
|
} }
|
|
86
|
-
function
|
|
87
|
-
i0.ɵɵ
|
|
88
|
-
i0.ɵɵtext(1
|
|
89
|
-
i0.ɵɵ
|
|
103
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
104
|
+
i0.ɵɵelementStart(0, "span", 21);
|
|
105
|
+
i0.ɵɵtext(1);
|
|
106
|
+
i0.ɵɵelementEnd();
|
|
107
|
+
} if (rf & 2) {
|
|
108
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
109
|
+
i0.ɵɵadvance();
|
|
110
|
+
i0.ɵɵtextInterpolate(ctx_r0.CustomerName || "\u2014");
|
|
90
111
|
} }
|
|
91
|
-
function
|
|
92
|
-
i0.ɵɵ
|
|
112
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_14_Template(rf, ctx) { if (rf & 1) {
|
|
113
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
114
|
+
i0.ɵɵelementStart(0, "button", 26);
|
|
115
|
+
i0.ɵɵlistener("click", function MJCContractHeroPanel_Conditional_21_Conditional_14_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OpenContact($event)); });
|
|
93
116
|
i0.ɵɵtext(1);
|
|
94
|
-
i0.ɵɵ
|
|
117
|
+
i0.ɵɵelementEnd();
|
|
95
118
|
} if (rf & 2) {
|
|
96
|
-
const ctx_r0 = i0.ɵɵnextContext();
|
|
119
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
97
120
|
i0.ɵɵadvance();
|
|
98
|
-
i0.ɵɵtextInterpolate(ctx_r0.
|
|
121
|
+
i0.ɵɵtextInterpolate(ctx_r0.ContactName);
|
|
99
122
|
} }
|
|
100
|
-
function
|
|
101
|
-
i0.ɵɵ
|
|
102
|
-
i0.ɵɵtext(1
|
|
103
|
-
i0.ɵɵ
|
|
123
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
124
|
+
i0.ɵɵelementStart(0, "span", 21);
|
|
125
|
+
i0.ɵɵtext(1);
|
|
126
|
+
i0.ɵɵelementEnd();
|
|
127
|
+
} if (rf & 2) {
|
|
128
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
129
|
+
i0.ɵɵadvance();
|
|
130
|
+
i0.ɵɵtextInterpolate(ctx_r0.ContactName || "\u2014");
|
|
131
|
+
} }
|
|
132
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_44_Template(rf, ctx) { if (rf & 1) {
|
|
133
|
+
i0.ɵɵelementStart(0, "div", 23)(1, "span", 20);
|
|
134
|
+
i0.ɵɵtext(2, "Term");
|
|
135
|
+
i0.ɵɵelementEnd();
|
|
136
|
+
i0.ɵɵelementStart(3, "span", 27);
|
|
137
|
+
i0.ɵɵtext(4);
|
|
138
|
+
i0.ɵɵelementEnd()();
|
|
139
|
+
} if (rf & 2) {
|
|
140
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
141
|
+
i0.ɵɵadvance(4);
|
|
142
|
+
i0.ɵɵtextInterpolate(ctx_r0.EndsInText);
|
|
104
143
|
} }
|
|
105
|
-
function
|
|
106
|
-
i0.ɵɵ
|
|
107
|
-
i0.ɵɵ
|
|
108
|
-
i0.ɵɵ
|
|
144
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_45_Template(rf, ctx) { if (rf & 1) {
|
|
145
|
+
i0.ɵɵelementStart(0, "div", 24)(1, "div", 28);
|
|
146
|
+
i0.ɵɵelement(2, "mj-form-field", 29);
|
|
147
|
+
i0.ɵɵelementEnd()();
|
|
148
|
+
} if (rf & 2) {
|
|
149
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
150
|
+
i0.ɵɵadvance(2);
|
|
151
|
+
i0.ɵɵproperty("Record", ctx_r0.Record)("ShowLabel", true)("EditMode", ctx_r0.EditMode)("FormContext", ctx_r0.FormContext);
|
|
109
152
|
} }
|
|
110
|
-
function
|
|
111
|
-
i0.ɵɵ
|
|
153
|
+
function MJCContractHeroPanel_Conditional_21_Conditional_46_Template(rf, ctx) { if (rf & 1) {
|
|
154
|
+
i0.ɵɵelementStart(0, "div", 25);
|
|
112
155
|
i0.ɵɵtext(1, " The contract number is minted on first save, from a counter taken under a lock \u2014 so it cannot collide with another contract created at the same moment. ");
|
|
113
|
-
i0.ɵɵ
|
|
156
|
+
i0.ɵɵelementEnd();
|
|
157
|
+
} }
|
|
158
|
+
function MJCContractHeroPanel_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
159
|
+
i0.ɵɵelementStart(0, "div", 18)(1, "div", 19)(2, "span", 20);
|
|
160
|
+
i0.ɵɵtext(3, "Company");
|
|
161
|
+
i0.ɵɵelementEnd();
|
|
162
|
+
i0.ɵɵelementStart(4, "span", 21);
|
|
163
|
+
i0.ɵɵtext(5);
|
|
164
|
+
i0.ɵɵelementEnd()();
|
|
165
|
+
i0.ɵɵelementStart(6, "div", 19)(7, "span", 20);
|
|
166
|
+
i0.ɵɵtext(8, "Customer");
|
|
167
|
+
i0.ɵɵelementEnd();
|
|
168
|
+
i0.ɵɵconditionalCreate(9, MJCContractHeroPanel_Conditional_21_Conditional_9_Template, 2, 1, "button", 22)(10, MJCContractHeroPanel_Conditional_21_Conditional_10_Template, 2, 1, "span", 21);
|
|
169
|
+
i0.ɵɵelementEnd();
|
|
170
|
+
i0.ɵɵelementStart(11, "div", 19)(12, "span", 20);
|
|
171
|
+
i0.ɵɵtext(13, "Contact");
|
|
172
|
+
i0.ɵɵelementEnd();
|
|
173
|
+
i0.ɵɵconditionalCreate(14, MJCContractHeroPanel_Conditional_21_Conditional_14_Template, 2, 1, "button", 22)(15, MJCContractHeroPanel_Conditional_21_Conditional_15_Template, 2, 1, "span", 21);
|
|
174
|
+
i0.ɵɵelementEnd();
|
|
175
|
+
i0.ɵɵelementStart(16, "div", 19)(17, "span", 20);
|
|
176
|
+
i0.ɵɵtext(18, "Executed");
|
|
177
|
+
i0.ɵɵelementEnd();
|
|
178
|
+
i0.ɵɵelementStart(19, "span", 21);
|
|
179
|
+
i0.ɵɵtext(20);
|
|
180
|
+
i0.ɵɵpipe(21, "date");
|
|
181
|
+
i0.ɵɵelementEnd()();
|
|
182
|
+
i0.ɵɵelementStart(22, "div", 19)(23, "span", 20);
|
|
183
|
+
i0.ɵɵtext(24, "Effective");
|
|
184
|
+
i0.ɵɵelementEnd();
|
|
185
|
+
i0.ɵɵelementStart(25, "span", 21);
|
|
186
|
+
i0.ɵɵtext(26);
|
|
187
|
+
i0.ɵɵpipe(27, "date");
|
|
188
|
+
i0.ɵɵelementEnd()();
|
|
189
|
+
i0.ɵɵelementStart(28, "div", 19)(29, "span", 20);
|
|
190
|
+
i0.ɵɵtext(30, "Term ends");
|
|
191
|
+
i0.ɵɵelementEnd();
|
|
192
|
+
i0.ɵɵelementStart(31, "span", 21);
|
|
193
|
+
i0.ɵɵtext(32);
|
|
194
|
+
i0.ɵɵpipe(33, "date");
|
|
195
|
+
i0.ɵɵelementEnd()();
|
|
196
|
+
i0.ɵɵelementStart(34, "div", 19)(35, "span", 20);
|
|
197
|
+
i0.ɵɵtext(36, "Agreement");
|
|
198
|
+
i0.ɵɵelementEnd();
|
|
199
|
+
i0.ɵɵelementStart(37, "span", 21);
|
|
200
|
+
i0.ɵɵtext(38);
|
|
201
|
+
i0.ɵɵelementEnd()();
|
|
202
|
+
i0.ɵɵelementStart(39, "div", 19)(40, "span", 20);
|
|
203
|
+
i0.ɵɵtext(41, "Created from");
|
|
204
|
+
i0.ɵɵelementEnd();
|
|
205
|
+
i0.ɵɵelementStart(42, "span", 21);
|
|
206
|
+
i0.ɵɵtext(43);
|
|
207
|
+
i0.ɵɵelementEnd()()();
|
|
208
|
+
i0.ɵɵconditionalCreate(44, MJCContractHeroPanel_Conditional_21_Conditional_44_Template, 5, 1, "div", 23);
|
|
209
|
+
i0.ɵɵconditionalCreate(45, MJCContractHeroPanel_Conditional_21_Conditional_45_Template, 3, 4, "div", 24);
|
|
210
|
+
i0.ɵɵconditionalCreate(46, MJCContractHeroPanel_Conditional_21_Conditional_46_Template, 2, 0, "div", 25);
|
|
211
|
+
} if (rf & 2) {
|
|
212
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
213
|
+
i0.ɵɵadvance(5);
|
|
214
|
+
i0.ɵɵtextInterpolate(ctx_r0.CompanyName || "\u2014");
|
|
215
|
+
i0.ɵɵadvance(4);
|
|
216
|
+
i0.ɵɵconditional(ctx_r0.Record.CustomerOrganizationID && ctx_r0.CustomerName ? 9 : 10);
|
|
217
|
+
i0.ɵɵadvance(5);
|
|
218
|
+
i0.ɵɵconditional(ctx_r0.Record.PrimaryContactPersonID && ctx_r0.ContactName ? 14 : 15);
|
|
219
|
+
i0.ɵɵadvance(6);
|
|
220
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(21, 11, ctx_r0.Record.ExecutedDate, "d MMM y") || "\u2014");
|
|
221
|
+
i0.ɵɵadvance(6);
|
|
222
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(27, 14, ctx_r0.Record.EffectiveDate, "d MMM y") || "\u2014");
|
|
223
|
+
i0.ɵɵadvance(6);
|
|
224
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(33, 17, ctx_r0.Record.EndDate, "d MMM y") || "\u2014");
|
|
225
|
+
i0.ɵɵadvance(6);
|
|
226
|
+
i0.ɵɵtextInterpolate(ctx_r0.TemplateName || "\u2014");
|
|
227
|
+
i0.ɵɵadvance(5);
|
|
228
|
+
i0.ɵɵtextInterpolate(ctx_r0.CreatingEntityName || "Entered directly");
|
|
229
|
+
i0.ɵɵadvance();
|
|
230
|
+
i0.ɵɵconditional(ctx_r0.DaysToEnd !== null ? 44 : -1);
|
|
231
|
+
i0.ɵɵadvance();
|
|
232
|
+
i0.ɵɵconditional(ctx_r0.EditMode ? 45 : -1);
|
|
233
|
+
i0.ɵɵadvance();
|
|
234
|
+
i0.ɵɵconditional(!ctx_r0.Record.ContractNumber ? 46 : -1);
|
|
114
235
|
} }
|
|
115
236
|
function MJCContractRenewalPanel_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
116
237
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
@@ -162,7 +283,7 @@ function MJCContractRenewalPanel_Conditional_15_Template(rf, ctx) { if (rf & 1)
|
|
|
162
283
|
i0.ɵɵadvance();
|
|
163
284
|
i0.ɵɵtextInterpolate(ctx_r1.Record.RenewalNoticeDays ? ctx_r1.Record.RenewalNoticeDays + " days" : "\u2014");
|
|
164
285
|
} }
|
|
165
|
-
function
|
|
286
|
+
function MJCContractRenewalPanel_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
166
287
|
i0.ɵɵelementStart(0, "div", 7);
|
|
167
288
|
i0.ɵɵtext(1);
|
|
168
289
|
i0.ɵɵpipe(2, "date");
|
|
@@ -172,16 +293,16 @@ function MJCContractRenewalPanel_Conditional_16_Template(rf, ctx) { if (rf & 1)
|
|
|
172
293
|
i0.ɵɵadvance();
|
|
173
294
|
i0.ɵɵtextInterpolate1("deadline: ", i0.ɵɵpipeBind2(2, 1, ctx_r1.NoticeDeadline, "d MMM y"));
|
|
174
295
|
} }
|
|
175
|
-
function
|
|
296
|
+
function MJCContractRenewalPanel_Conditional_22_Template(rf, ctx) { if (rf & 1) {
|
|
176
297
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
177
298
|
i0.ɵɵelementStart(0, "input", 16);
|
|
178
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
299
|
+
i0.ɵɵlistener("ngModelChange", function MJCContractRenewalPanel_Conditional_22_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Set("CancellationWindowDays", $event)); });
|
|
179
300
|
i0.ɵɵelementEnd();
|
|
180
301
|
} if (rf & 2) {
|
|
181
302
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
182
303
|
i0.ɵɵproperty("ngModel", ctx_r1.Record.CancellationWindowDays);
|
|
183
304
|
} }
|
|
184
|
-
function
|
|
305
|
+
function MJCContractRenewalPanel_Conditional_23_Template(rf, ctx) { if (rf & 1) {
|
|
185
306
|
i0.ɵɵelementStart(0, "div", 6);
|
|
186
307
|
i0.ɵɵtext(1);
|
|
187
308
|
i0.ɵɵelementEnd();
|
|
@@ -190,21 +311,21 @@ function MJCContractRenewalPanel_Conditional_21_Template(rf, ctx) { if (rf & 1)
|
|
|
190
311
|
i0.ɵɵadvance();
|
|
191
312
|
i0.ɵɵtextInterpolate(ctx_r1.Record.CancellationWindowDays ? ctx_r1.Record.CancellationWindowDays + " days" : "\u2014");
|
|
192
313
|
} }
|
|
193
|
-
function
|
|
314
|
+
function MJCContractRenewalPanel_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
194
315
|
i0.ɵɵelementStart(0, "div", 7);
|
|
195
316
|
i0.ɵɵtext(1, "the window is open now");
|
|
196
317
|
i0.ɵɵelementEnd();
|
|
197
318
|
} }
|
|
198
|
-
function
|
|
319
|
+
function MJCContractRenewalPanel_Conditional_30_Template(rf, ctx) { if (rf & 1) {
|
|
199
320
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
200
321
|
i0.ɵɵelementStart(0, "input", 17);
|
|
201
|
-
i0.ɵɵlistener("ngModelChange", function
|
|
322
|
+
i0.ɵɵlistener("ngModelChange", function MJCContractRenewalPanel_Conditional_30_Template_input_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Set("AnnualIncreasePercent", $event)); });
|
|
202
323
|
i0.ɵɵelementEnd();
|
|
203
324
|
} if (rf & 2) {
|
|
204
325
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
205
326
|
i0.ɵɵproperty("ngModel", ctx_r1.Record.AnnualIncreasePercent);
|
|
206
327
|
} }
|
|
207
|
-
function
|
|
328
|
+
function MJCContractRenewalPanel_Conditional_31_Template(rf, ctx) { if (rf & 1) {
|
|
208
329
|
i0.ɵɵelementStart(0, "div", 6);
|
|
209
330
|
i0.ɵɵtext(1);
|
|
210
331
|
i0.ɵɵelementEnd();
|
|
@@ -213,7 +334,7 @@ function MJCContractRenewalPanel_Conditional_27_Template(rf, ctx) { if (rf & 1)
|
|
|
213
334
|
i0.ɵɵadvance();
|
|
214
335
|
i0.ɵɵtextInterpolate(ctx_r1.Record.AnnualIncreasePercent !== null ? ctx_r1.Record.AnnualIncreasePercent + "%" : "\u2014");
|
|
215
336
|
} }
|
|
216
|
-
function
|
|
337
|
+
function MJCContractRenewalPanel_Conditional_34_Template(rf, ctx) { if (rf & 1) {
|
|
217
338
|
i0.ɵɵelementStart(0, "div", 12);
|
|
218
339
|
i0.ɵɵtext(1, " No renewal terms recorded. If the agreement states any, recording them is what puts this contract on the renewals watchlist. ");
|
|
219
340
|
i0.ɵɵelementEnd();
|
|
@@ -331,6 +452,7 @@ function MJCContractLineagePanel_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
|
331
452
|
i0.ɵɵtext(1, " A standalone agreement \u2014 nothing above it, no change orders, and nothing has replaced it. ");
|
|
332
453
|
i0.ɵɵelementEnd();
|
|
333
454
|
} }
|
|
455
|
+
const COLLAPSE_SETTING = 'mj.identityHeader.collapsed.contract';
|
|
334
456
|
/** Chip variant per lifecycle state — colour carries meaning, so each state gets a considered one. */
|
|
335
457
|
function chipClassFor(state) {
|
|
336
458
|
switch (state) {
|
|
@@ -346,6 +468,22 @@ function chipClassFor(state) {
|
|
|
346
468
|
* 1 · Hero — persistent identity, above the rail
|
|
347
469
|
* ──────────────────────────────────────────────────────────────────────────── */
|
|
348
470
|
let MJCContractHeroPanel = class MJCContractHeroPanel extends BaseFormPanel {
|
|
471
|
+
Collapsed = false;
|
|
472
|
+
ngOnInit() {
|
|
473
|
+
const raw = UserInfoEngine.Instance.GetSetting(COLLAPSE_SETTING);
|
|
474
|
+
if (raw) {
|
|
475
|
+
try {
|
|
476
|
+
this.Collapsed = JSON.parse(raw) === true;
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
this.Collapsed = false;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
ToggleCollapsed() {
|
|
484
|
+
this.Collapsed = !this.Collapsed;
|
|
485
|
+
UserInfoEngine.Instance.SetSettingDebounced(COLLAPSE_SETTING, JSON.stringify(this.Collapsed));
|
|
486
|
+
}
|
|
349
487
|
/**
|
|
350
488
|
* The human name for this agreement: its description, falling back to the number.
|
|
351
489
|
*
|
|
@@ -384,6 +522,14 @@ let MJCContractHeroPanel = class MJCContractHeroPanel extends BaseFormPanel {
|
|
|
384
522
|
get CreatingEntityName() { return this.Record?.CreatingEntity ?? ''; }
|
|
385
523
|
get IsAwaitingDocument() { return this.Record?.IsAwaitingDocument === true; }
|
|
386
524
|
get DaysToEnd() { return this.Record?.DaysToEnd ?? null; }
|
|
525
|
+
get StatusTone() {
|
|
526
|
+
switch (this.State) {
|
|
527
|
+
case 'Active':
|
|
528
|
+
case 'Executed': return 'success';
|
|
529
|
+
case 'Terminated': return 'warning';
|
|
530
|
+
default: return 'muted';
|
|
531
|
+
}
|
|
532
|
+
}
|
|
387
533
|
/** "in 16 months" reads better than "in 487 days" past a couple of months — the mockup's phrasing. */
|
|
388
534
|
get EndsInText() {
|
|
389
535
|
const d = this.DaysToEnd;
|
|
@@ -398,121 +544,76 @@ let MJCContractHeroPanel = class MJCContractHeroPanel extends BaseFormPanel {
|
|
|
398
544
|
const months = Math.round(d / 30);
|
|
399
545
|
return `in ${months} month${months === 1 ? '' : 's'}`;
|
|
400
546
|
}
|
|
547
|
+
OpenCustomer(event) {
|
|
548
|
+
this.open(event, MJC_FOREIGN_ENTITIES.Organization, this.Record?.CustomerOrganizationID);
|
|
549
|
+
}
|
|
550
|
+
OpenContact(event) {
|
|
551
|
+
this.open(event, MJC_FOREIGN_ENTITIES.Person, this.Record?.PrimaryContactPersonID);
|
|
552
|
+
}
|
|
553
|
+
open(event, entity, id) {
|
|
554
|
+
if (!id)
|
|
555
|
+
return;
|
|
556
|
+
event.preventDefault();
|
|
557
|
+
this.FormComponent.OnFormNavigate({
|
|
558
|
+
Kind: 'record',
|
|
559
|
+
EntityName: entity,
|
|
560
|
+
PrimaryKey: CompositeKey.FromID(id),
|
|
561
|
+
OpenInNewTab: event.ctrlKey || event.metaKey,
|
|
562
|
+
});
|
|
563
|
+
}
|
|
401
564
|
static ɵfac = /*@__PURE__*/ (() => { let ɵMJCContractHeroPanel_BaseFactory; return function MJCContractHeroPanel_Factory(__ngFactoryType__) { return (ɵMJCContractHeroPanel_BaseFactory || (ɵMJCContractHeroPanel_BaseFactory = i0.ɵɵgetInheritedFactory(MJCContractHeroPanel)))(__ngFactoryType__ || MJCContractHeroPanel); }; })();
|
|
402
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractHeroPanel, selectors: [["mjc-contract-hero-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
403
|
-
i0.ɵɵ
|
|
404
|
-
i0.ɵɵ
|
|
405
|
-
i0.ɵɵ
|
|
406
|
-
i0.ɵɵ
|
|
407
|
-
i0.ɵɵ
|
|
408
|
-
i0.ɵɵ
|
|
409
|
-
i0.ɵɵ
|
|
410
|
-
i0.ɵɵ
|
|
411
|
-
i0.ɵɵ
|
|
412
|
-
i0.ɵɵ
|
|
413
|
-
i0.ɵɵ
|
|
414
|
-
i0.ɵɵ
|
|
415
|
-
i0.ɵɵ
|
|
416
|
-
i0.ɵɵdomElementStart(13, "div", 11)(14, "span", 12);
|
|
565
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractHeroPanel, selectors: [["mjc-contract-hero-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 22, vars: 16, consts: [[1, "mjc-hero"], [1, "mjc-hero__identity"], ["aria-hidden", "true", 1, "mjc-hero__avatar"], [1, "fa-solid", "fa-file-signature"], [1, "mjc-hero__presence", 3, "title"], [1, "mjc-hero__copy"], [1, "mjc-hero__title-row"], [1, "mjc-hero__title"], [1, "mjc-hero__aka"], [1, "mjc-hero__badges"], [1, "mjc-hero__entity-chip"], [1, "mjc-chip"], [1, "mjc-chip", "mjc-chip--info"], ["title", "This contract deviates from the standard agreement \u2014 read the paper", 1, "mjc-chip", "mjc-chip--warn"], ["title", "This contract type expects an executed document and none is attached", 1, "mjc-chip", "mjc-chip--warn"], ["type", "button", 1, "mjc-hero__toggle", 3, "click", "title"], ["aria-hidden", "true", 1, "fa-solid", "fa-triangle-exclamation"], ["aria-hidden", "true", 1, "fa-solid", "fa-file-circle-question"], [1, "mjc-hero__summary"], [1, "mjc-hero__stat"], [1, "mjc-hero__stat-label"], [1, "mjc-hero__stat-val"], ["type", "button", 1, "mjc-hero__stat-val", "is-link"], [1, "mjc-hero__next"], [1, "mjc-hero__edit"], [1, "mjc-flag"], ["type", "button", 1, "mjc-hero__stat-val", "is-link", 3, "click"], [1, "mjc-hero__next-val"], [1, "mjc-hero__field"], ["FieldName", "Description", "Type", "textarea", 3, "Record", "ShowLabel", "EditMode", "FormContext"]], template: function MJCContractHeroPanel_Template(rf, ctx) { if (rf & 1) {
|
|
566
|
+
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2);
|
|
567
|
+
i0.ɵɵelement(3, "i", 3);
|
|
568
|
+
i0.ɵɵconditionalCreate(4, MJCContractHeroPanel_Conditional_4_Template, 1, 2, "span", 4);
|
|
569
|
+
i0.ɵɵelementEnd();
|
|
570
|
+
i0.ɵɵelementStart(5, "div", 5)(6, "div", 6)(7, "h1", 7);
|
|
571
|
+
i0.ɵɵtext(8);
|
|
572
|
+
i0.ɵɵelementEnd()();
|
|
573
|
+
i0.ɵɵconditionalCreate(9, MJCContractHeroPanel_Conditional_9_Template, 2, 1, "div", 8);
|
|
574
|
+
i0.ɵɵelementStart(10, "div", 9)(11, "span", 10);
|
|
575
|
+
i0.ɵɵelement(12, "i", 3);
|
|
576
|
+
i0.ɵɵtext(13, " Contract");
|
|
577
|
+
i0.ɵɵelementEnd();
|
|
578
|
+
i0.ɵɵelementStart(14, "span", 11);
|
|
417
579
|
i0.ɵɵtext(15);
|
|
418
|
-
i0.ɵɵ
|
|
419
|
-
i0.ɵɵ
|
|
420
|
-
i0.ɵɵ
|
|
421
|
-
i0.ɵɵ
|
|
422
|
-
i0.ɵɵ
|
|
423
|
-
i0.ɵɵ
|
|
424
|
-
i0.ɵɵ
|
|
425
|
-
i0.ɵɵ
|
|
426
|
-
i0.ɵɵ
|
|
427
|
-
i0.ɵɵ
|
|
428
|
-
i0.ɵɵ
|
|
429
|
-
i0.ɵɵconditionalCreate(24, MJCContractHeroPanel_Conditional_24_Template, 4, 1, "span");
|
|
430
|
-
i0.ɵɵdomElementEnd()()();
|
|
431
|
-
i0.ɵɵdomElementStart(25, "div", 13)(26, "div", 14)(27, "span", 15);
|
|
432
|
-
i0.ɵɵtext(28, "Executed");
|
|
433
|
-
i0.ɵɵdomElementEnd();
|
|
434
|
-
i0.ɵɵdomElementStart(29, "span", 16);
|
|
435
|
-
i0.ɵɵtext(30);
|
|
436
|
-
i0.ɵɵpipe(31, "date");
|
|
437
|
-
i0.ɵɵdomElementEnd();
|
|
438
|
-
i0.ɵɵconditionalCreate(32, MJCContractHeroPanel_Conditional_32_Template, 2, 0, "span", 17);
|
|
439
|
-
i0.ɵɵdomElementEnd();
|
|
440
|
-
i0.ɵɵdomElementStart(33, "div", 14)(34, "span", 15);
|
|
441
|
-
i0.ɵɵtext(35, "Effective");
|
|
442
|
-
i0.ɵɵdomElementEnd();
|
|
443
|
-
i0.ɵɵdomElementStart(36, "span", 16);
|
|
444
|
-
i0.ɵɵtext(37);
|
|
445
|
-
i0.ɵɵpipe(38, "date");
|
|
446
|
-
i0.ɵɵdomElementEnd()();
|
|
447
|
-
i0.ɵɵdomElementStart(39, "div", 14)(40, "span", 15);
|
|
448
|
-
i0.ɵɵtext(41, "Term ends");
|
|
449
|
-
i0.ɵɵdomElementEnd();
|
|
450
|
-
i0.ɵɵdomElementStart(42, "span", 16);
|
|
451
|
-
i0.ɵɵtext(43);
|
|
452
|
-
i0.ɵɵpipe(44, "date");
|
|
453
|
-
i0.ɵɵdomElementEnd();
|
|
454
|
-
i0.ɵɵconditionalCreate(45, MJCContractHeroPanel_Conditional_45_Template, 2, 1, "span", 17);
|
|
455
|
-
i0.ɵɵdomElementEnd();
|
|
456
|
-
i0.ɵɵdomElementStart(46, "div", 14)(47, "span", 15);
|
|
457
|
-
i0.ɵɵtext(48, "Agreement");
|
|
458
|
-
i0.ɵɵdomElementEnd();
|
|
459
|
-
i0.ɵɵdomElementStart(49, "span", 16);
|
|
460
|
-
i0.ɵɵtext(50);
|
|
461
|
-
i0.ɵɵdomElementEnd();
|
|
462
|
-
i0.ɵɵconditionalCreate(51, MJCContractHeroPanel_Conditional_51_Template, 2, 0, "span", 17);
|
|
463
|
-
i0.ɵɵdomElementEnd();
|
|
464
|
-
i0.ɵɵdomElementStart(52, "div", 14)(53, "span", 15);
|
|
465
|
-
i0.ɵɵtext(54, "Created by");
|
|
466
|
-
i0.ɵɵdomElementEnd();
|
|
467
|
-
i0.ɵɵdomElementStart(55, "span", 16);
|
|
468
|
-
i0.ɵɵtext(56);
|
|
469
|
-
i0.ɵɵdomElementEnd();
|
|
470
|
-
i0.ɵɵconditionalCreate(57, MJCContractHeroPanel_Conditional_57_Template, 2, 0, "span", 17);
|
|
471
|
-
i0.ɵɵdomElementEnd()();
|
|
472
|
-
i0.ɵɵconditionalCreate(58, MJCContractHeroPanel_Conditional_58_Template, 2, 0, "div", 18);
|
|
473
|
-
i0.ɵɵdomElementEnd();
|
|
580
|
+
i0.ɵɵelementEnd();
|
|
581
|
+
i0.ɵɵconditionalCreate(16, MJCContractHeroPanel_Conditional_16_Template, 2, 1, "span", 12);
|
|
582
|
+
i0.ɵɵconditionalCreate(17, MJCContractHeroPanel_Conditional_17_Template, 3, 0, "span", 13);
|
|
583
|
+
i0.ɵɵconditionalCreate(18, MJCContractHeroPanel_Conditional_18_Template, 3, 0, "span", 14);
|
|
584
|
+
i0.ɵɵelementEnd()();
|
|
585
|
+
i0.ɵɵelementStart(19, "button", 15);
|
|
586
|
+
i0.ɵɵlistener("click", function MJCContractHeroPanel_Template_button_click_19_listener() { return ctx.ToggleCollapsed(); });
|
|
587
|
+
i0.ɵɵelement(20, "i");
|
|
588
|
+
i0.ɵɵelementEnd()();
|
|
589
|
+
i0.ɵɵconditionalCreate(21, MJCContractHeroPanel_Conditional_21_Template, 47, 20);
|
|
590
|
+
i0.ɵɵelementEnd();
|
|
474
591
|
} if (rf & 2) {
|
|
475
|
-
i0.ɵɵ
|
|
592
|
+
i0.ɵɵclassProp("mjc-hero--collapsed", ctx.Collapsed);
|
|
593
|
+
i0.ɵɵadvance(4);
|
|
594
|
+
i0.ɵɵconditional(!ctx.EditMode ? 4 : -1);
|
|
595
|
+
i0.ɵɵadvance(4);
|
|
476
596
|
i0.ɵɵtextInterpolate(ctx.Title);
|
|
477
597
|
i0.ɵɵadvance();
|
|
598
|
+
i0.ɵɵconditional(ctx.Record.ContractNumber && !ctx.Collapsed ? 9 : -1);
|
|
599
|
+
i0.ɵɵadvance(5);
|
|
478
600
|
i0.ɵɵclassMap("mjc-chip " + ctx.StateChipClass);
|
|
479
601
|
i0.ɵɵadvance();
|
|
480
602
|
i0.ɵɵtextInterpolate(ctx.State);
|
|
481
603
|
i0.ɵɵadvance();
|
|
482
|
-
i0.ɵɵconditional(ctx.TypeName ?
|
|
604
|
+
i0.ɵɵconditional(ctx.TypeName ? 16 : -1);
|
|
483
605
|
i0.ɵɵadvance();
|
|
484
|
-
i0.ɵɵconditional(ctx.Record.HasModifications ?
|
|
606
|
+
i0.ɵɵconditional(ctx.Record.HasModifications ? 17 : -1);
|
|
485
607
|
i0.ɵɵadvance();
|
|
486
|
-
i0.ɵɵconditional(ctx.IsAwaitingDocument ?
|
|
487
|
-
i0.ɵɵadvance(3);
|
|
488
|
-
i0.ɵɵtextInterpolate(ctx.Record.ContractNumber || "Unnumbered");
|
|
489
|
-
i0.ɵɵadvance(4);
|
|
490
|
-
i0.ɵɵtextInterpolate(ctx.CustomerName || "\u2014");
|
|
491
|
-
i0.ɵɵadvance(4);
|
|
492
|
-
i0.ɵɵtextInterpolate(ctx.CompanyName || "\u2014");
|
|
608
|
+
i0.ɵɵconditional(ctx.IsAwaitingDocument ? 18 : -1);
|
|
493
609
|
i0.ɵɵadvance();
|
|
494
|
-
i0.ɵɵ
|
|
495
|
-
i0.ɵɵ
|
|
496
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(31, 21, ctx.Record.ExecutedDate, "d MMM y") || "\u2014");
|
|
497
|
-
i0.ɵɵadvance(2);
|
|
498
|
-
i0.ɵɵconditional(!ctx.Record.ExecutedDate ? 32 : -1);
|
|
499
|
-
i0.ɵɵadvance(5);
|
|
500
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(38, 24, ctx.Record.EffectiveDate, "d MMM y") || "\u2014");
|
|
501
|
-
i0.ɵɵadvance(6);
|
|
502
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(44, 27, ctx.Record.EndDate, "d MMM y") || "\u2014");
|
|
503
|
-
i0.ɵɵadvance(2);
|
|
504
|
-
i0.ɵɵconditional(ctx.DaysToEnd !== null ? 45 : -1);
|
|
505
|
-
i0.ɵɵadvance(5);
|
|
506
|
-
i0.ɵɵtextInterpolate(ctx.TemplateName || "\u2014");
|
|
610
|
+
i0.ɵɵproperty("title", ctx.Collapsed ? "Expand header" : "Collapse header");
|
|
611
|
+
i0.ɵɵattribute("aria-label", ctx.Collapsed ? "Expand header" : "Collapse header");
|
|
507
612
|
i0.ɵɵadvance();
|
|
508
|
-
i0.ɵɵ
|
|
509
|
-
i0.ɵɵadvance(5);
|
|
510
|
-
i0.ɵɵtextInterpolate(ctx.CreatingEntityName || "\u2014");
|
|
613
|
+
i0.ɵɵclassMap(ctx.Collapsed ? "fa-solid fa-chevron-down" : "fa-solid fa-chevron-up");
|
|
511
614
|
i0.ɵɵadvance();
|
|
512
|
-
i0.ɵɵconditional(!ctx.
|
|
513
|
-
i0.ɵɵadvance();
|
|
514
|
-
i0.ɵɵconditional(!ctx.Record.ContractNumber ? 58 : -1);
|
|
515
|
-
} }, dependencies: [CommonModule, BaseFormsModule, i1.DatePipe], encapsulation: 2 });
|
|
615
|
+
i0.ɵɵconditional(!ctx.Collapsed ? 21 : -1);
|
|
616
|
+
} }, dependencies: [CommonModule, BaseFormsModule, i1.MjFormFieldComponent, i2.DatePipe], styles: ["/**\n * contracts-kit.css \u2014 ported from design-docs/ui-design/mockups-v2/tokens.css.\n *\n * \u26A0 SEMANTIC TOKENS ONLY. MJ's design-token rule is explicit: *\"NEVER use primitive tokens\n * (`--mj-color-neutral-*`, `--mj-color-brand-*`) in component CSS. Primitives don't adapt to dark\n * mode.\"* An earlier version of this file used twelve of them, because the mockup did \u2014 and in a\n * standalone mockup page that is harmless, since there is no dark mode to adapt to. Ported into a real\n * component stylesheet it means every tinted surface, chip and clause box keeps its LIGHT colour when\n * the app is themed dark. That is the theming break, and it is invisible until someone switches theme.\n *\n * The mapping applied: neutral-50 \u2192 bg-surface-sunken, neutral-100 \u2192 border-subtle, neutral-300 \u2192\n * border-strong, success/error/warning-50 \u2192 status-*-bg, success/error-700 \u2192 status-*-text, brand-50 \u2192\n * status-info-bg, brand-100 \u2192 status-info-border, brand-700/900 \u2192 status-info-text. `#fff` on a brand\n * fill \u2192 `--mj-brand-on-primary`.\n *\n * THE MOCKUPS ARE THE SPEC, and this file exists to keep them so. An earlier version of this kit was\n * written from MEMORY of them, and it was wrong in a way that is invisible in source and obvious on\n * screen: it used token names that do not exist. `--mj-font-size-sm`, `--mj-text-tertiary`,\n * `--mj-color-warning-text`, `--mj-color-success-border` and four others are not MJ tokens (the real\n * names are `--mj-text-sm`, `--mj-status-warning-text`, `--mj-status-success`, \u2026). Every one of those\n * resolved to NOTHING \u2014 so font sizes fell back to browser defaults and the state chips rendered with\n * no colour at all. That is most of what \"looks bad\" was.\n *\n * So: class names and rules below are the mockup's, verbatim where possible, and **every token used\n * here has been checked to exist in MJ's `_tokens.scss`.** If you add a rule, check the token first \u2014\n * a missing custom property fails silently, which is the worst failure mode CSS has.\n *\n * SHIPPED VIA THE SECTION SHELL (`styleUrls` + `ViewEncapsulation.None`). `ngc` only compiles what a\n * component references, so a stylesheet nothing references is built into dist and never loaded.\n * `None` is required, not lazy: these classes are used by DESCENDANT components.\n *\n * Prefix note: the mockup used bare class names (`.panel`, `.chip`) because it was a standalone page.\n * Here everything is `mjc-` prefixed \u2014 bare `.panel` inside a real Explorer would collide with MJ's own\n * chrome, and `ViewEncapsulation.None` means these rules are global.\n */\n\n/* \u2500\u2500 Page frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-page {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-5);\n}\n\n/* A grid page needs a DEFINITE height: mj-explorer-entity-data-grid is height:100% outside a related\n panel, and 100% of an auto-height parent is zero \u2014 the grid renders no rows while its toolbar still\n reports the count. MJ's own source documents that symptom. `min-height: 0` on the fill slot is\n mandatory: a flex child defaults to min-height:auto and refuses to shrink, so without it the grid\n pushes the page taller instead of scrolling inside itself. */\n.mjc-page--grid { height: 100%; min-height: 0; }\n.mjc-grid-fill { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }\n\n/* Intro prose. Constrained measure \u2014 text stops being readable much past this \u2014 and it is a real\n block with real spacing, not a bare text node floating between cards. */\n.mjc-page__intro {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.55;\n margin: 0;\n max-width: 78ch;\n}\n\n/* \u2500\u2500 Panel body helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Our panels are real `<mj-collapsible-panel>`s, so MJ paints the frame, the header and the spacing.\n These classes style only what goes INSIDE one. */\n\n.mjc-body { padding: var(--mj-space-4); }\n.mjc-body--flush { padding: 0; } /* a table fills the panel edge to edge */\n.mjc-body > * + * { margin-top: var(--mj-space-3); } /* nothing ever touches its neighbour */\n\n.mjc-note {\n margin: 0;\n color: var(--mj-text-muted);\n font-size: var(--mj-text-xs);\n line-height: 1.55;\n}\n\n/* A note under a flush table needs its own padding and a rule above it, or it reads as a table row. */\n.mjc-note--footer {\n padding: var(--mj-space-3) var(--mj-space-4);\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n/* \u2500\u2500 Hero (mockup 1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-hero {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-4) var(--mj-space-5);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.mjc-hero__identity { display: flex; align-items: center; gap: var(--mj-space-4); min-width: 0; }\n\n.mjc-hero__avatar {\n flex: none;\n width: 52px; height: 52px;\n border-radius: var(--mj-radius-md);\n display: flex; align-items: center; justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-xl, 1.375rem);\n}\n\n.mjc-hero__copy { min-width: 0; flex: 1; }\n\n.mjc-hero__title-row {\n display: flex; align-items: center; flex-wrap: wrap;\n gap: var(--mj-space-2) var(--mj-space-3);\n}\n\n.mjc-hero__title {\n margin: 0;\n font-size: var(--mj-text-lg);\n font-weight: 700;\n line-height: 1.25;\n /* Long contract descriptions must not push the chips off the card. */\n overflow-wrap: anywhere;\n}\n\n.mjc-hero__meta {\n display: flex; flex-wrap: wrap;\n gap: var(--mj-space-3);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n margin-top: var(--mj-space-2);\n}\n\n/* auto-fit so five stats sit in a row on a wide screen and reflow on a laptop, rather than\n overflowing the card \u2014 which is what a fixed five-column grid did. */\n.mjc-hero__stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));\n gap: var(--mj-space-3);\n}\n\n.mjc-stat {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: var(--mj-space-3);\n min-width: 0;\n}\n.mjc-stat__label {\n display: block; font-size: var(--mj-text-xs);\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted);\n}\n.mjc-stat__value {\n display: block; font-size: var(--mj-text-base); font-weight: 700; margin-top: 2px;\n overflow-wrap: anywhere;\n}\n.mjc-stat__sub { display: block; font-size: var(--mj-text-xs); color: var(--mj-text-muted); }\n\n/* \u2500\u2500 Chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-chip {\n display: inline-flex; align-items: center; gap: 4px;\n font-size: var(--mj-text-xs); font-weight: 600;\n padding: 2px 9px; border-radius: 999px;\n border: 1px solid transparent; white-space: nowrap;\n}\n.mjc-chip--ok { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); border-color: var(--mj-status-success); }\n.mjc-chip--warn { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); border-color: var(--mj-status-warning); }\n.mjc-chip--error { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); border-color: var(--mj-status-error); }\n.mjc-chip--info { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); border-color: var(--mj-status-info-border); }\n.mjc-chip--muted { background: var(--mj-border-subtle); color: var(--mj-text-secondary); border-color: var(--mj-border-default); }\n\n/* \u2500\u2500 Buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-btn {\n display: inline-flex; align-items: center; gap: 6px;\n font-size: var(--mj-text-sm); font-weight: 600;\n padding: 6px 12px;\n border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n.mjc-btn:disabled { opacity: .5; cursor: default; }\n.mjc-btn--primary { background: var(--mj-brand-primary); border-color: var(--mj-brand-primary); color: var(--mj-brand-on-primary); }\n.mjc-btn--flat { background: transparent; border-color: transparent; color: var(--mj-brand-primary); }\n.mjc-btn--sm { padding: 3px 9px; font-size: var(--mj-text-xs); }\n.mjc-btn--danger { color: var(--mj-status-error-text); border-color: transparent; background: transparent; }\n\n/* \u2500\u2500 Field grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-fields {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));\n gap: var(--mj-space-3) var(--mj-space-4);\n}\n.mjc-field > label {\n display: block; font-size: var(--mj-text-xs); color: var(--mj-text-muted);\n text-transform: uppercase; letter-spacing: .04em; margin-bottom: 3px;\n}\n.mjc-field .mjc-val {\n padding: 6px 9px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n min-height: 31px;\n overflow-wrap: anywhere;\n}\n.mjc-field .mjc-val--ro { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.mjc-hint { color: var(--mj-text-muted); font-size: var(--mj-text-xs); margin-top: 3px; }\n\n/* \u2500\u2500 Tables \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The mockup renders modifications, documents and lineage as TABLES, not stacked cards. With three\n or more rows a table is scannable and a stack is a wall. */\n\ntable.mjc-grid { width: 100%; border-collapse: collapse; }\ntable.mjc-grid th {\n text-align: left; font-size: var(--mj-text-xs);\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700;\n padding: var(--mj-space-2) var(--mj-space-3);\n border-bottom: 1.5px solid var(--mj-border-default);\n}\ntable.mjc-grid td {\n padding: var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: top;\n}\ntable.mjc-grid tr:last-child td { border-bottom: 0; }\ntable.mjc-grid tbody tr:hover td { background: var(--mj-bg-surface-sunken); }\n.mjc-row--click { cursor: pointer; }\n\n.mjc-muted { color: var(--mj-text-muted); }\n.mjc-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--mj-text-xs); }\n\n/* \u2500\u2500 The clause pair (mockups 1 and 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The standard clause and what this contract says instead, read side by side. This is the app's\n central idea rendered, so it gets real styling rather than two paragraphs. */\n\n.mjc-pair {\n display: grid; grid-template-columns: 1fr; gap: var(--mj-space-3);\n margin-top: var(--mj-space-2);\n}\n/* Side by side only when there is room \u2014 two 40ch columns on a laptop is worse than one readable one. */\n@media (min-width: 1100px) { .mjc-pair { grid-template-columns: 1fr 1fr; } }\n\n.mjc-pair__tag {\n display: block; font-size: var(--mj-text-xs); font-weight: 700;\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); margin-bottom: 3px;\n}\n.mjc-pair__tag--mod { color: var(--mj-status-warning-text); }\n\n.mjc-clause {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-left: 2px solid var(--mj-border-strong);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-radius: 0 var(--mj-radius-sm) var(--mj-radius-sm) 0;\n margin: 0;\n /* Clause text carries its own line breaks, and 9.1 is a single 1,100-character sentence in caps \u2014\n both must wrap inside the box rather than escaping it. */\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.mjc-clause--mod {\n border-left-color: var(--mj-status-warning);\n background: var(--mj-status-warning-bg);\n color: var(--mj-text-primary);\n}\n\n.mjc-toggle {\n font-size: var(--mj-text-xs); color: var(--mj-brand-primary);\n font-weight: 600; margin-top: 4px; background: none; border: 0; padding: 0; cursor: pointer;\n}\n\n/* \u2500\u2500 Callout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-flag {\n background: var(--mj-status-warning-bg);\n border-left: 3px solid var(--mj-status-warning);\n padding: var(--mj-space-2) var(--mj-space-3);\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n border-radius: 0 var(--mj-radius-sm) var(--mj-radius-sm) 0;\n line-height: 1.55;\n}\n\n/* \u2500\u2500 Invalid input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* A required field the user has emptied. Border + ring only \u2014 no background change, because these\n are prose textareas and tinting the reading surface makes the text itself harder to read, which\n is the opposite of helpful when the point is \"write something here\". Tokens only, per the\n design-token gate. */\n.mjc-invalid {\n border-color: var(--mj-status-error) !important;\n box-shadow: 0 0 0 2px var(--mj-status-error-bg);\n outline: none;\n}\n\n/* \u2500\u2500 Filter pills (watchlist) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-pills { display: flex; flex-wrap: wrap; gap: var(--mj-space-2); align-items: center; }\n\n.mjc-pill {\n appearance: none; cursor: pointer;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border-radius: 999px;\n padding: 3px var(--mj-space-3);\n font-size: var(--mj-text-sm);\n line-height: 1.6;\n display: inline-flex; align-items: center; gap: var(--mj-space-2);\n}\n.mjc-pill:hover { border-color: var(--mj-brand-primary); color: var(--mj-text-primary); }\n.mjc-pill:disabled { opacity: .5; cursor: default; }\n.mjc-pill--active {\n background: var(--mj-status-info-bg);\n border-color: var(--mj-brand-primary);\n color: var(--mj-status-info-text);\n font-weight: 700;\n}\n.mjc-pill__count { font-variant-numeric: tabular-nums; opacity: .85; font-size: var(--mj-text-xs); }\n\n/* \u2500\u2500 Dashboard command center \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));\n gap: var(--mj-space-3);\n}\n.mjc-kpi {\n appearance: none;\n font: inherit;\n text-align: left;\n color: inherit;\n cursor: pointer;\n padding: var(--mj-space-3) var(--mj-space-4);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n}\n.mjc-kpi:hover { border-color: var(--mj-brand-primary); }\n.mjc-kpi:disabled { opacity: .6; cursor: default; }\n.mjc-kpi--alert .mjc-kpi__v { color: var(--mj-status-error-text); }\n.mjc-kpi__l {\n font-size: var(--mj-text-xs);\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: .04em;\n color: var(--mj-text-muted);\n}\n.mjc-kpi__v {\n font-size: var(--mj-text-xl, 1.35rem);\n font-weight: 700;\n margin: 4px 0 2px;\n font-variant-numeric: tabular-nums;\n}\n.mjc-kpi__f {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n line-height: 1.35;\n}\n\n.mjc-dash-split {\n display: grid;\n grid-template-columns: 1.15fr .85fr;\n gap: var(--mj-space-3);\n}\n@media (max-width: 900px) { .mjc-dash-split { grid-template-columns: 1fr; } }\n\n.mjc-dash-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n.mjc-dash-card__h {\n display: flex;\n justify-content: space-between;\n gap: var(--mj-space-2);\n align-items: baseline;\n padding: var(--mj-space-3) var(--mj-space-4);\n border-bottom: 1px solid var(--mj-border-subtle);\n font-weight: 700;\n}\n.mjc-dash-card__h span {\n font-weight: 500;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.mjc-barlist { display: flex; flex-direction: column; gap: var(--mj-space-2); padding: var(--mj-space-3) var(--mj-space-4); }\n.mjc-barrow {\n display: grid;\n grid-template-columns: 7.5rem 1fr auto;\n gap: var(--mj-space-2);\n align-items: center;\n font-size: var(--mj-text-sm);\n}\n.mjc-track {\n height: 8px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 99px;\n overflow: hidden;\n}\n.mjc-fill {\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 99px;\n}\n.mjc-num { font-variant-numeric: tabular-nums; font-weight: 700; }\n\n.mjc-funnel {\n display: flex;\n gap: var(--mj-space-2);\n align-items: flex-end;\n height: 10rem;\n padding: var(--mj-space-3) var(--mj-space-4);\n}\n.mjc-funnel__col {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n.mjc-funnel__bar {\n width: 100%;\n min-height: 8px;\n border-radius: 8px 8px 2px 2px;\n background: var(--mj-brand-primary);\n}\n.mjc-funnel__n { font-weight: 700; }\n.mjc-funnel__lab {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n text-align: center;\n}\n\n.mjc-buckets {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: var(--mj-space-2);\n padding: var(--mj-space-3) var(--mj-space-4);\n}\n@media (max-width: 700px) { .mjc-buckets { grid-template-columns: 1fr 1fr; } }\n.mjc-bucket {\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: var(--mj-space-3);\n}\n\n.mjc-viewer-host {\n min-height: 420px;\n height: 480px;\n display: flex;\n flex-direction: column;\n}\n.mjc-viewer-host mj-entity-viewer {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 350px;\n width: 100%;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n A sentence in a bordered box, never a bare line of text in whitespace. */\n\n.mjc-empty {\n display: flex; align-items: center; gap: var(--mj-space-2); justify-content: center;\n padding: var(--mj-space-6);\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n background: var(--mj-bg-surface-sunken);\n border: 1px dashed var(--mj-border-strong);\n border-radius: var(--mj-radius-md);\n text-align: center;\n}\n", "\n .mjc-hero {\n display: flex; flex-direction: column; gap: var(--mj-space-4);\n padding: 20px 24px; margin-bottom: var(--mj-space-4);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-xl, 16px);\n box-shadow: var(--mj-shadow-md, 0 4px 16px rgba(0, 0, 0, .08));\n position: relative; overflow: hidden;\n }\n .mjc-hero::before {\n content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3.5px;\n background: linear-gradient(90deg, #38bdf8 0%, #6366f1 50%, #10b981 100%);\n }\n .mjc-hero__identity { display: flex; align-items: center; gap: var(--mj-space-4); min-width: 0; }\n .mjc-hero__avatar {\n flex: none; width: 60px; height: 60px; border-radius: var(--mj-radius-lg, 14px);\n position: relative; display: flex; align-items: center; justify-content: center;\n background: linear-gradient(135deg, color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface)) 0%, color-mix(in srgb, var(--mj-brand-accent, #6366f1) 25%, var(--mj-bg-surface)) 100%);\n color: var(--mj-brand-primary); font-size: 1.35rem;\n box-shadow: 0 4px 14px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n }\n .mjc-hero__presence {\n position: absolute; bottom: -2px; right: -2px; width: 13px; height: 13px;\n border-radius: 50%; border: 2.5px solid var(--mj-bg-surface-card);\n background: var(--mj-text-muted, #94a3b8);\n }\n .mjc-hero__presence[data-tone='success'] { background: var(--mj-status-success, #10b981); }\n .mjc-hero__presence[data-tone='warning'] { background: var(--mj-status-warning, #f59e0b); }\n .mjc-hero__copy { min-width: 0; flex: 1; }\n .mjc-hero__title {\n margin: 0; font-size: var(--mj-text-lg, 18px); font-weight: 800;\n letter-spacing: -.02em; line-height: 1.25; color: var(--mj-text-primary);\n overflow-wrap: anywhere;\n }\n .mjc-hero__aka { margin-top: 2px; font-size: var(--mj-text-xs); color: var(--mj-text-muted); }\n .mjc-hero__badges {\n display: flex; align-items: center; flex-wrap: wrap;\n gap: var(--mj-space-2); margin-top: var(--mj-space-2);\n }\n .mjc-hero__entity-chip {\n display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px;\n border-radius: var(--mj-radius-sm);\n background: var(--mj-status-info-bg); color: var(--mj-brand-primary);\n font-size: var(--mj-text-xs); font-weight: 650;\n }\n .mjc-hero__toggle {\n display: inline-flex; align-items: center; justify-content: center;\n flex: none; width: 32px; height: 32px; margin-left: auto; padding: 0;\n border: 1px solid var(--mj-border-default); border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-sunken, rgba(255,255,255,.04));\n color: var(--mj-text-secondary); cursor: pointer; font-size: 12px;\n }\n .mjc-hero__toggle:hover {\n background: var(--mj-bg-surface-hover, rgba(255,255,255,.08));\n color: var(--mj-text-primary); border-color: var(--mj-brand-primary);\n }\n .mjc-hero__summary {\n display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n gap: var(--mj-space-3); padding-top: var(--mj-space-4);\n border-top: 1px solid var(--mj-border-default);\n }\n .mjc-hero__stat { display: flex; flex-direction: column; gap: 3px; min-width: 0; }\n .mjc-hero__stat-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .04em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjc-hero__stat-val {\n font-size: 15px; font-weight: 650; color: var(--mj-text-primary);\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n }\n button.mjc-hero__stat-val, .mjc-hero__stat-val.is-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 button.mjc-hero__stat-val:hover { text-decoration: underline; }\n .mjc-hero__next {\n display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px;\n padding: var(--mj-space-3) var(--mj-space-4);\n background: var(--mj-bg-page); border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n }\n .mjc-hero__next-val { font-weight: 700; font-size: 15px; }\n .mjc-hero__edit {\n display: flex; flex-direction: column; gap: var(--mj-space-3);\n padding-top: var(--mj-space-3); border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n }\n .mjc-hero__field { min-width: 0; }\n .mjc-hero__field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjc-hero__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 .mjc-hero--collapsed { padding: 12px 20px; gap: 0; margin-bottom: var(--mj-space-3); }\n .mjc-hero--collapsed .mjc-hero__avatar { width: 42px; height: 42px; border-radius: var(--mj-radius-md, 10px); font-size: 1.05rem; }\n .mjc-hero--collapsed .mjc-hero__title { font-size: 1.15rem; }\n @media (max-width: 720px) {\n .mjc-hero__identity { align-items: flex-start; }\n .mjc-hero__summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n }\n "], encapsulation: 2 });
|
|
516
617
|
};
|
|
517
618
|
MJCContractHeroPanel = __decorate([
|
|
518
619
|
RegisterClassEx(BaseFormPanel, {
|
|
@@ -529,18 +630,24 @@ MJCContractHeroPanel = __decorate([
|
|
|
529
630
|
export { MJCContractHeroPanel };
|
|
530
631
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJCContractHeroPanel, [{
|
|
531
632
|
type: Component,
|
|
532
|
-
args: [{
|
|
533
|
-
|
|
534
|
-
standalone: true,
|
|
535
|
-
encapsulation: ViewEncapsulation.None,
|
|
536
|
-
imports: [CommonModule, BaseFormsModule],
|
|
537
|
-
template: `
|
|
538
|
-
<div class="mjc-hero">
|
|
633
|
+
args: [{ selector: 'mjc-contract-hero-panel', standalone: true, encapsulation: ViewEncapsulation.None, imports: [CommonModule, BaseFormsModule], template: `
|
|
634
|
+
<div class="mjc-hero" [class.mjc-hero--collapsed]="Collapsed">
|
|
539
635
|
<div class="mjc-hero__identity">
|
|
540
|
-
<div class="mjc-hero__avatar"
|
|
636
|
+
<div class="mjc-hero__avatar" aria-hidden="true">
|
|
637
|
+
<i class="fa-solid fa-file-signature"></i>
|
|
638
|
+
@if (!EditMode) {
|
|
639
|
+
<span class="mjc-hero__presence" [attr.data-tone]="StatusTone" [title]="State"></span>
|
|
640
|
+
}
|
|
641
|
+
</div>
|
|
541
642
|
<div class="mjc-hero__copy">
|
|
542
643
|
<div class="mjc-hero__title-row">
|
|
543
644
|
<h1 class="mjc-hero__title">{{ Title }}</h1>
|
|
645
|
+
</div>
|
|
646
|
+
@if (Record.ContractNumber && !Collapsed) {
|
|
647
|
+
<div class="mjc-hero__aka">{{ Record.ContractNumber }}</div>
|
|
648
|
+
}
|
|
649
|
+
<div class="mjc-hero__badges">
|
|
650
|
+
<span class="mjc-hero__entity-chip"><i class="fa-solid fa-file-signature"></i> Contract</span>
|
|
544
651
|
<span class="mjc-chip" [class]="'mjc-chip ' + StateChipClass">{{ State }}</span>
|
|
545
652
|
@if (TypeName) { <span class="mjc-chip mjc-chip--info">{{ TypeName }}</span> }
|
|
546
653
|
@if (Record.HasModifications) {
|
|
@@ -556,53 +663,90 @@ export { MJCContractHeroPanel };
|
|
|
556
663
|
</span>
|
|
557
664
|
}
|
|
558
665
|
</div>
|
|
559
|
-
<div class="mjc-hero__meta">
|
|
560
|
-
<span class="mjc-mono">{{ Record.ContractNumber || 'Unnumbered' }}</span>
|
|
561
|
-
<span>Customer: <strong>{{ CustomerName || '—' }}</strong></span>
|
|
562
|
-
<span>Selling: <strong>{{ CompanyName || '—' }}</strong></span>
|
|
563
|
-
@if (ContactName) { <span>Contact: <strong>{{ ContactName }}</strong></span> }
|
|
564
|
-
</div>
|
|
565
666
|
</div>
|
|
667
|
+
<button type="button" class="mjc-hero__toggle"
|
|
668
|
+
[title]="Collapsed ? 'Expand header' : 'Collapse header'"
|
|
669
|
+
[attr.aria-label]="Collapsed ? 'Expand header' : 'Collapse header'"
|
|
670
|
+
(click)="ToggleCollapsed()">
|
|
671
|
+
<i [class]="Collapsed ? 'fa-solid fa-chevron-down' : 'fa-solid fa-chevron-up'"></i>
|
|
672
|
+
</button>
|
|
566
673
|
</div>
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
<
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
674
|
+
@if (!Collapsed) {
|
|
675
|
+
<div class="mjc-hero__summary">
|
|
676
|
+
<!--
|
|
677
|
+
OUR SIDE FIRST, AND IT IS NOT CALLED "SELLING" (#28 item 8).
|
|
678
|
+
|
|
679
|
+
CompanyID is which of OUR entities holds the agreement. Someone scanning contracts
|
|
680
|
+
orients by that before they look at who it is with, so it leads the summary rather
|
|
681
|
+
than sitting third. "Selling" was also the wrong word: the company holds the
|
|
682
|
+
contract whether or not anything is being sold.
|
|
683
|
+
-->
|
|
684
|
+
<div class="mjc-hero__stat">
|
|
685
|
+
<span class="mjc-hero__stat-label">Company</span>
|
|
686
|
+
<span class="mjc-hero__stat-val">{{ CompanyName || '—' }}</span>
|
|
687
|
+
</div>
|
|
688
|
+
<div class="mjc-hero__stat">
|
|
689
|
+
<span class="mjc-hero__stat-label">Customer</span>
|
|
690
|
+
@if (Record.CustomerOrganizationID && CustomerName) {
|
|
691
|
+
<button type="button" class="mjc-hero__stat-val is-link" (click)="OpenCustomer($event)">{{ CustomerName }}</button>
|
|
692
|
+
} @else {
|
|
693
|
+
<span class="mjc-hero__stat-val">{{ CustomerName || '—' }}</span>
|
|
694
|
+
}
|
|
695
|
+
</div>
|
|
696
|
+
<div class="mjc-hero__stat">
|
|
697
|
+
<span class="mjc-hero__stat-label">Contact</span>
|
|
698
|
+
@if (Record.PrimaryContactPersonID && ContactName) {
|
|
699
|
+
<button type="button" class="mjc-hero__stat-val is-link" (click)="OpenContact($event)">{{ ContactName }}</button>
|
|
700
|
+
} @else {
|
|
701
|
+
<span class="mjc-hero__stat-val">{{ ContactName || '—' }}</span>
|
|
702
|
+
}
|
|
703
|
+
</div>
|
|
704
|
+
<div class="mjc-hero__stat">
|
|
705
|
+
<span class="mjc-hero__stat-label">Executed</span>
|
|
706
|
+
<span class="mjc-hero__stat-val">{{ (Record.ExecutedDate | date: 'd MMM y') || '—' }}</span>
|
|
707
|
+
</div>
|
|
708
|
+
<div class="mjc-hero__stat">
|
|
709
|
+
<span class="mjc-hero__stat-label">Effective</span>
|
|
710
|
+
<span class="mjc-hero__stat-val">{{ (Record.EffectiveDate | date: 'd MMM y') || '—' }}</span>
|
|
711
|
+
</div>
|
|
712
|
+
<div class="mjc-hero__stat">
|
|
713
|
+
<span class="mjc-hero__stat-label">Term ends</span>
|
|
714
|
+
<span class="mjc-hero__stat-val">{{ (Record.EndDate | date: 'd MMM y') || '—' }}</span>
|
|
715
|
+
</div>
|
|
716
|
+
<div class="mjc-hero__stat">
|
|
717
|
+
<span class="mjc-hero__stat-label">Agreement</span>
|
|
718
|
+
<span class="mjc-hero__stat-val">{{ TemplateName || '—' }}</span>
|
|
719
|
+
</div>
|
|
720
|
+
<div class="mjc-hero__stat">
|
|
721
|
+
<span class="mjc-hero__stat-label">Created from</span>
|
|
722
|
+
<span class="mjc-hero__stat-val">{{ CreatingEntityName || 'Entered directly' }}</span>
|
|
723
|
+
</div>
|
|
599
724
|
</div>
|
|
725
|
+
@if (DaysToEnd !== null) {
|
|
726
|
+
<div class="mjc-hero__next">
|
|
727
|
+
<span class="mjc-hero__stat-label">Term</span>
|
|
728
|
+
<span class="mjc-hero__next-val">{{ EndsInText }}</span>
|
|
729
|
+
</div>
|
|
730
|
+
}
|
|
731
|
+
@if (EditMode) {
|
|
732
|
+
<div class="mjc-hero__edit">
|
|
733
|
+
<div class="mjc-hero__field">
|
|
734
|
+
<mj-form-field [Record]="Record" [ShowLabel]="true" FieldName="Description"
|
|
735
|
+
Type="textarea" [EditMode]="EditMode" [FormContext]="FormContext"></mj-form-field>
|
|
736
|
+
</div>
|
|
737
|
+
</div>
|
|
738
|
+
}
|
|
739
|
+
@if (!Record.ContractNumber) {
|
|
740
|
+
<div class="mjc-flag">
|
|
741
|
+
The contract number is minted on first save, from a counter taken under a lock — so it
|
|
742
|
+
cannot collide with another contract created at the same moment.
|
|
743
|
+
</div>
|
|
744
|
+
}
|
|
600
745
|
}
|
|
601
746
|
</div>
|
|
602
|
-
`,
|
|
603
|
-
}]
|
|
747
|
+
`, styles: ["/**\n * contracts-kit.css \u2014 ported from design-docs/ui-design/mockups-v2/tokens.css.\n *\n * \u26A0 SEMANTIC TOKENS ONLY. MJ's design-token rule is explicit: *\"NEVER use primitive tokens\n * (`--mj-color-neutral-*`, `--mj-color-brand-*`) in component CSS. Primitives don't adapt to dark\n * mode.\"* An earlier version of this file used twelve of them, because the mockup did \u2014 and in a\n * standalone mockup page that is harmless, since there is no dark mode to adapt to. Ported into a real\n * component stylesheet it means every tinted surface, chip and clause box keeps its LIGHT colour when\n * the app is themed dark. That is the theming break, and it is invisible until someone switches theme.\n *\n * The mapping applied: neutral-50 \u2192 bg-surface-sunken, neutral-100 \u2192 border-subtle, neutral-300 \u2192\n * border-strong, success/error/warning-50 \u2192 status-*-bg, success/error-700 \u2192 status-*-text, brand-50 \u2192\n * status-info-bg, brand-100 \u2192 status-info-border, brand-700/900 \u2192 status-info-text. `#fff` on a brand\n * fill \u2192 `--mj-brand-on-primary`.\n *\n * THE MOCKUPS ARE THE SPEC, and this file exists to keep them so. An earlier version of this kit was\n * written from MEMORY of them, and it was wrong in a way that is invisible in source and obvious on\n * screen: it used token names that do not exist. `--mj-font-size-sm`, `--mj-text-tertiary`,\n * `--mj-color-warning-text`, `--mj-color-success-border` and four others are not MJ tokens (the real\n * names are `--mj-text-sm`, `--mj-status-warning-text`, `--mj-status-success`, \u2026). Every one of those\n * resolved to NOTHING \u2014 so font sizes fell back to browser defaults and the state chips rendered with\n * no colour at all. That is most of what \"looks bad\" was.\n *\n * So: class names and rules below are the mockup's, verbatim where possible, and **every token used\n * here has been checked to exist in MJ's `_tokens.scss`.** If you add a rule, check the token first \u2014\n * a missing custom property fails silently, which is the worst failure mode CSS has.\n *\n * SHIPPED VIA THE SECTION SHELL (`styleUrls` + `ViewEncapsulation.None`). `ngc` only compiles what a\n * component references, so a stylesheet nothing references is built into dist and never loaded.\n * `None` is required, not lazy: these classes are used by DESCENDANT components.\n *\n * Prefix note: the mockup used bare class names (`.panel`, `.chip`) because it was a standalone page.\n * Here everything is `mjc-` prefixed \u2014 bare `.panel` inside a real Explorer would collide with MJ's own\n * chrome, and `ViewEncapsulation.None` means these rules are global.\n */\n\n/* \u2500\u2500 Page frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-page {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-5);\n}\n\n/* A grid page needs a DEFINITE height: mj-explorer-entity-data-grid is height:100% outside a related\n panel, and 100% of an auto-height parent is zero \u2014 the grid renders no rows while its toolbar still\n reports the count. MJ's own source documents that symptom. `min-height: 0` on the fill slot is\n mandatory: a flex child defaults to min-height:auto and refuses to shrink, so without it the grid\n pushes the page taller instead of scrolling inside itself. */\n.mjc-page--grid { height: 100%; min-height: 0; }\n.mjc-grid-fill { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }\n\n/* Intro prose. Constrained measure \u2014 text stops being readable much past this \u2014 and it is a real\n block with real spacing, not a bare text node floating between cards. */\n.mjc-page__intro {\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n line-height: 1.55;\n margin: 0;\n max-width: 78ch;\n}\n\n/* \u2500\u2500 Panel body helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Our panels are real `<mj-collapsible-panel>`s, so MJ paints the frame, the header and the spacing.\n These classes style only what goes INSIDE one. */\n\n.mjc-body { padding: var(--mj-space-4); }\n.mjc-body--flush { padding: 0; } /* a table fills the panel edge to edge */\n.mjc-body > * + * { margin-top: var(--mj-space-3); } /* nothing ever touches its neighbour */\n\n.mjc-note {\n margin: 0;\n color: var(--mj-text-muted);\n font-size: var(--mj-text-xs);\n line-height: 1.55;\n}\n\n/* A note under a flush table needs its own padding and a rule above it, or it reads as a table row. */\n.mjc-note--footer {\n padding: var(--mj-space-3) var(--mj-space-4);\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n/* \u2500\u2500 Hero (mockup 1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-hero {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n padding: var(--mj-space-4) var(--mj-space-5);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.mjc-hero__identity { display: flex; align-items: center; gap: var(--mj-space-4); min-width: 0; }\n\n.mjc-hero__avatar {\n flex: none;\n width: 52px; height: 52px;\n border-radius: var(--mj-radius-md);\n display: flex; align-items: center; justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: var(--mj-text-xl, 1.375rem);\n}\n\n.mjc-hero__copy { min-width: 0; flex: 1; }\n\n.mjc-hero__title-row {\n display: flex; align-items: center; flex-wrap: wrap;\n gap: var(--mj-space-2) var(--mj-space-3);\n}\n\n.mjc-hero__title {\n margin: 0;\n font-size: var(--mj-text-lg);\n font-weight: 700;\n line-height: 1.25;\n /* Long contract descriptions must not push the chips off the card. */\n overflow-wrap: anywhere;\n}\n\n.mjc-hero__meta {\n display: flex; flex-wrap: wrap;\n gap: var(--mj-space-3);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-sm);\n margin-top: var(--mj-space-2);\n}\n\n/* auto-fit so five stats sit in a row on a wide screen and reflow on a laptop, rather than\n overflowing the card \u2014 which is what a fixed five-column grid did. */\n.mjc-hero__stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));\n gap: var(--mj-space-3);\n}\n\n.mjc-stat {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: var(--mj-space-3);\n min-width: 0;\n}\n.mjc-stat__label {\n display: block; font-size: var(--mj-text-xs);\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted);\n}\n.mjc-stat__value {\n display: block; font-size: var(--mj-text-base); font-weight: 700; margin-top: 2px;\n overflow-wrap: anywhere;\n}\n.mjc-stat__sub { display: block; font-size: var(--mj-text-xs); color: var(--mj-text-muted); }\n\n/* \u2500\u2500 Chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-chip {\n display: inline-flex; align-items: center; gap: 4px;\n font-size: var(--mj-text-xs); font-weight: 600;\n padding: 2px 9px; border-radius: 999px;\n border: 1px solid transparent; white-space: nowrap;\n}\n.mjc-chip--ok { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); border-color: var(--mj-status-success); }\n.mjc-chip--warn { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); border-color: var(--mj-status-warning); }\n.mjc-chip--error { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); border-color: var(--mj-status-error); }\n.mjc-chip--info { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); border-color: var(--mj-status-info-border); }\n.mjc-chip--muted { background: var(--mj-border-subtle); color: var(--mj-text-secondary); border-color: var(--mj-border-default); }\n\n/* \u2500\u2500 Buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-btn {\n display: inline-flex; align-items: center; gap: 6px;\n font-size: var(--mj-text-sm); font-weight: 600;\n padding: 6px 12px;\n border-radius: var(--mj-radius-sm);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n.mjc-btn:disabled { opacity: .5; cursor: default; }\n.mjc-btn--primary { background: var(--mj-brand-primary); border-color: var(--mj-brand-primary); color: var(--mj-brand-on-primary); }\n.mjc-btn--flat { background: transparent; border-color: transparent; color: var(--mj-brand-primary); }\n.mjc-btn--sm { padding: 3px 9px; font-size: var(--mj-text-xs); }\n.mjc-btn--danger { color: var(--mj-status-error-text); border-color: transparent; background: transparent; }\n\n/* \u2500\u2500 Field grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-fields {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));\n gap: var(--mj-space-3) var(--mj-space-4);\n}\n.mjc-field > label {\n display: block; font-size: var(--mj-text-xs); color: var(--mj-text-muted);\n text-transform: uppercase; letter-spacing: .04em; margin-bottom: 3px;\n}\n.mjc-field .mjc-val {\n padding: 6px 9px;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n background: var(--mj-bg-surface);\n min-height: 31px;\n overflow-wrap: anywhere;\n}\n.mjc-field .mjc-val--ro { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.mjc-hint { color: var(--mj-text-muted); font-size: var(--mj-text-xs); margin-top: 3px; }\n\n/* \u2500\u2500 Tables \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The mockup renders modifications, documents and lineage as TABLES, not stacked cards. With three\n or more rows a table is scannable and a stack is a wall. */\n\ntable.mjc-grid { width: 100%; border-collapse: collapse; }\ntable.mjc-grid th {\n text-align: left; font-size: var(--mj-text-xs);\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700;\n padding: var(--mj-space-2) var(--mj-space-3);\n border-bottom: 1.5px solid var(--mj-border-default);\n}\ntable.mjc-grid td {\n padding: var(--mj-space-3);\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: top;\n}\ntable.mjc-grid tr:last-child td { border-bottom: 0; }\ntable.mjc-grid tbody tr:hover td { background: var(--mj-bg-surface-sunken); }\n.mjc-row--click { cursor: pointer; }\n\n.mjc-muted { color: var(--mj-text-muted); }\n.mjc-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--mj-text-xs); }\n\n/* \u2500\u2500 The clause pair (mockups 1 and 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The standard clause and what this contract says instead, read side by side. This is the app's\n central idea rendered, so it gets real styling rather than two paragraphs. */\n\n.mjc-pair {\n display: grid; grid-template-columns: 1fr; gap: var(--mj-space-3);\n margin-top: var(--mj-space-2);\n}\n/* Side by side only when there is room \u2014 two 40ch columns on a laptop is worse than one readable one. */\n@media (min-width: 1100px) { .mjc-pair { grid-template-columns: 1fr 1fr; } }\n\n.mjc-pair__tag {\n display: block; font-size: var(--mj-text-xs); font-weight: 700;\n text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); margin-bottom: 3px;\n}\n.mjc-pair__tag--mod { color: var(--mj-status-warning-text); }\n\n.mjc-clause {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border-left: 2px solid var(--mj-border-strong);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-radius: 0 var(--mj-radius-sm) var(--mj-radius-sm) 0;\n margin: 0;\n /* Clause text carries its own line breaks, and 9.1 is a single 1,100-character sentence in caps \u2014\n both must wrap inside the box rather than escaping it. */\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n.mjc-clause--mod {\n border-left-color: var(--mj-status-warning);\n background: var(--mj-status-warning-bg);\n color: var(--mj-text-primary);\n}\n\n.mjc-toggle {\n font-size: var(--mj-text-xs); color: var(--mj-brand-primary);\n font-weight: 600; margin-top: 4px; background: none; border: 0; padding: 0; cursor: pointer;\n}\n\n/* \u2500\u2500 Callout \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-flag {\n background: var(--mj-status-warning-bg);\n border-left: 3px solid var(--mj-status-warning);\n padding: var(--mj-space-2) var(--mj-space-3);\n font-size: var(--mj-text-xs);\n color: var(--mj-status-warning-text);\n border-radius: 0 var(--mj-radius-sm) var(--mj-radius-sm) 0;\n line-height: 1.55;\n}\n\n/* \u2500\u2500 Invalid input \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* A required field the user has emptied. Border + ring only \u2014 no background change, because these\n are prose textareas and tinting the reading surface makes the text itself harder to read, which\n is the opposite of helpful when the point is \"write something here\". Tokens only, per the\n design-token gate. */\n.mjc-invalid {\n border-color: var(--mj-status-error) !important;\n box-shadow: 0 0 0 2px var(--mj-status-error-bg);\n outline: none;\n}\n\n/* \u2500\u2500 Filter pills (watchlist) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-pills { display: flex; flex-wrap: wrap; gap: var(--mj-space-2); align-items: center; }\n\n.mjc-pill {\n appearance: none; cursor: pointer;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border-radius: 999px;\n padding: 3px var(--mj-space-3);\n font-size: var(--mj-text-sm);\n line-height: 1.6;\n display: inline-flex; align-items: center; gap: var(--mj-space-2);\n}\n.mjc-pill:hover { border-color: var(--mj-brand-primary); color: var(--mj-text-primary); }\n.mjc-pill:disabled { opacity: .5; cursor: default; }\n.mjc-pill--active {\n background: var(--mj-status-info-bg);\n border-color: var(--mj-brand-primary);\n color: var(--mj-status-info-text);\n font-weight: 700;\n}\n.mjc-pill__count { font-variant-numeric: tabular-nums; opacity: .85; font-size: var(--mj-text-xs); }\n\n/* \u2500\u2500 Dashboard command center \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mjc-kpis {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));\n gap: var(--mj-space-3);\n}\n.mjc-kpi {\n appearance: none;\n font: inherit;\n text-align: left;\n color: inherit;\n cursor: pointer;\n padding: var(--mj-space-3) var(--mj-space-4);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface);\n}\n.mjc-kpi:hover { border-color: var(--mj-brand-primary); }\n.mjc-kpi:disabled { opacity: .6; cursor: default; }\n.mjc-kpi--alert .mjc-kpi__v { color: var(--mj-status-error-text); }\n.mjc-kpi__l {\n font-size: var(--mj-text-xs);\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: .04em;\n color: var(--mj-text-muted);\n}\n.mjc-kpi__v {\n font-size: var(--mj-text-xl, 1.35rem);\n font-weight: 700;\n margin: 4px 0 2px;\n font-variant-numeric: tabular-nums;\n}\n.mjc-kpi__f {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n line-height: 1.35;\n}\n\n.mjc-dash-split {\n display: grid;\n grid-template-columns: 1.15fr .85fr;\n gap: var(--mj-space-3);\n}\n@media (max-width: 900px) { .mjc-dash-split { grid-template-columns: 1fr; } }\n\n.mjc-dash-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n overflow: hidden;\n}\n.mjc-dash-card__h {\n display: flex;\n justify-content: space-between;\n gap: var(--mj-space-2);\n align-items: baseline;\n padding: var(--mj-space-3) var(--mj-space-4);\n border-bottom: 1px solid var(--mj-border-subtle);\n font-weight: 700;\n}\n.mjc-dash-card__h span {\n font-weight: 500;\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.mjc-barlist { display: flex; flex-direction: column; gap: var(--mj-space-2); padding: var(--mj-space-3) var(--mj-space-4); }\n.mjc-barrow {\n display: grid;\n grid-template-columns: 7.5rem 1fr auto;\n gap: var(--mj-space-2);\n align-items: center;\n font-size: var(--mj-text-sm);\n}\n.mjc-track {\n height: 8px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 99px;\n overflow: hidden;\n}\n.mjc-fill {\n height: 100%;\n background: var(--mj-brand-primary);\n border-radius: 99px;\n}\n.mjc-num { font-variant-numeric: tabular-nums; font-weight: 700; }\n\n.mjc-funnel {\n display: flex;\n gap: var(--mj-space-2);\n align-items: flex-end;\n height: 10rem;\n padding: var(--mj-space-3) var(--mj-space-4);\n}\n.mjc-funnel__col {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n.mjc-funnel__bar {\n width: 100%;\n min-height: 8px;\n border-radius: 8px 8px 2px 2px;\n background: var(--mj-brand-primary);\n}\n.mjc-funnel__n { font-weight: 700; }\n.mjc-funnel__lab {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n text-align: center;\n}\n\n.mjc-buckets {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: var(--mj-space-2);\n padding: var(--mj-space-3) var(--mj-space-4);\n}\n@media (max-width: 700px) { .mjc-buckets { grid-template-columns: 1fr 1fr; } }\n.mjc-bucket {\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n padding: var(--mj-space-3);\n}\n\n.mjc-viewer-host {\n min-height: 420px;\n height: 480px;\n display: flex;\n flex-direction: column;\n}\n.mjc-viewer-host mj-entity-viewer {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 350px;\n width: 100%;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n A sentence in a bordered box, never a bare line of text in whitespace. */\n\n.mjc-empty {\n display: flex; align-items: center; gap: var(--mj-space-2); justify-content: center;\n padding: var(--mj-space-6);\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n background: var(--mj-bg-surface-sunken);\n border: 1px dashed var(--mj-border-strong);\n border-radius: var(--mj-radius-md);\n text-align: center;\n}\n", "\n .mjc-hero {\n display: flex; flex-direction: column; gap: var(--mj-space-4);\n padding: 20px 24px; margin-bottom: var(--mj-space-4);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-xl, 16px);\n box-shadow: var(--mj-shadow-md, 0 4px 16px rgba(0, 0, 0, .08));\n position: relative; overflow: hidden;\n }\n .mjc-hero::before {\n content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3.5px;\n background: linear-gradient(90deg, #38bdf8 0%, #6366f1 50%, #10b981 100%);\n }\n .mjc-hero__identity { display: flex; align-items: center; gap: var(--mj-space-4); min-width: 0; }\n .mjc-hero__avatar {\n flex: none; width: 60px; height: 60px; border-radius: var(--mj-radius-lg, 14px);\n position: relative; display: flex; align-items: center; justify-content: center;\n background: linear-gradient(135deg, color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-bg-surface)) 0%, color-mix(in srgb, var(--mj-brand-accent, #6366f1) 25%, var(--mj-bg-surface)) 100%);\n color: var(--mj-brand-primary); font-size: 1.35rem;\n box-shadow: 0 4px 14px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border: 2px solid color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n }\n .mjc-hero__presence {\n position: absolute; bottom: -2px; right: -2px; width: 13px; height: 13px;\n border-radius: 50%; border: 2.5px solid var(--mj-bg-surface-card);\n background: var(--mj-text-muted, #94a3b8);\n }\n .mjc-hero__presence[data-tone='success'] { background: var(--mj-status-success, #10b981); }\n .mjc-hero__presence[data-tone='warning'] { background: var(--mj-status-warning, #f59e0b); }\n .mjc-hero__copy { min-width: 0; flex: 1; }\n .mjc-hero__title {\n margin: 0; font-size: var(--mj-text-lg, 18px); font-weight: 800;\n letter-spacing: -.02em; line-height: 1.25; color: var(--mj-text-primary);\n overflow-wrap: anywhere;\n }\n .mjc-hero__aka { margin-top: 2px; font-size: var(--mj-text-xs); color: var(--mj-text-muted); }\n .mjc-hero__badges {\n display: flex; align-items: center; flex-wrap: wrap;\n gap: var(--mj-space-2); margin-top: var(--mj-space-2);\n }\n .mjc-hero__entity-chip {\n display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px;\n border-radius: var(--mj-radius-sm);\n background: var(--mj-status-info-bg); color: var(--mj-brand-primary);\n font-size: var(--mj-text-xs); font-weight: 650;\n }\n .mjc-hero__toggle {\n display: inline-flex; align-items: center; justify-content: center;\n flex: none; width: 32px; height: 32px; margin-left: auto; padding: 0;\n border: 1px solid var(--mj-border-default); border-radius: var(--mj-radius-md, 8px);\n background: var(--mj-bg-surface-sunken, rgba(255,255,255,.04));\n color: var(--mj-text-secondary); cursor: pointer; font-size: 12px;\n }\n .mjc-hero__toggle:hover {\n background: var(--mj-bg-surface-hover, rgba(255,255,255,.08));\n color: var(--mj-text-primary); border-color: var(--mj-brand-primary);\n }\n .mjc-hero__summary {\n display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));\n gap: var(--mj-space-3); padding-top: var(--mj-space-4);\n border-top: 1px solid var(--mj-border-default);\n }\n .mjc-hero__stat { display: flex; flex-direction: column; gap: 3px; min-width: 0; }\n .mjc-hero__stat-label {\n font-size: var(--mj-text-xs); font-weight: 700; letter-spacing: .04em;\n text-transform: uppercase; color: var(--mj-text-muted);\n }\n .mjc-hero__stat-val {\n font-size: 15px; font-weight: 650; color: var(--mj-text-primary);\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n }\n button.mjc-hero__stat-val, .mjc-hero__stat-val.is-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 button.mjc-hero__stat-val:hover { text-decoration: underline; }\n .mjc-hero__next {\n display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px;\n padding: var(--mj-space-3) var(--mj-space-4);\n background: var(--mj-bg-page); border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n }\n .mjc-hero__next-val { font-weight: 700; font-size: 15px; }\n .mjc-hero__edit {\n display: flex; flex-direction: column; gap: var(--mj-space-3);\n padding-top: var(--mj-space-3); border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n }\n .mjc-hero__field { min-width: 0; }\n .mjc-hero__field .mj-forms-field {\n display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 0;\n }\n .mjc-hero__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 .mjc-hero--collapsed { padding: 12px 20px; gap: 0; margin-bottom: var(--mj-space-3); }\n .mjc-hero--collapsed .mjc-hero__avatar { width: 42px; height: 42px; border-radius: var(--mj-radius-md, 10px); font-size: 1.05rem; }\n .mjc-hero--collapsed .mjc-hero__title { font-size: 1.15rem; }\n @media (max-width: 720px) {\n .mjc-hero__identity { align-items: flex-start; }\n .mjc-hero__summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n }\n "] }]
|
|
604
748
|
}], null, null); })();
|
|
605
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractHeroPanel, { className: "MJCContractHeroPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber:
|
|
749
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractHeroPanel, { className: "MJCContractHeroPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber: 301 }); })();
|
|
606
750
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
607
751
|
* 2 · Renewal terms — a real rail section
|
|
608
752
|
* ──────────────────────────────────────────────────────────────────────────── */
|
|
@@ -619,7 +763,7 @@ let MJCContractRenewalPanel = class MJCContractRenewalPanel extends BaseFormPane
|
|
|
619
763
|
get NoticeDeadline() { return this.Record?.RenewalNoticeDeadline ?? null; }
|
|
620
764
|
get InCancellationWindow() { return this.Record?.IsInCancellationWindow === true; }
|
|
621
765
|
static ɵfac = /*@__PURE__*/ (() => { let ɵMJCContractRenewalPanel_BaseFactory; return function MJCContractRenewalPanel_Factory(__ngFactoryType__) { return (ɵMJCContractRenewalPanel_BaseFactory || (ɵMJCContractRenewalPanel_BaseFactory = i0.ɵɵgetInheritedFactory(MJCContractRenewalPanel)))(__ngFactoryType__ || MJCContractRenewalPanel); }; })();
|
|
622
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractRenewalPanel, selectors: [["mjc-contract-renewal-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
766
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractRenewalPanel, selectors: [["mjc-contract-renewal-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 35, vars: 10, consts: [["SectionKey", "renewal", "SectionName", "Renewal terms", "Icon", "fa-solid fa-calendar-days", 3, "Form", "FormContext"], [1, "mjc-body"], [1, "mjc-chip", "mjc-chip--muted"], [1, "mjc-fields"], [1, "mjc-field"], ["aria-label", "Does this agreement auto-renew?", 3, "ngModel"], [1, "mjc-val"], [1, "mjc-hint"], ["type", "number", "min", "0", "aria-label", "Renewal notice days", 2, "width", "100%", 3, "ngModel"], ["type", "number", "min", "0", "aria-label", "Cancellation window days", 2, "width", "100%", 3, "ngModel"], ["type", "number", "min", "0", "step", "0.01", "aria-label", "Annual increase percent", 2, "width", "100%", 3, "ngModel"], [1, "mjc-note"], [1, "mjc-empty"], ["aria-label", "Does this agreement auto-renew?", 3, "ngModelChange", "ngModel"], [3, "ngValue"], ["type", "number", "min", "0", "aria-label", "Renewal notice days", 2, "width", "100%", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "0", "aria-label", "Cancellation window days", 2, "width", "100%", 3, "ngModelChange", "ngModel"], ["type", "number", "min", "0", "step", "0.01", "aria-label", "Annual increase percent", 2, "width", "100%", 3, "ngModelChange", "ngModel"]], template: function MJCContractRenewalPanel_Template(rf, ctx) { if (rf & 1) {
|
|
623
767
|
i0.ɵɵelementStart(0, "mj-collapsible-panel", 0)(1, "div", 1)(2, "span", 2);
|
|
624
768
|
i0.ɵɵtext(3, "as stated in the agreement");
|
|
625
769
|
i0.ɵɵelementEnd();
|
|
@@ -630,26 +774,32 @@ let MJCContractRenewalPanel = class MJCContractRenewalPanel extends BaseFormPane
|
|
|
630
774
|
i0.ɵɵconditionalCreate(10, MJCContractRenewalPanel_Conditional_10_Template, 2, 0, "div", 7);
|
|
631
775
|
i0.ɵɵelementEnd();
|
|
632
776
|
i0.ɵɵelementStart(11, "div", 4)(12, "label");
|
|
633
|
-
i0.ɵɵtext(13, "Renewal notice
|
|
777
|
+
i0.ɵɵtext(13, "Renewal notice (days)");
|
|
634
778
|
i0.ɵɵelementEnd();
|
|
635
779
|
i0.ɵɵconditionalCreate(14, MJCContractRenewalPanel_Conditional_14_Template, 1, 1, "input", 8)(15, MJCContractRenewalPanel_Conditional_15_Template, 2, 1, "div", 6);
|
|
636
|
-
i0.ɵɵ
|
|
780
|
+
i0.ɵɵelementStart(16, "div", 7);
|
|
781
|
+
i0.ɵɵtext(17, " Written notice we must give the customer before a renewal price change. ");
|
|
637
782
|
i0.ɵɵelementEnd();
|
|
638
|
-
i0.ɵɵ
|
|
639
|
-
i0.ɵɵtext(19, "Notice to cancel (days)");
|
|
783
|
+
i0.ɵɵconditionalCreate(18, MJCContractRenewalPanel_Conditional_18_Template, 3, 4, "div", 7);
|
|
640
784
|
i0.ɵɵelementEnd();
|
|
641
|
-
i0.ɵɵ
|
|
642
|
-
i0.ɵɵ
|
|
785
|
+
i0.ɵɵelementStart(19, "div", 4)(20, "label");
|
|
786
|
+
i0.ɵɵtext(21, "Notice to cancel (days)");
|
|
643
787
|
i0.ɵɵelementEnd();
|
|
644
|
-
i0.ɵɵ
|
|
645
|
-
i0.ɵɵ
|
|
788
|
+
i0.ɵɵconditionalCreate(22, MJCContractRenewalPanel_Conditional_22_Template, 1, 1, "input", 9)(23, MJCContractRenewalPanel_Conditional_23_Template, 2, 1, "div", 6);
|
|
789
|
+
i0.ɵɵelementStart(24, "div", 7);
|
|
790
|
+
i0.ɵɵtext(25, "Notice the customer must give us to cancel.");
|
|
646
791
|
i0.ɵɵelementEnd();
|
|
647
|
-
i0.ɵɵconditionalCreate(26, MJCContractRenewalPanel_Conditional_26_Template,
|
|
792
|
+
i0.ɵɵconditionalCreate(26, MJCContractRenewalPanel_Conditional_26_Template, 2, 0, "div", 7);
|
|
793
|
+
i0.ɵɵelementEnd();
|
|
794
|
+
i0.ɵɵelementStart(27, "div", 4)(28, "label");
|
|
795
|
+
i0.ɵɵtext(29, "Annual increase (%)");
|
|
796
|
+
i0.ɵɵelementEnd();
|
|
797
|
+
i0.ɵɵconditionalCreate(30, MJCContractRenewalPanel_Conditional_30_Template, 1, 1, "input", 10)(31, MJCContractRenewalPanel_Conditional_31_Template, 2, 1, "div", 6);
|
|
648
798
|
i0.ɵɵelementEnd()();
|
|
649
|
-
i0.ɵɵelementStart(
|
|
650
|
-
i0.ɵɵtext(
|
|
799
|
+
i0.ɵɵelementStart(32, "p", 11);
|
|
800
|
+
i0.ɵɵtext(33, " These record what the signed paper says. The subscription in orders holds the operational setting and may legitimately differ \u2014 a mismatch is a finding, not a bug. ");
|
|
651
801
|
i0.ɵɵelementEnd();
|
|
652
|
-
i0.ɵɵconditionalCreate(
|
|
802
|
+
i0.ɵɵconditionalCreate(34, MJCContractRenewalPanel_Conditional_34_Template, 2, 0, "div", 12);
|
|
653
803
|
i0.ɵɵelementEnd()();
|
|
654
804
|
} if (rf & 2) {
|
|
655
805
|
i0.ɵɵproperty("Form", ctx.FormComponent)("FormContext", ctx.FormContext);
|
|
@@ -659,17 +809,17 @@ let MJCContractRenewalPanel = class MJCContractRenewalPanel extends BaseFormPane
|
|
|
659
809
|
i0.ɵɵconditional(!ctx.Record.AutoRenew ? 10 : -1);
|
|
660
810
|
i0.ɵɵadvance(4);
|
|
661
811
|
i0.ɵɵconditional(ctx.EditMode ? 14 : 15);
|
|
662
|
-
i0.ɵɵadvance(2);
|
|
663
|
-
i0.ɵɵconditional(ctx.NoticeDeadline ? 16 : -1);
|
|
664
812
|
i0.ɵɵadvance(4);
|
|
665
|
-
i0.ɵɵconditional(ctx.
|
|
666
|
-
i0.ɵɵadvance(2);
|
|
667
|
-
i0.ɵɵconditional(ctx.InCancellationWindow ? 22 : -1);
|
|
813
|
+
i0.ɵɵconditional(ctx.NoticeDeadline ? 18 : -1);
|
|
668
814
|
i0.ɵɵadvance(4);
|
|
669
|
-
i0.ɵɵconditional(ctx.EditMode ?
|
|
815
|
+
i0.ɵɵconditional(ctx.EditMode ? 22 : 23);
|
|
670
816
|
i0.ɵɵadvance(4);
|
|
671
|
-
i0.ɵɵconditional(
|
|
672
|
-
|
|
817
|
+
i0.ɵɵconditional(ctx.InCancellationWindow ? 26 : -1);
|
|
818
|
+
i0.ɵɵadvance(4);
|
|
819
|
+
i0.ɵɵconditional(ctx.EditMode ? 30 : 31);
|
|
820
|
+
i0.ɵɵadvance(4);
|
|
821
|
+
i0.ɵɵconditional(!ctx.Record.RenewalNoticeDays && !ctx.Record.CancellationWindowDays && ctx.Record.AnnualIncreasePercent === null ? 34 : -1);
|
|
822
|
+
} }, dependencies: [CommonModule, FormsModule, i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i3.DefaultValueAccessor, i3.NumberValueAccessor, i3.SelectControlValueAccessor, i3.NgControlStatus, i3.MinValidator, i3.NgModel, BaseFormsModule, i1.MjCollapsiblePanelComponent, i2.DatePipe], encapsulation: 2 });
|
|
673
823
|
};
|
|
674
824
|
MJCContractRenewalPanel = __decorate([
|
|
675
825
|
RegisterClassEx(BaseFormPanel, {
|
|
@@ -744,13 +894,22 @@ export { MJCContractRenewalPanel };
|
|
|
744
894
|
}
|
|
745
895
|
</div>
|
|
746
896
|
<div class="mjc-field">
|
|
747
|
-
<label>Renewal notice
|
|
897
|
+
<label>Renewal notice (days)</label>
|
|
748
898
|
@if (EditMode) {
|
|
749
899
|
<input type="number" min="0" style="width:100%" [ngModel]="Record.RenewalNoticeDays"
|
|
750
900
|
(ngModelChange)="Set('RenewalNoticeDays', $event)" aria-label="Renewal notice days" />
|
|
751
901
|
} @else {
|
|
752
902
|
<div class="mjc-val">{{ Record.RenewalNoticeDays ? Record.RenewalNoticeDays + ' days' : '—' }}</div>
|
|
753
903
|
}
|
|
904
|
+
<!--
|
|
905
|
+
WHICH DIRECTION THE NOTICE RUNS IS THE WHOLE POINT (#28 item 6). This field
|
|
906
|
+
and CancellationWindowDays below are both "a number of days of notice",
|
|
907
|
+
and the old labels left the reader to work out whose notice each one was.
|
|
908
|
+
One is what we owe them; the other is what they owe us.
|
|
909
|
+
-->
|
|
910
|
+
<div class="mjc-hint">
|
|
911
|
+
Written notice we must give the customer before a renewal price change.
|
|
912
|
+
</div>
|
|
754
913
|
@if (NoticeDeadline) {
|
|
755
914
|
<div class="mjc-hint">deadline: {{ NoticeDeadline | date: 'd MMM y' }}</div>
|
|
756
915
|
}
|
|
@@ -763,6 +922,7 @@ export { MJCContractRenewalPanel };
|
|
|
763
922
|
} @else {
|
|
764
923
|
<div class="mjc-val">{{ Record.CancellationWindowDays ? Record.CancellationWindowDays + ' days' : '—' }}</div>
|
|
765
924
|
}
|
|
925
|
+
<div class="mjc-hint">Notice the customer must give us to cancel.</div>
|
|
766
926
|
@if (InCancellationWindow) { <div class="mjc-hint">the window is open now</div> }
|
|
767
927
|
</div>
|
|
768
928
|
<div class="mjc-field">
|
|
@@ -792,7 +952,7 @@ export { MJCContractRenewalPanel };
|
|
|
792
952
|
`,
|
|
793
953
|
}]
|
|
794
954
|
}], null, null); })();
|
|
795
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractRenewalPanel, { className: "MJCContractRenewalPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber:
|
|
955
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractRenewalPanel, { className: "MJCContractRenewalPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber: 525 }); })();
|
|
796
956
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
797
957
|
* 2b · Dates — its own rail section, replacing the generated `datesAndTerms`
|
|
798
958
|
* ──────────────────────────────────────────────────────────────────────────── */
|
|
@@ -875,7 +1035,7 @@ let MJCContractDatesPanel = class MJCContractDatesPanel extends BaseFormPanel {
|
|
|
875
1035
|
i0.ɵɵconditional(ctx.Record.DaysToEnd !== null ? 20 : -1);
|
|
876
1036
|
i0.ɵɵadvance(4);
|
|
877
1037
|
i0.ɵɵconditional(ctx.EditMode ? 24 : 25);
|
|
878
|
-
} }, dependencies: [CommonModule, FormsModule,
|
|
1038
|
+
} }, dependencies: [CommonModule, FormsModule, i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgModel, BaseFormsModule, i1.MjCollapsiblePanelComponent, i2.DatePipe], encapsulation: 2 });
|
|
879
1039
|
};
|
|
880
1040
|
MJCContractDatesPanel = __decorate([
|
|
881
1041
|
RegisterClassEx(BaseFormPanel, {
|
|
@@ -976,13 +1136,12 @@ export { MJCContractDatesPanel };
|
|
|
976
1136
|
`,
|
|
977
1137
|
}]
|
|
978
1138
|
}], null, null); })();
|
|
979
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractDatesPanel, { className: "MJCContractDatesPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber:
|
|
1139
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractDatesPanel, { className: "MJCContractDatesPanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber: 649 }); })();
|
|
980
1140
|
/* ────────────────────────────────────────────────────────────────────────────
|
|
981
1141
|
* 4 · Lineage — change orders and supersession, read-only
|
|
982
1142
|
* ──────────────────────────────────────────────────────────────────────────── */
|
|
983
1143
|
let MJCContractLineagePanel = class MJCContractLineagePanel extends BaseFormPanel {
|
|
984
1144
|
cdr = inject(ChangeDetectorRef);
|
|
985
|
-
navigation = inject(NavigationService);
|
|
986
1145
|
/**
|
|
987
1146
|
* The whole tree, declared rather than fetched.
|
|
988
1147
|
*
|
|
@@ -1022,7 +1181,7 @@ let MJCContractLineagePanel = class MJCContractLineagePanel extends BaseFormPane
|
|
|
1022
1181
|
const key = e?.Node?.PrimaryKey;
|
|
1023
1182
|
if (!key)
|
|
1024
1183
|
return;
|
|
1025
|
-
this.
|
|
1184
|
+
this.FormComponent.OnFormNavigate({ Kind: 'record', EntityName: MJC_ENTITIES.Contract, PrimaryKey: key });
|
|
1026
1185
|
}
|
|
1027
1186
|
get ParentName() { return this.Record?.ParentContract ?? ''; }
|
|
1028
1187
|
get Count() {
|
|
@@ -1071,7 +1230,7 @@ let MJCContractLineagePanel = class MJCContractLineagePanel extends BaseFormPane
|
|
|
1071
1230
|
return ScopedRunView(this.FormComponent?.ProviderToUse);
|
|
1072
1231
|
}
|
|
1073
1232
|
static ɵfac = /*@__PURE__*/ (() => { let ɵMJCContractLineagePanel_BaseFactory; return function MJCContractLineagePanel_Factory(__ngFactoryType__) { return (ɵMJCContractLineagePanel_BaseFactory || (ɵMJCContractLineagePanel_BaseFactory = i0.ɵɵgetInheritedFactory(MJCContractLineagePanel)))(__ngFactoryType__ || MJCContractLineagePanel); }; })();
|
|
1074
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractLineagePanel, selectors: [["mjc-contract-lineage-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 9, consts: [["SectionKey", "
|
|
1233
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJCContractLineagePanel, selectors: [["mjc-contract-lineage-panel"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 5, vars: 9, consts: [["SectionKey", "lineage", "SectionName", "Lineage", "Icon", "fa-solid fa-sitemap", "Variant", "related-entity", 3, "BadgeCount", "Form", "FormContext"], [1, "mjc-body"], [3, "NodeDoubleClick", "Config", "ActiveRecordID"], [1, "mjc-empty"], [1, "mjc-note"]], template: function MJCContractLineagePanel_Template(rf, ctx) { if (rf & 1) {
|
|
1075
1234
|
i0.ɵɵelementStart(0, "mj-collapsible-panel", 0)(1, "div", 1);
|
|
1076
1235
|
i0.ɵɵconditionalCreate(2, MJCContractLineagePanel_Conditional_2_Template, 2, 1, "div", 1);
|
|
1077
1236
|
i0.ɵɵelementStart(3, "mj-hierarchy-tree", 2);
|
|
@@ -1089,7 +1248,7 @@ let MJCContractLineagePanel = class MJCContractLineagePanel extends BaseFormPane
|
|
|
1089
1248
|
i0.ɵɵproperty("Config", ctx.TreeConfig)("ActiveRecordID", (ctx.Record == null ? null : ctx.Record.ID) ?? undefined);
|
|
1090
1249
|
i0.ɵɵadvance();
|
|
1091
1250
|
i0.ɵɵconditional(!ctx.ParentName && !ctx.HasChildren ? 4 : -1);
|
|
1092
|
-
} }, dependencies: [CommonModule, FormsModule, BaseFormsModule,
|
|
1251
|
+
} }, dependencies: [CommonModule, FormsModule, BaseFormsModule, i1.MjCollapsiblePanelComponent, HierarchyTreeComponent], styles: ["\n /* A PINNED FLOOR, not a percentage. height:100% cannot work here: it resolves against\n .mj-forms-panel-content, which the variant sets to height:auto, and 100% of auto collapses\n straight back to auto - measured blank. AG Grid escapes this because the grid supplies its\n own intrinsic height; a plain div does not. A px min-height resolves regardless of what the\n parent computes to, and stays under the variant's own 800px cap. */\n /* DIRECT child only. As a descendant selector this also matched the nested .mjc-body wrapper\n inside the panel, so the floor applied twice and left a tall empty block above the tree. */\n mjc-contract-lineage-panel > .mjc-body {\n min-height: 440px;\n overflow-y: auto;\n }\n mjc-contract-lineage-panel mj-hierarchy-tree { display: block; min-height: 380px; }\n "], encapsulation: 2 });
|
|
1093
1252
|
};
|
|
1094
1253
|
MJCContractLineagePanel = __decorate([
|
|
1095
1254
|
RegisterClassEx(BaseFormPanel, {
|
|
@@ -1126,7 +1285,7 @@ export { MJCContractLineagePanel };
|
|
|
1126
1285
|
type: Component,
|
|
1127
1286
|
args: [{ selector: 'mjc-contract-lineage-panel', standalone: true, encapsulation: ViewEncapsulation.None, imports: [CommonModule, FormsModule, BaseFormsModule, HierarchyTreeComponent], template: `
|
|
1128
1287
|
<mj-collapsible-panel
|
|
1129
|
-
SectionKey="
|
|
1288
|
+
SectionKey="lineage"
|
|
1130
1289
|
SectionName="Lineage"
|
|
1131
1290
|
Icon="fa-solid fa-sitemap"
|
|
1132
1291
|
Variant="related-entity"
|
|
@@ -1163,5 +1322,5 @@ export { MJCContractLineagePanel };
|
|
|
1163
1322
|
</mj-collapsible-panel>
|
|
1164
1323
|
`, styles: ["\n /* A PINNED FLOOR, not a percentage. height:100% cannot work here: it resolves against\n .mj-forms-panel-content, which the variant sets to height:auto, and 100% of auto collapses\n straight back to auto - measured blank. AG Grid escapes this because the grid supplies its\n own intrinsic height; a plain div does not. A px min-height resolves regardless of what the\n parent computes to, and stays under the variant's own 800px cap. */\n /* DIRECT child only. As a descendant selector this also matched the nested .mjc-body wrapper\n inside the panel, so the floor applied twice and left a tall empty block above the tree. */\n mjc-contract-lineage-panel > .mjc-body {\n min-height: 440px;\n overflow-y: auto;\n }\n mjc-contract-lineage-panel mj-hierarchy-tree { display: block; min-height: 380px; }\n "] }]
|
|
1165
1324
|
}], null, null); })();
|
|
1166
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractLineagePanel, { className: "MJCContractLineagePanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber:
|
|
1325
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJCContractLineagePanel, { className: "MJCContractLineagePanel", filePath: "lib/form-panels/contract.panels.ts", lineNumber: 779 }); })();
|
|
1167
1326
|
//# sourceMappingURL=contract.panels.js.map
|