@growth-labs/cms 0.5.25 → 0.5.27

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 (76) hide show
  1. package/dist/providers/null.d.ts.map +1 -1
  2. package/dist/providers/null.js +8 -0
  3. package/dist/providers/null.js.map +1 -1
  4. package/dist/providers/types.d.ts +26 -1
  5. package/dist/providers/types.d.ts.map +1 -1
  6. package/dist/providers/types.js.map +1 -1
  7. package/dist/ui/client/mount.d.ts +1 -0
  8. package/dist/ui/client/mount.d.ts.map +1 -1
  9. package/dist/ui/client/mount.js +1 -0
  10. package/dist/ui/client/mount.js.map +1 -1
  11. package/dist/ui/components/CmsApp.js +2 -11
  12. package/dist/ui/components/CmsApp.js.map +1 -1
  13. package/dist/ui/components/Sidebar.d.ts.map +1 -1
  14. package/dist/ui/components/Sidebar.js +2 -2
  15. package/dist/ui/components/Sidebar.js.map +1 -1
  16. package/dist/ui/components/Topbar.d.ts.map +1 -1
  17. package/dist/ui/components/Topbar.js +1 -10
  18. package/dist/ui/components/Topbar.js.map +1 -1
  19. package/dist/ui/editor/ContentForm.d.ts.map +1 -1
  20. package/dist/ui/editor/ContentForm.js +7 -8
  21. package/dist/ui/editor/ContentForm.js.map +1 -1
  22. package/dist/ui/editor/Rte.js +3 -3
  23. package/dist/ui/editor/Rte.js.map +1 -1
  24. package/dist/ui/inspector/FoundryTab.js +1 -1
  25. package/dist/ui/inspector/FoundryTab.js.map +1 -1
  26. package/dist/ui/pages/admin.astro +1 -1
  27. package/dist/ui/screens/AnalyticsScreen.d.ts +7 -0
  28. package/dist/ui/screens/AnalyticsScreen.d.ts.map +1 -1
  29. package/dist/ui/screens/AnalyticsScreen.js +38 -9
  30. package/dist/ui/screens/AnalyticsScreen.js.map +1 -1
  31. package/dist/ui/screens/AuthorsScreen.js +1 -1
  32. package/dist/ui/screens/ContentInsightsScreen.js +1 -1
  33. package/dist/ui/screens/ContentInsightsScreen.js.map +1 -1
  34. package/dist/ui/screens/EditorScreen.d.ts +3 -0
  35. package/dist/ui/screens/EditorScreen.d.ts.map +1 -1
  36. package/dist/ui/screens/EditorScreen.js +15 -9
  37. package/dist/ui/screens/EditorScreen.js.map +1 -1
  38. package/dist/ui/screens/LibraryScreen.js +2 -2
  39. package/dist/ui/screens/LibraryScreen.js.map +1 -1
  40. package/dist/ui/screens/SettingsScreen.js +1 -1
  41. package/dist/ui/screens/SubscriptionsScreen.js +2 -2
  42. package/dist/ui/screens/analytics-data.d.ts.map +1 -1
  43. package/dist/ui/screens/analytics-data.js +16 -1
  44. package/dist/ui/screens/analytics-data.js.map +1 -1
  45. package/dist/ui/styles/broadsheet.css +131 -156
  46. package/dist/ui/styles/growth-labs-tokens.css +149 -0
  47. package/dist/ui/theme.d.ts +7 -4
  48. package/dist/ui/theme.d.ts.map +1 -1
  49. package/dist/ui/theme.js +24 -65
  50. package/dist/ui/theme.js.map +1 -1
  51. package/dist/ui/use-tweaks.d.ts.map +1 -1
  52. package/dist/ui/use-tweaks.js +2 -1
  53. package/dist/ui/use-tweaks.js.map +1 -1
  54. package/package.json +1 -1
  55. package/src/providers/null.ts +8 -0
  56. package/src/providers/types.ts +27 -1
  57. package/src/ui/client/mount.tsx +1 -0
  58. package/src/ui/components/CmsApp.tsx +3 -20
  59. package/src/ui/components/Sidebar.tsx +5 -11
  60. package/src/ui/components/Topbar.tsx +2 -13
  61. package/src/ui/editor/ContentForm.tsx +7 -8
  62. package/src/ui/editor/Rte.tsx +3 -3
  63. package/src/ui/inspector/FoundryTab.tsx +1 -1
  64. package/src/ui/pages/admin.astro +1 -1
  65. package/src/ui/screens/AnalyticsScreen.tsx +86 -7
  66. package/src/ui/screens/AuthorsScreen.tsx +1 -1
  67. package/src/ui/screens/ContentInsightsScreen.tsx +1 -1
  68. package/src/ui/screens/EditorScreen.tsx +17 -9
  69. package/src/ui/screens/LibraryScreen.tsx +5 -2
  70. package/src/ui/screens/SettingsScreen.tsx +1 -1
  71. package/src/ui/screens/SubscriptionsScreen.tsx +2 -2
  72. package/src/ui/screens/analytics-data.ts +16 -2
  73. package/src/ui/styles/broadsheet.css +131 -156
  74. package/src/ui/styles/growth-labs-tokens.css +149 -0
  75. package/src/ui/theme.ts +29 -68
  76. package/src/ui/use-tweaks.ts +2 -1
@@ -58,12 +58,20 @@ const CONTENT_TYPE_LABELS: Record<ContentType, string> = {
58
58
 
59
59
  const STATUS_PILL_COLORS: Record<ContentStatus, string> = {
60
60
  draft: 'var(--ink-faint)',
61
- review: '#a78bfa',
62
- scheduled: '#60a5fa',
63
- published: '#34d399',
61
+ review: 'var(--amber)',
62
+ scheduled: 'var(--accent)',
63
+ published: 'var(--green)',
64
64
  archived: 'var(--ink-faint)',
65
65
  }
66
66
 
67
+ export function editorStatusColor(status: ContentStatus): string {
68
+ return STATUS_PILL_COLORS[status]
69
+ }
70
+
71
+ export function editorStatusBackground(status: ContentStatus): string {
72
+ return `color-mix(in srgb, ${editorStatusColor(status)} 14%, transparent)`
73
+ }
74
+
67
75
  // ---------------------------------------------------------------------------
68
76
  // EditorScreen
69
77
  // ---------------------------------------------------------------------------
@@ -503,8 +511,8 @@ function statusPill(status: ContentStatus): React.CSSProperties {
503
511
  fontWeight: 600,
504
512
  letterSpacing: '0.06em',
505
513
  textTransform: 'uppercase',
506
- background: `${STATUS_PILL_COLORS[status]}22`,
507
- color: STATUS_PILL_COLORS[status],
514
+ background: editorStatusBackground(status),
515
+ color: editorStatusColor(status),
508
516
  flexShrink: 0,
509
517
  }
510
518
  }
@@ -526,10 +534,10 @@ const headerBar: React.CSSProperties = {
526
534
  display: 'flex',
527
535
  alignItems: 'center',
528
536
  justifyContent: 'space-between',
529
- height: 48,
530
- padding: '0 16px',
537
+ height: 58,
538
+ padding: '0 20px',
531
539
  borderBottom: '1px solid var(--border)',
532
- background: 'var(--panel)',
540
+ background: 'var(--surface-raised-nav)',
533
541
  flexShrink: 0,
534
542
  gap: 12,
535
543
  }
@@ -661,7 +669,7 @@ const formArea: React.CSSProperties = {
661
669
  }
662
670
 
663
671
  const inspectorSlot: React.CSSProperties = {
664
- flex: '0 0 340px',
672
+ flex: '0 0 296px',
665
673
  borderLeft: '1px solid var(--border)',
666
674
  display: 'flex',
667
675
  flexDirection: 'column',
@@ -753,7 +753,10 @@ function ListRow({
753
753
  >
754
754
  {row.title || '(Untitled)'}
755
755
  {row.featured && (
756
- <span title="Premium" style={{ color: 'var(--gold)', flex: 'none' }}>
756
+ <span
757
+ title="Premium"
758
+ style={{ color: 'var(--accent-primary-strong)', flex: 'none' }}
759
+ >
757
760
  <Icon name="star" size={13} />
758
761
  </span>
759
762
  )}
@@ -1064,7 +1067,7 @@ function BoardCard({
1064
1067
  {row.updatedAt ? formatDate(row.updatedAt) : (row.authorName ?? '—')}
1065
1068
  </span>
1066
1069
  {row.featured && (
1067
- <span style={{ marginLeft: 'auto', color: 'var(--gold)' }}>
1070
+ <span style={{ marginLeft: 'auto', color: 'var(--accent-primary-strong)' }}>
1068
1071
  <Icon name="star" size={12} />
1069
1072
  </span>
1070
1073
  )}
@@ -375,7 +375,7 @@ function GeneralSettings({
375
375
  // Branding settings
376
376
  // ---------------------------------------------------------------------------
377
377
 
378
- const ACCENT_PRESETS = ['#0c4a6e', '#b23a2e', '#1f6b4a', '#5b4bc4', '#374151']
378
+ const ACCENT_PRESETS = ['#2F6FBD', '#1FA3A8', '#2CA8E0', '#8075ED', '#F56A61']
379
379
  const TYPEFACE_OPTIONS = ['serif', 'Source Serif 4', 'Spectral', 'Newsreader', 'Inter']
380
380
 
381
381
  function BrandingSettings({
@@ -1310,7 +1310,7 @@ function KpiCard({
1310
1310
  // PlanMixChart — stacked bar + legend rows (aside panel)
1311
1311
  // ---------------------------------------------------------------------------
1312
1312
 
1313
- const PLAN_DOT_COLORS = ['#1f6b4a', '#0c4a6e', '#5b4bc4', '#8c6d14', '#475569']
1313
+ const PLAN_DOT_COLORS = ['#1FA3A8', '#2F6FBD', '#8075ED', '#F7A34B', '#4D4D4D']
1314
1314
 
1315
1315
  function PlanMixChart({
1316
1316
  planMix,
@@ -1746,7 +1746,7 @@ function initialsFor(email: string): string {
1746
1746
  return local.slice(0, 2).toUpperCase()
1747
1747
  }
1748
1748
 
1749
- const AVATAR_COLORS = ['#0c4a6e', '#1f6b4a', '#5b4bc4', '#8c6d14', '#075985', '#475569']
1749
+ const AVATAR_COLORS = ['#2F6FBD', '#1FA3A8', '#8075ED', '#F7A34B', '#2CA8E0', '#4D4D4D']
1750
1750
 
1751
1751
  function avatarColor(seed: string): string {
1752
1752
  let h = 0
@@ -24,14 +24,28 @@ function providerStatus(value: unknown): ProviderStatus {
24
24
  return value === 'live' || value === 'partial' || value === 'empty' ? value : 'empty'
25
25
  }
26
26
 
27
+ function normalizeSources(value: unknown): Record<string, string> | undefined {
28
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined
29
+ const out: Record<string, string> = {}
30
+ for (const [key, label] of Object.entries(value as Record<string, unknown>)) {
31
+ if (typeof label === 'string' && label.length > 0) out[key] = label
32
+ }
33
+ return Object.keys(out).length > 0 ? out : undefined
34
+ }
35
+
27
36
  function normalizeObjectResult(result: unknown): ProviderResult<Record<string, number | null>> {
28
37
  if (!result || typeof result !== 'object') return { status: 'empty', data: {} }
29
- const record = result as { status?: unknown; data?: unknown }
38
+ const record = result as { status?: unknown; data?: unknown; sources?: unknown }
30
39
  const data =
31
40
  record.data && typeof record.data === 'object' && !Array.isArray(record.data)
32
41
  ? (record.data as Record<string, number | null>)
33
42
  : {}
34
- return { status: providerStatus(record.status), data }
43
+ const sources = normalizeSources(record.sources)
44
+ return {
45
+ status: providerStatus(record.status),
46
+ data,
47
+ ...(sources ? { sources } : {}),
48
+ }
35
49
  }
36
50
 
37
51
  function normalizeArrayResult<T>(result: unknown): ProviderResult<T[]> {
@@ -1,99 +1,54 @@
1
- /* ============================================================
2
- BROADSHEET publishing platform UI
3
- Rooted in Fronts DNA: Source Serif 4 display, DM Sans UI,
4
- DM Mono micro-labels, navy + gold. Its own product identity.
5
- ============================================================ */
1
+ /* Masthead CMS compatibility layer — Growth Labs visual contract.
2
+ * Keep the established class vocabulary; all visual decisions resolve through
3
+ * growth-labs-tokens.css, imported first by ui/client/mount.tsx. */
6
4
 
7
5
  :root {
8
- /* Brand constants (shared across themes) */
9
- --gold: #b8941b;
10
- --gold-soft: #d4b88a;
11
- --premium: #8c6d14;
12
-
13
- /* Accent — overridden live by Tweaks (JS sets these). Default ink-blue. */
14
- --accent: #0c4a6e;
15
- --accent-strong: #075985;
16
- --accent-fg: #ffffff;
17
- --accent-tint: rgba(12, 74, 110, 0.08);
18
- --accent-ring: rgba(12, 74, 110, 0.35);
19
-
20
- /* Type */
21
- --serif: "Source Serif 4", Georgia, serif;
22
- --ui: "DM Sans", system-ui, sans-serif;
23
- --mono: "DM Mono", ui-monospace, monospace;
24
-
25
- /* Density scale (overridden by [data-density]) */
6
+ --accent: var(--accent-cta);
7
+ --accent-strong: var(--accent-cta-active);
8
+ --accent-fg: var(--gl-white);
9
+ --accent-tint: color-mix(in srgb, var(--accent-primary) 14%, transparent);
10
+ --accent-ring: var(--focus-ring);
11
+ --serif: var(--font-display);
12
+ --ui: var(--font-body);
13
+ --mono: var(--font-mono);
14
+
26
15
  --row-h: 44px;
27
16
  --pad: 16px;
28
17
  --gap: 16px;
29
- --radius: 10px;
30
- --radius-sm: 7px;
18
+ --radius: var(--radius-none);
19
+ --legacy-radius-sm: var(--radius-control);
20
+ --bg: var(--surface-page);
21
+ --panel: var(--surface-card);
22
+ --panel-2: var(--surface-muted);
23
+ --sidebar: var(--surface-nav);
24
+ --sidebar-deep: var(--surface-inverse);
25
+ --ink: var(--text-strong);
26
+ --ink-soft: var(--text-primary);
27
+ --ink-muted: var(--text-secondary);
28
+ --ink-faint: var(--text-muted);
29
+ --border: var(--border-default);
30
+ --border-soft: color-mix(in srgb, var(--border-default) 42%, transparent);
31
+ --hairline: var(--border-default);
32
+ --hover: var(--surface-muted);
33
+ --field: var(--surface-card);
34
+ --field-border: var(--border-default);
35
+ --shadow-sm: var(--shadow-faint);
36
+ --shadow-md: var(--shadow-card);
37
+ --shadow-lg: var(--shadow-raised);
38
+ --green: var(--accent-primary-strong);
39
+ --green-tint: color-mix(in srgb, var(--accent-primary) 16%, transparent);
40
+ --amber: color-mix(in srgb, var(--gl-orange) 72%, var(--text-strong));
41
+ --amber-tint: color-mix(in srgb, var(--gl-orange) 18%, transparent);
42
+ --red: var(--gl-coral);
43
+ --red-tint: color-mix(in srgb, var(--gl-coral) 14%, transparent);
44
+ --blue-tint: color-mix(in srgb, var(--accent-secondary) 16%, transparent);
45
+ --violet: var(--gl-violet);
46
+ --violet-tint: color-mix(in srgb, var(--gl-violet) 16%, transparent);
31
47
  }
32
48
 
33
49
  [data-density="compact"] { --row-h: 38px; --pad: 12px; --gap: 12px; }
34
50
  [data-density="comfy"] { --row-h: 52px; --pad: 22px; --gap: 22px; }
35
51
 
36
- /* ---------- LIGHT (default) ---------- */
37
- :root,
38
- [data-theme="light"] {
39
- --bg: #f7f5f1;
40
- --panel: #ffffff;
41
- --panel-2: #fbfaf7;
42
- --sidebar: #ffffff;
43
- --sidebar-deep: #11151b;
44
- --ink: #1a2332;
45
- --ink-soft: #4a5562;
46
- --ink-muted: #79828f;
47
- --ink-faint: #a7adb6;
48
- --border: #e7e2d9;
49
- --border-soft: #efebe3;
50
- --hairline: #ddd7cc;
51
- --hover: #f3f0ea;
52
- --field: #ffffff;
53
- --field-border: #d9d3c8;
54
- --shadow-sm: 0 1px 2px rgba(26, 35, 50, 0.06);
55
- --shadow-md: 0 8px 24px rgba(26, 35, 50, 0.10);
56
- --shadow-lg: 0 20px 60px rgba(26, 35, 50, 0.18);
57
- --green: #1d7a4d;
58
- --green-tint: #e4f3ea;
59
- --amber: #9a6a00;
60
- --amber-tint: #f8eed5;
61
- --red: #c0392b;
62
- --red-tint: #f8e4e1;
63
- --blue-tint: #e6eef5;
64
- color-scheme: light;
65
- }
66
-
67
- /* ---------- DARK ---------- */
68
- [data-theme="dark"] {
69
- --bg: #0c0f14;
70
- --panel: #14181f;
71
- --panel-2: #11151b;
72
- --sidebar: #0b0e12;
73
- --sidebar-deep: #07090c;
74
- --ink: #e9ecf1;
75
- --ink-soft: #aeb6c2;
76
- --ink-muted: #79828f;
77
- --ink-faint: #565f6c;
78
- --border: #232a34;
79
- --border-soft: #1b212a;
80
- --hairline: #2a323d;
81
- --hover: #1a202a;
82
- --field: #11151b;
83
- --field-border: #2c343f;
84
- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
85
- --shadow-md: 0 10px 30px rgba(0, 0, 0, 0.5);
86
- --shadow-lg: 0 24px 70px rgba(0, 0, 0, 0.6);
87
- --green: #4ec98a;
88
- --green-tint: rgba(78, 201, 138, 0.14);
89
- --amber: #e0b65a;
90
- --amber-tint: rgba(224, 182, 90, 0.14);
91
- --red: #ef6e62;
92
- --red-tint: rgba(239, 110, 98, 0.14);
93
- --blue-tint: rgba(76, 154, 232, 0.14);
94
- color-scheme: dark;
95
- }
96
-
97
52
  * { box-sizing: border-box; }
98
53
 
99
54
  html, body {
@@ -111,12 +66,22 @@ html, body {
111
66
  button { font-family: inherit; cursor: pointer; appearance: none; -webkit-appearance: none; background: none; border: 0; color: inherit; }
112
67
  input, textarea, select { font-family: inherit; }
113
68
  ::selection { background: color-mix(in srgb, var(--accent) 26%, transparent); }
69
+ button:focus-visible,
70
+ [role="button"]:focus-visible,
71
+ input:focus-visible,
72
+ textarea:focus-visible,
73
+ select:focus-visible,
74
+ a:focus-visible {
75
+ outline: 2px solid var(--focus-ring);
76
+ outline-offset: 2px;
77
+ box-shadow: var(--shadow-glow);
78
+ }
114
79
 
115
80
  /* Scrollbars */
116
81
  *::-webkit-scrollbar { width: 11px; height: 11px; }
117
82
  *::-webkit-scrollbar-thumb {
118
83
  background: color-mix(in srgb, var(--ink) 18%, transparent);
119
- border-radius: 8px;
84
+ border-radius: var(--radius-pill);
120
85
  border: 3px solid transparent;
121
86
  background-clip: padding-box;
122
87
  }
@@ -127,28 +92,27 @@ input, textarea, select { font-family: inherit; }
127
92
  .serif { font-family: var(--serif); }
128
93
  .mono { font-family: var(--mono); }
129
94
  .kicker {
130
- font-family: var(--mono);
131
- font-size: 11px;
132
- font-weight: 500;
133
- letter-spacing: 0.14em;
95
+ font-family: var(--font-body);
96
+ font-size: 10.5px;
97
+ font-weight: 700;
98
+ line-height: 1;
99
+ letter-spacing: var(--tracking-eyebrow);
134
100
  text-transform: uppercase;
135
101
  color: var(--ink-muted);
136
102
  }
137
103
  .tnum { font-variant-numeric: tabular-nums; }
138
104
 
139
- /* The signature Broadsheet "masthead rule": a hairline above a heavier rule */
105
+ /* Legacy class retained as a single Growth Labs semantic separator. */
140
106
  .masthead-rule {
141
107
  border: 0;
142
- height: 3px;
143
- border-top: 1px solid var(--hairline);
144
- border-bottom: 2px solid var(--ink);
145
- background: transparent;
108
+ height: 1px;
109
+ background: var(--border-soft);
146
110
  }
147
111
 
148
112
  /* ---------- App shell ---------- */
149
113
  .app {
150
114
  display: grid;
151
- grid-template-columns: var(--sb-w, 248px) 1fr;
115
+ grid-template-columns: var(--sb-w, 224px) 1fr;
152
116
  height: 100%;
153
117
  overflow: hidden;
154
118
  transition: grid-template-columns 0.22s ease;
@@ -163,29 +127,29 @@ input, textarea, select { font-family: inherit; }
163
127
  flex-direction: column;
164
128
  min-height: 0;
165
129
  position: relative;
130
+ padding: 20px 14px;
131
+ gap: 20px;
166
132
  }
167
133
  .sb-brand {
168
134
  display: flex; align-items: center; gap: 11px;
169
- padding: 18px 18px 14px;
135
+ padding: 2px 8px;
170
136
  }
171
137
  .sb-mark {
172
- width: 30px; height: 30px; flex: none;
173
- border-radius: 8px;
174
- background: var(--ink);
175
- color: #fff;
138
+ width: 22px; height: 22px; flex: none;
139
+ border-radius: var(--radius-control);
140
+ background: var(--gl-gradient);
141
+ color: var(--gl-white);
176
142
  display: grid; place-items: center;
177
143
  }
178
- [data-theme="dark"] .sb-mark { background: var(--accent); }
179
- .sb-wordmark { font-family: var(--serif); font-weight: 600; font-size: 19px; letter-spacing: -0.01em; color: var(--ink); }
180
- .sb-wordmark .dot { color: var(--accent); }
144
+ .sb-wordmark { font-family: var(--font-display); font-weight: 600; font-size: 17px; line-height: 1.2; letter-spacing: -0.01em; color: var(--ink); }
181
145
 
182
146
  .site-switch {
183
- margin: 2px 12px 10px;
147
+ margin: 0 6px;
184
148
  display: flex; align-items: center; gap: 9px;
185
149
  padding: 8px 10px;
186
150
  border: 1px solid var(--border);
187
- border-radius: var(--radius-sm);
188
- background: var(--panel-2);
151
+ border-radius: var(--radius-control);
152
+ background: var(--panel);
189
153
  cursor: pointer;
190
154
  transition: border-color .15s, background .15s;
191
155
  }
@@ -194,27 +158,23 @@ input, textarea, select { font-family: inherit; }
194
158
  .site-name { font-size: 13px; font-weight: 600; color: var(--ink); flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
195
159
  .site-meta { font-size: 11px; color: var(--ink-muted); }
196
160
 
197
- .nav-section { padding: 6px 12px; }
161
+ .nav-section { padding: 0; }
198
162
  .nav-label {
199
- font-family: var(--mono); font-size: 10px; letter-spacing: 0.16em;
163
+ font-family: var(--font-body); font-size: 10.5px; font-weight: 700; letter-spacing: var(--tracking-eyebrow);
200
164
  text-transform: uppercase; color: var(--ink-faint);
201
- padding: 10px 10px 6px;
165
+ padding: 0 10px 8px;
202
166
  }
203
167
  .nav-item {
204
- display: flex; align-items: center; gap: 11px;
205
- padding: 8px 10px; border-radius: var(--radius-sm);
206
- color: var(--ink-soft); font-size: 13.5px; font-weight: 500;
168
+ width: 100%; display: flex; align-items: center; gap: 10px;
169
+ padding: 8px 10px; border-radius: var(--radius-control);
170
+ color: var(--ink-soft); font-family: var(--font-display); font-size: 13.5px; font-weight: 500;
207
171
  cursor: pointer; user-select: none;
208
172
  transition: background .12s, color .12s;
209
173
  position: relative;
210
174
  }
211
175
  .nav-item:hover { background: var(--hover); color: var(--ink); }
212
- .nav-item.active { background: var(--accent-tint); color: var(--accent); font-weight: 600; }
213
- [data-theme="dark"] .nav-item.active { color: var(--ink); }
214
- .nav-item.active::before {
215
- content: ""; position: absolute; left: -12px; top: 50%; transform: translateY(-50%);
216
- width: 3px; height: 18px; border-radius: 0 3px 3px 0; background: var(--accent);
217
- }
176
+ .nav-item.active { background: color-mix(in srgb, var(--accent-primary) 14%, transparent); color: var(--ink); font-weight: 600; }
177
+ .nav-item.active .ni-icon { color: var(--accent-primary-strong); }
218
178
  .nav-item .ni-icon { flex: none; color: currentColor; opacity: .9; }
219
179
  .nav-item .ni-count {
220
180
  margin-left: auto; font-family: var(--mono); font-size: 11px;
@@ -230,13 +190,13 @@ input, textarea, select { font-family: inherit; }
230
190
  [data-collapsed="true"] .sb-wordmark { display: none; }
231
191
  [data-collapsed="true"] .site-switch { justify-content: center; padding: 8px; }
232
192
 
233
- .sb-foot { margin-top: auto; padding: 12px; border-top: 1px solid var(--border); }
234
- .sb-user { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: var(--radius-sm); cursor: pointer; }
193
+ .sb-foot { margin-top: auto; padding: 0; border-top: 1px solid var(--border-soft); }
194
+ .sb-user { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: var(--legacy-radius-sm); cursor: pointer; }
235
195
  .sb-user:hover { background: var(--hover); }
236
196
  .avatar {
237
- width: 30px; height: 30px; border-radius: 50%; flex: none;
238
- display: grid; place-items: center; font-size: 12px; font-weight: 700; color: #fff;
239
- font-family: var(--ui);
197
+ width: 28px; height: 28px; border-radius: var(--radius-circle); flex: none;
198
+ display: grid; place-items: center; font-size: 11px; font-weight: 600; color: var(--text-on-inverse);
199
+ font-family: var(--font-display);
240
200
  }
241
201
 
242
202
  /* ---------- Main column ---------- */
@@ -244,70 +204,73 @@ input, textarea, select { font-family: inherit; }
244
204
  .topbar {
245
205
  height: 58px; flex: none;
246
206
  display: flex; align-items: center; gap: 14px;
247
- padding: 0 22px;
207
+ padding: 0 20px;
248
208
  border-bottom: 1px solid var(--border);
249
- background: color-mix(in srgb, var(--bg) 86%, transparent);
250
- backdrop-filter: blur(8px);
209
+ background: var(--surface-raised-nav);
210
+ backdrop-filter: var(--blur-panel);
251
211
  position: sticky; top: 0; z-index: 20;
252
212
  }
253
213
  .icon-btn {
254
- width: 34px; height: 34px; flex: none; border-radius: 8px;
214
+ width: 34px; height: 34px; flex: none; border-radius: var(--radius-control);
255
215
  border: 1px solid transparent; background: transparent; color: var(--ink-soft);
256
216
  display: grid; place-items: center; transition: background .12s, color .12s, border-color .12s;
257
217
  }
258
218
  .icon-btn:hover { background: var(--hover); color: var(--ink); }
219
+ .notification-dot { position: absolute; top: 7px; right: 8px; width: 7px; height: 7px; border-radius: var(--radius-circle); background: var(--gl-coral); border: 1.5px solid var(--surface-raised-nav); }
220
+ .topbar-divider { width: 1px; height: 22px; background: var(--border); margin: 0 4px; }
259
221
 
260
222
  .search {
261
223
  flex: 1; max-width: 460px;
262
224
  display: flex; align-items: center; gap: 9px;
263
225
  height: 36px; padding: 0 12px;
264
- background: var(--panel-2); border: 1px solid var(--border); border-radius: 9px;
226
+ background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-control);
265
227
  color: var(--ink-muted); font-size: 13px;
266
228
  }
267
229
  .search input { border: 0; background: transparent; outline: none; color: var(--ink); flex: 1; font-size: 13px; }
268
230
  .search .kbd {
269
231
  font-family: var(--mono); font-size: 10px; color: var(--ink-muted);
270
- border: 1px solid var(--border); border-radius: 5px; padding: 1px 6px;
232
+ border: 1px solid var(--border); border-radius: var(--radius-md); padding: 1px 6px;
271
233
  }
272
234
 
273
235
  .scroll { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; }
274
- .page { padding: 26px 30px 60px; max-width: 1280px; margin: 0 auto; }
236
+ .page { padding: 28px 32px 60px; max-width: 1280px; margin: 0 auto; }
275
237
  .page-wide { max-width: none; }
276
238
 
277
239
  .page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 22px; }
278
- .page-title { font-family: var(--serif); font-weight: 600; font-size: 30px; letter-spacing: -0.02em; color: var(--ink); margin: 0; line-height: 1.05; }
279
- .page-sub { color: var(--ink-muted); font-size: 13.5px; margin-top: 6px; }
240
+ .page-title { font-family: var(--font-display); font-weight: 600; font-size: 27px; letter-spacing: -0.01em; color: var(--ink); margin: 0; line-height: 1.15; }
241
+ .page-sub { color: var(--ink-muted); font-size: 13px; line-height: 1.4; margin-top: 4px; }
242
+ .shell-state { padding: 40px; color: var(--ink-muted); }
243
+ .shell-error-detail { margin-top: 16px; padding: 12px; font-size: 12px; color: var(--red); white-space: pre-wrap; word-break: break-word; background: var(--red-tint); border: 1px solid color-mix(in srgb, var(--red) 25%, transparent); border-radius: var(--radius-control); }
244
+ .editor-document { width: min(780px, calc(100% - 80px)); margin: 30px auto 0; padding: 44px 90px; box-sizing: border-box; background: var(--surface-card); border: 1px solid var(--border-default); box-shadow: var(--shadow-card); }
280
245
 
281
246
  /* ---------- Buttons ---------- */
282
247
  .btn {
283
248
  display: inline-flex; align-items: center; gap: 8px; justify-content: center;
284
- height: 36px; padding: 0 15px; border-radius: 9px;
285
- font-size: 13px; font-weight: 600; border: 1px solid var(--field-border);
249
+ height: 36px; padding: 0 14px; border-radius: var(--radius-control);
250
+ font-family: var(--font-display); font-size: 13px; font-weight: 600; border: 1px solid var(--field-border);
286
251
  background: var(--panel); color: var(--ink); transition: all .13s ease;
287
252
  white-space: nowrap;
288
253
  }
289
254
  .btn:hover { background: var(--hover); border-color: var(--hairline); }
290
- .btn.sm { height: 30px; padding: 0 11px; font-size: 12.5px; border-radius: 8px; }
255
+ .btn.sm { height: 30px; padding: 0 11px; font-size: 12.5px; border-radius: var(--radius-control); }
291
256
  .btn.lg { height: 42px; padding: 0 20px; font-size: 14px; }
292
257
  .btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
293
- .btn.primary:hover { background: var(--accent-strong); border-color: var(--accent-strong); }
258
+ .btn.primary:hover { background: var(--accent-cta-hover); border-color: var(--accent-cta-hover); }
294
259
  .btn.ghost { background: transparent; border-color: transparent; }
295
260
  .btn.ghost:hover { background: var(--hover); }
296
- .btn.gold { background: var(--gold); border-color: var(--gold); color: #1a1402; }
297
- .btn.gold:hover { filter: brightness(1.06); }
298
261
  .btn.danger { color: var(--red); border-color: transparent; background: transparent; }
299
262
  .btn.danger:hover { background: var(--red-tint); }
300
263
 
301
264
  /* ---------- Panels / cards ---------- */
302
- .panel { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); }
265
+ .panel { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-none); box-shadow: var(--shadow-card); }
303
266
  .panel-pad { padding: var(--pad); }
304
- .card-title { font-family: var(--serif); font-weight: 600; font-size: 17px; color: var(--ink); letter-spacing: -0.01em; }
267
+ .card-title { font-family: var(--font-display); font-weight: 600; font-size: 15px; line-height: 1.3; color: var(--ink); }
305
268
 
306
269
  /* ---------- Status pills ---------- */
307
270
  .pill {
308
271
  display: inline-flex; align-items: center; gap: 6px;
309
272
  font-family: var(--mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.06em;
310
- text-transform: uppercase; padding: 3px 9px; border-radius: 20px;
273
+ text-transform: uppercase; padding: 3px 9px; border-radius: var(--radius-pill);
311
274
  border: 1px solid transparent; white-space: nowrap;
312
275
  }
313
276
  .pill .pdot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
@@ -315,7 +278,7 @@ input, textarea, select { font-family: inherit; }
315
278
  .pill.draft { color: var(--ink-muted); background: var(--hover); }
316
279
  .pill.review { color: var(--amber); background: var(--amber-tint); }
317
280
  .pill.scheduled { color: var(--accent); background: var(--accent-tint); }
318
- .pill.processing { color: var(--amber); background: var(--amber-tint); }
281
+ .pill.processing { color: var(--violet); background: var(--violet-tint); }
319
282
 
320
283
  .type-tag {
321
284
  display: inline-flex; align-items: center; gap: 6px;
@@ -325,8 +288,8 @@ input, textarea, select { font-family: inherit; }
325
288
  /* ---------- Tables ---------- */
326
289
  .tbl { width: 100%; border-collapse: collapse; }
327
290
  .tbl thead th {
328
- font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.1em; text-transform: uppercase;
329
- color: var(--ink-muted); font-weight: 500; text-align: left;
291
+ font-family: var(--font-body); font-size: 10.5px; line-height: 1; letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
292
+ color: var(--ink-muted); font-weight: 700; text-align: left;
330
293
  padding: 0 14px 11px; border-bottom: 1px solid var(--border);
331
294
  }
332
295
  .tbl tbody td { padding: 13px 14px; border-bottom: 1px solid var(--border-soft); vertical-align: middle; }
@@ -339,7 +302,7 @@ input, textarea, select { font-family: inherit; }
339
302
  .field-label .req { color: var(--red); }
340
303
  .input, .textarea, .selectbox {
341
304
  width: 100%; background: var(--field); border: 1px solid var(--field-border);
342
- border-radius: var(--radius-sm); color: var(--ink); font-size: 14px;
305
+ border-radius: var(--legacy-radius-sm); color: var(--ink); font-size: 14px;
343
306
  padding: 10px 12px; outline: none; transition: border-color .14s, box-shadow .14s;
344
307
  }
345
308
  .input:focus, .textarea:focus, .selectbox:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
@@ -348,13 +311,13 @@ input, textarea, select { font-family: inherit; }
348
311
  .help { font-size: 12px; color: var(--ink-muted); margin-top: 6px; line-height: 1.5; }
349
312
 
350
313
  /* segmented control */
351
- .seg { display: inline-flex; background: var(--panel-2); border: 1px solid var(--border); border-radius: 9px; padding: 3px; gap: 2px; }
314
+ .seg { display: inline-flex; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-control); padding: 0; gap: 0; overflow: hidden; }
352
315
  .seg button {
353
316
  border: 0; background: transparent; color: var(--ink-muted); font-size: 12.5px; font-weight: 600;
354
- padding: 6px 13px; border-radius: 6px; transition: all .12s; display: inline-flex; align-items: center; gap: 7px;
317
+ padding: 8px 13px; border-radius: 0; transition: all .12s; display: inline-flex; align-items: center; gap: 7px;
355
318
  }
356
- .seg button.on { background: var(--panel); color: var(--ink); box-shadow: var(--shadow-sm); }
357
- [data-theme="dark"] .seg button.on { background: var(--hover); }
319
+ .seg button.on { background: var(--surface-inverse); color: var(--text-on-dark); box-shadow: none; }
320
+ [data-theme="dark"] .seg button.on { background: var(--surface-inverse); color: var(--surface-page); }
358
321
 
359
322
  /* ---------- Misc ---------- */
360
323
  .divider { height: 1px; background: var(--border); border: 0; margin: var(--gap) 0; }
@@ -367,10 +330,22 @@ input, textarea, select { font-family: inherit; }
367
330
  .grid-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
368
331
  .grid-split, .grid-split-wide { grid-template-columns: 1fr; }
369
332
  }
333
+ @media (max-width: 900px) {
334
+ .editor-document { width: calc(100% - 40px); padding: 32px; }
335
+ }
336
+ @media (max-width: 720px) {
337
+ .page { padding: 20px 16px 48px; }
338
+ .page-head { align-items: flex-start; flex-direction: column; }
339
+ .grid-stats { grid-template-columns: 1fr; }
340
+ .topbar { padding: 0 12px; gap: 8px; }
341
+ .topbar .search { max-width: none; }
342
+ .topbar .search input, .topbar .search .kbd { display: none; }
343
+ .editor-document { width: calc(100% - 24px); margin-top: 16px; padding: 20px; }
344
+ }
370
345
  .tag-chip {
371
346
  display: inline-flex; align-items: center; gap: 6px;
372
347
  font-size: 12px; color: var(--ink-soft); background: var(--panel-2);
373
- border: 1px solid var(--border); border-radius: 20px; padding: 3px 10px;
348
+ border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 3px 10px;
374
349
  }
375
350
  .tag-chip .x { color: var(--ink-faint); }
376
351
  .tag-chip .x:hover { color: var(--red); }
@@ -406,16 +381,16 @@ input, textarea, select { font-family: inherit; }
406
381
 
407
382
  /* ── Typed editorial blocks (Phase 1) ──────────────────────────────────── */
408
383
  .ProseMirror div[data-callout] { border-left: 3px solid var(--accent); background: var(--panel-2); border-radius: 6px; padding: 10px 14px; margin: 1em 0; }
409
- .ProseMirror div[data-callout][data-tone="warning"], .ProseMirror div[data-callout][data-tone="caution"] { border-left-color: #b45309; }
410
- .ProseMirror div[data-callout][data-tone="tip"] { border-left-color: #15803d; }
411
- .ProseMirror div[data-callout][data-tone="important"] { border-left-color: #7c3aed; }
384
+ .ProseMirror div[data-callout][data-tone="warning"], .ProseMirror div[data-callout][data-tone="caution"] { border-left-color: var(--gl-orange); }
385
+ .ProseMirror div[data-callout][data-tone="tip"] { border-left-color: var(--accent-primary-strong); }
386
+ .ProseMirror div[data-callout][data-tone="important"] { border-left-color: var(--gl-violet); }
412
387
  .ProseMirror figure[data-pull-quote] { border-left: 3px solid var(--ink-faint); margin: 1.5em 0; padding: 4px 18px; font-size: 1.15em; font-style: italic; color: var(--ink-soft); }
413
388
  .ProseMirror figure[data-pull-quote][data-attribution]::after { content: "— " attr(data-attribution); display: block; font-size: 0.8em; font-style: normal; color: var(--ink-faint); margin-top: 6px; }
414
389
  .ProseMirror div[data-generated-faq] { border: 1px dashed var(--border); border-radius: 6px; padding: 8px 12px; margin: 1em 0; color: var(--ink-faint); font-size: 0.85em; user-select: none; }
415
390
  .ProseMirror a[data-citation] { text-decoration: underline dotted; color: var(--accent); }
416
391
 
417
392
  /* ── Slash menu + drag handle ─────────────────────────────────────────── */
418
- .slash-menu { position: absolute; z-index: 90; min-width: 240px; max-height: 320px; overflow-y: auto; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.18); padding: 4px; }
393
+ .slash-menu { position: absolute; z-index: 90; min-width: 240px; max-height: 320px; overflow-y: auto; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-control); box-shadow: var(--shadow-raised); padding: 4px; }
419
394
  .slash-menu-item { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; width: 100%; padding: 6px 10px; border: 0; border-radius: 6px; background: transparent; cursor: pointer; text-align: left; }
420
395
  .slash-menu-item.is-selected, .slash-menu-item:hover { background: var(--hover); }
421
396
  .slash-menu-title { font-size: 13px; font-weight: 600; color: var(--ink); }