parapet-rails 0.1.0

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 (231) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +48 -0
  4. data/Rakefile +7 -0
  5. data/app/assets/config/parapet/grammar-registry.json +52 -0
  6. data/app/assets/images/parapet/icons/activities/component-inspector.svg +4 -0
  7. data/app/assets/images/parapet/icons/activities/coverage-heatmap.svg +3 -0
  8. data/app/assets/images/parapet/icons/activities/discovery-sidebar.svg +3 -0
  9. data/app/assets/images/parapet/icons/activities/environment-toggles.svg +4 -0
  10. data/app/assets/images/parapet/icons/activities/failure-inspector.svg +5 -0
  11. data/app/assets/images/parapet/icons/activities/flaky-history.svg +3 -0
  12. data/app/assets/images/parapet/icons/activities/flight-recorder.svg +5 -0
  13. data/app/assets/images/parapet/icons/activities/health-graph.svg +3 -0
  14. data/app/assets/images/parapet/icons/activities/injection-engine.svg +3 -0
  15. data/app/assets/images/parapet/icons/activities/live-sql-stream.svg +5 -0
  16. data/app/assets/images/parapet/icons/activities/live-web-preview.svg +4 -0
  17. data/app/assets/images/parapet/icons/activities/monaco-editor.svg +5 -0
  18. data/app/assets/images/parapet/icons/activities/progress-area.svg +3 -0
  19. data/app/assets/images/parapet/icons/activities/registry-metadata.svg +5 -0
  20. data/app/assets/images/parapet/icons/activities/seed-inspector.svg +4 -0
  21. data/app/assets/images/parapet/icons/activities/slow-test-bottlenecks.svg +4 -0
  22. data/app/assets/images/parapet/icons/activities/smart-search.svg +4 -0
  23. data/app/assets/images/parapet/icons/activities/snippet-library.svg +4 -0
  24. data/app/assets/images/parapet/icons/activities/terminal.svg +4 -0
  25. data/app/assets/images/parapet/icons/activities/unified-schema-view.svg +4 -0
  26. data/app/assets/images/parapet/icons/activities/visual-comparison.svg +3 -0
  27. data/app/assets/images/parapet/icons/activities/visual-summary-bar.svg +5 -0
  28. data/app/assets/images/parapet/icons/nav/ideas.svg +4 -0
  29. data/app/assets/images/parapet/icons/nav/languages.svg +8 -0
  30. data/app/assets/images/parapet/icons/nav/profile.svg +4 -0
  31. data/app/assets/images/parapet/icons/nav/pulse.svg +7 -0
  32. data/app/assets/images/parapet/icons/nav/settings.svg +4 -0
  33. data/app/assets/images/parapet/icons/nav/state.svg +5 -0
  34. data/app/assets/images/parapet/icons/nav/styles.svg +7 -0
  35. data/app/assets/images/parapet/icons/nav/tests.svg +4 -0
  36. data/app/assets/images/parapet/icons/nav/traffic.svg +12 -0
  37. data/app/assets/javascripts/parapet/activity-card.js +439 -0
  38. data/app/assets/javascripts/parapet/activity-cards.js +291 -0
  39. data/app/assets/javascripts/parapet/activity-registry.js +181 -0
  40. data/app/assets/javascripts/parapet/activity-toggles.js +76 -0
  41. data/app/assets/javascripts/parapet/application.js +37 -0
  42. data/app/assets/javascripts/parapet/card-failure-inspector.js +134 -0
  43. data/app/assets/javascripts/parapet/card-file-editor.js +1722 -0
  44. data/app/assets/javascripts/parapet/card-progress-area.js +297 -0
  45. data/app/assets/javascripts/parapet/card-smart-search.js +114 -0
  46. data/app/assets/javascripts/parapet/card-snippet-library.js +251 -0
  47. data/app/assets/javascripts/parapet/explorer-resizer.js +92 -0
  48. data/app/assets/javascripts/parapet/parapet_qss.js +342 -0
  49. data/app/assets/javascripts/parapet/proficiency-filter.js +53 -0
  50. data/app/assets/javascripts/parapet/sidebar-resizer.js +197 -0
  51. data/app/assets/javascripts/parapet/styles-workbench.js +819 -0
  52. data/app/assets/javascripts/parapet/tree-logic.js +320 -0
  53. data/app/assets/stylesheets/parapet/_qss_variables.scss +122 -0
  54. data/app/assets/stylesheets/parapet/parapet_qss.scss +69 -0
  55. data/app/assets/stylesheets/parapet/qss_application.css +260940 -0
  56. data/app/assets/stylesheets/parapet/qss_application.css.map +1 -0
  57. data/app/assets/stylesheets/parapet/qss_application.scss +5 -0
  58. data/app/assets/stylesheets/parapet/qss_workspace.scss +209 -0
  59. data/app/assets/stylesheets/parapet/sample.qss +22 -0
  60. data/app/controllers/parapet/application_controller.rb +54 -0
  61. data/app/controllers/parapet/base_controller.rb +18 -0
  62. data/app/controllers/parapet/build_suite/dashboard_controller.rb +10 -0
  63. data/app/controllers/parapet/css_suite/compiler_controller.rb +95 -0
  64. data/app/controllers/parapet/css_suite/dashboard_controller.rb +10 -0
  65. data/app/controllers/parapet/css_suite/preview_controller.rb +46 -0
  66. data/app/controllers/parapet/dashboard_controller.rb +8 -0
  67. data/app/controllers/parapet/drafts_controller.rb +30 -0
  68. data/app/controllers/parapet/explorers_controller.rb +53 -0
  69. data/app/controllers/parapet/files_controller.rb +208 -0
  70. data/app/controllers/parapet/footers_controller.rb +24 -0
  71. data/app/controllers/parapet/intentions_suite/dashboard_controller.rb +10 -0
  72. data/app/controllers/parapet/landing_controller.rb +14 -0
  73. data/app/controllers/parapet/monitor_suite/dashboard_controller.rb +10 -0
  74. data/app/controllers/parapet/pm_suite/publish_controller.rb +16 -0
  75. data/app/controllers/parapet/polyglot_suite/dashboard_controller.rb +10 -0
  76. data/app/controllers/parapet/runner_controller.rb +34 -0
  77. data/app/controllers/parapet/sessions_controller.rb +35 -0
  78. data/app/controllers/parapet/signal_suite/dashboard_controller.rb +10 -0
  79. data/app/controllers/parapet/test_suite/dashboard_controller.rb +10 -0
  80. data/app/controllers/parapet/widgets_controller.rb +33 -0
  81. data/app/helpers/parapet/application_helper.rb +23 -0
  82. data/app/helpers/parapet/icon_helper.rb +57 -0
  83. data/app/jobs/parapet/application_job.rb +4 -0
  84. data/app/mailers/parapet/application_mailer.rb +6 -0
  85. data/app/models/parapet/activity.rb +14 -0
  86. data/app/models/parapet/application_record.rb +5 -0
  87. data/app/models/parapet/current.rb +6 -0
  88. data/app/models/parapet/draft_recovery.rb +9 -0
  89. data/app/models/parapet/internal_record.rb +34 -0
  90. data/app/models/parapet/run_history.rb +22 -0
  91. data/app/models/parapet/runtime_setting.rb +8 -0
  92. data/app/models/parapet/session.rb +7 -0
  93. data/app/models/parapet/suite_assignment.rb +30 -0
  94. data/app/models/parapet/user.rb +12 -0
  95. data/app/services/parapet/activity_phrase_renderer.rb +35 -0
  96. data/app/services/parapet/activity_writer.rb +26 -0
  97. data/app/services/parapet/authorization.rb +198 -0
  98. data/app/services/parapet/consistency_auditor.rb +58 -0
  99. data/app/services/parapet/directory_scanner.rb +159 -0
  100. data/app/services/parapet/draft_recovery_store.rb +18 -0
  101. data/app/services/parapet/explorer_manager.rb +402 -0
  102. data/app/services/parapet/file_save_service.rb +21 -0
  103. data/app/services/parapet/git_side_ref_committer.rb +50 -0
  104. data/app/services/parapet/noun_discovery.rb +26 -0
  105. data/app/services/parapet/publish_gate.rb +83 -0
  106. data/app/services/parapet/test_runner.rb +178 -0
  107. data/app/views/layouts/parapet/application.html.erb +83 -0
  108. data/app/views/layouts/parapet/landing.html.erb +19 -0
  109. data/app/views/parapet/activities/_ai_error_explainer.html.erb +33 -0
  110. data/app/views/parapet/activities/_ai_explainer_widget.html.erb +20 -0
  111. data/app/views/parapet/activities/_calendar_widget.html.erb +31 -0
  112. data/app/views/parapet/activities/_code_snippets_widget.html.erb +22 -0
  113. data/app/views/parapet/activities/_coverage_explorer.html.erb +1 -0
  114. data/app/views/parapet/activities/_dropdown_test.html.erb +20 -0
  115. data/app/views/parapet/activities/_explorer_node.html.erb +102 -0
  116. data/app/views/parapet/activities/_explorer_tree.html.erb +16 -0
  117. data/app/views/parapet/activities/_file_editor.html.erb +183 -0
  118. data/app/views/parapet/activities/_file_explorer.html.erb +23 -0
  119. data/app/views/parapet/activities/_fix_suggestions_widget.html.erb +13 -0
  120. data/app/views/parapet/activities/_generic.html.erb +6 -0
  121. data/app/views/parapet/activities/_live_preview.html.erb +13 -0
  122. data/app/views/parapet/activities/_perspective_filters.html.erb +36 -0
  123. data/app/views/parapet/activities/_progress_area.html.erb +37 -0
  124. data/app/views/parapet/activities/_project_explorer.html.erb +1 -0
  125. data/app/views/parapet/activities/_registry_explorer.html.erb +1 -0
  126. data/app/views/parapet/activities/_run_history.html.erb +2 -0
  127. data/app/views/parapet/activities/_smart_search.html.erb +11 -0
  128. data/app/views/parapet/activities/file_explorer/_perspective_scripts.html.erb +58 -0
  129. data/app/views/parapet/activities/file_explorer/_perspectives.html.erb +0 -0
  130. data/app/views/parapet/activities/file_explorer/_viewport_scripts.html.erb +33 -0
  131. data/app/views/parapet/css_suite/_workbench.html.erb +51 -0
  132. data/app/views/parapet/dashboards/index.html.erb +113 -0
  133. data/app/views/parapet/debug_panel.html.erb +79 -0
  134. data/app/views/parapet/debug_panel_tailwind.html.erb +98 -0
  135. data/app/views/parapet/erb_patch_test.html.erb +5 -0
  136. data/app/views/parapet/explorers/show.html.erb +1 -0
  137. data/app/views/parapet/git_viewer.html.erb +62 -0
  138. data/app/views/parapet/git_viewer_after.html.erb +14 -0
  139. data/app/views/parapet/git_viewer_before.html.erb +14 -0
  140. data/app/views/parapet/git_viewer_governed.html.erb +88 -0
  141. data/app/views/parapet/git_viewer_governed_after.html.erb +36 -0
  142. data/app/views/parapet/git_viewer_governed_before.html.erb +36 -0
  143. data/app/views/parapet/git_viewer_tailwind.html.erb +88 -0
  144. data/app/views/parapet/git_viewer_thin_wrapper.html.erb +85 -0
  145. data/app/views/parapet/hierarchical_layout_test.html.erb +85 -0
  146. data/app/views/parapet/hybrid_stress_test.html.erb +25 -0
  147. data/app/views/parapet/index.html.erb +35 -0
  148. data/app/views/parapet/mutation_stress_test.html.erb +82 -0
  149. data/app/views/parapet/recursive_anchoring_test.html.erb +66 -0
  150. data/app/views/parapet/sessions/new.html.erb +28 -0
  151. data/app/views/parapet/shared/_cad_inspector.html.erb +92 -0
  152. data/app/views/parapet/shared/_discovery_sidebar.html.erb +48 -0
  153. data/app/views/parapet/shared/_explorer_bar.html.erb +71 -0
  154. data/app/views/parapet/shared/_footer.html.erb +10 -0
  155. data/app/views/parapet/shared/_footer_ideas.html.erb +36 -0
  156. data/app/views/parapet/shared/_footer_languages.html.erb +33 -0
  157. data/app/views/parapet/shared/_footer_pulse.html.erb +33 -0
  158. data/app/views/parapet/shared/_footer_state.html.erb +33 -0
  159. data/app/views/parapet/shared/_footer_styles.html.erb +37 -0
  160. data/app/views/parapet/shared/_footer_tests.html.erb +39 -0
  161. data/app/views/parapet/shared/_footer_traffic.html.erb +45 -0
  162. data/app/views/parapet/shared/_global_nav.html.erb +55 -0
  163. data/app/views/parapet/shared/_head.html.erb +4 -0
  164. data/app/views/parapet/shared/_header.html.erb +20 -0
  165. data/app/views/parapet/shared/_object_inspector.html.erb +76 -0
  166. data/app/views/parapet/shared/_ribbon_header.html.erb +3 -0
  167. data/app/views/parapet/shared/_root_selector_modal.html.erb +15 -0
  168. data/app/views/parapet/shared/_tab_bar.html.erb +62 -0
  169. data/app/views/parapet/shared/activities_ribbon/_agent_group.html.erb +15 -0
  170. data/app/views/parapet/shared/activities_ribbon/_analysis_group.html.erb +15 -0
  171. data/app/views/parapet/shared/activities_ribbon/_architect_group.html.erb +21 -0
  172. data/app/views/parapet/shared/activities_ribbon/_explorer_group.html.erb +12 -0
  173. data/app/views/parapet/shared/activities_ribbon/_inspector_group.html.erb +15 -0
  174. data/app/views/parapet/shared/activities_ribbon/_proficiency_filter.html.erb +24 -0
  175. data/app/views/parapet/shared/activities_ribbon/_runner_group.html.erb +21 -0
  176. data/app/views/parapet/shared/activities_ribbon/_spatial_inspector_group.html.erb +18 -0
  177. data/app/views/parapet/shared/activities_ribbon/_studio_group.html.erb +18 -0
  178. data/app/views/parapet/shared/activities_ribbon/_stylist_group.html.erb +18 -0
  179. data/app/views/parapet/shared/explorers/_base.html.erb +107 -0
  180. data/app/views/parapet/shared/explorers/_css.html.erb +1 -0
  181. data/app/views/parapet/shared/explorers/_intentions.html.erb +1 -0
  182. data/app/views/parapet/shared/explorers/_project.html.erb +1 -0
  183. data/app/views/parapet/shared/explorers/_tests.html.erb +1 -0
  184. data/app/views/parapet/shared/head/_meta.html.erb +3 -0
  185. data/app/views/parapet/shared/head/_styles_activities.html.erb +152 -0
  186. data/app/views/parapet/shared/head/_styles_shared.html.erb +52 -0
  187. data/app/views/parapet/shared/head/_styles_workspace.html.erb +67 -0
  188. data/app/views/parapet/shared/ribbon_header/_diagnostic_controls.html.erb +17 -0
  189. data/app/views/parapet/shared/ribbon_header/_execution_controls.html.erb +28 -0
  190. data/app/views/parapet/shared/ribbon_header/_focus_search.html.erb +5 -0
  191. data/app/views/parapet/shared/root_selector/_header.html.erb +10 -0
  192. data/app/views/parapet/shared/root_selector/_path_input.html.erb +13 -0
  193. data/app/views/parapet/shared/root_selector/_quick_select.html.erb +20 -0
  194. data/app/views/parapet/shared/root_selector/_scripts.html.erb +61 -0
  195. data/app/views/parapet/shared/root_selector/_warning.html.erb +11 -0
  196. data/app/views/parapet/shared/widgets/_base.html.erb +6 -0
  197. data/app/views/parapet/shared/widgets/_css.html.erb +79 -0
  198. data/app/views/parapet/widgets/_explainer.html.erb +17 -0
  199. data/app/views/parapet/widgets/_hotkeys.html.erb +20 -0
  200. data/app/views/parapet/widgets/_search.html.erb +68 -0
  201. data/app/views/parapet/widgets/_spatial_inspector.html.erb +54 -0
  202. data/app/views/parapet/widgets/_widget-explainer.html.erb +17 -0
  203. data/app/views/parapet/widgets/_widget-hotkeys.html.erb +20 -0
  204. data/app/views/parapet/widgets/_widget-search.html.erb +68 -0
  205. data/app/views/parapet/widgets/_widget-snippets.html.erb +18 -0
  206. data/app/views/parapet/widgets/_widget-suggestions.html.erb +15 -0
  207. data/app/views/parapet/widgets/show.html.erb +3 -0
  208. data/app/views/shared/_footer.html.erb +0 -0
  209. data/config/parapet/qss_config.yml +117 -0
  210. data/config/parapet/qss_registry.yml +14 -0
  211. data/config/routes.rb +40 -0
  212. data/db/migrate/20260916035300_create_run_histories.rb +16 -0
  213. data/db/migrate/20261002000000_expand_run_histories_for_activity_tracking.rb +7 -0
  214. data/db/parapet_migrate/20260929184200_create_parapet_users.rb +12 -0
  215. data/db/parapet_migrate/20260929184300_create_parapet_sessions.rb +9 -0
  216. data/db/parapet_migrate/20260930000000_create_parapet_runtime_settings.rb +12 -0
  217. data/db/parapet_migrate/20260930000100_create_parapet_suite_assignments.rb +14 -0
  218. data/db/parapet_migrate/20261002000000_create_parapet_activities.rb +16 -0
  219. data/db/parapet_migrate/20261002000100_create_parapet_draft_recoveries.rb +13 -0
  220. data/db/parapet_schema.rb +64 -0
  221. data/db/schema.rb +21 -0
  222. data/db/schema.released.rb +0 -0
  223. data/lib/parapet/engine.rb +11 -0
  224. data/lib/parapet/environment_guard.rb +14 -0
  225. data/lib/parapet/version.rb +3 -0
  226. data/lib/parapet-rails.rb +1 -0
  227. data/lib/parapet.rb +59 -0
  228. data/lib/tasks/parapet_qss.rake +26 -0
  229. data/lib/tasks/parapet_tasks.rake +25 -0
  230. data/lib/tasks/randomize_explorer_health.rb +101 -0
  231. metadata +423 -0
@@ -0,0 +1,85 @@
1
+ <div id="pp-hierarchical-wrapper" class="qss-canvas" style="contain: layout; width: 100vw; height: 100vh; position: relative; background: #f3f4f6; --header-height: 60px; --left-sidebar-width-decl: 260px;">
2
+ <!-- Top Level: Header -->
3
+ <header id="pp-top-header" style="contain: layout; width: 100%; height: var(--header-height); background: #1e293b; color: white; display: flex; items-center: center; padding: 0 20px;">
4
+ <h1 class="text-xl font-bold">Hierarchical Protocol Test</h1>
5
+ </header>
6
+
7
+ <!-- Top Level: Sidebar -->
8
+ <aside id="pp-left-sidebar" style="contain: layout; width: var(--left-sidebar-width-decl); top: var(--header-height); bottom: 0; left: 0; position: absolute; background: white; border-right: 1px solid #e5e7eb; padding: 20px;">
9
+ <p class="text-sm font-medium text-gray-500 uppercase">Top Level Navigation</p>
10
+ <div class="mt-4 space-y-2">
11
+ <div class="h-8 bg-gray-100 rounded"></div>
12
+ <div class="h-8 bg-gray-100 rounded"></div>
13
+ </div>
14
+ </aside>
15
+
16
+ <!-- Top Level: Main Content Area (Nested Frame) -->
17
+ <main id="pp-main-workspace" style="contain: layout; left: var(--left-sidebar-width); top: var(--header-height); right: 0; bottom: 0; position: absolute; background: #f9fafb; padding: 20px;">
18
+
19
+ <!-- Nested Structural Layout -->
20
+ <div id="pp-nested-frame" style="contain: layout; width: 100%; height: 100%; position: relative; border: 2px dashed #3b82f6; border-radius: 8px; background: white; --inner-sidebar-width-decl: 200px;">
21
+
22
+ <!-- Nested Sidebar -->
23
+ <aside id="pp-inner-sidebar" style="contain: layout; width: var(--inner-sidebar-width-decl); height: 100%; position: absolute; left: 0; top: 0; background: #eff6ff; border-right: 1px solid #bfdbfe; padding: 15px;">
24
+ <p class="text-xs font-bold text-blue-600 uppercase">Nested Sidebar</p>
25
+ <div class="mt-4 h-full bg-blue-50 rounded opacity-50"></div>
26
+ </aside>
27
+
28
+ <!-- Nested Workspace (Anchored to Nested Sidebar) -->
29
+ <section id="pp-inner-workspace" style="contain: layout; left: var(--inner-sidebar-width); right: 0; top: 0; bottom: 0; position: absolute; padding: 20px;">
30
+ <h2 class="text-lg font-semibold mb-4">Nested Content Area</h2>
31
+ <p class="text-gray-600 mb-6">This area anchors to the blue inner sidebar, which itself sits inside the main workspace.</p>
32
+
33
+ <!-- Overlay Trigger (Stacking Context Test) -->
34
+ <button id="pp-trigger-button" class="qss-content-driven px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors">
35
+ Open Portal Dropdown
36
+ </button>
37
+ </section>
38
+
39
+ <!-- Nested Thin Pulse (Scoped to pp-nested-frame) -->
40
+ <script>
41
+ (function() {
42
+ const sidebar = document.querySelector('#pp-inner-sidebar');
43
+ const root = document.querySelector('#pp-nested-frame');
44
+ const update = () => root.style.setProperty('--inner-sidebar-width', `${sidebar.offsetWidth}px`);
45
+ new MutationObserver(update).observe(sidebar, { attributes: true });
46
+ window.addEventListener('resize', update);
47
+ update();
48
+ })();
49
+ </script>
50
+ </div>
51
+
52
+ </main>
53
+
54
+ <!-- Top Level Thin Pulse (Scoped to pp-hierarchical-wrapper) -->
55
+ <script>
56
+ (function() {
57
+ const sidebar = document.querySelector('#pp-left-sidebar');
58
+ const root = document.querySelector('#pp-hierarchical-wrapper');
59
+ const update = () => root.style.setProperty('--left-sidebar-width', `${sidebar.offsetWidth}px`);
60
+ new MutationObserver(update).observe(sidebar, { attributes: true });
61
+ window.addEventListener('resize', update);
62
+ update();
63
+ })();
64
+ </script>
65
+
66
+ <!-- Portal Root (Rule 4 Compliance) -->
67
+ <div id="pp-portal-root">
68
+ <!-- Dropdown content will be injected here via JS to simulate portal behavior -->
69
+ <div id="pp-portal-dropdown" style="display: none; position: absolute; z-index: 9999; background: white; border: 1px solid #ccc; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); padding: 10px; border-radius: 4px;">
70
+ <p class="text-sm">I am a Portaled Dropdown</p>
71
+ <hr class="my-2">
72
+ <p class="text-xs text-gray-500">Escaped the Stacking Context Trap</p>
73
+ </div>
74
+ </div>
75
+
76
+ <script>
77
+ document.querySelector('#pp-trigger-button').addEventListener('click', (e) => {
78
+ const dropdown = document.querySelector('#pp-portal-dropdown');
79
+ const rect = e.target.getBoundingClientRect();
80
+ dropdown.style.display = 'block';
81
+ dropdown.style.top = `${rect.bottom + window.scrollY + 5}px`;
82
+ dropdown.style.left = `${rect.left + window.scrollX}px`;
83
+ });
84
+ </script>
85
+ </div>
@@ -0,0 +1,25 @@
1
+ <div id="pp-hybrid-test" class="qss w-full h-full vertical">
2
+ <!-- QSS Frame -->
3
+ <div id="pp-hybrid-frame" class="qss anchored w-full h[200] border-b[1] border-slate-800 vertical px[20] py[16] bg-brand-main">
4
+ <h3 class="qss text-size[14] weight[bold] text-slate-300">Auditor Context Test</h3>
5
+
6
+ <!-- Tailwind Drywall (inside .foreign) -->
7
+ <div id="pp-tailwind-payload" class="qss anchored w-full mt[10] foreign bg-slate-900 rounded p-4">
8
+ <div class="flex items-center justify-between divide-x divide-slate-800 border border-slate-700 rounded overflow-hidden">
9
+ <div class="flex-1 px-4 py-2 text-sm text-slate-300 cursor-pointer hover:bg-slate-800 transition-colors">
10
+ Unprefixed: flex, grid, divide-y
11
+ </div>
12
+ <div class="flex-none px-4 py-2 text-xs font-mono text-emerald-400 bg-emerald-500/10">
13
+ Status: Auditor Patched
14
+ </div>
15
+ </div>
16
+
17
+ <ul class="mt-4 divide-y divide-slate-800 border-t border-slate-800">
18
+ <li class="py-2 flex items-center gap-2">
19
+ <span class="w-2 h-2 rounded-full bg-blue-500 shadow-[0_0_8px_rgba(59,130,246,0.5)]"></span>
20
+ <span class="text-xs text-slate-400">Testing unprefixed classes inside .foreign</span>
21
+ </li>
22
+ </ul>
23
+ </div>
24
+ </div>
25
+ </div>
@@ -0,0 +1,35 @@
1
+ <div id="pp-landing-container" class="qss w-full h-full centered">
2
+
3
+ <div id="login-card" class="qss Card[400|500] pos[center] vertical v-mid pt[40]">
4
+
5
+ <div id="login-branding" class="qss mb[40] vertical v-mid">
6
+ <span class="qss text-indigo-500 font-black text-size[48] italic tracking-tighter">PARAPET</span>
7
+ <span class="qss text-slate-500 text-size[12] uppercase tracking-widest mt[-8]">Secure Access IDE</span>
8
+ </div>
9
+
10
+ <%= form_with url: login_path, method: :post, class: "qss vertical gap[24]" do |f| %>
11
+
12
+ <div class="qss Field[320|64]">
13
+ <label class="qss Field-label">USERNAME</label>
14
+ <%= f.text_field :username, class: "qss Field-input", placeholder: "Enter username..." %>
15
+ </div>
16
+
17
+ <div class="qss Field[320|64]">
18
+ <label class="qss Field-label">PASSWORD</label>
19
+ <%= f.password_field :password, class: "qss Field-input", placeholder: "••••••••" %>
20
+ </div>
21
+
22
+ <div class="qss mt[20]">
23
+ <button type="submit" class="qss Button[320|48]">
24
+ <span class="qss Button-label">SIGN IN</span>
25
+ </button>
26
+ </div>
27
+
28
+ <% end %>
29
+
30
+ <div class="qss mt[40] text-slate-600 text-size[12]">
31
+ &copy; <%= Time.now.year %> Parapet Software Engineering
32
+ </div>
33
+ </div>
34
+
35
+ </div>
@@ -0,0 +1,82 @@
1
+ <div id="pp-stress-wrapper" class="qss-canvas" style="contain: layout; width: 100vw; height: 100vh; position: relative; background: #0f172a; color: white; overflow: hidden;">
2
+
3
+ <!-- Sidebar -->
4
+ <aside id="pp-sidebar" style="contain: layout; width: var(--sidebar-w, 300px); height: 100%; position: absolute; left: 0; top: 0; background: #1e293b; border-right: 1px solid #334155; display: flex; flex-direction: column; padding: 20px;">
5
+ <h2 class="text-lg font-bold mb-4">Mutation Stress Test</h2>
6
+ <p class="text-sm text-slate-400 mb-8">Simulating 60fps continuous resize to detect layout thrashing.</p>
7
+
8
+ <div id="stats" class="mt-auto p-4 bg-black/20 rounded font-mono text-xs">
9
+ <div>FPS: <span id="fps-val">0</span></div>
10
+ <div>Pulse Latency: <span id="lat-val">0</span>ms</div>
11
+ </div>
12
+ </aside>
13
+
14
+ <!-- Workspace (Anchored to Sidebar) -->
15
+ <main id="pp-workspace" style="contain: layout; left: var(--sidebar-width); right: 0; height: 100%; position: absolute; background: #0f1115; padding: 40px; display: flex; items-center: center; justify-content: center;">
16
+ <div class="qss centered">
17
+ <div id="indicator" class="qss-payload-override" style="width: 100px; height: 100px; border-radius: 50%; background: #6366f1; transition: transform 0.1s linear;"></div>
18
+ <p class="mt-4 font-bold">Anchored Workspace</p>
19
+ <code class="text-xs text-slate-500">left: var(--sidebar-width)</code>
20
+ </div>
21
+ </main>
22
+
23
+ <!-- Thin Pulse Script -->
24
+ <script id="pp-thin-pulse">
25
+ (function() {
26
+ const sidebar = document.querySelector('#pp-sidebar');
27
+ const root = document.querySelector('#pp-stress-wrapper');
28
+
29
+ const update = () => {
30
+ const start = performance.now();
31
+ root.style.setProperty('--sidebar-width', `${sidebar.offsetWidth}px`);
32
+ const end = performance.now();
33
+ window.lastPulseDuration = end - start;
34
+ };
35
+
36
+ const observer = new MutationObserver(update);
37
+ observer.observe(sidebar, { attributes: true, attributeFilter: ['style'] });
38
+
39
+ window.addEventListener('resize', update);
40
+ update();
41
+ })();
42
+ </script>
43
+
44
+ <!-- Simulation Script -->
45
+ <script>
46
+ (function() {
47
+ const sidebar = document.querySelector('#pp-sidebar');
48
+ const fpsVal = document.querySelector('#fps-val');
49
+ const latVal = document.querySelector('#lat-val');
50
+ const indicator = document.querySelector('#indicator');
51
+
52
+ let frameCount = 0;
53
+ let lastTime = performance.now();
54
+ let phase = 0;
55
+
56
+ function simulate() {
57
+ const now = performance.now();
58
+ frameCount++;
59
+
60
+ if (now > lastTime + 1000) {
61
+ fpsVal.textContent = Math.round((frameCount * 1000) / (now - lastTime));
62
+ latVal.textContent = (window.lastPulseDuration || 0).toFixed(3);
63
+ frameCount = 0;
64
+ lastTime = now;
65
+ }
66
+
67
+ // Oscillate sidebar width between 200 and 600
68
+ phase += 0.05;
69
+ const width = 400 + Math.sin(phase) * 200;
70
+ sidebar.style.width = `${width}px`;
71
+
72
+ // Rotate indicator to show animation smoothness
73
+ indicator.style.transform = `rotate(${phase * 50}deg)`;
74
+
75
+ requestAnimationFrame(simulate);
76
+ }
77
+
78
+ // Start simulation after a small delay
79
+ setTimeout(simulate, 1000);
80
+ })();
81
+ </script>
82
+ </div>
@@ -0,0 +1,66 @@
1
+ <div id="pp-recursive-root" class="qss-canvas" style="contain: layout; width: 100vw; height: 100vh; position: relative; --header-h: 60px;">
2
+
3
+ <!-- Root Level: Header -->
4
+ <header id="pp-root-header" style="contain: layout; width: 100%; height: var(--header-h); background: #1e293b; color: white; display: flex; items-center: center; padding: 0 20px;">
5
+ <h1 class="text-xl font-bold">Recursive Anchor Standard</h1>
6
+ </header>
7
+
8
+ <!-- Root Level: Main Frame -->
9
+ <main id="pp-root-main" style="contain: layout; top: var(--header-h); bottom: 0; width: 100%; position: absolute; background: #f1f5f9; padding: 20px;">
10
+
11
+ <!-- Recursive Panel A -->
12
+ <div id="pp-panel-a" style="contain: layout; width: 100%; height: var(--local-panel-h); position: relative; background: white; border: 1px solid #cbd5e1; --local-sidebar-w: 200px; --local-panel-h: 400px;">
13
+
14
+ <!-- Panel A Sidebar (Uses local property) -->
15
+ <aside id="pp-panel-a-side" style="contain: layout; width: var(--local-sidebar-w); height: 100%; position: absolute; left: 0; top: 0; background: #f8fafc; border-right: 1px solid #e2e8f0; padding: 15px;">
16
+ <p class="text-xs font-bold text-slate-500 uppercase">Panel A Nav</p>
17
+ </aside>
18
+
19
+ <!-- Panel A Content (Anchored to local property) -->
20
+ <section id="pp-panel-a-content" style="contain: layout; left: var(--local-sidebar-w); right: 0; top: 0; bottom: 0; position: absolute; padding: 20px;">
21
+ <h2 class="text-md font-semibold">Panel A Content</h2>
22
+ <p class="text-sm text-slate-600">Anchored to local --local-sidebar-w</p>
23
+ </section>
24
+
25
+ <!-- Panel A Thin Pulse (Scoped to Panel A) -->
26
+ <script>
27
+ (function() {
28
+ const side = document.querySelector('#pp-panel-a-side');
29
+ const root = document.querySelector('#pp-panel-a');
30
+ const update = () => root.style.setProperty('--local-sidebar-w', `${side.offsetWidth}px`);
31
+ new MutationObserver(update).observe(side, { attributes: true });
32
+ window.addEventListener('resize', update);
33
+ update();
34
+ })();
35
+ </script>
36
+ </div>
37
+
38
+ <!-- Recursive Panel B (Identical structure, different scope) -->
39
+ <div id="pp-panel-b" class="mt-8" style="contain: layout; width: 100%; height: var(--local-panel-h); position: relative; background: white; border: 1px solid #cbd5e1; --local-sidebar-w: 250px; --local-panel-h: 400px;">
40
+
41
+ <!-- Panel B Sidebar -->
42
+ <aside id="pp-panel-b-side" style="contain: layout; width: var(--local-sidebar-w); height: 100%; position: absolute; left: 0; top: 0; background: #f8fafc; border-right: 1px solid #e2e8f0; padding: 15px;">
43
+ <p class="text-xs font-bold text-slate-500 uppercase">Panel B Nav</p>
44
+ </aside>
45
+
46
+ <!-- Panel B Content -->
47
+ <section id="pp-panel-b-content" style="contain: layout; left: var(--local-sidebar-w); right: 0; top: 0; bottom: 0; position: absolute; padding: 20px;">
48
+ <h2 class="text-md font-semibold">Panel B Content</h2>
49
+ <p class="text-sm text-slate-600">Anchored to local --local-sidebar-w (independent of Panel A)</p>
50
+ </section>
51
+
52
+ <!-- Panel B Thin Pulse -->
53
+ <script>
54
+ (function() {
55
+ const side = document.querySelector('#pp-panel-b-side');
56
+ const root = document.querySelector('#pp-panel-b');
57
+ const update = () => root.style.setProperty('--local-sidebar-w', `${side.offsetWidth}px`);
58
+ new MutationObserver(update).observe(side, { attributes: true });
59
+ window.addEventListener('resize', update);
60
+ update();
61
+ })();
62
+ </script>
63
+ </div>
64
+
65
+ </main>
66
+ </div>
@@ -0,0 +1,28 @@
1
+ <div id="pp-login-frame" class="qss pp-frame w-full h-full bg-brand-main contain-layout">
2
+ <main class="flex h-full items-center justify-center p-6">
3
+ <section class="w-full max-w-md rounded-lg border border-slate-700 bg-slate-900 p-8">
4
+ <header class="mb-8 text-center">
5
+ <h1 class="text-3xl font-bold tracking-tight text-indigo-400">Parapet</h1>
6
+ <p class="mt-2 text-sm text-slate-400">Sign in to your developer account</p>
7
+ </header>
8
+
9
+ <% if flash[:alert].present? %>
10
+ <p class="mb-4 rounded border border-red-800 bg-red-950 p-3 text-sm text-red-300" role="alert"><%= flash[:alert] %></p>
11
+ <% end %>
12
+
13
+ <%= form_with url: login_path, class: "space-y-5" do |form| %>
14
+ <div>
15
+ <%= form.label :email_address, "Email address", class: "mb-2 block text-sm font-medium text-slate-300" %>
16
+ <%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", class: "w-full rounded border border-slate-700 bg-slate-950 px-3 py-3 text-slate-100" %>
17
+ </div>
18
+
19
+ <div>
20
+ <%= form.label :password, "Password", class: "mb-2 block text-sm font-medium text-slate-300" %>
21
+ <%= form.password_field :password, required: true, autocomplete: "current-password", class: "w-full rounded border border-slate-700 bg-slate-950 px-3 py-3 text-slate-100" %>
22
+ </div>
23
+
24
+ <%= form.submit "Sign in", class: "w-full rounded bg-indigo-600 px-4 py-3 font-semibold text-white hover:bg-indigo-500" %>
25
+ <% end %>
26
+ </section>
27
+ </main>
28
+ </div>
@@ -0,0 +1,92 @@
1
+ <div id="qss-cad-inspector-canvas" class="qss-relative qss-w-pct[1000] qss-h-pct[1000] qss-bg-[#16191e] qss-overflow-hidden">
2
+
3
+ <!-- Inspector Header -->
4
+ <div id="qss-cad-header" class="qss-absolute qss-pos-x[0] qss-pos-y[0] qss-w-pct[1000] qss-h[40] qss-border-b qss-border-slate-800 qss-flex qss-justify-center qss-items-center">
5
+ <span class="qss-text-size[12] qss-font-bold qss-text-slate-400 qss-uppercase qss-tracking-widest">CAD Inspector</span>
6
+ </div>
7
+
8
+ <div id="qss-cad-content" class="qss-absolute qss-pos-x[0] qss-pos-y[40] qss-pos-b[0] qss-w-pct[1000] qss-overflow-y-auto qss-p-4 qss-space-y-6 custom-scrollbar">
9
+
10
+ <!-- Selection Info -->
11
+ <div class="qss-space-y-2">
12
+ <label class="qss-text-size[9] qss-font-bold qss-text-slate-500 qss-uppercase">Active Noun</label>
13
+ <div class="qss-bg-slate-900/50 qss-border qss-border-slate-800 qss-p-3 qss-rounded">
14
+ <span class="qss-text-size[12] qss-font-bold qss-text-indigo-400 qss-font-mono">#qss-main-canvas</span>
15
+ </div>
16
+ </div>
17
+
18
+ <!-- Spatial Adjectives -->
19
+ <div class="qss-space-y-3">
20
+ <label class="qss-text-size[9] qss-font-bold qss-text-slate-500 qss-uppercase">Spatial Adjectives</label>
21
+
22
+ <div class="qss-grid qss-grid-cols-2 qss-gap-3">
23
+ <div class="qss-space-y-1">
24
+ <label class="qss-text-size[8] qss-text-slate-600 qss-uppercase">X-Coord</label>
25
+ <div class="qss-bg-slate-900/30 qss-border qss-border-slate-800 qss-p-2 qss-text-size[11] qss-text-slate-300 qss-font-mono">0</div>
26
+ </div>
27
+ <div class="qss-space-y-1">
28
+ <label class="qss-text-size[8] qss-text-slate-600 qss-uppercase">Y-Coord</label>
29
+ <div class="qss-bg-slate-900/30 qss-border qss-border-slate-800 qss-p-2 qss-text-size[11] qss-text-slate-300 qss-font-mono">0</div>
30
+ </div>
31
+ </div>
32
+
33
+ <div class="qss-grid qss-grid-cols-2 qss-gap-3">
34
+ <div class="qss-space-y-1">
35
+ <label class="qss-text-size[8] qss-text-slate-600 qss-uppercase">Width %</label>
36
+ <div class="qss-bg-slate-900/30 qss-border qss-border-slate-800 qss-p-2 qss-text-size[11] qss-text-slate-300 qss-font-mono">100.0%</div>
37
+ </div>
38
+ <div class="qss-space-y-1">
39
+ <label class="qss-text-size[8] qss-text-slate-600 qss-uppercase">Height %</label>
40
+ <div class="qss-bg-slate-900/30 qss-border qss-border-slate-800 qss-p-2 qss-text-size[11] qss-text-slate-300 qss-font-mono">100.0%</div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ <!-- Ergonomic Auditor -->
46
+ <div class="qss-pt-6 qss-border-t qss-border-slate-800 qss-space-y-3">
47
+ <div class="qss-flex qss-items-center qss-justify-between">
48
+ <span class="qss-text-size[9] qss-font-bold qss-text-slate-500 qss-uppercase">Usability Auditor</span>
49
+ <span class="qss-text-size[10] qss-font-bold qss-text-emerald-500">OPTIMAL</span>
50
+ </div>
51
+
52
+ <div class="qss-space-y-2">
53
+ <div class="qss-flex qss-items-center qss-gap-2 qss-p-2 qss-bg-emerald-500/5 qss-border qss-border-emerald-500/20 qss-rounded">
54
+ <div class="qss-w[6] qss-h[6] qss-rounded-full qss-bg-emerald-500"></div>
55
+ <span class="qss-text-size[9] qss-text-emerald-400/80">Spatial alignment matches 1000-unit grid.</span>
56
+ </div>
57
+ </div>
58
+ </div>
59
+
60
+ <!-- Grammar Palette (Registry) -->
61
+ <div class="qss-pt-6 qss-border-t qss-border-slate-800 qss-space-y-3">
62
+ <div class="qss-flex qss-items-center qss-justify-between">
63
+ <span class="qss-text-size[9] qss-font-bold qss-text-slate-500 qss-uppercase">Grammar Palette</span>
64
+ <i class="lucide-book-open qss-w[12] qss-h[12] qss-text-slate-500"></i>
65
+ </div>
66
+
67
+ <div class="qss-relative">
68
+ <input type="text" placeholder="Search adjectives..."
69
+ class="qss-w-pct[1000] qss-bg-slate-900/50 qss-border qss-border-slate-800 qss-rounded qss-px-2 qss-py-1.5 qss-text-size[10] qss-text-slate-300 focus:qss-outline-none focus:qss-border-indigo-500/50">
70
+ </div>
71
+
72
+ <div class="qss-h[150] qss-overflow-y-auto qss-space-y-1 custom-scrollbar">
73
+ <div class="qss-text-size[8] qss-text-slate-600 qss-uppercase qss-font-bold qss-px-1 qss-mt-2">Spatial</div>
74
+ <div class="qss-p-1.5 qss-rounded hover:qss-bg-white/5 qss-cursor-pointer qss-text-size[10] qss-text-slate-300">.pos-x[...]</div>
75
+ <div class="qss-p-1.5 qss-rounded hover:qss-bg-white/5 qss-cursor-pointer qss-text-size[10] qss-text-slate-300">.pos-y[...]</div>
76
+ <div class="qss-p-1.5 qss-rounded hover:qss-bg-white/5 qss-cursor-pointer qss-text-size[10] qss-text-slate-300">.w[...]</div>
77
+ <div class="qss-p-1.5 qss-rounded hover:qss-bg-white/5 qss-cursor-pointer qss-text-size[10] qss-text-slate-300">.h[...]</div>
78
+
79
+ <div class="qss-text-size[8] qss-text-slate-600 qss-uppercase qss-font-bold qss-px-1 qss-mt-4">Typography</div>
80
+ <div class="qss-p-1.5 qss-rounded hover:qss-bg-white/5 qss-cursor-pointer qss-text-size[10] qss-text-slate-300">.text-size[...]</div>
81
+ <div class="qss-p-1.5 qss-rounded hover:qss-bg-white/5 qss-cursor-pointer qss-text-size[10] qss-text-slate-300">.font-bold</div>
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Action Logic -->
86
+ <div class="qss-pt-6 qss-border-t qss-border-slate-800">
87
+ <button class="qss-w-pct[1000] qss-py-3 qss-bg-indigo-500/20 qss-border qss-border-indigo-500/40 qss-text-indigo-400 qss-text-size[10] qss-font-bold qss-uppercase qss-rounded hover:qss-bg-indigo-500/30 qss-transition-all">
88
+ Commit Spatial Changes
89
+ </button>
90
+ </div>
91
+ </div>
92
+ </div>
@@ -0,0 +1,48 @@
1
+ <div id="pp-discovery-sidebar-canvas" class="qss relative w-pct[1000] h-pct[1000] bg-[#16191e] overflow-hidden">
2
+
3
+ <!-- Explorer Pane (Top 60%) -->
4
+ <div id="pp-explorer-pane" class="qss absolute pos-x[0] pos-y[0] w-pct[1000] h-pct[600] border-b border-slate-800">
5
+ <div id="pp-sidebar-header" class="qss absolute pos-x[0] pos-y[0] w-pct[1000] h[40] border-b border-slate-800 flex justify-center items-center">
6
+ <span id="pp-suite-explorer-title" class="qss text-size[12] font-bold text-slate-400 uppercase tracking-widest">Workspace Explorer</span>
7
+ </div>
8
+
9
+ <div id="pp-explorer-content" class="qss absolute pos-x[0] pos-y[40] w-pct[1000] pos-b[0] overflow-y-auto p[8] custom-scrollbar">
10
+ <!-- Project files tree -->
11
+ <div id="pp-tree-container" data-endpoint="<%= parapet.files_path %>">
12
+ <div class="qss text-size[10] text-slate-500 italic text-center mt[20]">
13
+ Scanning project files...
14
+ </div>
15
+ </div>
16
+ </div>
17
+ </div>
18
+
19
+ <!-- Agent Chat Pane (Bottom 40%) -->
20
+ <div id="pp-agent-chat-pane" class="qss absolute pos-x[0] pos-y-pct[600] w-pct[1000] pos-b[0] bg-[#0f1115] flex flex-col">
21
+ <div class="qss h[32] bg-slate-900/50 border-b border-slate-800 flex items-center px[12] gap[8]">
22
+ <div class="qss w[6] h[6] rounded-full bg-indigo-500 animate-pulse"></div>
23
+ <span class="qss text-size[10] font-bold text-slate-400 uppercase tracking-wider">Agent Intelligence</span>
24
+ </div>
25
+
26
+ <div id="pp-agent-messages" class="qss flex-grow overflow-y-auto p[12] space-y[16] custom-scrollbar">
27
+ <div class="qss flex flex-col gap[4]">
28
+ <span class="qss text-size[9] font-bold text-slate-600 uppercase">System</span>
29
+ <div class="qss bg-slate-800/30 border border-slate-800 p[8] rounded">
30
+ <p class="qss text-size[11] text-slate-400 leading-tight">
31
+ Awaiting spatial instructions...
32
+ </p>
33
+ </div>
34
+ </div>
35
+ </div>
36
+
37
+ <div class="qss p[8] bg-slate-900/30 border-t border-slate-800">
38
+ <div class="qss relative">
39
+ <textarea placeholder="Describe layout changes..."
40
+ class="qss w-pct[1000] bg-slate-950 border border-slate-800 rounded p[8] text-size[11] text-slate-300 outline-none focus:border-indigo-500/50 resize-none h[60]"></textarea>
41
+ <div class="qss absolute pos-r[8] pos-b[8] flex items-center gap[8]">
42
+ <span class="qss text-size[8] text-slate-700 font-mono">⌘⏎</span>
43
+ <i class="lucide-send qss w[14] h[14] text-indigo-500 cursor-pointer"></i>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </div>
@@ -0,0 +1,71 @@
1
+ <div id="pp-explorer-bar" class="qss bg-brand-main border-r border-slate-800 contain-layout" style="position: absolute; left: var(--global-nav-w, var(--global-nav-w-default)); top: var(--header-h); width: var(--explorer-bar-w, var(--explorer-bar-w-default)); min-width: var(--explorer-bar-min-w); max-width: var(--explorer-bar-max-w); bottom: var(--footer-h, var(--footer-h-default));">
2
+ <div id="pp-explorer-header" class="qss border-b border-slate-800 centered contain-layout" style="position: absolute; left: 0; top: 0; width: 100%; height: calc(20 * var(--qnt));">
3
+ <%
4
+ suite_title = case @active_suite
5
+ when 'css' then 'CSS Suite'
6
+ when 'tests' then 'Test Suite'
7
+ when 'intentions' then 'Intentions Suite'
8
+ when 'signal' then 'Signal Suite'
9
+ when 'monitor' then 'Monitor Suite'
10
+ when 'polyglot' then 'Polyglot Suite'
11
+ when 'build' then 'Build Suite'
12
+ else 'Explorer'
13
+ end
14
+ %>
15
+ <div id="pp-explorer-title" class="qss absolute pos-x-center text-slate-500 font-bold font-sans text-size[11] uppercase tracking qss-legibility-override"><%= suite_title %></div>
16
+ </div>
17
+
18
+ <!-- 1. Librarian (File Tree) -->
19
+ <div id="pp-explorer-content" class="qss border-b border-slate-800 scroll-auto contain-layout" style="position: absolute; width: 100%; top: calc(20 * var(--qnt)); bottom: calc(var(--agent-interface-h, var(--agent-interface-h-default)) + var(--explorer-widgets-h, var(--explorer-widgets-h-default)));">
20
+ <%
21
+ explorer_type = case @active_suite
22
+ when 'css' then 'css'
23
+ when 'tests' then 'tests'
24
+ when 'intentions' then 'intentions'
25
+ else 'project'
26
+ end
27
+ %>
28
+ <%= turbo_frame_tag "qss-explorer-content", src: parapet.explorer_path(type: explorer_type) do %>
29
+ <div class="qss p-2.5 text-slate-600 italic text-size[11] qss-legibility-override">
30
+ Initializing <%= explorer_type %> explorer...
31
+ </div>
32
+ <% end %>
33
+ </div>
34
+
35
+ <!-- 2. Agent Interface (Chat) -->
36
+ <div id="pp-agent-interface" class="qss bg-slate-900 border-b border-slate-800 vertical depth-ui contain-layout" style="position: absolute; width: 100%; height: var(--agent-interface-h, var(--agent-interface-h-default)); bottom: var(--explorer-widgets-h, var(--explorer-widgets-h-default));">
37
+ <div id="pp-agent-header" class="qss bg-brand-header border-b border-slate-800 px-2.5 horizontal v-mid spaced contain-layout" style="height: calc(20 * var(--qnt)); width: 100%;">
38
+ <span class="qss text-size[11] text-slate-500 font-bold uppercase tracking qss-legibility-override">Agent Chat</span>
39
+ <i class="icon-message-square text-size[11] text-slate-600 qss-legibility-override"></i>
40
+ </div>
41
+ <div id="pp-agent-chat-output" class="qss flex-1 scroll-auto p-2.5 text-size[11] text-slate-400 font-sans qss-legibility-override">
42
+ <div class="qss italic text-slate-600">Ready for instructions...</div>
43
+ </div>
44
+ <div id="pp-agent-input-wrapper" class="qss bg-slate-950 p-2 horizontal v-mid border-t border-slate-800 qss-ergonomic-override contain-layout" style="height: calc(44 * var(--qnt)); width: 100%;">
45
+ <input type="text" placeholder="Ask Zencoder..." class="qss flex-1 bg-transparent border-none text-white text-size[11] outline-none qss-legibility-override" />
46
+ <button id="pp-agent-send-button" class="qss centered bg-indigo-600/20 hover:bg-indigo-600/40 rounded smooth border-none clickable qss-ergonomic-override w-24 h-24">
47
+ <i class="icon-send text-size[11] text-indigo-400 qss-legibility-override"></i>
48
+ </button>
49
+ </div>
50
+ </div>
51
+
52
+ <!-- 3. Auditor Feed (Bottom) -->
53
+ <div id="pp-explorer-widgets" class="qss bg-brand-header vertical depth-ui scroll-hidden contain-layout" style="position: absolute; left: 0; bottom: 0; width: 100%; height: var(--explorer-widgets-h, var(--explorer-widgets-h-default));">
54
+ <div id="pp-auditor-header" class="qss bg-white/2 border-b border-slate-800 horizontal v-mid px-2.5 spaced contain-layout" style="height: calc(20 * var(--qnt)); width: 100%;">
55
+ <span class="qss text-size[11] font-bold text-slate-500 uppercase tracking qss-legibility-override">The Auditor</span>
56
+ <div class="qss horizontal gap-1">
57
+ <div id="pp-auditor-status-dot" class="qss rounded-full bg-emerald-500 shadow-sm w-8 h-8"></div>
58
+ </div>
59
+ </div>
60
+ <div id="pp-widget-container" class="qss flex-1 scroll-auto">
61
+ <%= turbo_frame_tag "qss-widget-content", src: parapet.widget_path(type: @active_suite || 'base') do %>
62
+ <div class="qss p-2.5 text-slate-600 italic text-size[11] qss-legibility-override">
63
+ Scanning layout...
64
+ </div>
65
+ <% end %>
66
+ </div>
67
+ </div>
68
+
69
+ <!-- Drag Resizer Handle -->
70
+ <div id="pp-explorer-resizer" class="qss bg-slate-800 hover:bg-indigo-500 opacity-30 hover:opacity-100 depth-overlay smooth contain-layout" style="position: absolute; right: 0; margin-left: calc(-4 * var(--qnt)); top: 0; width: calc(8 * var(--qnt)); height: 100%; cursor: col-resize;"></div>
71
+ </div>
@@ -0,0 +1,10 @@
1
+ <div id="pp-footer-inner" class="w-full h-full horizontal v-mid px-3 spaced contain-layout">
2
+ <div class="horizontal v-mid gap-1.5">
3
+ <div class="w-1.5 h-1.5 rounded-full bg-emerald-500 shadow-sm"></div>
4
+ <span class="text-size[11] text-slate-500 font-bold uppercase tracking qss-legibility-override">Engine Active</span>
5
+ </div>
6
+ <div class="horizontal v-mid gap-3">
7
+ <span class="text-size[11] text-slate-600 font-mono qss-legibility-override">v0.5.2-hardened</span>
8
+ <span class="text-size[11] text-slate-600 font-mono qss-legibility-override">Latency: 12ms</span>
9
+ </div>
10
+ </div>
@@ -0,0 +1,36 @@
1
+ <%= turbo_frame_tag "qss-suite-footer", class: "qss-absolute qss-pos-x[0] qss-pos-y[0] qss-w-pct[1000] qss-h-pct[1000]" do %>
2
+
3
+ <!-- Left Group: Git & File Info -->
4
+ <div id="qss-footer-code-branch" class="qss-absolute qss-pos-x[16] qss-pos-y[6] qss-opacity-80" title="Current git branch">
5
+ <i class="lucide-git-branch qss-w-3 qss-h-3 qss-absolute qss-pos-x[0] qss-pos-y[0]"></i>
6
+ <span class="qss-font-mono qss-text-[10px] qss-absolute qss-pos-x[16] qss-pos-y[0]">main</span>
7
+ </div>
8
+
9
+ <div id="qss-footer-code-file" class="qss-absolute qss-pos-x[80] qss-pos-y[6] qss-opacity-60" title="Active file context">
10
+ <i class="lucide-file-code qss-w-3 qss-h-3 qss-absolute qss-pos-x[0] qss-pos-y[0]"></i>
11
+ <span class="qss-font-mono qss-text-[9px] qss-absolute qss-pos-x[18] qss-pos-y[0]">No file open</span>
12
+ </div>
13
+
14
+ <!-- Center Group: Save Status -->
15
+ <div id="qss-footer-code-save" class="qss-absolute qss-pos-x[calc(50%-40px)] qss-pos-y[6] qss-opacity-50 qss-font-mono" title="Last save action">
16
+ <i class="lucide-save qss-w-3 qss-h-3 qss-absolute qss-pos-x[0] qss-pos-y[0]"></i>
17
+ <span class="qss-text-[9px] qss-absolute qss-pos-x[18] qss-pos-y[0]">—</span>
18
+ </div>
19
+
20
+ <!-- Right Group: Bench & Status -->
21
+ <div id="qss-footer-code-bench" class="qss-absolute qss-pos-r[140] qss-pos-y[6] qss-opacity-60" title="Benched code changes: unsaved Parapet-managed edits not yet flushed to source">
22
+ <i class="lucide-layers qss-w-3 qss-h-3 qss-absolute qss-pos-x[0] qss-pos-y[0]"></i>
23
+ <span class="qss-uppercase qss-tracking-widest qss-font-mono qss-text-[9px] qss-absolute qss-pos-x[18] qss-pos-y[0]">Bench: 0</span>
24
+ </div>
25
+
26
+ <div id="qss-footer-code-cable" class="qss-absolute qss-pos-r[80] qss-pos-y[6] qss-opacity-80" title="ActionCable connected">
27
+ <span class="qss-uppercase qss-tracking-widest qss-text-[9px] qss-absolute qss-pos-x[0] qss-pos-y[0]">Cable</span>
28
+ <div class="qss-w-[5px] qss-h-[5px] qss-rounded-full qss-bg-emerald-400 qss-shadow-[0_0_8px_#34d399] qss-absolute qss-pos-x[35] qss-pos-y[3]"></div>
29
+ </div>
30
+
31
+ <div id="qss-footer-code-ready" class="qss-absolute qss-pos-r[16] qss-pos-y[6]" title="Parapet Ready">
32
+ <div class="qss-w-[5px] qss-h-[5px] qss-rounded-full qss-bg-emerald-400 qss-shadow-[0_0_8px_#34d399] qss-absolute qss-pos-x[0] qss-pos-y[3]"></div>
33
+ <span class="qss-uppercase qss-tracking-widest qss-text-[9px] qss-absolute qss-pos-x[10] qss-pos-y[0]">Ready</span>
34
+ </div>
35
+
36
+ <% end %>
@@ -0,0 +1,33 @@
1
+ <!-- Footer: Polyglot Suite -->
2
+ <%= turbo_frame_tag "qss-suite-footer", class: "qss-w-full qss-flex qss-items-center qss-justify-between qss-px-2" do %>
3
+ <div class="qss-flex qss-items-center qss-gap-4">
4
+ <div class="qss-flex qss-items-center qss-gap-1 qss-opacity-80" title="Current git branch">
5
+ <i class="lucide-git-branch qss-w-3 qss-h-3"></i>
6
+ <span class="qss-font-mono">main</span>
7
+ </div>
8
+ <div class="qss-flex qss-items-center qss-gap-1.5 qss-opacity-80" title="Active reference locale">
9
+ <i class="lucide-globe qss-w-3 qss-h-3"></i>
10
+ <span class="qss-font-mono qss-uppercase qss-tracking-widest">en-US</span>
11
+ </div>
12
+ <div class="qss-flex qss-items-center qss-gap-1.5 qss-opacity-60" title="Total configured locales">
13
+ <i class="lucide-languages qss-w-3 qss-h-3"></i>
14
+ <span class="qss-uppercase qss-tracking-widest">1 Locale</span>
15
+ </div>
16
+ </div>
17
+
18
+ <div class="qss-flex qss-items-center qss-gap-3 qss-font-mono" title="Missing translation keys detected">
19
+ <i class="lucide-key qss-w-3 qss-h-3 qss-opacity-60"></i>
20
+ <span class="qss-opacity-60">0 missing keys</span>
21
+ </div>
22
+
23
+ <div class="qss-flex qss-items-center qss-gap-4">
24
+ <div class="qss-flex qss-items-center qss-gap-1.5 qss-opacity-80" title="ActionCable: connected&#10;Last ping: just now">
25
+ <span class="qss-uppercase qss-tracking-widest">Cable</span>
26
+ <div class="qss-w-[5px] qss-h-[5px] qss-rounded-full qss-bg-emerald-400 qss-shadow-[0_0_8px_#34d399]"></div>
27
+ </div>
28
+ <div class="qss-flex qss-items-center qss-gap-1.5" title="Parapet: ready&#10;ActionCable: connected&#10;Last ping: just now">
29
+ <div class="qss-w-[5px] qss-h-[5px] qss-rounded-full qss-bg-emerald-400 qss-shadow-[0_0_8px_#34d399]"></div>
30
+ <span class="qss-uppercase qss-tracking-widest">Ready</span>
31
+ </div>
32
+ </div>
33
+ <% end %>