@powerhousedao/contributor-billing 0.1.41 → 0.1.42

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 (108) hide show
  1. package/dist/document-models/document-models.d.ts.map +1 -1
  2. package/dist/document-models/document-models.js +2 -0
  3. package/dist/document-models/resource-template/gen/document-model.js +25 -25
  4. package/dist/document-models/resource-template/gen/reducer.d.ts +1 -1
  5. package/dist/document-models/resource-template/gen/reducer.d.ts.map +1 -1
  6. package/dist/document-models/resource-template/hooks.d.ts +1 -1
  7. package/dist/document-models/resource-template/hooks.d.ts.map +1 -1
  8. package/dist/document-models/resource-template/module.d.ts +1 -1
  9. package/dist/document-models/resource-template/module.d.ts.map +1 -1
  10. package/dist/document-models/resource-template/reducers/audience-management.d.ts +3 -0
  11. package/dist/document-models/resource-template/reducers/audience-management.d.ts.map +1 -0
  12. package/dist/document-models/resource-template/reducers/audience-management.js +17 -0
  13. package/dist/document-models/resource-template/reducers/facet-preset-management.d.ts +59 -0
  14. package/dist/document-models/resource-template/reducers/facet-preset-management.d.ts.map +1 -0
  15. package/dist/document-models/resource-template/reducers/facet-preset-management.js +52 -0
  16. package/dist/document-models/resource-template/reducers/facet-targeting.d.ts +3 -0
  17. package/dist/document-models/resource-template/reducers/facet-targeting.d.ts.map +1 -0
  18. package/dist/document-models/resource-template/reducers/facet-targeting.js +47 -0
  19. package/dist/document-models/resource-template/reducers/option-group-management.d.ts +3 -0
  20. package/dist/document-models/resource-template/reducers/option-group-management.d.ts.map +1 -0
  21. package/dist/document-models/resource-template/reducers/option-group-management.js +44 -0
  22. package/dist/document-models/resource-template/reducers/service-category-management.d.ts +3 -0
  23. package/dist/document-models/resource-template/reducers/service-category-management.d.ts.map +1 -0
  24. package/dist/document-models/resource-template/reducers/service-category-management.js +10 -0
  25. package/dist/document-models/resource-template/reducers/service-management.d.ts +3 -0
  26. package/dist/document-models/resource-template/reducers/service-management.d.ts.map +1 -0
  27. package/dist/document-models/resource-template/reducers/service-management.js +71 -0
  28. package/dist/document-models/resource-template/reducers/template-management.d.ts +3 -0
  29. package/dist/document-models/resource-template/reducers/template-management.d.ts.map +1 -0
  30. package/dist/document-models/resource-template/reducers/template-management.js +32 -0
  31. package/dist/document-models/resource-template/src/reducers/audience-management.d.ts.map +1 -1
  32. package/dist/document-models/resource-template/src/reducers/audience-management.js +1 -1
  33. package/dist/document-models/resource-template/src/reducers/facet-targeting.d.ts.map +1 -1
  34. package/dist/document-models/resource-template/src/reducers/facet-targeting.js +1 -1
  35. package/dist/document-models/resource-template/src/reducers/option-group-management.d.ts.map +1 -1
  36. package/dist/document-models/resource-template/src/reducers/option-group-management.js +1 -1
  37. package/dist/document-models/resource-template/src/reducers/service-category-management.d.ts.map +1 -1
  38. package/dist/document-models/resource-template/src/reducers/service-category-management.js +1 -1
  39. package/dist/document-models/resource-template/src/reducers/service-management.d.ts.map +1 -1
  40. package/dist/document-models/resource-template/src/reducers/service-management.js +1 -1
  41. package/dist/document-models/resource-template/src/reducers/template-management.d.ts.map +1 -1
  42. package/dist/document-models/resource-template/src/reducers/template-management.js +1 -1
  43. package/dist/document-models/service-offering/gen/document-model.js +5 -5
  44. package/dist/document-models/service-offering/gen/document-schema.d.ts.map +1 -1
  45. package/dist/document-models/service-offering/gen/reducer.d.ts +1 -1
  46. package/dist/document-models/service-offering/gen/reducer.d.ts.map +1 -1
  47. package/dist/document-models/service-offering/gen/schema/types.d.ts +3 -0
  48. package/dist/document-models/service-offering/gen/schema/types.d.ts.map +1 -1
  49. package/dist/document-models/service-offering/gen/schema/zod.d.ts.map +1 -1
  50. package/dist/document-models/service-offering/gen/schema/zod.js +3 -0
  51. package/dist/document-models/service-offering/src/reducers/option-group-management.d.ts.map +1 -1
  52. package/dist/document-models/service-offering/src/reducers/option-group-management.js +11 -8
  53. package/dist/document-models/service-offering/src/reducers/service-management.d.ts.map +1 -1
  54. package/dist/document-models/service-offering/src/reducers/service-management.js +20 -12
  55. package/dist/document-models/service-offering/src/reducers/tier-management.d.ts.map +1 -1
  56. package/dist/document-models/service-offering/src/reducers/tier-management.js +21 -19
  57. package/dist/editors/resource-template-editor/components/FacetTargeting.d.ts +1 -1
  58. package/dist/editors/resource-template-editor/components/FacetTargeting.d.ts.map +1 -1
  59. package/dist/editors/resource-template-editor/components/FacetTargeting.js +526 -19
  60. package/dist/editors/resource-template-editor/components/TemplateInfo.d.ts +1 -1
  61. package/dist/editors/resource-template-editor/components/TemplateInfo.d.ts.map +1 -1
  62. package/dist/editors/resource-template-editor/components/TemplateInfo.js +302 -2
  63. package/dist/editors/resource-template-editor/editor.d.ts.map +1 -1
  64. package/dist/editors/service-offering-editor/components/EditName.js +1 -1
  65. package/dist/editors/service-offering-editor/components/OfferingInfo.d.ts +1 -1
  66. package/dist/editors/service-offering-editor/components/OfferingInfo.d.ts.map +1 -1
  67. package/dist/editors/service-offering-editor/components/OfferingProgress.d.ts +10 -0
  68. package/dist/editors/service-offering-editor/components/OfferingProgress.d.ts.map +1 -0
  69. package/dist/editors/service-offering-editor/components/OfferingProgress.js +240 -0
  70. package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.d.ts +1 -1
  71. package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.d.ts.map +1 -1
  72. package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.js +111 -4
  73. package/dist/editors/service-offering-editor/components/ScopeAndFacets.d.ts +1 -1
  74. package/dist/editors/service-offering-editor/components/ScopeAndFacets.d.ts.map +1 -1
  75. package/dist/editors/service-offering-editor/components/ServiceCatalog.d.ts +1 -1
  76. package/dist/editors/service-offering-editor/components/ServiceCatalog.d.ts.map +1 -1
  77. package/dist/editors/service-offering-editor/components/ServiceCatalog.js +318 -1
  78. package/dist/editors/service-offering-editor/components/ServicesList.d.ts +1 -1
  79. package/dist/editors/service-offering-editor/components/ServicesList.d.ts.map +1 -1
  80. package/dist/editors/service-offering-editor/components/ServicesList.js +1 -1
  81. package/dist/editors/service-offering-editor/components/TheMatrix.d.ts +1 -1
  82. package/dist/editors/service-offering-editor/components/TheMatrix.d.ts.map +1 -1
  83. package/dist/editors/service-offering-editor/components/TheMatrix.js +548 -13
  84. package/dist/editors/service-offering-editor/components/TierDefinition.d.ts +1 -1
  85. package/dist/editors/service-offering-editor/components/TierDefinition.d.ts.map +1 -1
  86. package/dist/editors/service-offering-editor/components/TierDefinition.js +406 -4
  87. package/dist/editors/service-offering-editor/components/TiersList.d.ts +1 -1
  88. package/dist/editors/service-offering-editor/components/TiersList.d.ts.map +1 -1
  89. package/dist/editors/service-offering-editor/editor.d.ts.map +1 -1
  90. package/dist/editors/service-offering-editor/editor.js +2 -2
  91. package/dist/powerhouse.manifest.json +18 -0
  92. package/dist/subgraphs/index.d.ts +1 -0
  93. package/dist/subgraphs/index.d.ts.map +1 -1
  94. package/dist/subgraphs/index.js +1 -0
  95. package/dist/subgraphs/resource-template/index.d.ts +11 -0
  96. package/dist/subgraphs/resource-template/index.d.ts.map +1 -0
  97. package/dist/subgraphs/resource-template/index.js +11 -0
  98. package/dist/subgraphs/resource-template/resolvers.d.ts +3 -0
  99. package/dist/subgraphs/resource-template/resolvers.d.ts.map +1 -0
  100. package/dist/subgraphs/resource-template/resolvers.js +312 -0
  101. package/dist/subgraphs/resource-template/schema.d.ts +3 -0
  102. package/dist/subgraphs/resource-template/schema.d.ts.map +1 -0
  103. package/dist/subgraphs/resource-template/schema.js +262 -0
  104. package/dist/subgraphs/service-offering/resolvers.d.ts.map +1 -1
  105. package/dist/subgraphs/service-offering/resolvers.js +24 -0
  106. package/dist/subgraphs/service-offering/schema.d.ts.map +1 -1
  107. package/dist/subgraphs/service-offering/schema.js +21 -0
  108. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateInfo.d.ts","sourceRoot":"","sources":["../../../../editors/resource-template-editor/components/TemplateInfo.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,EAEvB,MAAM,yDAAyD,CAAC;AAWjE,UAAU,iBAAiB;IACzB,QAAQ,EAAE,wBAAwB,CAAC;IACnC,QAAQ,EAAE,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;CACpD;AAkBD,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CAikBrE"}
1
+ {"version":3,"file":"TemplateInfo.d.ts","sourceRoot":"","sources":["../../../../editors/resource-template-editor/components/TemplateInfo.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,EAEvB,MAAM,sEAAsE,CAAC;AAW9E,UAAU,iBAAiB;IACzB,QAAQ,EAAE,wBAAwB,CAAC;IACnC,QAAQ,EAAE,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;CACpD;AAuJD,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CAwuBrE"}
@@ -16,6 +16,130 @@ const AUDIENCE_PRESETS = [
16
16
  { label: "Contributors", color: "#10b981" },
17
17
  { label: "Investors", color: "#6366f1" },
18
18
  ];
19
+ const SETUP_SERVICE_TEMPLATES = {
20
+ "Entity Formation": [
21
+ {
22
+ title: "Entity Formation",
23
+ description: "Legal entity registration and setup",
24
+ icon: "🏛️",
25
+ },
26
+ {
27
+ title: "Registered Agent",
28
+ description: "Registered agent designation for one year",
29
+ icon: "📋",
30
+ },
31
+ {
32
+ title: "Operating Agreement",
33
+ description: "Custom operating agreement drafting",
34
+ icon: "📜",
35
+ },
36
+ {
37
+ title: "EIN Application",
38
+ description: "Federal tax ID number application",
39
+ icon: "🔢",
40
+ },
41
+ {
42
+ title: "Banking Resolution",
43
+ description: "Corporate banking resolution preparation",
44
+ icon: "🏦",
45
+ },
46
+ ],
47
+ "Initial Setup": [
48
+ {
49
+ title: "Corporate Seal & Kit",
50
+ description: "Official corporate seal and documentation kit",
51
+ icon: "🔏",
52
+ },
53
+ {
54
+ title: "Initial Minutes",
55
+ description: "Organizational meeting minutes preparation",
56
+ icon: "📝",
57
+ },
58
+ {
59
+ title: "Bylaws Drafting",
60
+ description: "Corporate bylaws and governance documents",
61
+ icon: "⚖️",
62
+ },
63
+ {
64
+ title: "Stock Certificates",
65
+ description: "Initial stock certificate issuance",
66
+ icon: "📃",
67
+ },
68
+ {
69
+ title: "Compliance Calendar",
70
+ description: "Annual compliance calendar setup",
71
+ icon: "📅",
72
+ },
73
+ ],
74
+ };
75
+ const RECURRING_SERVICE_TEMPLATES = {
76
+ "Compliance & Governance": [
77
+ {
78
+ title: "Annual Compliance Review",
79
+ description: "Yearly compliance status check and filings",
80
+ icon: "✓",
81
+ },
82
+ {
83
+ title: "Board Meeting Minutes",
84
+ description: "Quarterly board meeting documentation",
85
+ icon: "📋",
86
+ },
87
+ {
88
+ title: "Regulatory Filing Support",
89
+ description: "Ongoing regulatory submission assistance",
90
+ icon: "📊",
91
+ },
92
+ {
93
+ title: "Corporate Record Maintenance",
94
+ description: "Continuous corporate record keeping",
95
+ icon: "🗄️",
96
+ },
97
+ ],
98
+ "Accounting & Finance": [
99
+ {
100
+ title: "Bookkeeping",
101
+ description: "Monthly bookkeeping and reconciliation",
102
+ icon: "📚",
103
+ },
104
+ {
105
+ title: "Financial Reporting",
106
+ description: "Quarterly financial statement preparation",
107
+ icon: "📈",
108
+ },
109
+ {
110
+ title: "Tax Preparation",
111
+ description: "Annual tax return preparation and filing",
112
+ icon: "💰",
113
+ },
114
+ {
115
+ title: "Payroll Processing",
116
+ description: "Bi-weekly payroll management",
117
+ icon: "💵",
118
+ },
119
+ ],
120
+ "Advisory & Support": [
121
+ {
122
+ title: "Dedicated Account Manager",
123
+ description: "Personal point of contact for all needs",
124
+ icon: "👤",
125
+ },
126
+ {
127
+ title: "Priority Support",
128
+ description: "Fast-track support response times",
129
+ icon: "⚡",
130
+ },
131
+ {
132
+ title: "Strategic Consulting",
133
+ description: "Quarterly business strategy sessions",
134
+ icon: "🎯",
135
+ },
136
+ {
137
+ title: "Legal Document Review",
138
+ description: "Contract and document review services",
139
+ icon: "🔍",
140
+ },
141
+ ],
142
+ };
19
143
  export function TemplateInfo({ document, dispatch }) {
20
144
  const { state } = document;
21
145
  const globalState = state.global;
@@ -32,6 +156,8 @@ export function TemplateInfo({ document, dispatch }) {
32
156
  const [newRecurringService, setNewRecurringService] = useState("");
33
157
  const [newAudienceLabel, setNewAudienceLabel] = useState("");
34
158
  const [showAudienceInput, setShowAudienceInput] = useState(false);
159
+ const [showSetupTemplates, setShowSetupTemplates] = useState(false);
160
+ const [showRecurringTemplates, setShowRecurringTemplates] = useState(false);
35
161
  const setupServiceInputRef = useRef(null);
36
162
  const recurringServiceInputRef = useRef(null);
37
163
  useEffect(() => {
@@ -162,6 +288,24 @@ export function TemplateInfo({ document, dispatch }) {
162
288
  lastModified: new Date().toISOString(),
163
289
  }));
164
290
  };
291
+ const handleAddSetupFromTemplate = (template) => {
292
+ if (globalState.setupServices.includes(template.title))
293
+ return;
294
+ const updatedServices = [...globalState.setupServices, template.title];
295
+ dispatch(setSetupServices({
296
+ services: updatedServices,
297
+ lastModified: new Date().toISOString(),
298
+ }));
299
+ };
300
+ const handleAddRecurringFromTemplate = (template) => {
301
+ if (globalState.recurringServices.includes(template.title))
302
+ return;
303
+ const updatedServices = [...globalState.recurringServices, template.title];
304
+ dispatch(setRecurringServices({
305
+ services: updatedServices,
306
+ lastModified: new Date().toISOString(),
307
+ }));
308
+ };
165
309
  const currentStatus = STATUS_OPTIONS.find((s) => s.value === formData.status);
166
310
  const availablePresets = AUDIENCE_PRESETS.filter((preset) => !globalState.targetAudiences.some((a) => a.label === preset.label));
167
311
  return (_jsxs(_Fragment, { children: [_jsx("style", { children: styles }), _jsxs("div", { className: "template-editor", children: [_jsxs("section", { className: "template-editor__hero", children: [_jsxs("div", { className: "template-editor__thumbnail-area", children: [_jsxs("div", { className: "template-editor__thumbnail", style: {
@@ -179,10 +323,16 @@ export function TemplateInfo({ document, dispatch }) {
179
323
  handleAddAudience(newAudienceLabel);
180
324
  if (e.key === "Escape")
181
325
  setShowAudienceInput(false);
182
- }, placeholder: "Audience name...", className: "template-editor__audience-input", autoFocus: true }), _jsx("button", { type: "button", onClick: () => handleAddAudience(newAudienceLabel), className: "template-editor__audience-add-btn", children: "Add" })] })) : (_jsxs("button", { type: "button", onClick: () => setShowAudienceInput(true), className: "template-editor__add-audience-btn", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 5v14M5 12h14", strokeWidth: "2" }) }), "Add Audience"] }))] }), availablePresets.length > 0 && (_jsxs("div", { className: "template-editor__audience-presets", children: [_jsx("span", { className: "template-editor__presets-label", children: "Quick add:" }), availablePresets.slice(0, 4).map((preset) => (_jsx("button", { type: "button", onClick: () => handleAddAudience(preset.label, preset.color), className: "template-editor__preset-btn", style: { color: preset.color }, children: preset.label }, preset.label)))] })), _jsx("textarea", { value: formData.summary, onChange: (e) => handleFieldChange("summary", e.target.value), onBlur: handleInfoBlur, className: "template-editor__summary", placeholder: "Brief summary of your resource template...", rows: 2 })] })] }), _jsxs("section", { className: "template-editor__card template-editor__card--full", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--violet", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M4 6h16M4 12h16M4 18h10" }) }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Description" }), _jsx("p", { className: "template-editor__card-subtitle", children: "Detailed description of your resource template" })] })] }), _jsx("textarea", { value: formData.description, onChange: (e) => handleFieldChange("description", e.target.value), onBlur: handleInfoBlur, className: "template-editor__textarea", placeholder: "Provide a comprehensive description of your resource template, including what makes it unique and valuable...", rows: 4 })] }), _jsxs("div", { className: "template-editor__grid", children: [_jsxs("section", { className: "template-editor__card", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--emerald", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }), _jsx("path", { d: "M2 17l10 5 10-5" }), _jsx("path", { d: "M2 12l10 5 10-5" })] }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Formation & Setup" }), _jsx("p", { className: "template-editor__card-subtitle", children: "One-time setup services" })] })] }), _jsxs("div", { className: "template-editor__services", children: [globalState.setupServices.map((service, index) => (_jsxs("div", { className: "template-editor__service", children: [_jsx("span", { className: "template-editor__service-bullet" }), _jsx("span", { className: "template-editor__service-text", children: service }), _jsx("button", { type: "button", onClick: () => handleRemoveSetupService(index), className: "template-editor__service-remove", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", strokeWidth: "2" }) }) })] }, index))), _jsxs("div", { className: "template-editor__add-service", children: [_jsx("span", { className: "template-editor__service-bullet template-editor__service-bullet--ghost" }), _jsx("input", { ref: setupServiceInputRef, type: "text", value: newSetupService, onChange: (e) => setNewSetupService(e.target.value), onKeyDown: (e) => {
326
+ }, placeholder: "Audience name...", className: "template-editor__audience-input", autoFocus: true }), _jsx("button", { type: "button", onClick: () => handleAddAudience(newAudienceLabel), className: "template-editor__audience-add-btn", children: "Add" })] })) : (_jsxs("button", { type: "button", onClick: () => setShowAudienceInput(true), className: "template-editor__add-audience-btn", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 5v14M5 12h14", strokeWidth: "2" }) }), "Add Audience"] }))] }), availablePresets.length > 0 && (_jsxs("div", { className: "template-editor__audience-presets", children: [_jsx("span", { className: "template-editor__presets-label", children: "Quick add:" }), availablePresets.slice(0, 4).map((preset) => (_jsx("button", { type: "button", onClick: () => handleAddAudience(preset.label, preset.color), className: "template-editor__preset-btn", style: { color: preset.color }, children: preset.label }, preset.label)))] })), _jsx("textarea", { value: formData.summary, onChange: (e) => handleFieldChange("summary", e.target.value), onBlur: handleInfoBlur, className: "template-editor__summary", placeholder: "Brief summary of your resource template...", rows: 2 })] })] }), _jsxs("section", { className: "template-editor__card template-editor__card--full", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--violet", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M4 6h16M4 12h16M4 18h10" }) }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Description" }), _jsx("p", { className: "template-editor__card-subtitle", children: "Detailed description of your resource template" })] })] }), _jsx("textarea", { value: formData.description, onChange: (e) => handleFieldChange("description", e.target.value), onBlur: handleInfoBlur, className: "template-editor__textarea", placeholder: "Provide a comprehensive description of your resource template, including what makes it unique and valuable...", rows: 4 })] }), _jsxs("div", { className: "template-editor__grid", children: [_jsxs("section", { className: "template-editor__card", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--emerald", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }), _jsx("path", { d: "M2 17l10 5 10-5" }), _jsx("path", { d: "M2 12l10 5 10-5" })] }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Formation & Setup" }), _jsx("p", { className: "template-editor__card-subtitle", children: "One-time setup services" })] }), _jsxs("button", { type: "button", onClick: () => setShowSetupTemplates(!showSetupTemplates), className: `template-editor__templates-toggle ${showSetupTemplates ? "template-editor__templates-toggle--active" : ""}`, children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z" }) }), "Templates"] })] }), showSetupTemplates && (_jsx("div", { className: "template-editor__templates-panel", children: Object.entries(SETUP_SERVICE_TEMPLATES).map(([category, templates]) => (_jsxs("div", { className: "template-editor__template-category", children: [_jsx("span", { className: "template-editor__template-category-label", children: category }), _jsx("div", { className: "template-editor__template-items", children: templates.map((template) => {
327
+ const isAdded = globalState.setupServices.includes(template.title);
328
+ return (_jsxs("button", { type: "button", onClick: () => handleAddSetupFromTemplate(template), disabled: isAdded, className: `template-editor__template-item ${isAdded ? "template-editor__template-item--added" : ""}`, title: template.description, children: [_jsx("span", { className: "template-editor__template-icon", children: template.icon }), _jsx("span", { className: "template-editor__template-title", children: template.title }), isAdded && (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "template-editor__template-check", children: _jsx("path", { d: "M5 12l5 5L20 7" }) }))] }, template.title));
329
+ }) })] }, category))) })), _jsxs("div", { className: "template-editor__services", children: [globalState.setupServices.map((service, index) => (_jsxs("div", { className: "template-editor__service", children: [_jsx("span", { className: "template-editor__service-bullet" }), _jsx("span", { className: "template-editor__service-text", children: service }), _jsx("button", { type: "button", onClick: () => handleRemoveSetupService(index), className: "template-editor__service-remove", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", strokeWidth: "2" }) }) })] }, index))), _jsxs("div", { className: "template-editor__add-service", children: [_jsx("span", { className: "template-editor__service-bullet template-editor__service-bullet--ghost" }), _jsx("input", { ref: setupServiceInputRef, type: "text", value: newSetupService, onChange: (e) => setNewSetupService(e.target.value), onKeyDown: (e) => {
183
330
  if (e.key === "Enter")
184
331
  handleAddSetupService();
185
- }, placeholder: "Add a setup service...", className: "template-editor__service-new-input" }), newSetupService && (_jsx("button", { type: "button", onClick: handleAddSetupService, className: "template-editor__service-add-btn", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 5v14M5 12h14", strokeWidth: "2" }) }) }))] })] })] }), _jsxs("section", { className: "template-editor__card", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--amber", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("path", { d: "M12 8v4l3 3" }), _jsx("circle", { cx: "12", cy: "12", r: "9" })] }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Recurring Services" }), _jsx("p", { className: "template-editor__card-subtitle", children: "Ongoing services included" })] })] }), _jsxs("div", { className: "template-editor__services", children: [globalState.recurringServices.map((service, index) => (_jsxs("div", { className: "template-editor__service", children: [_jsx("span", { className: "template-editor__service-bullet template-editor__service-bullet--recurring" }), _jsx("span", { className: "template-editor__service-text", children: service }), _jsx("button", { type: "button", onClick: () => handleRemoveRecurringService(index), className: "template-editor__service-remove", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", strokeWidth: "2" }) }) })] }, index))), _jsxs("div", { className: "template-editor__add-service", children: [_jsx("span", { className: "template-editor__service-bullet template-editor__service-bullet--ghost" }), _jsx("input", { ref: recurringServiceInputRef, type: "text", value: newRecurringService, onChange: (e) => setNewRecurringService(e.target.value), onKeyDown: (e) => {
332
+ }, placeholder: "Add a setup service...", className: "template-editor__service-new-input" }), newSetupService && (_jsx("button", { type: "button", onClick: handleAddSetupService, className: "template-editor__service-add-btn", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 5v14M5 12h14", strokeWidth: "2" }) }) }))] })] })] }), _jsxs("section", { className: "template-editor__card", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--amber", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("path", { d: "M12 8v4l3 3" }), _jsx("circle", { cx: "12", cy: "12", r: "9" })] }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Recurring Services" }), _jsx("p", { className: "template-editor__card-subtitle", children: "Ongoing services included" })] }), _jsxs("button", { type: "button", onClick: () => setShowRecurringTemplates(!showRecurringTemplates), className: `template-editor__templates-toggle template-editor__templates-toggle--amber ${showRecurringTemplates ? "template-editor__templates-toggle--active" : ""}`, children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z" }) }), "Templates"] })] }), showRecurringTemplates && (_jsx("div", { className: "template-editor__templates-panel template-editor__templates-panel--amber", children: Object.entries(RECURRING_SERVICE_TEMPLATES).map(([category, templates]) => (_jsxs("div", { className: "template-editor__template-category", children: [_jsx("span", { className: "template-editor__template-category-label", children: category }), _jsx("div", { className: "template-editor__template-items", children: templates.map((template) => {
333
+ const isAdded = globalState.recurringServices.includes(template.title);
334
+ return (_jsxs("button", { type: "button", onClick: () => handleAddRecurringFromTemplate(template), disabled: isAdded, className: `template-editor__template-item template-editor__template-item--amber ${isAdded ? "template-editor__template-item--added" : ""}`, title: template.description, children: [_jsx("span", { className: "template-editor__template-icon", children: template.icon }), _jsx("span", { className: "template-editor__template-title", children: template.title }), isAdded && (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "template-editor__template-check", children: _jsx("path", { d: "M5 12l5 5L20 7" }) }))] }, template.title));
335
+ }) })] }, category))) })), _jsxs("div", { className: "template-editor__services", children: [globalState.recurringServices.map((service, index) => (_jsxs("div", { className: "template-editor__service", children: [_jsx("span", { className: "template-editor__service-bullet template-editor__service-bullet--recurring" }), _jsx("span", { className: "template-editor__service-text", children: service }), _jsx("button", { type: "button", onClick: () => handleRemoveRecurringService(index), className: "template-editor__service-remove", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", strokeWidth: "2" }) }) })] }, index))), _jsxs("div", { className: "template-editor__add-service", children: [_jsx("span", { className: "template-editor__service-bullet template-editor__service-bullet--ghost" }), _jsx("input", { ref: recurringServiceInputRef, type: "text", value: newRecurringService, onChange: (e) => setNewRecurringService(e.target.value), onKeyDown: (e) => {
186
336
  if (e.key === "Enter")
187
337
  handleAddRecurringService();
188
338
  }, placeholder: "Add a recurring service...", className: "template-editor__service-new-input" }), newRecurringService && (_jsx("button", { type: "button", onClick: handleAddRecurringService, className: "template-editor__service-add-btn", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 5v14M5 12h14", strokeWidth: "2" }) }) }))] })] })] })] }), _jsxs("section", { className: "template-editor__metadata", children: [_jsxs("div", { className: "template-editor__meta-field", children: [_jsx("label", { className: "template-editor__label", children: "Operator ID" }), _jsx("input", { type: "text", value: formData.operatorId, onChange: (e) => handleFieldChange("operatorId", e.target.value), onBlur: handleOperatorBlur, className: "template-editor__input template-editor__input--mono", placeholder: "operator-123" })] }), _jsxs("div", { className: "template-editor__meta-field", children: [_jsx("label", { className: "template-editor__label", children: "More Info Link" }), _jsx("input", { type: "text", value: formData.infoLink, onChange: (e) => handleFieldChange("infoLink", e.target.value), onBlur: handleInfoBlur, className: "template-editor__input", placeholder: "https://example.com/more-info" })] })] })] })] }));
@@ -953,6 +1103,156 @@ const styles = `
953
1103
  color: white;
954
1104
  }
955
1105
 
1106
+ /* Templates Panel */
1107
+ .template-editor__templates-toggle {
1108
+ display: inline-flex;
1109
+ align-items: center;
1110
+ gap: 6px;
1111
+ margin-left: auto;
1112
+ padding: 6px 12px;
1113
+ font-family: var(--te-font);
1114
+ font-size: 0.75rem;
1115
+ font-weight: 600;
1116
+ color: var(--te-emerald);
1117
+ background: var(--te-emerald-light);
1118
+ border: 1.5px solid transparent;
1119
+ border-radius: 100px;
1120
+ cursor: pointer;
1121
+ transition: all 0.15s ease;
1122
+ }
1123
+
1124
+ .template-editor__templates-toggle svg {
1125
+ width: 14px;
1126
+ height: 14px;
1127
+ }
1128
+
1129
+ .template-editor__templates-toggle:hover {
1130
+ border-color: var(--te-emerald);
1131
+ }
1132
+
1133
+ .template-editor__templates-toggle--active {
1134
+ background: var(--te-emerald);
1135
+ color: white;
1136
+ }
1137
+
1138
+ .template-editor__templates-toggle--amber {
1139
+ color: var(--te-amber);
1140
+ background: var(--te-amber-light);
1141
+ }
1142
+
1143
+ .template-editor__templates-toggle--amber:hover {
1144
+ border-color: var(--te-amber);
1145
+ }
1146
+
1147
+ .template-editor__templates-toggle--amber.template-editor__templates-toggle--active {
1148
+ background: var(--te-amber);
1149
+ color: white;
1150
+ }
1151
+
1152
+ .template-editor__templates-panel {
1153
+ background: var(--te-emerald-light);
1154
+ border: 1px solid rgba(16, 185, 129, 0.2);
1155
+ border-radius: 12px;
1156
+ padding: 16px;
1157
+ margin-bottom: 16px;
1158
+ animation: templatesPanelSlide 0.2s ease-out;
1159
+ }
1160
+
1161
+ .template-editor__templates-panel--amber {
1162
+ background: var(--te-amber-light);
1163
+ border-color: rgba(245, 158, 11, 0.2);
1164
+ }
1165
+
1166
+ @keyframes templatesPanelSlide {
1167
+ from {
1168
+ opacity: 0;
1169
+ transform: translateY(-8px);
1170
+ }
1171
+ to {
1172
+ opacity: 1;
1173
+ transform: translateY(0);
1174
+ }
1175
+ }
1176
+
1177
+ .template-editor__template-category {
1178
+ margin-bottom: 12px;
1179
+ }
1180
+
1181
+ .template-editor__template-category:last-child {
1182
+ margin-bottom: 0;
1183
+ }
1184
+
1185
+ .template-editor__template-category-label {
1186
+ display: block;
1187
+ font-size: 0.6875rem;
1188
+ font-weight: 700;
1189
+ text-transform: uppercase;
1190
+ letter-spacing: 0.05em;
1191
+ color: var(--te-ink-muted);
1192
+ margin-bottom: 8px;
1193
+ }
1194
+
1195
+ .template-editor__template-items {
1196
+ display: flex;
1197
+ flex-wrap: wrap;
1198
+ gap: 6px;
1199
+ }
1200
+
1201
+ .template-editor__template-item {
1202
+ display: inline-flex;
1203
+ align-items: center;
1204
+ gap: 6px;
1205
+ padding: 6px 10px;
1206
+ font-family: var(--te-font);
1207
+ font-size: 0.8125rem;
1208
+ font-weight: 500;
1209
+ color: var(--te-ink);
1210
+ background: var(--te-surface);
1211
+ border: 1.5px solid var(--te-border-light);
1212
+ border-radius: 8px;
1213
+ cursor: pointer;
1214
+ transition: all 0.15s ease;
1215
+ }
1216
+
1217
+ .template-editor__template-item:hover:not(:disabled) {
1218
+ border-color: var(--te-emerald);
1219
+ background: white;
1220
+ transform: translateY(-1px);
1221
+ box-shadow: 0 2px 8px rgba(16, 185, 129, 0.15);
1222
+ }
1223
+
1224
+ .template-editor__template-item--amber:hover:not(:disabled) {
1225
+ border-color: var(--te-amber);
1226
+ box-shadow: 0 2px 8px rgba(245, 158, 11, 0.15);
1227
+ }
1228
+
1229
+ .template-editor__template-item--added {
1230
+ background: var(--te-emerald-light);
1231
+ border-color: var(--te-emerald);
1232
+ color: var(--te-emerald);
1233
+ cursor: default;
1234
+ }
1235
+
1236
+ .template-editor__template-item--amber.template-editor__template-item--added {
1237
+ background: var(--te-amber-light);
1238
+ border-color: var(--te-amber);
1239
+ color: var(--te-amber);
1240
+ }
1241
+
1242
+ .template-editor__template-icon {
1243
+ font-size: 0.875rem;
1244
+ }
1245
+
1246
+ .template-editor__template-title {
1247
+ white-space: nowrap;
1248
+ }
1249
+
1250
+ .template-editor__template-check {
1251
+ width: 14px;
1252
+ height: 14px;
1253
+ margin-left: 2px;
1254
+ }
1255
+
956
1256
  /* Responsive */
957
1257
  @media (max-width: 900px) {
958
1258
  .template-editor__hero {
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/resource-template-editor/editor.tsx"],"names":[],"mappings":"AAOA,MAAM,CAAC,OAAO,UAAU,sBAAsB,4CA8D7C"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../../editors/resource-template-editor/editor.tsx"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,UAAU,sBAAsB,4CA8D7C"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { setName } from "document-model";
3
3
  import { useState } from "react";
4
- import { useSelectedServiceOfferingDocument } from "../../../document-models/service-offering/hooks.js";
4
+ import { useSelectedServiceOfferingDocument } from "@powerhousedao/contributor-billing/document-models/service-offering";
5
5
  /** Displays the name of the selected ServiceOffering document and allows editing it */
6
6
  export function EditServiceOfferingName() {
7
7
  const [serviceOfferingDocument, dispatch] = useSelectedServiceOfferingDocument();
@@ -1,5 +1,5 @@
1
1
  import type { DocumentDispatch } from "@powerhousedao/reactor-browser";
2
- import type { ServiceOfferingDocument, ServiceOfferingAction } from "../../../document-models/service-offering/gen/types.js";
2
+ import type { ServiceOfferingDocument, ServiceOfferingAction } from "@powerhousedao/contributor-billing/document-models/service-offering";
3
3
  interface OfferingInfoProps {
4
4
  document: ServiceOfferingDocument;
5
5
  dispatch: DocumentDispatch<ServiceOfferingAction>;
@@ -1 +1 @@
1
- {"version":3,"file":"OfferingInfo.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/OfferingInfo.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,wDAAwD,CAAC;AAQhE,UAAU,iBAAiB;IACzB,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CAsRrE"}
1
+ {"version":3,"file":"OfferingInfo.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/OfferingInfo.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,qEAAqE,CAAC;AAQ7E,UAAU,iBAAiB;IACzB,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CAsRrE"}
@@ -0,0 +1,10 @@
1
+ import type { ServiceOfferingDocument } from "@powerhousedao/contributor-billing/document-models/service-offering";
2
+ import type { TabId } from "./TabNavigation.js";
3
+ interface OfferingProgressProps {
4
+ document: ServiceOfferingDocument;
5
+ activeTab: TabId;
6
+ onTabChange: (tabId: TabId) => void;
7
+ }
8
+ export declare function OfferingProgress({ document, activeTab, onTabChange, }: OfferingProgressProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=OfferingProgress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OfferingProgress.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/OfferingProgress.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qEAAqE,CAAC;AACnH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,SAAS,EAAE,KAAK,CAAC;IACjB,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACrC;AAyCD,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAS,EACT,WAAW,GACZ,EAAE,qBAAqB,2CAoHvB"}
@@ -0,0 +1,240 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useMemo } from "react";
3
+ // Helper to check if matrix is reasonably complete
4
+ function hasCompleteMatrix(state) {
5
+ if (state.services.length === 0 || state.tiers.length === 0)
6
+ return false;
7
+ // Check if at least 50% of services have tier assignments
8
+ const servicesWithLevels = state.services.filter((service) => state.tiers.some((tier) => tier.serviceLevels.some((sl) => sl.serviceId === service.id))).length;
9
+ return servicesWithLevels >= Math.ceil(state.services.length * 0.5);
10
+ }
11
+ function getMatrixCompletionText(state) {
12
+ if (state.services.length === 0 || state.tiers.length === 0) {
13
+ return "Add services and tiers first";
14
+ }
15
+ const servicesWithLevels = state.services.filter((service) => state.tiers.some((tier) => tier.serviceLevels.some((sl) => sl.serviceId === service.id))).length;
16
+ return `${servicesWithLevels}/${state.services.length} services configured`;
17
+ }
18
+ export function OfferingProgress({ document, activeTab, onTabChange, }) {
19
+ const state = document.state.global;
20
+ const steps = useMemo(() => [
21
+ {
22
+ id: "scope-facets",
23
+ label: "Template",
24
+ isComplete: !!state.resourceTemplateId,
25
+ details: state.resourceTemplateId
26
+ ? `${state.facetTargets.length} facets configured`
27
+ : "Select a template",
28
+ },
29
+ {
30
+ id: "tier-definition",
31
+ label: "Tiers",
32
+ isComplete: state.tiers.length >= 2,
33
+ details: state.tiers.length > 0
34
+ ? `${state.tiers.length} tier${state.tiers.length !== 1 ? "s" : ""} defined`
35
+ : "Define pricing tiers",
36
+ },
37
+ {
38
+ id: "service-catalog",
39
+ label: "Services",
40
+ isComplete: state.services.length >= 1,
41
+ details: state.services.length > 0
42
+ ? `${state.services.length} service${state.services.length !== 1 ? "s" : ""} created`
43
+ : "Add your services",
44
+ },
45
+ {
46
+ id: "the-matrix",
47
+ label: "Matrix",
48
+ isComplete: hasCompleteMatrix(state),
49
+ details: getMatrixCompletionText(state),
50
+ },
51
+ ], [state]);
52
+ const completedCount = steps.filter((s) => s.isComplete).length;
53
+ const totalPercent = Math.round((completedCount / steps.length) * 100);
54
+ return (_jsxs(_Fragment, { children: [_jsx("style", { children: progressStyles }), _jsxs("div", { className: "offering-progress", children: [_jsxs("div", { className: "offering-progress__header", children: [_jsxs("div", { className: "offering-progress__percent-wrap", children: [_jsxs("span", { className: "offering-progress__percent", children: [totalPercent, "%"] }), _jsx("span", { className: "offering-progress__label", children: "Complete" })] }), totalPercent === 100 && (_jsxs("span", { className: "offering-progress__ready-badge", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: _jsx("path", { d: "M5 12l5 5L20 7" }) }), "Ready to publish"] }))] }), _jsx("div", { className: "offering-progress__bar", children: _jsx("div", { className: "offering-progress__fill", style: { width: `${totalPercent}%` } }) }), _jsx("div", { className: "offering-progress__steps", children: steps.map((step, i) => {
55
+ const isActive = step.id === activeTab;
56
+ return (_jsxs("button", { onClick: () => onTabChange(step.id), className: `
57
+ offering-progress__step
58
+ ${step.isComplete ? "offering-progress__step--complete" : ""}
59
+ ${isActive ? "offering-progress__step--active" : ""}
60
+ `, children: [_jsx("div", { className: "offering-progress__step-indicator", children: step.isComplete ? (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", children: _jsx("path", { d: "M5 12l5 5L20 7" }) })) : (_jsx("span", { children: i + 1 })) }), _jsxs("div", { className: "offering-progress__step-text", children: [_jsx("span", { className: "offering-progress__step-label", children: step.label }), _jsx("span", { className: "offering-progress__step-details", children: step.details })] })] }, step.id));
61
+ }) })] })] }));
62
+ }
63
+ const progressStyles = `
64
+ .offering-progress {
65
+ background: white;
66
+ border-radius: var(--so-radius-lg);
67
+ padding: 1rem 1.5rem;
68
+ margin-bottom: 1rem;
69
+ box-shadow: var(--so-shadow-sm);
70
+ border: 1px solid var(--so-slate-100);
71
+ }
72
+
73
+ .offering-progress__header {
74
+ display: flex;
75
+ align-items: center;
76
+ justify-content: space-between;
77
+ margin-bottom: 0.75rem;
78
+ }
79
+
80
+ .offering-progress__percent-wrap {
81
+ display: flex;
82
+ align-items: baseline;
83
+ gap: 0.5rem;
84
+ }
85
+
86
+ .offering-progress__percent {
87
+ font-size: 1.5rem;
88
+ font-weight: 700;
89
+ color: var(--so-violet-600);
90
+ font-family: var(--so-font-mono);
91
+ }
92
+
93
+ .offering-progress__label {
94
+ font-size: 0.75rem;
95
+ color: var(--so-slate-500);
96
+ text-transform: uppercase;
97
+ letter-spacing: 0.05em;
98
+ }
99
+
100
+ .offering-progress__ready-badge {
101
+ display: flex;
102
+ align-items: center;
103
+ gap: 0.375rem;
104
+ padding: 0.375rem 0.75rem;
105
+ background: var(--so-emerald-50);
106
+ color: var(--so-emerald-600);
107
+ font-size: 0.75rem;
108
+ font-weight: 600;
109
+ border-radius: 100px;
110
+ animation: progress-badge-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
111
+ }
112
+
113
+ .offering-progress__ready-badge svg {
114
+ width: 0.875rem;
115
+ height: 0.875rem;
116
+ }
117
+
118
+ @keyframes progress-badge-pop {
119
+ from {
120
+ transform: scale(0.8);
121
+ opacity: 0;
122
+ }
123
+ to {
124
+ transform: scale(1);
125
+ opacity: 1;
126
+ }
127
+ }
128
+
129
+ .offering-progress__bar {
130
+ height: 8px;
131
+ background: var(--so-slate-100);
132
+ border-radius: 100px;
133
+ overflow: hidden;
134
+ margin-bottom: 1rem;
135
+ }
136
+
137
+ .offering-progress__fill {
138
+ height: 100%;
139
+ background: linear-gradient(90deg, var(--so-violet-500), var(--so-emerald-500));
140
+ border-radius: 100px;
141
+ transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
142
+ }
143
+
144
+ .offering-progress__steps {
145
+ display: flex;
146
+ justify-content: space-between;
147
+ gap: 0.5rem;
148
+ }
149
+
150
+ .offering-progress__step {
151
+ flex: 1;
152
+ display: flex;
153
+ align-items: center;
154
+ gap: 0.625rem;
155
+ padding: 0.5rem 0.75rem;
156
+ background: transparent;
157
+ border: none;
158
+ border-radius: var(--so-radius-md);
159
+ cursor: pointer;
160
+ transition: all 0.15s ease;
161
+ text-align: left;
162
+ }
163
+
164
+ .offering-progress__step:hover {
165
+ background: var(--so-slate-50);
166
+ }
167
+
168
+ .offering-progress__step--active {
169
+ background: var(--so-violet-50);
170
+ }
171
+
172
+ .offering-progress__step-indicator {
173
+ width: 1.75rem;
174
+ height: 1.75rem;
175
+ border-radius: 50%;
176
+ background: var(--so-slate-200);
177
+ display: flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ font-size: 0.75rem;
181
+ font-weight: 600;
182
+ color: var(--so-slate-500);
183
+ flex-shrink: 0;
184
+ transition: all 0.2s ease;
185
+ }
186
+
187
+ .offering-progress__step--complete .offering-progress__step-indicator {
188
+ background: var(--so-emerald-500);
189
+ color: white;
190
+ }
191
+
192
+ .offering-progress__step--complete .offering-progress__step-indicator svg {
193
+ width: 0.875rem;
194
+ height: 0.875rem;
195
+ }
196
+
197
+ .offering-progress__step--active .offering-progress__step-indicator {
198
+ background: var(--so-violet-500);
199
+ color: white;
200
+ box-shadow: 0 0 0 3px var(--so-violet-100);
201
+ }
202
+
203
+ .offering-progress__step-text {
204
+ display: flex;
205
+ flex-direction: column;
206
+ min-width: 0;
207
+ }
208
+
209
+ .offering-progress__step-label {
210
+ font-size: 0.8125rem;
211
+ font-weight: 600;
212
+ color: var(--so-slate-700);
213
+ }
214
+
215
+ .offering-progress__step--active .offering-progress__step-label {
216
+ color: var(--so-violet-700);
217
+ }
218
+
219
+ .offering-progress__step-details {
220
+ font-size: 0.6875rem;
221
+ color: var(--so-slate-400);
222
+ white-space: nowrap;
223
+ overflow: hidden;
224
+ text-overflow: ellipsis;
225
+ }
226
+
227
+ .offering-progress__step--complete .offering-progress__step-details {
228
+ color: var(--so-emerald-600);
229
+ }
230
+
231
+ @media (max-width: 768px) {
232
+ .offering-progress__steps {
233
+ flex-wrap: wrap;
234
+ }
235
+
236
+ .offering-progress__step {
237
+ flex: 1 1 45%;
238
+ }
239
+ }
240
+ `;