socialcalc-ai 1.0.4 → 1.0.10

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 (45) hide show
  1. package/README.md +140 -8
  2. package/components/AgentModal/AgentModal.css +125 -36
  3. package/components/AgentModal/AgentModal.tsx +248 -31
  4. package/core/README.md +959 -0
  5. package/core/editor-widgets.js +3327 -0
  6. package/core/environment.js +582 -0
  7. package/core/format-number.js +3 -5944
  8. package/core/formula-functions.js +3911 -0
  9. package/core/formula.js +1797 -1367
  10. package/core/index.js +17 -7
  11. package/core/popup.js +1678 -0
  12. package/core/render.js +2290 -0
  13. package/core/{core.js → sheet.js} +5 -2641
  14. package/core/spreadsheet-control.js +14 -3288
  15. package/core/table-editor.js +7 -3289
  16. package/core/touch.js +422 -0
  17. package/core/workbook.js +2775 -0
  18. package/modules/agent.js +4 -1
  19. package/modules/device.js +3 -10
  20. package/modules/editable-cells.js +4 -9
  21. package/modules/events.js +363 -0
  22. package/modules/exporters.js +164 -11
  23. package/modules/formatting.js +156 -169
  24. package/modules/grid-lines.js +4 -9
  25. package/modules/history.js +13 -17
  26. package/modules/horizontal-scroll.js +4 -9
  27. package/modules/init.js +3 -9
  28. package/modules/invoice.js +4 -10
  29. package/modules/listeners.js +39 -61
  30. package/modules/logos.js +4 -11
  31. package/modules/pdf-export.js +408 -0
  32. package/modules/plugin-manager.js +13 -9
  33. package/modules/prompts.js +22 -48
  34. package/modules/row-col-headers.js +4 -9
  35. package/modules/runtime.js +544 -0
  36. package/modules/share.js +444 -0
  37. package/modules/sheets.js +18 -15
  38. package/modules/touch-scroll.js +4 -9
  39. package/modules/utils.js +10 -11
  40. package/modules/weight.js +4 -11
  41. package/package.json +31 -2
  42. package/pdf-export.d.ts +53 -0
  43. package/pdf-export.js +3 -0
  44. package/share.d.ts +96 -0
  45. package/share.js +3 -0
package/README.md CHANGED
@@ -18,6 +18,7 @@ Derived from Dan Bricklin's proven, industrial-strength **SocialCalc** engine, `
18
18
  - [Quick Start in React / Ionic](#-quick-start-in-react--ionic)
19
19
  - [Quick Start in Vanilla JavaScript](#-quick-start-in-vanilla-javascript)
20
20
  - [Architecture Overview](#-architecture-overview)
21
+ - [Core Engine Reference (`core/README.md`)](core/README.md)
21
22
  - [UI Components](#-ui-components)
22
23
  - [CellEditModal](#1-celleditmodal)
23
24
  - [HorizontalScrollBar](#2-horizontalscrollbar)
@@ -37,6 +38,8 @@ Derived from Dan Bricklin's proven, industrial-strength **SocialCalc** engine, `
37
38
  - [Invoice Utilities](#9-invoice-utilities-modulesinvoicejs)
38
39
  - [AI Agent Plugin (Text Editor Agent)](#10-ai-agent-plugin-text-editor-agent-modulesagentjs)
39
40
  - [Cell Formatting & Display Suite](#11-cell-formatting--display-suite)
41
+ - [Offline PDF Export Plugin](#12-offline-pdf-export-plugin-socialcalc-aipdf-export)
42
+ - [Share, Email & Print Plugin](#13-share-email--print-plugin-socialcalc-aishare)
40
43
  - [Event-Driven Architecture](#-event-driven-architecture)
41
44
  - [AI & MultiSheet Calc (MSC) Integration](#-ai--multisheet-calc-msc-integration)
42
45
  - [TypeScript Support](#-typescript-support)
@@ -229,14 +232,21 @@ socialcalc-ai/
229
232
  ├── index.js # Main entry point: aggregates core, modules & UI
230
233
  ├── index.d.ts # Complete TypeScript typings
231
234
  ├── package.json # Standalone package definition
232
- ├── core/ # Core calculation engine & DOM table rendering
233
- │ ├── constants.js # Formatting codes, default styles & limits
234
- │ ├── core.js # Spreadsheet sheet model, cell evaluation, formula AST
235
- │ ├── formula.js # Built-in math, logical, string, financial functions
236
- │ ├── format-number.js # Numeric and date formatting routines
237
- │ ├── spreadsheet-control.js # Spreadsheet control lifecycle & pane management
238
- │ ├── table-editor.js # DOM table editor layout & cursor rendering
239
- │ └── index.js # Assembled core SocialCalc singleton export
235
+ ├── core/ # Spreadsheet engine - full reference in core/README.md
236
+ │ ├── index.js # Imports the modules below in load order; exports the SocialCalc singleton
237
+ │ ├── constants.js # UI strings (localization), default styles & sizes
238
+ │ ├── sheet.js # Cell & Sheet model, save format, command language, recalc, undo, clipboard
239
+ │ ├── render.js # RenderContext (HTML table), coordinate/DOM helpers, value display, CSV/HTML conversion
240
+ │ ├── touch.js # Touch detection & gesture handling
241
+ │ ├── format-number.js # Excel-style number and date format strings
242
+ │ ├── formula.js # Formula tokenizer, parser, evaluator & function registry
243
+ │ ├── formula-functions.js # 109 built-in functions (stat, math, text, date, lookup, financial)
244
+ │ ├── popup.js # Popup list & color chooser widgets
245
+ │ ├── table-editor.js # Interactive grid: cursor, selection, scrolling, input box, cell actions
246
+ │ ├── editor-widgets.js # Cell handles, scrollbars, drag/tooltip/button/wheel registries, keyboard
247
+ │ ├── spreadsheet-control.js # Spreadsheet UI: toolbar tabs, formula bar, settings, save/load
248
+ │ ├── workbook.js # Multi-sheet WorkBook & WorkBookControl, sheet bar, MSC save/load
249
+ │ └── environment.js # Loaded last: JSON polyfill, app overrides, server/worker shims
240
250
  ├── modules/ # Modular functional features & plugins
241
251
  │ ├── plugin-manager.js # Central registry for dynamic SocialCalc plugins
242
252
  │ ├── grid-lines.js # Cell border grid-lines plugin
@@ -605,6 +615,22 @@ AppGeneral.switchSheet("Sheet2");
605
615
  AppGeneral.addNewSheet("Expenses");
606
616
  AppGeneral.deleteSheet("Sheet3");
607
617
  AppGeneral.renameSheet("Sheet1", "Overview");
618
+
619
+ // CSV files (UTF-8 BOM so Excel opens them correctly)
620
+ await AppGeneral.exportCurrentSheetAsCSV({ filename: "invoice" }); // downloads invoice.csv
621
+ const csvBlob = await AppGeneral.exportCurrentSheetAsCSV({ returnBlob: true });
622
+ AppGeneral.cleanCSV(csvData); // drop blank lines
623
+ AppGeneral.convertToCSV([["Item", "Price"], ["Pen", 2]]);
624
+
625
+ // MSC workbook files
626
+ await AppGeneral.exportMSC({ filename: "workbook" }); // raw save data, workbook.msc
627
+ await AppGeneral.exportMSC({ extension: "json", includeAppMapping: true }); // { msc, appMapping } template
628
+ const { msc, appMapping } = AppGeneral.parseMSCFile(fileText); // accepts either form
629
+ AppGeneral.loadWorkbookData(msc);
630
+
631
+ // File helpers
632
+ AppGeneral.downloadBlob(blob, "file.pdf");
633
+ const base64 = await AppGeneral.blobToBase64(blob); // for Capacitor Filesystem.writeFile
608
634
  ```
609
635
 
610
636
  ### 9. Invoice Utilities (`modules/invoice.js`)
@@ -687,6 +713,104 @@ SocialCalc provides built-in formatters for commercial, financial, and date/time
687
713
  - **Percentage Formats**: Automatic conversion of decimals/fractions into clean percentage percentages (`15.00%`).
688
714
  - **Date & Time Formats**: ISO timestamps, short date (`MM/DD/YYYY`), medium date (`DD-MMM-YYYY`), and 12/24-hour clocks.
689
715
 
716
+ ### 12. Offline PDF Export Plugin (`socialcalc-ai/pdf-export`)
717
+ Generates PDFs of one sheet or the whole workbook on the device, with no server involved, so it works offline and inside Capacitor apps. Pages are split on row boundaries, chart canvases in the live editor are included, and every page gets a timestamp header, a footer label and `Page X of Y`.
718
+
719
+ The plugin is opt-in: it is not part of the main `socialcalc-ai` entry, so apps that do not import it do not need its dependencies. To use it, install the optional peer dependencies:
720
+
721
+ ```bash
722
+ npm install jspdf html2canvas
723
+ ```
724
+
725
+ ```ts
726
+ import * as AppGeneral from "socialcalc-ai";
727
+ import {
728
+ configurePdfExport,
729
+ exportHTMLAsPDF,
730
+ exportAllSheetsAsPDF,
731
+ exportCurrentSheetAsPDF,
732
+ exportWorkbookAsPDF,
733
+ pdfBlobToBase64,
734
+ } from "socialcalc-ai/pdf-export";
735
+
736
+ // Optional app-wide defaults (per-call options still win)
737
+ configurePdfExport({ footerText: "Invoice", format: "a4", margin: 10 });
738
+
739
+ // Download the active sheet as invoice.pdf
740
+ await exportCurrentSheetAsPDF({ filename: "invoice", onProgress: console.log });
741
+
742
+ // Or pass HTML yourself and get a Blob back (e.g. to share with Capacitor)
743
+ const blob = await exportHTMLAsPDF(AppGeneral.getCurrentHTMLContent(), { returnBlob: true });
744
+ const base64 = await pdfBlobToBase64(blob); // ready for Filesystem.writeFile
745
+
746
+ // All sheets into one PDF, each sheet starting on a new page
747
+ await exportWorkbookAsPDF({ filename: "all_invoices" });
748
+ await exportAllSheetsAsPDF(AppGeneral.getAllSheetsData(), { returnBlob: true });
749
+ ```
750
+
751
+ | Option | Default | Description |
752
+ |---|---|---|
753
+ | `filename` | `"document"` / `"all_sheets"` | File name without `.pdf` |
754
+ | `format` | `"a4"` | `"a4"`, `"letter"` or `"legal"` |
755
+ | `orientation` | `"portrait"` | `"portrait"` or `"landscape"` |
756
+ | `margin` | `10` | Page margin in mm |
757
+ | `quality` | `4` (one sheet) / `2` (all sheets) | html2canvas render scale |
758
+ | `headerText` | `null` | Top-left text; `null` prints the current date and time, `""` hides it |
759
+ | `footerText` | `""` | Bottom-left text on every page |
760
+ | `showPageNumbers` | `true` | Print `Page X of Y` bottom-right |
761
+ | `editorElementId` | `"tableeditor"` | Live editor element whose chart canvases are copied |
762
+ | `returnBlob` | `false` | Return a `Blob` instead of downloading the file |
763
+ | `onProgress` | — | Called with progress messages |
764
+
765
+ Importing the module registers it with the Plugin Manager as `"pdfExport"`, so `disablePlugin("pdfExport")` / `enablePlugin("pdfExport", defaults)` and `configurePlugin("pdfExport", defaults)` work too. Export calls reject while the plugin is disabled.
766
+
767
+ ### 13. Share, Email & Print Plugin (`socialcalc-ai/share`)
768
+ Saves, shares, emails and prints exports the right way for the platform the app is running on, detected from the Capacitor runtime:
769
+
770
+ | | `saveFile` | `shareFile` | `sendEmail` / `emailCurrentSheet` | `printHTML` / `printCurrentSheet` |
771
+ |---|---|---|---|---|
772
+ | **iOS** | Cache file + share sheet | Share sheet | Share sheet with the attachment (PDF by default) | Native printer (AirPrint); PDF first, then HTML |
773
+ | **Android** | Cache file + share sheet | Share sheet | EmailComposer with the attachment (HTML by default) | Native printer (PrintService); PDF first, then HTML |
774
+ | **Web** | Download | Web Share API with the file, else download | Web Share with the file, else `mailto:` plus a download of the attachment | Hidden iframe + print dialog (no pop-up) |
775
+
776
+ The plugin does not import any Capacitor packages. On iOS and Android, pass in the ones your app has installed. On the web it needs nothing:
777
+
778
+ ```bash
779
+ npm install @capacitor/filesystem @capacitor/share capacitor-email-composer @bcyesil/capacitor-plugin-printer
780
+ ```
781
+
782
+ ```ts
783
+ import { Filesystem, Directory, Encoding } from "@capacitor/filesystem";
784
+ import { Share } from "@capacitor/share";
785
+ import { EmailComposer } from "capacitor-email-composer";
786
+ import { Printer } from "@bcyesil/capacitor-plugin-printer";
787
+ import "socialcalc-ai/pdf-export"; // optional: lets email and print use PDFs
788
+ import {
789
+ configureShare, getShareCapabilities,
790
+ saveFile, shareFile, emailCurrentSheet, sendEmail, printCurrentSheet,
791
+ } from "socialcalc-ai/share";
792
+ import { exportCurrentSheetAsPDF } from "socialcalc-ai/pdf-export";
793
+
794
+ configureShare({ Filesystem, Directory, Encoding, Share, EmailComposer, Printer });
795
+
796
+ getShareCapabilities(); // { platform: "ios", emailMethod: "share-sheet", printMethod: "native-printer", ... }
797
+
798
+ // Export + deliver (download on the web, share sheet on devices)
799
+ const pdf = await exportCurrentSheetAsPDF({ returnBlob: true });
800
+ await saveFile({ blob: pdf, filename: "invoice.pdf", dialogTitle: "Share PDF" });
801
+
802
+ // Email the active sheet (attachment format chosen per platform, or set attachmentFormat)
803
+ await emailCurrentSheet({ filename: "INV-001", subject: "Your invoice", body: "Please find it attached." });
804
+
805
+ // Or any email / attachment
806
+ await sendEmail({ to: ["a@b.com"], subject: "Data", attachment: { text: csv, filename: "data.csv", mimeType: "text/csv" } });
807
+
808
+ // Print the active sheet
809
+ await printCurrentSheet({ name: "INV-001", orientation: "portrait" });
810
+ ```
811
+
812
+ Every call resolves to `{ method, platform }` (e.g. `{ method: "email-composer", platform: "android" }`), so the app can show the right message. Temporary cache files are deleted 60 s after sharing (`configureShare({ cleanupAfterMs })`). The plugin registers as `"share"` with the Plugin Manager, and calls reject while it is disabled.
813
+
690
814
  ---
691
815
 
692
816
  ## 📡 Event-Driven Architecture
@@ -766,6 +890,14 @@ import {
766
890
 
767
891
  ## 📦 Release Notes
768
892
 
893
+ ### v1.0.8
894
+ - **Share, Email & Print Plugin**: New opt-in `socialcalc-ai/share` entry for platform-aware (iOS / Android / web) file saving and sharing, email with attachments, and printing. Capacitor plugins are passed in with `configureShare()`.
895
+ - **CSV & MSC exporters**: `exportCurrentSheetAsCSV`, `exportCSV`, `cleanCSV`, `convertToCSV`, `exportMSC`, `parseMSCFile`, `downloadBlob` and `blobToBase64` in the main entry.
896
+ - **Plugin Manager**: `getPlugin(name)` returns a registered plugin, including the `api` it exposes.
897
+
898
+ ### v1.0.7
899
+ - **Offline PDF Export Plugin**: New opt-in `socialcalc-ai/pdf-export` entry that exports the active sheet or the whole workbook to PDF on the device (jsPDF + html2canvas as optional peer dependencies), registered as the `pdfExport` plugin.
900
+
769
901
  ### v1.0.3
770
902
  - **Node.js ESM & Runtime Compatibility**: Enhanced UMD root resolution across all core modules to support `globalThis`, eliminating undefined root errors in Node.js ES module loaders.
771
903
  - **TypeScript Declarations**: Bundled official type declarations (`index.d.ts`) covering all core exports, plugin modules, and React/Ionic UI modal components.
@@ -256,11 +256,11 @@
256
256
 
257
257
  /* --- AI Copilot Box --- */
258
258
  .sc-copilot-box {
259
- background: linear-gradient(180deg, #faf5ff 0%, #ffffff 100%);
260
- border: 1.5px solid #d8b4fe;
259
+ background: var(--sc-copilot-bg, linear-gradient(180deg, #f8fafc 0%, #ffffff 100%));
260
+ border: 1.5px solid var(--sc-copilot-border, #e2e8f0);
261
261
  border-radius: 16px;
262
262
  padding: 18px;
263
- box-shadow: 0 4px 18px rgba(168, 85, 247, 0.06);
263
+ box-shadow: var(--sc-copilot-shadow, 0 4px 16px rgba(15, 23, 42, 0.04));
264
264
  margin-bottom: 20px;
265
265
  position: relative;
266
266
  }
@@ -278,7 +278,7 @@
278
278
  gap: 8px;
279
279
  font-size: 14px;
280
280
  font-weight: 700;
281
- color: #6b21a8;
281
+ color: var(--sc-copilot-title-color, #0f172a);
282
282
  }
283
283
 
284
284
  .sc-copilot-title-badge {
@@ -286,9 +286,9 @@
286
286
  font-weight: 600;
287
287
  padding: 2px 8px;
288
288
  border-radius: 6px;
289
- background: #f3e8ff;
290
- color: #7e22ce;
291
- border: 1px solid #e9d5ff;
289
+ background: var(--sc-copilot-badge-bg, #f1f5f9);
290
+ color: var(--sc-copilot-badge-color, #475569);
291
+ border: 1px solid var(--sc-copilot-badge-border, #e2e8f0);
292
292
  }
293
293
 
294
294
  .sc-copilot-textarea {
@@ -299,9 +299,9 @@
299
299
  line-height: 1.5;
300
300
  padding: 12px 14px;
301
301
  border-radius: 12px;
302
- border: 1.5px solid #e9d5ff;
303
- background: #ffffff;
304
- color: #0f172a;
302
+ border: 1.5px solid var(--sc-copilot-textarea-border, #e2e8f0);
303
+ background: var(--sc-copilot-textarea-bg, #ffffff);
304
+ color: var(--sc-text-main, #0f172a);
305
305
  outline: none;
306
306
  resize: vertical;
307
307
  font-family: inherit;
@@ -309,8 +309,8 @@
309
309
  }
310
310
 
311
311
  .sc-copilot-textarea:focus {
312
- border-color: #9333ea;
313
- box-shadow: 0 0 0 3px rgba(147, 51, 234, 0.15);
312
+ border-color: var(--sc-copilot-focus-border, #2563eb);
313
+ box-shadow: 0 0 0 3px var(--sc-copilot-focus-shadow, rgba(37, 99, 235, 0.12));
314
314
  }
315
315
 
316
316
  .sc-copilot-footer {
@@ -324,7 +324,7 @@
324
324
 
325
325
  .sc-copilot-shortcuts {
326
326
  font-size: 12px;
327
- color: #7e22ce;
327
+ color: var(--sc-copilot-shortcuts-color, #64748b);
328
328
  display: flex;
329
329
  align-items: center;
330
330
  gap: 6px;
@@ -332,13 +332,13 @@
332
332
 
333
333
  .sc-copilot-shortcuts kbd {
334
334
  background: #ffffff;
335
- border: 1px solid #d8b4fe;
335
+ border: 1px solid var(--sc-copilot-shortcuts-border, #e2e8f0);
336
336
  border-radius: 4px;
337
337
  padding: 1px 6px;
338
338
  font-size: 11px;
339
339
  font-family: ui-monospace, monospace;
340
340
  font-weight: 600;
341
- color: #581c87;
341
+ color: #334155;
342
342
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
343
343
  }
344
344
 
@@ -350,10 +350,16 @@
350
350
  margin-top: 10px;
351
351
  }
352
352
 
353
+ .sc-prompt-title {
354
+ font-size: 11px;
355
+ font-weight: 700;
356
+ color: var(--sc-copilot-suggestions-color, #64748b);
357
+ }
358
+
353
359
  .sc-prompt-chip {
354
- background: #ffffff;
355
- border: 1px solid #e9d5ff;
356
- color: #6b21a8;
360
+ background: var(--sc-copilot-chip-bg, #ffffff);
361
+ border: 1px solid var(--sc-copilot-chip-border, #e2e8f0);
362
+ color: var(--sc-copilot-chip-color, #334155);
357
363
  padding: 4px 10px;
358
364
  border-radius: 20px;
359
365
  font-size: 11.5px;
@@ -363,9 +369,9 @@
363
369
  }
364
370
 
365
371
  .sc-prompt-chip:hover {
366
- background: #f3e8ff;
367
- border-color: #c084fc;
368
- color: #581c87;
372
+ background: var(--sc-copilot-chip-hover-bg, #f1f5f9);
373
+ border-color: var(--sc-copilot-chip-hover-border, #cbd5e1);
374
+ color: var(--sc-copilot-chip-hover-color, #0f172a);
369
375
  transform: translateY(-1px);
370
376
  }
371
377
 
@@ -381,15 +387,16 @@
381
387
  font-weight: 600;
382
388
  cursor: pointer;
383
389
  border: none;
384
- background: linear-gradient(135deg, #7c3aed 0%, #9333ea 100%);
385
- color: #ffffff;
386
- box-shadow: 0 4px 12px rgba(124, 58, 237, 0.25);
390
+ background: var(--sc-primary-btn-bg, #0f172a);
391
+ color: var(--sc-primary-btn-color, #ffffff);
392
+ box-shadow: var(--sc-primary-btn-shadow, 0 4px 12px rgba(15, 23, 42, 0.12));
387
393
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
388
394
  }
389
395
 
390
396
  .sc-btn-primary:hover:not(:disabled) {
391
397
  transform: translateY(-1px);
392
- box-shadow: 0 6px 16px rgba(124, 58, 237, 0.35);
398
+ background: var(--sc-primary-btn-hover-bg, #1e293b);
399
+ box-shadow: 0 6px 16px rgba(15, 23, 42, 0.18);
393
400
  filter: brightness(1.05);
394
401
  }
395
402
 
@@ -1116,7 +1123,50 @@
1116
1123
  box-shadow: 0 3px 10px rgba(16, 185, 129, 0.3);
1117
1124
  }
1118
1125
 
1119
- /* --- PURPLE THEME --- */
1126
+ /* --- BLUE / CORPORATE / INDIGO THEME --- */
1127
+ .sc-agent-modal.sc-theme-blue ion-header ion-toolbar,
1128
+ .sc-agent-modal.sc-theme-corporate ion-header ion-toolbar,
1129
+ .sc-agent-modal.sc-theme-indigo ion-header ion-toolbar {
1130
+ --background: linear-gradient(135deg, #0f172a 0%, #1e3a8a 60%, #1d4ed8 100%);
1131
+ }
1132
+ .sc-agent-modal.sc-theme-blue .sc-agent-nav-tab.active,
1133
+ .sc-agent-modal.sc-theme-corporate .sc-agent-nav-tab.active,
1134
+ .sc-agent-modal.sc-theme-indigo .sc-agent-nav-tab.active {
1135
+ background: linear-gradient(135deg, #2563eb 0%, #3b82f6 100%);
1136
+ box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
1137
+ }
1138
+ .sc-agent-modal.sc-theme-blue .sc-copilot-box,
1139
+ .sc-agent-modal.sc-theme-corporate .sc-copilot-box,
1140
+ .sc-agent-modal.sc-theme-indigo .sc-copilot-box {
1141
+ background: linear-gradient(180deg, #f0f7ff 0%, #ffffff 100%);
1142
+ border-color: #bfdbfe;
1143
+ }
1144
+ .sc-agent-modal.sc-theme-blue .sc-copilot-title,
1145
+ .sc-agent-modal.sc-theme-corporate .sc-copilot-title,
1146
+ .sc-agent-modal.sc-theme-indigo .sc-copilot-title {
1147
+ color: #1e40af;
1148
+ }
1149
+ .sc-agent-modal.sc-theme-blue .sc-btn-primary,
1150
+ .sc-agent-modal.sc-theme-corporate .sc-btn-primary,
1151
+ .sc-agent-modal.sc-theme-indigo .sc-btn-primary {
1152
+ background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
1153
+ box-shadow: 0 3px 10px rgba(37, 99, 235, 0.3);
1154
+ }
1155
+ .sc-agent-modal.sc-theme-blue .sc-prompt-chip,
1156
+ .sc-agent-modal.sc-theme-corporate .sc-prompt-chip,
1157
+ .sc-agent-modal.sc-theme-indigo .sc-prompt-chip {
1158
+ border-color: #bfdbfe;
1159
+ color: #1e40af;
1160
+ }
1161
+ .sc-agent-modal.sc-theme-blue .sc-prompt-chip:hover,
1162
+ .sc-agent-modal.sc-theme-corporate .sc-prompt-chip:hover,
1163
+ .sc-agent-modal.sc-theme-indigo .sc-prompt-chip:hover {
1164
+ background: #eff6ff;
1165
+ border-color: #93c5fd;
1166
+ color: #1d4ed8;
1167
+ }
1168
+
1169
+ /* --- PURPLE / VIOLET THEME (Explicit opt-in) --- */
1120
1170
  .sc-agent-modal.sc-theme-purple ion-header ion-toolbar,
1121
1171
  .sc-agent-modal.sc-theme-violet ion-header ion-toolbar {
1122
1172
  --background: linear-gradient(135deg, #3b0764 0%, #581c87 50%, #6b21a8 100%);
@@ -1126,34 +1176,73 @@
1126
1176
  background: linear-gradient(135deg, #7c3aed 0%, #8b5cf6 100%);
1127
1177
  box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);
1128
1178
  }
1179
+ .sc-agent-modal.sc-theme-purple .sc-copilot-box,
1180
+ .sc-agent-modal.sc-theme-violet .sc-copilot-box {
1181
+ background: linear-gradient(180deg, #faf5ff 0%, #ffffff 100%);
1182
+ border-color: #d8b4fe;
1183
+ }
1184
+ .sc-agent-modal.sc-theme-purple .sc-copilot-title,
1185
+ .sc-agent-modal.sc-theme-violet .sc-copilot-title {
1186
+ color: #6b21a8;
1187
+ }
1188
+ .sc-agent-modal.sc-theme-purple .sc-prompt-chip,
1189
+ .sc-agent-modal.sc-theme-violet .sc-prompt-chip {
1190
+ border-color: #e9d5ff;
1191
+ color: #6b21a8;
1192
+ }
1193
+ .sc-agent-modal.sc-theme-purple .sc-prompt-chip:hover,
1194
+ .sc-agent-modal.sc-theme-violet .sc-prompt-chip:hover {
1195
+ background: #f3e8ff;
1196
+ border-color: #c084fc;
1197
+ color: #581c87;
1198
+ }
1129
1199
  .sc-agent-modal.sc-theme-purple .sc-btn-primary,
1130
1200
  .sc-agent-modal.sc-theme-violet .sc-btn-primary {
1131
1201
  background: linear-gradient(135deg, #7c3aed 0%, #8b5cf6 100%);
1132
1202
  box-shadow: 0 3px 10px rgba(139, 92, 246, 0.3);
1133
1203
  }
1134
1204
 
1135
- /* --- SLATE / MONOCHROME THEME --- */
1205
+ /* --- SLATE / MONOCHROME / NEUTRAL THEME --- */
1136
1206
  .sc-agent-modal.sc-theme-slate ion-header ion-toolbar,
1137
- .sc-agent-modal.sc-theme-monochrome ion-header ion-toolbar {
1138
- --background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
1207
+ .sc-agent-modal.sc-theme-monochrome ion-header ion-toolbar,
1208
+ .sc-agent-modal.sc-theme-neutral ion-header ion-toolbar {
1209
+ --background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
1139
1210
  }
1140
1211
  .sc-agent-modal.sc-theme-slate .sc-agent-nav-tab.active,
1141
- .sc-agent-modal.sc-theme-monochrome .sc-agent-nav-tab.active {
1142
- background: linear-gradient(135deg, #334155 0%, #475569 100%);
1143
- box-shadow: 0 4px 12px rgba(51, 65, 85, 0.25);
1212
+ .sc-agent-modal.sc-theme-monochrome .sc-agent-nav-tab.active,
1213
+ .sc-agent-modal.sc-theme-neutral .sc-agent-nav-tab.active {
1214
+ background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
1215
+ box-shadow: 0 4px 12px rgba(15, 23, 42, 0.25);
1144
1216
  }
1145
1217
  .sc-agent-modal.sc-theme-slate .sc-copilot-box,
1146
- .sc-agent-modal.sc-theme-monochrome .sc-copilot-box {
1218
+ .sc-agent-modal.sc-theme-monochrome .sc-copilot-box,
1219
+ .sc-agent-modal.sc-theme-neutral .sc-copilot-box {
1147
1220
  background: linear-gradient(180deg, #f8fafc 0%, #ffffff 100%);
1148
1221
  border-color: #cbd5e1;
1149
1222
  }
1150
1223
  .sc-agent-modal.sc-theme-slate .sc-copilot-title,
1151
- .sc-agent-modal.sc-theme-monochrome .sc-copilot-title {
1224
+ .sc-agent-modal.sc-theme-monochrome .sc-copilot-title,
1225
+ .sc-agent-modal.sc-theme-neutral .sc-copilot-title {
1226
+ color: #0f172a;
1227
+ }
1228
+ .sc-agent-modal.sc-theme-slate .sc-prompt-chip,
1229
+ .sc-agent-modal.sc-theme-monochrome .sc-prompt-chip,
1230
+ .sc-agent-modal.sc-theme-neutral .sc-prompt-chip {
1231
+ border-color: #cbd5e1;
1152
1232
  color: #334155;
1153
1233
  }
1234
+ .sc-agent-modal.sc-theme-slate .sc-prompt-chip:hover,
1235
+ .sc-agent-modal.sc-theme-monochrome .sc-prompt-chip:hover,
1236
+ .sc-agent-modal.sc-theme-neutral .sc-prompt-chip:hover {
1237
+ background: #f1f5f9;
1238
+ border-color: #94a3b8;
1239
+ color: #0f172a;
1240
+ }
1154
1241
  .sc-agent-modal.sc-theme-slate .sc-btn-primary,
1155
- .sc-agent-modal.sc-theme-monochrome .sc-btn-primary {
1156
- background: linear-gradient(135deg, #334155 0%, #475569 100%);
1242
+ .sc-agent-modal.sc-theme-monochrome .sc-btn-primary,
1243
+ .sc-agent-modal.sc-theme-neutral .sc-btn-primary {
1244
+ background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
1245
+ box-shadow: 0 3px 10px rgba(15, 23, 42, 0.2);
1157
1246
  }
1158
1247
 
1159
1248
  /* --- LIGHT / MINIMAL THEME --- */