@gotcos/glasses-server 6.99.20 → 6.99.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/docs/work-orchestrator.md +20 -0
  3. package/package.json +1 -1
  4. package/server/index.ts +2 -1
  5. package/server/lib/web-control-static.ts +226 -0
  6. package/server/lib/web-memories-bridge.ts +9 -8
  7. package/server/lib/web-pet-choice.ts +225 -0
  8. package/server/lib/web-pet.ts +226 -0
  9. package/server/lib/work-lens-rounds.ts +29 -4
  10. package/server/routes/web-control.ts +110 -7
  11. package/server/routes/work-lens-rounds.ts +19 -5
  12. package/server/web-control/app.css +24 -5
  13. package/server/web-control/app.js +646 -108
  14. package/server/web-control/control.css +1 -1
  15. package/server/web-control/index.html +27 -13
  16. package/server/web-control/memories/memory-workspace.js +1 -1
  17. package/server/web-control/panes/cos-chat.css +4 -0
  18. package/server/web-control/panes/cos-chat.js +26 -4
  19. package/server/web-control/panes/meetings.css +15 -2
  20. package/server/web-control/panes/memories.css +291 -0
  21. package/server/web-control/panes/memories.js +2208 -0
  22. package/server/web-control/panes/questions.js +59 -21
  23. package/server/web-control/panes/settings.js +102 -4
  24. package/server/web-control/panes/today-actions.css +109 -0
  25. package/server/web-control/panes/today-actions.js +972 -0
  26. package/server/web-control/panes/work.css +54 -0
  27. package/server/web-control/panes/work.js +1037 -18
  28. package/server/web-control/shell.js +6 -2
  29. package/server/web-control/theme.js +0 -2
  30. package/server/web-control/memories/memories-app.js +0 -1561
  31. package/server/web-control/memories/memories-theme.css +0 -73
  32. package/server/web-control/memories/memories.html +0 -72
  33. package/server/web-control/memories/memory-stewardship.js +0 -63
@@ -309,7 +309,7 @@ button.cx-set-row:hover { background: var(--qopen); }
309
309
  @media (min-width: 1100px) { .cx-set-name { font-size: 14px; } }
310
310
  @media (min-width: 1100px) { .rail-settings[aria-current='page'] { background: var(--rail-active); border: 1px solid var(--panel-border); } }
311
311
 
312
- /* Sign in another device: the QR the phone camera scans. */
312
+ /* Use COS on another phone or browser: the QR the phone camera scans. */
313
313
  .device-code .qr { display: block; width: 200px; height: 200px; margin: 4px 0 8px; border-radius: 8px; border: 1px solid var(--panel-border); background: #fff; }
314
314
  .device-code .qr-hint { font-weight: 600; color: var(--ink); }
315
315
 
@@ -19,6 +19,8 @@
19
19
  <link rel="stylesheet" href="/control/panes/sessions.css">
20
20
  <link rel="stylesheet" href="/control/panes/cos-chat.css">
21
21
  <link rel="stylesheet" href="/control/panes/questions.css">
22
+ <link rel="stylesheet" href="/control/panes/memories.css">
23
+ <link rel="stylesheet" href="/control/panes/today-actions.css">
22
24
  <script src="/control/theme.js"></script>
23
25
  </head>
24
26
  <body>
@@ -57,7 +59,7 @@
57
59
  <div id="auth-code-block">
58
60
  <label for="auth-code">Sign-in code</label>
59
61
  <input id="auth-code" class="field code-field" type="text" inputmode="text" autocomplete="one-time-code" autocapitalize="characters" spellcheck="false" maxlength="9" placeholder="K7P3-QX9M">
60
- <p class="auth-foot" style="margin-top:8px">Scan the QR with your phone's camera. A browser that is already signed in shows one under Settings, Sign in another device. COS Control on your Mac shows one under Open COS on your phone. Or type the code shown with the QR.</p>
62
+ <p class="auth-foot" style="margin-top:8px">Scan the QR with your phone's camera. A browser that is already signed in shows one under Settings, Use COS on another phone or browser. COS Control on your Mac shows one under Open COS on your phone. Or type the code shown with the QR.</p>
61
63
  <p class="auth-foot">The glasses pairing code does not work here.</p>
62
64
  </div>
63
65
  <div id="auth-token-block" class="hidden">
@@ -126,6 +128,7 @@
126
128
  <kbd class="kbd">⌘K</kbd>
127
129
  </button>
128
130
  </div>
131
+ <div id="today-pet" class="today-pet hidden"></div>
129
132
  <div id="today-rec"></div>
130
133
  <div class="today-cols">
131
134
  <div class="today-main">
@@ -148,13 +151,14 @@
148
151
  <section class="card hidden" id="intake-card" aria-labelledby="intake-title">
149
152
  <div class="panel-head">
150
153
  <h2 id="intake-title" class="panel-title">From today's meetings<span id="intake-count" class="count"></span></h2>
151
- <button type="button" class="link-btn" data-goto="work/sort">Review</button>
154
+ <button type="button" class="link-btn" data-today="intake" data-goto="work/sort">Review</button>
152
155
  </div>
153
156
  <div id="intake-body" class="intake-body"></div>
154
157
  </section>
155
158
  <section class="card hidden" id="next-card" aria-labelledby="next-title">
156
- <div class="panel-head"><h2 id="next-title" class="panel-title">Up next</h2></div>
159
+ <div class="panel-head"><h2 id="next-title" class="panel-title">Next up</h2></div>
157
160
  <div id="next-body" class="next-up"></div>
161
+ <div id="next-actions" class="next-actions"></div>
158
162
  </section>
159
163
  </div>
160
164
  </div>
@@ -207,9 +211,7 @@
207
211
  <section id="pane-dictation" class="pane hidden" data-title="Dictation"></section>
208
212
 
209
213
  <!-- MEMORIES -->
210
- <section id="pane-memories" class="pane flush hidden" data-title="Memories">
211
- <iframe id="memories-frame" class="memories-frame" title="Memories" src="about:blank"></iframe>
212
- </section>
214
+ <section id="pane-memories" class="pane hidden" data-title="Memories"><!-- rendered by panes/memories.js --></section>
213
215
 
214
216
  <!-- SPEAKERS -->
215
217
  <section id="pane-speakers" class="pane wide hidden" data-title="Speakers"><!-- rendered by panes/speakers.js --></section>
@@ -263,13 +265,25 @@
263
265
  <script src="/control/app.js"></script>
264
266
  <script src="/control/shell.js"></script>
265
267
  <script src="/control/panes/cos-chat.js"></script>
266
- <script src="/control/panes/messages.js"></script>
267
- <script src="/control/panes/threads.js"></script>
268
- <script src="/control/panes/speakers.js"></script>
269
- <script src="/control/panes/meetings.js"></script>
270
- <script src="/control/panes/work.js"></script>
271
- <script src="/control/panes/dictation.js"></script>
272
- <script src="/control/panes/settings.js"></script>
273
268
  <script src="/control/panes/questions.js"></script>
269
+ <!-- Loaded when first opened, then in the background once the page is idle (app.js ensurePane). -->
270
+ <script type="application/json" id="lazy-panes">{
271
+ "messages": "/control/panes/messages.js",
272
+ "threads": "/control/panes/threads.js",
273
+ "speakers": "/control/panes/speakers.js",
274
+ "meetings": "/control/panes/meetings.js",
275
+ "work": "/control/panes/work.js",
276
+ "dictation": "/control/panes/dictation.js",
277
+ "settings": "/control/panes/settings.js",
278
+ "memories": "/control/panes/memories.js",
279
+ "todayActions": "/control/panes/today-actions.js"
280
+ }</script>
281
+ <!-- The Knowledge graph explorer, loaded by panes/memories.js when the graph first opens. -->
282
+ <script type="application/json" id="memories-graph-assets">{
283
+ "css": "/control/memories/graph-explorer.css",
284
+ "d3": "/control/memories/d3.min.js",
285
+ "explorer": "/control/memories/graph-explorer.js",
286
+ "workspace": "/control/memories/memory-workspace.js"
287
+ }</script>
274
288
  </body>
275
289
  </html>
@@ -17,7 +17,7 @@
17
17
  var el=document.createElement('section');el.className='memory-investigation';
18
18
  var state={id:id(),revision:0,title:'Untitled investigation',nodes:[],links:[],anchors:[],waypoints:[],filters:{hops:3,direction:'undirected',avoid:[]},generation:null,paths:[]};
19
19
  var queuedFocus=null,editEpoch=0,lastFocus=null,selected=null,offsets={},history=[],controller=null,started=false,busy=false,requestSerial=0,saveIntents={},assertionIntent=null,separationIntent=null;
20
- el.innerHTML='<div data-role="canvas" class="cgx-host"></div><p data-role="overview-status" class="muted" role="status"></p><details class="investigation-tools" data-role="advanced"><summary>Advanced investigation</summary><div class="graph-search row"><input type="search" id="graphQuery" aria-label="Find an entity" placeholder="Find a person or idea…"><button onclick="cosApp.graphSearch()">Find points</button><span id="graphSearchStatus" class="muted"></span></div><div class="source-card"><div class="row"><input data-role="title" aria-label="Investigation title" placeholder="Investigation title"><button data-action="save">Save investigation</button><button data-action="open">Open saved</button><button data-action="new">New</button></div>'+
20
+ el.innerHTML='<div data-role="canvas" class="cgx-host"></div><p data-role="overview-status" class="muted" role="status"></p><details class="investigation-tools" data-role="advanced"><summary>Advanced investigation</summary><div class="graph-search row"><input type="search" id="graphQuery" aria-label="Find an entity" placeholder="Find a person or idea…"><button type="button" data-role="find-points">Find points</button><span id="graphSearchStatus" class="muted"></span></div><div class="source-card"><div class="row"><input data-role="title" aria-label="Investigation title" placeholder="Investigation title"><button data-action="save">Save investigation</button><button data-action="open">Open saved</button><button data-action="new">New</button></div>'+
21
21
  '<p data-role="receipt" class="muted">Draft · saved separately from standing knowledge.</p><div data-role="matches" class="row"></div>'+
22
22
  '<div class="row"><b data-role="selected">Select a point</b><button data-action="start">Set start</button><button data-action="target">Set target</button><button data-action="waypoint">Add waypoint</button><button data-action="expand">Expand point</button><button data-action="avoid">Avoid point</button><button data-action="hide">Hide point</button><button data-action="undo">Undo canvas edit</button></div>'+
23
23
  '<p data-role="anchors"></p><div data-role="waypoints" class="row"></div><div class="row"><label>Total hops <select data-role="hops" aria-label="Total hop limit"><option>3</option><option>4</option><option>5</option><option>6</option><option>7</option></select></label><label>Traversal <select data-role="direction" aria-label="Relationship direction"><option value="undirected">Undirected discovery</option><option value="directed">Known direction only</option></select></label><label>Known valid on <input data-role="valid" aria-label="Known valid on" type="date"></label><button data-action="paths">Find connections</button><button data-action="refresh">Review generation changes</button><button data-action="separate">Keep anchors separate</button></div>'+
@@ -189,6 +189,10 @@
189
189
  .cc-prep-add { position: relative; cursor: pointer; }
190
190
  .cc-prep-add:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
191
191
  .cc-prep-acts .cx-btn { height: 40px; }
192
+ @media (max-width: 480px) {
193
+ .cc-prep-acts .cx-btn { height: 44px; min-width: 44px; }
194
+ .cc-prep-head-acts button { min-height: 44px; }
195
+ }
192
196
  .cc-prep-note { margin: 0; font-size: 13px; }
193
197
  .cc-prep-note[hidden] { display: none; }
194
198
  .cc-prep.dragging .cc-prep-panel { outline: 2px dashed var(--accent); outline-offset: 4px; }
@@ -874,11 +874,11 @@
874
874
  throw err;
875
875
  });
876
876
  };
877
- var prepare = a.threaded ? threadPlan().then(function (plan) {
877
+ var prepare = (a.threaded ? threadPlan().then(function (plan) {
878
878
  if (plan.sessionId) body.sessionId = plan.sessionId;
879
879
  else if (plan.digest) body.reference = { query: THREAD_REF, response: plan.digest };
880
880
  a.carried = plan.sessionId ? '' : plan.digest ? 'summary' : 'plain';
881
- }) : Promise.resolve();
881
+ }) : Promise.resolve()).then(function () { withContext(body, opts.context); });
882
882
  prepare.then(function () { return admit(true); }).then(function (d) {
883
883
  var job = d && d.job; if (!job) throw new Error('The Mac did not take the question.');
884
884
  take(a, job);
@@ -897,6 +897,15 @@
897
897
  });
898
898
  return a;
899
899
  }
900
+ // An Ask from Today carries what Today shows (app.js askCos, panes/today-actions.js summary) as the quoted reference,
901
+ // after a carried thread summary when there is one. Bounded, and only on the Ask it was given to.
902
+ var TODAY_REF = 'What Today in COS Control shows right now', CONTEXT_MAX = 6000;
903
+ function withContext(body, context) {
904
+ var text = typeof context === 'string' ? context.trim().slice(0, CONTEXT_MAX) : '';
905
+ if (!text) return;
906
+ if (body.reference) body.reference = { query: body.reference.query + ', then ' + TODAY_REF.charAt(0).toLowerCase() + TODAY_REF.slice(1), response: body.reference.response + '\n\n' + text };
907
+ else body.reference = { query: TODAY_REF, response: text };
908
+ }
900
909
  function take(a, job) {
901
910
  a.jobId = job.jobId; a.status = job.status || a.status;
902
911
  if (job.globalMsgNum) a.no = job.globalMsgNum;
@@ -932,11 +941,12 @@
932
941
  api('/api/inbox/feed?limit=100').then(function (d) { C.items = (d && d.items) || []; paintFeed(false); markReadIfShown(); }, function () {});
933
942
  }
934
943
  // The Ask sheet (app.js askCos) hands its words here, so the answer streams in the chat instead of vanishing.
935
- function askFromSheet(text) {
944
+ function askFromSheet(text, extra) {
936
945
  return ensureCaps().then(function (caps) {
937
946
  if (!caps || !caps.jobs) { var off = new Error('Ask needs the durable query jobs switch on your Mac.'); off.code = 'durable_query_jobs_disabled'; throw off; }
938
947
  return new Promise(function (resolve, reject) {
939
- submitAsk(String(text || '').trim(), null, function (ok) { if (ok) resolve(['cos']); else reject(new Error('Not sent. The question is in Ask COS; try again there.')); });
948
+ submitAsk(String(text || '').trim(), null, function (ok) { if (ok) resolve(['cos']); else reject(new Error('Not sent. The question is in Ask COS; try again there.')); },
949
+ extra && extra.context ? { context: extra.context } : undefined);
940
950
  });
941
951
  });
942
952
  }
@@ -1722,6 +1732,18 @@
1722
1732
  classify: classify, uploadMedia: uploadMedia, uploadErrorText: uploadErrorText, uuid: uuid,
1723
1733
  // 6.99.19: Prep. meetings.js reads the capability from here (one /api/health read for the page).
1724
1734
  prepCaps: prepCaps,
1735
+ // Today's Next up (app.js prepNext): Prep me for that meeting, as the chat's own Prep me does. With Prep on the Mac
1736
+ // the Prep composer opens (it paints when the chat mounts; the same meeting reopens the same draft); without it,
1737
+ // the plain Ask. Resolves to 'prep', 'ask' or '' (neither is on).
1738
+ prepFor: function (title, startsAt) {
1739
+ return ensureCaps().then(function () {
1740
+ var t = String(title || '').trim() || 'my next meeting';
1741
+ var item = { id: 'today-next:' + (startsAt || '') + ':' + t, title: t, prep: { title: t, startsAt: startsAt || null } };
1742
+ if (prepOn()) { openPrep(item); return 'prep'; }
1743
+ if (C.caps && C.caps.jobs) { submitAsk('Prep me for ' + t, ''); return 'ask'; }
1744
+ return '';
1745
+ });
1746
+ },
1725
1747
  // The Prep server id to name on a write: the newest from capabilities.prep or any Prep answer (meetings.js reports its own).
1726
1748
  prepInstance: function () { return PREP_INST; }, notePrepInstance: function (id) { if (typeof id === 'string' && id) PREP_INST = id; },
1727
1749
  _prep: function () { return P; }, _openPrep: openPrep, _prepHtml: function () { return P ? prepPanelHtml(P) : ''; }, _addPrepFiles: addPrepFiles,
@@ -264,7 +264,7 @@
264
264
  .mt-lempty { color: var(--sub); text-align: center; font-size: 14px; padding: 26px 8px; margin: 0; }
265
265
  .mt-jump { position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%); box-shadow: var(--shadow); background: var(--panel); }
266
266
  .mt-jump[hidden] { display: none; }
267
- /* The recording bar (Control's LiveRecordingBar): one row, 50 px, never wraps. Under 560 px of bar Add file is the
267
+ /* The recording bar (Control's LiveRecordingBar): one row, 50 px (56 on phones), never wraps. Under 560 px of bar Add file is the
268
268
  paperclip alone; under 340 px the still glyph takes the strip's place. */
269
269
  .mt-lbarslot { container-type: inline-size; min-height: 50px; margin-top: 8px; }
270
270
  .mt-lbar { display: flex; align-items: center; gap: 10px; height: 50px; padding: 0 8px 0 14px; border: 1px solid var(--panel-border);
@@ -287,7 +287,13 @@
287
287
  .mt-addfile .icon { width: 14px; height: 14px; }
288
288
  .mt-lbar .mt-side-note { flex: none; }
289
289
  @container (max-width: 559px) { .mt-addlabel { display: none; } .mt-addfile { padding-left: 10px; padding-right: 10px; } }
290
- @container (max-width: 339px) { .mt-meter { visibility: hidden; } .mt-glyph { visibility: visible; } .mt-meterwrap { flex: 0 0 40px; } }
290
+ @container (max-width: 339px) {
291
+ .mt-lbar { gap: 4px; padding-left: 8px; }
292
+ .mt-meter { visibility: hidden; }
293
+ .mt-glyph { visibility: visible; }
294
+ .mt-meterwrap { flex: 0 0 10px; min-width: 10px; }
295
+ .mt-lbar .mt-side-note { flex: 1; min-width: 0; }
296
+ }
291
297
  .mt-lbarslot > .mt-stopline { margin: 8px 4px 0; }
292
298
  .mt-lbarslot > .mt-confirm { margin-top: 8px; }
293
299
  /* A file dragged over the pane: the column is outlined. Drawn only, so it moves nothing. */
@@ -327,6 +333,13 @@
327
333
  .mt-preplist li:last-child { border-bottom: 0; }
328
334
  .mt-preplist .mt-prepline-text { -webkit-line-clamp: 2; color: var(--ink); line-height: 1.3; }
329
335
  .mt-preplist .cx-btn { flex: none; white-space: nowrap; height: 34px; }
336
+ @media (max-width: 480px) {
337
+ .mt-lbar { height: 56px; }
338
+ .mt-lbar .cx-btn { min-height: 44px; min-width: 44px; }
339
+ .mt-prepslot { height: 112px; }
340
+ .mt-prepline .cx-btn { height: 44px; }
341
+ .mt-preplist li { padding-block: 4px; }
342
+ }
330
343
  /* The saved meeting's Prep: what it focused on and its files. */
331
344
  #mt-dprep:empty { display: none; }
332
345
  .mt-prep { margin: 12px 0; display: grid; gap: 10px; }
@@ -0,0 +1,291 @@
1
+ /* COS Control Web: Memories pane styles, on top of control.css. Control's Memories page in the app's own tokens: a
2
+ list of learning beside a reader from 760px (the split in app.css), a pushed reader below it, a text switch with a
3
+ gold rule for the views, and the timeline Control draws down the left of a lesson. Nothing here is fixed to the
4
+ bottom of the screen, and nothing is wider than the screen. */
5
+
6
+ #pane-memories { max-width: 1240px; }
7
+ .mm { min-width: 0; }
8
+ .mm-controls { margin: 12px 0 6px; }
9
+ .mm-tabs { display: flex; flex-wrap: wrap; gap: 2px 18px; }
10
+ .mm-counts { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; margin: 4px 2px 12px; font-size: 13px; line-height: 1.5; color: var(--sub); }
11
+ .mm-counts b { color: var(--ink); font-weight: 600; }
12
+ .mm-dot { color: var(--tertiary); }
13
+ .mm-foot { margin: 18px 2px 0; font-size: 12px; color: var(--tertiary); overflow-wrap: anywhere; }
14
+ .mm-icon-btn { width: 36px; justify-content: center; padding: 0; }
15
+ /* On a phone the top bar already says Memories, and the counts line carries Memory settings and Refresh, so the
16
+ hero steps aside and the list starts higher on the closed Duo (Control's page did the same for web phones). */
17
+ .mm-phone-only { display: none; }
18
+ @media (max-width: 599px) {
19
+ .mm-hero { display: none; }
20
+ .mm-phone-only { display: inline; }
21
+ .mm-controls { margin-top: 2px; }
22
+ }
23
+ .mm-link { display: inline; padding: 0; font: inherit; font-weight: 600; color: var(--accent); text-align: left; }
24
+ .mm-link:disabled { opacity: 0.45; }
25
+ .mm-muted { color: var(--sub); font-size: 13px; line-height: 1.45; overflow-wrap: anywhere; }
26
+ .mm-bad { color: var(--hot); font-size: 13.5px; overflow-wrap: anywhere; }
27
+ .mm-ok { color: var(--green); }
28
+ .mm-warn { color: var(--amber); font-size: 13px; }
29
+ .mm-split { margin-top: 2px; }
30
+ .mm-split, .mm-list, .mm-reader { min-width: 0; }
31
+
32
+ /* A reader on a narrow screen is a pushed page: the header, views and counts step aside. */
33
+ @media (max-width: 759px) {
34
+ #pane-memories.reading .mm-hero, #pane-memories.reading .mm-controls, #pane-memories.reading .mm-counts { display: none; }
35
+ }
36
+
37
+ /* ── list ─────────────────────────────────────────────── */
38
+ .mm-group { margin: 14px 4px 8px; align-items: baseline; }
39
+ .mm-group:first-child { margin-top: 4px; }
40
+ .mm-group span:last-child { font-weight: 500; font-size: 13px; }
41
+ .mm-group .mm-link { font-size: 13px; }
42
+ .mm-group-note { margin: -2px 4px 8px; font-size: 12.5px; line-height: 1.45; color: var(--sub); }
43
+ .mm-row { display: grid; grid-template-columns: minmax(0, 1fr) 12px; gap: 10px; align-items: center; width: 100%; padding: 12px 14px; text-align: left; color: inherit; position: relative; }
44
+ .mm-row + .mm-row::before { content: ''; position: absolute; top: 0; left: 14px; right: 0; height: 1px; background: var(--hairline); }
45
+ .mm-row:hover { background: var(--qopen); }
46
+ .mm-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
47
+ .mm-row[aria-selected='true'] { background: var(--qopen); box-shadow: inset 3px 0 0 var(--gold); }
48
+ .mm-row-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
49
+ .mm-row-title { font: 600 15px/1.35 var(--body); color: var(--ink); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
50
+ .mm-row-what { font-size: 12.5px; color: var(--sub); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
51
+ .mm-facts { font-size: 12px; line-height: 1.35; color: var(--tertiary); overflow-wrap: anywhere; }
52
+ .mm-kind { color: var(--tint); font-weight: 600; }
53
+ .mm-status { font-size: 12.5px; line-height: 1.4; color: var(--sub); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
54
+ .mm-status.ok { color: var(--green); }
55
+ .mm-status.warn { color: var(--amber); }
56
+ .mm-status.bad { color: var(--hot); }
57
+ .mm-state { display: flex; flex-direction: column; gap: 4px; padding: 18px 16px; font-size: 14px; line-height: 1.45; color: var(--sub); }
58
+ .mm-state strong { color: var(--ink); font-size: 15px; }
59
+ .mm-state-act { margin-top: 8px; }
60
+ .mm-list .skel-row:first-of-type { border-top: 1px solid var(--row-border); }
61
+ .mm-more { margin: 10px 0 4px; }
62
+ .mm-more-top { margin: 0 0 8px; }
63
+ .mm-search { max-width: none; margin: 4px 0 8px; }
64
+ .mm-search .field { width: 100%; }
65
+ .mm-aside-note { margin: 14px 4px 0; font-size: 13px; color: var(--sub); line-height: 1.45; }
66
+ .mm-aside-note h3 { margin: 0 0 4px; font: 600 14px/1.3 var(--body); color: var(--ink); overflow-wrap: anywhere; }
67
+ .mm-aside-note p { margin: 0 0 6px; }
68
+ @media (min-width: 760px) {
69
+ .mm-row-title { font-size: 13.5px; }
70
+ .mm-row { padding: 10px 12px; }
71
+ .mm-list .mm-group:first-child { margin-top: 0; }
72
+ }
73
+
74
+ /* ── reader ───────────────────────────────────────────── */
75
+ .mm-reader-head { padding: 4px 0 12px; border-bottom: 1px solid var(--hairline); margin-bottom: 14px; }
76
+ .mm-title { font: 500 23px/1.22 var(--display); letter-spacing: -0.005em; margin: 0; color: var(--ink); overflow-wrap: anywhere; }
77
+ .mm-sub { margin: 6px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--sub); overflow-wrap: anywhere; }
78
+ .mm-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; align-items: center; }
79
+ .mm-actions:first-child { margin-top: 0; }
80
+ .mm-reader-state { display: flex; flex-direction: column; gap: 4px; padding: 26px 4px; color: var(--sub); font-size: 14.5px; }
81
+ .mm-reader-state strong { color: var(--ink); font-size: 16px; }
82
+ .mm-reader .cx-notice { margin: 0 0 12px; overflow-wrap: anywhere; }
83
+ .mm-timeline { position: relative; padding-left: 22px; }
84
+ .mm-timeline::before { content: ''; position: absolute; left: 5px; top: 8px; bottom: 8px; width: 2px; border-radius: 1px; background: var(--hairline); }
85
+ .mm-step { position: relative; padding: 0 0 18px; min-width: 0; }
86
+ .mm-step::before { content: ''; position: absolute; left: -21px; top: 5px; width: 10px; height: 10px; border-radius: 50%; background: var(--panel); border: 2px solid var(--tint); }
87
+ .mm-step.last { padding-bottom: 4px; }
88
+ .mm-step-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 12px; margin-bottom: 6px; }
89
+ .mm-step-head h3 { margin: 0; font: 600 15px/1.3 var(--body); color: var(--ink); }
90
+ .mm-step-meta { font-size: 12px; color: var(--tertiary); overflow-wrap: anywhere; }
91
+ .mm-step-body { font-size: 14.5px; line-height: 1.5; color: var(--ink); overflow-wrap: anywhere; min-width: 0; }
92
+ .mm-step-body p { margin: 0 0 8px; }
93
+ .mm-step-body p:last-child { margin-bottom: 0; }
94
+ .mm-quote { margin: 0 0 8px; padding: 10px 12px; border-left: 3px solid var(--tint); border-radius: 0 10px 10px 0; background: var(--qopen); font-size: 14px; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--ink); }
95
+ .mm-label { display: block; font: 600 12px/1.3 var(--body); color: var(--sub); margin-bottom: 3px; }
96
+ .mm-change { display: grid; gap: 8px; margin-bottom: 8px; }
97
+ .mm-change > div { padding: 10px 12px; border-radius: 10px; background: var(--qopen); white-space: pre-wrap; }
98
+ .mm-change .after { background: var(--green-bg); }
99
+ .mm-effect { margin-top: 8px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--panel-border); }
100
+ .mm-effect ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; font-size: 13.5px; }
101
+ .mm-effect li b { display: block; font: 600 12px/1.3 var(--body); color: var(--sub); }
102
+ .mm-check { font-weight: 600; color: var(--green); }
103
+ @media (max-width: 599px) { .mm-title { font-size: 21px; line-height: 1.25; } }
104
+ @media (min-width: 1100px) { .mm-title { font-size: 26px; } }
105
+
106
+ /* ── Knowledge ────────────────────────────────────────── */
107
+ .mm-card { margin: 0 0 12px; }
108
+ .mm-card-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 12px; margin-bottom: 6px; }
109
+ .mm-card-title { margin: 0; font: 600 15.5px/1.3 var(--body); color: var(--ink); overflow-wrap: anywhere; }
110
+ .mm-card p { margin: 6px 0; font-size: 14px; line-height: 1.5; overflow-wrap: anywhere; }
111
+ .mm-card h4 { margin: 0 0 4px; font: 600 14px/1.35 var(--body); overflow-wrap: anywhere; }
112
+ .mm-sub-title { margin: 16px 0 6px; font: 600 14px/1.3 var(--body); color: var(--ink); }
113
+ .mm-inline { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0; }
114
+ .mm-inline > .field { flex: 1 1 200px; min-width: 0; min-height: 40px; padding: 0 12px; font-size: 16px; border-radius: 9px; }
115
+ .mm-inline > .cx-btn { min-height: 40px; height: 40px; }
116
+ .mm-wrap { align-items: flex-end; }
117
+ .mm-pick { display: inline-flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--sub); min-width: 0; }
118
+ .mm-pick > span { white-space: nowrap; }
119
+ .mm-block > span { white-space: normal; }
120
+ .mm-pick > .field { min-height: 40px; padding: 0 12px; font-size: 16px; border-radius: 9px; color: var(--ink); }
121
+ .mm-pick > select.field { padding-right: 34px; background-position: calc(100% - 18px) 17px, calc(100% - 13px) 17px; }
122
+ .mm-pick > textarea.field { padding: 10px 12px; min-height: 80px; }
123
+ .mm-block { display: flex; margin: 8px 0; }
124
+ .mm-num { width: 120px; }
125
+ .mm-progress { margin: 10px 0; padding: 10px 12px; border-radius: 10px; background: var(--qopen); border: 1px solid var(--panel-border); font-size: 13.5px; color: var(--ink); overflow-wrap: anywhere; }
126
+ .mm-progress ul { margin: 6px 0; padding-left: 18px; font-size: 12.5px; }
127
+ .mm-progress pre, .mm-pre { white-space: pre-wrap; overflow-wrap: anywhere; font: 400 11.5px/1.45 var(--mono); background: var(--qopen); padding: 10px; border-radius: 8px; max-height: 240px; overflow: auto; }
128
+ .mm-try { margin: 8px 0 2px; }
129
+ .mm-tries { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; }
130
+ .mm-tries .mm-link { font-size: 13.5px; overflow-wrap: anywhere; }
131
+ .mm-answer { margin: 12px 0 8px; padding: 12px 14px; border-radius: 10px; background: var(--qopen); font-size: 14.5px; line-height: 1.55; overflow-wrap: anywhere; max-height: 60vh; overflow-y: auto; }
132
+ .mm-answer h4 { margin: 10px 0 4px; font: 600 14.5px/1.3 var(--body); }
133
+ .mm-answer p { margin: 0 0 8px; }
134
+ .mm-answer ul { margin: 0 0 8px; padding-left: 1.2em; }
135
+ .mm-answer code { font: 400 13px/1.4 var(--mono); background: var(--panel); padding: 0 3px; border-radius: 4px; }
136
+ .mm-table { overflow-x: auto; max-width: 100%; }
137
+ .mm-answer table { border-collapse: collapse; font-size: 13px; }
138
+ .mm-answer th, .mm-answer td { border: 1px solid var(--panel-border); padding: 4px 8px; text-align: left; vertical-align: top; }
139
+ .mm-refs ol { margin: 0; padding-left: 1.4em; font-size: 13px; line-height: 1.45; }
140
+ .mm-refs li { margin-bottom: 4px; overflow-wrap: anywhere; }
141
+ .mm-ref { color: var(--accent); font-variant-numeric: tabular-nums; }
142
+ .mm-entity { margin-top: 10px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--panel-border); }
143
+ .mm-rels { margin: 6px 0; padding-left: 1.1em; font-size: 13px; line-height: 1.45; overflow-wrap: anywhere; }
144
+ .mm-health { margin: 14px 0 0; }
145
+ .mm-health > summary { cursor: pointer; padding: 12px 2px; font: 600 14px/1.3 var(--body); color: var(--ink); }
146
+ .mm-grid { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 14px; margin: 8px 0; font-size: 13.5px; }
147
+ .mm-grid dt { color: var(--sub); }
148
+ .mm-grid dd { margin: 0; overflow-wrap: anywhere; min-width: 0; }
149
+ .mm-ingest { margin-top: 8px; }
150
+ .mm-ingest .mm-pick { flex-direction: row; align-items: center; gap: 8px; flex: none; }
151
+ .mm-ingest select.field { width: auto; min-width: 96px; }
152
+ .mm-dup { padding: 10px 0; border-top: 1px solid var(--hairline); }
153
+ .mm-dup-member { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; padding: 6px 0; font-size: 13.5px; overflow-wrap: anywhere; }
154
+ .mm-dup-member > span { min-width: 0; flex: 1 1 200px; }
155
+ @media (max-width: 599px) {
156
+ .mm-grid { grid-template-columns: minmax(0, 1fr); gap: 0; }
157
+ .mm-grid dt { margin-top: 8px; font-size: 12.5px; }
158
+ }
159
+
160
+ /* Set up Knowledge */
161
+ .mm-setup { list-style: none; margin: 12px 0 8px; padding: 0; display: grid; gap: 14px; }
162
+ .mm-setup-step { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 12px; }
163
+ .mm-setup-mark { width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; font: 600 13px/1 var(--body); color: var(--sub); border: 1.5px solid var(--panel-border); background: var(--panel); }
164
+ .mm-setup-step.done .mm-setup-mark { color: var(--green); border-color: var(--green); background: var(--green-bg); }
165
+ .mm-setup-step.blocked .mm-setup-mark { color: var(--amber); border-color: var(--amber); }
166
+ .mm-setup-body { min-width: 0; }
167
+ .mm-setup-body h4 { margin: 3px 0 4px; font: 600 14.5px/1.3 var(--body); }
168
+ .mm-setup-body p { margin: 4px 0; font-size: 13.5px; line-height: 1.45; overflow-wrap: anywhere; }
169
+ .mm-checks, .mm-sources { list-style: none; margin: 6px 0; padding: 0; display: grid; gap: 6px; font-size: 13px; }
170
+ .mm-checks li { overflow-wrap: anywhere; }
171
+ .mm-checks li.ok { color: var(--ink); }
172
+ .mm-checks li.ok span { color: var(--green); }
173
+ .mm-sources li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
174
+ .mm-sources code { font: 400 12px/1.3 var(--mono); overflow-wrap: anywhere; min-width: 0; }
175
+ .mm-picks { display: grid; gap: 8px; margin: 8px 0; }
176
+ @media (min-width: 900px) { .mm-picks { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
177
+ .mm-pick-card { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 10px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--panel-border); background: var(--panel); cursor: pointer; font-size: 13px; line-height: 1.4; }
178
+ .mm-pick-card > span { display: flex; flex-direction: column; gap: 3px; min-width: 0; overflow-wrap: anywhere; }
179
+ .mm-pick-card.on { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); }
180
+ .mm-pick-card.off { opacity: 0.6; cursor: default; }
181
+ .mm-pick-card input { margin-top: 2px; accent-color: var(--gold); }
182
+ .mm-pick-card .cx-btn { align-self: flex-start; margin-top: 4px; }
183
+ .mm-ask-strip { gap: 6px 16px; font-size: 13.5px; }
184
+
185
+ /* ── the graph explorer, inside the reader and full screen ── */
186
+ .mm-graph { margin: 14px 0 0; min-width: 0; }
187
+ .mm-graph-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 6px 12px; margin-bottom: 8px; }
188
+ .mm-graph-text { min-width: 0; flex: 1 1 220px; }
189
+ .mm-graph-text p { margin: 2px 0 0; }
190
+ .mm-graph-host { min-width: 0; }
191
+ .mm-graph-wait { padding: 30px 4px; }
192
+ .mm-graph.full { position: fixed; inset: 0; z-index: 45; margin: 0; overflow-y: auto; overscroll-behavior: contain; background: var(--page);
193
+ padding: calc(var(--safe-top) + 10px) calc(var(--gutter) + var(--safe-right)) calc(var(--safe-bottom) + 16px) calc(var(--gutter) + var(--safe-left)); }
194
+ body.mm-graph-open { overflow: hidden; }
195
+ /* The explorer's own palette (graph-explorer.css reads these), in the app's light and dark. */
196
+ .mm-graph { --card: #ffffff; --raised: #eee8dd; --fg: #30312e; --muted: #74726d; --line: #ded6c8; --accent: #89662d; --green: #2f7952; --red: #a54732; --graph-bg: #faf8f3; }
197
+ :root[data-theme='dark'] .mm-graph { --card: #261d16; --raised: #30271f; --fg: #f5f0e6; --muted: #bbae9a; --line: #473a2c; --accent: #c9a86e; --green: #92c6a1; --red: #e8a494; --graph-bg: #14100c; }
198
+ /* The explorer sets its own stage height (and a smaller one when narrow); the pane decides it here instead. */
199
+ .mm-graph { --mm-graph-h: min(64dvh, 560px); }
200
+ .mm-graph.full { --mm-graph-h: max(320px, calc(100dvh - var(--safe-top) - var(--safe-bottom) - 230px)); }
201
+ .mm-graph .cgx .cgx-stage { height: var(--mm-graph-h); min-height: 320px; isolation: isolate; }
202
+ :root:not([data-theme='dark']) .mm-graph .cgx-panel { box-shadow: 0 4px 14px rgba(31, 23, 18, 0.08); }
203
+ :root:not([data-theme='dark']) .mm-graph .cgx-result { border-bottom-color: var(--line); }
204
+ /* The explorer and its investigation tools were drawn for Control's page, whose plain buttons, rows and fields had a
205
+ look of their own. The same base, at the lowest weight, so every explorer class still wins. */
206
+ :where(.mm-graph) button { border: 1px solid var(--line); background: var(--card); color: var(--fg); border-radius: 7px; padding: 7px 12px; font: 500 13px/1.2 var(--body); }
207
+ :where(.mm-graph) button:disabled { opacity: 0.45; }
208
+ :where(.mm-graph) input, :where(.mm-graph) select { color: var(--fg); background: var(--card); border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px; font: 400 14px/1.3 var(--body); max-width: 100%; }
209
+ .mm-graph .memory-investigation .row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; width: auto; min-height: 0; padding: 0; margin: 8px 0; border: 0; grid-template-columns: none; }
210
+ .mm-graph .memory-investigation .row:active { background: none; }
211
+ .mm-graph .memory-investigation .row input { flex: 1 1 160px; min-width: 0; }
212
+ .mm-graph .memory-investigation .muted { color: var(--muted); font-size: 12.5px; }
213
+ .mm-graph .memory-investigation .source-card { margin: 8px 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); }
214
+ .mm-graph .memory-investigation > [data-role='overview-status'] { margin: 8px 2px; font-size: 12.5px; color: var(--sub); }
215
+ .mm-graph .investigation-tools { border-top: 1px solid var(--hairline); margin-top: 10px; }
216
+ .mm-graph .investigation-tools > summary { cursor: pointer; padding: 12px 2px; font: 600 13.5px/1.3 var(--body); color: var(--ink); }
217
+ .mm-graph .investigation-tools details summary { cursor: pointer; font-size: 13px; overflow-wrap: anywhere; }
218
+ .mm-graph .investigation-tools p { font-size: 12.5px; overflow-wrap: anywhere; }
219
+ body.mm-modal-open .cgx-rail, body.mm-modal-open .cgx-railtoggle, body.mm-modal-open .cgx-pinned, body.mm-modal-open .cgx-dp, body.mm-modal-open .cgx-tip, body.mm-modal-open .cgx-hint { visibility: hidden; pointer-events: none; }
220
+
221
+ /* ── sheets ───────────────────────────────────────────── */
222
+ body.mm-modal-open { overflow: hidden; }
223
+ .mm-backdrop { position: fixed; inset: 0; z-index: 70; background: rgba(23, 18, 14, 0.5); display: flex; align-items: stretch; justify-content: center; }
224
+ .mm-backdrop.mm-enter { animation: fade 160ms ease; }
225
+ .mm-modal { position: relative; width: 100%; display: flex; flex-direction: column; background: var(--page); color: var(--ink); min-height: 0; }
226
+ .mm-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: calc(var(--safe-top) + 10px) calc(var(--gutter) + var(--safe-right)) 10px calc(var(--gutter) + var(--safe-left)); border-bottom: 1px solid var(--hairline); flex: none; }
227
+ .mm-modal-head h2 { margin: 0; font: 500 21px/1.2 var(--display); min-width: 0; overflow-wrap: anywhere; }
228
+ .mm-modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 14px calc(var(--gutter) + var(--safe-right)) calc(var(--safe-bottom) + 24px) calc(var(--gutter) + var(--safe-left)); font-size: 14.5px; line-height: 1.5; overflow-wrap: anywhere; }
229
+ .mm-modal-body > p { margin: 0 0 10px; }
230
+ .mm-set { margin: 0 0 18px; }
231
+ .mm-set .cx-list { margin: 8px 0; }
232
+ .mm-set .cx-set-row .switch { grid-row: auto; grid-column: auto; flex: none; }
233
+ .mm-set .switch:disabled { opacity: 0.5; }
234
+ .mm-checkrow { display: flex; flex-wrap: wrap; gap: 8px 18px; margin: 0 0 10px; }
235
+ .mm-checkrow .cx-check { margin: 0; font-size: 14px; }
236
+ .mm-preview { min-height: 220px; font: 400 13px/1.5 var(--mono); padding: 12px; white-space: pre-wrap; }
237
+ .mm-log { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 0; }
238
+ .mm-log li { display: flex; flex-direction: column; gap: 2px; padding: 8px 0; border-top: 1px solid var(--hairline); font-size: 13.5px; overflow-wrap: anywhere; }
239
+ .mm-log li:first-child { border-top: 0; }
240
+ .mm-merge { display: grid; gap: 10px; margin: 10px 0; }
241
+ @media (min-width: 600px) { .mm-merge { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
242
+ .mm-merge-col { border: 1px solid var(--panel-border); border-radius: 10px; padding: 10px 12px; min-width: 0; font-size: 13.5px; }
243
+ .mm-merge-col.keep { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold-bg); }
244
+ .mm-merge-col h4 { margin: 0 0 2px; }
245
+ .mm-merge-col p { margin: 6px 0; }
246
+ .mm-merge-steps { margin: 8px 0; padding-left: 20px; font-size: 13.5px; }
247
+ .mm-merge-steps li { opacity: 0.55; margin: 2px 0; }
248
+ .mm-merge-steps li.done { opacity: 0.8; text-decoration: line-through; }
249
+ .mm-merge-steps li.now { opacity: 1; font-weight: 600; }
250
+ @media (min-width: 600px) {
251
+ .mm-backdrop { align-items: center; padding: 24px; }
252
+ .mm-modal { max-width: 680px; max-height: 86dvh; border-radius: 16px; border: 1px solid var(--panel-border); box-shadow: 0 24px 60px rgba(0, 0, 0, 0.28); overflow: hidden; }
253
+ .mm-modal-head { padding: 14px 20px 12px; }
254
+ .mm-modal-body { padding: 16px 20px 22px; }
255
+ }
256
+ @media (prefers-reduced-motion: reduce) { .mm-backdrop.mm-enter { animation: none; } }
257
+
258
+ /* ── Cues to rate and Rated cues (Control's cue review: one card at a time, then the rated list) ── */
259
+ .split.mm-split.solo { display: block; }
260
+ .split.mm-split.solo .split-list { position: static; max-height: none; overflow: visible; max-width: 820px; }
261
+ .split.mm-split.solo .reader { display: none; }
262
+ .mm-cue-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin: 6px 2px 12px; }
263
+ .mm-cue-head p { margin: 3px 0 0; }
264
+ .mm-cue-title { margin: 0; font: 500 24px/1.15 var(--display); color: var(--ink); letter-spacing: -0.01em; }
265
+ .mm-cue { padding: 16px 18px; outline: none; }
266
+ .mm-cue:focus-visible { box-shadow: 0 0 0 2px var(--accent); }
267
+ .mm-cue-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; margin: 0 0 10px; font-size: 12.5px; color: var(--sub); overflow-wrap: anywhere; }
268
+ .mm-cue-meta b { color: var(--ink); font-weight: 600; }
269
+ .mm-cue-left { margin-left: auto; }
270
+ .mm-mono { font: 400 11.5px/1.3 var(--mono); }
271
+ .mm-cue-text { margin: 0 0 10px; font-size: 17px; line-height: 1.5; color: var(--ink); overflow-wrap: anywhere; }
272
+ .mm-cue-text.small { font-size: 14.5px; }
273
+ .mm-cue-sources { margin: 0 0 8px; font-size: 13px; }
274
+ .mm-cue-sources ul { margin: 2px 0 0; padding-left: 1.1em; }
275
+ .mm-cue-sources li { margin: 2px 0; overflow-wrap: anywhere; }
276
+ .mm-cue-before { margin: 8px 0; padding: 10px 14px; border-radius: 9px; background: var(--qopen); font-size: 13.5px; line-height: 1.45; overflow-wrap: anywhere; }
277
+ .mm-cue-before p { margin: 4px 0 0; color: var(--ink); }
278
+ .mm-verdicts { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 4px; }
279
+ .mm-verdicts .cx-btn { min-width: 0; }
280
+ .mm-key { font: 400 10.5px/1 var(--mono); opacity: 0.7; margin-right: 6px; }
281
+ .mm-cue .mm-block { margin-top: 12px; }
282
+ .mm-cue-next { margin: 10px 4px 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
283
+ .mm-cue-row { margin: 0 0 10px; padding: 12px 14px; }
284
+ .mm-cue-row .mm-verdicts { margin: 0; }
285
+ .mm-cue-rated { margin: 0 0 8px; font-size: 12.5px; font-weight: 600; color: var(--accent); overflow-wrap: anywhere; }
286
+ @media (max-width: 599px) {
287
+ .mm-keys-hint, .mm-key { display: none; }
288
+ .mm-cue { padding: 14px; }
289
+ .mm-cue-text { font-size: 16px; }
290
+ .mm-cue-title { font-size: 21px; }
291
+ }