kamiz commited on
Commit
034a79a
·
1 Parent(s): 197e9f9

Publish browser-only pre-data-room triage worksheet

Browse files
Files changed (4) hide show
  1. README.md +14 -5
  2. app.js +174 -0
  3. index.html +121 -17
  4. styles.css +278 -0
README.md CHANGED
@@ -1,10 +1,19 @@
1
  ---
2
- title: Pre Data Room Triage Worksheet
3
- emoji: 📉
4
- colorFrom: gray
5
- colorTo: gray
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Pre-Data-Room Triage Worksheet
3
+ emoji: 🗂️
4
+ colorFrom: indigo
5
+ colorTo: green
6
  sdk: static
7
  pinned: false
8
+ license: cc-by-4.0
9
+ short_description: Document first-pass evidence before a full data room.
10
  ---
11
 
12
+ # Pre-Data-Room Triage Worksheet
13
+
14
+ A browser-only worksheet for corporate venture, corporate development,
15
+ innovation, and M&A teams. Review 12 connected evidence checkpoints, assign
16
+ owners, and export the agenda before deeper diligence begins.
17
+
18
+ Nothing entered in the worksheet is uploaded or stored by the Space. The
19
+ template and fictional example are licensed under CC BY 4.0.
app.js ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use strict";
2
+
3
+ const checkpoints = [
4
+ ["Business Idea", "Strategic or transaction fit"],
5
+ ["Offering", "Current offering and buyer outcome"],
6
+ ["Team", "Execution ownership and key-person dependency"],
7
+ ["Market", "Target segment and demand evidence"],
8
+ ["Competitors", "Alternatives and differentiation"],
9
+ ["Technology & IP", "Technical readiness and defensibility"],
10
+ ["Scalability", "Deployment and operating scalability"],
11
+ ["Legal & Regulatory", "Regulatory, data, and contractual exposure"],
12
+ ["Financials", "Revenue quality and cash assumptions"],
13
+ ["Fundability", "Capital structure and financing dependencies"],
14
+ ["Exit", "Transaction and integration path"],
15
+ ["Presentation", "Evidence package and open-item traceability"],
16
+ ];
17
+ const fields = [
18
+ "priority",
19
+ "dimension",
20
+ "checkpoint",
21
+ "evidence_state",
22
+ "evidence",
23
+ "owner",
24
+ "next_action",
25
+ "review_note",
26
+ ];
27
+ const rows = document.querySelector("#checkpoint-rows");
28
+ const statusMessage = document.querySelector("#status-message");
29
+
30
+ function select(name, options) {
31
+ const element = document.createElement("select");
32
+ element.dataset.field = name;
33
+ element.setAttribute("aria-label", name.replaceAll("_", " "));
34
+ for (const optionText of options) {
35
+ const option = document.createElement("option");
36
+ option.textContent = optionText;
37
+ element.append(option);
38
+ }
39
+ return element;
40
+ }
41
+
42
+ function textControl(name, multiline = false) {
43
+ const element = document.createElement(multiline ? "textarea" : "input");
44
+ element.dataset.field = name;
45
+ element.setAttribute("aria-label", name.replaceAll("_", " "));
46
+ return element;
47
+ }
48
+
49
+ function buildRows() {
50
+ rows.replaceChildren();
51
+ checkpoints.forEach(([dimension, checkpoint], index) => {
52
+ const row = document.createElement("tr");
53
+ const values = [
54
+ select("priority", ["", "1", "2", "3", "4", "5"]),
55
+ Object.assign(document.createElement("span"), {
56
+ textContent: dimension,
57
+ }),
58
+ Object.assign(document.createElement("span"), {
59
+ textContent: checkpoint,
60
+ }),
61
+ select("evidence_state", [
62
+ "Not reviewed",
63
+ "Claim only",
64
+ "Partial",
65
+ "Supported",
66
+ "Conflicted",
67
+ ]),
68
+ textControl("evidence", true),
69
+ textControl("owner"),
70
+ textControl("next_action", true),
71
+ textControl("review_note", true),
72
+ ];
73
+ values[1].dataset.field = "dimension";
74
+ values[2].dataset.field = "checkpoint";
75
+ values.forEach((value) => {
76
+ const cell = document.createElement("td");
77
+ cell.append(value);
78
+ row.append(cell);
79
+ });
80
+ row.dataset.row = String(index + 1);
81
+ rows.append(row);
82
+ });
83
+ }
84
+
85
+ function controlValue(row, field) {
86
+ const element = row.querySelector(`[data-field="${field}"]`);
87
+ return ("value" in element ? element.value : element.textContent).trim();
88
+ }
89
+
90
+ function rowValues(row) {
91
+ return Object.fromEntries(fields.map((field) => [field, controlValue(row, field)]));
92
+ }
93
+
94
+ function csvCell(value) {
95
+ return `"${String(value).replaceAll('"', '""')}"`;
96
+ }
97
+
98
+ function exportCsv() {
99
+ const context = {
100
+ opportunity_type: document.querySelector("#opportunity-type").value,
101
+ review_stage: document.querySelector("#review-stage").value,
102
+ review_owner: document.querySelector("#review-owner").value.trim(),
103
+ };
104
+ const exportFields = [...Object.keys(context), ...fields];
105
+ const data = [...rows.querySelectorAll("tr")].map((row) => ({
106
+ ...context,
107
+ ...rowValues(row),
108
+ }));
109
+ const csv = [
110
+ exportFields.map(csvCell).join(","),
111
+ ...data.map((row) => exportFields.map((field) => csvCell(row[field])).join(",")),
112
+ ].join("\r\n");
113
+ const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
114
+ const url = URL.createObjectURL(blob);
115
+ const link = document.createElement("a");
116
+ link.href = url;
117
+ link.download = "pre-data-room-triage-workbook.csv";
118
+ link.click();
119
+ URL.revokeObjectURL(url);
120
+ statusMessage.textContent = "Downloaded all 12 checkpoints as CSV.";
121
+ }
122
+
123
+ function setRow(rowNumber, values) {
124
+ const row = rows.querySelector(`[data-row="${rowNumber}"]`);
125
+ Object.entries(values).forEach(([field, value]) => {
126
+ row.querySelector(`[data-field="${field}"]`).value = value;
127
+ });
128
+ }
129
+
130
+ function clearWorksheet() {
131
+ document.querySelector("#opportunity-type").value = "Corporate venture investment";
132
+ document.querySelector("#review-stage").value = "Inbound triage";
133
+ document.querySelector("#review-owner").value = "";
134
+ buildRows();
135
+ statusMessage.textContent = "Worksheet cleared.";
136
+ }
137
+
138
+ function loadExample() {
139
+ clearWorksheet();
140
+ document.querySelector("#opportunity-type").value = "Commercial partnership";
141
+ document.querySelector("#review-stage").value = "Before first management call";
142
+ document.querySelector("#review-owner").value = "Fictional CVC team";
143
+ setRow(4, {
144
+ priority: "1",
145
+ evidence_state: "Partial",
146
+ evidence: "Three pilot letters; no paid conversion history",
147
+ owner: "Commercial lead",
148
+ next_action: "Ask for cohort, conversion, and signed-pipeline evidence",
149
+ review_note: "Separate buyer interest from repeatable demand.",
150
+ });
151
+ setRow(6, {
152
+ priority: "2",
153
+ evidence_state: "Claim only",
154
+ evidence: "Architecture claim in deck; no integration test supplied",
155
+ owner: "Technical reviewer",
156
+ next_action: "Request data-flow map and one reproducible integration test",
157
+ review_note: "Fictional example only.",
158
+ });
159
+ setRow(8, {
160
+ priority: "3",
161
+ evidence_state: "Not reviewed",
162
+ evidence: "",
163
+ owner: "Legal reviewer",
164
+ next_action: "Confirm the lawful data basis and required customer terms",
165
+ review_note: "Scope only after the intended deployment is clear.",
166
+ });
167
+ statusMessage.textContent = "Loaded a completely fictional three-item example.";
168
+ }
169
+
170
+ document.querySelector("#load-example").addEventListener("click", loadExample);
171
+ document.querySelector("#clear").addEventListener("click", clearWorksheet);
172
+ document.querySelector("#export-csv").addEventListener("click", exportCsv);
173
+
174
+ buildRows();
index.html CHANGED
@@ -1,19 +1,123 @@
1
  <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
  <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta
7
+ name="description"
8
+ content="A browser-only pre-data-room triage worksheet for corporate venture and M&A teams."
9
+ />
10
+ <title>Pre-Data-Room Triage Worksheet</title>
11
+ <link rel="stylesheet" href="styles.css" />
12
+ </head>
13
+ <body>
14
+ <main>
15
+ <header class="intro">
16
+ <p class="eyebrow">Corporate venture and M&amp;A first pass</p>
17
+ <h1>Pre-Data-Room Triage Worksheet</h1>
18
+ <p class="lede">
19
+ Turn an inbound opportunity into a documented evidence agenda before
20
+ committing to a full data-room process. Everything stays in this
21
+ browser; export the worksheet before closing the page.
22
+ </p>
23
+ <div class="guardrails" aria-label="Worksheet guardrails">
24
+ <span>No uploads</span><span>No account</span><span>No scoring</span
25
+ ><span>No decision automation</span>
26
+ </div>
27
+ </header>
28
+
29
+ <section class="controls" aria-labelledby="controls-title">
30
+ <div>
31
+ <p class="eyebrow">Review context</p>
32
+ <h2 id="controls-title">Set the first-pass frame</h2>
33
+ </div>
34
+ <label>
35
+ Opportunity type
36
+ <select id="opportunity-type">
37
+ <option>Corporate venture investment</option>
38
+ <option>Commercial partnership</option>
39
+ <option>Minority investment</option>
40
+ <option>Acquisition screen</option>
41
+ </select>
42
+ </label>
43
+ <label>
44
+ Review stage
45
+ <select id="review-stage">
46
+ <option>Inbound triage</option>
47
+ <option>Before first management call</option>
48
+ <option>Before data-room request</option>
49
+ <option>Handoff to specialist diligence</option>
50
+ </select>
51
+ </label>
52
+ <label>
53
+ Internal sponsor or owner
54
+ <input id="review-owner" placeholder="Optional; stored only in this tab" />
55
+ </label>
56
+ </section>
57
+
58
+ <section class="workspace" aria-labelledby="workspace-title">
59
+ <div class="workspace-heading">
60
+ <div>
61
+ <p class="eyebrow">12 connected checkpoints</p>
62
+ <h2 id="workspace-title">Evidence agenda</h2>
63
+ </div>
64
+ <div class="actions">
65
+ <button id="load-example" type="button" class="secondary">
66
+ Load fictional example
67
+ </button>
68
+ <button id="clear" type="button">Clear</button>
69
+ <button id="export-csv" type="button" class="primary">
70
+ Download CSV
71
+ </button>
72
+ </div>
73
+ </div>
74
+
75
+ <div class="table-wrap">
76
+ <table>
77
+ <thead>
78
+ <tr>
79
+ <th>Priority</th>
80
+ <th>Dimension</th>
81
+ <th>Checkpoint</th>
82
+ <th>Evidence state</th>
83
+ <th>Evidence reviewed or needed</th>
84
+ <th>Owner</th>
85
+ <th>Next question or action</th>
86
+ <th>Review note</th>
87
+ </tr>
88
+ </thead>
89
+ <tbody id="checkpoint-rows"></tbody>
90
+ </table>
91
+ </div>
92
+ <p id="status-message" class="status" role="status" aria-live="polite"></p>
93
+ </section>
94
+
95
+ <section class="method" aria-labelledby="method-title">
96
+ <h2 id="method-title">Use the worksheet as a handoff, not a verdict</h2>
97
+ <p>
98
+ Select no more than five decision-changing items for the next call or
99
+ evidence request. “Supported” means the source behind a claim is
100
+ identifiable; it does not mean the claim is favourable. “Conflicted”
101
+ means the next step should resolve a discrepancy, not that the company
102
+ has failed diligence.
103
+ </p>
104
+ </section>
105
+
106
+ <footer>
107
+ <p>
108
+ This open worksheet is maintained by
109
+ <a
110
+ href="https://www.ddscore.ai/for-investor/?utm_source=hugging-face-space&amp;utm_medium=referral&amp;utm_campaign=ddscore-30d-jul-2026&amp;utm_content=pre-data-room-triage-planner-a"
111
+ rel="noopener noreferrer"
112
+ >DDScore.ai</a
113
+ >, a Finnish product that structures private-company materials into a
114
+ 0–100 Due Diligence Score and written report across 12 dimensions.
115
+ DDScore supports judgement and full due diligence rather than
116
+ replacing either.
117
+ </p>
118
+ <p>Template and fictional example: CC BY 4.0.</p>
119
+ </footer>
120
+ </main>
121
+ <script src="app.js"></script>
122
+ </body>
123
  </html>
styles.css ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ color-scheme: light;
3
+ font-family:
4
+ Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
5
+ sans-serif;
6
+ color: #17211d;
7
+ background: #f4f7f5;
8
+ }
9
+
10
+ * {
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ margin: 0;
16
+ }
17
+
18
+ main {
19
+ width: min(1500px, calc(100% - 32px));
20
+ margin: 0 auto;
21
+ padding: 48px 0 32px;
22
+ }
23
+
24
+ h1,
25
+ h2,
26
+ p {
27
+ margin-top: 0;
28
+ }
29
+
30
+ h1 {
31
+ max-width: 980px;
32
+ margin-bottom: 18px;
33
+ font-size: clamp(2.5rem, 6vw, 5.8rem);
34
+ line-height: 0.98;
35
+ letter-spacing: -0.055em;
36
+ }
37
+
38
+ h2 {
39
+ margin-bottom: 12px;
40
+ font-size: 1.45rem;
41
+ }
42
+
43
+ .intro,
44
+ .controls,
45
+ .workspace,
46
+ .method,
47
+ footer {
48
+ border: 1px solid #d4ded8;
49
+ background: #fff;
50
+ box-shadow: 0 12px 30px rgb(24 45 35 / 6%);
51
+ }
52
+
53
+ .intro {
54
+ padding: clamp(28px, 5vw, 72px);
55
+ border-radius: 24px 24px 0 0;
56
+ background:
57
+ radial-gradient(circle at 92% 4%, rgb(68 115 255 / 20%), transparent 34%),
58
+ radial-gradient(circle at 72% 100%, rgb(28 154 100 / 13%), transparent 38%),
59
+ #fff;
60
+ }
61
+
62
+ .eyebrow {
63
+ margin-bottom: 9px;
64
+ color: #245f49;
65
+ font-size: 0.76rem;
66
+ font-weight: 800;
67
+ letter-spacing: 0.12em;
68
+ text-transform: uppercase;
69
+ }
70
+
71
+ .lede {
72
+ max-width: 900px;
73
+ color: #4d5f56;
74
+ font-size: clamp(1.05rem, 2vw, 1.28rem);
75
+ line-height: 1.65;
76
+ }
77
+
78
+ .guardrails {
79
+ display: flex;
80
+ flex-wrap: wrap;
81
+ gap: 8px;
82
+ margin-top: 24px;
83
+ }
84
+
85
+ .guardrails span {
86
+ border: 1px solid #bfd3c8;
87
+ border-radius: 999px;
88
+ padding: 7px 11px;
89
+ color: #245f49;
90
+ background: #eff8f3;
91
+ font-size: 0.83rem;
92
+ font-weight: 750;
93
+ }
94
+
95
+ .controls {
96
+ display: grid;
97
+ grid-template-columns: 1.2fr repeat(3, minmax(180px, 1fr));
98
+ gap: 22px;
99
+ align-items: end;
100
+ padding: 28px clamp(24px, 4vw, 52px);
101
+ }
102
+
103
+ label {
104
+ display: grid;
105
+ gap: 8px;
106
+ color: #3f5048;
107
+ font-size: 0.78rem;
108
+ font-weight: 800;
109
+ letter-spacing: 0.03em;
110
+ text-transform: uppercase;
111
+ }
112
+
113
+ .workspace {
114
+ padding: 28px 0 16px;
115
+ overflow: hidden;
116
+ }
117
+
118
+ .workspace-heading {
119
+ display: flex;
120
+ align-items: end;
121
+ justify-content: space-between;
122
+ gap: 24px;
123
+ padding: 0 28px 20px;
124
+ }
125
+
126
+ .workspace-heading h2 {
127
+ margin-bottom: 0;
128
+ }
129
+
130
+ .actions {
131
+ display: flex;
132
+ flex-wrap: wrap;
133
+ gap: 10px;
134
+ }
135
+
136
+ button {
137
+ border: 1px solid #b8c8bf;
138
+ border-radius: 9px;
139
+ padding: 10px 14px;
140
+ color: #17211d;
141
+ background: #fff;
142
+ font: inherit;
143
+ font-weight: 750;
144
+ cursor: pointer;
145
+ }
146
+
147
+ button:hover,
148
+ button:focus-visible {
149
+ border-color: #245f49;
150
+ outline: 3px solid rgb(36 95 73 / 16%);
151
+ }
152
+
153
+ button.primary {
154
+ border-color: #245f49;
155
+ color: #fff;
156
+ background: #245f49;
157
+ }
158
+
159
+ button.secondary {
160
+ color: #2b438f;
161
+ background: #eef2ff;
162
+ }
163
+
164
+ .table-wrap {
165
+ overflow-x: auto;
166
+ border-top: 1px solid #d4ded8;
167
+ border-bottom: 1px solid #d4ded8;
168
+ }
169
+
170
+ table {
171
+ width: 100%;
172
+ min-width: 1420px;
173
+ border-collapse: collapse;
174
+ }
175
+
176
+ th,
177
+ td {
178
+ border-right: 1px solid #d4ded8;
179
+ border-bottom: 1px solid #e6ece8;
180
+ padding: 10px;
181
+ text-align: left;
182
+ vertical-align: top;
183
+ }
184
+
185
+ th {
186
+ color: #405047;
187
+ background: #f0f4f1;
188
+ font-size: 0.72rem;
189
+ letter-spacing: 0.04em;
190
+ text-transform: uppercase;
191
+ }
192
+
193
+ td:nth-child(1) {
194
+ width: 78px;
195
+ }
196
+
197
+ td:nth-child(2) {
198
+ width: 140px;
199
+ color: #245f49;
200
+ font-weight: 800;
201
+ }
202
+
203
+ td:nth-child(3) {
204
+ width: 210px;
205
+ font-weight: 700;
206
+ }
207
+
208
+ input,
209
+ textarea,
210
+ select {
211
+ width: 100%;
212
+ border: 1px solid #c9d4ce;
213
+ border-radius: 7px;
214
+ padding: 9px;
215
+ color: #17211d;
216
+ background: #fff;
217
+ font: inherit;
218
+ }
219
+
220
+ textarea {
221
+ min-height: 86px;
222
+ resize: vertical;
223
+ }
224
+
225
+ input:focus,
226
+ textarea:focus,
227
+ select:focus {
228
+ border-color: #245f49;
229
+ outline: 3px solid rgb(36 95 73 / 14%);
230
+ }
231
+
232
+ .status {
233
+ min-height: 24px;
234
+ margin: 12px 28px 0;
235
+ color: #245f49;
236
+ font-weight: 750;
237
+ }
238
+
239
+ .method,
240
+ footer {
241
+ padding: 28px clamp(24px, 4vw, 52px);
242
+ }
243
+
244
+ .method p,
245
+ footer p {
246
+ max-width: 980px;
247
+ color: #4d5f56;
248
+ line-height: 1.65;
249
+ }
250
+
251
+ footer {
252
+ border-radius: 0 0 24px 24px;
253
+ }
254
+
255
+ footer p:last-child {
256
+ margin-bottom: 0;
257
+ }
258
+
259
+ a {
260
+ color: #2b438f;
261
+ font-weight: 750;
262
+ }
263
+
264
+ @media (max-width: 980px) {
265
+ main {
266
+ width: min(100% - 18px, 1500px);
267
+ padding-top: 10px;
268
+ }
269
+
270
+ .controls {
271
+ grid-template-columns: 1fr;
272
+ }
273
+
274
+ .workspace-heading {
275
+ align-items: flex-start;
276
+ flex-direction: column;
277
+ }
278
+ }