@hanzlaa/rcode 3.3.2 → 3.4.1

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 (111) hide show
  1. package/README.md +23 -38
  2. package/cli/index.js +0 -0
  3. package/cli/install.js +37 -29
  4. package/cli/update.js +17 -20
  5. package/dist/rcode.js +52 -48
  6. package/package.json +10 -10
  7. package/rihal/agents/rihal-assumptions-analyzer.md +1 -1
  8. package/rihal/agents/rihal-fatima.md +1 -0
  9. package/rihal/agents/rihal-integration-checker.md +1 -0
  10. package/rihal/agents/rihal-khalid.md +1 -0
  11. package/rihal/agents/rihal-noor.md +1 -0
  12. package/rihal/agents/rihal-project-researcher.md +1 -0
  13. package/rihal/agents/rihal-research-synthesizer.md +1 -0
  14. package/rihal/agents/rihal-waleed.md +1 -0
  15. package/rihal/skills/actions/1-analysis/research/rihal-domain-research/SKILL.md +2 -0
  16. package/rihal/skills/actions/1-analysis/research/rihal-market-research/SKILL.md +2 -0
  17. package/rihal/skills/actions/1-analysis/research/rihal-technical-research/SKILL.md +2 -0
  18. package/rihal/skills/actions/1-analysis/rihal-document-project/SKILL.md +2 -0
  19. package/rihal/skills/actions/1-analysis/rihal-prfaq/SKILL.md +2 -0
  20. package/rihal/skills/actions/1-analysis/rihal-product-brief/SKILL.md +2 -0
  21. package/rihal/skills/actions/2-plan/rihal-create-epics-and-stories/SKILL.md +2 -0
  22. package/rihal/skills/actions/2-plan/rihal-create-milestone/SKILL.md +2 -0
  23. package/rihal/skills/actions/2-plan/rihal-create-prd/SKILL.md +2 -0
  24. package/rihal/skills/actions/2-plan/rihal-create-story/SKILL.md +2 -0
  25. package/rihal/skills/actions/2-plan/rihal-create-ux-design/SKILL.md +2 -0
  26. package/rihal/skills/actions/2-plan/rihal-edit-prd/SKILL.md +2 -0
  27. package/rihal/skills/actions/2-plan/rihal-frontend-design/SKILL.md +2 -0
  28. package/rihal/skills/actions/2-plan/rihal-validate-prd/SKILL.md +2 -0
  29. package/rihal/skills/actions/3-solutioning/rihal-check-implementation-readiness/SKILL.md +2 -0
  30. package/rihal/skills/actions/3-solutioning/rihal-create-architecture/SKILL.md +2 -0
  31. package/rihal/skills/actions/3-solutioning/rihal-generate-project-context/SKILL.md +2 -0
  32. package/rihal/skills/actions/4-implementation/rihal-browser-verify/SKILL.md +2 -0
  33. package/rihal/skills/actions/4-implementation/rihal-ci/SKILL.md +2 -0
  34. package/rihal/skills/actions/4-implementation/rihal-code-review/SKILL.md +2 -0
  35. package/rihal/skills/actions/4-implementation/rihal-correct-course/SKILL.md +2 -0
  36. package/rihal/skills/actions/4-implementation/rihal-debug/SKILL.md +2 -0
  37. package/rihal/skills/actions/4-implementation/rihal-dev-story/SKILL.md +2 -0
  38. package/rihal/skills/actions/4-implementation/rihal-git-flow/SKILL.md +2 -0
  39. package/rihal/skills/actions/4-implementation/rihal-harden/SKILL.md +2 -0
  40. package/rihal/skills/actions/4-implementation/rihal-incremental/SKILL.md +2 -0
  41. package/rihal/skills/actions/4-implementation/rihal-migrate/SKILL.md +2 -0
  42. package/rihal/skills/actions/4-implementation/rihal-perf/SKILL.md +2 -0
  43. package/rihal/skills/actions/4-implementation/rihal-prove-it/SKILL.md +2 -0
  44. package/rihal/skills/actions/4-implementation/rihal-qa-generate-e2e-tests/SKILL.md +2 -0
  45. package/rihal/skills/actions/4-implementation/rihal-retrospective/SKILL.md +2 -0
  46. package/rihal/skills/actions/4-implementation/rihal-scaffold-project/SKILL.md +2 -0
  47. package/rihal/skills/actions/4-implementation/rihal-source-truth/SKILL.md +2 -0
  48. package/rihal/skills/actions/4-implementation/rihal-sprint-planning/SKILL.md +2 -0
  49. package/rihal/skills/actions/4-implementation/rihal-sprint-status/SKILL.md +2 -0
  50. package/rihal/skills/actions/4-implementation/rihal-trim/SKILL.md +2 -0
  51. package/rihal/skills/agents/ahmed-hassani-director/SKILL.md +2 -0
  52. package/rihal/skills/agents/dalil-scout/SKILL.md +2 -0
  53. package/rihal/skills/agents/fatima-qa/SKILL.md +2 -0
  54. package/rihal/skills/agents/haitham-frontend/SKILL.md +2 -0
  55. package/rihal/skills/agents/hanzla-engineer/SKILL.md +2 -0
  56. package/rihal/skills/agents/hussain-pm/SKILL.md +2 -0
  57. package/rihal/skills/agents/hussain-sm/SKILL.md +2 -0
  58. package/rihal/skills/agents/layla-designer/SKILL.md +2 -0
  59. package/rihal/skills/agents/majlis-council/SKILL.md +2 -0
  60. package/rihal/skills/agents/mariam-marketing/SKILL.md +2 -0
  61. package/rihal/skills/agents/nasser-eng-manager/SKILL.md +2 -0
  62. package/rihal/skills/agents/noor-writer/SKILL.md +2 -0
  63. package/rihal/skills/agents/raees-orchestrator/SKILL.md +2 -0
  64. package/rihal/skills/agents/sadiq-analyst/SKILL.md +2 -0
  65. package/rihal/skills/agents/waleed-architect/SKILL.md +2 -0
  66. package/rihal/skills/agents/yousef-backend/SKILL.md +2 -0
  67. package/rihal/skills/agents/zahra-branding/SKILL.md +2 -0
  68. package/rihal/skills/agents/zayd-ml/SKILL.md +2 -0
  69. package/rihal/skills/core/rihal-advanced-elicitation/SKILL.md +2 -0
  70. package/rihal/skills/core/rihal-auth-audit/SKILL.md +2 -0
  71. package/rihal/skills/core/rihal-brainstorming/SKILL.md +2 -0
  72. package/rihal/skills/core/rihal-client-gate/SKILL.md +2 -0
  73. package/rihal/skills/core/rihal-clone-website/SKILL.md +2 -0
  74. package/rihal/skills/core/rihal-deploy-unify/SKILL.md +2 -0
  75. package/rihal/skills/core/rihal-distillator/SKILL.md +2 -0
  76. package/rihal/skills/core/rihal-editorial-review-prose/SKILL.md +2 -0
  77. package/rihal/skills/core/rihal-editorial-review-structure/SKILL.md +2 -0
  78. package/rihal/skills/core/rihal-help/SKILL.md +2 -0
  79. package/rihal/skills/core/rihal-incident-record/SKILL.md +2 -0
  80. package/rihal/skills/core/rihal-index-docs/SKILL.md +2 -0
  81. package/rihal/skills/core/rihal-init/SKILL.md +2 -0
  82. package/rihal/skills/core/rihal-memory-audit/SKILL.md +2 -0
  83. package/rihal/skills/core/rihal-memory-distill/SKILL.md +2 -0
  84. package/rihal/skills/core/rihal-memory-init/SKILL.md +2 -0
  85. package/rihal/skills/core/rihal-memory-update/SKILL.md +2 -0
  86. package/rihal/skills/core/rihal-mvp-graduate/SKILL.md +2 -0
  87. package/rihal/skills/core/rihal-ocr-consistency/SKILL.md +2 -0
  88. package/rihal/skills/core/rihal-party-mode/SKILL.md +2 -0
  89. package/rihal/skills/core/rihal-rebrand/SKILL.md +2 -0
  90. package/rihal/skills/core/rihal-review-adversarial-general/SKILL.md +2 -0
  91. package/rihal/skills/core/rihal-review-edge-case-hunter/SKILL.md +2 -0
  92. package/rihal/skills/core/rihal-shard-doc/SKILL.md +2 -0
  93. package/rihal/skills/core/rihal-theme-system/SKILL.md +2 -0
  94. package/rihal/workflows/add-tests.md +1 -0
  95. package/rihal/workflows/audit-fix.md +2 -0
  96. package/rihal/workflows/autonomous.md +1 -0
  97. package/rihal/workflows/code-review-fix.md +2 -1
  98. package/rihal/workflows/debug.md +1 -0
  99. package/rihal/workflows/dev-story.md +1 -0
  100. package/rihal/workflows/execute-sprint.md +1 -0
  101. package/rihal/workflows/execute.md +1 -0
  102. package/rihal/workflows/init.md +82 -0
  103. package/rihal/workflows/plan.md +1 -0
  104. package/rihal/workflows/ship.md +2 -0
  105. package/rihal/workflows/sprint-planning.md +1 -0
  106. package/rihal/workflows/validate-phase.md +1 -0
  107. package/rihal/workflows/verify-phase.md +1 -0
  108. package/server/lib/api.js +49 -0
  109. package/server/lib/html/client.js +100 -10
  110. package/server/lib/html/css.js +64 -1
  111. package/server/lib/html/shell.js +11 -5
@@ -32,7 +32,7 @@ function chip(s) {
32
32
  return '<span class="status-chip ' + c + '">● ' + s + '</span>';
33
33
  }
34
34
  function tag(t) { return '<span class="tag">' + t + '</span>'; }
35
- function esc(s) { return String(s || '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }
35
+ function esc(s) { return String(s || '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;'); }
36
36
  function pct(d, t) { return t > 0 ? Math.round(d/t*100) + '%' : '—'; }
37
37
  function pctNum(d, t) { return t > 0 ? Math.round(d/t*100) : 0; }
38
38
  function dateStr(s) { return s ? String(s).slice(0,10) : null; }
@@ -197,16 +197,55 @@ function sprintCard(s) {
197
197
 
198
198
  function taskCard(t) {
199
199
  const done = t.status === 'done' || t.status === 'completed';
200
- return '<div class="item" data-status="' + (t.status||'') + '" style="' + (done ? 'opacity:.65' : '') + '">' +
200
+ const tid = 'task-' + (t.id || t.title || '').replace(/[^a-zA-Z0-9]/g, '-').slice(0, 40) + '-' + Math.random().toString(36).slice(2, 6);
201
+ // Build detail rows from all available context
202
+ var rows = '';
203
+ if (t.id) rows += '<div class="task-detail-row"><strong>ID:</strong> <code>' + esc(t.id) + '</code></div>';
204
+ if (t.points) rows += '<div class="task-detail-row"><strong>Points:</strong> ' + t.points + '</div>';
205
+ rows += '<div class="task-detail-row"><strong>Status:</strong> ' + chip(t.status || 'unknown') + '</div>';
206
+ if (t.sprintId) rows += '<div class="task-detail-row"><strong>Sprint:</strong> ' + esc(t.sprintId) + '</div>';
207
+ if (t.sprintGoal) rows += '<div class="task-detail-row"><strong>Sprint Goal:</strong> ' + esc(t.sprintGoal) + '</div>';
208
+ if (t.phaseId) rows += '<div class="task-detail-row"><strong>Phase:</strong> P' + esc(t.phaseId) + (t.phaseName ? ' — ' + esc(t.phaseName) : '') + '</div>';
209
+ if (t.acceptance) rows += '<div class="task-detail-row"><strong>Acceptance:</strong> ' + esc(t.acceptance) + '</div>';
210
+ if (t.assignee) rows += '<div class="task-detail-row"><strong>Assignee:</strong> ' + esc(t.assignee) + '</div>';
211
+ // Context-aware commands for this specific task
212
+ var cmds = '';
213
+ if (t.id) {
214
+ var taskCmds = [];
215
+ if (!done) {
216
+ taskCmds.push(cmdHint('/rihal-dev-story ' + t.id, 'Implement this story'));
217
+ taskCmds.push(cmdHint('/rihal-create-story ' + (t.sprintId || ''), 'Add related story'));
218
+ } else {
219
+ taskCmds.push(cmdHint('/rihal-verify-work ' + t.id, 'Verify this story'));
220
+ taskCmds.push(cmdHint('/rihal-code-review ' + t.id, 'Review code for this story'));
221
+ }
222
+ if (t.sprintId) {
223
+ taskCmds.push(cmdHint('/rihal-sprint-status ' + t.sprintId, 'Sprint ' + t.sprintId + ' status'));
224
+ }
225
+ cmds = '<div class="task-detail-cmds">' + taskCmds.join('') + '</div>';
226
+ }
227
+ return '<div class="item item-clickable" data-status="' + (t.status||'') + '" style="' + (done ? 'opacity:.65' : '') + '"' +
228
+ ' onclick="toggleTaskDetail(\\'' + tid + '\\')">' +
201
229
  '<div class="item-title" style="' + (done ? 'text-decoration:line-through' : '') + '">' +
202
- (done ? '✓ ' : '') + esc(t.title) + chip(t.status) + '</div>' +
230
+ (done ? '✓ ' : '') + esc(t.title) + chip(t.status) +
231
+ '<span class="task-expand-icon" id="icon-' + tid + '">▶</span></div>' +
203
232
  '<div class="item-meta">' +
204
233
  (t.points ? tag(t.points + 'pts') : '') +
234
+ (t.id ? tag(t.id) : '') +
205
235
  (t.sprintId ? tag('Sprint ' + t.sprintId) : '') +
206
236
  (t.phaseId ? tag('Phase ' + t.phaseId) : '') + '</div>' +
207
- (t.acceptance ? '<div style="color:var(--text-muted);font-size:var(--text-xs);margin-top:4px;">✓ ' + esc(t.acceptance) + '</div>' : '') +
237
+ '<div class="task-detail" id="' + tid + '" style="display:none;">' +
238
+ rows + cmds + '</div>' +
208
239
  '</div>';
209
240
  }
241
+ function toggleTaskDetail(id) {
242
+ const el = document.getElementById(id);
243
+ const icon = document.getElementById('icon-' + id);
244
+ if (!el) return;
245
+ const open = el.style.display !== 'none';
246
+ el.style.display = open ? 'none' : 'block';
247
+ if (icon) icon.textContent = open ? '▶' : '▼';
248
+ }
210
249
 
211
250
  // ---- View renderers ----
212
251
  function renderOverview() {
@@ -464,7 +503,8 @@ function renderSprints(subId) {
464
503
  if (subId) {
465
504
  const s = sprints.find(sp => sp.id === subId);
466
505
  if (!s) { el.innerHTML = breadcrumb('All Sprints','sprints') + '<div class="empty">Sprint not found.</div>'; return; }
467
- const stories = Array.isArray(s.stories) ? s.stories : [];
506
+ const rawStories = Array.isArray(s.stories) ? s.stories : [];
507
+ const stories = rawStories.map(function(t) { return Object.assign({}, t, {sprintId: s.id, sprintGoal: s.goal || '', phaseId: s.phaseId, phaseName: s.phaseName}); });
468
508
  const done = stories.filter(t => t.status==='done'||t.status==='completed').length;
469
509
  // #290: acceptance criteria
470
510
  let acHtml = '';
@@ -783,9 +823,20 @@ function filterItems(input, listId) {
783
823
  let h = '<div style="padding:0 var(--space-2) var(--space-2);"><input class="filter-input" style="width:100%;max-width:none;" type="text" placeholder="Search files…" id="file-tree-search" oninput="filterFileTree(this.value)"></div>';
784
824
  h += '<div class="file-tree" id="file-tree-items">';
785
825
  h += groups.map(function(g) {
826
+ // Support sub-groups (e.g. Phases with per-phase sub-groups)
827
+ if (g.subGroups) {
828
+ return '<details class="file-tree-group" open><summary>' + g.group + '</summary>' +
829
+ g.subGroups.map(function(sg) {
830
+ return '<details class="file-tree-subgroup" open style="margin-left:var(--space-2);margin-bottom:var(--space-1);">' +
831
+ '<summary style="font-size:var(--text-xs);font-weight:500;color:var(--text-secondary);cursor:pointer;padding:var(--space-1) 0;user-select:none;">' + sg.subGroup + ' <span style="color:var(--text-muted);font-weight:400;">(' + sg.files.length + ')</span></summary>' +
832
+ sg.files.map(function(f) {
833
+ return '<span class="file-tree-item" data-path="' + esc(f.path) + '" data-filter-text="' + esc(f.label + ' ' + f.path + ' ' + sg.subGroup).toLowerCase() + '" style="padding-left:var(--space-4);">' + esc(f.label) + '</span>';
834
+ }).join('') + '</details>';
835
+ }).join('') + '</details>';
836
+ }
786
837
  return '<details class="file-tree-group" open><summary>' + g.group + '</summary>' +
787
838
  g.files.map(function(f) {
788
- return '<span class="file-tree-item" data-path="' + f.path + '" data-filter-text="' + (f.label + ' ' + f.path).toLowerCase() + '">' + f.label + '</span>';
839
+ return '<span class="file-tree-item" data-path="' + esc(f.path) + '" data-filter-text="' + esc(f.label + ' ' + f.path).toLowerCase() + '">' + esc(f.label) + '</span>';
789
840
  }).join('') + '</details>';
790
841
  }).join('');
791
842
  h += '</div>';
@@ -799,6 +850,8 @@ function filterItems(input, listId) {
799
850
  var fv = document.getElementById('file-view');
800
851
  // #315: loading skeleton
801
852
  fv.innerHTML = '<div class="skeleton"></div><div class="skeleton" style="height:200px;"></div>';
853
+ // Scroll file content into view
854
+ fv.scrollIntoView({ behavior: 'smooth', block: 'start' });
802
855
  try {
803
856
  var resp = await fetch('/api/file?path=' + encodeURIComponent(item.dataset.path));
804
857
  if (!resp.ok) { fv.innerHTML = '<div style="color:var(--accent-red);padding:16px;">Failed to load file.</div>'; return; }
@@ -819,12 +872,30 @@ function filterItems(input, listId) {
819
872
  if (!el) return;
820
873
  let h = '<div class="filter-bar"><input class="filter-input" type="text" placeholder="Search files…" oninput="filterInlineFiles(this.value)"></div>';
821
874
  h += '<div id="inline-file-items" class="phase-list">';
875
+
876
+ function renderFileItem(f, extraFilterText) {
877
+ var filterText = esc(f.label + ' ' + f.path + (extraFilterText ? ' ' + extraFilterText : '')).toLowerCase();
878
+ return '<div class="item item-clickable inline-file-entry" data-path="' + esc(f.path) + '" data-filter-text="' + filterText + '" onclick="loadInlineFile(this)" style="padding:var(--space-2) var(--space-3);font-family:\\'SF Mono\\',Monaco,Consolas,monospace;font-size:var(--text-xs);">' + esc(f.label) + '</div>';
879
+ }
880
+
822
881
  groups.forEach(function(g) {
823
882
  h += '<div class="inline-file-group" style="margin-bottom:var(--space-3);">';
824
- h += '<div style="font-size:var(--text-xs);font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.07em;padding:var(--space-1) 0;">' + g.group + '</div>';
825
- g.files.forEach(function(f) {
826
- h += '<div class="item item-clickable inline-file-entry" data-path="' + esc(f.path) + '" data-filter-text="' + esc(f.label + ' ' + f.path).toLowerCase() + '" onclick="loadInlineFile(this)" style="padding:var(--space-2) var(--space-3);font-family:\\'SF Mono\\',Monaco,Consolas,monospace;font-size:var(--text-xs);">' + esc(f.label) + '</div>';
827
- });
883
+ h += '<div style="font-size:var(--text-xs);font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:0.07em;padding:var(--space-1) 0;">' + esc(g.group) + '</div>';
884
+ if (g.subGroups) {
885
+ // Render expandable sub-groups (e.g. per-phase)
886
+ g.subGroups.forEach(function(sg) {
887
+ h += '<details class="inline-subgroup" open style="margin-left:var(--space-2);margin-bottom:var(--space-1);">';
888
+ h += '<summary style="font-size:var(--text-xs);font-weight:500;color:var(--text-secondary);cursor:pointer;padding:var(--space-1) 0;user-select:none;">' + esc(sg.subGroup) + ' <span style="color:var(--text-muted);font-weight:400;">(' + sg.files.length + ')</span></summary>';
889
+ sg.files.forEach(function(f) {
890
+ h += renderFileItem(f, sg.subGroup);
891
+ });
892
+ h += '</details>';
893
+ });
894
+ } else if (g.files) {
895
+ g.files.forEach(function(f) {
896
+ h += renderFileItem(f, '');
897
+ });
898
+ }
828
899
  h += '</div>';
829
900
  });
830
901
  h += '</div>';
@@ -840,6 +911,8 @@ async function loadInlineFile(el) {
840
911
  var fv = document.getElementById('file-view');
841
912
  if (!fv) return;
842
913
  fv.innerHTML = '<div class="skeleton"></div><div class="skeleton" style="height:200px;"></div>';
914
+ // Scroll file content into view immediately
915
+ fv.scrollIntoView({ behavior: 'smooth', block: 'start' });
843
916
  document.querySelectorAll('.inline-file-entry').forEach(function(e) { e.style.borderLeftColor = ''; });
844
917
  el.style.borderLeftColor = 'var(--accent-blue)';
845
918
  // Also sync sidebar selection
@@ -1023,6 +1096,23 @@ function updateTitle() {
1023
1096
  }
1024
1097
  window.addEventListener('hashchange', updateTitle);
1025
1098
 
1099
+ // Sidebar toggle (hamburger menu)
1100
+ function toggleSidebar() {
1101
+ var sidebar = document.querySelector('.sidebar');
1102
+ var backdrop = document.getElementById('sidebar-backdrop');
1103
+ if (!sidebar) return;
1104
+ var open = sidebar.classList.toggle('sidebar-open');
1105
+ if (backdrop) backdrop.classList.toggle('active', open);
1106
+ document.body.classList.toggle('sidebar-visible', open);
1107
+ }
1108
+ function closeSidebar() {
1109
+ var sidebar = document.querySelector('.sidebar');
1110
+ var backdrop = document.getElementById('sidebar-backdrop');
1111
+ if (sidebar) sidebar.classList.remove('sidebar-open');
1112
+ if (backdrop) backdrop.classList.remove('active');
1113
+ document.body.classList.remove('sidebar-visible');
1114
+ }
1115
+
1026
1116
  // ---- Boot ----
1027
1117
  route();
1028
1118
  updateTitle();
@@ -186,6 +186,36 @@ function renderCss() {
186
186
  .item .item-meta { color: var(--text-muted); font-size: var(--text-xs); margin-bottom: var(--space-2); }
187
187
  .item-clickable { cursor: pointer; }
188
188
  .item-clickable:hover { background: var(--bg-hover); border-color: var(--accent-blue); }
189
+
190
+ /* Task expandable detail */
191
+ .task-expand-icon {
192
+ float: right; font-size: 10px; color: var(--text-muted);
193
+ transition: transform 0.2s ease;
194
+ }
195
+ .task-detail {
196
+ margin-top: var(--space-3); padding-top: var(--space-3);
197
+ border-top: 1px solid var(--border); font-size: var(--text-sm);
198
+ }
199
+ .task-detail-row { margin-bottom: var(--space-2); color: var(--text-secondary); line-height: 1.5; }
200
+ .task-detail-row strong { color: var(--text-primary); }
201
+
202
+ /* Hamburger & sidebar toggle */
203
+ .hamburger-btn {
204
+ display: none; background: none; border: 1px solid var(--border);
205
+ border-radius: var(--radius-sm); padding: 6px 8px; cursor: pointer;
206
+ flex-direction: column; gap: 4px; align-items: center; justify-content: center;
207
+ }
208
+ .hamburger-btn span {
209
+ display: block; width: 18px; height: 2px; background: var(--text-primary);
210
+ border-radius: 1px; transition: 0.2s;
211
+ }
212
+ .hamburger-btn:hover { background: var(--bg-hover); }
213
+ #sidebar-backdrop {
214
+ display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.5);
215
+ z-index: 90;
216
+ }
217
+ #sidebar-backdrop.active { display: block; }
218
+
189
219
  .empty { color: var(--text-muted); text-align: center; padding: var(--space-8); font-style: italic; }
190
220
  /* #316 Actionable empty states */
191
221
  .empty-action {
@@ -332,6 +362,17 @@ function renderCss() {
332
362
  cursor: pointer; font-size: var(--text-xs); font-family: inherit;
333
363
  }
334
364
  .file-path-header .copy-btn:hover { color: var(--text-primary); }
365
+ /* File view layout */
366
+ #view-files { display: flex; flex-direction: column; }
367
+ #file-list-inline { margin-bottom: var(--space-4); }
368
+ #file-view { min-height: 200px; }
369
+ .inline-subgroup summary { list-style: none; cursor: pointer; }
370
+ .inline-subgroup summary::-webkit-details-marker { display: none; }
371
+ .inline-subgroup summary:hover { color: var(--text-primary); }
372
+ .file-tree-subgroup summary { list-style: none; cursor: pointer; }
373
+ .file-tree-subgroup summary::-webkit-details-marker { display: none; }
374
+ .file-tree-subgroup > summary::before { content: '▶ '; font-size: 9px; display: inline-block; }
375
+ .file-tree-subgroup[open] > summary::before { content: '▼ '; }
335
376
  /* Footer */
336
377
  footer {
337
378
  text-align: center; padding: var(--space-8); color: var(--text-muted); font-size: var(--text-sm);
@@ -361,7 +402,13 @@ function renderCss() {
361
402
  }
362
403
  /* #323 Responsive */
363
404
  @media (max-width: 768px) {
364
- .sidebar { display: none; }
405
+ .hamburger-btn { display: flex; }
406
+ .sidebar {
407
+ display: flex; position: fixed; left: -260px; top: 0; bottom: 0;
408
+ z-index: 100; transition: left 0.25s ease;
409
+ background: var(--bg-sidebar); box-shadow: 2px 0 12px rgba(0,0,0,0.3);
410
+ }
411
+ .sidebar.sidebar-open { left: 0; }
365
412
  .content-area { width: 100%; }
366
413
  .view { padding: var(--space-4); }
367
414
  header { padding: var(--space-3) var(--space-4); flex-wrap: wrap; gap: var(--space-2); }
@@ -371,6 +418,12 @@ function renderCss() {
371
418
  .agents { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
372
419
  .attr-grid { grid-template-columns: 1fr 1fr; }
373
420
  }
421
+ /* Desktop sidebar toggle */
422
+ @media (min-width: 769px) {
423
+ .hamburger-btn { display: flex; }
424
+ .sidebar { transition: margin-left 0.25s ease, opacity 0.25s ease; }
425
+ body.sidebar-visible .sidebar { margin-left: 0; opacity: 1; }
426
+ }
374
427
  /* Command hints accordion */
375
428
  .cmd-hints {
376
429
  margin-top: var(--space-4); border: 1px solid var(--border); border-radius: var(--radius-md);
@@ -402,6 +455,16 @@ function renderCss() {
402
455
  font-size: 10px; color: var(--text-muted); opacity: 0; transition: opacity 0.15s; margin-left: auto;
403
456
  }
404
457
  .cmd-hint-item:hover .cmd-copy { opacity: 1; }
458
+ /* Task detail inline commands */
459
+ .task-detail-cmds {
460
+ margin-top: var(--space-3); padding-top: var(--space-3);
461
+ border-top: 1px solid var(--border);
462
+ }
463
+ .task-detail-cmds::before {
464
+ content: '💡 Quick Commands'; display: block; font-size: var(--text-xs);
465
+ color: var(--text-muted); font-weight: 600; margin-bottom: var(--space-2);
466
+ text-transform: uppercase; letter-spacing: 0.5px;
467
+ }
405
468
  /* Toast notification (for copy feedback) */
406
469
  .toast {
407
470
  position: fixed; bottom: 20px; right: 20px; background: var(--accent-green);
@@ -85,13 +85,19 @@ ${renderCss()}
85
85
  </nav>
86
86
  <div id="sidebar-file-tree" style="margin-top:var(--space-4);padding:0 var(--space-2);"></div>
87
87
  </aside>
88
+ <div id="sidebar-backdrop" onclick="closeSidebar()"></div>
88
89
  <div class="content-area" id="main-content">
89
90
  <header>
90
- <div class="brand">
91
- <div class="icon">🕌</div>
92
- <div>
93
- <h1>Majlis — The Council</h1>
94
- <div class="arabic">مجلس · ${esc(projectName)}</div>
91
+ <div style="display:flex;align-items:center;gap:var(--space-3);">
92
+ <button class="hamburger-btn" id="hamburger-btn" onclick="toggleSidebar()" aria-label="Toggle menu">
93
+ <span></span><span></span><span></span>
94
+ </button>
95
+ <div class="brand">
96
+ <div class="icon">🕌</div>
97
+ <div>
98
+ <h1>Majlis — The Council</h1>
99
+ <div class="arabic">مجلس · ${esc(projectName)}</div>
100
+ </div>
95
101
  </div>
96
102
  </div>
97
103
  <div class="header-actions">