retold-data-service 2.1.1 → 2.1.2

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 (22) hide show
  1. package/package.json +15 -15
  2. package/source/services/comprehension-loader/pict-app/providers/Pict-Provider-ComprehensionLoader.js +2 -2
  3. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Layout.js +43 -43
  4. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Load.js +14 -14
  5. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Schema.js +3 -3
  6. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Session.js +2 -2
  7. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Source.js +7 -7
  8. package/source/services/comprehension-loader/web/comprehension-loader.js +77 -77
  9. package/source/services/comprehension-loader/web/comprehension-loader.min.js +1 -1
  10. package/source/services/data-cloner/pict-app/providers/Pict-Provider-DataCloner.js +3 -3
  11. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Connection.js +1 -1
  12. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Deploy.js +5 -5
  13. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Export.js +11 -11
  14. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Layout.js +53 -53
  15. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Schema.js +3 -3
  16. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Session.js +2 -2
  17. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Sync.js +22 -22
  18. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-ViewData.js +4 -4
  19. package/source/services/data-cloner/web/data-cloner.js +110 -108
  20. package/source/services/data-cloner/web/data-cloner.js.map +1 -1
  21. package/source/services/data-cloner/web/data-cloner.min.js +1 -1
  22. package/source/services/data-cloner/web/data-cloner.min.js.map +1 -1
@@ -185,7 +185,7 @@
185
185
  3: [function (require, module, exports) {
186
186
  module.exports = {
187
187
  "name": "pict-application",
188
- "version": "1.0.33",
188
+ "version": "1.0.34",
189
189
  "description": "Application base class for a pict view-based application",
190
190
  "main": "source/Pict-Application.js",
191
191
  "scripts": {
@@ -216,9 +216,10 @@
216
216
  "browser-env": "^3.3.0",
217
217
  "eslint": "^9.28.0",
218
218
  "pict": "^1.0.348",
219
+ "pict-docuserve": "^0.1.5",
219
220
  "pict-provider": "^1.0.10",
220
221
  "pict-view": "^1.0.66",
221
- "quackage": "^1.0.58",
222
+ "quackage": "^1.1.0",
222
223
  "typescript": "^5.9.3"
223
224
  },
224
225
  "mocha": {
@@ -1475,7 +1476,7 @@
1475
1476
  5: [function (require, module, exports) {
1476
1477
  module.exports = {
1477
1478
  "name": "pict-provider",
1478
- "version": "1.0.12",
1479
+ "version": "1.0.13",
1479
1480
  "description": "Pict Provider Base Class",
1480
1481
  "main": "source/Pict-Provider.js",
1481
1482
  "scripts": {
@@ -1505,7 +1506,8 @@
1505
1506
  "@eslint/js": "^9.39.1",
1506
1507
  "eslint": "^9.39.1",
1507
1508
  "pict": "^1.0.351",
1508
- "quackage": "^1.0.58",
1509
+ "pict-docuserve": "^0.1.5",
1510
+ "quackage": "^1.1.0",
1509
1511
  "typescript": "^5.9.3"
1510
1512
  },
1511
1513
  "dependencies": {
@@ -6121,7 +6123,7 @@
6121
6123
  tmpHtml += '<tr' + tmpRowClass + '>';
6122
6124
  tmpHtml += '<td>' + this.escapeHtml(tmpT.Name) + '</td>';
6123
6125
  tmpHtml += '<td style="text-align:right; font-variant-numeric:tabular-nums">' + tmpCountFmt + '</td>';
6124
- tmpHtml += '<td style="text-align:right; font-variant-numeric:tabular-nums; color:#888">' + tmpTimeFmt + '</td>';
6126
+ tmpHtml += '<td style="text-align:right; font-variant-numeric:tabular-nums; color:var(--theme-color-text-muted, #888)">' + tmpTimeFmt + '</td>';
6125
6127
  tmpHtml += '</tr>';
6126
6128
  }
6127
6129
  tmpHtml += '</tbody>';
@@ -6266,9 +6268,9 @@
6266
6268
  }
6267
6269
  if (tmpHtml === '') {
6268
6270
  if (tmpIsLive) {
6269
- tmpHtml = '<div style="font-size:0.9em; color:#888; padding:8px 0">Sync in progress, waiting for table data\u2026</div>';
6271
+ tmpHtml = '<div style="font-size:0.9em; color:var(--theme-color-text-muted, #888); padding:8px 0">Sync in progress, waiting for table data\u2026</div>';
6270
6272
  } else {
6271
- tmpHtml = '<div style="font-size:0.9em; color:#888; padding:8px 0">No sync data available. Run a sync to see operation details here.</div>';
6273
+ tmpHtml = '<div style="font-size:0.9em; color:var(--theme-color-text-muted, #888); padding:8px 0">No sync data available. Run a sync to see operation details here.</div>';
6272
6274
  }
6273
6275
  }
6274
6276
  tmpContainer.innerHTML = tmpHtml;
@@ -6651,7 +6653,7 @@
6651
6653
  <div class="accordion-toggle">&#9660;</div>
6652
6654
  </div>
6653
6655
  <div class="accordion-body">
6654
- <p style="font-size:0.9em; color:#666; margin-bottom:10px">Configure the local database where cloned data will be stored. The provider list comes from the host's installed meadow-connection modules.</p>
6656
+ <p style="font-size:0.9em; color:var(--theme-color-text-secondary, #666); margin-bottom:10px">Configure the local database where cloned data will be stored. The provider list comes from the host's installed meadow-connection modules.</p>
6655
6657
 
6656
6658
  <div class="inline-group" style="margin-bottom:10px">
6657
6659
  <div style="flex:1; display:flex; align-items:flex-end; gap:8px; justify-content:flex-end">
@@ -6896,7 +6898,7 @@
6896
6898
  }
6897
6899
  auditGUIDIndices() {
6898
6900
  let tmpReportEl = document.getElementById('guidIndexReport');
6899
- if (tmpReportEl) tmpReportEl.innerHTML = '<span style="color:#888">Checking GUID indices...</span>';
6901
+ if (tmpReportEl) tmpReportEl.innerHTML = '<span style="color:var(--theme-color-text-muted, #888)">Checking GUID indices...</span>';
6900
6902
  let tmpSelf = this;
6901
6903
  this.pict.providers.DataCloner.api('GET', '/clone/schema/guid-index-audit').then(function (pData) {
6902
6904
  if (!tmpReportEl) return;
@@ -6910,13 +6912,13 @@
6910
6912
  }
6911
6913
  let tmpHTML = '<div style="margin-top:6px"><strong>' + pData.Message + '</strong></div>';
6912
6914
  tmpHTML += '<table style="font-size:0.85em; margin:6px 0; border-collapse:collapse; width:100%">';
6913
- tmpHTML += '<tr style="text-align:left; border-bottom:1px solid #ccc"><th style="padding:3px 8px">Table</th><th style="padding:3px 8px">GUID Column</th><th style="padding:3px 8px">Index</th></tr>';
6915
+ tmpHTML += '<tr style="text-align:left; border-bottom:1px solid var(--theme-color-border-default, #ccc)"><th style="padding:3px 8px">Table</th><th style="padding:3px 8px">GUID Column</th><th style="padding:3px 8px">Index</th></tr>';
6914
6916
  for (let t = 0; t < pData.Tables.length; t++) {
6915
6917
  let tmpTable = pData.Tables[t];
6916
6918
  for (let c = 0; c < tmpTable.GUIDColumns.length; c++) {
6917
6919
  let tmpCol = tmpTable.GUIDColumns[c];
6918
6920
  let tmpStatus = tmpCol.HasIndex ? '<span style="color:green">' + tmpCol.IndexName + '</span>' : '<span style="color:red">MISSING</span>';
6919
- tmpHTML += '<tr style="border-bottom:1px solid #eee"><td style="padding:3px 8px">' + tmpTable.Table + '</td><td style="padding:3px 8px">' + tmpCol.Column + '</td><td style="padding:3px 8px">' + tmpStatus + '</td></tr>';
6921
+ tmpHTML += '<tr style="border-bottom:1px solid var(--theme-color-border-light, #eee)"><td style="padding:3px 8px">' + tmpTable.Table + '</td><td style="padding:3px 8px">' + tmpCol.Column + '</td><td style="padding:3px 8px">' + tmpStatus + '</td></tr>';
6920
6922
  }
6921
6923
  }
6922
6924
  tmpHTML += '</table>';
@@ -6928,7 +6930,7 @@
6928
6930
  }
6929
6931
  createMissingGUIDIndices() {
6930
6932
  let tmpReportEl = document.getElementById('guidIndexReport');
6931
- if (tmpReportEl) tmpReportEl.innerHTML = '<span style="color:#888">Creating GUID indices...</span>';
6933
+ if (tmpReportEl) tmpReportEl.innerHTML = '<span style="color:var(--theme-color-text-muted, #888)">Creating GUID indices...</span>';
6932
6934
  let tmpSelf = this;
6933
6935
  this.pict.providers.DataCloner.api('POST', '/clone/schema/guid-index-create').then(function (pData) {
6934
6936
  if (!tmpReportEl) return;
@@ -6993,7 +6995,7 @@
6993
6995
  <div class="accordion-toggle">&#9660;</div>
6994
6996
  </div>
6995
6997
  <div class="accordion-body">
6996
- <p style="font-size:0.9em; color:#666; margin-bottom:10px">Creates the selected tables in the local database and sets up CRUD endpoints (e.g. GET /1.0/Documents).</p>
6998
+ <p style="font-size:0.9em; color:var(--theme-color-text-secondary, #666); margin-bottom:10px">Creates the selected tables in the local database and sets up CRUD endpoints (e.g. GET /1.0/Documents).</p>
6997
6999
  <button class="primary" onclick="pict.views['DataCloner-Deploy'].deploySchema()">Deploy Selected Tables</button>
6998
7000
  <button onclick="pict.views['DataCloner-Deploy'].auditGUIDIndices()">Check GUID Indices</button>
6999
7001
  <button class="danger" onclick="pict.views['DataCloner-Deploy'].resetDatabase()">Reset Database</button>
@@ -7395,7 +7397,7 @@
7395
7397
  <div class="accordion-toggle">&#9660;</div>
7396
7398
  </div>
7397
7399
  <div class="accordion-body">
7398
- <p style="font-size:0.9em; color:#666; margin-bottom:10px">Generate a JSON config file from your current settings. Use it to run headless clones from the command line.</p>
7400
+ <p style="font-size:0.9em; color:var(--theme-color-text-secondary, #666); margin-bottom:10px">Generate a JSON config file from your current settings. Use it to run headless clones from the command line.</p>
7399
7401
  <div style="display:flex; gap:8px; margin-bottom:10px">
7400
7402
  <button class="primary" onclick="pict.views['DataCloner-Export'].generateConfig()">Generate Config</button>
7401
7403
  <button class="secondary" onclick="pict.views['DataCloner-Export'].copyConfig()">Copy to Clipboard</button>
@@ -7403,28 +7405,28 @@
7403
7405
  </div>
7404
7406
  <div id="configExportStatus"></div>
7405
7407
  <div id="cliCommand" style="display:none; margin-bottom:10px">
7406
- <label style="margin-bottom:4px">CLI Command <span style="color:#888; font-weight:normal">(with config file)</span></label>
7407
- <div style="background:#1a1a1a; color:#4fc3f7; padding:10px 14px; border-radius:4px; font-family:monospace; font-size:0.9em; word-break:break-all; cursor:pointer" onclick="pict.views['DataCloner-Export'].copyCLI()" title="Click to copy"></div>
7408
+ <label style="margin-bottom:4px">CLI Command <span style="color:var(--theme-color-text-muted, #888); font-weight:normal">(with config file)</span></label>
7409
+ <div style="background:var(--theme-color-text-primary, #1a1a1a); color:#4fc3f7; padding:10px 14px; border-radius:4px; font-family:monospace; font-size:0.9em; word-break:break-all; cursor:pointer" onclick="pict.views['DataCloner-Export'].copyCLI()" title="Click to copy"></div>
7408
7410
  </div>
7409
7411
  <div id="cliOneShot" style="display:none; margin-bottom:10px">
7410
- <label style="margin-bottom:4px">One-liner <span style="color:#888; font-weight:normal">(no config file needed)</span></label>
7411
- <div style="background:#1a1a1a; color:#4fc3f7; padding:10px 14px; border-radius:4px; font-family:monospace; font-size:0.9em; word-break:break-all; cursor:pointer; white-space:pre-wrap" onclick="pict.views['DataCloner-Export'].copyOneShot()" title="Click to copy"></div>
7412
+ <label style="margin-bottom:4px">One-liner <span style="color:var(--theme-color-text-muted, #888); font-weight:normal">(no config file needed)</span></label>
7413
+ <div style="background:var(--theme-color-text-primary, #1a1a1a); color:#4fc3f7; padding:10px 14px; border-radius:4px; font-family:monospace; font-size:0.9em; word-break:break-all; cursor:pointer; white-space:pre-wrap" onclick="pict.views['DataCloner-Export'].copyOneShot()" title="Click to copy"></div>
7412
7414
  </div>
7413
- <textarea id="configOutput" style="display:none; width:100%; min-height:300px; font-family:monospace; font-size:0.85em; padding:10px; border:1px solid #ccc; border-radius:4px; background:#fafafa; tab-size:4; resize:vertical" readonly></textarea>
7415
+ <textarea id="configOutput" style="display:none; width:100%; min-height:300px; font-family:monospace; font-size:0.85em; padding:10px; border:1px solid var(--theme-color-border-default, #ccc); border-radius:4px; background:var(--theme-color-background-secondary, #fafafa); tab-size:4; resize:vertical" readonly></textarea>
7414
7416
 
7415
- <div id="mdwintExport" style="display:none; margin-top:16px; padding-top:16px; border-top:1px solid #eee">
7416
- <h3 style="margin:0 0 8px; font-size:1em">meadow-integration CLI <span style="color:#888; font-weight:normal; font-size:0.85em">(mdwint clone)</span></h3>
7417
- <p style="font-size:0.85em; color:#666; margin-bottom:8px">Save as <code>.meadow.config.json</code> in your project root, then run the command below. Requires a local Meadow extended schema JSON file.</p>
7417
+ <div id="mdwintExport" style="display:none; margin-top:16px; padding-top:16px; border-top:1px solid var(--theme-color-border-light, #eee)">
7418
+ <h3 style="margin:0 0 8px; font-size:1em">meadow-integration CLI <span style="color:var(--theme-color-text-muted, #888); font-weight:normal; font-size:0.85em">(mdwint clone)</span></h3>
7419
+ <p style="font-size:0.85em; color:var(--theme-color-text-secondary, #666); margin-bottom:8px">Save as <code>.meadow.config.json</code> in your project root, then run the command below. Requires a local Meadow extended schema JSON file.</p>
7418
7420
  <div style="display:flex; gap:8px; margin-bottom:10px">
7419
7421
  <button class="secondary" onclick="pict.views['DataCloner-Export'].copyMdwintConfig()">Copy Config</button>
7420
7422
  <button class="secondary" onclick="pict.views['DataCloner-Export'].downloadMdwintConfig()">Download .meadow.config.json</button>
7421
7423
  </div>
7422
7424
  <div id="mdwintCLICommand" style="margin-bottom:10px">
7423
7425
  <label style="margin-bottom:4px">CLI Command</label>
7424
- <div style="background:#1a1a1a; color:#4fc3f7; padding:10px 14px; border-radius:4px; font-family:monospace; font-size:0.9em; word-break:break-all; cursor:pointer" onclick="pict.views['DataCloner-Export'].copyMdwintCLI()" title="Click to copy"></div>
7426
+ <div style="background:var(--theme-color-text-primary, #1a1a1a); color:#4fc3f7; padding:10px 14px; border-radius:4px; font-family:monospace; font-size:0.9em; word-break:break-all; cursor:pointer" onclick="pict.views['DataCloner-Export'].copyMdwintCLI()" title="Click to copy"></div>
7425
7427
  </div>
7426
7428
  <div id="mdwintConfigStatus"></div>
7427
- <textarea id="mdwintConfigOutput" style="width:100%; min-height:250px; font-family:monospace; font-size:0.85em; padding:10px; border:1px solid #ccc; border-radius:4px; background:#fafafa; tab-size:4; resize:vertical" readonly></textarea>
7429
+ <textarea id="mdwintConfigOutput" style="width:100%; min-height:250px; font-family:monospace; font-size:0.85em; padding:10px; border:1px solid var(--theme-color-border-default, #ccc); border-radius:4px; background:var(--theme-color-background-secondary, #fafafa); tab-size:4; resize:vertical" readonly></textarea>
7428
7430
  </div>
7429
7431
  </div>
7430
7432
  </div>
@@ -7506,11 +7508,11 @@
7506
7508
  DefaultDestinationAddress: '#DataCloner-Application-Container',
7507
7509
  CSS: /*css*/`
7508
7510
  * { box-sizing: border-box; margin: 0; padding: 0; }
7509
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; color: #333; padding: 20px; }
7510
- h1 { margin-bottom: 20px; color: #1a1a1a; }
7511
- h2 { margin-bottom: 12px; color: #444; font-size: 1.2em; border-bottom: 2px solid #ddd; padding-bottom: 6px; }
7511
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: var(--theme-color-background-secondary, #f5f5f5); color: var(--theme-color-text-primary, #333); padding: 20px; }
7512
+ h1 { margin-bottom: 20px; color: var(--theme-color-text-primary, #1a1a1a); }
7513
+ h2 { margin-bottom: 12px; color: var(--theme-color-text-secondary, #444); font-size: 1.2em; border-bottom: 2px solid var(--theme-color-border-default, #ddd); padding-bottom: 6px; }
7512
7514
 
7513
- .section { background: #fff; border-radius: 8px; padding: 20px; margin-bottom: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
7515
+ .section { background: var(--theme-color-background-panel, #fff); border-radius: 8px; padding: 20px; margin-bottom: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
7514
7516
 
7515
7517
  /* Accordion layout */
7516
7518
  .accordion-row { display: flex; gap: 0; margin-bottom: 16px; align-items: stretch; }
@@ -7520,25 +7522,25 @@ h2 { margin-bottom: 12px; color: #444; font-size: 1.2em; border-bottom: 2px soli
7520
7522
  user-select: none;
7521
7523
  }
7522
7524
  .accordion-card {
7523
- flex: 1; background: #fff; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);
7525
+ flex: 1; background: var(--theme-color-background-panel, #fff); border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);
7524
7526
  overflow: hidden; min-width: 0;
7525
7527
  }
7526
7528
  .accordion-header {
7527
7529
  display: flex; align-items: center; padding: 14px 20px; cursor: pointer;
7528
7530
  user-select: none; gap: 12px; transition: background 0.15s; line-height: 1.4;
7529
7531
  }
7530
- .accordion-header:hover { background: #fafafa; }
7531
- .accordion-title { font-weight: 600; color: #333; font-size: 1.05em; white-space: nowrap; }
7532
- .accordion-preview { flex: 1; font-style: italic; color: #888; font-size: 0.9em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
7532
+ .accordion-header:hover { background: var(--theme-color-background-secondary, #fafafa); }
7533
+ .accordion-title { font-weight: 600; color: var(--theme-color-text-primary, #333); font-size: 1.05em; white-space: nowrap; }
7534
+ .accordion-preview { flex: 1; font-style: italic; color: var(--theme-color-text-muted, #888); font-size: 0.9em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
7533
7535
  .accordion-toggle {
7534
7536
  flex: 0 0 20px; display: flex; align-items: center; justify-content: center;
7535
- border-radius: 4px; transition: background 0.15s, transform 0.25s; font-size: 0.7em; color: #888;
7537
+ border-radius: 4px; transition: background 0.15s, transform 0.25s; font-size: 0.7em; color: var(--theme-color-text-muted, #888);
7536
7538
  }
7537
- .accordion-header:hover .accordion-toggle { background: #eee; color: #555; }
7539
+ .accordion-header:hover .accordion-toggle { background: var(--theme-color-border-light, #eee); color: var(--theme-color-text-secondary, #555); }
7538
7540
  .accordion-card.open .accordion-toggle { transform: rotate(180deg); }
7539
7541
  .accordion-body { padding: 0 20px 20px; display: none; }
7540
7542
  .accordion-card.open .accordion-body { display: block; }
7541
- .accordion-card.open .accordion-header { border-bottom: 1px solid #eee; }
7543
+ .accordion-card.open .accordion-header { border-bottom: 1px solid var(--theme-color-border-light, #eee); }
7542
7544
  .accordion-card.open .accordion-preview { display: none; }
7543
7545
 
7544
7546
  /* Action controls (go link + auto checkbox) */
@@ -7551,13 +7553,13 @@ h2 { margin-bottom: 12px; color: #444; font-size: 1.2em; border-bottom: 2px soli
7551
7553
  }
7552
7554
  .accordion-go:hover { background: #e8f0fe; text-decoration: underline; }
7553
7555
  .accordion-auto {
7554
- font-size: 0.82em; color: #999; white-space: nowrap; cursor: pointer;
7556
+ font-size: 0.82em; color: var(--theme-color-text-muted, #999); white-space: nowrap; cursor: pointer;
7555
7557
  }
7556
7558
  .accordion-auto .auto-label { display: none; }
7557
7559
  .accordion-auto:hover .auto-label { display: inline; }
7558
7560
  .accordion-auto input[type="checkbox"] { width: auto; margin: 0; cursor: pointer; vertical-align: middle; position: relative; top: 0px; opacity: 0.75; transition: opacity 0.15s; }
7559
7561
  .accordion-auto:hover input[type="checkbox"] { opacity: 1; }
7560
- .accordion-auto:hover { color: #666; }
7562
+ .accordion-auto:hover { color: var(--theme-color-text-secondary, #666); }
7561
7563
 
7562
7564
  /* Phase status indicator */
7563
7565
  .accordion-phase {
@@ -7565,12 +7567,12 @@ h2 { margin-bottom: 12px; color: #444; font-size: 1.2em; border-bottom: 2px soli
7565
7567
  font-size: 0.85em; line-height: 1;
7566
7568
  }
7567
7569
  .accordion-phase.visible { display: flex; }
7568
- .accordion-phase-ok { color: #28a745; }
7570
+ .accordion-phase-ok { color: var(--theme-color-status-success, #28a745); }
7569
7571
  .accordion-phase-error { color: #dc3545; }
7570
- .accordion-phase-busy { color: #28a745; }
7572
+ .accordion-phase-busy { color: var(--theme-color-status-success, #28a745); }
7571
7573
  .accordion-phase-busy .phase-spinner {
7572
7574
  display: inline-block; width: 14px; height: 14px;
7573
- border: 2px solid #28a745; border-top-color: transparent; border-radius: 50%;
7575
+ border: 2px solid var(--theme-color-status-success, #28a745); border-top-color: transparent; border-radius: 50%;
7574
7576
  animation: phase-spin 0.8s linear infinite; vertical-align: middle;
7575
7577
  }
7576
7578
  @keyframes phase-spin {
@@ -7582,13 +7584,13 @@ h2 { margin-bottom: 12px; color: #444; font-size: 1.2em; border-bottom: 2px soli
7582
7584
  }
7583
7585
  .accordion-controls button {
7584
7586
  padding: 4px 10px; font-size: 0.82em; font-weight: 500; background: none;
7585
- border: 1px solid #ccc; border-radius: 4px; color: #666; cursor: pointer; margin: 0;
7587
+ border: 1px solid var(--theme-color-border-default, #ccc); border-radius: 4px; color: var(--theme-color-text-secondary, #666); cursor: pointer; margin: 0;
7586
7588
  }
7587
- .accordion-controls button:hover { background: #f0f0f0; border-color: #aaa; color: #333; }
7589
+ .accordion-controls button:hover { background: var(--theme-color-background-tertiary, #f0f0f0); border-color: var(--theme-color-text-muted, #aaa); color: var(--theme-color-text-primary, #333); }
7588
7590
 
7589
7591
  label { display: block; font-weight: 600; margin-bottom: 4px; font-size: 0.9em; }
7590
7592
  input[type="text"], input[type="password"], input[type="number"] {
7591
- width: 100%; padding: 8px 12px; border: 1px solid #ccc; border-radius: 4px;
7593
+ width: 100%; padding: 8px 12px; border: 1px solid var(--theme-color-border-default, #ccc); border-radius: 4px;
7592
7594
  font-size: 0.95em; margin-bottom: 10px;
7593
7595
  }
7594
7596
  input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus {
@@ -7599,13 +7601,13 @@ button {
7599
7601
  padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer;
7600
7602
  font-size: 0.9em; font-weight: 600; margin-right: 8px; margin-bottom: 8px;
7601
7603
  }
7602
- button.primary { background: #4a90d9; color: #fff; }
7604
+ button.primary { background: #4a90d9; color: var(--theme-color-background-panel, #fff); }
7603
7605
  button.primary:hover { background: #357abd; }
7604
- button.secondary { background: #6c757d; color: #fff; }
7606
+ button.secondary { background: #6c757d; color: var(--theme-color-background-panel, #fff); }
7605
7607
  button.secondary:hover { background: #5a6268; }
7606
- button.danger { background: #dc3545; color: #fff; }
7608
+ button.danger { background: #dc3545; color: var(--theme-color-background-panel, #fff); }
7607
7609
  button.danger:hover { background: #c82333; }
7608
- button.success { background: #28a745; color: #fff; }
7610
+ button.success { background: var(--theme-color-status-success, #28a745); color: var(--theme-color-background-panel, #fff); }
7609
7611
  button.success:hover { background: #218838; }
7610
7612
  button:disabled { opacity: 0.5; cursor: not-allowed; }
7611
7613
 
@@ -7620,7 +7622,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
7620
7622
 
7621
7623
  a { color: #4a90d9; }
7622
7624
 
7623
- select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #ccc; border-radius: 4px; font-size: 0.95em; margin-bottom: 10px; }
7625
+ select { background: var(--theme-color-background-panel, #fff); width: 100%; padding: 8px 12px; border: 1px solid var(--theme-color-border-default, #ccc); border-radius: 4px; font-size: 0.95em; margin-bottom: 10px; }
7624
7626
 
7625
7627
  .checkbox-row { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
7626
7628
  .checkbox-row input[type="checkbox"] { width: auto; margin: 0; }
@@ -7628,16 +7630,16 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
7628
7630
 
7629
7631
  /* Live Status Bar */
7630
7632
  .live-status-bar {
7631
- background: #fff; border-radius: 8px; margin-bottom: 16px;
7633
+ background: var(--theme-color-background-panel, #fff); border-radius: 8px; margin-bottom: 16px;
7632
7634
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
7633
7635
  position: sticky; top: 0; z-index: 100; border-left: 4px solid #6c757d;
7634
7636
  }
7635
7637
  .live-status-bar.phase-idle { border-left-color: #6c757d; }
7636
7638
  .live-status-bar.phase-disconnected { border-left-color: #dc3545; }
7637
7639
  .live-status-bar.phase-ready { border-left-color: #4a90d9; }
7638
- .live-status-bar.phase-syncing { border-left-color: #28a745; }
7640
+ .live-status-bar.phase-syncing { border-left-color: var(--theme-color-status-success, #28a745); }
7639
7641
  .live-status-bar.phase-stopping { border-left-color: #ffc107; }
7640
- .live-status-bar.phase-complete { border-left-color: #28a745; }
7642
+ .live-status-bar.phase-complete { border-left-color: var(--theme-color-status-success, #28a745); }
7641
7643
 
7642
7644
  .live-status-dot {
7643
7645
  width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0;
@@ -7647,34 +7649,34 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
7647
7649
  .live-status-bar.phase-disconnected .live-status-dot { background: #dc3545; }
7648
7650
  .live-status-bar.phase-ready .live-status-dot { background: #4a90d9; }
7649
7651
  .live-status-bar.phase-syncing .live-status-dot {
7650
- background: #28a745;
7652
+ background: var(--theme-color-status-success, #28a745);
7651
7653
  animation: live-pulse 1.5s ease-in-out infinite;
7652
7654
  }
7653
7655
  .live-status-bar.phase-stopping .live-status-dot {
7654
7656
  background: #ffc107;
7655
7657
  animation: live-pulse 0.8s ease-in-out infinite;
7656
7658
  }
7657
- .live-status-bar.phase-complete .live-status-dot { background: #28a745; }
7659
+ .live-status-bar.phase-complete .live-status-dot { background: var(--theme-color-status-success, #28a745); }
7658
7660
 
7659
7661
  @keyframes live-pulse {
7660
7662
  0%, 100% { opacity: 1; transform: scale(1); }
7661
7663
  50% { opacity: 0.4; transform: scale(0.8); }
7662
7664
  }
7663
7665
 
7664
- .live-status-message { flex: 1; font-size: 0.92em; color: #333; line-height: 1.4; }
7666
+ .live-status-message { flex: 1; font-size: 0.92em; color: var(--theme-color-text-primary, #333); line-height: 1.4; }
7665
7667
 
7666
7668
  .live-status-meta {
7667
- display: flex; gap: 16px; flex-shrink: 0; font-size: 0.82em; color: #666;
7669
+ display: flex; gap: 16px; flex-shrink: 0; font-size: 0.82em; color: var(--theme-color-text-secondary, #666);
7668
7670
  }
7669
7671
  .live-status-meta-item { white-space: nowrap; }
7670
- .live-status-meta-item strong { color: #333; }
7672
+ .live-status-meta-item strong { color: var(--theme-color-text-primary, #333); }
7671
7673
 
7672
7674
  .live-status-progress-bar {
7673
7675
  height: 3px; background: #e9ecef; border-radius: 2px; overflow: hidden;
7674
7676
  position: absolute; bottom: 0; left: 0; right: 0;
7675
7677
  }
7676
7678
  .live-status-progress-fill {
7677
- height: 100%; background: #28a745; transition: width 1s ease;
7679
+ height: 100%; background: var(--theme-color-status-success, #28a745); transition: width 1s ease;
7678
7680
  }
7679
7681
  /* Expandable status bar */
7680
7682
  .live-status-header {
@@ -7686,7 +7688,7 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
7686
7688
  }
7687
7689
  .live-status-expand-toggle {
7688
7690
  flex: 0 0 20px; display: flex; align-items: center; justify-content: center;
7689
- font-size: 0.7em; color: #888; transition: transform 0.25s;
7691
+ font-size: 0.7em; color: var(--theme-color-text-muted, #888); transition: transform 0.25s;
7690
7692
  }
7691
7693
  .live-status-bar.expanded .live-status-expand-toggle { transform: rotate(180deg); }
7692
7694
 
@@ -7700,19 +7702,19 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
7700
7702
  padding: 8px 0 12px; margin-bottom: 12px; border-bottom: 1px solid #e9ecef;
7701
7703
  }
7702
7704
  .status-detail-summary-message {
7703
- font-size: 0.92em; color: #333; font-weight: 600;
7705
+ font-size: 0.92em; color: var(--theme-color-text-primary, #333); font-weight: 600;
7704
7706
  }
7705
7707
  .status-detail-summary-counters {
7706
- display: flex; gap: 16px; flex-wrap: wrap; font-size: 0.82em; color: #666;
7708
+ display: flex; gap: 16px; flex-wrap: wrap; font-size: 0.82em; color: var(--theme-color-text-secondary, #666);
7707
7709
  }
7708
7710
 
7709
7711
  /* Status Detail Sections */
7710
7712
  .status-detail-section { margin-bottom: 14px; }
7711
7713
  .status-detail-section:last-child { margin-bottom: 0; }
7712
7714
  .status-detail-section-title {
7713
- font-size: 0.85em; font-weight: 600; color: #555; text-transform: uppercase;
7715
+ font-size: 0.85em; font-weight: 600; color: var(--theme-color-text-secondary, #555); text-transform: uppercase;
7714
7716
  letter-spacing: 0.5px; margin-bottom: 8px; padding-bottom: 4px;
7715
- border-bottom: 1px solid #eee;
7717
+ border-bottom: 1px solid var(--theme-color-border-light, #eee);
7716
7718
  }
7717
7719
 
7718
7720
  /* Running Operations */
@@ -7726,18 +7728,18 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
7726
7728
  min-width: 120px;
7727
7729
  }
7728
7730
  .running-op-bar-fill { height: 100%; background: #4a90d9; transition: width 0.5s ease; }
7729
- .running-op-count { font-size: 0.85em; color: #666; white-space: nowrap; }
7730
- .running-op-pending { color: #888; font-size: 0.85em; font-style: italic; padding: 4px 0; }
7731
+ .running-op-count { font-size: 0.85em; color: var(--theme-color-text-secondary, #666); white-space: nowrap; }
7732
+ .running-op-pending { color: var(--theme-color-text-muted, #888); font-size: 0.85em; font-style: italic; padding: 4px 0; }
7731
7733
 
7732
7734
  /* Completed Operations */
7733
- .completed-op-row { padding: 8px 0; border-bottom: 1px solid #f0f0f0; }
7735
+ .completed-op-row { padding: 8px 0; border-bottom: 1px solid var(--theme-color-background-tertiary, #f0f0f0); }
7734
7736
  .completed-op-row:last-child { border-bottom: none; }
7735
7737
  .completed-op-header {
7736
7738
  display: flex; align-items: center; gap: 10px; font-size: 0.9em; margin-bottom: 4px;
7737
7739
  }
7738
7740
  .completed-op-name { font-weight: 600; }
7739
- .completed-op-stats { color: #666; font-size: 0.85em; }
7740
- .completed-op-checkmark { color: #28a745; }
7741
+ .completed-op-stats { color: var(--theme-color-text-secondary, #666); font-size: 0.85em; }
7742
+ .completed-op-checkmark { color: var(--theme-color-status-success, #28a745); }
7741
7743
 
7742
7744
  /* Ratio Bar */
7743
7745
  .ratio-bar-container {
@@ -7746,28 +7748,28 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
7746
7748
  }
7747
7749
  .ratio-bar-segment { height: 100%; transition: width 0.5s ease; }
7748
7750
  .ratio-bar-segment.unchanged { background: #6c757d; }
7749
- .ratio-bar-segment.new-records { background: #28a745; }
7751
+ .ratio-bar-segment.new-records { background: var(--theme-color-status-success, #28a745); }
7750
7752
  .ratio-bar-segment.updated { background: #4a90d9; }
7751
7753
  .ratio-bar-segment.deleted { background: #dc3545; }
7752
7754
  .ratio-bar-legend {
7753
- display: flex; gap: 12px; font-size: 0.75em; color: #666; margin-top: 2px; flex-wrap: wrap;
7755
+ display: flex; gap: 12px; font-size: 0.75em; color: var(--theme-color-text-secondary, #666); margin-top: 2px; flex-wrap: wrap;
7754
7756
  }
7755
7757
  .ratio-bar-legend-item { display: flex; align-items: center; gap: 4px; }
7756
7758
  .ratio-bar-legend-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
7757
7759
  .ratio-bar-legend-dot.unchanged-dot { background: #6c757d; }
7758
- .ratio-bar-legend-dot.new-dot { background: #28a745; }
7760
+ .ratio-bar-legend-dot.new-dot { background: var(--theme-color-status-success, #28a745); }
7759
7761
  .ratio-bar-legend-dot.updated-dot { background: #4a90d9; }
7760
7762
  .ratio-bar-legend-dot.deleted-dot { background: #dc3545; }
7761
7763
 
7762
7764
  /* Error Operations */
7763
- .error-op-row { padding: 6px 0; border-bottom: 1px solid #f0f0f0; font-size: 0.9em; }
7765
+ .error-op-row { padding: 6px 0; border-bottom: 1px solid var(--theme-color-background-tertiary, #f0f0f0); font-size: 0.9em; }
7764
7766
  .error-op-row:last-child { border-bottom: none; }
7765
7767
  .error-op-header { display: flex; align-items: center; gap: 8px; }
7766
7768
  .error-op-name { font-weight: 600; color: #dc3545; }
7767
7769
  .error-op-status { font-size: 0.82em; color: #dc3545; }
7768
- .error-op-message { font-size: 0.82em; color: #888; margin-top: 2px; padding-left: 18px; }
7770
+ .error-op-message { font-size: 0.82em; color: var(--theme-color-text-muted, #888); margin-top: 2px; padding-left: 18px; }
7769
7771
  .error-op-log-entries {
7770
- font-size: 0.78em; color: #888; margin-top: 4px; padding-left: 18px;
7772
+ font-size: 0.78em; color: var(--theme-color-text-muted, #888); margin-top: 4px; padding-left: 18px;
7771
7773
  font-family: monospace; max-height: 80px; overflow-y: auto;
7772
7774
  }
7773
7775
 
@@ -7776,12 +7778,12 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
7776
7778
  width: 100%; border-collapse: collapse; font-size: 0.88em;
7777
7779
  }
7778
7780
  .precount-table thead th {
7779
- text-align: left; font-weight: 600; color: #555; font-size: 0.85em;
7781
+ text-align: left; font-weight: 600; color: var(--theme-color-text-secondary, #555); font-size: 0.85em;
7780
7782
  text-transform: uppercase; letter-spacing: 0.3px;
7781
7783
  padding: 4px 8px 6px; border-bottom: 2px solid #e9ecef;
7782
7784
  }
7783
7785
  .precount-table tbody td {
7784
- padding: 4px 8px; border-bottom: 1px solid #f0f0f0;
7786
+ padding: 4px 8px; border-bottom: 1px solid var(--theme-color-background-tertiary, #f0f0f0);
7785
7787
  }
7786
7788
  .precount-table tbody tr:last-child td { border-bottom: 1px solid #e9ecef; }
7787
7789
  .precount-table tfoot td {
@@ -7789,12 +7791,12 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
7789
7791
  }
7790
7792
  .precount-error td { color: #dc3545; }
7791
7793
  .precount-pending {
7792
- color: #888; font-size: 0.85em; font-style: italic; padding: 8px 0 2px;
7794
+ color: var(--theme-color-text-muted, #888); font-size: 0.85em; font-style: italic; padding: 8px 0 2px;
7793
7795
  display: flex; align-items: center; gap: 6px;
7794
7796
  }
7795
7797
  .precount-spinner {
7796
7798
  display: inline-block; width: 12px; height: 12px;
7797
- border: 2px solid #ddd; border-top-color: #4a90d9;
7799
+ border: 2px solid var(--theme-color-border-default, #ddd); border-top-color: #4a90d9;
7798
7800
  border-radius: 50%; animation: precount-spin 0.8s linear infinite;
7799
7801
  }
7800
7802
  @keyframes precount-spin { to { transform: rotate(360deg); } }
@@ -7979,9 +7981,9 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
7979
7981
  DefaultRenderable: 'DataCloner-Schema',
7980
7982
  DefaultDestinationAddress: '#DataCloner-Section-Schema',
7981
7983
  CSS: /*css*/`
7982
- .table-list { max-height: 300px; overflow-y: auto; border: 1px solid #ddd; border-radius: 4px; padding: 8px; margin: 10px 0; }
7984
+ .table-list { max-height: 300px; overflow-y: auto; border: 1px solid var(--theme-color-border-default, #ddd); border-radius: 4px; padding: 8px; margin: 10px 0; }
7983
7985
  .table-item { padding: 4px 8px; display: flex; align-items: center; }
7984
- .table-item:hover { background: #f0f0f0; }
7986
+ .table-item:hover { background: var(--theme-color-background-tertiary, #f0f0f0); }
7985
7987
  .table-item input[type="checkbox"] { margin-right: 8px; width: auto; }
7986
7988
  .table-item label { display: inline; font-weight: normal; margin-bottom: 0; cursor: pointer; }
7987
7989
  `,
@@ -8014,7 +8016,7 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8014
8016
  <input type="text" id="tableFilter" placeholder="Filter tables..." style="flex:1; margin-bottom:0" oninput="pict.views['DataCloner-Schema'].filterTableList()">
8015
8017
  <button class="secondary" onclick="pict.views['DataCloner-Schema'].selectAllTables(true)" style="font-size:0.8em">Select All</button>
8016
8018
  <button class="secondary" onclick="pict.views['DataCloner-Schema'].selectAllTables(false)" style="font-size:0.8em">Deselect All</button>
8017
- <span id="tableSelectionCount" style="font-size:0.85em; color:#666; white-space:nowrap"></span>
8019
+ <span id="tableSelectionCount" style="font-size:0.85em; color:var(--theme-color-text-secondary, #666); white-space:nowrap"></span>
8018
8020
  </div>
8019
8021
  <div id="tableList" class="table-list"></div>
8020
8022
  </div>
@@ -8176,7 +8178,7 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8176
8178
  </div>
8177
8179
 
8178
8180
  <details style="margin-bottom:10px">
8179
- <summary style="cursor:pointer; font-size:0.9em; color:#666">Advanced Session Options</summary>
8181
+ <summary style="cursor:pointer; font-size:0.9em; color:var(--theme-color-text-secondary, #666)">Advanced Session Options</summary>
8180
8182
  <div style="padding:10px 0">
8181
8183
  <label for="authURI">Authentication URI Template (leave blank for default)</label>
8182
8184
  <input type="text" id="authURI" placeholder="Authenticate/{~D:Record.UserName~}/{~D:Record.Password~}">
@@ -8196,7 +8198,7 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8196
8198
  <button class="primary" onclick="pict.views['DataCloner-Session'].configureSession()">Configure Session</button>
8197
8199
  <div id="sessionConfigStatus"></div>
8198
8200
 
8199
- <hr style="margin:16px 0; border:none; border-top:1px solid #eee">
8201
+ <hr style="margin:16px 0; border:none; border-top:1px solid var(--theme-color-border-light, #eee)">
8200
8202
 
8201
8203
  <div class="inline-group">
8202
8204
  <div>
@@ -8386,12 +8388,12 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8386
8388
  let tmpDurationStr = tmpDurationSec < 60 ? tmpDurationSec + 's' : Math.floor(tmpDurationSec / 60) + 'm ' + tmpDurationSec % 60 + 's';
8387
8389
  let tmpTotalSynced = pReport.Summary.TotalSynced.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
8388
8390
  let tmpTotalRecords = pReport.Summary.TotalRecords.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
8389
- tmpCardsContainer.innerHTML = '' + '<div class="report-card ' + tmpOutcomeClass + '">' + ' <div class="card-label">Outcome</div>' + ' <div class="card-value" style="color:' + tmpOutcomeColor + '">' + pReport.Outcome + '</div>' + '</div>' + '<div class="report-card">' + ' <div class="card-label">Mode</div>' + ' <div class="card-value">' + pReport.Config.SyncMode + '</div>' + '</div>' + '<div class="report-card">' + ' <div class="card-label">Duration</div>' + ' <div class="card-value">' + tmpDurationStr + '</div>' + '</div>' + '<div class="report-card">' + ' <div class="card-label">Tables</div>' + ' <div class="card-value">' + pReport.Summary.Complete + ' / ' + pReport.Summary.TotalTables + '</div>' + '</div>' + '<div class="report-card">' + ' <div class="card-label">Records</div>' + ' <div class="card-value">' + tmpTotalSynced + '</div>' + ' <div style="font-size:0.75em; color:#888">of ' + tmpTotalRecords + '</div>' + '</div>';
8391
+ tmpCardsContainer.innerHTML = '' + '<div class="report-card ' + tmpOutcomeClass + '">' + ' <div class="card-label">Outcome</div>' + ' <div class="card-value" style="color:' + tmpOutcomeColor + '">' + pReport.Outcome + '</div>' + '</div>' + '<div class="report-card">' + ' <div class="card-label">Mode</div>' + ' <div class="card-value">' + pReport.Config.SyncMode + '</div>' + '</div>' + '<div class="report-card">' + ' <div class="card-label">Duration</div>' + ' <div class="card-value">' + tmpDurationStr + '</div>' + '</div>' + '<div class="report-card">' + ' <div class="card-label">Tables</div>' + ' <div class="card-value">' + pReport.Summary.Complete + ' / ' + pReport.Summary.TotalTables + '</div>' + '</div>' + '<div class="report-card">' + ' <div class="card-label">Records</div>' + ' <div class="card-value">' + tmpTotalSynced + '</div>' + ' <div style="font-size:0.75em; color:var(--theme-color-text-muted, #888)">of ' + tmpTotalRecords + '</div>' + '</div>';
8390
8392
 
8391
8393
  // --- Anomalies ---
8392
8394
  let tmpAnomalyContainer = document.getElementById('reportAnomalies');
8393
8395
  if (pReport.Anomalies.length === 0) {
8394
- tmpAnomalyContainer.innerHTML = '<div style="color:#28a745; font-weight:600; font-size:0.9em">No anomalies detected.</div>';
8396
+ tmpAnomalyContainer.innerHTML = '<div style="color:var(--theme-color-status-success, #28a745); font-weight:600; font-size:0.9em">No anomalies detected.</div>';
8395
8397
  } else {
8396
8398
  let tmpHtml = '<h4 style="margin:0 0 8px; color:#dc3545; font-size:0.95em">Anomalies (' + pReport.Anomalies.length + ')</h4>';
8397
8399
  tmpHtml += '<table class="progress-table">';
@@ -8413,7 +8415,7 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8413
8415
  let tmpTopContainer = document.getElementById('reportTopTables');
8414
8416
  let tmpTopCount = Math.min(10, pReport.Tables.length);
8415
8417
  if (tmpTopCount > 0) {
8416
- let tmpHtml = '<h4 style="margin:0 0 8px; font-size:0.95em; color:#444">Top Tables by Duration</h4>';
8418
+ let tmpHtml = '<h4 style="margin:0 0 8px; font-size:0.95em; color:var(--theme-color-text-secondary, #444)">Top Tables by Duration</h4>';
8417
8419
  tmpHtml += '<table class="progress-table">';
8418
8420
  tmpHtml += '<tr><th>Table</th><th>Duration</th><th>Records</th><th>Status</th></tr>';
8419
8421
  for (let i = 0; i < tmpTopCount; i++) {
@@ -8604,22 +8606,22 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8604
8606
  DefaultDestinationAddress: '#DataCloner-Section-Sync',
8605
8607
  CSS: /*css*/`
8606
8608
  .progress-table { width: 100%; border-collapse: collapse; margin-top: 4px; margin-bottom: 4px; }
8607
- .progress-table th, .progress-table td { text-align: left; padding: 6px 12px; border-bottom: 1px solid #eee; font-size: 0.9em; }
8609
+ .progress-table th, .progress-table td { text-align: left; padding: 6px 12px; border-bottom: 1px solid var(--theme-color-border-light, #eee); font-size: 0.9em; }
8608
8610
  .progress-table th { background: #f8f9fa; font-weight: 600; }
8609
- .progress-table-muted td { color: #888; padding: 3px 12px; font-size: 0.85em; border-bottom: 1px solid #f4f5f6; }
8611
+ .progress-table-muted td { color: var(--theme-color-text-muted, #888); padding: 3px 12px; font-size: 0.85em; border-bottom: 1px solid #f4f5f6; }
8610
8612
  .progress-bar-container { width: 120px; height: 16px; background: #e9ecef; border-radius: 8px; overflow: hidden; display: inline-block; vertical-align: middle; }
8611
- .progress-bar-fill { height: 100%; background: #28a745; transition: width 0.3s; }
8612
- .sync-section-header { font-size: 0.8em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: #4a90d9; padding: 10px 0 2px 0; margin-top: 6px; border-top: 1px solid #e0e0e0; }
8613
+ .progress-bar-fill { height: 100%; background: var(--theme-color-status-success, #28a745); transition: width 0.3s; }
8614
+ .sync-section-header { font-size: 0.8em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: #4a90d9; padding: 10px 0 2px 0; margin-top: 6px; border-top: 1px solid var(--theme-color-border-default, #e0e0e0); }
8613
8615
  .sync-section-header:first-child { border-top: none; margin-top: 10px; }
8614
8616
  .sync-section-header-error { color: #dc3545; }
8615
- .sync-section-header-ok { color: #28a745; }
8616
- .sync-section-count { font-weight: 400; color: #999; font-size: 0.95em; }
8617
- .sync-section-overflow { font-size: 0.8em; color: #aaa; padding: 2px 12px 6px; }
8618
- .sync-pending-count { text-align: right; color: #aaa; font-size: 0.85em; }
8617
+ .sync-section-header-ok { color: var(--theme-color-status-success, #28a745); }
8618
+ .sync-section-count { font-weight: 400; color: var(--theme-color-text-muted, #999); font-size: 0.95em; }
8619
+ .sync-section-overflow { font-size: 0.8em; color: var(--theme-color-text-muted, #aaa); padding: 2px 12px 6px; }
8620
+ .sync-pending-count { text-align: right; color: var(--theme-color-text-muted, #aaa); font-size: 0.85em; }
8619
8621
  .report-card { background: #f8f9fa; border-radius: 8px; padding: 12px 16px; min-width: 140px; text-align: center; border: 1px solid #e9ecef; }
8620
- .report-card .card-label { font-size: 0.8em; color: #666; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
8622
+ .report-card .card-label { font-size: 0.8em; color: var(--theme-color-text-secondary, #666); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
8621
8623
  .report-card .card-value { font-size: 1.4em; font-weight: 700; }
8622
- .report-card.outcome-success { border-left: 4px solid #28a745; }
8624
+ .report-card.outcome-success { border-left: 4px solid var(--theme-color-status-success, #28a745); }
8623
8625
  .report-card.outcome-partial { border-left: 4px solid #ffc107; }
8624
8626
  .report-card.outcome-error { border-left: 4px solid #dc3545; }
8625
8627
  .report-card.outcome-stopped { border-left: 4px solid #6c757d; }
@@ -8655,30 +8657,30 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8655
8657
  <button class="danger" style="margin:0" onclick="pict.views['DataCloner-Sync'].stopSync()">Stop Sync</button>
8656
8658
  </div>
8657
8659
  </div>
8658
- <div style="font-size:0.8em; color:#888; margin-bottom:10px; padding-left:158px">Cross-DB tolerance for date comparison (default: 1000ms)</div>
8660
+ <div style="font-size:0.8em; color:var(--theme-color-text-muted, #888); margin-bottom:10px; padding-left:158px">Cross-DB tolerance for date comparison (default: 1000ms)</div>
8659
8661
 
8660
8662
  <div style="margin-bottom:10px">
8661
8663
  <label style="margin-bottom:6px">Sync Mode</label>
8662
8664
  <div style="display:flex; gap:12px 20px; align-items:center; flex-wrap:wrap">
8663
8665
  <label style="font-weight:normal; margin:0; cursor:pointer">
8664
8666
  <input type="radio" name="syncMode" id="syncModeInitial" value="Initial" checked onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> Initial
8665
- <span style="color:#888; font-size:0.85em">(full clone)</span>
8667
+ <span style="color:var(--theme-color-text-muted, #888); font-size:0.85em">(full clone)</span>
8666
8668
  </label>
8667
8669
  <label style="font-weight:normal; margin:0; cursor:pointer">
8668
8670
  <input type="radio" name="syncMode" id="syncModeOngoing" value="Ongoing" onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> Ongoing
8669
- <span style="color:#888; font-size:0.85em">(delta sync)</span>
8671
+ <span style="color:var(--theme-color-text-muted, #888); font-size:0.85em">(delta sync)</span>
8670
8672
  </label>
8671
8673
  <label style="font-weight:normal; margin:0; cursor:pointer">
8672
8674
  <input type="radio" name="syncMode" id="syncModeOngoingEventualConsistency" value="OngoingEventualConsistency" onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> Eventual
8673
- <span style="color:#888; font-size:0.85em">(time-budgeted back-sync)</span>
8675
+ <span style="color:var(--theme-color-text-muted, #888); font-size:0.85em">(time-budgeted back-sync)</span>
8674
8676
  </label>
8675
8677
  <label style="font-weight:normal; margin:0; cursor:pointer">
8676
8678
  <input type="radio" name="syncMode" id="syncModeTrueUp" value="TrueUp" onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> True-Up
8677
- <span style="color:#888; font-size:0.85em">(linear walk, one-time)</span>
8679
+ <span style="color:var(--theme-color-text-muted, #888); font-size:0.85em">(linear walk, one-time)</span>
8678
8680
  </label>
8679
8681
  <label style="font-weight:normal; margin:0; cursor:pointer">
8680
8682
  <input type="radio" name="syncMode" id="syncModeComparisonOnly" value="ComparisonOnly" onchange="pict.views['DataCloner-Sync'].onSyncModeChanged()"> Compare
8681
- <span style="color:#888; font-size:0.85em">(diff report, no sync)</span>
8683
+ <span style="color:var(--theme-color-text-muted, #888); font-size:0.85em">(diff report, no sync)</span>
8682
8684
  </label>
8683
8685
  </div>
8684
8686
  </div>
@@ -8690,7 +8692,7 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8690
8692
  <input type="number" id="backSyncTimeLimit" value="30000" min="1000" max="600000" style="margin-bottom:0">
8691
8693
  </div>
8692
8694
  </div>
8693
- <div style="font-size:0.8em; color:#888; padding-left:4px">Milliseconds devoted to backwards bisection per entity before pulling new records (default: 30000)</div>
8695
+ <div style="font-size:0.8em; color:var(--theme-color-text-muted, #888); padding-left:4px">Milliseconds devoted to backwards bisection per entity before pulling new records (default: 30000)</div>
8694
8696
  </div>
8695
8697
 
8696
8698
  <div id="syncModeOptions-TrueUp" style="display:none; margin-bottom:10px">
@@ -8700,7 +8702,7 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8700
8702
  <input type="number" id="trueUpPageSize" value="500" min="10" max="10000" style="margin-bottom:0">
8701
8703
  </div>
8702
8704
  </div>
8703
- <div style="font-size:0.8em; color:#888; padding-left:4px">Records per page for the linear keyset walk (default: 500)</div>
8705
+ <div style="font-size:0.8em; color:var(--theme-color-text-muted, #888); padding-left:4px">Records per page for the linear keyset walk (default: 500)</div>
8704
8706
  </div>
8705
8707
 
8706
8708
  <div class="checkbox-row">
@@ -8730,7 +8732,7 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8730
8732
  <div id="syncProgress"></div>
8731
8733
 
8732
8734
  <!-- Sync Report (appears after sync completes) -->
8733
- <div id="syncReportSection" style="display:none; margin-top:16px; padding-top:16px; border-top:2px solid #ddd">
8735
+ <div id="syncReportSection" style="display:none; margin-top:16px; padding-top:16px; border-top:2px solid var(--theme-color-border-default, #ddd)">
8734
8736
  <h3 style="margin:0 0 12px; font-size:1.1em">Sync Report</h3>
8735
8737
 
8736
8738
  <!-- Summary cards -->
@@ -8819,7 +8821,7 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8819
8821
  renderDataTable(pRows) {
8820
8822
  let tmpContainer = document.getElementById('viewDataContainer');
8821
8823
  if (!pRows || pRows.length === 0) {
8822
- tmpContainer.innerHTML = '<p style="color:#666; font-size:0.9em; padding:8px">No rows.</p>';
8824
+ tmpContainer.innerHTML = '<p style="color:var(--theme-color-text-secondary, #666); font-size:0.9em; padding:8px">No rows.</p>';
8823
8825
  return;
8824
8826
  }
8825
8827
 
@@ -8852,9 +8854,9 @@ select { background: #fff; width: 100%; padding: 8px 12px; border: 1px solid #cc
8852
8854
  DefaultDestinationAddress: '#DataCloner-Section-ViewData',
8853
8855
  CSS: /*css*/`
8854
8856
  .data-table { width: 100%; border-collapse: collapse; font-size: 0.8em; font-family: monospace; }
8855
- .data-table th { background: #f8f9fa; font-weight: 600; text-align: left; padding: 4px 8px; border: 1px solid #ddd; white-space: nowrap; position: sticky; top: 0; }
8856
- .data-table td { padding: 4px 8px; border: 1px solid #eee; white-space: nowrap; max-width: 300px; overflow: hidden; text-overflow: ellipsis; }
8857
- .data-table tr:nth-child(even) { background: #fafafa; }
8857
+ .data-table th { background: #f8f9fa; font-weight: 600; text-align: left; padding: 4px 8px; border: 1px solid var(--theme-color-border-default, #ddd); white-space: nowrap; position: sticky; top: 0; }
8858
+ .data-table td { padding: 4px 8px; border: 1px solid var(--theme-color-border-light, #eee); white-space: nowrap; max-width: 300px; overflow: hidden; text-overflow: ellipsis; }
8859
+ .data-table tr:nth-child(even) { background: var(--theme-color-background-secondary, #fafafa); }
8858
8860
  .data-table tr:hover { background: #f0f7ff; }
8859
8861
  `,
8860
8862
  Templates: [{